diff options
Diffstat (limited to 'drivers')
43 files changed, 4145 insertions, 178 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 9120717c0701..2aa1908e5ce0 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -535,6 +535,15 @@ config PATA_OPTIDMA | |||
535 | 535 | ||
536 | If unsure, say N. | 536 | If unsure, say N. |
537 | 537 | ||
538 | config PATA_PALMLD | ||
539 | tristate "Palm LifeDrive PATA support" | ||
540 | depends on MACH_PALMLD | ||
541 | help | ||
542 | This option enables support for Palm LifeDrive's internal ATA | ||
543 | port via the new ATA layer. | ||
544 | |||
545 | If unsure, say N. | ||
546 | |||
538 | config PATA_PCMCIA | 547 | config PATA_PCMCIA |
539 | tristate "PCMCIA PATA support" | 548 | tristate "PCMCIA PATA support" |
540 | depends on PCMCIA | 549 | depends on PCMCIA |
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 7f1ecf99528c..1558059874f0 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
@@ -50,6 +50,7 @@ obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o | |||
50 | obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o | 50 | obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o |
51 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o | 51 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o |
52 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o | 52 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o |
53 | obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o | ||
53 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o | 54 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o |
54 | obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o | 55 | obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o |
55 | obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o | 56 | obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o |
diff --git a/drivers/ata/pata_palmld.c b/drivers/ata/pata_palmld.c new file mode 100644 index 000000000000..11fb4ccc74b4 --- /dev/null +++ b/drivers/ata/pata_palmld.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * drivers/ata/pata_palmld.c | ||
3 | * | ||
4 | * Driver for IDE channel in Palm LifeDrive | ||
5 | * | ||
6 | * Based on research of: | ||
7 | * Alex Osborne <ato@meshy.org> | ||
8 | * | ||
9 | * Rewrite for mainline: | ||
10 | * Marek Vasut <marek.vasut@gmail.com> | ||
11 | * | ||
12 | * Rewritten version based on pata_ixp4xx_cf.c: | ||
13 | * ixp4xx PATA/Compact Flash driver | ||
14 | * Copyright (C) 2006-07 Tower Technologies | ||
15 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License version 2 as | ||
19 | * published by the Free Software Foundation. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/libata.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/gpio.h> | ||
30 | |||
31 | #include <scsi/scsi_host.h> | ||
32 | #include <mach/palmld.h> | ||
33 | |||
34 | #define DRV_NAME "pata_palmld" | ||
35 | |||
36 | static struct scsi_host_template palmld_sht = { | ||
37 | ATA_PIO_SHT(DRV_NAME), | ||
38 | }; | ||
39 | |||
40 | static struct ata_port_operations palmld_port_ops = { | ||
41 | .inherits = &ata_sff_port_ops, | ||
42 | .sff_data_xfer = ata_sff_data_xfer_noirq, | ||
43 | .cable_detect = ata_cable_40wire, | ||
44 | }; | ||
45 | |||
46 | static __devinit int palmld_pata_probe(struct platform_device *pdev) | ||
47 | { | ||
48 | struct ata_host *host; | ||
49 | struct ata_port *ap; | ||
50 | void __iomem *mem; | ||
51 | int ret; | ||
52 | |||
53 | /* allocate host */ | ||
54 | host = ata_host_alloc(&pdev->dev, 1); | ||
55 | if (!host) | ||
56 | return -ENOMEM; | ||
57 | |||
58 | /* remap drive's physical memory address */ | ||
59 | mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000); | ||
60 | if (!mem) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | /* request and activate power GPIO, IRQ GPIO */ | ||
64 | ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR"); | ||
65 | if (ret) | ||
66 | goto err1; | ||
67 | ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_PWEN, 1); | ||
68 | if (ret) | ||
69 | goto err2; | ||
70 | |||
71 | ret = gpio_request(GPIO_NR_PALMLD_IDE_RESET, "HDD RST"); | ||
72 | if (ret) | ||
73 | goto err2; | ||
74 | ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_RESET, 0); | ||
75 | if (ret) | ||
76 | goto err3; | ||
77 | |||
78 | /* reset the drive */ | ||
79 | gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 0); | ||
80 | msleep(30); | ||
81 | gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 1); | ||
82 | msleep(30); | ||
83 | |||
84 | /* setup the ata port */ | ||
85 | ap = host->ports[0]; | ||
86 | ap->ops = &palmld_port_ops; | ||
87 | ap->pio_mask = ATA_PIO4; | ||
88 | ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_PIO_POLLING; | ||
89 | |||
90 | /* memory mapping voodoo */ | ||
91 | ap->ioaddr.cmd_addr = mem + 0x10; | ||
92 | ap->ioaddr.altstatus_addr = mem + 0xe; | ||
93 | ap->ioaddr.ctl_addr = mem + 0xe; | ||
94 | |||
95 | /* start the port */ | ||
96 | ata_sff_std_ports(&ap->ioaddr); | ||
97 | |||
98 | /* activate host */ | ||
99 | return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING, | ||
100 | &palmld_sht); | ||
101 | |||
102 | err3: | ||
103 | gpio_free(GPIO_NR_PALMLD_IDE_RESET); | ||
104 | err2: | ||
105 | gpio_free(GPIO_NR_PALMLD_IDE_PWEN); | ||
106 | err1: | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | static __devexit int palmld_pata_remove(struct platform_device *dev) | ||
111 | { | ||
112 | struct ata_host *host = platform_get_drvdata(dev); | ||
113 | |||
114 | ata_host_detach(host); | ||
115 | |||
116 | /* power down the HDD */ | ||
117 | gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0); | ||
118 | |||
119 | gpio_free(GPIO_NR_PALMLD_IDE_RESET); | ||
120 | gpio_free(GPIO_NR_PALMLD_IDE_PWEN); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static struct platform_driver palmld_pata_platform_driver = { | ||
126 | .driver = { | ||
127 | .name = DRV_NAME, | ||
128 | .owner = THIS_MODULE, | ||
129 | }, | ||
130 | .probe = palmld_pata_probe, | ||
131 | .remove = __devexit_p(palmld_pata_remove), | ||
132 | }; | ||
133 | |||
134 | static int __init palmld_pata_init(void) | ||
135 | { | ||
136 | return platform_driver_register(&palmld_pata_platform_driver); | ||
137 | } | ||
138 | |||
139 | static void __exit palmld_pata_exit(void) | ||
140 | { | ||
141 | platform_driver_unregister(&palmld_pata_platform_driver); | ||
142 | } | ||
143 | |||
144 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
145 | MODULE_DESCRIPTION("PalmLD PATA driver"); | ||
146 | MODULE_LICENSE("GPL"); | ||
147 | MODULE_ALIAS("platform:" DRV_NAME); | ||
148 | |||
149 | module_init(palmld_pata_init); | ||
150 | module_exit(palmld_pata_exit); | ||
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 9c00440dcf86..f4b3f7293feb 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -148,3 +148,15 @@ config HW_RANDOM_VIRTIO | |||
148 | 148 | ||
149 | To compile this driver as a module, choose M here: the | 149 | To compile this driver as a module, choose M here: the |
150 | module will be called virtio-rng. If unsure, say N. | 150 | module will be called virtio-rng. If unsure, say N. |
151 | |||
152 | config HW_RANDOM_MXC_RNGA | ||
153 | tristate "Freescale i.MX RNGA Random Number Generator" | ||
154 | depends on HW_RANDOM && ARCH_HAS_RNGA | ||
155 | ---help--- | ||
156 | This driver provides kernel-side support for the Random Number | ||
157 | Generator hardware found on Freescale i.MX processors. | ||
158 | |||
159 | To compile this driver as a module, choose M here: the | ||
160 | module will be called mxc-rnga. | ||
161 | |||
162 | If unsure, say Y. | ||
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index e81d21a5f28f..fd1ecd2f6731 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -15,3 +15,4 @@ obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o | |||
15 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o | 15 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o |
16 | obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o | 16 | obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o |
17 | obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o | 17 | obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o |
18 | obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o | ||
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c new file mode 100644 index 000000000000..187c6be80f43 --- /dev/null +++ b/drivers/char/hw_random/mxc-rnga.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * RNG driver for Freescale RNGA | ||
3 | * | ||
4 | * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. | ||
5 | * Author: Alan Carvalho de Assis <acassis@gmail.com> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * The code contained herein is licensed under the GNU General Public | ||
10 | * License. You may obtain a copy of the GNU General Public License | ||
11 | * Version 2 or later at the following locations: | ||
12 | * | ||
13 | * http://www.opensource.org/licenses/gpl-license.html | ||
14 | * http://www.gnu.org/copyleft/gpl.html | ||
15 | * | ||
16 | * This driver is based on other RNG drivers. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/hw_random.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | /* RNGA Registers */ | ||
30 | #define RNGA_CONTROL 0x00 | ||
31 | #define RNGA_STATUS 0x04 | ||
32 | #define RNGA_ENTROPY 0x08 | ||
33 | #define RNGA_OUTPUT_FIFO 0x0c | ||
34 | #define RNGA_MODE 0x10 | ||
35 | #define RNGA_VERIFICATION_CONTROL 0x14 | ||
36 | #define RNGA_OSC_CONTROL_COUNTER 0x18 | ||
37 | #define RNGA_OSC1_COUNTER 0x1c | ||
38 | #define RNGA_OSC2_COUNTER 0x20 | ||
39 | #define RNGA_OSC_COUNTER_STATUS 0x24 | ||
40 | |||
41 | /* RNGA Registers Range */ | ||
42 | #define RNG_ADDR_RANGE 0x28 | ||
43 | |||
44 | /* RNGA Control Register */ | ||
45 | #define RNGA_CONTROL_SLEEP 0x00000010 | ||
46 | #define RNGA_CONTROL_CLEAR_INT 0x00000008 | ||
47 | #define RNGA_CONTROL_MASK_INTS 0x00000004 | ||
48 | #define RNGA_CONTROL_HIGH_ASSURANCE 0x00000002 | ||
49 | #define RNGA_CONTROL_GO 0x00000001 | ||
50 | |||
51 | #define RNGA_STATUS_LEVEL_MASK 0x0000ff00 | ||
52 | |||
53 | /* RNGA Status Register */ | ||
54 | #define RNGA_STATUS_OSC_DEAD 0x80000000 | ||
55 | #define RNGA_STATUS_SLEEP 0x00000010 | ||
56 | #define RNGA_STATUS_ERROR_INT 0x00000008 | ||
57 | #define RNGA_STATUS_FIFO_UNDERFLOW 0x00000004 | ||
58 | #define RNGA_STATUS_LAST_READ_STATUS 0x00000002 | ||
59 | #define RNGA_STATUS_SECURITY_VIOLATION 0x00000001 | ||
60 | |||
61 | static struct platform_device *rng_dev; | ||
62 | |||
63 | static int mxc_rnga_data_present(struct hwrng *rng) | ||
64 | { | ||
65 | int level; | ||
66 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
67 | |||
68 | /* how many random numbers is in FIFO? [0-16] */ | ||
69 | level = ((__raw_readl(rng_base + RNGA_STATUS) & | ||
70 | RNGA_STATUS_LEVEL_MASK) >> 8); | ||
71 | |||
72 | return level > 0 ? 1 : 0; | ||
73 | } | ||
74 | |||
75 | static int mxc_rnga_data_read(struct hwrng *rng, u32 * data) | ||
76 | { | ||
77 | int err; | ||
78 | u32 ctrl; | ||
79 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
80 | |||
81 | /* retrieve a random number from FIFO */ | ||
82 | *data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO); | ||
83 | |||
84 | /* some error while reading this random number? */ | ||
85 | err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT; | ||
86 | |||
87 | /* if error: clear error interrupt, but doesn't return random number */ | ||
88 | if (err) { | ||
89 | dev_dbg(&rng_dev->dev, "Error while reading random number!\n"); | ||
90 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
91 | __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT, | ||
92 | rng_base + RNGA_CONTROL); | ||
93 | return 0; | ||
94 | } else | ||
95 | return 4; | ||
96 | } | ||
97 | |||
98 | static int mxc_rnga_init(struct hwrng *rng) | ||
99 | { | ||
100 | u32 ctrl, osc; | ||
101 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
102 | |||
103 | /* wake up */ | ||
104 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
105 | __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL); | ||
106 | |||
107 | /* verify if oscillator is working */ | ||
108 | osc = __raw_readl(rng_base + RNGA_STATUS); | ||
109 | if (osc & RNGA_STATUS_OSC_DEAD) { | ||
110 | dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n"); | ||
111 | return -ENODEV; | ||
112 | } | ||
113 | |||
114 | /* go running */ | ||
115 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
116 | __raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static void mxc_rnga_cleanup(struct hwrng *rng) | ||
122 | { | ||
123 | u32 ctrl; | ||
124 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
125 | |||
126 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
127 | |||
128 | /* stop rnga */ | ||
129 | __raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); | ||
130 | } | ||
131 | |||
132 | static struct hwrng mxc_rnga = { | ||
133 | .name = "mxc-rnga", | ||
134 | .init = mxc_rnga_init, | ||
135 | .cleanup = mxc_rnga_cleanup, | ||
136 | .data_present = mxc_rnga_data_present, | ||
137 | .data_read = mxc_rnga_data_read | ||
138 | }; | ||
139 | |||
140 | static int __init mxc_rnga_probe(struct platform_device *pdev) | ||
141 | { | ||
142 | int err = -ENODEV; | ||
143 | struct clk *clk; | ||
144 | struct resource *res, *mem; | ||
145 | void __iomem *rng_base = NULL; | ||
146 | |||
147 | if (rng_dev) | ||
148 | return -EBUSY; | ||
149 | |||
150 | clk = clk_get(&pdev->dev, "rng"); | ||
151 | if (IS_ERR(clk)) { | ||
152 | dev_err(&pdev->dev, "Could not get rng_clk!\n"); | ||
153 | err = PTR_ERR(clk); | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | clk_enable(clk); | ||
158 | |||
159 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
160 | if (!res) { | ||
161 | err = -ENOENT; | ||
162 | goto err_region; | ||
163 | } | ||
164 | |||
165 | mem = request_mem_region(res->start, resource_size(res), pdev->name); | ||
166 | if (mem == NULL) { | ||
167 | err = -EBUSY; | ||
168 | goto err_region; | ||
169 | } | ||
170 | |||
171 | rng_base = ioremap(res->start, resource_size(res)); | ||
172 | if (!rng_base) { | ||
173 | err = -ENOMEM; | ||
174 | goto err_ioremap; | ||
175 | } | ||
176 | |||
177 | mxc_rnga.priv = (unsigned long)rng_base; | ||
178 | |||
179 | err = hwrng_register(&mxc_rnga); | ||
180 | if (err) { | ||
181 | dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err); | ||
182 | goto err_register; | ||
183 | } | ||
184 | |||
185 | rng_dev = pdev; | ||
186 | |||
187 | dev_info(&pdev->dev, "MXC RNGA Registered.\n"); | ||
188 | |||
189 | return 0; | ||
190 | |||
191 | err_register: | ||
192 | iounmap(rng_base); | ||
193 | rng_base = NULL; | ||
194 | |||
195 | err_ioremap: | ||
196 | release_mem_region(res->start, resource_size(res)); | ||
197 | |||
198 | err_region: | ||
199 | clk_disable(clk); | ||
200 | clk_put(clk); | ||
201 | |||
202 | out: | ||
203 | return err; | ||
204 | } | ||
205 | |||
206 | static int __exit mxc_rnga_remove(struct platform_device *pdev) | ||
207 | { | ||
208 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
209 | void __iomem *rng_base = (void __iomem *)mxc_rnga.priv; | ||
210 | struct clk *clk = clk_get(&pdev->dev, "rng"); | ||
211 | |||
212 | hwrng_unregister(&mxc_rnga); | ||
213 | |||
214 | iounmap(rng_base); | ||
215 | |||
216 | release_mem_region(res->start, resource_size(res)); | ||
217 | |||
218 | clk_disable(clk); | ||
219 | clk_put(clk); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static struct platform_driver mxc_rnga_driver = { | ||
225 | .driver = { | ||
226 | .name = "mxc_rnga", | ||
227 | .owner = THIS_MODULE, | ||
228 | }, | ||
229 | .remove = __exit_p(mxc_rnga_remove), | ||
230 | }; | ||
231 | |||
232 | static int __init mod_init(void) | ||
233 | { | ||
234 | return platform_driver_probe(&mxc_rnga_driver, mxc_rnga_probe); | ||
235 | } | ||
236 | |||
237 | static void __exit mod_exit(void) | ||
238 | { | ||
239 | platform_driver_unregister(&mxc_rnga_driver); | ||
240 | } | ||
241 | |||
242 | module_init(mod_init); | ||
243 | module_exit(mod_exit); | ||
244 | |||
245 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
246 | MODULE_DESCRIPTION("H/W RNGA driver for i.MX"); | ||
247 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index acc7143d9655..035a6c7e59df 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -34,10 +34,24 @@ | |||
34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
35 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
36 | 36 | ||
37 | #include <mach/hardware.h> | ||
38 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
39 | #include <asm/io.h> | 38 | #include <asm/io.h> |
40 | #include <mach/i2c.h> | 39 | #include <plat/i2c.h> |
40 | |||
41 | /* | ||
42 | * I2C register offsets will be shifted 0 or 1 bit left, depending on | ||
43 | * different SoCs | ||
44 | */ | ||
45 | #define REG_SHIFT_0 (0 << 0) | ||
46 | #define REG_SHIFT_1 (1 << 0) | ||
47 | #define REG_SHIFT(d) ((d) & 0x1) | ||
48 | |||
49 | static const struct platform_device_id i2c_pxa_id_table[] = { | ||
50 | { "pxa2xx-i2c", REG_SHIFT_1 }, | ||
51 | { "pxa3xx-pwri2c", REG_SHIFT_0 }, | ||
52 | { }, | ||
53 | }; | ||
54 | MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); | ||
41 | 55 | ||
42 | /* | 56 | /* |
43 | * I2C registers and bit definitions | 57 | * I2C registers and bit definitions |
@@ -985,6 +999,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
985 | struct pxa_i2c *i2c; | 999 | struct pxa_i2c *i2c; |
986 | struct resource *res; | 1000 | struct resource *res; |
987 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | 1001 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; |
1002 | struct platform_device_id *id = platform_get_device_id(dev); | ||
988 | int ret; | 1003 | int ret; |
989 | int irq; | 1004 | int irq; |
990 | 1005 | ||
@@ -1028,7 +1043,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1028 | ret = -EIO; | 1043 | ret = -EIO; |
1029 | goto eremap; | 1044 | goto eremap; |
1030 | } | 1045 | } |
1031 | i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1; | 1046 | i2c->reg_shift = REG_SHIFT(id->driver_data); |
1032 | 1047 | ||
1033 | i2c->iobase = res->start; | 1048 | i2c->iobase = res->start; |
1034 | i2c->iosize = res_len(res); | 1049 | i2c->iosize = res_len(res); |
@@ -1150,6 +1165,7 @@ static struct platform_driver i2c_pxa_driver = { | |||
1150 | .name = "pxa2xx-i2c", | 1165 | .name = "pxa2xx-i2c", |
1151 | .owner = THIS_MODULE, | 1166 | .owner = THIS_MODULE, |
1152 | }, | 1167 | }, |
1168 | .id_table = i2c_pxa_id_table, | ||
1153 | }; | 1169 | }; |
1154 | 1170 | ||
1155 | static int __init i2c_adap_pxa_init(void) | 1171 | static int __init i2c_adap_pxa_init(void) |
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index a28c06d686e1..89b394183a75 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
@@ -135,7 +135,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | |||
135 | io->dev.parent = &dev->dev; | 135 | io->dev.parent = &dev->dev; |
136 | 136 | ||
137 | kmi->io = io; | 137 | kmi->io = io; |
138 | kmi->base = ioremap(dev->res.start, KMI_SIZE); | 138 | kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); |
139 | if (!kmi->base) { | 139 | if (!kmi->base) { |
140 | ret = -ENOMEM; | 140 | ret = -ENOMEM; |
141 | goto out; | 141 | goto out; |
diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c index 1aa46a390a0d..173d104d9ff2 100644 --- a/drivers/leds/leds-h1940.c +++ b/drivers/leds/leds-h1940.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
18 | #include <linux/leds.h> | 18 | #include <linux/leds.h> |
19 | #include <linux/gpio.h> | ||
20 | |||
19 | #include <mach/regs-gpio.h> | 21 | #include <mach/regs-gpio.h> |
20 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
21 | #include <mach/h1940-latch.h> | 23 | #include <mach/h1940-latch.h> |
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index aa2e7ae0cdae..aa7acf3b9224 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/leds.h> | 17 | #include <linux/leds.h> |
18 | #include <linux/gpio.h> | ||
18 | 19 | ||
19 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
20 | #include <mach/regs-gpio.h> | 21 | #include <mach/regs-gpio.h> |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9d48da2fb013..57835f5715fc 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -758,10 +758,14 @@ config VIDEO_MX1 | |||
758 | ---help--- | 758 | ---help--- |
759 | This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface | 759 | This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface |
760 | 760 | ||
761 | config MX3_VIDEO | ||
762 | bool | ||
763 | |||
761 | config VIDEO_MX3 | 764 | config VIDEO_MX3 |
762 | tristate "i.MX3x Camera Sensor Interface driver" | 765 | tristate "i.MX3x Camera Sensor Interface driver" |
763 | depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA | 766 | depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA |
764 | select VIDEOBUF_DMA_CONTIG | 767 | select VIDEOBUF_DMA_CONTIG |
768 | select MX3_VIDEO | ||
765 | ---help--- | 769 | ---help--- |
766 | This is a v4l2 driver for the i.MX3x Camera Sensor Interface | 770 | This is a v4l2 driver for the i.MX3x Camera Sensor Interface |
767 | 771 | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index b4cf691f3f64..3eb87bda14f3 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -155,7 +155,7 @@ config MMC_ATMELMCI_DMA | |||
155 | 155 | ||
156 | config MMC_IMX | 156 | config MMC_IMX |
157 | tristate "Motorola i.MX Multimedia Card Interface support" | 157 | tristate "Motorola i.MX Multimedia Card Interface support" |
158 | depends on ARCH_IMX | 158 | depends on ARCH_MX1 |
159 | help | 159 | help |
160 | This selects the Motorola i.MX Multimedia card Interface. | 160 | This selects the Motorola i.MX Multimedia card Interface. |
161 | If you have a i.MX platform with a Multimedia Card slot, | 161 | If you have a i.MX platform with a Multimedia Card slot, |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 7d4febdab286..e1aa8471ab1c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -546,7 +546,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
546 | host->mclk = clk_get_rate(host->clk); | 546 | host->mclk = clk_get_rate(host->clk); |
547 | DBG(host, "eventual mclk rate: %u Hz\n", host->mclk); | 547 | DBG(host, "eventual mclk rate: %u Hz\n", host->mclk); |
548 | } | 548 | } |
549 | host->base = ioremap(dev->res.start, SZ_4K); | 549 | host->base = ioremap(dev->res.start, resource_size(&dev->res)); |
550 | if (!host->base) { | 550 | if (!host->base) { |
551 | ret = -ENOMEM; | 551 | ret = -ENOMEM; |
552 | goto clk_disable; | 552 | goto clk_disable; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index c40cb96255a2..1cf9cfb3b64f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -1073,7 +1073,6 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1073 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1073 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
1074 | mmc->max_seg_size = mmc->max_req_size; | 1074 | mmc->max_seg_size = mmc->max_req_size; |
1075 | 1075 | ||
1076 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | ||
1077 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; | 1076 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; |
1078 | 1077 | ||
1079 | if (pdata->slots[host->slot_id].wires >= 8) | 1078 | if (pdata->slots[host->slot_id].wires >= 8) |
@@ -1110,13 +1109,14 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1110 | goto err_irq; | 1109 | goto err_irq; |
1111 | } | 1110 | } |
1112 | 1111 | ||
1112 | /* initialize power supplies, gpios, etc */ | ||
1113 | if (pdata->init != NULL) { | 1113 | if (pdata->init != NULL) { |
1114 | if (pdata->init(&pdev->dev) != 0) { | 1114 | if (pdata->init(&pdev->dev) != 0) { |
1115 | dev_dbg(mmc_dev(host->mmc), | 1115 | dev_dbg(mmc_dev(host->mmc), "late init error\n"); |
1116 | "Unable to configure MMC IRQs\n"); | ||
1117 | goto err_irq_cd_init; | 1116 | goto err_irq_cd_init; |
1118 | } | 1117 | } |
1119 | } | 1118 | } |
1119 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | ||
1120 | 1120 | ||
1121 | /* Request IRQ for card detect */ | 1121 | /* Request IRQ for card detect */ |
1122 | if ((mmc_slot(host).card_detect_irq)) { | 1122 | if ((mmc_slot(host).card_detect_irq)) { |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 2db166b7096f..4eb4f37544ab 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/mmc/host.h> | 17 | #include <linux/mmc/host.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/cpufreq.h> | 19 | #include <linux/cpufreq.h> |
20 | #include <linux/gpio.h> | ||
20 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | 23 | ||
@@ -789,7 +790,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, | |||
789 | 790 | ||
790 | last_source = source; | 791 | last_source = source; |
791 | 792 | ||
792 | s3c2410_dma_devconfig(host->dma, source, 3, | 793 | s3c2410_dma_devconfig(host->dma, source, |
793 | host->mem->start + host->sdidata); | 794 | host->mem->start + host->sdidata); |
794 | 795 | ||
795 | if (!setup_ok) { | 796 | if (!setup_ok) { |
@@ -1121,7 +1122,7 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1121 | case MMC_POWER_OFF: | 1122 | case MMC_POWER_OFF: |
1122 | default: | 1123 | default: |
1123 | s3c2410_gpio_setpin(S3C2410_GPE5, 0); | 1124 | s3c2410_gpio_setpin(S3C2410_GPE5, 0); |
1124 | s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP); | 1125 | s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPIO_OUTPUT); |
1125 | 1126 | ||
1126 | if (host->is2440) | 1127 | if (host->is2440) |
1127 | mci_con |= S3C2440_SDICON_SDRESET; | 1128 | mci_con |= S3C2440_SDICON_SDRESET; |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index f2e9de1414df..6391e3dc8002 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <mach/gpmc.h> | 39 | #include <mach/gpmc.h> |
40 | #include <mach/onenand.h> | 40 | #include <mach/onenand.h> |
41 | #include <mach/gpio.h> | 41 | #include <mach/gpio.h> |
42 | #include <mach/pm.h> | ||
43 | 42 | ||
44 | #include <mach/dma.h> | 43 | #include <mach/dma.h> |
45 | 44 | ||
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index a740053d3af3..b6d188115caf 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c | |||
@@ -456,7 +456,8 @@ static inline void queue_put_desc(unsigned int queue, u32 phys, | |||
456 | debug_desc(phys, desc); | 456 | debug_desc(phys, desc); |
457 | BUG_ON(phys & 0x1F); | 457 | BUG_ON(phys & 0x1F); |
458 | qmgr_put_entry(queue, phys); | 458 | qmgr_put_entry(queue, phys); |
459 | BUG_ON(qmgr_stat_overflow(queue)); | 459 | /* Don't check for queue overflow here, we've allocated sufficient |
460 | length and queues >= 32 don't support this check anyway. */ | ||
460 | } | 461 | } |
461 | 462 | ||
462 | 463 | ||
@@ -512,8 +513,8 @@ static int eth_poll(struct napi_struct *napi, int budget) | |||
512 | #endif | 513 | #endif |
513 | napi_complete(napi); | 514 | napi_complete(napi); |
514 | qmgr_enable_irq(rxq); | 515 | qmgr_enable_irq(rxq); |
515 | if (!qmgr_stat_empty(rxq) && | 516 | if (!qmgr_stat_below_low_watermark(rxq) && |
516 | napi_reschedule(napi)) { | 517 | napi_reschedule(napi)) { /* not empty again */ |
517 | #if DEBUG_RX | 518 | #if DEBUG_RX |
518 | printk(KERN_DEBUG "%s: eth_poll" | 519 | printk(KERN_DEBUG "%s: eth_poll" |
519 | " napi_reschedule successed\n", | 520 | " napi_reschedule successed\n", |
@@ -630,9 +631,9 @@ static void eth_txdone_irq(void *unused) | |||
630 | port->tx_buff_tab[n_desc] = NULL; | 631 | port->tx_buff_tab[n_desc] = NULL; |
631 | } | 632 | } |
632 | 633 | ||
633 | start = qmgr_stat_empty(port->plat->txreadyq); | 634 | start = qmgr_stat_below_low_watermark(port->plat->txreadyq); |
634 | queue_put_desc(port->plat->txreadyq, phys, desc); | 635 | queue_put_desc(port->plat->txreadyq, phys, desc); |
635 | if (start) { | 636 | if (start) { /* TX-ready queue was empty */ |
636 | #if DEBUG_TX | 637 | #if DEBUG_TX |
637 | printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n", | 638 | printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n", |
638 | port->netdev->name); | 639 | port->netdev->name); |
@@ -708,13 +709,14 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
708 | queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc); | 709 | queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc); |
709 | dev->trans_start = jiffies; | 710 | dev->trans_start = jiffies; |
710 | 711 | ||
711 | if (qmgr_stat_empty(txreadyq)) { | 712 | if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ |
712 | #if DEBUG_TX | 713 | #if DEBUG_TX |
713 | printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name); | 714 | printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name); |
714 | #endif | 715 | #endif |
715 | netif_stop_queue(dev); | 716 | netif_stop_queue(dev); |
716 | /* we could miss TX ready interrupt */ | 717 | /* we could miss TX ready interrupt */ |
717 | if (!qmgr_stat_empty(txreadyq)) { | 718 | /* really empty in fact */ |
719 | if (!qmgr_stat_below_low_watermark(txreadyq)) { | ||
718 | #if DEBUG_TX | 720 | #if DEBUG_TX |
719 | printk(KERN_DEBUG "%s: eth_xmit ready again\n", | 721 | printk(KERN_DEBUG "%s: eth_xmit ready again\n", |
720 | dev->name); | 722 | dev->name); |
@@ -814,29 +816,29 @@ static int request_queues(struct port *port) | |||
814 | int err; | 816 | int err; |
815 | 817 | ||
816 | err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0, | 818 | err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0, |
817 | "%s:RX-free", port->netdev->name); | 819 | "%s:RX-free", port->netdev->name); |
818 | if (err) | 820 | if (err) |
819 | return err; | 821 | return err; |
820 | 822 | ||
821 | err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0, | 823 | err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0, |
822 | "%s:RX", port->netdev->name); | 824 | "%s:RX", port->netdev->name); |
823 | if (err) | 825 | if (err) |
824 | goto rel_rxfree; | 826 | goto rel_rxfree; |
825 | 827 | ||
826 | err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0, | 828 | err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0, |
827 | "%s:TX", port->netdev->name); | 829 | "%s:TX", port->netdev->name); |
828 | if (err) | 830 | if (err) |
829 | goto rel_rx; | 831 | goto rel_rx; |
830 | 832 | ||
831 | err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, | 833 | err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, |
832 | "%s:TX-ready", port->netdev->name); | 834 | "%s:TX-ready", port->netdev->name); |
833 | if (err) | 835 | if (err) |
834 | goto rel_tx; | 836 | goto rel_tx; |
835 | 837 | ||
836 | /* TX-done queue handles skbs sent out by the NPEs */ | 838 | /* TX-done queue handles skbs sent out by the NPEs */ |
837 | if (!ports_open) { | 839 | if (!ports_open) { |
838 | err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0, | 840 | err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0, |
839 | "%s:TX-done", DRV_NAME); | 841 | "%s:TX-done", DRV_NAME); |
840 | if (err) | 842 | if (err) |
841 | goto rel_txready; | 843 | goto rel_txready; |
842 | } | 844 | } |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 329f890e2903..f1f773b17fe1 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
@@ -45,7 +45,8 @@ | |||
45 | defined(CONFIG_MACH_ZYLONITE) ||\ | 45 | defined(CONFIG_MACH_ZYLONITE) ||\ |
46 | defined(CONFIG_MACH_LITTLETON) ||\ | 46 | defined(CONFIG_MACH_LITTLETON) ||\ |
47 | defined(CONFIG_MACH_ZYLONITE2) ||\ | 47 | defined(CONFIG_MACH_ZYLONITE2) ||\ |
48 | defined(CONFIG_ARCH_VIPER) | 48 | defined(CONFIG_ARCH_VIPER) ||\ |
49 | defined(CONFIG_MACH_STARGATE2) | ||
49 | 50 | ||
50 | #include <asm/mach-types.h> | 51 | #include <asm/mach-types.h> |
51 | 52 | ||
@@ -73,7 +74,7 @@ | |||
73 | /* We actually can't write halfwords properly if not word aligned */ | 74 | /* We actually can't write halfwords properly if not word aligned */ |
74 | static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) | 75 | static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) |
75 | { | 76 | { |
76 | if (machine_is_mainstone() && reg & 2) { | 77 | if ((machine_is_mainstone() || machine_is_stargate2()) && reg & 2) { |
77 | unsigned int v = val << 16; | 78 | unsigned int v = val << 16; |
78 | v |= readl(ioaddr + (reg & ~2)) & 0xffff; | 79 | v |= readl(ioaddr + (reg & ~2)) & 0xffff; |
79 | writel(v, ioaddr + (reg & ~2)); | 80 | writel(v, ioaddr + (reg & ~2)); |
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 765a7f5d6aa4..a6dc317083d3 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c | |||
@@ -579,7 +579,8 @@ static inline void queue_put_desc(unsigned int queue, u32 phys, | |||
579 | debug_desc(phys, desc); | 579 | debug_desc(phys, desc); |
580 | BUG_ON(phys & 0x1F); | 580 | BUG_ON(phys & 0x1F); |
581 | qmgr_put_entry(queue, phys); | 581 | qmgr_put_entry(queue, phys); |
582 | BUG_ON(qmgr_stat_overflow(queue)); | 582 | /* Don't check for queue overflow here, we've allocated sufficient |
583 | length and queues >= 32 don't support this check anyway. */ | ||
583 | } | 584 | } |
584 | 585 | ||
585 | 586 | ||
@@ -789,10 +790,10 @@ static void hss_hdlc_txdone_irq(void *pdev) | |||
789 | free_buffer_irq(port->tx_buff_tab[n_desc]); | 790 | free_buffer_irq(port->tx_buff_tab[n_desc]); |
790 | port->tx_buff_tab[n_desc] = NULL; | 791 | port->tx_buff_tab[n_desc] = NULL; |
791 | 792 | ||
792 | start = qmgr_stat_empty(port->plat->txreadyq); | 793 | start = qmgr_stat_below_low_watermark(port->plat->txreadyq); |
793 | queue_put_desc(port->plat->txreadyq, | 794 | queue_put_desc(port->plat->txreadyq, |
794 | tx_desc_phys(port, n_desc), desc); | 795 | tx_desc_phys(port, n_desc), desc); |
795 | if (start) { | 796 | if (start) { /* TX-ready queue was empty */ |
796 | #if DEBUG_TX | 797 | #if DEBUG_TX |
797 | printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" | 798 | printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" |
798 | " ready\n", dev->name); | 799 | " ready\n", dev->name); |
@@ -867,13 +868,13 @@ static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) | |||
867 | queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); | 868 | queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); |
868 | dev->trans_start = jiffies; | 869 | dev->trans_start = jiffies; |
869 | 870 | ||
870 | if (qmgr_stat_empty(txreadyq)) { | 871 | if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ |
871 | #if DEBUG_TX | 872 | #if DEBUG_TX |
872 | printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); | 873 | printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); |
873 | #endif | 874 | #endif |
874 | netif_stop_queue(dev); | 875 | netif_stop_queue(dev); |
875 | /* we could miss TX ready interrupt */ | 876 | /* we could miss TX ready interrupt */ |
876 | if (!qmgr_stat_empty(txreadyq)) { | 877 | if (!qmgr_stat_below_low_watermark(txreadyq)) { |
877 | #if DEBUG_TX | 878 | #if DEBUG_TX |
878 | printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", | 879 | printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", |
879 | dev->name); | 880 | dev->name); |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 276473543982..fbf965b31c14 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -217,7 +217,7 @@ config PCMCIA_PXA2XX | |||
217 | depends on ARM && ARCH_PXA && PCMCIA | 217 | depends on ARM && ARCH_PXA && PCMCIA |
218 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ | 218 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ |
219 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ | 219 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ |
220 | || ARCH_VIPER || ARCH_PXA_ESERIES) | 220 | || ARCH_VIPER || ARCH_PXA_ESERIES || MACH_STARGATE2) |
221 | help | 221 | help |
222 | Say Y here to include support for the PXA2xx PCMCIA controller | 222 | Say Y here to include support for the PXA2xx PCMCIA controller |
223 | 223 | ||
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index bbac46327227..047394d98ac2 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -73,5 +73,6 @@ pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o | |||
73 | pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o | 73 | pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o |
74 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o | 74 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o |
75 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o | 75 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o |
76 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o | ||
76 | 77 | ||
77 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o $(pxa2xx-obj-y) | 78 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o $(pxa2xx-obj-y) |
diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c new file mode 100644 index 000000000000..490749ea677f --- /dev/null +++ b/drivers/pcmcia/pxa2xx_stargate2.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * linux/drivers/pcmcia/pxa2xx_stargate2.c | ||
3 | * | ||
4 | * Stargate 2 PCMCIA specific routines. | ||
5 | * | ||
6 | * Created: December 6, 2005 | ||
7 | * Author: Ed C. Epp | ||
8 | * Copyright: Intel Corp 2005 | ||
9 | * Jonathan Cameron <jic23@cam.ac.uk> 2009 | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/gpio.h> | ||
23 | |||
24 | #include <pcmcia/ss.h> | ||
25 | |||
26 | #include <asm/irq.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | |||
29 | #include "soc_common.h" | ||
30 | |||
31 | #define SG2_S0_BUFF_CTL 120 | ||
32 | #define SG2_S0_POWER_CTL 108 | ||
33 | #define SG2_S0_GPIO_RESET 82 | ||
34 | #define SG2_S0_GPIO_DETECT 53 | ||
35 | #define SG2_S0_GPIO_READY 81 | ||
36 | |||
37 | static struct pcmcia_irqs irqs[] = { | ||
38 | { 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "PCMCIA0 CD" }, | ||
39 | }; | ||
40 | |||
41 | static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | ||
42 | { | ||
43 | skt->irq = IRQ_GPIO(SG2_S0_GPIO_READY); | ||
44 | return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
45 | } | ||
46 | |||
47 | static void sg2_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | ||
48 | { | ||
49 | soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
50 | } | ||
51 | |||
52 | static void sg2_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | ||
53 | struct pcmcia_state *state) | ||
54 | { | ||
55 | state->detect = !gpio_get_value(SG2_S0_GPIO_DETECT); | ||
56 | state->ready = !!gpio_get_value(SG2_S0_GPIO_READY); | ||
57 | state->bvd1 = 0; /* not available - battery detect on card */ | ||
58 | state->bvd2 = 0; /* not available */ | ||
59 | state->vs_3v = 1; /* not available - voltage detect for card */ | ||
60 | state->vs_Xv = 0; /* not available */ | ||
61 | state->wrprot = 0; /* not available - write protect */ | ||
62 | } | ||
63 | |||
64 | static int sg2_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | ||
65 | const socket_state_t *state) | ||
66 | { | ||
67 | /* Enable card power */ | ||
68 | switch (state->Vcc) { | ||
69 | case 0: | ||
70 | /* sets power ctl register high */ | ||
71 | gpio_set_value(SG2_S0_POWER_CTL, 1); | ||
72 | break; | ||
73 | case 33: | ||
74 | case 50: | ||
75 | /* sets power control register low (clear) */ | ||
76 | gpio_set_value(SG2_S0_POWER_CTL, 0); | ||
77 | msleep(100); | ||
78 | break; | ||
79 | default: | ||
80 | pr_err("%s(): bad Vcc %u\n", | ||
81 | __func__, state->Vcc); | ||
82 | return -1; | ||
83 | } | ||
84 | |||
85 | /* reset */ | ||
86 | gpio_set_value(SG2_S0_GPIO_RESET, !!(state->flags & SS_RESET)); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static void sg2_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | ||
92 | { | ||
93 | soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
94 | } | ||
95 | |||
96 | static void sg2_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | ||
97 | { | ||
98 | soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
99 | } | ||
100 | |||
101 | static struct pcmcia_low_level sg2_pcmcia_ops __initdata = { | ||
102 | .owner = THIS_MODULE, | ||
103 | .hw_init = sg2_pcmcia_hw_init, | ||
104 | .hw_shutdown = sg2_pcmcia_hw_shutdown, | ||
105 | .socket_state = sg2_pcmcia_socket_state, | ||
106 | .configure_socket = sg2_pcmcia_configure_socket, | ||
107 | .socket_init = sg2_pcmcia_socket_init, | ||
108 | .socket_suspend = sg2_pcmcia_socket_suspend, | ||
109 | .nr = 1, | ||
110 | }; | ||
111 | |||
112 | static struct platform_device *sg2_pcmcia_device; | ||
113 | |||
114 | static int __init sg2_pcmcia_init(void) | ||
115 | { | ||
116 | int ret; | ||
117 | |||
118 | if (!machine_is_stargate2()) | ||
119 | return -ENODEV; | ||
120 | |||
121 | sg2_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | ||
122 | if (!sg2_pcmcia_device) | ||
123 | return -ENOMEM; | ||
124 | |||
125 | ret = gpio_request(SG2_S0_BUFF_CTL, "SG2 CF buff ctl"); | ||
126 | if (ret) | ||
127 | goto error_put_platform_device; | ||
128 | ret = gpio_request(SG2_S0_POWER_CTL, "SG2 CF power ctl"); | ||
129 | if (ret) | ||
130 | goto error_free_gpio_buff_ctl; | ||
131 | ret = gpio_request(SG2_S0_GPIO_RESET, "SG2 CF reset"); | ||
132 | if (ret) | ||
133 | goto error_free_gpio_power_ctl; | ||
134 | /* Set gpio directions */ | ||
135 | gpio_direction_output(SG2_S0_BUFF_CTL, 0); | ||
136 | gpio_direction_output(SG2_S0_POWER_CTL, 1); | ||
137 | gpio_direction_output(SG2_S0_GPIO_RESET, 1); | ||
138 | |||
139 | ret = platform_device_add_data(sg2_pcmcia_device, | ||
140 | &sg2_pcmcia_ops, | ||
141 | sizeof(sg2_pcmcia_ops)); | ||
142 | if (ret) | ||
143 | goto error_free_gpio_reset; | ||
144 | |||
145 | ret = platform_device_add(sg2_pcmcia_device); | ||
146 | if (ret) | ||
147 | goto error_free_gpio_reset; | ||
148 | |||
149 | return 0; | ||
150 | error_free_gpio_reset: | ||
151 | gpio_free(SG2_S0_GPIO_RESET); | ||
152 | error_free_gpio_power_ctl: | ||
153 | gpio_free(SG2_S0_POWER_CTL); | ||
154 | error_free_gpio_buff_ctl: | ||
155 | gpio_free(SG2_S0_BUFF_CTL); | ||
156 | error_put_platform_device: | ||
157 | platform_device_put(sg2_pcmcia_device); | ||
158 | |||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | static void __exit sg2_pcmcia_exit(void) | ||
163 | { | ||
164 | platform_device_unregister(sg2_pcmcia_device); | ||
165 | gpio_free(SG2_S0_BUFF_CTL); | ||
166 | gpio_free(SG2_S0_POWER_CTL); | ||
167 | gpio_free(SG2_S0_GPIO_RESET); | ||
168 | } | ||
169 | |||
170 | fs_initcall(sg2_pcmcia_init); | ||
171 | module_exit(sg2_pcmcia_exit); | ||
172 | |||
173 | MODULE_LICENSE("GPL"); | ||
174 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index f7a3283dd029..551332e4ed02 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
@@ -12,32 +12,56 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <mach/hardware.h> | 15 | #include <linux/io.h> |
16 | |||
17 | #define EP93XX_RTC_DATA 0x000 | ||
18 | #define EP93XX_RTC_MATCH 0x004 | ||
19 | #define EP93XX_RTC_STATUS 0x008 | ||
20 | #define EP93XX_RTC_STATUS_INTR (1<<0) | ||
21 | #define EP93XX_RTC_LOAD 0x00C | ||
22 | #define EP93XX_RTC_CONTROL 0x010 | ||
23 | #define EP93XX_RTC_CONTROL_MIE (1<<0) | ||
24 | #define EP93XX_RTC_SWCOMP 0x108 | ||
25 | #define EP93XX_RTC_SWCOMP_DEL_MASK 0x001f0000 | ||
26 | #define EP93XX_RTC_SWCOMP_DEL_SHIFT 16 | ||
27 | #define EP93XX_RTC_SWCOMP_INT_MASK 0x0000ffff | ||
28 | #define EP93XX_RTC_SWCOMP_INT_SHIFT 0 | ||
29 | |||
30 | #define DRV_VERSION "0.3" | ||
16 | 31 | ||
17 | #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) | 32 | /* |
18 | #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) | 33 | * struct device dev.platform_data is used to store our private data |
19 | #define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C) | 34 | * because struct rtc_device does not have a variable to hold it. |
20 | #define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108) | 35 | */ |
21 | 36 | struct ep93xx_rtc { | |
22 | #define DRV_VERSION "0.2" | 37 | void __iomem *mmio_base; |
38 | }; | ||
23 | 39 | ||
24 | static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload, | 40 | static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, |
25 | unsigned short *delete) | 41 | unsigned short *delete) |
26 | { | 42 | { |
27 | unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP); | 43 | struct ep93xx_rtc *ep93xx_rtc = dev->platform_data; |
44 | unsigned long comp; | ||
45 | |||
46 | comp = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP); | ||
28 | 47 | ||
29 | if (preload) | 48 | if (preload) |
30 | *preload = comp & 0xffff; | 49 | *preload = (comp & EP93XX_RTC_SWCOMP_INT_MASK) |
50 | >> EP93XX_RTC_SWCOMP_INT_SHIFT; | ||
31 | 51 | ||
32 | if (delete) | 52 | if (delete) |
33 | *delete = (comp >> 16) & 0x1f; | 53 | *delete = (comp & EP93XX_RTC_SWCOMP_DEL_MASK) |
54 | >> EP93XX_RTC_SWCOMP_DEL_SHIFT; | ||
34 | 55 | ||
35 | return 0; | 56 | return 0; |
36 | } | 57 | } |
37 | 58 | ||
38 | static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) | 59 | static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) |
39 | { | 60 | { |
40 | unsigned long time = __raw_readl(EP93XX_RTC_DATA); | 61 | struct ep93xx_rtc *ep93xx_rtc = dev->platform_data; |
62 | unsigned long time; | ||
63 | |||
64 | time = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA); | ||
41 | 65 | ||
42 | rtc_time_to_tm(time, tm); | 66 | rtc_time_to_tm(time, tm); |
43 | return 0; | 67 | return 0; |
@@ -45,7 +69,9 @@ static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
45 | 69 | ||
46 | static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) | 70 | static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) |
47 | { | 71 | { |
48 | __raw_writel(secs + 1, EP93XX_RTC_LOAD); | 72 | struct ep93xx_rtc *ep93xx_rtc = dev->platform_data; |
73 | |||
74 | __raw_writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD); | ||
49 | return 0; | 75 | return 0; |
50 | } | 76 | } |
51 | 77 | ||
@@ -53,7 +79,7 @@ static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq) | |||
53 | { | 79 | { |
54 | unsigned short preload, delete; | 80 | unsigned short preload, delete; |
55 | 81 | ||
56 | ep93xx_get_swcomp(dev, &preload, &delete); | 82 | ep93xx_rtc_get_swcomp(dev, &preload, &delete); |
57 | 83 | ||
58 | seq_printf(seq, "preload\t\t: %d\n", preload); | 84 | seq_printf(seq, "preload\t\t: %d\n", preload); |
59 | seq_printf(seq, "delete\t\t: %d\n", delete); | 85 | seq_printf(seq, "delete\t\t: %d\n", delete); |
@@ -67,54 +93,104 @@ static const struct rtc_class_ops ep93xx_rtc_ops = { | |||
67 | .proc = ep93xx_rtc_proc, | 93 | .proc = ep93xx_rtc_proc, |
68 | }; | 94 | }; |
69 | 95 | ||
70 | static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev, | 96 | static ssize_t ep93xx_rtc_show_comp_preload(struct device *dev, |
71 | struct device_attribute *attr, char *buf) | 97 | struct device_attribute *attr, char *buf) |
72 | { | 98 | { |
73 | unsigned short preload; | 99 | unsigned short preload; |
74 | 100 | ||
75 | ep93xx_get_swcomp(dev, &preload, NULL); | 101 | ep93xx_rtc_get_swcomp(dev, &preload, NULL); |
76 | 102 | ||
77 | return sprintf(buf, "%d\n", preload); | 103 | return sprintf(buf, "%d\n", preload); |
78 | } | 104 | } |
79 | static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL); | 105 | static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_rtc_show_comp_preload, NULL); |
80 | 106 | ||
81 | static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev, | 107 | static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev, |
82 | struct device_attribute *attr, char *buf) | 108 | struct device_attribute *attr, char *buf) |
83 | { | 109 | { |
84 | unsigned short delete; | 110 | unsigned short delete; |
85 | 111 | ||
86 | ep93xx_get_swcomp(dev, NULL, &delete); | 112 | ep93xx_rtc_get_swcomp(dev, NULL, &delete); |
87 | 113 | ||
88 | return sprintf(buf, "%d\n", delete); | 114 | return sprintf(buf, "%d\n", delete); |
89 | } | 115 | } |
90 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL); | 116 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); |
91 | 117 | ||
92 | 118 | ||
93 | static int __devinit ep93xx_rtc_probe(struct platform_device *dev) | 119 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) |
94 | { | 120 | { |
95 | struct rtc_device *rtc = rtc_device_register("ep93xx", | 121 | struct ep93xx_rtc *ep93xx_rtc; |
96 | &dev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 122 | struct resource *res; |
123 | struct rtc_device *rtc; | ||
124 | int err; | ||
125 | |||
126 | ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL); | ||
127 | if (ep93xx_rtc == NULL) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
131 | if (res == NULL) | ||
132 | return -ENXIO; | ||
133 | |||
134 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
135 | if (res == NULL) | ||
136 | return -EBUSY; | ||
137 | |||
138 | ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res)); | ||
139 | if (ep93xx_rtc->mmio_base == NULL) { | ||
140 | err = -ENXIO; | ||
141 | goto fail; | ||
142 | } | ||
97 | 143 | ||
144 | pdev->dev.platform_data = ep93xx_rtc; | ||
145 | |||
146 | rtc = rtc_device_register(pdev->name, | ||
147 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | ||
98 | if (IS_ERR(rtc)) { | 148 | if (IS_ERR(rtc)) { |
99 | return PTR_ERR(rtc); | 149 | err = PTR_ERR(rtc); |
150 | goto fail; | ||
100 | } | 151 | } |
101 | 152 | ||
102 | platform_set_drvdata(dev, rtc); | 153 | platform_set_drvdata(pdev, rtc); |
103 | 154 | ||
104 | device_create_file(&dev->dev, &dev_attr_comp_preload); | 155 | err = device_create_file(&pdev->dev, &dev_attr_comp_preload); |
105 | device_create_file(&dev->dev, &dev_attr_comp_delete); | 156 | if (err) |
157 | goto fail; | ||
158 | err = device_create_file(&pdev->dev, &dev_attr_comp_delete); | ||
159 | if (err) { | ||
160 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
161 | goto fail; | ||
162 | } | ||
106 | 163 | ||
107 | return 0; | 164 | return 0; |
165 | |||
166 | fail: | ||
167 | if (ep93xx_rtc->mmio_base) { | ||
168 | iounmap(ep93xx_rtc->mmio_base); | ||
169 | pdev->dev.platform_data = NULL; | ||
170 | } | ||
171 | release_mem_region(res->start, resource_size(res)); | ||
172 | return err; | ||
108 | } | 173 | } |
109 | 174 | ||
110 | static int __devexit ep93xx_rtc_remove(struct platform_device *dev) | 175 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
111 | { | 176 | { |
112 | struct rtc_device *rtc = platform_get_drvdata(dev); | 177 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
178 | struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data; | ||
179 | struct resource *res; | ||
180 | |||
181 | /* cleanup sysfs */ | ||
182 | device_remove_file(&pdev->dev, &dev_attr_comp_delete); | ||
183 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
184 | |||
185 | rtc_device_unregister(rtc); | ||
186 | |||
187 | iounmap(ep93xx_rtc->mmio_base); | ||
188 | pdev->dev.platform_data = NULL; | ||
113 | 189 | ||
114 | if (rtc) | 190 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
115 | rtc_device_unregister(rtc); | 191 | release_mem_region(res->start, resource_size(res)); |
116 | 192 | ||
117 | platform_set_drvdata(dev, NULL); | 193 | platform_set_drvdata(pdev, NULL); |
118 | 194 | ||
119 | return 0; | 195 | return 0; |
120 | } | 196 | } |
@@ -122,23 +198,22 @@ static int __devexit ep93xx_rtc_remove(struct platform_device *dev) | |||
122 | /* work with hotplug and coldplug */ | 198 | /* work with hotplug and coldplug */ |
123 | MODULE_ALIAS("platform:ep93xx-rtc"); | 199 | MODULE_ALIAS("platform:ep93xx-rtc"); |
124 | 200 | ||
125 | static struct platform_driver ep93xx_rtc_platform_driver = { | 201 | static struct platform_driver ep93xx_rtc_driver = { |
126 | .driver = { | 202 | .driver = { |
127 | .name = "ep93xx-rtc", | 203 | .name = "ep93xx-rtc", |
128 | .owner = THIS_MODULE, | 204 | .owner = THIS_MODULE, |
129 | }, | 205 | }, |
130 | .probe = ep93xx_rtc_probe, | 206 | .remove = __exit_p(ep93xx_rtc_remove), |
131 | .remove = __devexit_p(ep93xx_rtc_remove), | ||
132 | }; | 207 | }; |
133 | 208 | ||
134 | static int __init ep93xx_rtc_init(void) | 209 | static int __init ep93xx_rtc_init(void) |
135 | { | 210 | { |
136 | return platform_driver_register(&ep93xx_rtc_platform_driver); | 211 | return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe); |
137 | } | 212 | } |
138 | 213 | ||
139 | static void __exit ep93xx_rtc_exit(void) | 214 | static void __exit ep93xx_rtc_exit(void) |
140 | { | 215 | { |
141 | platform_driver_unregister(&ep93xx_rtc_platform_driver); | 216 | platform_driver_unregister(&ep93xx_rtc_driver); |
142 | } | 217 | } |
143 | 218 | ||
144 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | 219 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); |
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index aaf1f75fa293..457231bb1029 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c | |||
@@ -117,7 +117,7 @@ static int pl030_probe(struct amba_device *dev, struct amba_id *id) | |||
117 | goto err_rtc; | 117 | goto err_rtc; |
118 | } | 118 | } |
119 | 119 | ||
120 | rtc->base = ioremap(dev->res.start, SZ_4K); | 120 | rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); |
121 | if (!rtc->base) { | 121 | if (!rtc->base) { |
122 | ret = -ENOMEM; | 122 | ret = -ENOMEM; |
123 | goto err_map; | 123 | goto err_map; |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 451fc13784d1..f41873f98f66 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -142,8 +142,7 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
142 | goto out; | 142 | goto out; |
143 | } | 143 | } |
144 | 144 | ||
145 | ldata->base = ioremap(adev->res.start, | 145 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); |
146 | adev->res.end - adev->res.start + 1); | ||
147 | if (!ldata->base) { | 146 | if (!ldata->base) { |
148 | ret = -ENOMEM; | 147 | ret = -ENOMEM; |
149 | goto out_no_remap; | 148 | goto out_no_remap; |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index cdc049d4350f..58a4879c7e48 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -686,7 +686,7 @@ static int pl010_probe(struct amba_device *dev, struct amba_id *id) | |||
686 | goto out; | 686 | goto out; |
687 | } | 687 | } |
688 | 688 | ||
689 | base = ioremap(dev->res.start, PAGE_SIZE); | 689 | base = ioremap(dev->res.start, resource_size(&dev->res)); |
690 | if (!base) { | 690 | if (!base) { |
691 | ret = -ENOMEM; | 691 | ret = -ENOMEM; |
692 | goto free; | 692 | goto free; |
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 88fdac51b6c5..bf82e28770a9 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
@@ -70,6 +70,23 @@ struct uart_amba_port { | |||
70 | struct clk *clk; | 70 | struct clk *clk; |
71 | unsigned int im; /* interrupt mask */ | 71 | unsigned int im; /* interrupt mask */ |
72 | unsigned int old_status; | 72 | unsigned int old_status; |
73 | unsigned int ifls; /* vendor-specific */ | ||
74 | }; | ||
75 | |||
76 | /* There is by now at least one vendor with differing details, so handle it */ | ||
77 | struct vendor_data { | ||
78 | unsigned int ifls; | ||
79 | unsigned int fifosize; | ||
80 | }; | ||
81 | |||
82 | static struct vendor_data vendor_arm = { | ||
83 | .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, | ||
84 | .fifosize = 16, | ||
85 | }; | ||
86 | |||
87 | static struct vendor_data vendor_st = { | ||
88 | .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, | ||
89 | .fifosize = 64, | ||
73 | }; | 90 | }; |
74 | 91 | ||
75 | static void pl011_stop_tx(struct uart_port *port) | 92 | static void pl011_stop_tx(struct uart_port *port) |
@@ -360,8 +377,7 @@ static int pl011_startup(struct uart_port *port) | |||
360 | if (retval) | 377 | if (retval) |
361 | goto clk_dis; | 378 | goto clk_dis; |
362 | 379 | ||
363 | writew(UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, | 380 | writew(uap->ifls, uap->port.membase + UART011_IFLS); |
364 | uap->port.membase + UART011_IFLS); | ||
365 | 381 | ||
366 | /* | 382 | /* |
367 | * Provoke TX FIFO interrupt into asserting. | 383 | * Provoke TX FIFO interrupt into asserting. |
@@ -732,6 +748,7 @@ static struct uart_driver amba_reg = { | |||
732 | static int pl011_probe(struct amba_device *dev, struct amba_id *id) | 748 | static int pl011_probe(struct amba_device *dev, struct amba_id *id) |
733 | { | 749 | { |
734 | struct uart_amba_port *uap; | 750 | struct uart_amba_port *uap; |
751 | struct vendor_data *vendor = id->data; | ||
735 | void __iomem *base; | 752 | void __iomem *base; |
736 | int i, ret; | 753 | int i, ret; |
737 | 754 | ||
@@ -750,7 +767,7 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id) | |||
750 | goto out; | 767 | goto out; |
751 | } | 768 | } |
752 | 769 | ||
753 | base = ioremap(dev->res.start, PAGE_SIZE); | 770 | base = ioremap(dev->res.start, resource_size(&dev->res)); |
754 | if (!base) { | 771 | if (!base) { |
755 | ret = -ENOMEM; | 772 | ret = -ENOMEM; |
756 | goto free; | 773 | goto free; |
@@ -762,12 +779,13 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id) | |||
762 | goto unmap; | 779 | goto unmap; |
763 | } | 780 | } |
764 | 781 | ||
782 | uap->ifls = vendor->ifls; | ||
765 | uap->port.dev = &dev->dev; | 783 | uap->port.dev = &dev->dev; |
766 | uap->port.mapbase = dev->res.start; | 784 | uap->port.mapbase = dev->res.start; |
767 | uap->port.membase = base; | 785 | uap->port.membase = base; |
768 | uap->port.iotype = UPIO_MEM; | 786 | uap->port.iotype = UPIO_MEM; |
769 | uap->port.irq = dev->irq[0]; | 787 | uap->port.irq = dev->irq[0]; |
770 | uap->port.fifosize = 16; | 788 | uap->port.fifosize = vendor->fifosize; |
771 | uap->port.ops = &amba_pl011_pops; | 789 | uap->port.ops = &amba_pl011_pops; |
772 | uap->port.flags = UPF_BOOT_AUTOCONF; | 790 | uap->port.flags = UPF_BOOT_AUTOCONF; |
773 | uap->port.line = i; | 791 | uap->port.line = i; |
@@ -812,6 +830,12 @@ static struct amba_id pl011_ids[] __initdata = { | |||
812 | { | 830 | { |
813 | .id = 0x00041011, | 831 | .id = 0x00041011, |
814 | .mask = 0x000fffff, | 832 | .mask = 0x000fffff, |
833 | .data = &vendor_arm, | ||
834 | }, | ||
835 | { | ||
836 | .id = 0x00380802, | ||
837 | .mask = 0x00ffffff, | ||
838 | .data = &vendor_st, | ||
815 | }, | 839 | }, |
816 | { 0, 0 }, | 840 | { 0, 0 }, |
817 | }; | 841 | }; |
@@ -845,7 +869,11 @@ static void __exit pl011_exit(void) | |||
845 | uart_unregister_driver(&amba_reg); | 869 | uart_unregister_driver(&amba_reg); |
846 | } | 870 | } |
847 | 871 | ||
848 | module_init(pl011_init); | 872 | /* |
873 | * While this can be a module, if builtin it's most likely the console | ||
874 | * So let's leave module_exit but move module_init to an earlier place | ||
875 | */ | ||
876 | arch_initcall(pl011_init); | ||
849 | module_exit(pl011_exit); | 877 | module_exit(pl011_exit); |
850 | 878 | ||
851 | MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); | 879 | MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 7b5d1de9cfe3..285b414f3054 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -71,7 +71,7 @@ | |||
71 | #define ONEMS 0xb0 /* One Millisecond register */ | 71 | #define ONEMS 0xb0 /* One Millisecond register */ |
72 | #define UTS 0xb4 /* UART Test Register */ | 72 | #define UTS 0xb4 /* UART Test Register */ |
73 | #endif | 73 | #endif |
74 | #if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1) | 74 | #ifdef CONFIG_ARCH_MX1 |
75 | #define BIPR1 0xb0 /* Incremental Preset Register 1 */ | 75 | #define BIPR1 0xb0 /* Incremental Preset Register 1 */ |
76 | #define BIPR2 0xb4 /* Incremental Preset Register 2 */ | 76 | #define BIPR2 0xb4 /* Incremental Preset Register 2 */ |
77 | #define BIPR3 0xb8 /* Incremental Preset Register 3 */ | 77 | #define BIPR3 0xb8 /* Incremental Preset Register 3 */ |
@@ -101,7 +101,7 @@ | |||
101 | #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ | 101 | #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ |
102 | #define UCR1_SNDBRK (1<<4) /* Send break */ | 102 | #define UCR1_SNDBRK (1<<4) /* Send break */ |
103 | #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ | 103 | #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ |
104 | #if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1) | 104 | #ifdef CONFIG_ARCH_MX1 |
105 | #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ | 105 | #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ |
106 | #endif | 106 | #endif |
107 | #if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 | 107 | #if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 |
@@ -132,7 +132,7 @@ | |||
132 | #define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ | 132 | #define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ |
133 | #define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ | 133 | #define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ |
134 | #define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ | 134 | #define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ |
135 | #ifdef CONFIG_ARCH_IMX | 135 | #ifdef CONFIG_ARCH_MX1 |
136 | #define UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */ | 136 | #define UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */ |
137 | #define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */ | 137 | #define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */ |
138 | #endif | 138 | #endif |
@@ -186,13 +186,6 @@ | |||
186 | #define UTS_SOFTRST (1<<0) /* Software reset */ | 186 | #define UTS_SOFTRST (1<<0) /* Software reset */ |
187 | 187 | ||
188 | /* We've been assigned a range on the "Low-density serial ports" major */ | 188 | /* We've been assigned a range on the "Low-density serial ports" major */ |
189 | #ifdef CONFIG_ARCH_IMX | ||
190 | #define SERIAL_IMX_MAJOR 204 | ||
191 | #define MINOR_START 41 | ||
192 | #define DEV_NAME "ttySMX" | ||
193 | #define MAX_INTERNAL_IRQ IMX_IRQS | ||
194 | #endif | ||
195 | |||
196 | #ifdef CONFIG_ARCH_MXC | 189 | #ifdef CONFIG_ARCH_MXC |
197 | #define SERIAL_IMX_MAJOR 207 | 190 | #define SERIAL_IMX_MAJOR 207 |
198 | #define MINOR_START 16 | 191 | #define MINOR_START 16 |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 957494775413..e8aae227b5e0 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -118,7 +118,7 @@ config SPI_GPIO | |||
118 | 118 | ||
119 | config SPI_IMX | 119 | config SPI_IMX |
120 | tristate "Freescale iMX SPI controller" | 120 | tristate "Freescale iMX SPI controller" |
121 | depends on ARCH_IMX && EXPERIMENTAL | 121 | depends on ARCH_MX1 && EXPERIMENTAL |
122 | help | 122 | help |
123 | This enables using the Freescale iMX SPI controller in master | 123 | This enables using the Freescale iMX SPI controller in master |
124 | mode. | 124 | mode. |
@@ -171,6 +171,15 @@ config SPI_ORION | |||
171 | help | 171 | help |
172 | This enables using the SPI master controller on the Orion chips. | 172 | This enables using the SPI master controller on the Orion chips. |
173 | 173 | ||
174 | config SPI_PL022 | ||
175 | tristate "ARM AMBA PL022 SSP controller (EXPERIMENTAL)" | ||
176 | depends on ARM_AMBA && EXPERIMENTAL | ||
177 | default y if MACH_U300 | ||
178 | help | ||
179 | This selects the ARM(R) AMBA(R) PrimeCell PL022 SSP | ||
180 | controller. If you have an embedded system with an AMBA(R) | ||
181 | bus and a PL022 controller, say Y or M here. | ||
182 | |||
174 | config SPI_PXA2XX | 183 | config SPI_PXA2XX |
175 | tristate "PXA2xx SSP SPI master" | 184 | tristate "PXA2xx SSP SPI master" |
176 | depends on ARCH_PXA && EXPERIMENTAL | 185 | depends on ARCH_PXA && EXPERIMENTAL |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 5d0451936d86..ecfadb180482 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o | |||
23 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o | 23 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o |
24 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o | 24 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o |
25 | obj-$(CONFIG_SPI_ORION) += orion_spi.o | 25 | obj-$(CONFIG_SPI_ORION) += orion_spi.o |
26 | obj-$(CONFIG_SPI_PL022) += amba-pl022.o | ||
26 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o | 27 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o |
27 | obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o | 28 | obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o |
28 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o | 29 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o |
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c new file mode 100644 index 000000000000..da76797ce8b9 --- /dev/null +++ b/drivers/spi/amba-pl022.c | |||
@@ -0,0 +1,1866 @@ | |||
1 | /* | ||
2 | * drivers/spi/amba-pl022.c | ||
3 | * | ||
4 | * A driver for the ARM PL022 PrimeCell SSP/SPI bus master. | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 ST-Ericsson AB | ||
7 | * Copyright (C) 2006 STMicroelectronics Pvt. Ltd. | ||
8 | * | ||
9 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
10 | * | ||
11 | * Initial version inspired by: | ||
12 | * linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c | ||
13 | * Initial adoption to PL022 by: | ||
14 | * Sachin Verma <sachin.verma@st.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * TODO: | ||
29 | * - add timeout on polled transfers | ||
30 | * - add generic DMA framework support | ||
31 | */ | ||
32 | |||
33 | #include <linux/init.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/device.h> | ||
36 | #include <linux/ioport.h> | ||
37 | #include <linux/errno.h> | ||
38 | #include <linux/interrupt.h> | ||
39 | #include <linux/spi/spi.h> | ||
40 | #include <linux/workqueue.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/clk.h> | ||
44 | #include <linux/err.h> | ||
45 | #include <linux/amba/bus.h> | ||
46 | #include <linux/amba/pl022.h> | ||
47 | #include <linux/io.h> | ||
48 | #include <linux/delay.h> | ||
49 | |||
50 | /* | ||
51 | * This macro is used to define some register default values. | ||
52 | * reg is masked with mask, the OR:ed with an (again masked) | ||
53 | * val shifted sb steps to the left. | ||
54 | */ | ||
55 | #define SSP_WRITE_BITS(reg, val, mask, sb) \ | ||
56 | ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask)))) | ||
57 | |||
58 | /* | ||
59 | * This macro is also used to define some default values. | ||
60 | * It will just shift val by sb steps to the left and mask | ||
61 | * the result with mask. | ||
62 | */ | ||
63 | #define GEN_MASK_BITS(val, mask, sb) \ | ||
64 | (((val)<<(sb)) & (mask)) | ||
65 | |||
66 | #define DRIVE_TX 0 | ||
67 | #define DO_NOT_DRIVE_TX 1 | ||
68 | |||
69 | #define DO_NOT_QUEUE_DMA 0 | ||
70 | #define QUEUE_DMA 1 | ||
71 | |||
72 | #define RX_TRANSFER 1 | ||
73 | #define TX_TRANSFER 2 | ||
74 | |||
75 | /* | ||
76 | * Macros to access SSP Registers with their offsets | ||
77 | */ | ||
78 | #define SSP_CR0(r) (r + 0x000) | ||
79 | #define SSP_CR1(r) (r + 0x004) | ||
80 | #define SSP_DR(r) (r + 0x008) | ||
81 | #define SSP_SR(r) (r + 0x00C) | ||
82 | #define SSP_CPSR(r) (r + 0x010) | ||
83 | #define SSP_IMSC(r) (r + 0x014) | ||
84 | #define SSP_RIS(r) (r + 0x018) | ||
85 | #define SSP_MIS(r) (r + 0x01C) | ||
86 | #define SSP_ICR(r) (r + 0x020) | ||
87 | #define SSP_DMACR(r) (r + 0x024) | ||
88 | #define SSP_ITCR(r) (r + 0x080) | ||
89 | #define SSP_ITIP(r) (r + 0x084) | ||
90 | #define SSP_ITOP(r) (r + 0x088) | ||
91 | #define SSP_TDR(r) (r + 0x08C) | ||
92 | |||
93 | #define SSP_PID0(r) (r + 0xFE0) | ||
94 | #define SSP_PID1(r) (r + 0xFE4) | ||
95 | #define SSP_PID2(r) (r + 0xFE8) | ||
96 | #define SSP_PID3(r) (r + 0xFEC) | ||
97 | |||
98 | #define SSP_CID0(r) (r + 0xFF0) | ||
99 | #define SSP_CID1(r) (r + 0xFF4) | ||
100 | #define SSP_CID2(r) (r + 0xFF8) | ||
101 | #define SSP_CID3(r) (r + 0xFFC) | ||
102 | |||
103 | /* | ||
104 | * SSP Control Register 0 - SSP_CR0 | ||
105 | */ | ||
106 | #define SSP_CR0_MASK_DSS (0x1FUL << 0) | ||
107 | #define SSP_CR0_MASK_HALFDUP (0x1UL << 5) | ||
108 | #define SSP_CR0_MASK_SPO (0x1UL << 6) | ||
109 | #define SSP_CR0_MASK_SPH (0x1UL << 7) | ||
110 | #define SSP_CR0_MASK_SCR (0xFFUL << 8) | ||
111 | #define SSP_CR0_MASK_CSS (0x1FUL << 16) | ||
112 | #define SSP_CR0_MASK_FRF (0x3UL << 21) | ||
113 | |||
114 | /* | ||
115 | * SSP Control Register 0 - SSP_CR1 | ||
116 | */ | ||
117 | #define SSP_CR1_MASK_LBM (0x1UL << 0) | ||
118 | #define SSP_CR1_MASK_SSE (0x1UL << 1) | ||
119 | #define SSP_CR1_MASK_MS (0x1UL << 2) | ||
120 | #define SSP_CR1_MASK_SOD (0x1UL << 3) | ||
121 | #define SSP_CR1_MASK_RENDN (0x1UL << 4) | ||
122 | #define SSP_CR1_MASK_TENDN (0x1UL << 5) | ||
123 | #define SSP_CR1_MASK_MWAIT (0x1UL << 6) | ||
124 | #define SSP_CR1_MASK_RXIFLSEL (0x7UL << 7) | ||
125 | #define SSP_CR1_MASK_TXIFLSEL (0x7UL << 10) | ||
126 | |||
127 | /* | ||
128 | * SSP Data Register - SSP_DR | ||
129 | */ | ||
130 | #define SSP_DR_MASK_DATA 0xFFFFFFFF | ||
131 | |||
132 | /* | ||
133 | * SSP Status Register - SSP_SR | ||
134 | */ | ||
135 | #define SSP_SR_MASK_TFE (0x1UL << 0) /* Transmit FIFO empty */ | ||
136 | #define SSP_SR_MASK_TNF (0x1UL << 1) /* Transmit FIFO not full */ | ||
137 | #define SSP_SR_MASK_RNE (0x1UL << 2) /* Receive FIFO not empty */ | ||
138 | #define SSP_SR_MASK_RFF (0x1UL << 3) /* Receive FIFO full */ | ||
139 | #define SSP_SR_MASK_BSY (0x1UL << 4) /* Busy Flag */ | ||
140 | |||
141 | /* | ||
142 | * SSP Clock Prescale Register - SSP_CPSR | ||
143 | */ | ||
144 | #define SSP_CPSR_MASK_CPSDVSR (0xFFUL << 0) | ||
145 | |||
146 | /* | ||
147 | * SSP Interrupt Mask Set/Clear Register - SSP_IMSC | ||
148 | */ | ||
149 | #define SSP_IMSC_MASK_RORIM (0x1UL << 0) /* Receive Overrun Interrupt mask */ | ||
150 | #define SSP_IMSC_MASK_RTIM (0x1UL << 1) /* Receive timeout Interrupt mask */ | ||
151 | #define SSP_IMSC_MASK_RXIM (0x1UL << 2) /* Receive FIFO Interrupt mask */ | ||
152 | #define SSP_IMSC_MASK_TXIM (0x1UL << 3) /* Transmit FIFO Interrupt mask */ | ||
153 | |||
154 | /* | ||
155 | * SSP Raw Interrupt Status Register - SSP_RIS | ||
156 | */ | ||
157 | /* Receive Overrun Raw Interrupt status */ | ||
158 | #define SSP_RIS_MASK_RORRIS (0x1UL << 0) | ||
159 | /* Receive Timeout Raw Interrupt status */ | ||
160 | #define SSP_RIS_MASK_RTRIS (0x1UL << 1) | ||
161 | /* Receive FIFO Raw Interrupt status */ | ||
162 | #define SSP_RIS_MASK_RXRIS (0x1UL << 2) | ||
163 | /* Transmit FIFO Raw Interrupt status */ | ||
164 | #define SSP_RIS_MASK_TXRIS (0x1UL << 3) | ||
165 | |||
166 | /* | ||
167 | * SSP Masked Interrupt Status Register - SSP_MIS | ||
168 | */ | ||
169 | /* Receive Overrun Masked Interrupt status */ | ||
170 | #define SSP_MIS_MASK_RORMIS (0x1UL << 0) | ||
171 | /* Receive Timeout Masked Interrupt status */ | ||
172 | #define SSP_MIS_MASK_RTMIS (0x1UL << 1) | ||
173 | /* Receive FIFO Masked Interrupt status */ | ||
174 | #define SSP_MIS_MASK_RXMIS (0x1UL << 2) | ||
175 | /* Transmit FIFO Masked Interrupt status */ | ||
176 | #define SSP_MIS_MASK_TXMIS (0x1UL << 3) | ||
177 | |||
178 | /* | ||
179 | * SSP Interrupt Clear Register - SSP_ICR | ||
180 | */ | ||
181 | /* Receive Overrun Raw Clear Interrupt bit */ | ||
182 | #define SSP_ICR_MASK_RORIC (0x1UL << 0) | ||
183 | /* Receive Timeout Clear Interrupt bit */ | ||
184 | #define SSP_ICR_MASK_RTIC (0x1UL << 1) | ||
185 | |||
186 | /* | ||
187 | * SSP DMA Control Register - SSP_DMACR | ||
188 | */ | ||
189 | /* Receive DMA Enable bit */ | ||
190 | #define SSP_DMACR_MASK_RXDMAE (0x1UL << 0) | ||
191 | /* Transmit DMA Enable bit */ | ||
192 | #define SSP_DMACR_MASK_TXDMAE (0x1UL << 1) | ||
193 | |||
194 | /* | ||
195 | * SSP Integration Test control Register - SSP_ITCR | ||
196 | */ | ||
197 | #define SSP_ITCR_MASK_ITEN (0x1UL << 0) | ||
198 | #define SSP_ITCR_MASK_TESTFIFO (0x1UL << 1) | ||
199 | |||
200 | /* | ||
201 | * SSP Integration Test Input Register - SSP_ITIP | ||
202 | */ | ||
203 | #define ITIP_MASK_SSPRXD (0x1UL << 0) | ||
204 | #define ITIP_MASK_SSPFSSIN (0x1UL << 1) | ||
205 | #define ITIP_MASK_SSPCLKIN (0x1UL << 2) | ||
206 | #define ITIP_MASK_RXDMAC (0x1UL << 3) | ||
207 | #define ITIP_MASK_TXDMAC (0x1UL << 4) | ||
208 | #define ITIP_MASK_SSPTXDIN (0x1UL << 5) | ||
209 | |||
210 | /* | ||
211 | * SSP Integration Test output Register - SSP_ITOP | ||
212 | */ | ||
213 | #define ITOP_MASK_SSPTXD (0x1UL << 0) | ||
214 | #define ITOP_MASK_SSPFSSOUT (0x1UL << 1) | ||
215 | #define ITOP_MASK_SSPCLKOUT (0x1UL << 2) | ||
216 | #define ITOP_MASK_SSPOEn (0x1UL << 3) | ||
217 | #define ITOP_MASK_SSPCTLOEn (0x1UL << 4) | ||
218 | #define ITOP_MASK_RORINTR (0x1UL << 5) | ||
219 | #define ITOP_MASK_RTINTR (0x1UL << 6) | ||
220 | #define ITOP_MASK_RXINTR (0x1UL << 7) | ||
221 | #define ITOP_MASK_TXINTR (0x1UL << 8) | ||
222 | #define ITOP_MASK_INTR (0x1UL << 9) | ||
223 | #define ITOP_MASK_RXDMABREQ (0x1UL << 10) | ||
224 | #define ITOP_MASK_RXDMASREQ (0x1UL << 11) | ||
225 | #define ITOP_MASK_TXDMABREQ (0x1UL << 12) | ||
226 | #define ITOP_MASK_TXDMASREQ (0x1UL << 13) | ||
227 | |||
228 | /* | ||
229 | * SSP Test Data Register - SSP_TDR | ||
230 | */ | ||
231 | #define TDR_MASK_TESTDATA (0xFFFFFFFF) | ||
232 | |||
233 | /* | ||
234 | * Message State | ||
235 | * we use the spi_message.state (void *) pointer to | ||
236 | * hold a single state value, that's why all this | ||
237 | * (void *) casting is done here. | ||
238 | */ | ||
239 | #define STATE_START ((void *) 0) | ||
240 | #define STATE_RUNNING ((void *) 1) | ||
241 | #define STATE_DONE ((void *) 2) | ||
242 | #define STATE_ERROR ((void *) -1) | ||
243 | |||
244 | /* | ||
245 | * Queue State | ||
246 | */ | ||
247 | #define QUEUE_RUNNING (0) | ||
248 | #define QUEUE_STOPPED (1) | ||
249 | /* | ||
250 | * SSP State - Whether Enabled or Disabled | ||
251 | */ | ||
252 | #define SSP_DISABLED (0) | ||
253 | #define SSP_ENABLED (1) | ||
254 | |||
255 | /* | ||
256 | * SSP DMA State - Whether DMA Enabled or Disabled | ||
257 | */ | ||
258 | #define SSP_DMA_DISABLED (0) | ||
259 | #define SSP_DMA_ENABLED (1) | ||
260 | |||
261 | /* | ||
262 | * SSP Clock Defaults | ||
263 | */ | ||
264 | #define NMDK_SSP_DEFAULT_CLKRATE 0x2 | ||
265 | #define NMDK_SSP_DEFAULT_PRESCALE 0x40 | ||
266 | |||
267 | /* | ||
268 | * SSP Clock Parameter ranges | ||
269 | */ | ||
270 | #define CPSDVR_MIN 0x02 | ||
271 | #define CPSDVR_MAX 0xFE | ||
272 | #define SCR_MIN 0x00 | ||
273 | #define SCR_MAX 0xFF | ||
274 | |||
275 | /* | ||
276 | * SSP Interrupt related Macros | ||
277 | */ | ||
278 | #define DEFAULT_SSP_REG_IMSC 0x0UL | ||
279 | #define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC | ||
280 | #define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC) | ||
281 | |||
282 | #define CLEAR_ALL_INTERRUPTS 0x3 | ||
283 | |||
284 | |||
285 | /* | ||
286 | * The type of reading going on on this chip | ||
287 | */ | ||
288 | enum ssp_reading { | ||
289 | READING_NULL, | ||
290 | READING_U8, | ||
291 | READING_U16, | ||
292 | READING_U32 | ||
293 | }; | ||
294 | |||
295 | /** | ||
296 | * The type of writing going on on this chip | ||
297 | */ | ||
298 | enum ssp_writing { | ||
299 | WRITING_NULL, | ||
300 | WRITING_U8, | ||
301 | WRITING_U16, | ||
302 | WRITING_U32 | ||
303 | }; | ||
304 | |||
305 | /** | ||
306 | * struct vendor_data - vendor-specific config parameters | ||
307 | * for PL022 derivates | ||
308 | * @fifodepth: depth of FIFOs (both) | ||
309 | * @max_bpw: maximum number of bits per word | ||
310 | * @unidir: supports unidirection transfers | ||
311 | */ | ||
312 | struct vendor_data { | ||
313 | int fifodepth; | ||
314 | int max_bpw; | ||
315 | bool unidir; | ||
316 | }; | ||
317 | |||
318 | /** | ||
319 | * struct pl022 - This is the private SSP driver data structure | ||
320 | * @adev: AMBA device model hookup | ||
321 | * @phybase: The physical memory where the SSP device resides | ||
322 | * @virtbase: The virtual memory where the SSP is mapped | ||
323 | * @master: SPI framework hookup | ||
324 | * @master_info: controller-specific data from machine setup | ||
325 | * @regs: SSP controller register's virtual address | ||
326 | * @pump_messages: Work struct for scheduling work to the workqueue | ||
327 | * @lock: spinlock to syncronise access to driver data | ||
328 | * @workqueue: a workqueue on which any spi_message request is queued | ||
329 | * @busy: workqueue is busy | ||
330 | * @run: workqueue is running | ||
331 | * @pump_transfers: Tasklet used in Interrupt Transfer mode | ||
332 | * @cur_msg: Pointer to current spi_message being processed | ||
333 | * @cur_transfer: Pointer to current spi_transfer | ||
334 | * @cur_chip: pointer to current clients chip(assigned from controller_state) | ||
335 | * @tx: current position in TX buffer to be read | ||
336 | * @tx_end: end position in TX buffer to be read | ||
337 | * @rx: current position in RX buffer to be written | ||
338 | * @rx_end: end position in RX buffer to be written | ||
339 | * @readingtype: the type of read currently going on | ||
340 | * @writingtype: the type or write currently going on | ||
341 | */ | ||
342 | struct pl022 { | ||
343 | struct amba_device *adev; | ||
344 | struct vendor_data *vendor; | ||
345 | resource_size_t phybase; | ||
346 | void __iomem *virtbase; | ||
347 | struct clk *clk; | ||
348 | struct spi_master *master; | ||
349 | struct pl022_ssp_controller *master_info; | ||
350 | /* Driver message queue */ | ||
351 | struct workqueue_struct *workqueue; | ||
352 | struct work_struct pump_messages; | ||
353 | spinlock_t queue_lock; | ||
354 | struct list_head queue; | ||
355 | int busy; | ||
356 | int run; | ||
357 | /* Message transfer pump */ | ||
358 | struct tasklet_struct pump_transfers; | ||
359 | struct spi_message *cur_msg; | ||
360 | struct spi_transfer *cur_transfer; | ||
361 | struct chip_data *cur_chip; | ||
362 | void *tx; | ||
363 | void *tx_end; | ||
364 | void *rx; | ||
365 | void *rx_end; | ||
366 | enum ssp_reading read; | ||
367 | enum ssp_writing write; | ||
368 | }; | ||
369 | |||
370 | /** | ||
371 | * struct chip_data - To maintain runtime state of SSP for each client chip | ||
372 | * @cr0: Value of control register CR0 of SSP | ||
373 | * @cr1: Value of control register CR1 of SSP | ||
374 | * @dmacr: Value of DMA control Register of SSP | ||
375 | * @cpsr: Value of Clock prescale register | ||
376 | * @n_bytes: how many bytes(power of 2) reqd for a given data width of client | ||
377 | * @enable_dma: Whether to enable DMA or not | ||
378 | * @write: function ptr to be used to write when doing xfer for this chip | ||
379 | * @read: function ptr to be used to read when doing xfer for this chip | ||
380 | * @cs_control: chip select callback provided by chip | ||
381 | * @xfer_type: polling/interrupt/DMA | ||
382 | * | ||
383 | * Runtime state of the SSP controller, maintained per chip, | ||
384 | * This would be set according to the current message that would be served | ||
385 | */ | ||
386 | struct chip_data { | ||
387 | u16 cr0; | ||
388 | u16 cr1; | ||
389 | u16 dmacr; | ||
390 | u16 cpsr; | ||
391 | u8 n_bytes; | ||
392 | u8 enable_dma:1; | ||
393 | enum ssp_reading read; | ||
394 | enum ssp_writing write; | ||
395 | void (*cs_control) (u32 command); | ||
396 | int xfer_type; | ||
397 | }; | ||
398 | |||
399 | /** | ||
400 | * null_cs_control - Dummy chip select function | ||
401 | * @command: select/delect the chip | ||
402 | * | ||
403 | * If no chip select function is provided by client this is used as dummy | ||
404 | * chip select | ||
405 | */ | ||
406 | static void null_cs_control(u32 command) | ||
407 | { | ||
408 | pr_debug("pl022: dummy chip select control, CS=0x%x\n", command); | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * giveback - current spi_message is over, schedule next message and call | ||
413 | * callback of this message. Assumes that caller already | ||
414 | * set message->status; dma and pio irqs are blocked | ||
415 | * @pl022: SSP driver private data structure | ||
416 | */ | ||
417 | static void giveback(struct pl022 *pl022) | ||
418 | { | ||
419 | struct spi_transfer *last_transfer; | ||
420 | unsigned long flags; | ||
421 | struct spi_message *msg; | ||
422 | void (*curr_cs_control) (u32 command); | ||
423 | |||
424 | /* | ||
425 | * This local reference to the chip select function | ||
426 | * is needed because we set curr_chip to NULL | ||
427 | * as a step toward termininating the message. | ||
428 | */ | ||
429 | curr_cs_control = pl022->cur_chip->cs_control; | ||
430 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
431 | msg = pl022->cur_msg; | ||
432 | pl022->cur_msg = NULL; | ||
433 | pl022->cur_transfer = NULL; | ||
434 | pl022->cur_chip = NULL; | ||
435 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
436 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
437 | |||
438 | last_transfer = list_entry(msg->transfers.prev, | ||
439 | struct spi_transfer, | ||
440 | transfer_list); | ||
441 | |||
442 | /* Delay if requested before any change in chip select */ | ||
443 | if (last_transfer->delay_usecs) | ||
444 | /* | ||
445 | * FIXME: This runs in interrupt context. | ||
446 | * Is this really smart? | ||
447 | */ | ||
448 | udelay(last_transfer->delay_usecs); | ||
449 | |||
450 | /* | ||
451 | * Drop chip select UNLESS cs_change is true or we are returning | ||
452 | * a message with an error, or next message is for another chip | ||
453 | */ | ||
454 | if (!last_transfer->cs_change) | ||
455 | curr_cs_control(SSP_CHIP_DESELECT); | ||
456 | else { | ||
457 | struct spi_message *next_msg; | ||
458 | |||
459 | /* Holding of cs was hinted, but we need to make sure | ||
460 | * the next message is for the same chip. Don't waste | ||
461 | * time with the following tests unless this was hinted. | ||
462 | * | ||
463 | * We cannot postpone this until pump_messages, because | ||
464 | * after calling msg->complete (below) the driver that | ||
465 | * sent the current message could be unloaded, which | ||
466 | * could invalidate the cs_control() callback... | ||
467 | */ | ||
468 | |||
469 | /* get a pointer to the next message, if any */ | ||
470 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
471 | if (list_empty(&pl022->queue)) | ||
472 | next_msg = NULL; | ||
473 | else | ||
474 | next_msg = list_entry(pl022->queue.next, | ||
475 | struct spi_message, queue); | ||
476 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
477 | |||
478 | /* see if the next and current messages point | ||
479 | * to the same chip | ||
480 | */ | ||
481 | if (next_msg && next_msg->spi != msg->spi) | ||
482 | next_msg = NULL; | ||
483 | if (!next_msg || msg->state == STATE_ERROR) | ||
484 | curr_cs_control(SSP_CHIP_DESELECT); | ||
485 | } | ||
486 | msg->state = NULL; | ||
487 | if (msg->complete) | ||
488 | msg->complete(msg->context); | ||
489 | /* This message is completed, so let's turn off the clock! */ | ||
490 | clk_disable(pl022->clk); | ||
491 | } | ||
492 | |||
493 | /** | ||
494 | * flush - flush the FIFO to reach a clean state | ||
495 | * @pl022: SSP driver private data structure | ||
496 | */ | ||
497 | static int flush(struct pl022 *pl022) | ||
498 | { | ||
499 | unsigned long limit = loops_per_jiffy << 1; | ||
500 | |||
501 | dev_dbg(&pl022->adev->dev, "flush\n"); | ||
502 | do { | ||
503 | while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) | ||
504 | readw(SSP_DR(pl022->virtbase)); | ||
505 | } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); | ||
506 | return limit; | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * restore_state - Load configuration of current chip | ||
511 | * @pl022: SSP driver private data structure | ||
512 | */ | ||
513 | static void restore_state(struct pl022 *pl022) | ||
514 | { | ||
515 | struct chip_data *chip = pl022->cur_chip; | ||
516 | |||
517 | writew(chip->cr0, SSP_CR0(pl022->virtbase)); | ||
518 | writew(chip->cr1, SSP_CR1(pl022->virtbase)); | ||
519 | writew(chip->dmacr, SSP_DMACR(pl022->virtbase)); | ||
520 | writew(chip->cpsr, SSP_CPSR(pl022->virtbase)); | ||
521 | writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
522 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
523 | } | ||
524 | |||
525 | /** | ||
526 | * load_ssp_default_config - Load default configuration for SSP | ||
527 | * @pl022: SSP driver private data structure | ||
528 | */ | ||
529 | |||
530 | /* | ||
531 | * Default SSP Register Values | ||
532 | */ | ||
533 | #define DEFAULT_SSP_REG_CR0 ( \ | ||
534 | GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS, 0) | \ | ||
535 | GEN_MASK_BITS(SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, SSP_CR0_MASK_HALFDUP, 5) | \ | ||
536 | GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \ | ||
537 | GEN_MASK_BITS(SSP_CLK_FALLING_EDGE, SSP_CR0_MASK_SPH, 7) | \ | ||
538 | GEN_MASK_BITS(NMDK_SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) | \ | ||
539 | GEN_MASK_BITS(SSP_BITS_8, SSP_CR0_MASK_CSS, 16) | \ | ||
540 | GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF, 21) \ | ||
541 | ) | ||
542 | |||
543 | #define DEFAULT_SSP_REG_CR1 ( \ | ||
544 | GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \ | ||
545 | GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \ | ||
546 | GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \ | ||
547 | GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \ | ||
548 | GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN, 4) | \ | ||
549 | GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN, 5) | \ | ||
550 | GEN_MASK_BITS(SSP_MWIRE_WAIT_ZERO, SSP_CR1_MASK_MWAIT, 6) |\ | ||
551 | GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL, 7) | \ | ||
552 | GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL, 10) \ | ||
553 | ) | ||
554 | |||
555 | #define DEFAULT_SSP_REG_CPSR ( \ | ||
556 | GEN_MASK_BITS(NMDK_SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \ | ||
557 | ) | ||
558 | |||
559 | #define DEFAULT_SSP_REG_DMACR (\ | ||
560 | GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_RXDMAE, 0) | \ | ||
561 | GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \ | ||
562 | ) | ||
563 | |||
564 | |||
565 | static void load_ssp_default_config(struct pl022 *pl022) | ||
566 | { | ||
567 | writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase)); | ||
568 | writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase)); | ||
569 | writew(DEFAULT_SSP_REG_DMACR, SSP_DMACR(pl022->virtbase)); | ||
570 | writew(DEFAULT_SSP_REG_CPSR, SSP_CPSR(pl022->virtbase)); | ||
571 | writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
572 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
573 | } | ||
574 | |||
575 | /** | ||
576 | * This will write to TX and read from RX according to the parameters | ||
577 | * set in pl022. | ||
578 | */ | ||
579 | static void readwriter(struct pl022 *pl022) | ||
580 | { | ||
581 | |||
582 | /* | ||
583 | * The FIFO depth is different inbetween primecell variants. | ||
584 | * I believe filling in too much in the FIFO might cause | ||
585 | * errons in 8bit wide transfers on ARM variants (just 8 words | ||
586 | * FIFO, means only 8x8 = 64 bits in FIFO) at least. | ||
587 | * | ||
588 | * FIXME: currently we have no logic to account for this. | ||
589 | * perhaps there is even something broken in HW regarding | ||
590 | * 8bit transfers (it doesn't fail on 16bit) so this needs | ||
591 | * more investigation... | ||
592 | */ | ||
593 | dev_dbg(&pl022->adev->dev, | ||
594 | "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", | ||
595 | __func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end); | ||
596 | |||
597 | /* Read as much as you can */ | ||
598 | while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) | ||
599 | && (pl022->rx < pl022->rx_end)) { | ||
600 | switch (pl022->read) { | ||
601 | case READING_NULL: | ||
602 | readw(SSP_DR(pl022->virtbase)); | ||
603 | break; | ||
604 | case READING_U8: | ||
605 | *(u8 *) (pl022->rx) = | ||
606 | readw(SSP_DR(pl022->virtbase)) & 0xFFU; | ||
607 | break; | ||
608 | case READING_U16: | ||
609 | *(u16 *) (pl022->rx) = | ||
610 | (u16) readw(SSP_DR(pl022->virtbase)); | ||
611 | break; | ||
612 | case READING_U32: | ||
613 | *(u32 *) (pl022->rx) = | ||
614 | readl(SSP_DR(pl022->virtbase)); | ||
615 | break; | ||
616 | } | ||
617 | pl022->rx += (pl022->cur_chip->n_bytes); | ||
618 | } | ||
619 | /* | ||
620 | * Write as much as you can, while keeping an eye on the RX FIFO! | ||
621 | */ | ||
622 | while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) | ||
623 | && (pl022->tx < pl022->tx_end)) { | ||
624 | switch (pl022->write) { | ||
625 | case WRITING_NULL: | ||
626 | writew(0x0, SSP_DR(pl022->virtbase)); | ||
627 | break; | ||
628 | case WRITING_U8: | ||
629 | writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase)); | ||
630 | break; | ||
631 | case WRITING_U16: | ||
632 | writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase)); | ||
633 | break; | ||
634 | case WRITING_U32: | ||
635 | writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase)); | ||
636 | break; | ||
637 | } | ||
638 | pl022->tx += (pl022->cur_chip->n_bytes); | ||
639 | /* | ||
640 | * This inner reader takes care of things appearing in the RX | ||
641 | * FIFO as we're transmitting. This will happen a lot since the | ||
642 | * clock starts running when you put things into the TX FIFO, | ||
643 | * and then things are continously clocked into the RX FIFO. | ||
644 | */ | ||
645 | while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) | ||
646 | && (pl022->rx < pl022->rx_end)) { | ||
647 | switch (pl022->read) { | ||
648 | case READING_NULL: | ||
649 | readw(SSP_DR(pl022->virtbase)); | ||
650 | break; | ||
651 | case READING_U8: | ||
652 | *(u8 *) (pl022->rx) = | ||
653 | readw(SSP_DR(pl022->virtbase)) & 0xFFU; | ||
654 | break; | ||
655 | case READING_U16: | ||
656 | *(u16 *) (pl022->rx) = | ||
657 | (u16) readw(SSP_DR(pl022->virtbase)); | ||
658 | break; | ||
659 | case READING_U32: | ||
660 | *(u32 *) (pl022->rx) = | ||
661 | readl(SSP_DR(pl022->virtbase)); | ||
662 | break; | ||
663 | } | ||
664 | pl022->rx += (pl022->cur_chip->n_bytes); | ||
665 | } | ||
666 | } | ||
667 | /* | ||
668 | * When we exit here the TX FIFO should be full and the RX FIFO | ||
669 | * should be empty | ||
670 | */ | ||
671 | } | ||
672 | |||
673 | |||
674 | /** | ||
675 | * next_transfer - Move to the Next transfer in the current spi message | ||
676 | * @pl022: SSP driver private data structure | ||
677 | * | ||
678 | * This function moves though the linked list of spi transfers in the | ||
679 | * current spi message and returns with the state of current spi | ||
680 | * message i.e whether its last transfer is done(STATE_DONE) or | ||
681 | * Next transfer is ready(STATE_RUNNING) | ||
682 | */ | ||
683 | static void *next_transfer(struct pl022 *pl022) | ||
684 | { | ||
685 | struct spi_message *msg = pl022->cur_msg; | ||
686 | struct spi_transfer *trans = pl022->cur_transfer; | ||
687 | |||
688 | /* Move to next transfer */ | ||
689 | if (trans->transfer_list.next != &msg->transfers) { | ||
690 | pl022->cur_transfer = | ||
691 | list_entry(trans->transfer_list.next, | ||
692 | struct spi_transfer, transfer_list); | ||
693 | return STATE_RUNNING; | ||
694 | } | ||
695 | return STATE_DONE; | ||
696 | } | ||
697 | /** | ||
698 | * pl022_interrupt_handler - Interrupt handler for SSP controller | ||
699 | * | ||
700 | * This function handles interrupts generated for an interrupt based transfer. | ||
701 | * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the | ||
702 | * current message's state as STATE_ERROR and schedule the tasklet | ||
703 | * pump_transfers which will do the postprocessing of the current message by | ||
704 | * calling giveback(). Otherwise it reads data from RX FIFO till there is no | ||
705 | * more data, and writes data in TX FIFO till it is not full. If we complete | ||
706 | * the transfer we move to the next transfer and schedule the tasklet. | ||
707 | */ | ||
708 | static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) | ||
709 | { | ||
710 | struct pl022 *pl022 = dev_id; | ||
711 | struct spi_message *msg = pl022->cur_msg; | ||
712 | u16 irq_status = 0; | ||
713 | u16 flag = 0; | ||
714 | |||
715 | if (unlikely(!msg)) { | ||
716 | dev_err(&pl022->adev->dev, | ||
717 | "bad message state in interrupt handler"); | ||
718 | /* Never fail */ | ||
719 | return IRQ_HANDLED; | ||
720 | } | ||
721 | |||
722 | /* Read the Interrupt Status Register */ | ||
723 | irq_status = readw(SSP_MIS(pl022->virtbase)); | ||
724 | |||
725 | if (unlikely(!irq_status)) | ||
726 | return IRQ_NONE; | ||
727 | |||
728 | /* This handles the error code interrupts */ | ||
729 | if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) { | ||
730 | /* | ||
731 | * Overrun interrupt - bail out since our Data has been | ||
732 | * corrupted | ||
733 | */ | ||
734 | dev_err(&pl022->adev->dev, | ||
735 | "FIFO overrun\n"); | ||
736 | if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF) | ||
737 | dev_err(&pl022->adev->dev, | ||
738 | "RXFIFO is full\n"); | ||
739 | if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) | ||
740 | dev_err(&pl022->adev->dev, | ||
741 | "TXFIFO is full\n"); | ||
742 | |||
743 | /* | ||
744 | * Disable and clear interrupts, disable SSP, | ||
745 | * mark message with bad status so it can be | ||
746 | * retried. | ||
747 | */ | ||
748 | writew(DISABLE_ALL_INTERRUPTS, | ||
749 | SSP_IMSC(pl022->virtbase)); | ||
750 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
751 | writew((readw(SSP_CR1(pl022->virtbase)) & | ||
752 | (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); | ||
753 | msg->state = STATE_ERROR; | ||
754 | |||
755 | /* Schedule message queue handler */ | ||
756 | tasklet_schedule(&pl022->pump_transfers); | ||
757 | return IRQ_HANDLED; | ||
758 | } | ||
759 | |||
760 | readwriter(pl022); | ||
761 | |||
762 | if ((pl022->tx == pl022->tx_end) && (flag == 0)) { | ||
763 | flag = 1; | ||
764 | /* Disable Transmit interrupt */ | ||
765 | writew(readw(SSP_IMSC(pl022->virtbase)) & | ||
766 | (~SSP_IMSC_MASK_TXIM), | ||
767 | SSP_IMSC(pl022->virtbase)); | ||
768 | } | ||
769 | |||
770 | /* | ||
771 | * Since all transactions must write as much as shall be read, | ||
772 | * we can conclude the entire transaction once RX is complete. | ||
773 | * At this point, all TX will always be finished. | ||
774 | */ | ||
775 | if (pl022->rx >= pl022->rx_end) { | ||
776 | writew(DISABLE_ALL_INTERRUPTS, | ||
777 | SSP_IMSC(pl022->virtbase)); | ||
778 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
779 | if (unlikely(pl022->rx > pl022->rx_end)) { | ||
780 | dev_warn(&pl022->adev->dev, "read %u surplus " | ||
781 | "bytes (did you request an odd " | ||
782 | "number of bytes on a 16bit bus?)\n", | ||
783 | (u32) (pl022->rx - pl022->rx_end)); | ||
784 | } | ||
785 | /* Update total bytes transfered */ | ||
786 | msg->actual_length += pl022->cur_transfer->len; | ||
787 | if (pl022->cur_transfer->cs_change) | ||
788 | pl022->cur_chip-> | ||
789 | cs_control(SSP_CHIP_DESELECT); | ||
790 | /* Move to next transfer */ | ||
791 | msg->state = next_transfer(pl022); | ||
792 | tasklet_schedule(&pl022->pump_transfers); | ||
793 | return IRQ_HANDLED; | ||
794 | } | ||
795 | |||
796 | return IRQ_HANDLED; | ||
797 | } | ||
798 | |||
799 | /** | ||
800 | * This sets up the pointers to memory for the next message to | ||
801 | * send out on the SPI bus. | ||
802 | */ | ||
803 | static int set_up_next_transfer(struct pl022 *pl022, | ||
804 | struct spi_transfer *transfer) | ||
805 | { | ||
806 | int residue; | ||
807 | |||
808 | /* Sanity check the message for this bus width */ | ||
809 | residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes; | ||
810 | if (unlikely(residue != 0)) { | ||
811 | dev_err(&pl022->adev->dev, | ||
812 | "message of %u bytes to transmit but the current " | ||
813 | "chip bus has a data width of %u bytes!\n", | ||
814 | pl022->cur_transfer->len, | ||
815 | pl022->cur_chip->n_bytes); | ||
816 | dev_err(&pl022->adev->dev, "skipping this message\n"); | ||
817 | return -EIO; | ||
818 | } | ||
819 | pl022->tx = (void *)transfer->tx_buf; | ||
820 | pl022->tx_end = pl022->tx + pl022->cur_transfer->len; | ||
821 | pl022->rx = (void *)transfer->rx_buf; | ||
822 | pl022->rx_end = pl022->rx + pl022->cur_transfer->len; | ||
823 | pl022->write = | ||
824 | pl022->tx ? pl022->cur_chip->write : WRITING_NULL; | ||
825 | pl022->read = pl022->rx ? pl022->cur_chip->read : READING_NULL; | ||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * pump_transfers - Tasklet function which schedules next interrupt transfer | ||
831 | * when running in interrupt transfer mode. | ||
832 | * @data: SSP driver private data structure | ||
833 | * | ||
834 | */ | ||
835 | static void pump_transfers(unsigned long data) | ||
836 | { | ||
837 | struct pl022 *pl022 = (struct pl022 *) data; | ||
838 | struct spi_message *message = NULL; | ||
839 | struct spi_transfer *transfer = NULL; | ||
840 | struct spi_transfer *previous = NULL; | ||
841 | |||
842 | /* Get current state information */ | ||
843 | message = pl022->cur_msg; | ||
844 | transfer = pl022->cur_transfer; | ||
845 | |||
846 | /* Handle for abort */ | ||
847 | if (message->state == STATE_ERROR) { | ||
848 | message->status = -EIO; | ||
849 | giveback(pl022); | ||
850 | return; | ||
851 | } | ||
852 | |||
853 | /* Handle end of message */ | ||
854 | if (message->state == STATE_DONE) { | ||
855 | message->status = 0; | ||
856 | giveback(pl022); | ||
857 | return; | ||
858 | } | ||
859 | |||
860 | /* Delay if requested at end of transfer before CS change */ | ||
861 | if (message->state == STATE_RUNNING) { | ||
862 | previous = list_entry(transfer->transfer_list.prev, | ||
863 | struct spi_transfer, | ||
864 | transfer_list); | ||
865 | if (previous->delay_usecs) | ||
866 | /* | ||
867 | * FIXME: This runs in interrupt context. | ||
868 | * Is this really smart? | ||
869 | */ | ||
870 | udelay(previous->delay_usecs); | ||
871 | |||
872 | /* Drop chip select only if cs_change is requested */ | ||
873 | if (previous->cs_change) | ||
874 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
875 | } else { | ||
876 | /* STATE_START */ | ||
877 | message->state = STATE_RUNNING; | ||
878 | } | ||
879 | |||
880 | if (set_up_next_transfer(pl022, transfer)) { | ||
881 | message->state = STATE_ERROR; | ||
882 | message->status = -EIO; | ||
883 | giveback(pl022); | ||
884 | return; | ||
885 | } | ||
886 | /* Flush the FIFOs and let's go! */ | ||
887 | flush(pl022); | ||
888 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
889 | } | ||
890 | |||
891 | /** | ||
892 | * NOT IMPLEMENTED | ||
893 | * configure_dma - It configures the DMA pipes for DMA transfers | ||
894 | * @data: SSP driver's private data structure | ||
895 | * | ||
896 | */ | ||
897 | static int configure_dma(void *data) | ||
898 | { | ||
899 | struct pl022 *pl022 = data; | ||
900 | dev_dbg(&pl022->adev->dev, "configure DMA\n"); | ||
901 | return -ENOTSUPP; | ||
902 | } | ||
903 | |||
904 | /** | ||
905 | * do_dma_transfer - It handles transfers of the current message | ||
906 | * if it is DMA xfer. | ||
907 | * NOT FULLY IMPLEMENTED | ||
908 | * @data: SSP driver's private data structure | ||
909 | */ | ||
910 | static void do_dma_transfer(void *data) | ||
911 | { | ||
912 | struct pl022 *pl022 = data; | ||
913 | |||
914 | if (configure_dma(data)) { | ||
915 | dev_dbg(&pl022->adev->dev, "configuration of DMA Failed!\n"); | ||
916 | goto err_config_dma; | ||
917 | } | ||
918 | |||
919 | /* TODO: Implememt DMA setup of pipes here */ | ||
920 | |||
921 | /* Enable target chip, set up transfer */ | ||
922 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
923 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { | ||
924 | /* Error path */ | ||
925 | pl022->cur_msg->state = STATE_ERROR; | ||
926 | pl022->cur_msg->status = -EIO; | ||
927 | giveback(pl022); | ||
928 | return; | ||
929 | } | ||
930 | /* Enable SSP */ | ||
931 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | ||
932 | SSP_CR1(pl022->virtbase)); | ||
933 | |||
934 | /* TODO: Enable the DMA transfer here */ | ||
935 | return; | ||
936 | |||
937 | err_config_dma: | ||
938 | pl022->cur_msg->state = STATE_ERROR; | ||
939 | pl022->cur_msg->status = -EIO; | ||
940 | giveback(pl022); | ||
941 | return; | ||
942 | } | ||
943 | |||
944 | static void do_interrupt_transfer(void *data) | ||
945 | { | ||
946 | struct pl022 *pl022 = data; | ||
947 | |||
948 | /* Enable target chip */ | ||
949 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
950 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { | ||
951 | /* Error path */ | ||
952 | pl022->cur_msg->state = STATE_ERROR; | ||
953 | pl022->cur_msg->status = -EIO; | ||
954 | giveback(pl022); | ||
955 | return; | ||
956 | } | ||
957 | /* Enable SSP, turn on interrupts */ | ||
958 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | ||
959 | SSP_CR1(pl022->virtbase)); | ||
960 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
961 | } | ||
962 | |||
963 | static void do_polling_transfer(void *data) | ||
964 | { | ||
965 | struct pl022 *pl022 = data; | ||
966 | struct spi_message *message = NULL; | ||
967 | struct spi_transfer *transfer = NULL; | ||
968 | struct spi_transfer *previous = NULL; | ||
969 | struct chip_data *chip; | ||
970 | |||
971 | chip = pl022->cur_chip; | ||
972 | message = pl022->cur_msg; | ||
973 | |||
974 | while (message->state != STATE_DONE) { | ||
975 | /* Handle for abort */ | ||
976 | if (message->state == STATE_ERROR) | ||
977 | break; | ||
978 | transfer = pl022->cur_transfer; | ||
979 | |||
980 | /* Delay if requested at end of transfer */ | ||
981 | if (message->state == STATE_RUNNING) { | ||
982 | previous = | ||
983 | list_entry(transfer->transfer_list.prev, | ||
984 | struct spi_transfer, transfer_list); | ||
985 | if (previous->delay_usecs) | ||
986 | udelay(previous->delay_usecs); | ||
987 | if (previous->cs_change) | ||
988 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
989 | } else { | ||
990 | /* STATE_START */ | ||
991 | message->state = STATE_RUNNING; | ||
992 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
993 | } | ||
994 | |||
995 | /* Configuration Changing Per Transfer */ | ||
996 | if (set_up_next_transfer(pl022, transfer)) { | ||
997 | /* Error path */ | ||
998 | message->state = STATE_ERROR; | ||
999 | break; | ||
1000 | } | ||
1001 | /* Flush FIFOs and enable SSP */ | ||
1002 | flush(pl022); | ||
1003 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | ||
1004 | SSP_CR1(pl022->virtbase)); | ||
1005 | |||
1006 | dev_dbg(&pl022->adev->dev, "POLLING TRANSFER ONGOING ... \n"); | ||
1007 | /* FIXME: insert a timeout so we don't hang here indefinately */ | ||
1008 | while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) | ||
1009 | readwriter(pl022); | ||
1010 | |||
1011 | /* Update total byte transfered */ | ||
1012 | message->actual_length += pl022->cur_transfer->len; | ||
1013 | if (pl022->cur_transfer->cs_change) | ||
1014 | pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); | ||
1015 | /* Move to next transfer */ | ||
1016 | message->state = next_transfer(pl022); | ||
1017 | } | ||
1018 | |||
1019 | /* Handle end of message */ | ||
1020 | if (message->state == STATE_DONE) | ||
1021 | message->status = 0; | ||
1022 | else | ||
1023 | message->status = -EIO; | ||
1024 | |||
1025 | giveback(pl022); | ||
1026 | return; | ||
1027 | } | ||
1028 | |||
1029 | /** | ||
1030 | * pump_messages - Workqueue function which processes spi message queue | ||
1031 | * @data: pointer to private data of SSP driver | ||
1032 | * | ||
1033 | * This function checks if there is any spi message in the queue that | ||
1034 | * needs processing and delegate control to appropriate function | ||
1035 | * do_polling_transfer()/do_interrupt_transfer()/do_dma_transfer() | ||
1036 | * based on the kind of the transfer | ||
1037 | * | ||
1038 | */ | ||
1039 | static void pump_messages(struct work_struct *work) | ||
1040 | { | ||
1041 | struct pl022 *pl022 = | ||
1042 | container_of(work, struct pl022, pump_messages); | ||
1043 | unsigned long flags; | ||
1044 | |||
1045 | /* Lock queue and check for queue work */ | ||
1046 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
1047 | if (list_empty(&pl022->queue) || pl022->run == QUEUE_STOPPED) { | ||
1048 | pl022->busy = 0; | ||
1049 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1050 | return; | ||
1051 | } | ||
1052 | /* Make sure we are not already running a message */ | ||
1053 | if (pl022->cur_msg) { | ||
1054 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1055 | return; | ||
1056 | } | ||
1057 | /* Extract head of queue */ | ||
1058 | pl022->cur_msg = | ||
1059 | list_entry(pl022->queue.next, struct spi_message, queue); | ||
1060 | |||
1061 | list_del_init(&pl022->cur_msg->queue); | ||
1062 | pl022->busy = 1; | ||
1063 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1064 | |||
1065 | /* Initial message state */ | ||
1066 | pl022->cur_msg->state = STATE_START; | ||
1067 | pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next, | ||
1068 | struct spi_transfer, | ||
1069 | transfer_list); | ||
1070 | |||
1071 | /* Setup the SPI using the per chip configuration */ | ||
1072 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | ||
1073 | /* | ||
1074 | * We enable the clock here, then the clock will be disabled when | ||
1075 | * giveback() is called in each method (poll/interrupt/DMA) | ||
1076 | */ | ||
1077 | clk_enable(pl022->clk); | ||
1078 | restore_state(pl022); | ||
1079 | flush(pl022); | ||
1080 | |||
1081 | if (pl022->cur_chip->xfer_type == POLLING_TRANSFER) | ||
1082 | do_polling_transfer(pl022); | ||
1083 | else if (pl022->cur_chip->xfer_type == INTERRUPT_TRANSFER) | ||
1084 | do_interrupt_transfer(pl022); | ||
1085 | else | ||
1086 | do_dma_transfer(pl022); | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | static int __init init_queue(struct pl022 *pl022) | ||
1091 | { | ||
1092 | INIT_LIST_HEAD(&pl022->queue); | ||
1093 | spin_lock_init(&pl022->queue_lock); | ||
1094 | |||
1095 | pl022->run = QUEUE_STOPPED; | ||
1096 | pl022->busy = 0; | ||
1097 | |||
1098 | tasklet_init(&pl022->pump_transfers, | ||
1099 | pump_transfers, (unsigned long)pl022); | ||
1100 | |||
1101 | INIT_WORK(&pl022->pump_messages, pump_messages); | ||
1102 | pl022->workqueue = create_singlethread_workqueue( | ||
1103 | dev_name(pl022->master->dev.parent)); | ||
1104 | if (pl022->workqueue == NULL) | ||
1105 | return -EBUSY; | ||
1106 | |||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | |||
1111 | static int start_queue(struct pl022 *pl022) | ||
1112 | { | ||
1113 | unsigned long flags; | ||
1114 | |||
1115 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
1116 | |||
1117 | if (pl022->run == QUEUE_RUNNING || pl022->busy) { | ||
1118 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1119 | return -EBUSY; | ||
1120 | } | ||
1121 | |||
1122 | pl022->run = QUEUE_RUNNING; | ||
1123 | pl022->cur_msg = NULL; | ||
1124 | pl022->cur_transfer = NULL; | ||
1125 | pl022->cur_chip = NULL; | ||
1126 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1127 | |||
1128 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
1129 | |||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | |||
1134 | static int stop_queue(struct pl022 *pl022) | ||
1135 | { | ||
1136 | unsigned long flags; | ||
1137 | unsigned limit = 500; | ||
1138 | int status = 0; | ||
1139 | |||
1140 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
1141 | |||
1142 | /* This is a bit lame, but is optimized for the common execution path. | ||
1143 | * A wait_queue on the pl022->busy could be used, but then the common | ||
1144 | * execution path (pump_messages) would be required to call wake_up or | ||
1145 | * friends on every SPI message. Do this instead */ | ||
1146 | pl022->run = QUEUE_STOPPED; | ||
1147 | while (!list_empty(&pl022->queue) && pl022->busy && limit--) { | ||
1148 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1149 | msleep(10); | ||
1150 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
1151 | } | ||
1152 | |||
1153 | if (!list_empty(&pl022->queue) || pl022->busy) | ||
1154 | status = -EBUSY; | ||
1155 | |||
1156 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1157 | |||
1158 | return status; | ||
1159 | } | ||
1160 | |||
1161 | static int destroy_queue(struct pl022 *pl022) | ||
1162 | { | ||
1163 | int status; | ||
1164 | |||
1165 | status = stop_queue(pl022); | ||
1166 | /* we are unloading the module or failing to load (only two calls | ||
1167 | * to this routine), and neither call can handle a return value. | ||
1168 | * However, destroy_workqueue calls flush_workqueue, and that will | ||
1169 | * block until all work is done. If the reason that stop_queue | ||
1170 | * timed out is that the work will never finish, then it does no | ||
1171 | * good to call destroy_workqueue, so return anyway. */ | ||
1172 | if (status != 0) | ||
1173 | return status; | ||
1174 | |||
1175 | destroy_workqueue(pl022->workqueue); | ||
1176 | |||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | static int verify_controller_parameters(struct pl022 *pl022, | ||
1181 | struct pl022_config_chip *chip_info) | ||
1182 | { | ||
1183 | if ((chip_info->lbm != LOOPBACK_ENABLED) | ||
1184 | && (chip_info->lbm != LOOPBACK_DISABLED)) { | ||
1185 | dev_err(chip_info->dev, | ||
1186 | "loopback Mode is configured incorrectly\n"); | ||
1187 | return -EINVAL; | ||
1188 | } | ||
1189 | if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI) | ||
1190 | || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) { | ||
1191 | dev_err(chip_info->dev, | ||
1192 | "interface is configured incorrectly\n"); | ||
1193 | return -EINVAL; | ||
1194 | } | ||
1195 | if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) && | ||
1196 | (!pl022->vendor->unidir)) { | ||
1197 | dev_err(chip_info->dev, | ||
1198 | "unidirectional mode not supported in this " | ||
1199 | "hardware version\n"); | ||
1200 | return -EINVAL; | ||
1201 | } | ||
1202 | if ((chip_info->hierarchy != SSP_MASTER) | ||
1203 | && (chip_info->hierarchy != SSP_SLAVE)) { | ||
1204 | dev_err(chip_info->dev, | ||
1205 | "hierarchy is configured incorrectly\n"); | ||
1206 | return -EINVAL; | ||
1207 | } | ||
1208 | if (((chip_info->clk_freq).cpsdvsr < CPSDVR_MIN) | ||
1209 | || ((chip_info->clk_freq).cpsdvsr > CPSDVR_MAX)) { | ||
1210 | dev_err(chip_info->dev, | ||
1211 | "cpsdvsr is configured incorrectly\n"); | ||
1212 | return -EINVAL; | ||
1213 | } | ||
1214 | if ((chip_info->endian_rx != SSP_RX_MSB) | ||
1215 | && (chip_info->endian_rx != SSP_RX_LSB)) { | ||
1216 | dev_err(chip_info->dev, | ||
1217 | "RX FIFO endianess is configured incorrectly\n"); | ||
1218 | return -EINVAL; | ||
1219 | } | ||
1220 | if ((chip_info->endian_tx != SSP_TX_MSB) | ||
1221 | && (chip_info->endian_tx != SSP_TX_LSB)) { | ||
1222 | dev_err(chip_info->dev, | ||
1223 | "TX FIFO endianess is configured incorrectly\n"); | ||
1224 | return -EINVAL; | ||
1225 | } | ||
1226 | if ((chip_info->data_size < SSP_DATA_BITS_4) | ||
1227 | || (chip_info->data_size > SSP_DATA_BITS_32)) { | ||
1228 | dev_err(chip_info->dev, | ||
1229 | "DATA Size is configured incorrectly\n"); | ||
1230 | return -EINVAL; | ||
1231 | } | ||
1232 | if ((chip_info->com_mode != INTERRUPT_TRANSFER) | ||
1233 | && (chip_info->com_mode != DMA_TRANSFER) | ||
1234 | && (chip_info->com_mode != POLLING_TRANSFER)) { | ||
1235 | dev_err(chip_info->dev, | ||
1236 | "Communication mode is configured incorrectly\n"); | ||
1237 | return -EINVAL; | ||
1238 | } | ||
1239 | if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM) | ||
1240 | || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) { | ||
1241 | dev_err(chip_info->dev, | ||
1242 | "RX FIFO Trigger Level is configured incorrectly\n"); | ||
1243 | return -EINVAL; | ||
1244 | } | ||
1245 | if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC) | ||
1246 | || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) { | ||
1247 | dev_err(chip_info->dev, | ||
1248 | "TX FIFO Trigger Level is configured incorrectly\n"); | ||
1249 | return -EINVAL; | ||
1250 | } | ||
1251 | if (chip_info->iface == SSP_INTERFACE_MOTOROLA_SPI) { | ||
1252 | if ((chip_info->clk_phase != SSP_CLK_RISING_EDGE) | ||
1253 | && (chip_info->clk_phase != SSP_CLK_FALLING_EDGE)) { | ||
1254 | dev_err(chip_info->dev, | ||
1255 | "Clock Phase is configured incorrectly\n"); | ||
1256 | return -EINVAL; | ||
1257 | } | ||
1258 | if ((chip_info->clk_pol != SSP_CLK_POL_IDLE_LOW) | ||
1259 | && (chip_info->clk_pol != SSP_CLK_POL_IDLE_HIGH)) { | ||
1260 | dev_err(chip_info->dev, | ||
1261 | "Clock Polarity is configured incorrectly\n"); | ||
1262 | return -EINVAL; | ||
1263 | } | ||
1264 | } | ||
1265 | if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) { | ||
1266 | if ((chip_info->ctrl_len < SSP_BITS_4) | ||
1267 | || (chip_info->ctrl_len > SSP_BITS_32)) { | ||
1268 | dev_err(chip_info->dev, | ||
1269 | "CTRL LEN is configured incorrectly\n"); | ||
1270 | return -EINVAL; | ||
1271 | } | ||
1272 | if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO) | ||
1273 | && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) { | ||
1274 | dev_err(chip_info->dev, | ||
1275 | "Wait State is configured incorrectly\n"); | ||
1276 | return -EINVAL; | ||
1277 | } | ||
1278 | if ((chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX) | ||
1279 | && (chip_info->duplex != | ||
1280 | SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) { | ||
1281 | dev_err(chip_info->dev, | ||
1282 | "DUPLEX is configured incorrectly\n"); | ||
1283 | return -EINVAL; | ||
1284 | } | ||
1285 | } | ||
1286 | if (chip_info->cs_control == NULL) { | ||
1287 | dev_warn(chip_info->dev, | ||
1288 | "Chip Select Function is NULL for this chip\n"); | ||
1289 | chip_info->cs_control = null_cs_control; | ||
1290 | } | ||
1291 | return 0; | ||
1292 | } | ||
1293 | |||
1294 | /** | ||
1295 | * pl022_transfer - transfer function registered to SPI master framework | ||
1296 | * @spi: spi device which is requesting transfer | ||
1297 | * @msg: spi message which is to handled is queued to driver queue | ||
1298 | * | ||
1299 | * This function is registered to the SPI framework for this SPI master | ||
1300 | * controller. It will queue the spi_message in the queue of driver if | ||
1301 | * the queue is not stopped and return. | ||
1302 | */ | ||
1303 | static int pl022_transfer(struct spi_device *spi, struct spi_message *msg) | ||
1304 | { | ||
1305 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); | ||
1306 | unsigned long flags; | ||
1307 | |||
1308 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
1309 | |||
1310 | if (pl022->run == QUEUE_STOPPED) { | ||
1311 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1312 | return -ESHUTDOWN; | ||
1313 | } | ||
1314 | msg->actual_length = 0; | ||
1315 | msg->status = -EINPROGRESS; | ||
1316 | msg->state = STATE_START; | ||
1317 | |||
1318 | list_add_tail(&msg->queue, &pl022->queue); | ||
1319 | if (pl022->run == QUEUE_RUNNING && !pl022->busy) | ||
1320 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
1321 | |||
1322 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
1323 | return 0; | ||
1324 | } | ||
1325 | |||
1326 | static int calculate_effective_freq(struct pl022 *pl022, | ||
1327 | int freq, | ||
1328 | struct ssp_clock_params *clk_freq) | ||
1329 | { | ||
1330 | /* Lets calculate the frequency parameters */ | ||
1331 | u16 cpsdvsr = 2; | ||
1332 | u16 scr = 0; | ||
1333 | bool freq_found = false; | ||
1334 | u32 rate; | ||
1335 | u32 max_tclk; | ||
1336 | u32 min_tclk; | ||
1337 | |||
1338 | rate = clk_get_rate(pl022->clk); | ||
1339 | /* cpsdvscr = 2 & scr 0 */ | ||
1340 | max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN))); | ||
1341 | /* cpsdvsr = 254 & scr = 255 */ | ||
1342 | min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX))); | ||
1343 | |||
1344 | if ((freq <= max_tclk) && (freq >= min_tclk)) { | ||
1345 | while (cpsdvsr <= CPSDVR_MAX && !freq_found) { | ||
1346 | while (scr <= SCR_MAX && !freq_found) { | ||
1347 | if ((rate / | ||
1348 | (cpsdvsr * (1 + scr))) > freq) | ||
1349 | scr += 1; | ||
1350 | else { | ||
1351 | /* | ||
1352 | * This bool is made true when | ||
1353 | * effective frequency >= | ||
1354 | * target frequency is found | ||
1355 | */ | ||
1356 | freq_found = true; | ||
1357 | if ((rate / | ||
1358 | (cpsdvsr * (1 + scr))) != freq) { | ||
1359 | if (scr == SCR_MIN) { | ||
1360 | cpsdvsr -= 2; | ||
1361 | scr = SCR_MAX; | ||
1362 | } else | ||
1363 | scr -= 1; | ||
1364 | } | ||
1365 | } | ||
1366 | } | ||
1367 | if (!freq_found) { | ||
1368 | cpsdvsr += 2; | ||
1369 | scr = SCR_MIN; | ||
1370 | } | ||
1371 | } | ||
1372 | if (cpsdvsr != 0) { | ||
1373 | dev_dbg(&pl022->adev->dev, | ||
1374 | "SSP Effective Frequency is %u\n", | ||
1375 | (rate / (cpsdvsr * (1 + scr)))); | ||
1376 | clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF); | ||
1377 | clk_freq->scr = (u8) (scr & 0xFF); | ||
1378 | dev_dbg(&pl022->adev->dev, | ||
1379 | "SSP cpsdvsr = %d, scr = %d\n", | ||
1380 | clk_freq->cpsdvsr, clk_freq->scr); | ||
1381 | } | ||
1382 | } else { | ||
1383 | dev_err(&pl022->adev->dev, | ||
1384 | "controller data is incorrect: out of range frequency"); | ||
1385 | return -EINVAL; | ||
1386 | } | ||
1387 | return 0; | ||
1388 | } | ||
1389 | |||
1390 | /** | ||
1391 | * NOT IMPLEMENTED | ||
1392 | * process_dma_info - Processes the DMA info provided by client drivers | ||
1393 | * @chip_info: chip info provided by client device | ||
1394 | * @chip: Runtime state maintained by the SSP controller for each spi device | ||
1395 | * | ||
1396 | * This function processes and stores DMA config provided by client driver | ||
1397 | * into the runtime state maintained by the SSP controller driver | ||
1398 | */ | ||
1399 | static int process_dma_info(struct pl022_config_chip *chip_info, | ||
1400 | struct chip_data *chip) | ||
1401 | { | ||
1402 | dev_err(chip_info->dev, | ||
1403 | "cannot process DMA info, DMA not implemented!\n"); | ||
1404 | return -ENOTSUPP; | ||
1405 | } | ||
1406 | |||
1407 | /** | ||
1408 | * pl022_setup - setup function registered to SPI master framework | ||
1409 | * @spi: spi device which is requesting setup | ||
1410 | * | ||
1411 | * This function is registered to the SPI framework for this SPI master | ||
1412 | * controller. If it is the first time when setup is called by this device, | ||
1413 | * this function will initialize the runtime state for this chip and save | ||
1414 | * the same in the device structure. Else it will update the runtime info | ||
1415 | * with the updated chip info. Nothing is really being written to the | ||
1416 | * controller hardware here, that is not done until the actual transfer | ||
1417 | * commence. | ||
1418 | */ | ||
1419 | |||
1420 | /* FIXME: JUST GUESSING the spi->mode bits understood by this driver */ | ||
1421 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | ||
1422 | | SPI_LSB_FIRST | SPI_LOOP) | ||
1423 | |||
1424 | static int pl022_setup(struct spi_device *spi) | ||
1425 | { | ||
1426 | struct pl022_config_chip *chip_info; | ||
1427 | struct chip_data *chip; | ||
1428 | int status = 0; | ||
1429 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); | ||
1430 | |||
1431 | if (spi->mode & ~MODEBITS) { | ||
1432 | dev_dbg(&spi->dev, "unsupported mode bits %x\n", | ||
1433 | spi->mode & ~MODEBITS); | ||
1434 | return -EINVAL; | ||
1435 | } | ||
1436 | |||
1437 | if (!spi->max_speed_hz) | ||
1438 | return -EINVAL; | ||
1439 | |||
1440 | /* Get controller_state if one is supplied */ | ||
1441 | chip = spi_get_ctldata(spi); | ||
1442 | |||
1443 | if (chip == NULL) { | ||
1444 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); | ||
1445 | if (!chip) { | ||
1446 | dev_err(&spi->dev, | ||
1447 | "cannot allocate controller state\n"); | ||
1448 | return -ENOMEM; | ||
1449 | } | ||
1450 | dev_dbg(&spi->dev, | ||
1451 | "allocated memory for controller's runtime state\n"); | ||
1452 | } | ||
1453 | |||
1454 | /* Get controller data if one is supplied */ | ||
1455 | chip_info = spi->controller_data; | ||
1456 | |||
1457 | if (chip_info == NULL) { | ||
1458 | /* spi_board_info.controller_data not is supplied */ | ||
1459 | dev_dbg(&spi->dev, | ||
1460 | "using default controller_data settings\n"); | ||
1461 | |||
1462 | chip_info = | ||
1463 | kzalloc(sizeof(struct pl022_config_chip), GFP_KERNEL); | ||
1464 | |||
1465 | if (!chip_info) { | ||
1466 | dev_err(&spi->dev, | ||
1467 | "cannot allocate controller data\n"); | ||
1468 | status = -ENOMEM; | ||
1469 | goto err_first_setup; | ||
1470 | } | ||
1471 | |||
1472 | dev_dbg(&spi->dev, "allocated memory for controller data\n"); | ||
1473 | |||
1474 | /* Pointer back to the SPI device */ | ||
1475 | chip_info->dev = &spi->dev; | ||
1476 | /* | ||
1477 | * Set controller data default values: | ||
1478 | * Polling is supported by default | ||
1479 | */ | ||
1480 | chip_info->lbm = LOOPBACK_DISABLED; | ||
1481 | chip_info->com_mode = POLLING_TRANSFER; | ||
1482 | chip_info->iface = SSP_INTERFACE_MOTOROLA_SPI; | ||
1483 | chip_info->hierarchy = SSP_SLAVE; | ||
1484 | chip_info->slave_tx_disable = DO_NOT_DRIVE_TX; | ||
1485 | chip_info->endian_tx = SSP_TX_LSB; | ||
1486 | chip_info->endian_rx = SSP_RX_LSB; | ||
1487 | chip_info->data_size = SSP_DATA_BITS_12; | ||
1488 | chip_info->rx_lev_trig = SSP_RX_1_OR_MORE_ELEM; | ||
1489 | chip_info->tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC; | ||
1490 | chip_info->clk_phase = SSP_CLK_FALLING_EDGE; | ||
1491 | chip_info->clk_pol = SSP_CLK_POL_IDLE_LOW; | ||
1492 | chip_info->ctrl_len = SSP_BITS_8; | ||
1493 | chip_info->wait_state = SSP_MWIRE_WAIT_ZERO; | ||
1494 | chip_info->duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX; | ||
1495 | chip_info->cs_control = null_cs_control; | ||
1496 | } else { | ||
1497 | dev_dbg(&spi->dev, | ||
1498 | "using user supplied controller_data settings\n"); | ||
1499 | } | ||
1500 | |||
1501 | /* | ||
1502 | * We can override with custom divisors, else we use the board | ||
1503 | * frequency setting | ||
1504 | */ | ||
1505 | if ((0 == chip_info->clk_freq.cpsdvsr) | ||
1506 | && (0 == chip_info->clk_freq.scr)) { | ||
1507 | status = calculate_effective_freq(pl022, | ||
1508 | spi->max_speed_hz, | ||
1509 | &chip_info->clk_freq); | ||
1510 | if (status < 0) | ||
1511 | goto err_config_params; | ||
1512 | } else { | ||
1513 | if ((chip_info->clk_freq.cpsdvsr % 2) != 0) | ||
1514 | chip_info->clk_freq.cpsdvsr = | ||
1515 | chip_info->clk_freq.cpsdvsr - 1; | ||
1516 | } | ||
1517 | status = verify_controller_parameters(pl022, chip_info); | ||
1518 | if (status) { | ||
1519 | dev_err(&spi->dev, "controller data is incorrect"); | ||
1520 | goto err_config_params; | ||
1521 | } | ||
1522 | /* Now set controller state based on controller data */ | ||
1523 | chip->xfer_type = chip_info->com_mode; | ||
1524 | chip->cs_control = chip_info->cs_control; | ||
1525 | |||
1526 | if (chip_info->data_size <= 8) { | ||
1527 | dev_dbg(&spi->dev, "1 <= n <=8 bits per word\n"); | ||
1528 | chip->n_bytes = 1; | ||
1529 | chip->read = READING_U8; | ||
1530 | chip->write = WRITING_U8; | ||
1531 | } else if (chip_info->data_size <= 16) { | ||
1532 | dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n"); | ||
1533 | chip->n_bytes = 2; | ||
1534 | chip->read = READING_U16; | ||
1535 | chip->write = WRITING_U16; | ||
1536 | } else { | ||
1537 | if (pl022->vendor->max_bpw >= 32) { | ||
1538 | dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n"); | ||
1539 | chip->n_bytes = 4; | ||
1540 | chip->read = READING_U32; | ||
1541 | chip->write = WRITING_U32; | ||
1542 | } else { | ||
1543 | dev_err(&spi->dev, | ||
1544 | "illegal data size for this controller!\n"); | ||
1545 | dev_err(&spi->dev, | ||
1546 | "a standard pl022 can only handle " | ||
1547 | "1 <= n <= 16 bit words\n"); | ||
1548 | goto err_config_params; | ||
1549 | } | ||
1550 | } | ||
1551 | |||
1552 | /* Now Initialize all register settings required for this chip */ | ||
1553 | chip->cr0 = 0; | ||
1554 | chip->cr1 = 0; | ||
1555 | chip->dmacr = 0; | ||
1556 | chip->cpsr = 0; | ||
1557 | if ((chip_info->com_mode == DMA_TRANSFER) | ||
1558 | && ((pl022->master_info)->enable_dma)) { | ||
1559 | chip->enable_dma = 1; | ||
1560 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); | ||
1561 | status = process_dma_info(chip_info, chip); | ||
1562 | if (status < 0) | ||
1563 | goto err_config_params; | ||
1564 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | ||
1565 | SSP_DMACR_MASK_RXDMAE, 0); | ||
1566 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | ||
1567 | SSP_DMACR_MASK_TXDMAE, 1); | ||
1568 | } else { | ||
1569 | chip->enable_dma = 0; | ||
1570 | dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n"); | ||
1571 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED, | ||
1572 | SSP_DMACR_MASK_RXDMAE, 0); | ||
1573 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED, | ||
1574 | SSP_DMACR_MASK_TXDMAE, 1); | ||
1575 | } | ||
1576 | |||
1577 | chip->cpsr = chip_info->clk_freq.cpsdvsr; | ||
1578 | |||
1579 | SSP_WRITE_BITS(chip->cr0, chip_info->data_size, SSP_CR0_MASK_DSS, 0); | ||
1580 | SSP_WRITE_BITS(chip->cr0, chip_info->duplex, SSP_CR0_MASK_HALFDUP, 5); | ||
1581 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6); | ||
1582 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7); | ||
1583 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8); | ||
1584 | SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len, SSP_CR0_MASK_CSS, 16); | ||
1585 | SSP_WRITE_BITS(chip->cr0, chip_info->iface, SSP_CR0_MASK_FRF, 21); | ||
1586 | SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0); | ||
1587 | SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); | ||
1588 | SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); | ||
1589 | SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3); | ||
1590 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx, SSP_CR1_MASK_RENDN, 4); | ||
1591 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx, SSP_CR1_MASK_TENDN, 5); | ||
1592 | SSP_WRITE_BITS(chip->cr1, chip_info->wait_state, SSP_CR1_MASK_MWAIT, 6); | ||
1593 | SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig, SSP_CR1_MASK_RXIFLSEL, 7); | ||
1594 | SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, SSP_CR1_MASK_TXIFLSEL, 10); | ||
1595 | |||
1596 | /* Save controller_state */ | ||
1597 | spi_set_ctldata(spi, chip); | ||
1598 | return status; | ||
1599 | err_config_params: | ||
1600 | err_first_setup: | ||
1601 | kfree(chip); | ||
1602 | return status; | ||
1603 | } | ||
1604 | |||
1605 | /** | ||
1606 | * pl022_cleanup - cleanup function registered to SPI master framework | ||
1607 | * @spi: spi device which is requesting cleanup | ||
1608 | * | ||
1609 | * This function is registered to the SPI framework for this SPI master | ||
1610 | * controller. It will free the runtime state of chip. | ||
1611 | */ | ||
1612 | static void pl022_cleanup(struct spi_device *spi) | ||
1613 | { | ||
1614 | struct chip_data *chip = spi_get_ctldata(spi); | ||
1615 | |||
1616 | spi_set_ctldata(spi, NULL); | ||
1617 | kfree(chip); | ||
1618 | } | ||
1619 | |||
1620 | |||
1621 | static int __init | ||
1622 | pl022_probe(struct amba_device *adev, struct amba_id *id) | ||
1623 | { | ||
1624 | struct device *dev = &adev->dev; | ||
1625 | struct pl022_ssp_controller *platform_info = adev->dev.platform_data; | ||
1626 | struct spi_master *master; | ||
1627 | struct pl022 *pl022 = NULL; /*Data for this driver */ | ||
1628 | int status = 0; | ||
1629 | |||
1630 | dev_info(&adev->dev, | ||
1631 | "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid); | ||
1632 | if (platform_info == NULL) { | ||
1633 | dev_err(&adev->dev, "probe - no platform data supplied\n"); | ||
1634 | status = -ENODEV; | ||
1635 | goto err_no_pdata; | ||
1636 | } | ||
1637 | |||
1638 | /* Allocate master with space for data */ | ||
1639 | master = spi_alloc_master(dev, sizeof(struct pl022)); | ||
1640 | if (master == NULL) { | ||
1641 | dev_err(&adev->dev, "probe - cannot alloc SPI master\n"); | ||
1642 | status = -ENOMEM; | ||
1643 | goto err_no_master; | ||
1644 | } | ||
1645 | |||
1646 | pl022 = spi_master_get_devdata(master); | ||
1647 | pl022->master = master; | ||
1648 | pl022->master_info = platform_info; | ||
1649 | pl022->adev = adev; | ||
1650 | pl022->vendor = id->data; | ||
1651 | |||
1652 | /* | ||
1653 | * Bus Number Which has been Assigned to this SSP controller | ||
1654 | * on this board | ||
1655 | */ | ||
1656 | master->bus_num = platform_info->bus_id; | ||
1657 | master->num_chipselect = platform_info->num_chipselect; | ||
1658 | master->cleanup = pl022_cleanup; | ||
1659 | master->setup = pl022_setup; | ||
1660 | master->transfer = pl022_transfer; | ||
1661 | |||
1662 | dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num); | ||
1663 | |||
1664 | status = amba_request_regions(adev, NULL); | ||
1665 | if (status) | ||
1666 | goto err_no_ioregion; | ||
1667 | |||
1668 | pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); | ||
1669 | if (pl022->virtbase == NULL) { | ||
1670 | status = -ENOMEM; | ||
1671 | goto err_no_ioremap; | ||
1672 | } | ||
1673 | printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", | ||
1674 | adev->res.start, pl022->virtbase); | ||
1675 | |||
1676 | pl022->clk = clk_get(&adev->dev, NULL); | ||
1677 | if (IS_ERR(pl022->clk)) { | ||
1678 | status = PTR_ERR(pl022->clk); | ||
1679 | dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n"); | ||
1680 | goto err_no_clk; | ||
1681 | } | ||
1682 | |||
1683 | /* Disable SSP */ | ||
1684 | clk_enable(pl022->clk); | ||
1685 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), | ||
1686 | SSP_CR1(pl022->virtbase)); | ||
1687 | load_ssp_default_config(pl022); | ||
1688 | clk_disable(pl022->clk); | ||
1689 | |||
1690 | status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", | ||
1691 | pl022); | ||
1692 | if (status < 0) { | ||
1693 | dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status); | ||
1694 | goto err_no_irq; | ||
1695 | } | ||
1696 | /* Initialize and start queue */ | ||
1697 | status = init_queue(pl022); | ||
1698 | if (status != 0) { | ||
1699 | dev_err(&adev->dev, "probe - problem initializing queue\n"); | ||
1700 | goto err_init_queue; | ||
1701 | } | ||
1702 | status = start_queue(pl022); | ||
1703 | if (status != 0) { | ||
1704 | dev_err(&adev->dev, "probe - problem starting queue\n"); | ||
1705 | goto err_start_queue; | ||
1706 | } | ||
1707 | /* Register with the SPI framework */ | ||
1708 | amba_set_drvdata(adev, pl022); | ||
1709 | status = spi_register_master(master); | ||
1710 | if (status != 0) { | ||
1711 | dev_err(&adev->dev, | ||
1712 | "probe - problem registering spi master\n"); | ||
1713 | goto err_spi_register; | ||
1714 | } | ||
1715 | dev_dbg(dev, "probe succeded\n"); | ||
1716 | return 0; | ||
1717 | |||
1718 | err_spi_register: | ||
1719 | err_start_queue: | ||
1720 | err_init_queue: | ||
1721 | destroy_queue(pl022); | ||
1722 | free_irq(adev->irq[0], pl022); | ||
1723 | err_no_irq: | ||
1724 | clk_put(pl022->clk); | ||
1725 | err_no_clk: | ||
1726 | iounmap(pl022->virtbase); | ||
1727 | err_no_ioremap: | ||
1728 | amba_release_regions(adev); | ||
1729 | err_no_ioregion: | ||
1730 | spi_master_put(master); | ||
1731 | err_no_master: | ||
1732 | err_no_pdata: | ||
1733 | return status; | ||
1734 | } | ||
1735 | |||
1736 | static int __exit | ||
1737 | pl022_remove(struct amba_device *adev) | ||
1738 | { | ||
1739 | struct pl022 *pl022 = amba_get_drvdata(adev); | ||
1740 | int status = 0; | ||
1741 | if (!pl022) | ||
1742 | return 0; | ||
1743 | |||
1744 | /* Remove the queue */ | ||
1745 | status = destroy_queue(pl022); | ||
1746 | if (status != 0) { | ||
1747 | dev_err(&adev->dev, | ||
1748 | "queue remove failed (%d)\n", status); | ||
1749 | return status; | ||
1750 | } | ||
1751 | load_ssp_default_config(pl022); | ||
1752 | free_irq(adev->irq[0], pl022); | ||
1753 | clk_disable(pl022->clk); | ||
1754 | clk_put(pl022->clk); | ||
1755 | iounmap(pl022->virtbase); | ||
1756 | amba_release_regions(adev); | ||
1757 | tasklet_disable(&pl022->pump_transfers); | ||
1758 | spi_unregister_master(pl022->master); | ||
1759 | spi_master_put(pl022->master); | ||
1760 | amba_set_drvdata(adev, NULL); | ||
1761 | dev_dbg(&adev->dev, "remove succeded\n"); | ||
1762 | return 0; | ||
1763 | } | ||
1764 | |||
1765 | #ifdef CONFIG_PM | ||
1766 | static int pl022_suspend(struct amba_device *adev, pm_message_t state) | ||
1767 | { | ||
1768 | struct pl022 *pl022 = amba_get_drvdata(adev); | ||
1769 | int status = 0; | ||
1770 | |||
1771 | status = stop_queue(pl022); | ||
1772 | if (status) { | ||
1773 | dev_warn(&adev->dev, "suspend cannot stop queue\n"); | ||
1774 | return status; | ||
1775 | } | ||
1776 | |||
1777 | clk_enable(pl022->clk); | ||
1778 | load_ssp_default_config(pl022); | ||
1779 | clk_disable(pl022->clk); | ||
1780 | dev_dbg(&adev->dev, "suspended\n"); | ||
1781 | return 0; | ||
1782 | } | ||
1783 | |||
1784 | static int pl022_resume(struct amba_device *adev) | ||
1785 | { | ||
1786 | struct pl022 *pl022 = amba_get_drvdata(adev); | ||
1787 | int status = 0; | ||
1788 | |||
1789 | /* Start the queue running */ | ||
1790 | status = start_queue(pl022); | ||
1791 | if (status) | ||
1792 | dev_err(&adev->dev, "problem starting queue (%d)\n", status); | ||
1793 | else | ||
1794 | dev_dbg(&adev->dev, "resumed\n"); | ||
1795 | |||
1796 | return status; | ||
1797 | } | ||
1798 | #else | ||
1799 | #define pl022_suspend NULL | ||
1800 | #define pl022_resume NULL | ||
1801 | #endif /* CONFIG_PM */ | ||
1802 | |||
1803 | static struct vendor_data vendor_arm = { | ||
1804 | .fifodepth = 8, | ||
1805 | .max_bpw = 16, | ||
1806 | .unidir = false, | ||
1807 | }; | ||
1808 | |||
1809 | |||
1810 | static struct vendor_data vendor_st = { | ||
1811 | .fifodepth = 32, | ||
1812 | .max_bpw = 32, | ||
1813 | .unidir = false, | ||
1814 | }; | ||
1815 | |||
1816 | static struct amba_id pl022_ids[] = { | ||
1817 | { | ||
1818 | /* | ||
1819 | * ARM PL022 variant, this has a 16bit wide | ||
1820 | * and 8 locations deep TX/RX FIFO | ||
1821 | */ | ||
1822 | .id = 0x00041022, | ||
1823 | .mask = 0x000fffff, | ||
1824 | .data = &vendor_arm, | ||
1825 | }, | ||
1826 | { | ||
1827 | /* | ||
1828 | * ST Micro derivative, this has 32bit wide | ||
1829 | * and 32 locations deep TX/RX FIFO | ||
1830 | */ | ||
1831 | .id = 0x00108022, | ||
1832 | .mask = 0xffffffff, | ||
1833 | .data = &vendor_st, | ||
1834 | }, | ||
1835 | { 0, 0 }, | ||
1836 | }; | ||
1837 | |||
1838 | static struct amba_driver pl022_driver = { | ||
1839 | .drv = { | ||
1840 | .name = "ssp-pl022", | ||
1841 | }, | ||
1842 | .id_table = pl022_ids, | ||
1843 | .probe = pl022_probe, | ||
1844 | .remove = __exit_p(pl022_remove), | ||
1845 | .suspend = pl022_suspend, | ||
1846 | .resume = pl022_resume, | ||
1847 | }; | ||
1848 | |||
1849 | |||
1850 | static int __init pl022_init(void) | ||
1851 | { | ||
1852 | return amba_driver_register(&pl022_driver); | ||
1853 | } | ||
1854 | |||
1855 | module_init(pl022_init); | ||
1856 | |||
1857 | static void __exit pl022_exit(void) | ||
1858 | { | ||
1859 | amba_driver_unregister(&pl022_driver); | ||
1860 | } | ||
1861 | |||
1862 | module_exit(pl022_exit); | ||
1863 | |||
1864 | MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); | ||
1865 | MODULE_DESCRIPTION("PL022 SSP Controller Driver"); | ||
1866 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index f2447a5476bb..bbf9371cd284 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/gpio.h> | ||
20 | 21 | ||
21 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
22 | #include <linux/spi/spi_bitbang.h> | 23 | #include <linux/spi/spi_bitbang.h> |
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 7cf74f8c2db1..b0dbf4157d29 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c | |||
@@ -47,7 +47,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, | |||
47 | struct usb_hcd *hcd; | 47 | struct usb_hcd *hcd; |
48 | 48 | ||
49 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { | 49 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { |
50 | pr_debug("resource[1] is not IORESOURCE_IRQ"); | 50 | dbg("resource[1] is not IORESOURCE_IRQ"); |
51 | return -ENOMEM; | 51 | return -ENOMEM; |
52 | } | 52 | } |
53 | 53 | ||
@@ -65,12 +65,18 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, | |||
65 | 65 | ||
66 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | 66 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); |
67 | if (hcd->regs == NULL) { | 67 | if (hcd->regs == NULL) { |
68 | pr_debug("ioremap failed"); | 68 | dbg("ioremap failed"); |
69 | retval = -ENOMEM; | 69 | retval = -ENOMEM; |
70 | goto err2; | 70 | goto err2; |
71 | } | 71 | } |
72 | 72 | ||
73 | usb_host_clock = clk_get(&pdev->dev, "usb_host"); | 73 | usb_host_clock = clk_get(&pdev->dev, NULL); |
74 | if (IS_ERR(usb_host_clock)) { | ||
75 | dbg("clk_get failed"); | ||
76 | retval = PTR_ERR(usb_host_clock); | ||
77 | goto err3; | ||
78 | } | ||
79 | |||
74 | ep93xx_start_hc(&pdev->dev); | 80 | ep93xx_start_hc(&pdev->dev); |
75 | 81 | ||
76 | ohci_hcd_init(hcd_to_ohci(hcd)); | 82 | ohci_hcd_init(hcd_to_ohci(hcd)); |
@@ -80,6 +86,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, | |||
80 | return retval; | 86 | return retval; |
81 | 87 | ||
82 | ep93xx_stop_hc(&pdev->dev); | 88 | ep93xx_stop_hc(&pdev->dev); |
89 | err3: | ||
83 | iounmap(hcd->regs); | 90 | iounmap(hcd->regs); |
84 | err2: | 91 | err2: |
85 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 92 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 74712cb8399a..2b5a691064b7 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -397,7 +397,7 @@ config FB_SA1100 | |||
397 | 397 | ||
398 | config FB_IMX | 398 | config FB_IMX |
399 | tristate "Motorola i.MX LCD support" | 399 | tristate "Motorola i.MX LCD support" |
400 | depends on FB && (ARCH_IMX || ARCH_MX2) | 400 | depends on FB && (ARCH_MX1 || ARCH_MX2) |
401 | select FB_CFB_FILLRECT | 401 | select FB_CFB_FILLRECT |
402 | select FB_CFB_COPYAREA | 402 | select FB_CFB_COPYAREA |
403 | select FB_CFB_IMAGEBLIT | 403 | select FB_CFB_IMAGEBLIT |
@@ -1759,6 +1759,16 @@ config FB_68328 | |||
1759 | Say Y here if you want to support the built-in frame buffer of | 1759 | Say Y here if you want to support the built-in frame buffer of |
1760 | the Motorola 68328 CPU family. | 1760 | the Motorola 68328 CPU family. |
1761 | 1761 | ||
1762 | config FB_PXA168 | ||
1763 | tristate "PXA168/910 LCD framebuffer support" | ||
1764 | depends on FB && (CPU_PXA168 || CPU_PXA910) | ||
1765 | select FB_CFB_FILLRECT | ||
1766 | select FB_CFB_COPYAREA | ||
1767 | select FB_CFB_IMAGEBLIT | ||
1768 | ---help--- | ||
1769 | Frame buffer driver for the built-in LCD controller in the Marvell | ||
1770 | MMP processor. | ||
1771 | |||
1762 | config FB_PXA | 1772 | config FB_PXA |
1763 | tristate "PXA LCD framebuffer support" | 1773 | tristate "PXA LCD framebuffer support" |
1764 | depends on FB && ARCH_PXA | 1774 | depends on FB && ARCH_PXA |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index d8d0be5151e3..01a819f47371 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -97,6 +97,7 @@ obj-$(CONFIG_FB_GBE) += gbefb.o | |||
97 | obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o | 97 | obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o |
98 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o | 98 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o |
99 | obj-$(CONFIG_FB_PXA) += pxafb.o | 99 | obj-$(CONFIG_FB_PXA) += pxafb.o |
100 | obj-$(CONFIG_FB_PXA168) += pxa168fb.o | ||
100 | obj-$(CONFIG_FB_W100) += w100fb.o | 101 | obj-$(CONFIG_FB_W100) += w100fb.o |
101 | obj-$(CONFIG_FB_TMIO) += tmiofb.o | 102 | obj-$(CONFIG_FB_TMIO) += tmiofb.o |
102 | obj-$(CONFIG_FB_AU1100) += au1100fb.o | 103 | obj-$(CONFIG_FB_AU1100) += au1100fb.o |
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index d1f80bac54f0..fb8163d181ab 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c | |||
@@ -351,7 +351,7 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
351 | } | 351 | } |
352 | 352 | ||
353 | fb->fb.fix.mmio_start = fb->dev->res.start; | 353 | fb->fb.fix.mmio_start = fb->dev->res.start; |
354 | fb->fb.fix.mmio_len = 4096; | 354 | fb->fb.fix.mmio_len = resource_size(&fb->dev->res); |
355 | 355 | ||
356 | fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len); | 356 | fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len); |
357 | if (!fb->regs) { | 357 | if (!fb->regs) { |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 9894de1c9b9f..b7af5256e887 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
@@ -706,7 +706,7 @@ static void mx3fb_dma_done(void *arg) | |||
706 | dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq); | 706 | dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq); |
707 | 707 | ||
708 | /* We only need one interrupt, it will be re-enabled as needed */ | 708 | /* We only need one interrupt, it will be re-enabled as needed */ |
709 | disable_irq(ichannel->eof_irq); | 709 | disable_irq_nosync(ichannel->eof_irq); |
710 | 710 | ||
711 | complete(&mx3_fbi->flip_cmpl); | 711 | complete(&mx3_fbi->flip_cmpl); |
712 | } | 712 | } |
@@ -1366,7 +1366,7 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) | |||
1366 | 1366 | ||
1367 | mx3fb_blank(FB_BLANK_UNBLANK, fbi); | 1367 | mx3fb_blank(FB_BLANK_UNBLANK, fbi); |
1368 | 1368 | ||
1369 | dev_info(dev, "mx3fb: fb registered, using mode %s\n", fb_mode); | 1369 | dev_info(dev, "registered, using mode %s\n", fb_mode); |
1370 | 1370 | ||
1371 | ret = register_framebuffer(fbi); | 1371 | ret = register_framebuffer(fbi); |
1372 | if (ret < 0) | 1372 | if (ret < 0) |
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 8aa6e47202b9..5d4f34887a22 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c | |||
@@ -133,8 +133,7 @@ struct { | |||
133 | struct lcd_ctrl_extif *extif; | 133 | struct lcd_ctrl_extif *extif; |
134 | struct lcd_ctrl *int_ctrl; | 134 | struct lcd_ctrl *int_ctrl; |
135 | 135 | ||
136 | void (*power_up)(struct device *dev); | 136 | struct clk *sys_ck; |
137 | void (*power_down)(struct device *dev); | ||
138 | } hwa742; | 137 | } hwa742; |
139 | 138 | ||
140 | struct lcd_ctrl hwa742_ctrl; | 139 | struct lcd_ctrl hwa742_ctrl; |
@@ -915,14 +914,13 @@ static void hwa742_suspend(void) | |||
915 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); | 914 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); |
916 | /* Enable sleep mode */ | 915 | /* Enable sleep mode */ |
917 | hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1); | 916 | hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1); |
918 | if (hwa742.power_down != NULL) | 917 | clk_disable(hwa742.sys_ck); |
919 | hwa742.power_down(hwa742.fbdev->dev); | ||
920 | } | 918 | } |
921 | 919 | ||
922 | static void hwa742_resume(void) | 920 | static void hwa742_resume(void) |
923 | { | 921 | { |
924 | if (hwa742.power_up != NULL) | 922 | clk_enable(hwa742.sys_ck); |
925 | hwa742.power_up(hwa742.fbdev->dev); | 923 | |
926 | /* Disable sleep mode */ | 924 | /* Disable sleep mode */ |
927 | hwa742_write_reg(HWA742_POWER_SAVE, 0); | 925 | hwa742_write_reg(HWA742_POWER_SAVE, 0); |
928 | while (1) { | 926 | while (1) { |
@@ -955,14 +953,13 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, | |||
955 | omapfb_conf = fbdev->dev->platform_data; | 953 | omapfb_conf = fbdev->dev->platform_data; |
956 | ctrl_conf = omapfb_conf->ctrl_platform_data; | 954 | ctrl_conf = omapfb_conf->ctrl_platform_data; |
957 | 955 | ||
958 | if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) { | 956 | if (ctrl_conf == NULL) { |
959 | dev_err(fbdev->dev, "HWA742: missing platform data\n"); | 957 | dev_err(fbdev->dev, "HWA742: missing platform data\n"); |
960 | r = -ENOENT; | 958 | r = -ENOENT; |
961 | goto err1; | 959 | goto err1; |
962 | } | 960 | } |
963 | 961 | ||
964 | hwa742.power_down = ctrl_conf->power_down; | 962 | hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); |
965 | hwa742.power_up = ctrl_conf->power_up; | ||
966 | 963 | ||
967 | spin_lock_init(&hwa742.req_lock); | 964 | spin_lock_init(&hwa742.req_lock); |
968 | 965 | ||
@@ -972,12 +969,11 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, | |||
972 | if ((r = hwa742.extif->init(fbdev)) < 0) | 969 | if ((r = hwa742.extif->init(fbdev)) < 0) |
973 | goto err2; | 970 | goto err2; |
974 | 971 | ||
975 | ext_clk = ctrl_conf->get_clock_rate(fbdev->dev); | 972 | ext_clk = clk_get_rate(hwa742.sys_ck); |
976 | if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0) | 973 | if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0) |
977 | goto err3; | 974 | goto err3; |
978 | hwa742.extif->set_timings(&hwa742.reg_timings); | 975 | hwa742.extif->set_timings(&hwa742.reg_timings); |
979 | if (hwa742.power_up != NULL) | 976 | clk_enable(hwa742.sys_ck); |
980 | hwa742.power_up(fbdev->dev); | ||
981 | 977 | ||
982 | calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk); | 978 | calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk); |
983 | if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0) | 979 | if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0) |
@@ -1040,8 +1036,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, | |||
1040 | 1036 | ||
1041 | return 0; | 1037 | return 0; |
1042 | err4: | 1038 | err4: |
1043 | if (hwa742.power_down != NULL) | 1039 | clk_disable(hwa742.sys_ck); |
1044 | hwa742.power_down(fbdev->dev); | ||
1045 | err3: | 1040 | err3: |
1046 | hwa742.extif->cleanup(); | 1041 | hwa742.extif->cleanup(); |
1047 | err2: | 1042 | err2: |
@@ -1055,8 +1050,7 @@ static void hwa742_cleanup(void) | |||
1055 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); | 1050 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); |
1056 | hwa742.extif->cleanup(); | 1051 | hwa742.extif->cleanup(); |
1057 | hwa742.int_ctrl->cleanup(); | 1052 | hwa742.int_ctrl->cleanup(); |
1058 | if (hwa742.power_down != NULL) | 1053 | clk_disable(hwa742.sys_ck); |
1059 | hwa742.power_down(hwa742.fbdev->dev); | ||
1060 | } | 1054 | } |
1061 | 1055 | ||
1062 | struct lcd_ctrl hwa742_ctrl = { | 1056 | struct lcd_ctrl hwa742_ctrl = { |
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c new file mode 100644 index 000000000000..84d8327e47db --- /dev/null +++ b/drivers/video/pxa168fb.c | |||
@@ -0,0 +1,803 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller | ||
3 | * | ||
4 | * Copyright (C) 2008 Marvell International Ltd. | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * 2009-02-16 adapted from original version for PXA168/910 | ||
8 | * Jun Nie <njun@marvell.com> | ||
9 | * | ||
10 | * This file is subject to the terms and conditions of the GNU General Public | ||
11 | * License. See the file COPYING in the main directory of this archive for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/fb.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/dma-mapping.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | #include <video/pxa168fb.h> | ||
31 | |||
32 | #include "pxa168fb.h" | ||
33 | |||
34 | #define DEFAULT_REFRESH 60 /* Hz */ | ||
35 | |||
36 | static int determine_best_pix_fmt(struct fb_var_screeninfo *var) | ||
37 | { | ||
38 | /* | ||
39 | * Pseudocolor mode? | ||
40 | */ | ||
41 | if (var->bits_per_pixel == 8) | ||
42 | return PIX_FMT_PSEUDOCOLOR; | ||
43 | |||
44 | /* | ||
45 | * Check for 565/1555. | ||
46 | */ | ||
47 | if (var->bits_per_pixel == 16 && var->red.length <= 5 && | ||
48 | var->green.length <= 6 && var->blue.length <= 5) { | ||
49 | if (var->transp.length == 0) { | ||
50 | if (var->red.offset >= var->blue.offset) | ||
51 | return PIX_FMT_RGB565; | ||
52 | else | ||
53 | return PIX_FMT_BGR565; | ||
54 | } | ||
55 | |||
56 | if (var->transp.length == 1 && var->green.length <= 5) { | ||
57 | if (var->red.offset >= var->blue.offset) | ||
58 | return PIX_FMT_RGB1555; | ||
59 | else | ||
60 | return PIX_FMT_BGR1555; | ||
61 | } | ||
62 | |||
63 | /* fall through */ | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Check for 888/A888. | ||
68 | */ | ||
69 | if (var->bits_per_pixel <= 32 && var->red.length <= 8 && | ||
70 | var->green.length <= 8 && var->blue.length <= 8) { | ||
71 | if (var->bits_per_pixel == 24 && var->transp.length == 0) { | ||
72 | if (var->red.offset >= var->blue.offset) | ||
73 | return PIX_FMT_RGB888PACK; | ||
74 | else | ||
75 | return PIX_FMT_BGR888PACK; | ||
76 | } | ||
77 | |||
78 | if (var->bits_per_pixel == 32 && var->transp.length == 8) { | ||
79 | if (var->red.offset >= var->blue.offset) | ||
80 | return PIX_FMT_RGBA888; | ||
81 | else | ||
82 | return PIX_FMT_BGRA888; | ||
83 | } else { | ||
84 | if (var->red.offset >= var->blue.offset) | ||
85 | return PIX_FMT_RGB888UNPACK; | ||
86 | else | ||
87 | return PIX_FMT_BGR888UNPACK; | ||
88 | } | ||
89 | |||
90 | /* fall through */ | ||
91 | } | ||
92 | |||
93 | return -EINVAL; | ||
94 | } | ||
95 | |||
96 | static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt) | ||
97 | { | ||
98 | switch (pix_fmt) { | ||
99 | case PIX_FMT_RGB565: | ||
100 | var->bits_per_pixel = 16; | ||
101 | var->red.offset = 11; var->red.length = 5; | ||
102 | var->green.offset = 5; var->green.length = 6; | ||
103 | var->blue.offset = 0; var->blue.length = 5; | ||
104 | var->transp.offset = 0; var->transp.length = 0; | ||
105 | break; | ||
106 | case PIX_FMT_BGR565: | ||
107 | var->bits_per_pixel = 16; | ||
108 | var->red.offset = 0; var->red.length = 5; | ||
109 | var->green.offset = 5; var->green.length = 6; | ||
110 | var->blue.offset = 11; var->blue.length = 5; | ||
111 | var->transp.offset = 0; var->transp.length = 0; | ||
112 | break; | ||
113 | case PIX_FMT_RGB1555: | ||
114 | var->bits_per_pixel = 16; | ||
115 | var->red.offset = 10; var->red.length = 5; | ||
116 | var->green.offset = 5; var->green.length = 5; | ||
117 | var->blue.offset = 0; var->blue.length = 5; | ||
118 | var->transp.offset = 15; var->transp.length = 1; | ||
119 | break; | ||
120 | case PIX_FMT_BGR1555: | ||
121 | var->bits_per_pixel = 16; | ||
122 | var->red.offset = 0; var->red.length = 5; | ||
123 | var->green.offset = 5; var->green.length = 5; | ||
124 | var->blue.offset = 10; var->blue.length = 5; | ||
125 | var->transp.offset = 15; var->transp.length = 1; | ||
126 | break; | ||
127 | case PIX_FMT_RGB888PACK: | ||
128 | var->bits_per_pixel = 24; | ||
129 | var->red.offset = 16; var->red.length = 8; | ||
130 | var->green.offset = 8; var->green.length = 8; | ||
131 | var->blue.offset = 0; var->blue.length = 8; | ||
132 | var->transp.offset = 0; var->transp.length = 0; | ||
133 | break; | ||
134 | case PIX_FMT_BGR888PACK: | ||
135 | var->bits_per_pixel = 24; | ||
136 | var->red.offset = 0; var->red.length = 8; | ||
137 | var->green.offset = 8; var->green.length = 8; | ||
138 | var->blue.offset = 16; var->blue.length = 8; | ||
139 | var->transp.offset = 0; var->transp.length = 0; | ||
140 | break; | ||
141 | case PIX_FMT_RGBA888: | ||
142 | var->bits_per_pixel = 32; | ||
143 | var->red.offset = 16; var->red.length = 8; | ||
144 | var->green.offset = 8; var->green.length = 8; | ||
145 | var->blue.offset = 0; var->blue.length = 8; | ||
146 | var->transp.offset = 24; var->transp.length = 8; | ||
147 | break; | ||
148 | case PIX_FMT_BGRA888: | ||
149 | var->bits_per_pixel = 32; | ||
150 | var->red.offset = 0; var->red.length = 8; | ||
151 | var->green.offset = 8; var->green.length = 8; | ||
152 | var->blue.offset = 16; var->blue.length = 8; | ||
153 | var->transp.offset = 24; var->transp.length = 8; | ||
154 | break; | ||
155 | case PIX_FMT_PSEUDOCOLOR: | ||
156 | var->bits_per_pixel = 8; | ||
157 | var->red.offset = 0; var->red.length = 8; | ||
158 | var->green.offset = 0; var->green.length = 8; | ||
159 | var->blue.offset = 0; var->blue.length = 8; | ||
160 | var->transp.offset = 0; var->transp.length = 0; | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var, | ||
166 | struct fb_videomode *mode, int pix_fmt, int ystretch) | ||
167 | { | ||
168 | struct fb_info *info = fbi->info; | ||
169 | |||
170 | set_pix_fmt(var, pix_fmt); | ||
171 | |||
172 | var->xres = mode->xres; | ||
173 | var->yres = mode->yres; | ||
174 | var->xres_virtual = max(var->xres, var->xres_virtual); | ||
175 | if (ystretch) | ||
176 | var->yres_virtual = info->fix.smem_len / | ||
177 | (var->xres_virtual * (var->bits_per_pixel >> 3)); | ||
178 | else | ||
179 | var->yres_virtual = max(var->yres, var->yres_virtual); | ||
180 | var->grayscale = 0; | ||
181 | var->accel_flags = FB_ACCEL_NONE; | ||
182 | var->pixclock = mode->pixclock; | ||
183 | var->left_margin = mode->left_margin; | ||
184 | var->right_margin = mode->right_margin; | ||
185 | var->upper_margin = mode->upper_margin; | ||
186 | var->lower_margin = mode->lower_margin; | ||
187 | var->hsync_len = mode->hsync_len; | ||
188 | var->vsync_len = mode->vsync_len; | ||
189 | var->sync = mode->sync; | ||
190 | var->vmode = FB_VMODE_NONINTERLACED; | ||
191 | var->rotate = FB_ROTATE_UR; | ||
192 | } | ||
193 | |||
194 | static int pxa168fb_check_var(struct fb_var_screeninfo *var, | ||
195 | struct fb_info *info) | ||
196 | { | ||
197 | struct pxa168fb_info *fbi = info->par; | ||
198 | int pix_fmt; | ||
199 | |||
200 | /* | ||
201 | * Determine which pixel format we're going to use. | ||
202 | */ | ||
203 | pix_fmt = determine_best_pix_fmt(var); | ||
204 | if (pix_fmt < 0) | ||
205 | return pix_fmt; | ||
206 | set_pix_fmt(var, pix_fmt); | ||
207 | fbi->pix_fmt = pix_fmt; | ||
208 | |||
209 | /* | ||
210 | * Basic geometry sanity checks. | ||
211 | */ | ||
212 | if (var->xoffset + var->xres > var->xres_virtual) | ||
213 | return -EINVAL; | ||
214 | if (var->yoffset + var->yres > var->yres_virtual) | ||
215 | return -EINVAL; | ||
216 | if (var->xres + var->right_margin + | ||
217 | var->hsync_len + var->left_margin > 2048) | ||
218 | return -EINVAL; | ||
219 | if (var->yres + var->lower_margin + | ||
220 | var->vsync_len + var->upper_margin > 2048) | ||
221 | return -EINVAL; | ||
222 | |||
223 | /* | ||
224 | * Check size of framebuffer. | ||
225 | */ | ||
226 | if (var->xres_virtual * var->yres_virtual * | ||
227 | (var->bits_per_pixel >> 3) > info->fix.smem_len) | ||
228 | return -EINVAL; | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * The hardware clock divider has an integer and a fractional | ||
235 | * stage: | ||
236 | * | ||
237 | * clk2 = clk_in / integer_divider | ||
238 | * clk_out = clk2 * (1 - (fractional_divider >> 12)) | ||
239 | * | ||
240 | * Calculate integer and fractional divider for given clk_in | ||
241 | * and clk_out. | ||
242 | */ | ||
243 | static void set_clock_divider(struct pxa168fb_info *fbi, | ||
244 | const struct fb_videomode *m) | ||
245 | { | ||
246 | int divider_int; | ||
247 | int needed_pixclk; | ||
248 | u64 div_result; | ||
249 | u32 x = 0; | ||
250 | |||
251 | /* | ||
252 | * Notice: The field pixclock is used by linux fb | ||
253 | * is in pixel second. E.g. struct fb_videomode & | ||
254 | * struct fb_var_screeninfo | ||
255 | */ | ||
256 | |||
257 | /* | ||
258 | * Check input values. | ||
259 | */ | ||
260 | if (!m || !m->pixclock || !m->refresh) { | ||
261 | dev_err(fbi->dev, "Input refresh or pixclock is wrong.\n"); | ||
262 | return; | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Using PLL/AXI clock. | ||
267 | */ | ||
268 | x = 0x80000000; | ||
269 | |||
270 | /* | ||
271 | * Calc divider according to refresh rate. | ||
272 | */ | ||
273 | div_result = 1000000000000ll; | ||
274 | do_div(div_result, m->pixclock); | ||
275 | needed_pixclk = (u32)div_result; | ||
276 | |||
277 | divider_int = clk_get_rate(fbi->clk) / needed_pixclk; | ||
278 | |||
279 | /* check whether divisor is too small. */ | ||
280 | if (divider_int < 2) { | ||
281 | dev_warn(fbi->dev, "Warning: clock source is too slow." | ||
282 | "Try smaller resolution\n"); | ||
283 | divider_int = 2; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * Set setting to reg. | ||
288 | */ | ||
289 | x |= divider_int; | ||
290 | writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV); | ||
291 | } | ||
292 | |||
293 | static void set_dma_control0(struct pxa168fb_info *fbi) | ||
294 | { | ||
295 | u32 x; | ||
296 | |||
297 | /* | ||
298 | * Set bit to enable graphics DMA. | ||
299 | */ | ||
300 | x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); | ||
301 | x |= fbi->active ? 0x00000100 : 0; | ||
302 | fbi->active = 0; | ||
303 | |||
304 | /* | ||
305 | * If we are in a pseudo-color mode, we need to enable | ||
306 | * palette lookup. | ||
307 | */ | ||
308 | if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR) | ||
309 | x |= 0x10000000; | ||
310 | |||
311 | /* | ||
312 | * Configure hardware pixel format. | ||
313 | */ | ||
314 | x &= ~(0xF << 16); | ||
315 | x |= (fbi->pix_fmt >> 1) << 16; | ||
316 | |||
317 | /* | ||
318 | * Check red and blue pixel swap. | ||
319 | * 1. source data swap | ||
320 | * 2. panel output data swap | ||
321 | */ | ||
322 | x &= ~(1 << 12); | ||
323 | x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12; | ||
324 | |||
325 | writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0); | ||
326 | } | ||
327 | |||
328 | static void set_dma_control1(struct pxa168fb_info *fbi, int sync) | ||
329 | { | ||
330 | u32 x; | ||
331 | |||
332 | /* | ||
333 | * Configure default bits: vsync triggers DMA, gated clock | ||
334 | * enable, power save enable, configure alpha registers to | ||
335 | * display 100% graphics, and set pixel command. | ||
336 | */ | ||
337 | x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1); | ||
338 | x |= 0x2032ff81; | ||
339 | |||
340 | /* | ||
341 | * We trigger DMA on the falling edge of vsync if vsync is | ||
342 | * active low, or on the rising edge if vsync is active high. | ||
343 | */ | ||
344 | if (!(sync & FB_SYNC_VERT_HIGH_ACT)) | ||
345 | x |= 0x08000000; | ||
346 | |||
347 | writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1); | ||
348 | } | ||
349 | |||
350 | static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset) | ||
351 | { | ||
352 | struct pxa168fb_info *fbi = info->par; | ||
353 | struct fb_var_screeninfo *var = &info->var; | ||
354 | int pixel_offset; | ||
355 | unsigned long addr; | ||
356 | |||
357 | pixel_offset = (yoffset * var->xres_virtual) + xoffset; | ||
358 | |||
359 | addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3)); | ||
360 | writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0); | ||
361 | } | ||
362 | |||
363 | static void set_dumb_panel_control(struct fb_info *info) | ||
364 | { | ||
365 | struct pxa168fb_info *fbi = info->par; | ||
366 | struct pxa168fb_mach_info *mi = fbi->dev->platform_data; | ||
367 | u32 x; | ||
368 | |||
369 | /* | ||
370 | * Preserve enable flag. | ||
371 | */ | ||
372 | x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001; | ||
373 | |||
374 | x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28; | ||
375 | x |= mi->gpio_output_data << 20; | ||
376 | x |= mi->gpio_output_mask << 12; | ||
377 | x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0; | ||
378 | x |= mi->invert_composite_blank ? 0x00000040 : 0; | ||
379 | x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0; | ||
380 | x |= mi->invert_pix_val_ena ? 0x00000010 : 0; | ||
381 | x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008; | ||
382 | x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004; | ||
383 | x |= mi->invert_pixclock ? 0x00000002 : 0; | ||
384 | |||
385 | writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
386 | } | ||
387 | |||
388 | static void set_dumb_screen_dimensions(struct fb_info *info) | ||
389 | { | ||
390 | struct pxa168fb_info *fbi = info->par; | ||
391 | struct fb_var_screeninfo *v = &info->var; | ||
392 | int x; | ||
393 | int y; | ||
394 | |||
395 | x = v->xres + v->right_margin + v->hsync_len + v->left_margin; | ||
396 | y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin; | ||
397 | |||
398 | writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL); | ||
399 | } | ||
400 | |||
401 | static int pxa168fb_set_par(struct fb_info *info) | ||
402 | { | ||
403 | struct pxa168fb_info *fbi = info->par; | ||
404 | struct fb_var_screeninfo *var = &info->var; | ||
405 | struct fb_videomode mode; | ||
406 | u32 x; | ||
407 | struct pxa168fb_mach_info *mi; | ||
408 | |||
409 | mi = fbi->dev->platform_data; | ||
410 | |||
411 | /* | ||
412 | * Set additional mode info. | ||
413 | */ | ||
414 | if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR) | ||
415 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
416 | else | ||
417 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
418 | info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; | ||
419 | info->fix.ypanstep = var->yres; | ||
420 | |||
421 | /* | ||
422 | * Disable panel output while we setup the display. | ||
423 | */ | ||
424 | x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
425 | writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
426 | |||
427 | /* | ||
428 | * Configure global panel parameters. | ||
429 | */ | ||
430 | writel((var->yres << 16) | var->xres, | ||
431 | fbi->reg_base + LCD_SPU_V_H_ACTIVE); | ||
432 | |||
433 | /* | ||
434 | * convet var to video mode | ||
435 | */ | ||
436 | fb_var_to_videomode(&mode, &info->var); | ||
437 | |||
438 | /* Calculate clock divisor. */ | ||
439 | set_clock_divider(fbi, &mode); | ||
440 | |||
441 | /* Configure dma ctrl regs. */ | ||
442 | set_dma_control0(fbi); | ||
443 | set_dma_control1(fbi, info->var.sync); | ||
444 | |||
445 | /* | ||
446 | * Configure graphics DMA parameters. | ||
447 | */ | ||
448 | x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH); | ||
449 | x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3); | ||
450 | writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH); | ||
451 | writel((var->yres << 16) | var->xres, | ||
452 | fbi->reg_base + LCD_SPU_GRA_HPXL_VLN); | ||
453 | writel((var->yres << 16) | var->xres, | ||
454 | fbi->reg_base + LCD_SPU_GZM_HPXL_VLN); | ||
455 | |||
456 | /* | ||
457 | * Configure dumb panel ctrl regs & timings. | ||
458 | */ | ||
459 | set_dumb_panel_control(info); | ||
460 | set_dumb_screen_dimensions(info); | ||
461 | |||
462 | writel((var->left_margin << 16) | var->right_margin, | ||
463 | fbi->reg_base + LCD_SPU_H_PORCH); | ||
464 | writel((var->upper_margin << 16) | var->lower_margin, | ||
465 | fbi->reg_base + LCD_SPU_V_PORCH); | ||
466 | |||
467 | /* | ||
468 | * Re-enable panel output. | ||
469 | */ | ||
470 | x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
471 | writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) | ||
477 | { | ||
478 | return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; | ||
479 | } | ||
480 | |||
481 | static u32 to_rgb(u16 red, u16 green, u16 blue) | ||
482 | { | ||
483 | red >>= 8; | ||
484 | green >>= 8; | ||
485 | blue >>= 8; | ||
486 | |||
487 | return (red << 16) | (green << 8) | blue; | ||
488 | } | ||
489 | |||
490 | static int | ||
491 | pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, | ||
492 | unsigned int blue, unsigned int trans, struct fb_info *info) | ||
493 | { | ||
494 | struct pxa168fb_info *fbi = info->par; | ||
495 | u32 val; | ||
496 | |||
497 | if (info->var.grayscale) | ||
498 | red = green = blue = (19595 * red + 38470 * green + | ||
499 | 7471 * blue) >> 16; | ||
500 | |||
501 | if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) { | ||
502 | val = chan_to_field(red, &info->var.red); | ||
503 | val |= chan_to_field(green, &info->var.green); | ||
504 | val |= chan_to_field(blue , &info->var.blue); | ||
505 | fbi->pseudo_palette[regno] = val; | ||
506 | } | ||
507 | |||
508 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) { | ||
509 | val = to_rgb(red, green, blue); | ||
510 | writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT); | ||
511 | writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL); | ||
512 | } | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static int pxa168fb_blank(int blank, struct fb_info *info) | ||
518 | { | ||
519 | struct pxa168fb_info *fbi = info->par; | ||
520 | |||
521 | fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1; | ||
522 | set_dumb_panel_control(info); | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int pxa168fb_pan_display(struct fb_var_screeninfo *var, | ||
528 | struct fb_info *info) | ||
529 | { | ||
530 | set_graphics_start(info, var->xoffset, var->yoffset); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id) | ||
536 | { | ||
537 | struct pxa168fb_info *fbi = dev_id; | ||
538 | u32 isr = readl(fbi->reg_base + SPU_IRQ_ISR); | ||
539 | |||
540 | if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) { | ||
541 | |||
542 | writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK), | ||
543 | fbi->reg_base + SPU_IRQ_ISR); | ||
544 | |||
545 | return IRQ_HANDLED; | ||
546 | } | ||
547 | return IRQ_NONE; | ||
548 | } | ||
549 | |||
550 | static struct fb_ops pxa168fb_ops = { | ||
551 | .owner = THIS_MODULE, | ||
552 | .fb_check_var = pxa168fb_check_var, | ||
553 | .fb_set_par = pxa168fb_set_par, | ||
554 | .fb_setcolreg = pxa168fb_setcolreg, | ||
555 | .fb_blank = pxa168fb_blank, | ||
556 | .fb_pan_display = pxa168fb_pan_display, | ||
557 | .fb_fillrect = cfb_fillrect, | ||
558 | .fb_copyarea = cfb_copyarea, | ||
559 | .fb_imageblit = cfb_imageblit, | ||
560 | }; | ||
561 | |||
562 | static int __init pxa168fb_init_mode(struct fb_info *info, | ||
563 | struct pxa168fb_mach_info *mi) | ||
564 | { | ||
565 | struct pxa168fb_info *fbi = info->par; | ||
566 | struct fb_var_screeninfo *var = &info->var; | ||
567 | int ret = 0; | ||
568 | u32 total_w, total_h, refresh; | ||
569 | u64 div_result; | ||
570 | const struct fb_videomode *m; | ||
571 | |||
572 | /* | ||
573 | * Set default value | ||
574 | */ | ||
575 | refresh = DEFAULT_REFRESH; | ||
576 | |||
577 | /* try to find best video mode. */ | ||
578 | m = fb_find_best_mode(&info->var, &info->modelist); | ||
579 | if (m) | ||
580 | fb_videomode_to_var(&info->var, m); | ||
581 | |||
582 | /* Init settings. */ | ||
583 | var->xres_virtual = var->xres; | ||
584 | var->yres_virtual = info->fix.smem_len / | ||
585 | (var->xres_virtual * (var->bits_per_pixel >> 3)); | ||
586 | dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n", | ||
587 | var->xres, var->yres); | ||
588 | |||
589 | /* correct pixclock. */ | ||
590 | total_w = var->xres + var->left_margin + var->right_margin + | ||
591 | var->hsync_len; | ||
592 | total_h = var->yres + var->upper_margin + var->lower_margin + | ||
593 | var->vsync_len; | ||
594 | |||
595 | div_result = 1000000000000ll; | ||
596 | do_div(div_result, total_w * total_h * refresh); | ||
597 | var->pixclock = (u32)div_result; | ||
598 | |||
599 | return ret; | ||
600 | } | ||
601 | |||
602 | static int __init pxa168fb_probe(struct platform_device *pdev) | ||
603 | { | ||
604 | struct pxa168fb_mach_info *mi; | ||
605 | struct fb_info *info = 0; | ||
606 | struct pxa168fb_info *fbi = 0; | ||
607 | struct resource *res; | ||
608 | struct clk *clk; | ||
609 | int irq, ret; | ||
610 | |||
611 | mi = pdev->dev.platform_data; | ||
612 | if (mi == NULL) { | ||
613 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
617 | clk = clk_get(&pdev->dev, "LCDCLK"); | ||
618 | if (IS_ERR(clk)) { | ||
619 | dev_err(&pdev->dev, "unable to get LCDCLK"); | ||
620 | return PTR_ERR(clk); | ||
621 | } | ||
622 | |||
623 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
624 | if (res == NULL) { | ||
625 | dev_err(&pdev->dev, "no IO memory defined\n"); | ||
626 | return -ENOENT; | ||
627 | } | ||
628 | |||
629 | irq = platform_get_irq(pdev, 0); | ||
630 | if (irq < 0) { | ||
631 | dev_err(&pdev->dev, "no IRQ defined\n"); | ||
632 | return -ENOENT; | ||
633 | } | ||
634 | |||
635 | info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev); | ||
636 | if (info == NULL) { | ||
637 | clk_put(clk); | ||
638 | return -ENOMEM; | ||
639 | } | ||
640 | |||
641 | /* Initialize private data */ | ||
642 | fbi = info->par; | ||
643 | fbi->info = info; | ||
644 | fbi->clk = clk; | ||
645 | fbi->dev = info->dev = &pdev->dev; | ||
646 | fbi->panel_rbswap = mi->panel_rbswap; | ||
647 | fbi->is_blanked = 0; | ||
648 | fbi->active = mi->active; | ||
649 | |||
650 | /* | ||
651 | * Initialise static fb parameters. | ||
652 | */ | ||
653 | info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | | ||
654 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | ||
655 | info->node = -1; | ||
656 | strlcpy(info->fix.id, mi->id, 16); | ||
657 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
658 | info->fix.type_aux = 0; | ||
659 | info->fix.xpanstep = 0; | ||
660 | info->fix.ypanstep = 0; | ||
661 | info->fix.ywrapstep = 0; | ||
662 | info->fix.mmio_start = res->start; | ||
663 | info->fix.mmio_len = res->end - res->start + 1; | ||
664 | info->fix.accel = FB_ACCEL_NONE; | ||
665 | info->fbops = &pxa168fb_ops; | ||
666 | info->pseudo_palette = fbi->pseudo_palette; | ||
667 | |||
668 | /* | ||
669 | * Map LCD controller registers. | ||
670 | */ | ||
671 | fbi->reg_base = ioremap_nocache(res->start, res->end - res->start); | ||
672 | if (fbi->reg_base == NULL) { | ||
673 | ret = -ENOMEM; | ||
674 | goto failed; | ||
675 | } | ||
676 | |||
677 | /* | ||
678 | * Allocate framebuffer memory. | ||
679 | */ | ||
680 | info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE); | ||
681 | |||
682 | info->screen_base = dma_alloc_writecombine(fbi->dev, info->fix.smem_len, | ||
683 | &fbi->fb_start_dma, GFP_KERNEL); | ||
684 | if (info->screen_base == NULL) { | ||
685 | ret = -ENOMEM; | ||
686 | goto failed; | ||
687 | } | ||
688 | |||
689 | info->fix.smem_start = (unsigned long)fbi->fb_start_dma; | ||
690 | |||
691 | /* | ||
692 | * Set video mode according to platform data. | ||
693 | */ | ||
694 | set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1); | ||
695 | |||
696 | fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist); | ||
697 | |||
698 | /* | ||
699 | * init video mode data. | ||
700 | */ | ||
701 | pxa168fb_init_mode(info, mi); | ||
702 | |||
703 | ret = pxa168fb_check_var(&info->var, info); | ||
704 | if (ret) | ||
705 | goto failed_free_fbmem; | ||
706 | |||
707 | /* | ||
708 | * Fill in sane defaults. | ||
709 | */ | ||
710 | ret = pxa168fb_check_var(&info->var, info); | ||
711 | if (ret) | ||
712 | goto failed; | ||
713 | |||
714 | /* | ||
715 | * enable controller clock | ||
716 | */ | ||
717 | clk_enable(fbi->clk); | ||
718 | |||
719 | pxa168fb_set_par(info); | ||
720 | |||
721 | /* | ||
722 | * Configure default register values. | ||
723 | */ | ||
724 | writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR); | ||
725 | writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL); | ||
726 | writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1); | ||
727 | writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN); | ||
728 | writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0); | ||
729 | writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1), | ||
730 | fbi->reg_base + LCD_SPU_SRAM_PARA1); | ||
731 | |||
732 | /* | ||
733 | * Allocate color map. | ||
734 | */ | ||
735 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { | ||
736 | ret = -ENOMEM; | ||
737 | goto failed_free_clk; | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | * Register irq handler. | ||
742 | */ | ||
743 | ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED, | ||
744 | info->fix.id, fbi); | ||
745 | if (ret < 0) { | ||
746 | dev_err(&pdev->dev, "unable to request IRQ\n"); | ||
747 | ret = -ENXIO; | ||
748 | goto failed_free_cmap; | ||
749 | } | ||
750 | |||
751 | /* | ||
752 | * Enable GFX interrupt | ||
753 | */ | ||
754 | writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA); | ||
755 | |||
756 | /* | ||
757 | * Register framebuffer. | ||
758 | */ | ||
759 | ret = register_framebuffer(info); | ||
760 | if (ret < 0) { | ||
761 | dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret); | ||
762 | ret = -ENXIO; | ||
763 | goto failed_free_irq; | ||
764 | } | ||
765 | |||
766 | platform_set_drvdata(pdev, fbi); | ||
767 | return 0; | ||
768 | |||
769 | failed_free_irq: | ||
770 | free_irq(irq, fbi); | ||
771 | failed_free_cmap: | ||
772 | fb_dealloc_cmap(&info->cmap); | ||
773 | failed_free_clk: | ||
774 | clk_disable(fbi->clk); | ||
775 | failed_free_fbmem: | ||
776 | dma_free_coherent(fbi->dev, info->fix.smem_len, | ||
777 | info->screen_base, fbi->fb_start_dma); | ||
778 | failed: | ||
779 | kfree(info); | ||
780 | clk_put(clk); | ||
781 | |||
782 | dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret); | ||
783 | return ret; | ||
784 | } | ||
785 | |||
786 | static struct platform_driver pxa168fb_driver = { | ||
787 | .driver = { | ||
788 | .name = "pxa168-fb", | ||
789 | .owner = THIS_MODULE, | ||
790 | }, | ||
791 | .probe = pxa168fb_probe, | ||
792 | }; | ||
793 | |||
794 | static int __devinit pxa168fb_init(void) | ||
795 | { | ||
796 | return platform_driver_register(&pxa168fb_driver); | ||
797 | } | ||
798 | module_init(pxa168fb_init); | ||
799 | |||
800 | MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " | ||
801 | "Green Wan <gwan@marvell.com>"); | ||
802 | MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); | ||
803 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h new file mode 100644 index 000000000000..eee09279c524 --- /dev/null +++ b/drivers/video/pxa168fb.h | |||
@@ -0,0 +1,558 @@ | |||
1 | #ifndef __PXA168FB_H__ | ||
2 | #define __PXA168FB_H__ | ||
3 | |||
4 | /* ------------< LCD register >------------ */ | ||
5 | /* Video Frame 0&1 start address registers */ | ||
6 | #define LCD_SPU_DMA_START_ADDR_Y0 0x00C0 | ||
7 | #define LCD_SPU_DMA_START_ADDR_U0 0x00C4 | ||
8 | #define LCD_SPU_DMA_START_ADDR_V0 0x00C8 | ||
9 | #define LCD_CFG_DMA_START_ADDR_0 0x00CC /* Cmd address */ | ||
10 | #define LCD_SPU_DMA_START_ADDR_Y1 0x00D0 | ||
11 | #define LCD_SPU_DMA_START_ADDR_U1 0x00D4 | ||
12 | #define LCD_SPU_DMA_START_ADDR_V1 0x00D8 | ||
13 | #define LCD_CFG_DMA_START_ADDR_1 0x00DC /* Cmd address */ | ||
14 | |||
15 | /* YC & UV Pitch */ | ||
16 | #define LCD_SPU_DMA_PITCH_YC 0x00E0 | ||
17 | #define SPU_DMA_PITCH_C(c) ((c) << 16) | ||
18 | #define SPU_DMA_PITCH_Y(y) (y) | ||
19 | #define LCD_SPU_DMA_PITCH_UV 0x00E4 | ||
20 | #define SPU_DMA_PITCH_V(v) ((v) << 16) | ||
21 | #define SPU_DMA_PITCH_U(u) (u) | ||
22 | |||
23 | /* Video Starting Point on Screen Register */ | ||
24 | #define LCD_SPUT_DMA_OVSA_HPXL_VLN 0x00E8 | ||
25 | #define CFG_DMA_OVSA_VLN(y) ((y) << 16) /* 0~0xfff */ | ||
26 | #define CFG_DMA_OVSA_HPXL(x) (x) /* 0~0xfff */ | ||
27 | |||
28 | /* Video Size Register */ | ||
29 | #define LCD_SPU_DMA_HPXL_VLN 0x00EC | ||
30 | #define CFG_DMA_VLN(y) ((y) << 16) | ||
31 | #define CFG_DMA_HPXL(x) (x) | ||
32 | |||
33 | /* Video Size After zooming Register */ | ||
34 | #define LCD_SPU_DZM_HPXL_VLN 0x00F0 | ||
35 | #define CFG_DZM_VLN(y) ((y) << 16) | ||
36 | #define CFG_DZM_HPXL(x) (x) | ||
37 | |||
38 | /* Graphic Frame 0&1 Starting Address Register */ | ||
39 | #define LCD_CFG_GRA_START_ADDR0 0x00F4 | ||
40 | #define LCD_CFG_GRA_START_ADDR1 0x00F8 | ||
41 | |||
42 | /* Graphic Frame Pitch */ | ||
43 | #define LCD_CFG_GRA_PITCH 0x00FC | ||
44 | |||
45 | /* Graphic Starting Point on Screen Register */ | ||
46 | #define LCD_SPU_GRA_OVSA_HPXL_VLN 0x0100 | ||
47 | #define CFG_GRA_OVSA_VLN(y) ((y) << 16) | ||
48 | #define CFG_GRA_OVSA_HPXL(x) (x) | ||
49 | |||
50 | /* Graphic Size Register */ | ||
51 | #define LCD_SPU_GRA_HPXL_VLN 0x0104 | ||
52 | #define CFG_GRA_VLN(y) ((y) << 16) | ||
53 | #define CFG_GRA_HPXL(x) (x) | ||
54 | |||
55 | /* Graphic Size after Zooming Register */ | ||
56 | #define LCD_SPU_GZM_HPXL_VLN 0x0108 | ||
57 | #define CFG_GZM_VLN(y) ((y) << 16) | ||
58 | #define CFG_GZM_HPXL(x) (x) | ||
59 | |||
60 | /* HW Cursor Starting Point on Screen Register */ | ||
61 | #define LCD_SPU_HWC_OVSA_HPXL_VLN 0x010C | ||
62 | #define CFG_HWC_OVSA_VLN(y) ((y) << 16) | ||
63 | #define CFG_HWC_OVSA_HPXL(x) (x) | ||
64 | |||
65 | /* HW Cursor Size */ | ||
66 | #define LCD_SPU_HWC_HPXL_VLN 0x0110 | ||
67 | #define CFG_HWC_VLN(y) ((y) << 16) | ||
68 | #define CFG_HWC_HPXL(x) (x) | ||
69 | |||
70 | /* Total Screen Size Register */ | ||
71 | #define LCD_SPUT_V_H_TOTAL 0x0114 | ||
72 | #define CFG_V_TOTAL(y) ((y) << 16) | ||
73 | #define CFG_H_TOTAL(x) (x) | ||
74 | |||
75 | /* Total Screen Active Size Register */ | ||
76 | #define LCD_SPU_V_H_ACTIVE 0x0118 | ||
77 | #define CFG_V_ACTIVE(y) ((y) << 16) | ||
78 | #define CFG_H_ACTIVE(x) (x) | ||
79 | |||
80 | /* Screen H&V Porch Register */ | ||
81 | #define LCD_SPU_H_PORCH 0x011C | ||
82 | #define CFG_H_BACK_PORCH(b) ((b) << 16) | ||
83 | #define CFG_H_FRONT_PORCH(f) (f) | ||
84 | #define LCD_SPU_V_PORCH 0x0120 | ||
85 | #define CFG_V_BACK_PORCH(b) ((b) << 16) | ||
86 | #define CFG_V_FRONT_PORCH(f) (f) | ||
87 | |||
88 | /* Screen Blank Color Register */ | ||
89 | #define LCD_SPU_BLANKCOLOR 0x0124 | ||
90 | #define CFG_BLANKCOLOR_MASK 0x00FFFFFF | ||
91 | #define CFG_BLANKCOLOR_R_MASK 0x000000FF | ||
92 | #define CFG_BLANKCOLOR_G_MASK 0x0000FF00 | ||
93 | #define CFG_BLANKCOLOR_B_MASK 0x00FF0000 | ||
94 | |||
95 | /* HW Cursor Color 1&2 Register */ | ||
96 | #define LCD_SPU_ALPHA_COLOR1 0x0128 | ||
97 | #define CFG_HWC_COLOR1 0x00FFFFFF | ||
98 | #define CFG_HWC_COLOR1_R(red) ((red) << 16) | ||
99 | #define CFG_HWC_COLOR1_G(green) ((green) << 8) | ||
100 | #define CFG_HWC_COLOR1_B(blue) (blue) | ||
101 | #define CFG_HWC_COLOR1_R_MASK 0x000000FF | ||
102 | #define CFG_HWC_COLOR1_G_MASK 0x0000FF00 | ||
103 | #define CFG_HWC_COLOR1_B_MASK 0x00FF0000 | ||
104 | #define LCD_SPU_ALPHA_COLOR2 0x012C | ||
105 | #define CFG_HWC_COLOR2 0x00FFFFFF | ||
106 | #define CFG_HWC_COLOR2_R_MASK 0x000000FF | ||
107 | #define CFG_HWC_COLOR2_G_MASK 0x0000FF00 | ||
108 | #define CFG_HWC_COLOR2_B_MASK 0x00FF0000 | ||
109 | |||
110 | /* Video YUV Color Key Control */ | ||
111 | #define LCD_SPU_COLORKEY_Y 0x0130 | ||
112 | #define CFG_CKEY_Y2(y2) ((y2) << 24) | ||
113 | #define CFG_CKEY_Y2_MASK 0xFF000000 | ||
114 | #define CFG_CKEY_Y1(y1) ((y1) << 16) | ||
115 | #define CFG_CKEY_Y1_MASK 0x00FF0000 | ||
116 | #define CFG_CKEY_Y(y) ((y) << 8) | ||
117 | #define CFG_CKEY_Y_MASK 0x0000FF00 | ||
118 | #define CFG_ALPHA_Y(y) (y) | ||
119 | #define CFG_ALPHA_Y_MASK 0x000000FF | ||
120 | #define LCD_SPU_COLORKEY_U 0x0134 | ||
121 | #define CFG_CKEY_U2(u2) ((u2) << 24) | ||
122 | #define CFG_CKEY_U2_MASK 0xFF000000 | ||
123 | #define CFG_CKEY_U1(u1) ((u1) << 16) | ||
124 | #define CFG_CKEY_U1_MASK 0x00FF0000 | ||
125 | #define CFG_CKEY_U(u) ((u) << 8) | ||
126 | #define CFG_CKEY_U_MASK 0x0000FF00 | ||
127 | #define CFG_ALPHA_U(u) (u) | ||
128 | #define CFG_ALPHA_U_MASK 0x000000FF | ||
129 | #define LCD_SPU_COLORKEY_V 0x0138 | ||
130 | #define CFG_CKEY_V2(v2) ((v2) << 24) | ||
131 | #define CFG_CKEY_V2_MASK 0xFF000000 | ||
132 | #define CFG_CKEY_V1(v1) ((v1) << 16) | ||
133 | #define CFG_CKEY_V1_MASK 0x00FF0000 | ||
134 | #define CFG_CKEY_V(v) ((v) << 8) | ||
135 | #define CFG_CKEY_V_MASK 0x0000FF00 | ||
136 | #define CFG_ALPHA_V(v) (v) | ||
137 | #define CFG_ALPHA_V_MASK 0x000000FF | ||
138 | |||
139 | /* SPI Read Data Register */ | ||
140 | #define LCD_SPU_SPI_RXDATA 0x0140 | ||
141 | |||
142 | /* Smart Panel Read Data Register */ | ||
143 | #define LCD_SPU_ISA_RSDATA 0x0144 | ||
144 | #define ISA_RXDATA_16BIT_1_DATA_MASK 0x000000FF | ||
145 | #define ISA_RXDATA_16BIT_2_DATA_MASK 0x0000FF00 | ||
146 | #define ISA_RXDATA_16BIT_3_DATA_MASK 0x00FF0000 | ||
147 | #define ISA_RXDATA_16BIT_4_DATA_MASK 0xFF000000 | ||
148 | #define ISA_RXDATA_32BIT_1_DATA_MASK 0x00FFFFFF | ||
149 | |||
150 | /* HWC SRAM Read Data Register */ | ||
151 | #define LCD_SPU_HWC_RDDAT 0x0158 | ||
152 | |||
153 | /* Gamma Table SRAM Read Data Register */ | ||
154 | #define LCD_SPU_GAMMA_RDDAT 0x015c | ||
155 | #define CFG_GAMMA_RDDAT_MASK 0x000000FF | ||
156 | |||
157 | /* Palette Table SRAM Read Data Register */ | ||
158 | #define LCD_SPU_PALETTE_RDDAT 0x0160 | ||
159 | #define CFG_PALETTE_RDDAT_MASK 0x00FFFFFF | ||
160 | |||
161 | /* I/O Pads Input Read Only Register */ | ||
162 | #define LCD_SPU_IOPAD_IN 0x0178 | ||
163 | #define CFG_IOPAD_IN_MASK 0x0FFFFFFF | ||
164 | |||
165 | /* Reserved Read Only Registers */ | ||
166 | #define LCD_CFG_RDREG5F 0x017C | ||
167 | #define IRE_FRAME_CNT_MASK 0x000000C0 | ||
168 | #define IPE_FRAME_CNT_MASK 0x00000030 | ||
169 | #define GRA_FRAME_CNT_MASK 0x0000000C /* Graphic */ | ||
170 | #define DMA_FRAME_CNT_MASK 0x00000003 /* Video */ | ||
171 | |||
172 | /* SPI Control Register. */ | ||
173 | #define LCD_SPU_SPI_CTRL 0x0180 | ||
174 | #define CFG_SCLKCNT(div) ((div) << 24) /* 0xFF~0x2 */ | ||
175 | #define CFG_SCLKCNT_MASK 0xFF000000 | ||
176 | #define CFG_RXBITS(rx) ((rx) << 16) /* 0x1F~0x1 */ | ||
177 | #define CFG_RXBITS_MASK 0x00FF0000 | ||
178 | #define CFG_TXBITS(tx) ((tx) << 8) /* 0x1F~0x1 */ | ||
179 | #define CFG_TXBITS_MASK 0x0000FF00 | ||
180 | #define CFG_CLKINV(clk) ((clk) << 7) | ||
181 | #define CFG_CLKINV_MASK 0x00000080 | ||
182 | #define CFG_KEEPXFER(transfer) ((transfer) << 6) | ||
183 | #define CFG_KEEPXFER_MASK 0x00000040 | ||
184 | #define CFG_RXBITSTO0(rx) ((rx) << 5) | ||
185 | #define CFG_RXBITSTO0_MASK 0x00000020 | ||
186 | #define CFG_TXBITSTO0(tx) ((tx) << 4) | ||
187 | #define CFG_TXBITSTO0_MASK 0x00000010 | ||
188 | #define CFG_SPI_ENA(spi) ((spi) << 3) | ||
189 | #define CFG_SPI_ENA_MASK 0x00000008 | ||
190 | #define CFG_SPI_SEL(spi) ((spi) << 2) | ||
191 | #define CFG_SPI_SEL_MASK 0x00000004 | ||
192 | #define CFG_SPI_3W4WB(wire) ((wire) << 1) | ||
193 | #define CFG_SPI_3W4WB_MASK 0x00000002 | ||
194 | #define CFG_SPI_START(start) (start) | ||
195 | #define CFG_SPI_START_MASK 0x00000001 | ||
196 | |||
197 | /* SPI Tx Data Register */ | ||
198 | #define LCD_SPU_SPI_TXDATA 0x0184 | ||
199 | |||
200 | /* | ||
201 | 1. Smart Pannel 8-bit Bus Control Register. | ||
202 | 2. AHB Slave Path Data Port Register | ||
203 | */ | ||
204 | #define LCD_SPU_SMPN_CTRL 0x0188 | ||
205 | |||
206 | /* DMA Control 0 Register */ | ||
207 | #define LCD_SPU_DMA_CTRL0 0x0190 | ||
208 | #define CFG_NOBLENDING(nb) ((nb) << 31) | ||
209 | #define CFG_NOBLENDING_MASK 0x80000000 | ||
210 | #define CFG_GAMMA_ENA(gn) ((gn) << 30) | ||
211 | #define CFG_GAMMA_ENA_MASK 0x40000000 | ||
212 | #define CFG_CBSH_ENA(cn) ((cn) << 29) | ||
213 | #define CFG_CBSH_ENA_MASK 0x20000000 | ||
214 | #define CFG_PALETTE_ENA(pn) ((pn) << 28) | ||
215 | #define CFG_PALETTE_ENA_MASK 0x10000000 | ||
216 | #define CFG_ARBFAST_ENA(an) ((an) << 27) | ||
217 | #define CFG_ARBFAST_ENA_MASK 0x08000000 | ||
218 | #define CFG_HWC_1BITMOD(mode) ((mode) << 26) | ||
219 | #define CFG_HWC_1BITMOD_MASK 0x04000000 | ||
220 | #define CFG_HWC_1BITENA(mn) ((mn) << 25) | ||
221 | #define CFG_HWC_1BITENA_MASK 0x02000000 | ||
222 | #define CFG_HWC_ENA(cn) ((cn) << 24) | ||
223 | #define CFG_HWC_ENA_MASK 0x01000000 | ||
224 | #define CFG_DMAFORMAT(dmaformat) ((dmaformat) << 20) | ||
225 | #define CFG_DMAFORMAT_MASK 0x00F00000 | ||
226 | #define CFG_GRAFORMAT(graformat) ((graformat) << 16) | ||
227 | #define CFG_GRAFORMAT_MASK 0x000F0000 | ||
228 | /* for graphic part */ | ||
229 | #define CFG_GRA_FTOGGLE(toggle) ((toggle) << 15) | ||
230 | #define CFG_GRA_FTOGGLE_MASK 0x00008000 | ||
231 | #define CFG_GRA_HSMOOTH(smooth) ((smooth) << 14) | ||
232 | #define CFG_GRA_HSMOOTH_MASK 0x00004000 | ||
233 | #define CFG_GRA_TSTMODE(test) ((test) << 13) | ||
234 | #define CFG_GRA_TSTMODE_MASK 0x00002000 | ||
235 | #define CFG_GRA_SWAPRB(swap) ((swap) << 12) | ||
236 | #define CFG_GRA_SWAPRB_MASK 0x00001000 | ||
237 | #define CFG_GRA_SWAPUV(swap) ((swap) << 11) | ||
238 | #define CFG_GRA_SWAPUV_MASK 0x00000800 | ||
239 | #define CFG_GRA_SWAPYU(swap) ((swap) << 10) | ||
240 | #define CFG_GRA_SWAPYU_MASK 0x00000400 | ||
241 | #define CFG_YUV2RGB_GRA(cvrt) ((cvrt) << 9) | ||
242 | #define CFG_YUV2RGB_GRA_MASK 0x00000200 | ||
243 | #define CFG_GRA_ENA(gra) ((gra) << 8) | ||
244 | #define CFG_GRA_ENA_MASK 0x00000100 | ||
245 | /* for video part */ | ||
246 | #define CFG_DMA_FTOGGLE(toggle) ((toggle) << 7) | ||
247 | #define CFG_DMA_FTOGGLE_MASK 0x00000080 | ||
248 | #define CFG_DMA_HSMOOTH(smooth) ((smooth) << 6) | ||
249 | #define CFG_DMA_HSMOOTH_MASK 0x00000040 | ||
250 | #define CFG_DMA_TSTMODE(test) ((test) << 5) | ||
251 | #define CFG_DMA_TSTMODE_MASK 0x00000020 | ||
252 | #define CFG_DMA_SWAPRB(swap) ((swap) << 4) | ||
253 | #define CFG_DMA_SWAPRB_MASK 0x00000010 | ||
254 | #define CFG_DMA_SWAPUV(swap) ((swap) << 3) | ||
255 | #define CFG_DMA_SWAPUV_MASK 0x00000008 | ||
256 | #define CFG_DMA_SWAPYU(swap) ((swap) << 2) | ||
257 | #define CFG_DMA_SWAPYU_MASK 0x00000004 | ||
258 | #define CFG_DMA_SWAP_MASK 0x0000001C | ||
259 | #define CFG_YUV2RGB_DMA(cvrt) ((cvrt) << 1) | ||
260 | #define CFG_YUV2RGB_DMA_MASK 0x00000002 | ||
261 | #define CFG_DMA_ENA(video) (video) | ||
262 | #define CFG_DMA_ENA_MASK 0x00000001 | ||
263 | |||
264 | /* DMA Control 1 Register */ | ||
265 | #define LCD_SPU_DMA_CTRL1 0x0194 | ||
266 | #define CFG_FRAME_TRIG(trig) ((trig) << 31) | ||
267 | #define CFG_FRAME_TRIG_MASK 0x80000000 | ||
268 | #define CFG_VSYNC_TRIG(trig) ((trig) << 28) | ||
269 | #define CFG_VSYNC_TRIG_MASK 0x70000000 | ||
270 | #define CFG_VSYNC_INV(inv) ((inv) << 27) | ||
271 | #define CFG_VSYNC_INV_MASK 0x08000000 | ||
272 | #define CFG_COLOR_KEY_MODE(cmode) ((cmode) << 24) | ||
273 | #define CFG_COLOR_KEY_MASK 0x07000000 | ||
274 | #define CFG_CARRY(carry) ((carry) << 23) | ||
275 | #define CFG_CARRY_MASK 0x00800000 | ||
276 | #define CFG_LNBUF_ENA(lnbuf) ((lnbuf) << 22) | ||
277 | #define CFG_LNBUF_ENA_MASK 0x00400000 | ||
278 | #define CFG_GATED_ENA(gated) ((gated) << 21) | ||
279 | #define CFG_GATED_ENA_MASK 0x00200000 | ||
280 | #define CFG_PWRDN_ENA(power) ((power) << 20) | ||
281 | #define CFG_PWRDN_ENA_MASK 0x00100000 | ||
282 | #define CFG_DSCALE(dscale) ((dscale) << 18) | ||
283 | #define CFG_DSCALE_MASK 0x000C0000 | ||
284 | #define CFG_ALPHA_MODE(amode) ((amode) << 16) | ||
285 | #define CFG_ALPHA_MODE_MASK 0x00030000 | ||
286 | #define CFG_ALPHA(alpha) ((alpha) << 8) | ||
287 | #define CFG_ALPHA_MASK 0x0000FF00 | ||
288 | #define CFG_PXLCMD(pxlcmd) (pxlcmd) | ||
289 | #define CFG_PXLCMD_MASK 0x000000FF | ||
290 | |||
291 | /* SRAM Control Register */ | ||
292 | #define LCD_SPU_SRAM_CTRL 0x0198 | ||
293 | #define CFG_SRAM_INIT_WR_RD(mode) ((mode) << 14) | ||
294 | #define CFG_SRAM_INIT_WR_RD_MASK 0x0000C000 | ||
295 | #define CFG_SRAM_ADDR_LCDID(id) ((id) << 8) | ||
296 | #define CFG_SRAM_ADDR_LCDID_MASK 0x00000F00 | ||
297 | #define CFG_SRAM_ADDR(addr) (addr) | ||
298 | #define CFG_SRAM_ADDR_MASK 0x000000FF | ||
299 | |||
300 | /* SRAM Write Data Register */ | ||
301 | #define LCD_SPU_SRAM_WRDAT 0x019C | ||
302 | |||
303 | /* SRAM RTC/WTC Control Register */ | ||
304 | #define LCD_SPU_SRAM_PARA0 0x01A0 | ||
305 | |||
306 | /* SRAM Power Down Control Register */ | ||
307 | #define LCD_SPU_SRAM_PARA1 0x01A4 | ||
308 | #define CFG_CSB_256x32(hwc) ((hwc) << 15) /* HWC */ | ||
309 | #define CFG_CSB_256x32_MASK 0x00008000 | ||
310 | #define CFG_CSB_256x24(palette) ((palette) << 14) /* Palette */ | ||
311 | #define CFG_CSB_256x24_MASK 0x00004000 | ||
312 | #define CFG_CSB_256x8(gamma) ((gamma) << 13) /* Gamma */ | ||
313 | #define CFG_CSB_256x8_MASK 0x00002000 | ||
314 | #define CFG_PDWN256x32(pdwn) ((pdwn) << 7) /* HWC */ | ||
315 | #define CFG_PDWN256x32_MASK 0x00000080 | ||
316 | #define CFG_PDWN256x24(pdwn) ((pdwn) << 6) /* Palette */ | ||
317 | #define CFG_PDWN256x24_MASK 0x00000040 | ||
318 | #define CFG_PDWN256x8(pdwn) ((pdwn) << 5) /* Gamma */ | ||
319 | #define CFG_PDWN256x8_MASK 0x00000020 | ||
320 | #define CFG_PDWN32x32(pdwn) ((pdwn) << 3) | ||
321 | #define CFG_PDWN32x32_MASK 0x00000008 | ||
322 | #define CFG_PDWN16x66(pdwn) ((pdwn) << 2) | ||
323 | #define CFG_PDWN16x66_MASK 0x00000004 | ||
324 | #define CFG_PDWN32x66(pdwn) ((pdwn) << 1) | ||
325 | #define CFG_PDWN32x66_MASK 0x00000002 | ||
326 | #define CFG_PDWN64x66(pdwn) (pdwn) | ||
327 | #define CFG_PDWN64x66_MASK 0x00000001 | ||
328 | |||
329 | /* Smart or Dumb Panel Clock Divider */ | ||
330 | #define LCD_CFG_SCLK_DIV 0x01A8 | ||
331 | #define SCLK_SOURCE_SELECT(src) ((src) << 31) | ||
332 | #define SCLK_SOURCE_SELECT_MASK 0x80000000 | ||
333 | #define CLK_FRACDIV(frac) ((frac) << 16) | ||
334 | #define CLK_FRACDIV_MASK 0x0FFF0000 | ||
335 | #define CLK_INT_DIV(div) (div) | ||
336 | #define CLK_INT_DIV_MASK 0x0000FFFF | ||
337 | |||
338 | /* Video Contrast Register */ | ||
339 | #define LCD_SPU_CONTRAST 0x01AC | ||
340 | #define CFG_BRIGHTNESS(bright) ((bright) << 16) | ||
341 | #define CFG_BRIGHTNESS_MASK 0xFFFF0000 | ||
342 | #define CFG_CONTRAST(contrast) (contrast) | ||
343 | #define CFG_CONTRAST_MASK 0x0000FFFF | ||
344 | |||
345 | /* Video Saturation Register */ | ||
346 | #define LCD_SPU_SATURATION 0x01B0 | ||
347 | #define CFG_C_MULTS(mult) ((mult) << 16) | ||
348 | #define CFG_C_MULTS_MASK 0xFFFF0000 | ||
349 | #define CFG_SATURATION(sat) (sat) | ||
350 | #define CFG_SATURATION_MASK 0x0000FFFF | ||
351 | |||
352 | /* Video Hue Adjust Register */ | ||
353 | #define LCD_SPU_CBSH_HUE 0x01B4 | ||
354 | #define CFG_SIN0(sin0) ((sin0) << 16) | ||
355 | #define CFG_SIN0_MASK 0xFFFF0000 | ||
356 | #define CFG_COS0(con0) (con0) | ||
357 | #define CFG_COS0_MASK 0x0000FFFF | ||
358 | |||
359 | /* Dump LCD Panel Control Register */ | ||
360 | #define LCD_SPU_DUMB_CTRL 0x01B8 | ||
361 | #define CFG_DUMBMODE(mode) ((mode) << 28) | ||
362 | #define CFG_DUMBMODE_MASK 0xF0000000 | ||
363 | #define CFG_LCDGPIO_O(data) ((data) << 20) | ||
364 | #define CFG_LCDGPIO_O_MASK 0x0FF00000 | ||
365 | #define CFG_LCDGPIO_ENA(gpio) ((gpio) << 12) | ||
366 | #define CFG_LCDGPIO_ENA_MASK 0x000FF000 | ||
367 | #define CFG_BIAS_OUT(bias) ((bias) << 8) | ||
368 | #define CFG_BIAS_OUT_MASK 0x00000100 | ||
369 | #define CFG_REVERSE_RGB(rRGB) ((rRGB) << 7) | ||
370 | #define CFG_REVERSE_RGB_MASK 0x00000080 | ||
371 | #define CFG_INV_COMPBLANK(blank) ((blank) << 6) | ||
372 | #define CFG_INV_COMPBLANK_MASK 0x00000040 | ||
373 | #define CFG_INV_COMPSYNC(sync) ((sync) << 5) | ||
374 | #define CFG_INV_COMPSYNC_MASK 0x00000020 | ||
375 | #define CFG_INV_HENA(hena) ((hena) << 4) | ||
376 | #define CFG_INV_HENA_MASK 0x00000010 | ||
377 | #define CFG_INV_VSYNC(vsync) ((vsync) << 3) | ||
378 | #define CFG_INV_VSYNC_MASK 0x00000008 | ||
379 | #define CFG_INV_HSYNC(hsync) ((hsync) << 2) | ||
380 | #define CFG_INV_HSYNC_MASK 0x00000004 | ||
381 | #define CFG_INV_PCLK(pclk) ((pclk) << 1) | ||
382 | #define CFG_INV_PCLK_MASK 0x00000002 | ||
383 | #define CFG_DUMB_ENA(dumb) (dumb) | ||
384 | #define CFG_DUMB_ENA_MASK 0x00000001 | ||
385 | |||
386 | /* LCD I/O Pads Control Register */ | ||
387 | #define SPU_IOPAD_CONTROL 0x01BC | ||
388 | #define CFG_GRA_VM_ENA(vm) ((vm) << 15) /* gfx */ | ||
389 | #define CFG_GRA_VM_ENA_MASK 0x00008000 | ||
390 | #define CFG_DMA_VM_ENA(vm) ((vm) << 13) /* video */ | ||
391 | #define CFG_DMA_VM_ENA_MASK 0x00002000 | ||
392 | #define CFG_CMD_VM_ENA(vm) ((vm) << 13) | ||
393 | #define CFG_CMD_VM_ENA_MASK 0x00000800 | ||
394 | #define CFG_CSC(csc) ((csc) << 8) /* csc */ | ||
395 | #define CFG_CSC_MASK 0x00000300 | ||
396 | #define CFG_AXICTRL(axi) ((axi) << 4) | ||
397 | #define CFG_AXICTRL_MASK 0x000000F0 | ||
398 | #define CFG_IOPADMODE(iopad) (iopad) | ||
399 | #define CFG_IOPADMODE_MASK 0x0000000F | ||
400 | |||
401 | /* LCD Interrupt Control Register */ | ||
402 | #define SPU_IRQ_ENA 0x01C0 | ||
403 | #define DMA_FRAME_IRQ0_ENA(irq) ((irq) << 31) | ||
404 | #define DMA_FRAME_IRQ0_ENA_MASK 0x80000000 | ||
405 | #define DMA_FRAME_IRQ1_ENA(irq) ((irq) << 30) | ||
406 | #define DMA_FRAME_IRQ1_ENA_MASK 0x40000000 | ||
407 | #define DMA_FF_UNDERFLOW_ENA(ff) ((ff) << 29) | ||
408 | #define DMA_FF_UNDERFLOW_ENA_MASK 0x20000000 | ||
409 | #define GRA_FRAME_IRQ0_ENA(irq) ((irq) << 27) | ||
410 | #define GRA_FRAME_IRQ0_ENA_MASK 0x08000000 | ||
411 | #define GRA_FRAME_IRQ1_ENA(irq) ((irq) << 26) | ||
412 | #define GRA_FRAME_IRQ1_ENA_MASK 0x04000000 | ||
413 | #define GRA_FF_UNDERFLOW_ENA(ff) ((ff) << 25) | ||
414 | #define GRA_FF_UNDERFLOW_ENA_MASK 0x02000000 | ||
415 | #define VSYNC_IRQ_ENA(vsync_irq) ((vsync_irq) << 23) | ||
416 | #define VSYNC_IRQ_ENA_MASK 0x00800000 | ||
417 | #define DUMB_FRAMEDONE_ENA(fdone) ((fdone) << 22) | ||
418 | #define DUMB_FRAMEDONE_ENA_MASK 0x00400000 | ||
419 | #define TWC_FRAMEDONE_ENA(fdone) ((fdone) << 21) | ||
420 | #define TWC_FRAMEDONE_ENA_MASK 0x00200000 | ||
421 | #define HWC_FRAMEDONE_ENA(fdone) ((fdone) << 20) | ||
422 | #define HWC_FRAMEDONE_ENA_MASK 0x00100000 | ||
423 | #define SLV_IRQ_ENA(irq) ((irq) << 19) | ||
424 | #define SLV_IRQ_ENA_MASK 0x00080000 | ||
425 | #define SPI_IRQ_ENA(irq) ((irq) << 18) | ||
426 | #define SPI_IRQ_ENA_MASK 0x00040000 | ||
427 | #define PWRDN_IRQ_ENA(irq) ((irq) << 17) | ||
428 | #define PWRDN_IRQ_ENA_MASK 0x00020000 | ||
429 | #define ERR_IRQ_ENA(irq) ((irq) << 16) | ||
430 | #define ERR_IRQ_ENA_MASK 0x00010000 | ||
431 | #define CLEAN_SPU_IRQ_ISR(irq) (irq) | ||
432 | #define CLEAN_SPU_IRQ_ISR_MASK 0x0000FFFF | ||
433 | |||
434 | /* LCD Interrupt Status Register */ | ||
435 | #define SPU_IRQ_ISR 0x01C4 | ||
436 | #define DMA_FRAME_IRQ0(irq) ((irq) << 31) | ||
437 | #define DMA_FRAME_IRQ0_MASK 0x80000000 | ||
438 | #define DMA_FRAME_IRQ1(irq) ((irq) << 30) | ||
439 | #define DMA_FRAME_IRQ1_MASK 0x40000000 | ||
440 | #define DMA_FF_UNDERFLOW(ff) ((ff) << 29) | ||
441 | #define DMA_FF_UNDERFLOW_MASK 0x20000000 | ||
442 | #define GRA_FRAME_IRQ0(irq) ((irq) << 27) | ||
443 | #define GRA_FRAME_IRQ0_MASK 0x08000000 | ||
444 | #define GRA_FRAME_IRQ1(irq) ((irq) << 26) | ||
445 | #define GRA_FRAME_IRQ1_MASK 0x04000000 | ||
446 | #define GRA_FF_UNDERFLOW(ff) ((ff) << 25) | ||
447 | #define GRA_FF_UNDERFLOW_MASK 0x02000000 | ||
448 | #define VSYNC_IRQ(vsync_irq) ((vsync_irq) << 23) | ||
449 | #define VSYNC_IRQ_MASK 0x00800000 | ||
450 | #define DUMB_FRAMEDONE(fdone) ((fdone) << 22) | ||
451 | #define DUMB_FRAMEDONE_MASK 0x00400000 | ||
452 | #define TWC_FRAMEDONE(fdone) ((fdone) << 21) | ||
453 | #define TWC_FRAMEDONE_MASK 0x00200000 | ||
454 | #define HWC_FRAMEDONE(fdone) ((fdone) << 20) | ||
455 | #define HWC_FRAMEDONE_MASK 0x00100000 | ||
456 | #define SLV_IRQ(irq) ((irq) << 19) | ||
457 | #define SLV_IRQ_MASK 0x00080000 | ||
458 | #define SPI_IRQ(irq) ((irq) << 18) | ||
459 | #define SPI_IRQ_MASK 0x00040000 | ||
460 | #define PWRDN_IRQ(irq) ((irq) << 17) | ||
461 | #define PWRDN_IRQ_MASK 0x00020000 | ||
462 | #define ERR_IRQ(irq) ((irq) << 16) | ||
463 | #define ERR_IRQ_MASK 0x00010000 | ||
464 | /* read-only */ | ||
465 | #define DMA_FRAME_IRQ0_LEVEL_MASK 0x00008000 | ||
466 | #define DMA_FRAME_IRQ1_LEVEL_MASK 0x00004000 | ||
467 | #define DMA_FRAME_CNT_ISR_MASK 0x00003000 | ||
468 | #define GRA_FRAME_IRQ0_LEVEL_MASK 0x00000800 | ||
469 | #define GRA_FRAME_IRQ1_LEVEL_MASK 0x00000400 | ||
470 | #define GRA_FRAME_CNT_ISR_MASK 0x00000300 | ||
471 | #define VSYNC_IRQ_LEVEL_MASK 0x00000080 | ||
472 | #define DUMB_FRAMEDONE_LEVEL_MASK 0x00000040 | ||
473 | #define TWC_FRAMEDONE_LEVEL_MASK 0x00000020 | ||
474 | #define HWC_FRAMEDONE_LEVEL_MASK 0x00000010 | ||
475 | #define SLV_FF_EMPTY_MASK 0x00000008 | ||
476 | #define DMA_FF_ALLEMPTY_MASK 0x00000004 | ||
477 | #define GRA_FF_ALLEMPTY_MASK 0x00000002 | ||
478 | #define PWRDN_IRQ_LEVEL_MASK 0x00000001 | ||
479 | |||
480 | |||
481 | /* | ||
482 | * defined Video Memory Color format for DMA control 0 register | ||
483 | * DMA0 bit[23:20] | ||
484 | */ | ||
485 | #define VMODE_RGB565 0x0 | ||
486 | #define VMODE_RGB1555 0x1 | ||
487 | #define VMODE_RGB888PACKED 0x2 | ||
488 | #define VMODE_RGB888UNPACKED 0x3 | ||
489 | #define VMODE_RGBA888 0x4 | ||
490 | #define VMODE_YUV422PACKED 0x5 | ||
491 | #define VMODE_YUV422PLANAR 0x6 | ||
492 | #define VMODE_YUV420PLANAR 0x7 | ||
493 | #define VMODE_SMPNCMD 0x8 | ||
494 | #define VMODE_PALETTE4BIT 0x9 | ||
495 | #define VMODE_PALETTE8BIT 0xa | ||
496 | #define VMODE_RESERVED 0xb | ||
497 | |||
498 | /* | ||
499 | * defined Graphic Memory Color format for DMA control 0 register | ||
500 | * DMA0 bit[19:16] | ||
501 | */ | ||
502 | #define GMODE_RGB565 0x0 | ||
503 | #define GMODE_RGB1555 0x1 | ||
504 | #define GMODE_RGB888PACKED 0x2 | ||
505 | #define GMODE_RGB888UNPACKED 0x3 | ||
506 | #define GMODE_RGBA888 0x4 | ||
507 | #define GMODE_YUV422PACKED 0x5 | ||
508 | #define GMODE_YUV422PLANAR 0x6 | ||
509 | #define GMODE_YUV420PLANAR 0x7 | ||
510 | #define GMODE_SMPNCMD 0x8 | ||
511 | #define GMODE_PALETTE4BIT 0x9 | ||
512 | #define GMODE_PALETTE8BIT 0xa | ||
513 | #define GMODE_RESERVED 0xb | ||
514 | |||
515 | /* | ||
516 | * define for DMA control 1 register | ||
517 | */ | ||
518 | #define DMA1_FRAME_TRIG 31 /* bit location */ | ||
519 | #define DMA1_VSYNC_MODE 28 | ||
520 | #define DMA1_VSYNC_INV 27 | ||
521 | #define DMA1_CKEY 24 | ||
522 | #define DMA1_CARRY 23 | ||
523 | #define DMA1_LNBUF_ENA 22 | ||
524 | #define DMA1_GATED_ENA 21 | ||
525 | #define DMA1_PWRDN_ENA 20 | ||
526 | #define DMA1_DSCALE 18 | ||
527 | #define DMA1_ALPHA_MODE 16 | ||
528 | #define DMA1_ALPHA 08 | ||
529 | #define DMA1_PXLCMD 00 | ||
530 | |||
531 | /* | ||
532 | * defined for Configure Dumb Mode | ||
533 | * DUMB LCD Panel bit[31:28] | ||
534 | */ | ||
535 | #define DUMB16_RGB565_0 0x0 | ||
536 | #define DUMB16_RGB565_1 0x1 | ||
537 | #define DUMB18_RGB666_0 0x2 | ||
538 | #define DUMB18_RGB666_1 0x3 | ||
539 | #define DUMB12_RGB444_0 0x4 | ||
540 | #define DUMB12_RGB444_1 0x5 | ||
541 | #define DUMB24_RGB888_0 0x6 | ||
542 | #define DUMB_BLANK 0x7 | ||
543 | |||
544 | /* | ||
545 | * defined for Configure I/O Pin Allocation Mode | ||
546 | * LCD LCD I/O Pads control register bit[3:0] | ||
547 | */ | ||
548 | #define IOPAD_DUMB24 0x0 | ||
549 | #define IOPAD_DUMB18SPI 0x1 | ||
550 | #define IOPAD_DUMB18GPIO 0x2 | ||
551 | #define IOPAD_DUMB16SPI 0x3 | ||
552 | #define IOPAD_DUMB16GPIO 0x4 | ||
553 | #define IOPAD_DUMB12 0x5 | ||
554 | #define IOPAD_SMART18SPI 0x6 | ||
555 | #define IOPAD_SMART16SPI 0x7 | ||
556 | #define IOPAD_SMART8BOTH 0x8 | ||
557 | |||
558 | #endif /* __PXA168FB_H__ */ | ||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 5eb8f21da82e..5744cac4864b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -231,14 +231,14 @@ config DAVINCI_WATCHDOG | |||
231 | NOTE: once enabled, this timer cannot be disabled. | 231 | NOTE: once enabled, this timer cannot be disabled. |
232 | Say N if you are unsure. | 232 | Say N if you are unsure. |
233 | 233 | ||
234 | config ORION5X_WATCHDOG | 234 | config ORION_WATCHDOG |
235 | tristate "Orion5x watchdog" | 235 | tristate "Orion watchdog" |
236 | depends on ARCH_ORION5X | 236 | depends on ARCH_ORION5X || ARCH_KIRKWOOD |
237 | help | 237 | help |
238 | Say Y here if to include support for the watchdog timer | 238 | Say Y here if to include support for the watchdog timer |
239 | in the Orion5x ARM SoCs. | 239 | in the Marvell Orion5x and Kirkwood ARM SoCs. |
240 | To compile this driver as a module, choose M here: the | 240 | To compile this driver as a module, choose M here: the |
241 | module will be called orion5x_wdt. | 241 | module will be called orion_wdt. |
242 | 242 | ||
243 | # AVR32 Architecture | 243 | # AVR32 Architecture |
244 | 244 | ||
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 7f8c56b14f58..c3afa14d5be1 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -40,7 +40,7 @@ obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o | |||
40 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o | 40 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o |
41 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o | 41 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o |
42 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o | 42 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o |
43 | obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o | 43 | obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o |
44 | 44 | ||
45 | # AVR32 Architecture | 45 | # AVR32 Architecture |
46 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 46 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion_wdt.c index 2cde568e4fb0..2d9fb96a9ee9 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion_wdt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/watchdog/orion5x_wdt.c | 2 | * drivers/watchdog/orion_wdt.c |
3 | * | 3 | * |
4 | * Watchdog driver for Orion5x processors | 4 | * Watchdog driver for Orion/Kirkwood processors |
5 | * | 5 | * |
6 | * Author: Sylver Bruneau <sylver.bruneau@googlemail.com> | 6 | * Author: Sylver Bruneau <sylver.bruneau@googlemail.com> |
7 | * | 7 | * |
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <mach/bridge-regs.h> | 25 | #include <mach/bridge-regs.h> |
26 | #include <plat/orion5x_wdt.h> | 26 | #include <plat/orion_wdt.h> |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * Watchdog timer block registers. | 29 | * Watchdog timer block registers. |
@@ -43,7 +43,7 @@ static unsigned int wdt_tclk; | |||
43 | static unsigned long wdt_status; | 43 | static unsigned long wdt_status; |
44 | static spinlock_t wdt_lock; | 44 | static spinlock_t wdt_lock; |
45 | 45 | ||
46 | static void orion5x_wdt_ping(void) | 46 | static void orion_wdt_ping(void) |
47 | { | 47 | { |
48 | spin_lock(&wdt_lock); | 48 | spin_lock(&wdt_lock); |
49 | 49 | ||
@@ -53,7 +53,7 @@ static void orion5x_wdt_ping(void) | |||
53 | spin_unlock(&wdt_lock); | 53 | spin_unlock(&wdt_lock); |
54 | } | 54 | } |
55 | 55 | ||
56 | static void orion5x_wdt_enable(void) | 56 | static void orion_wdt_enable(void) |
57 | { | 57 | { |
58 | u32 reg; | 58 | u32 reg; |
59 | 59 | ||
@@ -73,23 +73,23 @@ static void orion5x_wdt_enable(void) | |||
73 | writel(reg, TIMER_CTRL); | 73 | writel(reg, TIMER_CTRL); |
74 | 74 | ||
75 | /* Enable reset on watchdog */ | 75 | /* Enable reset on watchdog */ |
76 | reg = readl(CPU_RESET_MASK); | 76 | reg = readl(RSTOUTn_MASK); |
77 | reg |= WDT_RESET; | 77 | reg |= WDT_RESET_OUT_EN; |
78 | writel(reg, CPU_RESET_MASK); | 78 | writel(reg, RSTOUTn_MASK); |
79 | 79 | ||
80 | spin_unlock(&wdt_lock); | 80 | spin_unlock(&wdt_lock); |
81 | } | 81 | } |
82 | 82 | ||
83 | static void orion5x_wdt_disable(void) | 83 | static void orion_wdt_disable(void) |
84 | { | 84 | { |
85 | u32 reg; | 85 | u32 reg; |
86 | 86 | ||
87 | spin_lock(&wdt_lock); | 87 | spin_lock(&wdt_lock); |
88 | 88 | ||
89 | /* Disable reset on watchdog */ | 89 | /* Disable reset on watchdog */ |
90 | reg = readl(CPU_RESET_MASK); | 90 | reg = readl(RSTOUTn_MASK); |
91 | reg &= ~WDT_RESET; | 91 | reg &= ~WDT_RESET_OUT_EN; |
92 | writel(reg, CPU_RESET_MASK); | 92 | writel(reg, RSTOUTn_MASK); |
93 | 93 | ||
94 | /* Disable watchdog timer */ | 94 | /* Disable watchdog timer */ |
95 | reg = readl(TIMER_CTRL); | 95 | reg = readl(TIMER_CTRL); |
@@ -99,7 +99,7 @@ static void orion5x_wdt_disable(void) | |||
99 | spin_unlock(&wdt_lock); | 99 | spin_unlock(&wdt_lock); |
100 | } | 100 | } |
101 | 101 | ||
102 | static int orion5x_wdt_get_timeleft(int *time_left) | 102 | static int orion_wdt_get_timeleft(int *time_left) |
103 | { | 103 | { |
104 | spin_lock(&wdt_lock); | 104 | spin_lock(&wdt_lock); |
105 | *time_left = readl(WDT_VAL) / wdt_tclk; | 105 | *time_left = readl(WDT_VAL) / wdt_tclk; |
@@ -107,16 +107,16 @@ static int orion5x_wdt_get_timeleft(int *time_left) | |||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | static int orion5x_wdt_open(struct inode *inode, struct file *file) | 110 | static int orion_wdt_open(struct inode *inode, struct file *file) |
111 | { | 111 | { |
112 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | 112 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) |
113 | return -EBUSY; | 113 | return -EBUSY; |
114 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 114 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
115 | orion5x_wdt_enable(); | 115 | orion_wdt_enable(); |
116 | return nonseekable_open(inode, file); | 116 | return nonseekable_open(inode, file); |
117 | } | 117 | } |
118 | 118 | ||
119 | static ssize_t orion5x_wdt_write(struct file *file, const char *data, | 119 | static ssize_t orion_wdt_write(struct file *file, const char *data, |
120 | size_t len, loff_t *ppos) | 120 | size_t len, loff_t *ppos) |
121 | { | 121 | { |
122 | if (len) { | 122 | if (len) { |
@@ -133,18 +133,18 @@ static ssize_t orion5x_wdt_write(struct file *file, const char *data, | |||
133 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | 133 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); |
134 | } | 134 | } |
135 | } | 135 | } |
136 | orion5x_wdt_ping(); | 136 | orion_wdt_ping(); |
137 | } | 137 | } |
138 | return len; | 138 | return len; |
139 | } | 139 | } |
140 | 140 | ||
141 | static int orion5x_wdt_settimeout(int new_time) | 141 | static int orion_wdt_settimeout(int new_time) |
142 | { | 142 | { |
143 | if ((new_time <= 0) || (new_time > wdt_max_duration)) | 143 | if ((new_time <= 0) || (new_time > wdt_max_duration)) |
144 | return -EINVAL; | 144 | return -EINVAL; |
145 | 145 | ||
146 | /* Set new watchdog time to be used when | 146 | /* Set new watchdog time to be used when |
147 | * orion5x_wdt_enable() or orion5x_wdt_ping() is called. */ | 147 | * orion_wdt_enable() or orion_wdt_ping() is called. */ |
148 | heartbeat = new_time; | 148 | heartbeat = new_time; |
149 | return 0; | 149 | return 0; |
150 | } | 150 | } |
@@ -152,10 +152,10 @@ static int orion5x_wdt_settimeout(int new_time) | |||
152 | static const struct watchdog_info ident = { | 152 | static const struct watchdog_info ident = { |
153 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | 153 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | |
154 | WDIOF_KEEPALIVEPING, | 154 | WDIOF_KEEPALIVEPING, |
155 | .identity = "Orion5x Watchdog", | 155 | .identity = "Orion Watchdog", |
156 | }; | 156 | }; |
157 | 157 | ||
158 | static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | 158 | static long orion_wdt_ioctl(struct file *file, unsigned int cmd, |
159 | unsigned long arg) | 159 | unsigned long arg) |
160 | { | 160 | { |
161 | int ret = -ENOTTY; | 161 | int ret = -ENOTTY; |
@@ -173,7 +173,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
173 | break; | 173 | break; |
174 | 174 | ||
175 | case WDIOC_KEEPALIVE: | 175 | case WDIOC_KEEPALIVE: |
176 | orion5x_wdt_ping(); | 176 | orion_wdt_ping(); |
177 | ret = 0; | 177 | ret = 0; |
178 | break; | 178 | break; |
179 | 179 | ||
@@ -182,11 +182,11 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
182 | if (ret) | 182 | if (ret) |
183 | break; | 183 | break; |
184 | 184 | ||
185 | if (orion5x_wdt_settimeout(time)) { | 185 | if (orion_wdt_settimeout(time)) { |
186 | ret = -EINVAL; | 186 | ret = -EINVAL; |
187 | break; | 187 | break; |
188 | } | 188 | } |
189 | orion5x_wdt_ping(); | 189 | orion_wdt_ping(); |
190 | /* Fall through */ | 190 | /* Fall through */ |
191 | 191 | ||
192 | case WDIOC_GETTIMEOUT: | 192 | case WDIOC_GETTIMEOUT: |
@@ -194,7 +194,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
194 | break; | 194 | break; |
195 | 195 | ||
196 | case WDIOC_GETTIMELEFT: | 196 | case WDIOC_GETTIMELEFT: |
197 | if (orion5x_wdt_get_timeleft(&time)) { | 197 | if (orion_wdt_get_timeleft(&time)) { |
198 | ret = -EINVAL; | 198 | ret = -EINVAL; |
199 | break; | 199 | break; |
200 | } | 200 | } |
@@ -204,10 +204,10 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
204 | return ret; | 204 | return ret; |
205 | } | 205 | } |
206 | 206 | ||
207 | static int orion5x_wdt_release(struct inode *inode, struct file *file) | 207 | static int orion_wdt_release(struct inode *inode, struct file *file) |
208 | { | 208 | { |
209 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | 209 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) |
210 | orion5x_wdt_disable(); | 210 | orion_wdt_disable(); |
211 | else | 211 | else |
212 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | 212 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " |
213 | "timer will not stop\n"); | 213 | "timer will not stop\n"); |
@@ -218,98 +218,98 @@ static int orion5x_wdt_release(struct inode *inode, struct file *file) | |||
218 | } | 218 | } |
219 | 219 | ||
220 | 220 | ||
221 | static const struct file_operations orion5x_wdt_fops = { | 221 | static const struct file_operations orion_wdt_fops = { |
222 | .owner = THIS_MODULE, | 222 | .owner = THIS_MODULE, |
223 | .llseek = no_llseek, | 223 | .llseek = no_llseek, |
224 | .write = orion5x_wdt_write, | 224 | .write = orion_wdt_write, |
225 | .unlocked_ioctl = orion5x_wdt_ioctl, | 225 | .unlocked_ioctl = orion_wdt_ioctl, |
226 | .open = orion5x_wdt_open, | 226 | .open = orion_wdt_open, |
227 | .release = orion5x_wdt_release, | 227 | .release = orion_wdt_release, |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static struct miscdevice orion5x_wdt_miscdev = { | 230 | static struct miscdevice orion_wdt_miscdev = { |
231 | .minor = WATCHDOG_MINOR, | 231 | .minor = WATCHDOG_MINOR, |
232 | .name = "watchdog", | 232 | .name = "watchdog", |
233 | .fops = &orion5x_wdt_fops, | 233 | .fops = &orion_wdt_fops, |
234 | }; | 234 | }; |
235 | 235 | ||
236 | static int __devinit orion5x_wdt_probe(struct platform_device *pdev) | 236 | static int __devinit orion_wdt_probe(struct platform_device *pdev) |
237 | { | 237 | { |
238 | struct orion5x_wdt_platform_data *pdata = pdev->dev.platform_data; | 238 | struct orion_wdt_platform_data *pdata = pdev->dev.platform_data; |
239 | int ret; | 239 | int ret; |
240 | 240 | ||
241 | if (pdata) { | 241 | if (pdata) { |
242 | wdt_tclk = pdata->tclk; | 242 | wdt_tclk = pdata->tclk; |
243 | } else { | 243 | } else { |
244 | printk(KERN_ERR "Orion5x Watchdog misses platform data\n"); | 244 | printk(KERN_ERR "Orion Watchdog misses platform data\n"); |
245 | return -ENODEV; | 245 | return -ENODEV; |
246 | } | 246 | } |
247 | 247 | ||
248 | if (orion5x_wdt_miscdev.parent) | 248 | if (orion_wdt_miscdev.parent) |
249 | return -EBUSY; | 249 | return -EBUSY; |
250 | orion5x_wdt_miscdev.parent = &pdev->dev; | 250 | orion_wdt_miscdev.parent = &pdev->dev; |
251 | 251 | ||
252 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; | 252 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; |
253 | if (orion5x_wdt_settimeout(heartbeat)) | 253 | if (orion_wdt_settimeout(heartbeat)) |
254 | heartbeat = wdt_max_duration; | 254 | heartbeat = wdt_max_duration; |
255 | 255 | ||
256 | ret = misc_register(&orion5x_wdt_miscdev); | 256 | ret = misc_register(&orion_wdt_miscdev); |
257 | if (ret) | 257 | if (ret) |
258 | return ret; | 258 | return ret; |
259 | 259 | ||
260 | printk(KERN_INFO "Orion5x Watchdog Timer: Initial timeout %d sec%s\n", | 260 | printk(KERN_INFO "Orion Watchdog Timer: Initial timeout %d sec%s\n", |
261 | heartbeat, nowayout ? ", nowayout" : ""); | 261 | heartbeat, nowayout ? ", nowayout" : ""); |
262 | return 0; | 262 | return 0; |
263 | } | 263 | } |
264 | 264 | ||
265 | static int __devexit orion5x_wdt_remove(struct platform_device *pdev) | 265 | static int __devexit orion_wdt_remove(struct platform_device *pdev) |
266 | { | 266 | { |
267 | int ret; | 267 | int ret; |
268 | 268 | ||
269 | if (test_bit(WDT_IN_USE, &wdt_status)) { | 269 | if (test_bit(WDT_IN_USE, &wdt_status)) { |
270 | orion5x_wdt_disable(); | 270 | orion_wdt_disable(); |
271 | clear_bit(WDT_IN_USE, &wdt_status); | 271 | clear_bit(WDT_IN_USE, &wdt_status); |
272 | } | 272 | } |
273 | 273 | ||
274 | ret = misc_deregister(&orion5x_wdt_miscdev); | 274 | ret = misc_deregister(&orion_wdt_miscdev); |
275 | if (!ret) | 275 | if (!ret) |
276 | orion5x_wdt_miscdev.parent = NULL; | 276 | orion_wdt_miscdev.parent = NULL; |
277 | 277 | ||
278 | return ret; | 278 | return ret; |
279 | } | 279 | } |
280 | 280 | ||
281 | static void orion5x_wdt_shutdown(struct platform_device *pdev) | 281 | static void orion_wdt_shutdown(struct platform_device *pdev) |
282 | { | 282 | { |
283 | if (test_bit(WDT_IN_USE, &wdt_status)) | 283 | if (test_bit(WDT_IN_USE, &wdt_status)) |
284 | orion5x_wdt_disable(); | 284 | orion_wdt_disable(); |
285 | } | 285 | } |
286 | 286 | ||
287 | static struct platform_driver orion5x_wdt_driver = { | 287 | static struct platform_driver orion_wdt_driver = { |
288 | .probe = orion5x_wdt_probe, | 288 | .probe = orion_wdt_probe, |
289 | .remove = __devexit_p(orion5x_wdt_remove), | 289 | .remove = __devexit_p(orion_wdt_remove), |
290 | .shutdown = orion5x_wdt_shutdown, | 290 | .shutdown = orion_wdt_shutdown, |
291 | .driver = { | 291 | .driver = { |
292 | .owner = THIS_MODULE, | 292 | .owner = THIS_MODULE, |
293 | .name = "orion5x_wdt", | 293 | .name = "orion_wdt", |
294 | }, | 294 | }, |
295 | }; | 295 | }; |
296 | 296 | ||
297 | static int __init orion5x_wdt_init(void) | 297 | static int __init orion_wdt_init(void) |
298 | { | 298 | { |
299 | spin_lock_init(&wdt_lock); | 299 | spin_lock_init(&wdt_lock); |
300 | return platform_driver_register(&orion5x_wdt_driver); | 300 | return platform_driver_register(&orion_wdt_driver); |
301 | } | 301 | } |
302 | 302 | ||
303 | static void __exit orion5x_wdt_exit(void) | 303 | static void __exit orion_wdt_exit(void) |
304 | { | 304 | { |
305 | platform_driver_unregister(&orion5x_wdt_driver); | 305 | platform_driver_unregister(&orion_wdt_driver); |
306 | } | 306 | } |
307 | 307 | ||
308 | module_init(orion5x_wdt_init); | 308 | module_init(orion_wdt_init); |
309 | module_exit(orion5x_wdt_exit); | 309 | module_exit(orion_wdt_exit); |
310 | 310 | ||
311 | MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); | 311 | MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); |
312 | MODULE_DESCRIPTION("Orion5x Processor Watchdog"); | 312 | MODULE_DESCRIPTION("Orion Processor Watchdog"); |
313 | 313 | ||
314 | module_param(heartbeat, int, 0); | 314 | module_param(heartbeat, int, 0); |
315 | MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); | 315 | MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); |