diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-03-25 18:56:30 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-03-25 18:57:10 -0400 |
commit | 7256ecc2b7b91b4212ccc5511cb12254bdf806d0 (patch) | |
tree | 1a39b3de03cfc92c5b5dedfb01174d17b49df18a | |
parent | 18bbff9f679cd470db66402fdb9c577b34324183 (diff) | |
parent | 6ed3e2acc7995625625592abe8cd3383c34a471b (diff) |
Merge branch 'sa11x0-mcp' into sa11x0
Conflicts:
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/lart.c
arch/arm/mach-sa1100/shannon.c
-rw-r--r-- | arch/arm/mach-sa1100/assabet.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/cerf.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/collie.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/generic.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/generic.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/include/mach/mcp.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/lart.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/shannon.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/simpad.c | 8 | ||||
-rw-r--r-- | drivers/mfd/Kconfig | 5 | ||||
-rw-r--r-- | drivers/mfd/mcp-core.c | 49 | ||||
-rw-r--r-- | drivers/mfd/mcp-sa11x0.c | 198 | ||||
-rw-r--r-- | drivers/mfd/ucb1x00-assabet.c | 46 | ||||
-rw-r--r-- | drivers/mfd/ucb1x00-core.c | 433 | ||||
-rw-r--r-- | drivers/mfd/ucb1x00-ts.c | 39 | ||||
-rw-r--r-- | include/linux/mfd/mcp.h | 14 | ||||
-rw-r--r-- | include/linux/mfd/ucb1x00.h | 38 |
17 files changed, 518 insertions, 357 deletions
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index c3f5064df4bf..e708a93a7ddb 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
17 | #include <linux/serial_core.h> | 17 | #include <linux/serial_core.h> |
18 | #include <linux/mfd/ucb1x00.h> | ||
18 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/partitions.h> | 20 | #include <linux/mtd/partitions.h> |
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
@@ -71,6 +72,12 @@ void ASSABET_BCR_frob(unsigned int mask, unsigned int val) | |||
71 | 72 | ||
72 | EXPORT_SYMBOL(ASSABET_BCR_frob); | 73 | EXPORT_SYMBOL(ASSABET_BCR_frob); |
73 | 74 | ||
75 | static void assabet_ucb1x00_reset(enum ucb1x00_reset state) | ||
76 | { | ||
77 | if (state == UCB_RST_PROBE) | ||
78 | ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); | ||
79 | } | ||
80 | |||
74 | 81 | ||
75 | /* | 82 | /* |
76 | * Assabet flash support code. | 83 | * Assabet flash support code. |
@@ -167,9 +174,15 @@ static struct irda_platform_data assabet_irda_data = { | |||
167 | .set_speed = assabet_irda_set_speed, | 174 | .set_speed = assabet_irda_set_speed, |
168 | }; | 175 | }; |
169 | 176 | ||
177 | static struct ucb1x00_plat_data assabet_ucb1x00_data = { | ||
178 | .reset = assabet_ucb1x00_reset, | ||
179 | .gpio_base = -1, | ||
180 | }; | ||
181 | |||
170 | static struct mcp_plat_data assabet_mcp_data = { | 182 | static struct mcp_plat_data assabet_mcp_data = { |
171 | .mccr0 = MCCR0_ADM, | 183 | .mccr0 = MCCR0_ADM, |
172 | .sclk_rate = 11981000, | 184 | .sclk_rate = 11981000, |
185 | .codec_pdata = &assabet_ucb1x00_data, | ||
173 | }; | 186 | }; |
174 | 187 | ||
175 | static void assabet_lcd_set_visual(u32 visual) | 188 | static void assabet_lcd_set_visual(u32 visual) |
@@ -309,6 +322,8 @@ static void __init assabet_init(void) | |||
309 | PPDR |= PPC_TXD3 | PPC_TXD1; | 322 | PPDR |= PPC_TXD3 | PPC_TXD1; |
310 | PPSR |= PPC_TXD3 | PPC_TXD1; | 323 | PPSR |= PPC_TXD3 | PPC_TXD1; |
311 | 324 | ||
325 | sa11x0_ppc_configure_mcp(); | ||
326 | |||
312 | if (machine_has_neponset()) { | 327 | if (machine_has_neponset()) { |
313 | /* | 328 | /* |
314 | * Angel sets this, but other bootloaders may not. | 329 | * Angel sets this, but other bootloaders may not. |
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index c2f9ba3a9578..8015604cfc22 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c | |||
@@ -121,6 +121,7 @@ static struct mcp_plat_data cerf_mcp_data = { | |||
121 | 121 | ||
122 | static void __init cerf_init(void) | 122 | static void __init cerf_init(void) |
123 | { | 123 | { |
124 | sa11x0_ppc_configure_mcp(); | ||
124 | platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); | 125 | platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); |
125 | sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1); | 126 | sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1); |
126 | sa11x0_register_mcp(&cerf_mcp_data); | 127 | sa11x0_register_mcp(&cerf_mcp_data); |
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 841041e11815..d4339d639475 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/tty.h> | 22 | #include <linux/tty.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/mfd/ucb1x00.h> | ||
25 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
26 | #include <linux/mtd/partitions.h> | 27 | #include <linux/mtd/partitions.h> |
27 | #include <linux/timer.h> | 28 | #include <linux/timer.h> |
@@ -83,10 +84,14 @@ static struct scoop_pcmcia_config collie_pcmcia_config = { | |||
83 | .num_devs = 1, | 84 | .num_devs = 1, |
84 | }; | 85 | }; |
85 | 86 | ||
87 | static struct ucb1x00_plat_data collie_ucb1x00_data = { | ||
88 | .gpio_base = COLLIE_TC35143_GPIO_BASE, | ||
89 | }; | ||
90 | |||
86 | static struct mcp_plat_data collie_mcp_data = { | 91 | static struct mcp_plat_data collie_mcp_data = { |
87 | .mccr0 = MCCR0_ADM | MCCR0_ExtClk, | 92 | .mccr0 = MCCR0_ADM | MCCR0_ExtClk, |
88 | .sclk_rate = 9216000, | 93 | .sclk_rate = 9216000, |
89 | .gpio_base = COLLIE_TC35143_GPIO_BASE, | 94 | .codec_pdata = &collie_ucb1x00_data, |
90 | }; | 95 | }; |
91 | 96 | ||
92 | /* | 97 | /* |
@@ -341,6 +346,10 @@ static void __init collie_init(void) | |||
341 | 346 | ||
342 | collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN); | 347 | collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN); |
343 | collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN); | 348 | collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN); |
349 | |||
350 | sa11x0_ppc_configure_mcp(); | ||
351 | |||
352 | |||
344 | platform_scoop_config = &collie_pcmcia_config; | 353 | platform_scoop_config = &collie_pcmcia_config; |
345 | 354 | ||
346 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); | 355 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); |
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 0296d69622ac..97e9bdf7f297 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c | |||
@@ -195,7 +195,8 @@ static struct platform_device sa11x0uart3_device = { | |||
195 | 195 | ||
196 | static struct resource sa11x0mcp_resources[] = { | 196 | static struct resource sa11x0mcp_resources[] = { |
197 | [0] = DEFINE_RES_MEM(__PREG(Ser4MCCR0), SZ_64K), | 197 | [0] = DEFINE_RES_MEM(__PREG(Ser4MCCR0), SZ_64K), |
198 | [1] = DEFINE_RES_IRQ(IRQ_Ser4MCP), | 198 | [1] = DEFINE_RES_MEM(__PREG(Ser4MCCR1), 4), |
199 | [2] = DEFINE_RES_IRQ(IRQ_Ser4MCP), | ||
199 | }; | 200 | }; |
200 | 201 | ||
201 | static u64 sa11x0mcp_dma_mask = 0xffffffffUL; | 202 | static u64 sa11x0mcp_dma_mask = 0xffffffffUL; |
@@ -211,6 +212,16 @@ static struct platform_device sa11x0mcp_device = { | |||
211 | .resource = sa11x0mcp_resources, | 212 | .resource = sa11x0mcp_resources, |
212 | }; | 213 | }; |
213 | 214 | ||
215 | void __init sa11x0_ppc_configure_mcp(void) | ||
216 | { | ||
217 | /* Setup the PPC unit for the MCP */ | ||
218 | PPDR &= ~PPC_RXD4; | ||
219 | PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; | ||
220 | PSDR |= PPC_RXD4; | ||
221 | PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); | ||
222 | PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); | ||
223 | } | ||
224 | |||
214 | void sa11x0_register_mcp(struct mcp_plat_data *data) | 225 | void sa11x0_register_mcp(struct mcp_plat_data *data) |
215 | { | 226 | { |
216 | sa11x0_register_device(&sa11x0mcp_device, data); | 227 | sa11x0_register_device(&sa11x0mcp_device, data); |
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 5c68be858e0c..9eb3b3cd5a63 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h | |||
@@ -36,6 +36,7 @@ struct irda_platform_data; | |||
36 | void sa11x0_register_irda(struct irda_platform_data *irda); | 36 | void sa11x0_register_irda(struct irda_platform_data *irda); |
37 | 37 | ||
38 | struct mcp_plat_data; | 38 | struct mcp_plat_data; |
39 | void sa11x0_ppc_configure_mcp(void); | ||
39 | void sa11x0_register_mcp(struct mcp_plat_data *data); | 40 | void sa11x0_register_mcp(struct mcp_plat_data *data); |
40 | 41 | ||
41 | struct sa1100fb_mach_info; | 42 | struct sa1100fb_mach_info; |
diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h index ed1a331508a7..4b2860ae3828 100644 --- a/arch/arm/mach-sa1100/include/mach/mcp.h +++ b/arch/arm/mach-sa1100/include/mach/mcp.h | |||
@@ -16,7 +16,7 @@ struct mcp_plat_data { | |||
16 | u32 mccr0; | 16 | u32 mccr0; |
17 | u32 mccr1; | 17 | u32 mccr1; |
18 | unsigned int sclk_rate; | 18 | unsigned int sclk_rate; |
19 | int gpio_base; | 19 | void *codec_pdata; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | #endif | 22 | #endif |
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index 463a322a425b..570f75fb73a2 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c | |||
@@ -107,6 +107,7 @@ static void __init lart_init(void) | |||
107 | if (inf) | 107 | if (inf) |
108 | sa11x0_register_lcd(inf); | 108 | sa11x0_register_lcd(inf); |
109 | 109 | ||
110 | sa11x0_ppc_configure_mcp(); | ||
110 | sa11x0_register_mcp(&lart_mcp_data); | 111 | sa11x0_register_mcp(&lart_mcp_data); |
111 | } | 112 | } |
112 | 113 | ||
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 77b2b9b522ac..08bb1228961f 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c | |||
@@ -72,6 +72,7 @@ static struct sa1100fb_mach_info shannon_lcd_info = { | |||
72 | 72 | ||
73 | static void __init shannon_init(void) | 73 | static void __init shannon_init(void) |
74 | { | 74 | { |
75 | sa11x0_ppc_configure_mcp(); | ||
75 | sa11x0_register_lcd(&shannon_lcd_info); | 76 | sa11x0_register_lcd(&shannon_lcd_info); |
76 | sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1); | 77 | sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1); |
77 | sa11x0_register_mcp(&shannon_mcp_data); | 78 | sa11x0_register_mcp(&shannon_mcp_data); |
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index cdb9d197c092..3da4c1f11cf5 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/pm.h> | 11 | #include <linux/pm.h> |
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/mfd/ucb1x00.h> | ||
13 | #include <linux/mtd/mtd.h> | 14 | #include <linux/mtd/mtd.h> |
14 | #include <linux/mtd/partitions.h> | 15 | #include <linux/mtd/partitions.h> |
15 | #include <linux/io.h> | 16 | #include <linux/io.h> |
@@ -180,10 +181,14 @@ static struct resource simpad_flash_resources [] = { | |||
180 | DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_16M), | 181 | DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_16M), |
181 | }; | 182 | }; |
182 | 183 | ||
184 | static struct ucb1x00_plat_data simpad_ucb1x00_data = { | ||
185 | .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, | ||
186 | }; | ||
187 | |||
183 | static struct mcp_plat_data simpad_mcp_data = { | 188 | static struct mcp_plat_data simpad_mcp_data = { |
184 | .mccr0 = MCCR0_ADM, | 189 | .mccr0 = MCCR0_ADM, |
185 | .sclk_rate = 11981000, | 190 | .sclk_rate = 11981000, |
186 | .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, | 191 | .codec_pdata = &simpad_ucb1x00_data, |
187 | }; | 192 | }; |
188 | 193 | ||
189 | 194 | ||
@@ -369,6 +374,7 @@ static int __init simpad_init(void) | |||
369 | 374 | ||
370 | pm_power_off = simpad_power_off; | 375 | pm_power_off = simpad_power_off; |
371 | 376 | ||
377 | sa11x0_ppc_configure_mcp(); | ||
372 | sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, | 378 | sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, |
373 | ARRAY_SIZE(simpad_flash_resources)); | 379 | ARRAY_SIZE(simpad_flash_resources)); |
374 | sa11x0_register_mcp(&simpad_mcp_data); | 380 | sa11x0_register_mcp(&simpad_mcp_data); |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index cd13e9f2f5e6..28a301b28579 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -847,8 +847,9 @@ config MCP_SA11X0 | |||
847 | 847 | ||
848 | # Chip drivers | 848 | # Chip drivers |
849 | config MCP_UCB1200 | 849 | config MCP_UCB1200 |
850 | tristate "Support for UCB1200 / UCB1300" | 850 | bool "Support for UCB1200 / UCB1300" |
851 | depends on MCP | 851 | depends on MCP_SA11X0 |
852 | select MCP | ||
852 | 853 | ||
853 | config MCP_UCB1200_TS | 854 | config MCP_UCB1200_TS |
854 | tristate "Touchscreen interface support" | 855 | tristate "Touchscreen interface support" |
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 86cc3f7841cd..6acf2e03f2ba 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/mfd/mcp.h> | 20 | #include <linux/mfd/mcp.h> |
21 | 21 | ||
22 | #include <mach/dma.h> | ||
23 | #include <asm/system.h> | 22 | #include <asm/system.h> |
24 | 23 | ||
25 | 24 | ||
@@ -48,39 +47,11 @@ static int mcp_bus_remove(struct device *dev) | |||
48 | return 0; | 47 | return 0; |
49 | } | 48 | } |
50 | 49 | ||
51 | static int mcp_bus_suspend(struct device *dev, pm_message_t state) | ||
52 | { | ||
53 | struct mcp *mcp = to_mcp(dev); | ||
54 | int ret = 0; | ||
55 | |||
56 | if (dev->driver) { | ||
57 | struct mcp_driver *drv = to_mcp_driver(dev->driver); | ||
58 | |||
59 | ret = drv->suspend(mcp, state); | ||
60 | } | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | static int mcp_bus_resume(struct device *dev) | ||
65 | { | ||
66 | struct mcp *mcp = to_mcp(dev); | ||
67 | int ret = 0; | ||
68 | |||
69 | if (dev->driver) { | ||
70 | struct mcp_driver *drv = to_mcp_driver(dev->driver); | ||
71 | |||
72 | ret = drv->resume(mcp); | ||
73 | } | ||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | static struct bus_type mcp_bus_type = { | 50 | static struct bus_type mcp_bus_type = { |
78 | .name = "mcp", | 51 | .name = "mcp", |
79 | .match = mcp_bus_match, | 52 | .match = mcp_bus_match, |
80 | .probe = mcp_bus_probe, | 53 | .probe = mcp_bus_probe, |
81 | .remove = mcp_bus_remove, | 54 | .remove = mcp_bus_remove, |
82 | .suspend = mcp_bus_suspend, | ||
83 | .resume = mcp_bus_resume, | ||
84 | }; | 55 | }; |
85 | 56 | ||
86 | /** | 57 | /** |
@@ -208,6 +179,7 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) | |||
208 | mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL); | 179 | mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL); |
209 | if (mcp) { | 180 | if (mcp) { |
210 | spin_lock_init(&mcp->lock); | 181 | spin_lock_init(&mcp->lock); |
182 | device_initialize(&mcp->attached_device); | ||
211 | mcp->attached_device.parent = parent; | 183 | mcp->attached_device.parent = parent; |
212 | mcp->attached_device.bus = &mcp_bus_type; | 184 | mcp->attached_device.bus = &mcp_bus_type; |
213 | mcp->attached_device.dma_mask = parent->dma_mask; | 185 | mcp->attached_device.dma_mask = parent->dma_mask; |
@@ -217,18 +189,25 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) | |||
217 | } | 189 | } |
218 | EXPORT_SYMBOL(mcp_host_alloc); | 190 | EXPORT_SYMBOL(mcp_host_alloc); |
219 | 191 | ||
220 | int mcp_host_register(struct mcp *mcp) | 192 | int mcp_host_add(struct mcp *mcp, void *pdata) |
221 | { | 193 | { |
194 | mcp->attached_device.platform_data = pdata; | ||
222 | dev_set_name(&mcp->attached_device, "mcp0"); | 195 | dev_set_name(&mcp->attached_device, "mcp0"); |
223 | return device_register(&mcp->attached_device); | 196 | return device_add(&mcp->attached_device); |
197 | } | ||
198 | EXPORT_SYMBOL(mcp_host_add); | ||
199 | |||
200 | void mcp_host_del(struct mcp *mcp) | ||
201 | { | ||
202 | device_del(&mcp->attached_device); | ||
224 | } | 203 | } |
225 | EXPORT_SYMBOL(mcp_host_register); | 204 | EXPORT_SYMBOL(mcp_host_del); |
226 | 205 | ||
227 | void mcp_host_unregister(struct mcp *mcp) | 206 | void mcp_host_free(struct mcp *mcp) |
228 | { | 207 | { |
229 | device_unregister(&mcp->attached_device); | 208 | put_device(&mcp->attached_device); |
230 | } | 209 | } |
231 | EXPORT_SYMBOL(mcp_host_unregister); | 210 | EXPORT_SYMBOL(mcp_host_free); |
232 | 211 | ||
233 | int mcp_driver_register(struct mcp_driver *mcpdrv) | 212 | int mcp_driver_register(struct mcp_driver *mcpdrv) |
234 | { | 213 | { |
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 02c53a0766c4..1c0ceacaa1f6 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c | |||
@@ -13,51 +13,61 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/io.h> | ||
16 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/pm.h> | ||
21 | #include <linux/mfd/mcp.h> | 23 | #include <linux/mfd/mcp.h> |
22 | 24 | ||
23 | #include <mach/dma.h> | ||
24 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
25 | #include <asm/mach-types.h> | 26 | #include <asm/mach-types.h> |
26 | #include <asm/system.h> | 27 | #include <asm/system.h> |
27 | #include <mach/mcp.h> | 28 | #include <mach/mcp.h> |
28 | 29 | ||
29 | #include <mach/assabet.h> | 30 | #define DRIVER_NAME "sa11x0-mcp" |
30 | |||
31 | 31 | ||
32 | struct mcp_sa11x0 { | 32 | struct mcp_sa11x0 { |
33 | u32 mccr0; | 33 | void __iomem *base0; |
34 | u32 mccr1; | 34 | void __iomem *base1; |
35 | u32 mccr0; | ||
36 | u32 mccr1; | ||
35 | }; | 37 | }; |
36 | 38 | ||
39 | /* Register offsets */ | ||
40 | #define MCCR0(m) ((m)->base0 + 0x00) | ||
41 | #define MCDR0(m) ((m)->base0 + 0x08) | ||
42 | #define MCDR1(m) ((m)->base0 + 0x0c) | ||
43 | #define MCDR2(m) ((m)->base0 + 0x10) | ||
44 | #define MCSR(m) ((m)->base0 + 0x18) | ||
45 | #define MCCR1(m) ((m)->base1 + 0x00) | ||
46 | |||
37 | #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) | 47 | #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) |
38 | 48 | ||
39 | static void | 49 | static void |
40 | mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) | 50 | mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) |
41 | { | 51 | { |
42 | unsigned int mccr0; | 52 | struct mcp_sa11x0 *m = priv(mcp); |
43 | 53 | ||
44 | divisor /= 32; | 54 | divisor /= 32; |
45 | 55 | ||
46 | mccr0 = Ser4MCCR0 & ~0x00007f00; | 56 | m->mccr0 &= ~0x00007f00; |
47 | mccr0 |= divisor << 8; | 57 | m->mccr0 |= divisor << 8; |
48 | Ser4MCCR0 = mccr0; | 58 | writel_relaxed(m->mccr0, MCCR0(m)); |
49 | } | 59 | } |
50 | 60 | ||
51 | static void | 61 | static void |
52 | mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) | 62 | mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) |
53 | { | 63 | { |
54 | unsigned int mccr0; | 64 | struct mcp_sa11x0 *m = priv(mcp); |
55 | 65 | ||
56 | divisor /= 32; | 66 | divisor /= 32; |
57 | 67 | ||
58 | mccr0 = Ser4MCCR0 & ~0x0000007f; | 68 | m->mccr0 &= ~0x0000007f; |
59 | mccr0 |= divisor; | 69 | m->mccr0 |= divisor; |
60 | Ser4MCCR0 = mccr0; | 70 | writel_relaxed(m->mccr0, MCCR0(m)); |
61 | } | 71 | } |
62 | 72 | ||
63 | /* | 73 | /* |
@@ -69,14 +79,15 @@ mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) | |||
69 | static void | 79 | static void |
70 | mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) | 80 | mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) |
71 | { | 81 | { |
82 | struct mcp_sa11x0 *m = priv(mcp); | ||
72 | int ret = -ETIME; | 83 | int ret = -ETIME; |
73 | int i; | 84 | int i; |
74 | 85 | ||
75 | Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); | 86 | writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m)); |
76 | 87 | ||
77 | for (i = 0; i < 2; i++) { | 88 | for (i = 0; i < 2; i++) { |
78 | udelay(mcp->rw_timeout); | 89 | udelay(mcp->rw_timeout); |
79 | if (Ser4MCSR & MCSR_CWC) { | 90 | if (readl_relaxed(MCSR(m)) & MCSR_CWC) { |
80 | ret = 0; | 91 | ret = 0; |
81 | break; | 92 | break; |
82 | } | 93 | } |
@@ -95,15 +106,16 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) | |||
95 | static unsigned int | 106 | static unsigned int |
96 | mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) | 107 | mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) |
97 | { | 108 | { |
109 | struct mcp_sa11x0 *m = priv(mcp); | ||
98 | int ret = -ETIME; | 110 | int ret = -ETIME; |
99 | int i; | 111 | int i; |
100 | 112 | ||
101 | Ser4MCDR2 = reg << 17 | MCDR2_Rd; | 113 | writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m)); |
102 | 114 | ||
103 | for (i = 0; i < 2; i++) { | 115 | for (i = 0; i < 2; i++) { |
104 | udelay(mcp->rw_timeout); | 116 | udelay(mcp->rw_timeout); |
105 | if (Ser4MCSR & MCSR_CRC) { | 117 | if (readl_relaxed(MCSR(m)) & MCSR_CRC) { |
106 | ret = Ser4MCDR2 & 0xffff; | 118 | ret = readl_relaxed(MCDR2(m)) & 0xffff; |
107 | break; | 119 | break; |
108 | } | 120 | } |
109 | } | 121 | } |
@@ -116,13 +128,19 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) | |||
116 | 128 | ||
117 | static void mcp_sa11x0_enable(struct mcp *mcp) | 129 | static void mcp_sa11x0_enable(struct mcp *mcp) |
118 | { | 130 | { |
119 | Ser4MCSR = -1; | 131 | struct mcp_sa11x0 *m = priv(mcp); |
120 | Ser4MCCR0 |= MCCR0_MCE; | 132 | |
133 | writel(-1, MCSR(m)); | ||
134 | m->mccr0 |= MCCR0_MCE; | ||
135 | writel_relaxed(m->mccr0, MCCR0(m)); | ||
121 | } | 136 | } |
122 | 137 | ||
123 | static void mcp_sa11x0_disable(struct mcp *mcp) | 138 | static void mcp_sa11x0_disable(struct mcp *mcp) |
124 | { | 139 | { |
125 | Ser4MCCR0 &= ~MCCR0_MCE; | 140 | struct mcp_sa11x0 *m = priv(mcp); |
141 | |||
142 | m->mccr0 &= ~MCCR0_MCE; | ||
143 | writel_relaxed(m->mccr0, MCCR0(m)); | ||
126 | } | 144 | } |
127 | 145 | ||
128 | /* | 146 | /* |
@@ -137,55 +155,64 @@ static struct mcp_ops mcp_sa11x0 = { | |||
137 | .disable = mcp_sa11x0_disable, | 155 | .disable = mcp_sa11x0_disable, |
138 | }; | 156 | }; |
139 | 157 | ||
140 | static int mcp_sa11x0_probe(struct platform_device *pdev) | 158 | static int mcp_sa11x0_probe(struct platform_device *dev) |
141 | { | 159 | { |
142 | struct mcp_plat_data *data = pdev->dev.platform_data; | 160 | struct mcp_plat_data *data = dev->dev.platform_data; |
161 | struct resource *mem0, *mem1; | ||
162 | struct mcp_sa11x0 *m; | ||
143 | struct mcp *mcp; | 163 | struct mcp *mcp; |
144 | int ret; | 164 | int ret; |
145 | 165 | ||
146 | if (!data) | 166 | if (!data) |
147 | return -ENODEV; | 167 | return -ENODEV; |
148 | 168 | ||
149 | if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) | 169 | mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); |
150 | return -EBUSY; | 170 | mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); |
171 | if (!mem0 || !mem1) | ||
172 | return -ENXIO; | ||
173 | |||
174 | if (!request_mem_region(mem0->start, resource_size(mem0), | ||
175 | DRIVER_NAME)) { | ||
176 | ret = -EBUSY; | ||
177 | goto err_mem0; | ||
178 | } | ||
151 | 179 | ||
152 | mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0)); | 180 | if (!request_mem_region(mem1->start, resource_size(mem1), |
181 | DRIVER_NAME)) { | ||
182 | ret = -EBUSY; | ||
183 | goto err_mem1; | ||
184 | } | ||
185 | |||
186 | mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0)); | ||
153 | if (!mcp) { | 187 | if (!mcp) { |
154 | ret = -ENOMEM; | 188 | ret = -ENOMEM; |
155 | goto release; | 189 | goto err_alloc; |
156 | } | 190 | } |
157 | 191 | ||
158 | mcp->owner = THIS_MODULE; | 192 | mcp->owner = THIS_MODULE; |
159 | mcp->ops = &mcp_sa11x0; | 193 | mcp->ops = &mcp_sa11x0; |
160 | mcp->sclk_rate = data->sclk_rate; | 194 | mcp->sclk_rate = data->sclk_rate; |
161 | mcp->dma_audio_rd = DMA_Ser4MCP0Rd; | ||
162 | mcp->dma_audio_wr = DMA_Ser4MCP0Wr; | ||
163 | mcp->dma_telco_rd = DMA_Ser4MCP1Rd; | ||
164 | mcp->dma_telco_wr = DMA_Ser4MCP1Wr; | ||
165 | mcp->gpio_base = data->gpio_base; | ||
166 | 195 | ||
167 | platform_set_drvdata(pdev, mcp); | 196 | m = priv(mcp); |
197 | m->mccr0 = data->mccr0 | 0x7f7f; | ||
198 | m->mccr1 = data->mccr1; | ||
168 | 199 | ||
169 | if (machine_is_assabet()) { | 200 | m->base0 = ioremap(mem0->start, resource_size(mem0)); |
170 | ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); | 201 | m->base1 = ioremap(mem1->start, resource_size(mem1)); |
202 | if (!m->base0 || !m->base1) { | ||
203 | ret = -ENOMEM; | ||
204 | goto err_ioremap; | ||
171 | } | 205 | } |
172 | 206 | ||
173 | /* | 207 | platform_set_drvdata(dev, mcp); |
174 | * Setup the PPC unit correctly. | ||
175 | */ | ||
176 | PPDR &= ~PPC_RXD4; | ||
177 | PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; | ||
178 | PSDR |= PPC_RXD4; | ||
179 | PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); | ||
180 | PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); | ||
181 | 208 | ||
182 | /* | 209 | /* |
183 | * Initialise device. Note that we initially | 210 | * Initialise device. Note that we initially |
184 | * set the sampling rate to minimum. | 211 | * set the sampling rate to minimum. |
185 | */ | 212 | */ |
186 | Ser4MCSR = -1; | 213 | writel_relaxed(-1, MCSR(m)); |
187 | Ser4MCCR1 = data->mccr1; | 214 | writel_relaxed(m->mccr1, MCCR1(m)); |
188 | Ser4MCCR0 = data->mccr0 | 0x7f7f; | 215 | writel_relaxed(m->mccr0, MCCR0(m)); |
189 | 216 | ||
190 | /* | 217 | /* |
191 | * Calculate the read/write timeout (us) from the bit clock | 218 | * Calculate the read/write timeout (us) from the bit clock |
@@ -195,62 +222,90 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) | |||
195 | mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / | 222 | mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / |
196 | mcp->sclk_rate; | 223 | mcp->sclk_rate; |
197 | 224 | ||
198 | ret = mcp_host_register(mcp); | 225 | ret = mcp_host_add(mcp, data->codec_pdata); |
199 | if (ret == 0) | 226 | if (ret == 0) |
200 | goto out; | 227 | return 0; |
201 | 228 | ||
202 | release: | 229 | platform_set_drvdata(dev, NULL); |
203 | release_mem_region(0x80060000, 0x60); | ||
204 | platform_set_drvdata(pdev, NULL); | ||
205 | 230 | ||
206 | out: | 231 | err_ioremap: |
232 | iounmap(m->base1); | ||
233 | iounmap(m->base0); | ||
234 | mcp_host_free(mcp); | ||
235 | err_alloc: | ||
236 | release_mem_region(mem1->start, resource_size(mem1)); | ||
237 | err_mem1: | ||
238 | release_mem_region(mem0->start, resource_size(mem0)); | ||
239 | err_mem0: | ||
207 | return ret; | 240 | return ret; |
208 | } | 241 | } |
209 | 242 | ||
210 | static int mcp_sa11x0_remove(struct platform_device *dev) | 243 | static int mcp_sa11x0_remove(struct platform_device *dev) |
211 | { | 244 | { |
212 | struct mcp *mcp = platform_get_drvdata(dev); | 245 | struct mcp *mcp = platform_get_drvdata(dev); |
246 | struct mcp_sa11x0 *m = priv(mcp); | ||
247 | struct resource *mem0, *mem1; | ||
248 | |||
249 | if (m->mccr0 & MCCR0_MCE) | ||
250 | dev_warn(&dev->dev, | ||
251 | "device left active (missing disable call?)\n"); | ||
252 | |||
253 | mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
254 | mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); | ||
213 | 255 | ||
214 | platform_set_drvdata(dev, NULL); | 256 | platform_set_drvdata(dev, NULL); |
215 | mcp_host_unregister(mcp); | 257 | mcp_host_del(mcp); |
216 | release_mem_region(0x80060000, 0x60); | 258 | iounmap(m->base1); |
259 | iounmap(m->base0); | ||
260 | mcp_host_free(mcp); | ||
261 | release_mem_region(mem1->start, resource_size(mem1)); | ||
262 | release_mem_region(mem0->start, resource_size(mem0)); | ||
217 | 263 | ||
218 | return 0; | 264 | return 0; |
219 | } | 265 | } |
220 | 266 | ||
221 | static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state) | 267 | #ifdef CONFIG_PM_SLEEP |
268 | static int mcp_sa11x0_suspend(struct device *dev) | ||
222 | { | 269 | { |
223 | struct mcp *mcp = platform_get_drvdata(dev); | 270 | struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev)); |
271 | |||
272 | if (m->mccr0 & MCCR0_MCE) | ||
273 | dev_warn(dev, "device left active (missing disable call?)\n"); | ||
224 | 274 | ||
225 | priv(mcp)->mccr0 = Ser4MCCR0; | 275 | writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m)); |
226 | priv(mcp)->mccr1 = Ser4MCCR1; | ||
227 | Ser4MCCR0 &= ~MCCR0_MCE; | ||
228 | 276 | ||
229 | return 0; | 277 | return 0; |
230 | } | 278 | } |
231 | 279 | ||
232 | static int mcp_sa11x0_resume(struct platform_device *dev) | 280 | static int mcp_sa11x0_resume(struct device *dev) |
233 | { | 281 | { |
234 | struct mcp *mcp = platform_get_drvdata(dev); | 282 | struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev)); |
235 | 283 | ||
236 | Ser4MCCR1 = priv(mcp)->mccr1; | 284 | writel_relaxed(m->mccr1, MCCR1(m)); |
237 | Ser4MCCR0 = priv(mcp)->mccr0; | 285 | writel_relaxed(m->mccr0, MCCR0(m)); |
238 | 286 | ||
239 | return 0; | 287 | return 0; |
240 | } | 288 | } |
241 | 289 | #endif | |
242 | /* | 290 | |
243 | * The driver for the SA11x0 MCP port. | 291 | static const struct dev_pm_ops mcp_sa11x0_pm_ops = { |
244 | */ | 292 | #ifdef CONFIG_PM_SLEEP |
245 | MODULE_ALIAS("platform:sa11x0-mcp"); | 293 | .suspend = mcp_sa11x0_suspend, |
294 | .freeze = mcp_sa11x0_suspend, | ||
295 | .poweroff = mcp_sa11x0_suspend, | ||
296 | .resume_noirq = mcp_sa11x0_resume, | ||
297 | .thaw_noirq = mcp_sa11x0_resume, | ||
298 | .restore_noirq = mcp_sa11x0_resume, | ||
299 | #endif | ||
300 | }; | ||
246 | 301 | ||
247 | static struct platform_driver mcp_sa11x0_driver = { | 302 | static struct platform_driver mcp_sa11x0_driver = { |
248 | .probe = mcp_sa11x0_probe, | 303 | .probe = mcp_sa11x0_probe, |
249 | .remove = mcp_sa11x0_remove, | 304 | .remove = mcp_sa11x0_remove, |
250 | .suspend = mcp_sa11x0_suspend, | ||
251 | .resume = mcp_sa11x0_resume, | ||
252 | .driver = { | 305 | .driver = { |
253 | .name = "sa11x0-mcp", | 306 | .name = DRIVER_NAME, |
307 | .owner = THIS_MODULE, | ||
308 | .pm = &mcp_sa11x0_pm_ops, | ||
254 | }, | 309 | }, |
255 | }; | 310 | }; |
256 | 311 | ||
@@ -259,6 +314,7 @@ static struct platform_driver mcp_sa11x0_driver = { | |||
259 | */ | 314 | */ |
260 | module_platform_driver(mcp_sa11x0_driver); | 315 | module_platform_driver(mcp_sa11x0_driver); |
261 | 316 | ||
317 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
262 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); | 318 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); |
263 | MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); | 319 | MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); |
264 | MODULE_LICENSE("GPL"); | 320 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c index cea9da60850d..b63c0756a669 100644 --- a/drivers/mfd/ucb1x00-assabet.c +++ b/drivers/mfd/ucb1x00-assabet.c | |||
@@ -11,14 +11,15 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/device.h> | ||
15 | #include <linux/err.h> | ||
14 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/gpio_keys.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/platform_device.h> | ||
15 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
16 | #include <linux/device.h> | ||
17 | #include <linux/mfd/ucb1x00.h> | 21 | #include <linux/mfd/ucb1x00.h> |
18 | 22 | ||
19 | #include <mach/dma.h> | ||
20 | |||
21 | |||
22 | #define UCB1X00_ATTR(name,input)\ | 23 | #define UCB1X00_ATTR(name,input)\ |
23 | static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ | 24 | static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ |
24 | char *buf) \ | 25 | char *buf) \ |
@@ -38,14 +39,45 @@ UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2); | |||
38 | 39 | ||
39 | static int ucb1x00_assabet_add(struct ucb1x00_dev *dev) | 40 | static int ucb1x00_assabet_add(struct ucb1x00_dev *dev) |
40 | { | 41 | { |
41 | device_create_file(&dev->ucb->dev, &dev_attr_vbatt); | 42 | struct ucb1x00 *ucb = dev->ucb; |
42 | device_create_file(&dev->ucb->dev, &dev_attr_vcharger); | 43 | struct platform_device *pdev; |
43 | device_create_file(&dev->ucb->dev, &dev_attr_batt_temp); | 44 | struct gpio_keys_platform_data keys; |
45 | static struct gpio_keys_button buttons[6]; | ||
46 | unsigned i; | ||
47 | |||
48 | memset(buttons, 0, sizeof(buttons)); | ||
49 | memset(&keys, 0, sizeof(keys)); | ||
50 | |||
51 | for (i = 0; i < ARRAY_SIZE(buttons); i++) { | ||
52 | buttons[i].code = BTN_0 + i; | ||
53 | buttons[i].gpio = ucb->gpio.base + i; | ||
54 | buttons[i].type = EV_KEY; | ||
55 | buttons[i].can_disable = true; | ||
56 | } | ||
57 | |||
58 | keys.buttons = buttons; | ||
59 | keys.nbuttons = ARRAY_SIZE(buttons); | ||
60 | keys.poll_interval = 50; | ||
61 | keys.name = "ucb1x00"; | ||
62 | |||
63 | pdev = platform_device_register_data(&ucb->dev, "gpio-keys", -1, | ||
64 | &keys, sizeof(keys)); | ||
65 | |||
66 | device_create_file(&ucb->dev, &dev_attr_vbatt); | ||
67 | device_create_file(&ucb->dev, &dev_attr_vcharger); | ||
68 | device_create_file(&ucb->dev, &dev_attr_batt_temp); | ||
69 | |||
70 | dev->priv = pdev; | ||
44 | return 0; | 71 | return 0; |
45 | } | 72 | } |
46 | 73 | ||
47 | static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev) | 74 | static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev) |
48 | { | 75 | { |
76 | struct platform_device *pdev = dev->priv; | ||
77 | |||
78 | if (!IS_ERR(pdev)) | ||
79 | platform_device_unregister(pdev); | ||
80 | |||
49 | device_remove_file(&dev->ucb->dev, &dev_attr_batt_temp); | 81 | device_remove_file(&dev->ucb->dev, &dev_attr_batt_temp); |
50 | device_remove_file(&dev->ucb->dev, &dev_attr_vcharger); | 82 | device_remove_file(&dev->ucb->dev, &dev_attr_vcharger); |
51 | device_remove_file(&dev->ucb->dev, &dev_attr_vbatt); | 83 | device_remove_file(&dev->ucb->dev, &dev_attr_vbatt); |
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index febc90cdef7e..70f02daeb22a 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c | |||
@@ -23,14 +23,12 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/irq.h> | ||
26 | #include <linux/device.h> | 27 | #include <linux/device.h> |
27 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
28 | #include <linux/mfd/ucb1x00.h> | 29 | #include <linux/mfd/ucb1x00.h> |
30 | #include <linux/pm.h> | ||
29 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
30 | #include <linux/semaphore.h> | ||
31 | |||
32 | #include <mach/dma.h> | ||
33 | #include <mach/hardware.h> | ||
34 | 32 | ||
35 | static DEFINE_MUTEX(ucb1x00_mutex); | 33 | static DEFINE_MUTEX(ucb1x00_mutex); |
36 | static LIST_HEAD(ucb1x00_drivers); | 34 | static LIST_HEAD(ucb1x00_drivers); |
@@ -102,7 +100,7 @@ void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear) | |||
102 | * ucb1x00_enable must have been called to enable the comms | 100 | * ucb1x00_enable must have been called to enable the comms |
103 | * before using this function. | 101 | * before using this function. |
104 | * | 102 | * |
105 | * This function does not take any semaphores or spinlocks. | 103 | * This function does not take any mutexes or spinlocks. |
106 | */ | 104 | */ |
107 | unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) | 105 | unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) |
108 | { | 106 | { |
@@ -120,14 +118,22 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
120 | else | 118 | else |
121 | ucb->io_out &= ~(1 << offset); | 119 | ucb->io_out &= ~(1 << offset); |
122 | 120 | ||
121 | ucb1x00_enable(ucb); | ||
123 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); | 122 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); |
123 | ucb1x00_disable(ucb); | ||
124 | spin_unlock_irqrestore(&ucb->io_lock, flags); | 124 | spin_unlock_irqrestore(&ucb->io_lock, flags); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) | 127 | static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) |
128 | { | 128 | { |
129 | struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); | 129 | struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); |
130 | return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset); | 130 | unsigned val; |
131 | |||
132 | ucb1x00_enable(ucb); | ||
133 | val = ucb1x00_reg_read(ucb, UCB_IO_DATA); | ||
134 | ucb1x00_disable(ucb); | ||
135 | |||
136 | return val & (1 << offset); | ||
131 | } | 137 | } |
132 | 138 | ||
133 | static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 139 | static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
@@ -137,7 +143,9 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | |||
137 | 143 | ||
138 | spin_lock_irqsave(&ucb->io_lock, flags); | 144 | spin_lock_irqsave(&ucb->io_lock, flags); |
139 | ucb->io_dir &= ~(1 << offset); | 145 | ucb->io_dir &= ~(1 << offset); |
146 | ucb1x00_enable(ucb); | ||
140 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); | 147 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); |
148 | ucb1x00_disable(ucb); | ||
141 | spin_unlock_irqrestore(&ucb->io_lock, flags); | 149 | spin_unlock_irqrestore(&ucb->io_lock, flags); |
142 | 150 | ||
143 | return 0; | 151 | return 0; |
@@ -157,6 +165,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
157 | else | 165 | else |
158 | ucb->io_out &= ~mask; | 166 | ucb->io_out &= ~mask; |
159 | 167 | ||
168 | ucb1x00_enable(ucb); | ||
160 | if (old != ucb->io_out) | 169 | if (old != ucb->io_out) |
161 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); | 170 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); |
162 | 171 | ||
@@ -164,11 +173,19 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
164 | ucb->io_dir |= mask; | 173 | ucb->io_dir |= mask; |
165 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); | 174 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); |
166 | } | 175 | } |
176 | ucb1x00_disable(ucb); | ||
167 | spin_unlock_irqrestore(&ucb->io_lock, flags); | 177 | spin_unlock_irqrestore(&ucb->io_lock, flags); |
168 | 178 | ||
169 | return 0; | 179 | return 0; |
170 | } | 180 | } |
171 | 181 | ||
182 | static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset) | ||
183 | { | ||
184 | struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); | ||
185 | |||
186 | return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO; | ||
187 | } | ||
188 | |||
172 | /* | 189 | /* |
173 | * UCB1300 data sheet says we must: | 190 | * UCB1300 data sheet says we must: |
174 | * 1. enable ADC => 5us (including reference startup time) | 191 | * 1. enable ADC => 5us (including reference startup time) |
@@ -186,7 +203,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
186 | * Any code wishing to use the ADC converter must call this | 203 | * Any code wishing to use the ADC converter must call this |
187 | * function prior to using it. | 204 | * function prior to using it. |
188 | * | 205 | * |
189 | * This function takes the ADC semaphore to prevent two or more | 206 | * This function takes the ADC mutex to prevent two or more |
190 | * concurrent uses, and therefore may sleep. As a result, it | 207 | * concurrent uses, and therefore may sleep. As a result, it |
191 | * can only be called from process context, not interrupt | 208 | * can only be called from process context, not interrupt |
192 | * context. | 209 | * context. |
@@ -196,7 +213,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset | |||
196 | */ | 213 | */ |
197 | void ucb1x00_adc_enable(struct ucb1x00 *ucb) | 214 | void ucb1x00_adc_enable(struct ucb1x00 *ucb) |
198 | { | 215 | { |
199 | down(&ucb->adc_sem); | 216 | mutex_lock(&ucb->adc_mutex); |
200 | 217 | ||
201 | ucb->adc_cr |= UCB_ADC_ENA; | 218 | ucb->adc_cr |= UCB_ADC_ENA; |
202 | 219 | ||
@@ -218,7 +235,7 @@ void ucb1x00_adc_enable(struct ucb1x00 *ucb) | |||
218 | * complete (2 frames max without sync). | 235 | * complete (2 frames max without sync). |
219 | * | 236 | * |
220 | * If called for a synchronised ADC conversion, it may sleep | 237 | * If called for a synchronised ADC conversion, it may sleep |
221 | * with the ADC semaphore held. | 238 | * with the ADC mutex held. |
222 | */ | 239 | */ |
223 | unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) | 240 | unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) |
224 | { | 241 | { |
@@ -246,7 +263,7 @@ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) | |||
246 | * ucb1x00_adc_disable - disable the ADC converter | 263 | * ucb1x00_adc_disable - disable the ADC converter |
247 | * @ucb: UCB1x00 structure describing chip | 264 | * @ucb: UCB1x00 structure describing chip |
248 | * | 265 | * |
249 | * Disable the ADC converter and release the ADC semaphore. | 266 | * Disable the ADC converter and release the ADC mutex. |
250 | */ | 267 | */ |
251 | void ucb1x00_adc_disable(struct ucb1x00 *ucb) | 268 | void ucb1x00_adc_disable(struct ucb1x00 *ucb) |
252 | { | 269 | { |
@@ -254,7 +271,7 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb) | |||
254 | ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); | 271 | ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); |
255 | ucb1x00_disable(ucb); | 272 | ucb1x00_disable(ucb); |
256 | 273 | ||
257 | up(&ucb->adc_sem); | 274 | mutex_unlock(&ucb->adc_mutex); |
258 | } | 275 | } |
259 | 276 | ||
260 | /* | 277 | /* |
@@ -265,10 +282,9 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb) | |||
265 | * SIBCLK to talk to the chip. We leave the clock running until | 282 | * SIBCLK to talk to the chip. We leave the clock running until |
266 | * we have finished processing all interrupts from the chip. | 283 | * we have finished processing all interrupts from the chip. |
267 | */ | 284 | */ |
268 | static irqreturn_t ucb1x00_irq(int irqnr, void *devid) | 285 | static void ucb1x00_irq(unsigned int irq, struct irq_desc *desc) |
269 | { | 286 | { |
270 | struct ucb1x00 *ucb = devid; | 287 | struct ucb1x00 *ucb = irq_desc_get_handler_data(desc); |
271 | struct ucb1x00_irq *irq; | ||
272 | unsigned int isr, i; | 288 | unsigned int isr, i; |
273 | 289 | ||
274 | ucb1x00_enable(ucb); | 290 | ucb1x00_enable(ucb); |
@@ -276,157 +292,104 @@ static irqreturn_t ucb1x00_irq(int irqnr, void *devid) | |||
276 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); | 292 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); |
277 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); | 293 | ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); |
278 | 294 | ||
279 | for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++) | 295 | for (i = 0; i < 16 && isr; i++, isr >>= 1, irq++) |
280 | if (isr & 1 && irq->fn) | 296 | if (isr & 1) |
281 | irq->fn(i, irq->devid); | 297 | generic_handle_irq(ucb->irq_base + i); |
282 | ucb1x00_disable(ucb); | 298 | ucb1x00_disable(ucb); |
283 | |||
284 | return IRQ_HANDLED; | ||
285 | } | 299 | } |
286 | 300 | ||
287 | /** | 301 | static void ucb1x00_irq_update(struct ucb1x00 *ucb, unsigned mask) |
288 | * ucb1x00_hook_irq - hook a UCB1x00 interrupt | ||
289 | * @ucb: UCB1x00 structure describing chip | ||
290 | * @idx: interrupt index | ||
291 | * @fn: function to call when interrupt is triggered | ||
292 | * @devid: device id to pass to interrupt handler | ||
293 | * | ||
294 | * Hook the specified interrupt. You can only register one handler | ||
295 | * for each interrupt source. The interrupt source is not enabled | ||
296 | * by this function; use ucb1x00_enable_irq instead. | ||
297 | * | ||
298 | * Interrupt handlers will be called with other interrupts enabled. | ||
299 | * | ||
300 | * Returns zero on success, or one of the following errors: | ||
301 | * -EINVAL if the interrupt index is invalid | ||
302 | * -EBUSY if the interrupt has already been hooked | ||
303 | */ | ||
304 | int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid) | ||
305 | { | 302 | { |
306 | struct ucb1x00_irq *irq; | 303 | ucb1x00_enable(ucb); |
307 | int ret = -EINVAL; | 304 | if (ucb->irq_ris_enbl & mask) |
308 | 305 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | |
309 | if (idx < 16) { | 306 | ucb->irq_mask); |
310 | irq = ucb->irq_handler + idx; | 307 | if (ucb->irq_fal_enbl & mask) |
311 | ret = -EBUSY; | 308 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & |
312 | 309 | ucb->irq_mask); | |
313 | spin_lock_irq(&ucb->lock); | 310 | ucb1x00_disable(ucb); |
314 | if (irq->fn == NULL) { | ||
315 | irq->devid = devid; | ||
316 | irq->fn = fn; | ||
317 | ret = 0; | ||
318 | } | ||
319 | spin_unlock_irq(&ucb->lock); | ||
320 | } | ||
321 | return ret; | ||
322 | } | 311 | } |
323 | 312 | ||
324 | /** | 313 | static void ucb1x00_irq_noop(struct irq_data *data) |
325 | * ucb1x00_enable_irq - enable an UCB1x00 interrupt source | ||
326 | * @ucb: UCB1x00 structure describing chip | ||
327 | * @idx: interrupt index | ||
328 | * @edges: interrupt edges to enable | ||
329 | * | ||
330 | * Enable the specified interrupt to trigger on %UCB_RISING, | ||
331 | * %UCB_FALLING or both edges. The interrupt should have been | ||
332 | * hooked by ucb1x00_hook_irq. | ||
333 | */ | ||
334 | void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) | ||
335 | { | 314 | { |
336 | unsigned long flags; | 315 | } |
337 | 316 | ||
338 | if (idx < 16) { | 317 | static void ucb1x00_irq_mask(struct irq_data *data) |
339 | spin_lock_irqsave(&ucb->lock, flags); | 318 | { |
319 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); | ||
320 | unsigned mask = 1 << (data->irq - ucb->irq_base); | ||
340 | 321 | ||
341 | ucb1x00_enable(ucb); | 322 | raw_spin_lock(&ucb->irq_lock); |
342 | if (edges & UCB_RISING) { | 323 | ucb->irq_mask &= ~mask; |
343 | ucb->irq_ris_enbl |= 1 << idx; | 324 | ucb1x00_irq_update(ucb, mask); |
344 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); | 325 | raw_spin_unlock(&ucb->irq_lock); |
345 | } | ||
346 | if (edges & UCB_FALLING) { | ||
347 | ucb->irq_fal_enbl |= 1 << idx; | ||
348 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); | ||
349 | } | ||
350 | ucb1x00_disable(ucb); | ||
351 | spin_unlock_irqrestore(&ucb->lock, flags); | ||
352 | } | ||
353 | } | 326 | } |
354 | 327 | ||
355 | /** | 328 | static void ucb1x00_irq_unmask(struct irq_data *data) |
356 | * ucb1x00_disable_irq - disable an UCB1x00 interrupt source | ||
357 | * @ucb: UCB1x00 structure describing chip | ||
358 | * @edges: interrupt edges to disable | ||
359 | * | ||
360 | * Disable the specified interrupt triggering on the specified | ||
361 | * (%UCB_RISING, %UCB_FALLING or both) edges. | ||
362 | */ | ||
363 | void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) | ||
364 | { | 329 | { |
365 | unsigned long flags; | 330 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); |
331 | unsigned mask = 1 << (data->irq - ucb->irq_base); | ||
366 | 332 | ||
367 | if (idx < 16) { | 333 | raw_spin_lock(&ucb->irq_lock); |
368 | spin_lock_irqsave(&ucb->lock, flags); | 334 | ucb->irq_mask |= mask; |
369 | 335 | ucb1x00_irq_update(ucb, mask); | |
370 | ucb1x00_enable(ucb); | 336 | raw_spin_unlock(&ucb->irq_lock); |
371 | if (edges & UCB_RISING) { | ||
372 | ucb->irq_ris_enbl &= ~(1 << idx); | ||
373 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); | ||
374 | } | ||
375 | if (edges & UCB_FALLING) { | ||
376 | ucb->irq_fal_enbl &= ~(1 << idx); | ||
377 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); | ||
378 | } | ||
379 | ucb1x00_disable(ucb); | ||
380 | spin_unlock_irqrestore(&ucb->lock, flags); | ||
381 | } | ||
382 | } | 337 | } |
383 | 338 | ||
384 | /** | 339 | static int ucb1x00_irq_set_type(struct irq_data *data, unsigned int type) |
385 | * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt | ||
386 | * @ucb: UCB1x00 structure describing chip | ||
387 | * @idx: interrupt index | ||
388 | * @devid: device id. | ||
389 | * | ||
390 | * Disable the interrupt source and remove the handler. devid must | ||
391 | * match the devid passed when hooking the interrupt. | ||
392 | * | ||
393 | * Returns zero on success, or one of the following errors: | ||
394 | * -EINVAL if the interrupt index is invalid | ||
395 | * -ENOENT if devid does not match | ||
396 | */ | ||
397 | int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid) | ||
398 | { | 340 | { |
399 | struct ucb1x00_irq *irq; | 341 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); |
400 | int ret; | 342 | unsigned mask = 1 << (data->irq - ucb->irq_base); |
401 | 343 | ||
402 | if (idx >= 16) | 344 | raw_spin_lock(&ucb->irq_lock); |
403 | goto bad; | 345 | if (type & IRQ_TYPE_EDGE_RISING) |
346 | ucb->irq_ris_enbl |= mask; | ||
347 | else | ||
348 | ucb->irq_ris_enbl &= ~mask; | ||
404 | 349 | ||
405 | irq = ucb->irq_handler + idx; | 350 | if (type & IRQ_TYPE_EDGE_FALLING) |
406 | ret = -ENOENT; | 351 | ucb->irq_fal_enbl |= mask; |
352 | else | ||
353 | ucb->irq_fal_enbl &= ~mask; | ||
354 | if (ucb->irq_mask & mask) { | ||
355 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | ||
356 | ucb->irq_mask); | ||
357 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & | ||
358 | ucb->irq_mask); | ||
359 | } | ||
360 | raw_spin_unlock(&ucb->irq_lock); | ||
407 | 361 | ||
408 | spin_lock_irq(&ucb->lock); | 362 | return 0; |
409 | if (irq->devid == devid) { | 363 | } |
410 | ucb->irq_ris_enbl &= ~(1 << idx); | ||
411 | ucb->irq_fal_enbl &= ~(1 << idx); | ||
412 | 364 | ||
413 | ucb1x00_enable(ucb); | 365 | static int ucb1x00_irq_set_wake(struct irq_data *data, unsigned int on) |
414 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); | 366 | { |
415 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); | 367 | struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data); |
416 | ucb1x00_disable(ucb); | 368 | struct ucb1x00_plat_data *pdata = ucb->mcp->attached_device.platform_data; |
369 | unsigned mask = 1 << (data->irq - ucb->irq_base); | ||
417 | 370 | ||
418 | irq->fn = NULL; | 371 | if (!pdata || !pdata->can_wakeup) |
419 | irq->devid = NULL; | 372 | return -EINVAL; |
420 | ret = 0; | ||
421 | } | ||
422 | spin_unlock_irq(&ucb->lock); | ||
423 | return ret; | ||
424 | 373 | ||
425 | bad: | 374 | raw_spin_lock(&ucb->irq_lock); |
426 | printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx); | 375 | if (on) |
427 | return -EINVAL; | 376 | ucb->irq_wake |= mask; |
377 | else | ||
378 | ucb->irq_wake &= ~mask; | ||
379 | raw_spin_unlock(&ucb->irq_lock); | ||
380 | |||
381 | return 0; | ||
428 | } | 382 | } |
429 | 383 | ||
384 | static struct irq_chip ucb1x00_irqchip = { | ||
385 | .name = "ucb1x00", | ||
386 | .irq_ack = ucb1x00_irq_noop, | ||
387 | .irq_mask = ucb1x00_irq_mask, | ||
388 | .irq_unmask = ucb1x00_irq_unmask, | ||
389 | .irq_set_type = ucb1x00_irq_set_type, | ||
390 | .irq_set_wake = ucb1x00_irq_set_wake, | ||
391 | }; | ||
392 | |||
430 | static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) | 393 | static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) |
431 | { | 394 | { |
432 | struct ucb1x00_dev *dev; | 395 | struct ucb1x00_dev *dev; |
@@ -440,8 +403,8 @@ static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) | |||
440 | ret = drv->add(dev); | 403 | ret = drv->add(dev); |
441 | 404 | ||
442 | if (ret == 0) { | 405 | if (ret == 0) { |
443 | list_add(&dev->dev_node, &ucb->devs); | 406 | list_add_tail(&dev->dev_node, &ucb->devs); |
444 | list_add(&dev->drv_node, &drv->devs); | 407 | list_add_tail(&dev->drv_node, &drv->devs); |
445 | } else { | 408 | } else { |
446 | kfree(dev); | 409 | kfree(dev); |
447 | } | 410 | } |
@@ -533,98 +496,126 @@ static struct class ucb1x00_class = { | |||
533 | 496 | ||
534 | static int ucb1x00_probe(struct mcp *mcp) | 497 | static int ucb1x00_probe(struct mcp *mcp) |
535 | { | 498 | { |
536 | struct ucb1x00 *ucb; | 499 | struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; |
537 | struct ucb1x00_driver *drv; | 500 | struct ucb1x00_driver *drv; |
538 | unsigned int id; | 501 | struct ucb1x00 *ucb; |
502 | unsigned id, i, irq_base; | ||
539 | int ret = -ENODEV; | 503 | int ret = -ENODEV; |
540 | int temp; | 504 | |
505 | /* Tell the platform to deassert the UCB1x00 reset */ | ||
506 | if (pdata && pdata->reset) | ||
507 | pdata->reset(UCB_RST_PROBE); | ||
541 | 508 | ||
542 | mcp_enable(mcp); | 509 | mcp_enable(mcp); |
543 | id = mcp_reg_read(mcp, UCB_ID); | 510 | id = mcp_reg_read(mcp, UCB_ID); |
511 | mcp_disable(mcp); | ||
544 | 512 | ||
545 | if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { | 513 | if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { |
546 | printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); | 514 | printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); |
547 | goto err_disable; | 515 | goto out; |
548 | } | 516 | } |
549 | 517 | ||
550 | ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL); | 518 | ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL); |
551 | ret = -ENOMEM; | 519 | ret = -ENOMEM; |
552 | if (!ucb) | 520 | if (!ucb) |
553 | goto err_disable; | 521 | goto out; |
554 | |||
555 | 522 | ||
523 | device_initialize(&ucb->dev); | ||
556 | ucb->dev.class = &ucb1x00_class; | 524 | ucb->dev.class = &ucb1x00_class; |
557 | ucb->dev.parent = &mcp->attached_device; | 525 | ucb->dev.parent = &mcp->attached_device; |
558 | dev_set_name(&ucb->dev, "ucb1x00"); | 526 | dev_set_name(&ucb->dev, "ucb1x00"); |
559 | 527 | ||
560 | spin_lock_init(&ucb->lock); | 528 | raw_spin_lock_init(&ucb->irq_lock); |
561 | spin_lock_init(&ucb->io_lock); | 529 | spin_lock_init(&ucb->io_lock); |
562 | sema_init(&ucb->adc_sem, 1); | 530 | mutex_init(&ucb->adc_mutex); |
563 | 531 | ||
564 | ucb->id = id; | 532 | ucb->id = id; |
565 | ucb->mcp = mcp; | 533 | ucb->mcp = mcp; |
534 | |||
535 | ret = device_add(&ucb->dev); | ||
536 | if (ret) | ||
537 | goto err_dev_add; | ||
538 | |||
539 | ucb1x00_enable(ucb); | ||
566 | ucb->irq = ucb1x00_detect_irq(ucb); | 540 | ucb->irq = ucb1x00_detect_irq(ucb); |
541 | ucb1x00_disable(ucb); | ||
567 | if (ucb->irq == NO_IRQ) { | 542 | if (ucb->irq == NO_IRQ) { |
568 | printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); | 543 | dev_err(&ucb->dev, "IRQ probe failed\n"); |
569 | ret = -ENODEV; | 544 | ret = -ENODEV; |
570 | goto err_free; | 545 | goto err_no_irq; |
571 | } | 546 | } |
572 | 547 | ||
573 | ucb->gpio.base = -1; | 548 | ucb->gpio.base = -1; |
574 | if (mcp->gpio_base != 0) { | 549 | irq_base = pdata ? pdata->irq_base : 0; |
550 | ucb->irq_base = irq_alloc_descs(-1, irq_base, 16, -1); | ||
551 | if (ucb->irq_base < 0) { | ||
552 | dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n", | ||
553 | ucb->irq_base); | ||
554 | goto err_irq_alloc; | ||
555 | } | ||
556 | |||
557 | for (i = 0; i < 16; i++) { | ||
558 | unsigned irq = ucb->irq_base + i; | ||
559 | |||
560 | irq_set_chip_and_handler(irq, &ucb1x00_irqchip, handle_edge_irq); | ||
561 | irq_set_chip_data(irq, ucb); | ||
562 | set_irq_flags(irq, IRQF_VALID | IRQ_NOREQUEST); | ||
563 | } | ||
564 | |||
565 | irq_set_irq_type(ucb->irq, IRQ_TYPE_EDGE_RISING); | ||
566 | irq_set_handler_data(ucb->irq, ucb); | ||
567 | irq_set_chained_handler(ucb->irq, ucb1x00_irq); | ||
568 | |||
569 | if (pdata && pdata->gpio_base) { | ||
575 | ucb->gpio.label = dev_name(&ucb->dev); | 570 | ucb->gpio.label = dev_name(&ucb->dev); |
576 | ucb->gpio.base = mcp->gpio_base; | 571 | ucb->gpio.dev = &ucb->dev; |
572 | ucb->gpio.owner = THIS_MODULE; | ||
573 | ucb->gpio.base = pdata->gpio_base; | ||
577 | ucb->gpio.ngpio = 10; | 574 | ucb->gpio.ngpio = 10; |
578 | ucb->gpio.set = ucb1x00_gpio_set; | 575 | ucb->gpio.set = ucb1x00_gpio_set; |
579 | ucb->gpio.get = ucb1x00_gpio_get; | 576 | ucb->gpio.get = ucb1x00_gpio_get; |
580 | ucb->gpio.direction_input = ucb1x00_gpio_direction_input; | 577 | ucb->gpio.direction_input = ucb1x00_gpio_direction_input; |
581 | ucb->gpio.direction_output = ucb1x00_gpio_direction_output; | 578 | ucb->gpio.direction_output = ucb1x00_gpio_direction_output; |
579 | ucb->gpio.to_irq = ucb1x00_to_irq; | ||
582 | ret = gpiochip_add(&ucb->gpio); | 580 | ret = gpiochip_add(&ucb->gpio); |
583 | if (ret) | 581 | if (ret) |
584 | goto err_free; | 582 | goto err_gpio_add; |
585 | } else | 583 | } else |
586 | dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); | 584 | dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); |
587 | 585 | ||
588 | ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, | ||
589 | "UCB1x00", ucb); | ||
590 | if (ret) { | ||
591 | printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", | ||
592 | ucb->irq, ret); | ||
593 | goto err_gpio; | ||
594 | } | ||
595 | |||
596 | mcp_set_drvdata(mcp, ucb); | 586 | mcp_set_drvdata(mcp, ucb); |
597 | 587 | ||
598 | ret = device_register(&ucb->dev); | 588 | if (pdata) |
599 | if (ret) | 589 | device_set_wakeup_capable(&ucb->dev, pdata->can_wakeup); |
600 | goto err_irq; | ||
601 | |||
602 | 590 | ||
603 | INIT_LIST_HEAD(&ucb->devs); | 591 | INIT_LIST_HEAD(&ucb->devs); |
604 | mutex_lock(&ucb1x00_mutex); | 592 | mutex_lock(&ucb1x00_mutex); |
605 | list_add(&ucb->node, &ucb1x00_devices); | 593 | list_add_tail(&ucb->node, &ucb1x00_devices); |
606 | list_for_each_entry(drv, &ucb1x00_drivers, node) { | 594 | list_for_each_entry(drv, &ucb1x00_drivers, node) { |
607 | ucb1x00_add_dev(ucb, drv); | 595 | ucb1x00_add_dev(ucb, drv); |
608 | } | 596 | } |
609 | mutex_unlock(&ucb1x00_mutex); | 597 | mutex_unlock(&ucb1x00_mutex); |
610 | 598 | ||
611 | goto out; | 599 | return ret; |
612 | 600 | ||
613 | err_irq: | 601 | err_gpio_add: |
614 | free_irq(ucb->irq, ucb); | 602 | irq_set_chained_handler(ucb->irq, NULL); |
615 | err_gpio: | 603 | err_irq_alloc: |
616 | if (ucb->gpio.base != -1) | 604 | if (ucb->irq_base > 0) |
617 | temp = gpiochip_remove(&ucb->gpio); | 605 | irq_free_descs(ucb->irq_base, 16); |
618 | err_free: | 606 | err_no_irq: |
619 | kfree(ucb); | 607 | device_del(&ucb->dev); |
620 | err_disable: | 608 | err_dev_add: |
621 | mcp_disable(mcp); | 609 | put_device(&ucb->dev); |
622 | out: | 610 | out: |
611 | if (pdata && pdata->reset) | ||
612 | pdata->reset(UCB_RST_PROBE_FAIL); | ||
623 | return ret; | 613 | return ret; |
624 | } | 614 | } |
625 | 615 | ||
626 | static void ucb1x00_remove(struct mcp *mcp) | 616 | static void ucb1x00_remove(struct mcp *mcp) |
627 | { | 617 | { |
618 | struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; | ||
628 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 619 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); |
629 | struct list_head *l, *n; | 620 | struct list_head *l, *n; |
630 | int ret; | 621 | int ret; |
@@ -643,8 +634,12 @@ static void ucb1x00_remove(struct mcp *mcp) | |||
643 | dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret); | 634 | dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret); |
644 | } | 635 | } |
645 | 636 | ||
646 | free_irq(ucb->irq, ucb); | 637 | irq_set_chained_handler(ucb->irq, NULL); |
638 | irq_free_descs(ucb->irq_base, 16); | ||
647 | device_unregister(&ucb->dev); | 639 | device_unregister(&ucb->dev); |
640 | |||
641 | if (pdata && pdata->reset) | ||
642 | pdata->reset(UCB_RST_REMOVE); | ||
648 | } | 643 | } |
649 | 644 | ||
650 | int ucb1x00_register_driver(struct ucb1x00_driver *drv) | 645 | int ucb1x00_register_driver(struct ucb1x00_driver *drv) |
@@ -653,7 +648,7 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv) | |||
653 | 648 | ||
654 | INIT_LIST_HEAD(&drv->devs); | 649 | INIT_LIST_HEAD(&drv->devs); |
655 | mutex_lock(&ucb1x00_mutex); | 650 | mutex_lock(&ucb1x00_mutex); |
656 | list_add(&drv->node, &ucb1x00_drivers); | 651 | list_add_tail(&drv->node, &ucb1x00_drivers); |
657 | list_for_each_entry(ucb, &ucb1x00_devices, node) { | 652 | list_for_each_entry(ucb, &ucb1x00_devices, node) { |
658 | ucb1x00_add_dev(ucb, drv); | 653 | ucb1x00_add_dev(ucb, drv); |
659 | } | 654 | } |
@@ -674,44 +669,86 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv) | |||
674 | mutex_unlock(&ucb1x00_mutex); | 669 | mutex_unlock(&ucb1x00_mutex); |
675 | } | 670 | } |
676 | 671 | ||
677 | static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) | 672 | static int ucb1x00_suspend(struct device *dev) |
678 | { | 673 | { |
679 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 674 | struct ucb1x00_plat_data *pdata = dev->platform_data; |
680 | struct ucb1x00_dev *dev; | 675 | struct ucb1x00 *ucb = dev_get_drvdata(dev); |
676 | struct ucb1x00_dev *udev; | ||
681 | 677 | ||
682 | mutex_lock(&ucb1x00_mutex); | 678 | mutex_lock(&ucb1x00_mutex); |
683 | list_for_each_entry(dev, &ucb->devs, dev_node) { | 679 | list_for_each_entry(udev, &ucb->devs, dev_node) { |
684 | if (dev->drv->suspend) | 680 | if (udev->drv->suspend) |
685 | dev->drv->suspend(dev, state); | 681 | udev->drv->suspend(udev); |
686 | } | 682 | } |
687 | mutex_unlock(&ucb1x00_mutex); | 683 | mutex_unlock(&ucb1x00_mutex); |
684 | |||
685 | if (ucb->irq_wake) { | ||
686 | unsigned long flags; | ||
687 | |||
688 | raw_spin_lock_irqsave(&ucb->irq_lock, flags); | ||
689 | ucb1x00_enable(ucb); | ||
690 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | ||
691 | ucb->irq_wake); | ||
692 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & | ||
693 | ucb->irq_wake); | ||
694 | ucb1x00_disable(ucb); | ||
695 | raw_spin_unlock_irqrestore(&ucb->irq_lock, flags); | ||
696 | |||
697 | enable_irq_wake(ucb->irq); | ||
698 | } else if (pdata && pdata->reset) | ||
699 | pdata->reset(UCB_RST_SUSPEND); | ||
700 | |||
688 | return 0; | 701 | return 0; |
689 | } | 702 | } |
690 | 703 | ||
691 | static int ucb1x00_resume(struct mcp *mcp) | 704 | static int ucb1x00_resume(struct device *dev) |
692 | { | 705 | { |
693 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 706 | struct ucb1x00_plat_data *pdata = dev->platform_data; |
694 | struct ucb1x00_dev *dev; | 707 | struct ucb1x00 *ucb = dev_get_drvdata(dev); |
708 | struct ucb1x00_dev *udev; | ||
709 | |||
710 | if (!ucb->irq_wake && pdata && pdata->reset) | ||
711 | pdata->reset(UCB_RST_RESUME); | ||
695 | 712 | ||
713 | ucb1x00_enable(ucb); | ||
696 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); | 714 | ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); |
697 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); | 715 | ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); |
716 | |||
717 | if (ucb->irq_wake) { | ||
718 | unsigned long flags; | ||
719 | |||
720 | raw_spin_lock_irqsave(&ucb->irq_lock, flags); | ||
721 | ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & | ||
722 | ucb->irq_mask); | ||
723 | ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & | ||
724 | ucb->irq_mask); | ||
725 | raw_spin_unlock_irqrestore(&ucb->irq_lock, flags); | ||
726 | |||
727 | disable_irq_wake(ucb->irq); | ||
728 | } | ||
729 | ucb1x00_disable(ucb); | ||
730 | |||
698 | mutex_lock(&ucb1x00_mutex); | 731 | mutex_lock(&ucb1x00_mutex); |
699 | list_for_each_entry(dev, &ucb->devs, dev_node) { | 732 | list_for_each_entry(udev, &ucb->devs, dev_node) { |
700 | if (dev->drv->resume) | 733 | if (udev->drv->resume) |
701 | dev->drv->resume(dev); | 734 | udev->drv->resume(udev); |
702 | } | 735 | } |
703 | mutex_unlock(&ucb1x00_mutex); | 736 | mutex_unlock(&ucb1x00_mutex); |
704 | return 0; | 737 | return 0; |
705 | } | 738 | } |
706 | 739 | ||
740 | static const struct dev_pm_ops ucb1x00_pm_ops = { | ||
741 | SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume) | ||
742 | }; | ||
743 | |||
707 | static struct mcp_driver ucb1x00_driver = { | 744 | static struct mcp_driver ucb1x00_driver = { |
708 | .drv = { | 745 | .drv = { |
709 | .name = "ucb1x00", | 746 | .name = "ucb1x00", |
747 | .owner = THIS_MODULE, | ||
748 | .pm = &ucb1x00_pm_ops, | ||
710 | }, | 749 | }, |
711 | .probe = ucb1x00_probe, | 750 | .probe = ucb1x00_probe, |
712 | .remove = ucb1x00_remove, | 751 | .remove = ucb1x00_remove, |
713 | .suspend = ucb1x00_suspend, | ||
714 | .resume = ucb1x00_resume, | ||
715 | }; | 752 | }; |
716 | 753 | ||
717 | static int __init ucb1x00_init(void) | 754 | static int __init ucb1x00_init(void) |
@@ -742,14 +779,10 @@ EXPORT_SYMBOL(ucb1x00_adc_enable); | |||
742 | EXPORT_SYMBOL(ucb1x00_adc_read); | 779 | EXPORT_SYMBOL(ucb1x00_adc_read); |
743 | EXPORT_SYMBOL(ucb1x00_adc_disable); | 780 | EXPORT_SYMBOL(ucb1x00_adc_disable); |
744 | 781 | ||
745 | EXPORT_SYMBOL(ucb1x00_hook_irq); | ||
746 | EXPORT_SYMBOL(ucb1x00_free_irq); | ||
747 | EXPORT_SYMBOL(ucb1x00_enable_irq); | ||
748 | EXPORT_SYMBOL(ucb1x00_disable_irq); | ||
749 | |||
750 | EXPORT_SYMBOL(ucb1x00_register_driver); | 782 | EXPORT_SYMBOL(ucb1x00_register_driver); |
751 | EXPORT_SYMBOL(ucb1x00_unregister_driver); | 783 | EXPORT_SYMBOL(ucb1x00_unregister_driver); |
752 | 784 | ||
785 | MODULE_ALIAS("mcp:ucb1x00"); | ||
753 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); | 786 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); |
754 | MODULE_DESCRIPTION("UCB1x00 core driver"); | 787 | MODULE_DESCRIPTION("UCB1x00 core driver"); |
755 | MODULE_LICENSE("GPL"); | 788 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 63a3cbdfa3f3..1e0e20c0e082 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c | |||
@@ -20,8 +20,9 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/moduleparam.h> | 21 | #include <linux/moduleparam.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/smp.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/spinlock.h> | ||
25 | #include <linux/completion.h> | 26 | #include <linux/completion.h> |
26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
@@ -32,7 +33,6 @@ | |||
32 | #include <linux/kthread.h> | 33 | #include <linux/kthread.h> |
33 | #include <linux/mfd/ucb1x00.h> | 34 | #include <linux/mfd/ucb1x00.h> |
34 | 35 | ||
35 | #include <mach/dma.h> | ||
36 | #include <mach/collie.h> | 36 | #include <mach/collie.h> |
37 | #include <asm/mach-types.h> | 37 | #include <asm/mach-types.h> |
38 | 38 | ||
@@ -42,6 +42,8 @@ struct ucb1x00_ts { | |||
42 | struct input_dev *idev; | 42 | struct input_dev *idev; |
43 | struct ucb1x00 *ucb; | 43 | struct ucb1x00 *ucb; |
44 | 44 | ||
45 | spinlock_t irq_lock; | ||
46 | unsigned irq_disabled; | ||
45 | wait_queue_head_t irq_wait; | 47 | wait_queue_head_t irq_wait; |
46 | struct task_struct *rtask; | 48 | struct task_struct *rtask; |
47 | u16 x_res; | 49 | u16 x_res; |
@@ -238,7 +240,12 @@ static int ucb1x00_thread(void *_ts) | |||
238 | if (ucb1x00_ts_pen_down(ts)) { | 240 | if (ucb1x00_ts_pen_down(ts)) { |
239 | set_current_state(TASK_INTERRUPTIBLE); | 241 | set_current_state(TASK_INTERRUPTIBLE); |
240 | 242 | ||
241 | ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); | 243 | spin_lock_irq(&ts->irq_lock); |
244 | if (ts->irq_disabled) { | ||
245 | ts->irq_disabled = 0; | ||
246 | enable_irq(ts->ucb->irq_base + UCB_IRQ_TSPX); | ||
247 | } | ||
248 | spin_unlock_irq(&ts->irq_lock); | ||
242 | ucb1x00_disable(ts->ucb); | 249 | ucb1x00_disable(ts->ucb); |
243 | 250 | ||
244 | /* | 251 | /* |
@@ -281,23 +288,37 @@ static int ucb1x00_thread(void *_ts) | |||
281 | * We only detect touch screen _touches_ with this interrupt | 288 | * We only detect touch screen _touches_ with this interrupt |
282 | * handler, and even then we just schedule our task. | 289 | * handler, and even then we just schedule our task. |
283 | */ | 290 | */ |
284 | static void ucb1x00_ts_irq(int idx, void *id) | 291 | static irqreturn_t ucb1x00_ts_irq(int irq, void *id) |
285 | { | 292 | { |
286 | struct ucb1x00_ts *ts = id; | 293 | struct ucb1x00_ts *ts = id; |
287 | 294 | ||
288 | ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); | 295 | spin_lock(&ts->irq_lock); |
296 | ts->irq_disabled = 1; | ||
297 | disable_irq_nosync(ts->ucb->irq_base + UCB_IRQ_TSPX); | ||
298 | spin_unlock(&ts->irq_lock); | ||
289 | wake_up(&ts->irq_wait); | 299 | wake_up(&ts->irq_wait); |
300 | |||
301 | return IRQ_HANDLED; | ||
290 | } | 302 | } |
291 | 303 | ||
292 | static int ucb1x00_ts_open(struct input_dev *idev) | 304 | static int ucb1x00_ts_open(struct input_dev *idev) |
293 | { | 305 | { |
294 | struct ucb1x00_ts *ts = input_get_drvdata(idev); | 306 | struct ucb1x00_ts *ts = input_get_drvdata(idev); |
307 | unsigned long flags = 0; | ||
295 | int ret = 0; | 308 | int ret = 0; |
296 | 309 | ||
297 | BUG_ON(ts->rtask); | 310 | BUG_ON(ts->rtask); |
298 | 311 | ||
312 | if (machine_is_collie()) | ||
313 | flags = IRQF_TRIGGER_RISING; | ||
314 | else | ||
315 | flags = IRQF_TRIGGER_FALLING; | ||
316 | |||
317 | ts->irq_disabled = 0; | ||
318 | |||
299 | init_waitqueue_head(&ts->irq_wait); | 319 | init_waitqueue_head(&ts->irq_wait); |
300 | ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); | 320 | ret = request_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ucb1x00_ts_irq, |
321 | flags, "ucb1x00-ts", ts); | ||
301 | if (ret < 0) | 322 | if (ret < 0) |
302 | goto out; | 323 | goto out; |
303 | 324 | ||
@@ -314,7 +335,7 @@ static int ucb1x00_ts_open(struct input_dev *idev) | |||
314 | if (!IS_ERR(ts->rtask)) { | 335 | if (!IS_ERR(ts->rtask)) { |
315 | ret = 0; | 336 | ret = 0; |
316 | } else { | 337 | } else { |
317 | ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); | 338 | free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts); |
318 | ts->rtask = NULL; | 339 | ts->rtask = NULL; |
319 | ret = -EFAULT; | 340 | ret = -EFAULT; |
320 | } | 341 | } |
@@ -334,7 +355,7 @@ static void ucb1x00_ts_close(struct input_dev *idev) | |||
334 | kthread_stop(ts->rtask); | 355 | kthread_stop(ts->rtask); |
335 | 356 | ||
336 | ucb1x00_enable(ts->ucb); | 357 | ucb1x00_enable(ts->ucb); |
337 | ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); | 358 | free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts); |
338 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); | 359 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); |
339 | ucb1x00_disable(ts->ucb); | 360 | ucb1x00_disable(ts->ucb); |
340 | } | 361 | } |
@@ -359,11 +380,13 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) | |||
359 | ts->ucb = dev->ucb; | 380 | ts->ucb = dev->ucb; |
360 | ts->idev = idev; | 381 | ts->idev = idev; |
361 | ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; | 382 | ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; |
383 | spin_lock_init(&ts->irq_lock); | ||
362 | 384 | ||
363 | idev->name = "Touchscreen panel"; | 385 | idev->name = "Touchscreen panel"; |
364 | idev->id.product = ts->ucb->id; | 386 | idev->id.product = ts->ucb->id; |
365 | idev->open = ucb1x00_ts_open; | 387 | idev->open = ucb1x00_ts_open; |
366 | idev->close = ucb1x00_ts_close; | 388 | idev->close = ucb1x00_ts_close; |
389 | idev->dev.parent = &ts->ucb->dev; | ||
367 | 390 | ||
368 | idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); | 391 | idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); |
369 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 392 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h index f88c1cc0cb0f..a9e8bd157673 100644 --- a/include/linux/mfd/mcp.h +++ b/include/linux/mfd/mcp.h | |||
@@ -10,8 +10,6 @@ | |||
10 | #ifndef MCP_H | 10 | #ifndef MCP_H |
11 | #define MCP_H | 11 | #define MCP_H |
12 | 12 | ||
13 | #include <mach/dma.h> | ||
14 | |||
15 | struct mcp_ops; | 13 | struct mcp_ops; |
16 | 14 | ||
17 | struct mcp { | 15 | struct mcp { |
@@ -21,12 +19,7 @@ struct mcp { | |||
21 | int use_count; | 19 | int use_count; |
22 | unsigned int sclk_rate; | 20 | unsigned int sclk_rate; |
23 | unsigned int rw_timeout; | 21 | unsigned int rw_timeout; |
24 | dma_device_t dma_audio_rd; | ||
25 | dma_device_t dma_audio_wr; | ||
26 | dma_device_t dma_telco_rd; | ||
27 | dma_device_t dma_telco_wr; | ||
28 | struct device attached_device; | 22 | struct device attached_device; |
29 | int gpio_base; | ||
30 | }; | 23 | }; |
31 | 24 | ||
32 | struct mcp_ops { | 25 | struct mcp_ops { |
@@ -47,15 +40,14 @@ void mcp_disable(struct mcp *); | |||
47 | #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) | 40 | #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) |
48 | 41 | ||
49 | struct mcp *mcp_host_alloc(struct device *, size_t); | 42 | struct mcp *mcp_host_alloc(struct device *, size_t); |
50 | int mcp_host_register(struct mcp *); | 43 | int mcp_host_add(struct mcp *, void *); |
51 | void mcp_host_unregister(struct mcp *); | 44 | void mcp_host_del(struct mcp *); |
45 | void mcp_host_free(struct mcp *); | ||
52 | 46 | ||
53 | struct mcp_driver { | 47 | struct mcp_driver { |
54 | struct device_driver drv; | 48 | struct device_driver drv; |
55 | int (*probe)(struct mcp *); | 49 | int (*probe)(struct mcp *); |
56 | void (*remove)(struct mcp *); | 50 | void (*remove)(struct mcp *); |
57 | int (*suspend)(struct mcp *, pm_message_t); | ||
58 | int (*resume)(struct mcp *); | ||
59 | }; | 51 | }; |
60 | 52 | ||
61 | int mcp_driver_register(struct mcp_driver *); | 53 | int mcp_driver_register(struct mcp_driver *); |
diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h index 4321f044d1e4..28af41756360 100644 --- a/include/linux/mfd/ucb1x00.h +++ b/include/linux/mfd/ucb1x00.h | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/mfd/mcp.h> | 13 | #include <linux/mfd/mcp.h> |
14 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
15 | #include <linux/semaphore.h> | 15 | #include <linux/mutex.h> |
16 | 16 | ||
17 | #define UCB_IO_DATA 0x00 | 17 | #define UCB_IO_DATA 0x00 |
18 | #define UCB_IO_DIR 0x01 | 18 | #define UCB_IO_DIR 0x01 |
@@ -104,17 +104,27 @@ | |||
104 | #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) | 104 | #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) |
105 | #define UCB_MODE_AUD_OFF_CAN (1 << 13) | 105 | #define UCB_MODE_AUD_OFF_CAN (1 << 13) |
106 | 106 | ||
107 | enum ucb1x00_reset { | ||
108 | UCB_RST_PROBE, | ||
109 | UCB_RST_RESUME, | ||
110 | UCB_RST_SUSPEND, | ||
111 | UCB_RST_REMOVE, | ||
112 | UCB_RST_PROBE_FAIL, | ||
113 | }; | ||
107 | 114 | ||
108 | struct ucb1x00_irq { | 115 | struct ucb1x00_plat_data { |
109 | void *devid; | 116 | void (*reset)(enum ucb1x00_reset); |
110 | void (*fn)(int, void *); | 117 | unsigned irq_base; |
118 | int gpio_base; | ||
119 | unsigned can_wakeup; | ||
111 | }; | 120 | }; |
112 | 121 | ||
113 | struct ucb1x00 { | 122 | struct ucb1x00 { |
114 | spinlock_t lock; | 123 | raw_spinlock_t irq_lock; |
115 | struct mcp *mcp; | 124 | struct mcp *mcp; |
116 | unsigned int irq; | 125 | unsigned int irq; |
117 | struct semaphore adc_sem; | 126 | int irq_base; |
127 | struct mutex adc_mutex; | ||
118 | spinlock_t io_lock; | 128 | spinlock_t io_lock; |
119 | u16 id; | 129 | u16 id; |
120 | u16 io_dir; | 130 | u16 io_dir; |
@@ -122,7 +132,8 @@ struct ucb1x00 { | |||
122 | u16 adc_cr; | 132 | u16 adc_cr; |
123 | u16 irq_fal_enbl; | 133 | u16 irq_fal_enbl; |
124 | u16 irq_ris_enbl; | 134 | u16 irq_ris_enbl; |
125 | struct ucb1x00_irq irq_handler[16]; | 135 | u16 irq_mask; |
136 | u16 irq_wake; | ||
126 | struct device dev; | 137 | struct device dev; |
127 | struct list_head node; | 138 | struct list_head node; |
128 | struct list_head devs; | 139 | struct list_head devs; |
@@ -144,7 +155,7 @@ struct ucb1x00_driver { | |||
144 | struct list_head devs; | 155 | struct list_head devs; |
145 | int (*add)(struct ucb1x00_dev *dev); | 156 | int (*add)(struct ucb1x00_dev *dev); |
146 | void (*remove)(struct ucb1x00_dev *dev); | 157 | void (*remove)(struct ucb1x00_dev *dev); |
147 | int (*suspend)(struct ucb1x00_dev *dev, pm_message_t state); | 158 | int (*suspend)(struct ucb1x00_dev *dev); |
148 | int (*resume)(struct ucb1x00_dev *dev); | 159 | int (*resume)(struct ucb1x00_dev *dev); |
149 | }; | 160 | }; |
150 | 161 | ||
@@ -245,15 +256,4 @@ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync); | |||
245 | void ucb1x00_adc_enable(struct ucb1x00 *ucb); | 256 | void ucb1x00_adc_enable(struct ucb1x00 *ucb); |
246 | void ucb1x00_adc_disable(struct ucb1x00 *ucb); | 257 | void ucb1x00_adc_disable(struct ucb1x00 *ucb); |
247 | 258 | ||
248 | /* | ||
249 | * Which edges of the IRQ do you want to control today? | ||
250 | */ | ||
251 | #define UCB_RISING (1 << 0) | ||
252 | #define UCB_FALLING (1 << 1) | ||
253 | |||
254 | int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid); | ||
255 | void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); | ||
256 | void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); | ||
257 | int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid); | ||
258 | |||
259 | #endif | 259 | #endif |