diff options
110 files changed, 6059 insertions, 785 deletions
diff --git a/Documentation/hwmon/twl4030-madc-hwmon b/Documentation/hwmon/twl4030-madc-hwmon new file mode 100644 index 000000000000..ef7984317cec --- /dev/null +++ b/Documentation/hwmon/twl4030-madc-hwmon | |||
@@ -0,0 +1,45 @@ | |||
1 | Kernel driver twl4030-madc | ||
2 | ========================= | ||
3 | |||
4 | Supported chips: | ||
5 | * Texas Instruments TWL4030 | ||
6 | Prefix: 'twl4030-madc' | ||
7 | |||
8 | |||
9 | Authors: | ||
10 | J Keerthy <j-keerthy@ti.com> | ||
11 | |||
12 | Description | ||
13 | ----------- | ||
14 | |||
15 | The Texas Instruments TWL4030 is a Power Management and Audio Circuit. Among | ||
16 | other things it contains a 10-bit A/D converter MADC. The converter has 16 | ||
17 | channels which can be used in different modes. | ||
18 | |||
19 | |||
20 | See this table for the meaning of the different channels | ||
21 | |||
22 | Channel Signal | ||
23 | ------------------------------------------ | ||
24 | 0 Battery type(BTYPE) | ||
25 | 1 BCI: Battery temperature (BTEMP) | ||
26 | 2 GP analog input | ||
27 | 3 GP analog input | ||
28 | 4 GP analog input | ||
29 | 5 GP analog input | ||
30 | 6 GP analog input | ||
31 | 7 GP analog input | ||
32 | 8 BCI: VBUS voltage(VBUS) | ||
33 | 9 Backup Battery voltage (VBKP) | ||
34 | 10 BCI: Battery charger current (ICHG) | ||
35 | 11 BCI: Battery charger voltage (VCHG) | ||
36 | 12 BCI: Main battery voltage (VBAT) | ||
37 | 13 Reserved | ||
38 | 14 Reserved | ||
39 | 15 VRUSB Supply/Speaker left/Speaker right polarization level | ||
40 | |||
41 | |||
42 | The Sysfs nodes will represent the voltage in the units of mV, | ||
43 | the temperature channel shows the converted temperature in | ||
44 | degree celcius. The Battery charging current channel represents | ||
45 | battery charging current in mA. | ||
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index 614b3c00c4a0..6e1accf93f81 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c | |||
@@ -232,10 +232,13 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = { | |||
232 | }; | 232 | }; |
233 | 233 | ||
234 | /* MC13783 */ | 234 | /* MC13783 */ |
235 | static struct mc13xxx_platform_data mc13783_pdata __initdata = { | 235 | static struct mc13xxx_platform_data mc13783_pdata = { |
236 | .regulators = mx27_3ds_regulators, | 236 | .regulators = { |
237 | .num_regulators = ARRAY_SIZE(mx27_3ds_regulators), | 237 | .regulators = mx27_3ds_regulators, |
238 | .flags = MC13XXX_USE_REGULATOR, | 238 | .num_regulators = ARRAY_SIZE(mx27_3ds_regulators), |
239 | |||
240 | }, | ||
241 | .flags = MC13783_USE_REGULATOR, | ||
239 | }; | 242 | }; |
240 | 243 | ||
241 | /* SPI */ | 244 | /* SPI */ |
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c index 38c77084b615..4cbce6d0fef1 100644 --- a/arch/arm/mach-imx/mach-pcm038.c +++ b/arch/arm/mach-imx/mach-pcm038.c | |||
@@ -263,10 +263,12 @@ static struct mc13xxx_regulator_init_data pcm038_regulators[] = { | |||
263 | }; | 263 | }; |
264 | 264 | ||
265 | static struct mc13xxx_platform_data pcm038_pmic = { | 265 | static struct mc13xxx_platform_data pcm038_pmic = { |
266 | .regulators = pcm038_regulators, | 266 | .regulators = { |
267 | .num_regulators = ARRAY_SIZE(pcm038_regulators), | 267 | .regulators = pcm038_regulators, |
268 | .flags = MC13XXX_USE_ADC | MC13XXX_USE_REGULATOR | | 268 | .num_regulators = ARRAY_SIZE(pcm038_regulators), |
269 | MC13XXX_USE_TOUCHSCREEN, | 269 | }, |
270 | .flags = MC13783_USE_ADC | MC13783_USE_REGULATOR | | ||
271 | MC13783_USE_TOUCHSCREEN, | ||
270 | }; | 272 | }; |
271 | 273 | ||
272 | static struct spi_board_info pcm038_spi_board_info[] __initdata = { | 274 | static struct spi_board_info pcm038_spi_board_info[] __initdata = { |
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c index 544d3e414f58..034be624d35c 100644 --- a/arch/arm/mach-mx3/mach-mx31_3ds.c +++ b/arch/arm/mach-mx3/mach-mx31_3ds.c | |||
@@ -488,10 +488,12 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = { | |||
488 | }; | 488 | }; |
489 | 489 | ||
490 | /* MC13783 */ | 490 | /* MC13783 */ |
491 | static struct mc13xxx_platform_data mc13783_pdata __initdata = { | 491 | static struct mc13xxx_platform_data mc13783_pdata = { |
492 | .regulators = mx31_3ds_regulators, | 492 | .regulators = { |
493 | .num_regulators = ARRAY_SIZE(mx31_3ds_regulators), | 493 | .regulators = mx31_3ds_regulators, |
494 | .flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_TOUCHSCREEN | 494 | .num_regulators = ARRAY_SIZE(mx31_3ds_regulators), |
495 | }, | ||
496 | .flags = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN, | ||
495 | }; | 497 | }; |
496 | 498 | ||
497 | /* SPI */ | 499 | /* SPI */ |
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c index 6f3692bccb8a..3a021b01161d 100644 --- a/arch/arm/mach-mx3/mach-mx31moboard.c +++ b/arch/arm/mach-mx3/mach-mx31moboard.c | |||
@@ -268,8 +268,10 @@ static struct mc13783_leds_platform_data moboard_leds = { | |||
268 | }; | 268 | }; |
269 | 269 | ||
270 | static struct mc13xxx_platform_data moboard_pmic = { | 270 | static struct mc13xxx_platform_data moboard_pmic = { |
271 | .regulators = moboard_regulators, | 271 | .regulators = { |
272 | .num_regulators = ARRAY_SIZE(moboard_regulators), | 272 | .regulators = moboard_regulators, |
273 | .num_regulators = ARRAY_SIZE(moboard_regulators), | ||
274 | }, | ||
273 | .leds = &moboard_leds, | 275 | .leds = &moboard_leds, |
274 | .flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC | | 276 | .flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC | |
275 | MC13XXX_USE_ADC | MC13XXX_USE_LED, | 277 | MC13XXX_USE_ADC | MC13XXX_USE_LED, |
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 62c78de1aa51..56702c5e577f 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c | |||
@@ -550,6 +550,12 @@ static struct regulator_init_data sdp4430_vusb = { | |||
550 | }, | 550 | }, |
551 | }; | 551 | }; |
552 | 552 | ||
553 | static struct regulator_init_data sdp4430_clk32kg = { | ||
554 | .constraints = { | ||
555 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
556 | }, | ||
557 | }; | ||
558 | |||
553 | static struct twl4030_platform_data sdp4430_twldata = { | 559 | static struct twl4030_platform_data sdp4430_twldata = { |
554 | .irq_base = TWL6030_IRQ_BASE, | 560 | .irq_base = TWL6030_IRQ_BASE, |
555 | .irq_end = TWL6030_IRQ_END, | 561 | .irq_end = TWL6030_IRQ_END, |
@@ -565,6 +571,7 @@ static struct twl4030_platform_data sdp4430_twldata = { | |||
565 | .vaux1 = &sdp4430_vaux1, | 571 | .vaux1 = &sdp4430_vaux1, |
566 | .vaux2 = &sdp4430_vaux2, | 572 | .vaux2 = &sdp4430_vaux2, |
567 | .vaux3 = &sdp4430_vaux3, | 573 | .vaux3 = &sdp4430_vaux3, |
574 | .clk32kg = &sdp4430_clk32kg, | ||
568 | .usb = &omap4_usbphy_data | 575 | .usb = &omap4_usbphy_data |
569 | }; | 576 | }; |
570 | 577 | ||
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 209cffbee4e0..c936c6d7ded0 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c | |||
@@ -411,6 +411,12 @@ static struct regulator_init_data omap4_panda_vusb = { | |||
411 | }, | 411 | }, |
412 | }; | 412 | }; |
413 | 413 | ||
414 | static struct regulator_init_data omap4_panda_clk32kg = { | ||
415 | .constraints = { | ||
416 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
417 | }, | ||
418 | }; | ||
419 | |||
414 | static struct twl4030_platform_data omap4_panda_twldata = { | 420 | static struct twl4030_platform_data omap4_panda_twldata = { |
415 | .irq_base = TWL6030_IRQ_BASE, | 421 | .irq_base = TWL6030_IRQ_BASE, |
416 | .irq_end = TWL6030_IRQ_END, | 422 | .irq_end = TWL6030_IRQ_END, |
@@ -426,6 +432,7 @@ static struct twl4030_platform_data omap4_panda_twldata = { | |||
426 | .vaux1 = &omap4_panda_vaux1, | 432 | .vaux1 = &omap4_panda_vaux1, |
427 | .vaux2 = &omap4_panda_vaux2, | 433 | .vaux2 = &omap4_panda_vaux2, |
428 | .vaux3 = &omap4_panda_vaux3, | 434 | .vaux3 = &omap4_panda_vaux3, |
435 | .clk32kg = &omap4_panda_clk32kg, | ||
429 | .usb = &omap4_usbphy_data, | 436 | .usb = &omap4_usbphy_data, |
430 | }; | 437 | }; |
431 | 438 | ||
diff --git a/arch/x86/platform/olpc/olpc-xo1.c b/arch/x86/platform/olpc/olpc-xo1.c index 127775696d6c..99513642a0e6 100644 --- a/arch/x86/platform/olpc/olpc-xo1.c +++ b/arch/x86/platform/olpc/olpc-xo1.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/mfd/core.h> | ||
18 | 19 | ||
19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
20 | #include <asm/olpc.h> | 21 | #include <asm/olpc.h> |
@@ -56,25 +57,24 @@ static void xo1_power_off(void) | |||
56 | static int __devinit olpc_xo1_probe(struct platform_device *pdev) | 57 | static int __devinit olpc_xo1_probe(struct platform_device *pdev) |
57 | { | 58 | { |
58 | struct resource *res; | 59 | struct resource *res; |
60 | int err; | ||
59 | 61 | ||
60 | /* don't run on non-XOs */ | 62 | /* don't run on non-XOs */ |
61 | if (!machine_is_olpc()) | 63 | if (!machine_is_olpc()) |
62 | return -ENODEV; | 64 | return -ENODEV; |
63 | 65 | ||
66 | err = mfd_cell_enable(pdev); | ||
67 | if (err) | ||
68 | return err; | ||
69 | |||
64 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 70 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
65 | if (!res) { | 71 | if (!res) { |
66 | dev_err(&pdev->dev, "can't fetch device resource info\n"); | 72 | dev_err(&pdev->dev, "can't fetch device resource info\n"); |
67 | return -EIO; | 73 | return -EIO; |
68 | } | 74 | } |
69 | 75 | if (strcmp(pdev->name, "olpc-xo1-pms") == 0) | |
70 | if (!request_region(res->start, resource_size(res), DRV_NAME)) { | ||
71 | dev_err(&pdev->dev, "can't request region\n"); | ||
72 | return -EIO; | ||
73 | } | ||
74 | |||
75 | if (strcmp(pdev->name, "cs5535-pms") == 0) | ||
76 | pms_base = res->start; | 76 | pms_base = res->start; |
77 | else if (strcmp(pdev->name, "cs5535-acpi") == 0) | 77 | else if (strcmp(pdev->name, "olpc-xo1-ac-acpi") == 0) |
78 | acpi_base = res->start; | 78 | acpi_base = res->start; |
79 | 79 | ||
80 | /* If we have both addresses, we can override the poweroff hook */ | 80 | /* If we have both addresses, we can override the poweroff hook */ |
@@ -88,14 +88,11 @@ static int __devinit olpc_xo1_probe(struct platform_device *pdev) | |||
88 | 88 | ||
89 | static int __devexit olpc_xo1_remove(struct platform_device *pdev) | 89 | static int __devexit olpc_xo1_remove(struct platform_device *pdev) |
90 | { | 90 | { |
91 | struct resource *r; | 91 | mfd_cell_disable(pdev); |
92 | |||
93 | r = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
94 | release_region(r->start, resource_size(r)); | ||
95 | 92 | ||
96 | if (strcmp(pdev->name, "cs5535-pms") == 0) | 93 | if (strcmp(pdev->name, "olpc-xo1-pms") == 0) |
97 | pms_base = 0; | 94 | pms_base = 0; |
98 | else if (strcmp(pdev->name, "cs5535-acpi") == 0) | 95 | else if (strcmp(pdev->name, "olpc-xo1-acpi") == 0) |
99 | acpi_base = 0; | 96 | acpi_base = 0; |
100 | 97 | ||
101 | pm_power_off = NULL; | 98 | pm_power_off = NULL; |
@@ -104,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev) | |||
104 | 101 | ||
105 | static struct platform_driver cs5535_pms_drv = { | 102 | static struct platform_driver cs5535_pms_drv = { |
106 | .driver = { | 103 | .driver = { |
107 | .name = "cs5535-pms", | 104 | .name = "olpc-xo1-pms", |
108 | .owner = THIS_MODULE, | 105 | .owner = THIS_MODULE, |
109 | }, | 106 | }, |
110 | .probe = olpc_xo1_probe, | 107 | .probe = olpc_xo1_probe, |
@@ -113,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = { | |||
113 | 110 | ||
114 | static struct platform_driver cs5535_acpi_drv = { | 111 | static struct platform_driver cs5535_acpi_drv = { |
115 | .driver = { | 112 | .driver = { |
116 | .name = "cs5535-acpi", | 113 | .name = "olpc-xo1-acpi", |
117 | .owner = THIS_MODULE, | 114 | .owner = THIS_MODULE, |
118 | }, | 115 | }, |
119 | .probe = olpc_xo1_probe, | 116 | .probe = olpc_xo1_probe, |
@@ -124,26 +121,27 @@ static int __init olpc_xo1_init(void) | |||
124 | { | 121 | { |
125 | int r; | 122 | int r; |
126 | 123 | ||
127 | r = platform_driver_register(&cs5535_pms_drv); | 124 | r = mfd_shared_platform_driver_register(&cs5535_pms_drv, "cs5535-pms"); |
128 | if (r) | 125 | if (r) |
129 | return r; | 126 | return r; |
130 | 127 | ||
131 | r = platform_driver_register(&cs5535_acpi_drv); | 128 | r = mfd_shared_platform_driver_register(&cs5535_acpi_drv, |
129 | "cs5535-acpi"); | ||
132 | if (r) | 130 | if (r) |
133 | platform_driver_unregister(&cs5535_pms_drv); | 131 | mfd_shared_platform_driver_unregister(&cs5535_pms_drv); |
134 | 132 | ||
135 | return r; | 133 | return r; |
136 | } | 134 | } |
137 | 135 | ||
138 | static void __exit olpc_xo1_exit(void) | 136 | static void __exit olpc_xo1_exit(void) |
139 | { | 137 | { |
140 | platform_driver_unregister(&cs5535_acpi_drv); | 138 | mfd_shared_platform_driver_unregister(&cs5535_acpi_drv); |
141 | platform_driver_unregister(&cs5535_pms_drv); | 139 | mfd_shared_platform_driver_unregister(&cs5535_pms_drv); |
142 | } | 140 | } |
143 | 141 | ||
144 | MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); | 142 | MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); |
145 | MODULE_LICENSE("GPL"); | 143 | MODULE_LICENSE("GPL"); |
146 | MODULE_ALIAS("platform:olpc-xo1"); | 144 | MODULE_ALIAS("platform:cs5535-pms"); |
147 | 145 | ||
148 | module_init(olpc_xo1_init); | 146 | module_init(olpc_xo1_init); |
149 | module_exit(olpc_xo1_exit); | 147 | module_exit(olpc_xo1_exit); |
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index f69f90a61873..d2c75feff7df 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/mfd/core.h> | ||
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
31 | 32 | ||
32 | #include <linux/timb_dma.h> | 33 | #include <linux/timb_dma.h> |
@@ -684,7 +685,7 @@ static irqreturn_t td_irq(int irq, void *devid) | |||
684 | 685 | ||
685 | static int __devinit td_probe(struct platform_device *pdev) | 686 | static int __devinit td_probe(struct platform_device *pdev) |
686 | { | 687 | { |
687 | struct timb_dma_platform_data *pdata = pdev->dev.platform_data; | 688 | struct timb_dma_platform_data *pdata = mfd_get_data(pdev); |
688 | struct timb_dma *td; | 689 | struct timb_dma *td; |
689 | struct resource *iomem; | 690 | struct resource *iomem; |
690 | int irq; | 691 | int irq; |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b46442d7d66e..d8d0cda2641d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -100,18 +100,21 @@ config GPIO_VR41XX | |||
100 | Say yes here to support the NEC VR4100 series General-purpose I/O Uint | 100 | Say yes here to support the NEC VR4100 series General-purpose I/O Uint |
101 | 101 | ||
102 | config GPIO_SCH | 102 | config GPIO_SCH |
103 | tristate "Intel SCH GPIO" | 103 | tristate "Intel SCH/TunnelCreek GPIO" |
104 | depends on GPIOLIB && PCI && X86 | 104 | depends on GPIOLIB && PCI && X86 |
105 | select MFD_CORE | 105 | select MFD_CORE |
106 | select LPC_SCH | 106 | select LPC_SCH |
107 | help | 107 | help |
108 | Say yes here to support GPIO interface on Intel Poulsbo SCH. | 108 | Say yes here to support GPIO interface on Intel Poulsbo SCH |
109 | or Intel Tunnel Creek processor. | ||
109 | The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are | 110 | The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are |
110 | powered by the core power rail and are turned off during sleep | 111 | powered by the core power rail and are turned off during sleep |
111 | modes (S3 and higher). The remaining four GPIOs are powered by | 112 | modes (S3 and higher). The remaining four GPIOs are powered by |
112 | the Intel SCH suspend power supply. These GPIOs remain | 113 | the Intel SCH suspend power supply. These GPIOs remain |
113 | active during S3. The suspend powered GPIOs can be used to wake the | 114 | active during S3. The suspend powered GPIOs can be used to wake the |
114 | system from the Suspend-to-RAM state. | 115 | system from the Suspend-to-RAM state. |
116 | The Intel Tunnel Creek processor has 5 GPIOs powered by the | ||
117 | core power rail and 9 from suspend power supply. | ||
115 | 118 | ||
116 | This driver can also be built as a module. If so, the module | 119 | This driver can also be built as a module. If so, the module |
117 | will be called sch-gpio. | 120 | will be called sch-gpio. |
diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/janz-ttl.c index 813ac077e5d7..2514fb075f4a 100644 --- a/drivers/gpio/janz-ttl.c +++ b/drivers/gpio/janz-ttl.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/mfd/core.h> | ||
18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
19 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -149,7 +150,7 @@ static int __devinit ttl_probe(struct platform_device *pdev) | |||
149 | struct resource *res; | 150 | struct resource *res; |
150 | int ret; | 151 | int ret; |
151 | 152 | ||
152 | pdata = pdev->dev.platform_data; | 153 | pdata = mfd_get_data(pdev); |
153 | if (!pdata) { | 154 | if (!pdata) { |
154 | dev_err(dev, "no platform data\n"); | 155 | dev_err(dev, "no platform data\n"); |
155 | ret = -ENXIO; | 156 | ret = -ENXIO; |
diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c index 897e0577e65e..a9bda881935a 100644 --- a/drivers/gpio/rdc321x-gpio.c +++ b/drivers/gpio/rdc321x-gpio.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | #include <linux/mfd/rdc321x.h> | 29 | #include <linux/mfd/rdc321x.h> |
30 | #include <linux/mfd/core.h> | ||
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
31 | 32 | ||
32 | struct rdc321x_gpio { | 33 | struct rdc321x_gpio { |
@@ -135,7 +136,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) | |||
135 | struct rdc321x_gpio *rdc321x_gpio_dev; | 136 | struct rdc321x_gpio *rdc321x_gpio_dev; |
136 | struct rdc321x_gpio_pdata *pdata; | 137 | struct rdc321x_gpio_pdata *pdata; |
137 | 138 | ||
138 | pdata = platform_get_drvdata(pdev); | 139 | pdata = mfd_get_data(pdev); |
139 | if (!pdata) { | 140 | if (!pdata) { |
140 | dev_err(&pdev->dev, "no platform data supplied\n"); | 141 | dev_err(&pdev->dev, "no platform data supplied\n"); |
141 | return -ENODEV; | 142 | return -ENODEV; |
diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/sch_gpio.c index 583521352c16..56060421cdff 100644 --- a/drivers/gpio/sch_gpio.c +++ b/drivers/gpio/sch_gpio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/acpi.h> | 26 | #include <linux/acpi.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/pci_ids.h> | ||
28 | 29 | ||
29 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
30 | 31 | ||
@@ -187,7 +188,11 @@ static struct gpio_chip sch_gpio_resume = { | |||
187 | static int __devinit sch_gpio_probe(struct platform_device *pdev) | 188 | static int __devinit sch_gpio_probe(struct platform_device *pdev) |
188 | { | 189 | { |
189 | struct resource *res; | 190 | struct resource *res; |
190 | int err; | 191 | int err, id; |
192 | |||
193 | id = pdev->id; | ||
194 | if (!id) | ||
195 | return -ENODEV; | ||
191 | 196 | ||
192 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 197 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
193 | if (!res) | 198 | if (!res) |
@@ -198,12 +203,40 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) | |||
198 | 203 | ||
199 | gpio_ba = res->start; | 204 | gpio_ba = res->start; |
200 | 205 | ||
201 | sch_gpio_core.base = 0; | 206 | switch (id) { |
202 | sch_gpio_core.ngpio = 10; | 207 | case PCI_DEVICE_ID_INTEL_SCH_LPC: |
203 | sch_gpio_core.dev = &pdev->dev; | 208 | sch_gpio_core.base = 0; |
209 | sch_gpio_core.ngpio = 10; | ||
210 | |||
211 | sch_gpio_resume.base = 10; | ||
212 | sch_gpio_resume.ngpio = 4; | ||
213 | |||
214 | /* | ||
215 | * GPIO[6:0] enabled by default | ||
216 | * GPIO7 is configured by the CMC as SLPIOVR | ||
217 | * Enable GPIO[9:8] core powered gpios explicitly | ||
218 | */ | ||
219 | outb(0x3, gpio_ba + CGEN + 1); | ||
220 | /* | ||
221 | * SUS_GPIO[2:0] enabled by default | ||
222 | * Enable SUS_GPIO3 resume powered gpio explicitly | ||
223 | */ | ||
224 | outb(0x8, gpio_ba + RGEN); | ||
225 | break; | ||
226 | |||
227 | case PCI_DEVICE_ID_INTEL_ITC_LPC: | ||
228 | sch_gpio_core.base = 0; | ||
229 | sch_gpio_core.ngpio = 5; | ||
230 | |||
231 | sch_gpio_resume.base = 5; | ||
232 | sch_gpio_resume.ngpio = 9; | ||
233 | break; | ||
234 | |||
235 | default: | ||
236 | return -ENODEV; | ||
237 | } | ||
204 | 238 | ||
205 | sch_gpio_resume.base = 10; | 239 | sch_gpio_core.dev = &pdev->dev; |
206 | sch_gpio_resume.ngpio = 4; | ||
207 | sch_gpio_resume.dev = &pdev->dev; | 240 | sch_gpio_resume.dev = &pdev->dev; |
208 | 241 | ||
209 | err = gpiochip_add(&sch_gpio_core); | 242 | err = gpiochip_add(&sch_gpio_core); |
@@ -214,18 +247,6 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) | |||
214 | if (err < 0) | 247 | if (err < 0) |
215 | goto err_sch_gpio_resume; | 248 | goto err_sch_gpio_resume; |
216 | 249 | ||
217 | /* | ||
218 | * GPIO[6:0] enabled by default | ||
219 | * GPIO7 is configured by the CMC as SLPIOVR | ||
220 | * Enable GPIO[9:8] core powered gpios explicitly | ||
221 | */ | ||
222 | outb(0x3, gpio_ba + CGEN + 1); | ||
223 | /* | ||
224 | * SUS_GPIO[2:0] enabled by default | ||
225 | * Enable SUS_GPIO3 resume powered gpio explicitly | ||
226 | */ | ||
227 | outb(0x8, gpio_ba + RGEN); | ||
228 | |||
229 | return 0; | 250 | return 0; |
230 | 251 | ||
231 | err_sch_gpio_resume: | 252 | err_sch_gpio_resume: |
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index 58c8f30352dd..ffcd815b8b8b 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/timbgpio.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/mfd/core.h> | ||
26 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
28 | #include <linux/timb_gpio.h> | 29 | #include <linux/timb_gpio.h> |
@@ -228,7 +229,7 @@ static int __devinit timbgpio_probe(struct platform_device *pdev) | |||
228 | struct gpio_chip *gc; | 229 | struct gpio_chip *gc; |
229 | struct timbgpio *tgpio; | 230 | struct timbgpio *tgpio; |
230 | struct resource *iomem; | 231 | struct resource *iomem; |
231 | struct timbgpio_platform_data *pdata = pdev->dev.platform_data; | 232 | struct timbgpio_platform_data *pdata = mfd_get_data(pdev); |
232 | int irq = platform_get_irq(pdev, 0); | 233 | int irq = platform_get_irq(pdev, 0); |
233 | 234 | ||
234 | if (!pdata || pdata->nr_pins > 32) { | 235 | if (!pdata || pdata->nr_pins > 32) { |
@@ -319,14 +320,13 @@ err_mem: | |||
319 | static int __devexit timbgpio_remove(struct platform_device *pdev) | 320 | static int __devexit timbgpio_remove(struct platform_device *pdev) |
320 | { | 321 | { |
321 | int err; | 322 | int err; |
322 | struct timbgpio_platform_data *pdata = pdev->dev.platform_data; | ||
323 | struct timbgpio *tgpio = platform_get_drvdata(pdev); | 323 | struct timbgpio *tgpio = platform_get_drvdata(pdev); |
324 | struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 324 | struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
325 | int irq = platform_get_irq(pdev, 0); | 325 | int irq = platform_get_irq(pdev, 0); |
326 | 326 | ||
327 | if (irq >= 0 && tgpio->irq_base > 0) { | 327 | if (irq >= 0 && tgpio->irq_base > 0) { |
328 | int i; | 328 | int i; |
329 | for (i = 0; i < pdata->nr_pins; i++) { | 329 | for (i = 0; i < tgpio->gpio.ngpio; i++) { |
330 | set_irq_chip(tgpio->irq_base + i, NULL); | 330 | set_irq_chip(tgpio->irq_base + i, NULL); |
331 | set_irq_chip_data(tgpio->irq_base + i, NULL); | 331 | set_irq_chip_data(tgpio->irq_base + i, NULL); |
332 | } | 332 | } |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e4bd13b3cd8b..81131eda5544 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -1047,6 +1047,16 @@ config SENSORS_TMP421 | |||
1047 | This driver can also be built as a module. If so, the module | 1047 | This driver can also be built as a module. If so, the module |
1048 | will be called tmp421. | 1048 | will be called tmp421. |
1049 | 1049 | ||
1050 | config SENSORS_TWL4030_MADC | ||
1051 | tristate "Texas Instruments TWL4030 MADC Hwmon" | ||
1052 | depends on TWL4030_MADC | ||
1053 | help | ||
1054 | If you say yes here you get hwmon support for triton | ||
1055 | TWL4030-MADC. | ||
1056 | |||
1057 | This driver can also be built as a module. If so it will be called | ||
1058 | twl4030-madc-hwmon. | ||
1059 | |||
1050 | config SENSORS_VIA_CPUTEMP | 1060 | config SENSORS_VIA_CPUTEMP |
1051 | tristate "VIA CPU temperature sensor" | 1061 | tristate "VIA CPU temperature sensor" |
1052 | depends on X86 | 1062 | depends on X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 54ca5939d028..967d0ea9447f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -104,6 +104,7 @@ obj-$(CONFIG_SENSORS_THMC50) += thmc50.o | |||
104 | obj-$(CONFIG_SENSORS_TMP102) += tmp102.o | 104 | obj-$(CONFIG_SENSORS_TMP102) += tmp102.o |
105 | obj-$(CONFIG_SENSORS_TMP401) += tmp401.o | 105 | obj-$(CONFIG_SENSORS_TMP401) += tmp401.o |
106 | obj-$(CONFIG_SENSORS_TMP421) += tmp421.o | 106 | obj-$(CONFIG_SENSORS_TMP421) += tmp421.o |
107 | obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o | ||
107 | obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o | 108 | obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o |
108 | obj-$(CONFIG_SENSORS_VIA686A) += via686a.o | 109 | obj-$(CONFIG_SENSORS_VIA686A) += via686a.o |
109 | obj-$(CONFIG_SENSORS_VT1211) += vt1211.o | 110 | obj-$(CONFIG_SENSORS_VT1211) += vt1211.o |
diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c index 1c8b3d9e2051..fea292d43407 100644 --- a/drivers/hwmon/jz4740-hwmon.c +++ b/drivers/hwmon/jz4740-hwmon.c | |||
@@ -32,7 +32,7 @@ struct jz4740_hwmon { | |||
32 | 32 | ||
33 | int irq; | 33 | int irq; |
34 | 34 | ||
35 | struct mfd_cell *cell; | 35 | const struct mfd_cell *cell; |
36 | struct device *hwmon; | 36 | struct device *hwmon; |
37 | 37 | ||
38 | struct completion read_completion; | 38 | struct completion read_completion; |
@@ -112,7 +112,7 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) | |||
112 | return -ENOMEM; | 112 | return -ENOMEM; |
113 | } | 113 | } |
114 | 114 | ||
115 | hwmon->cell = pdev->dev.platform_data; | 115 | hwmon->cell = mfd_get_cell(pdev); |
116 | 116 | ||
117 | hwmon->irq = platform_get_irq(pdev, 0); | 117 | hwmon->irq = platform_get_irq(pdev, 0); |
118 | if (hwmon->irq < 0) { | 118 | if (hwmon->irq < 0) { |
diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c new file mode 100644 index 000000000000..97e22bef85ab --- /dev/null +++ b/drivers/hwmon/twl4030-madc-hwmon.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * | ||
3 | * TWL4030 MADC Hwmon driver-This driver monitors the real time | ||
4 | * conversion of analog signals like battery temperature, | ||
5 | * battery type, battery level etc. User can ask for the conversion on a | ||
6 | * particular channel using the sysfs nodes. | ||
7 | * | ||
8 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
9 | * J Keerthy <j-keerthy@ti.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | * | ||
25 | */ | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/i2c/twl.h> | ||
30 | #include <linux/device.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/i2c/twl4030-madc.h> | ||
33 | #include <linux/hwmon.h> | ||
34 | #include <linux/hwmon-sysfs.h> | ||
35 | #include <linux/stddef.h> | ||
36 | #include <linux/sysfs.h> | ||
37 | #include <linux/err.h> | ||
38 | #include <linux/types.h> | ||
39 | |||
40 | /* | ||
41 | * sysfs hook function | ||
42 | */ | ||
43 | static ssize_t madc_read(struct device *dev, | ||
44 | struct device_attribute *devattr, char *buf) | ||
45 | { | ||
46 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
47 | struct twl4030_madc_request req; | ||
48 | long val; | ||
49 | |||
50 | req.channels = (1 << attr->index); | ||
51 | req.method = TWL4030_MADC_SW2; | ||
52 | req.func_cb = NULL; | ||
53 | val = twl4030_madc_conversion(&req); | ||
54 | if (val < 0) | ||
55 | return val; | ||
56 | |||
57 | return sprintf(buf, "%d\n", req.rbuf[attr->index]); | ||
58 | } | ||
59 | |||
60 | /* sysfs nodes to read individual channels from user side */ | ||
61 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0); | ||
62 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1); | ||
63 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2); | ||
64 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3); | ||
65 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4); | ||
66 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5); | ||
67 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6); | ||
68 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7); | ||
69 | static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8); | ||
70 | static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9); | ||
71 | static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10); | ||
72 | static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11); | ||
73 | static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12); | ||
74 | static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15); | ||
75 | |||
76 | static struct attribute *twl4030_madc_attributes[] = { | ||
77 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
78 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
79 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
80 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
81 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
82 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
83 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
84 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
85 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
86 | &sensor_dev_attr_in9_input.dev_attr.attr, | ||
87 | &sensor_dev_attr_curr10_input.dev_attr.attr, | ||
88 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
89 | &sensor_dev_attr_in12_input.dev_attr.attr, | ||
90 | &sensor_dev_attr_in15_input.dev_attr.attr, | ||
91 | NULL | ||
92 | }; | ||
93 | |||
94 | static const struct attribute_group twl4030_madc_group = { | ||
95 | .attrs = twl4030_madc_attributes, | ||
96 | }; | ||
97 | |||
98 | static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev) | ||
99 | { | ||
100 | int ret; | ||
101 | int status; | ||
102 | struct device *hwmon; | ||
103 | |||
104 | ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group); | ||
105 | if (ret) | ||
106 | goto err_sysfs; | ||
107 | hwmon = hwmon_device_register(&pdev->dev); | ||
108 | if (IS_ERR(hwmon)) { | ||
109 | dev_err(&pdev->dev, "hwmon_device_register failed.\n"); | ||
110 | status = PTR_ERR(hwmon); | ||
111 | goto err_reg; | ||
112 | } | ||
113 | |||
114 | return 0; | ||
115 | |||
116 | err_reg: | ||
117 | sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group); | ||
118 | err_sysfs: | ||
119 | |||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | static int __devexit twl4030_madc_hwmon_remove(struct platform_device *pdev) | ||
124 | { | ||
125 | hwmon_device_unregister(&pdev->dev); | ||
126 | sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static struct platform_driver twl4030_madc_hwmon_driver = { | ||
132 | .probe = twl4030_madc_hwmon_probe, | ||
133 | .remove = __exit_p(twl4030_madc_hwmon_remove), | ||
134 | .driver = { | ||
135 | .name = "twl4030_madc_hwmon", | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | }; | ||
139 | |||
140 | static int __init twl4030_madc_hwmon_init(void) | ||
141 | { | ||
142 | return platform_driver_register(&twl4030_madc_hwmon_driver); | ||
143 | } | ||
144 | |||
145 | module_init(twl4030_madc_hwmon_init); | ||
146 | |||
147 | static void __exit twl4030_madc_hwmon_exit(void) | ||
148 | { | ||
149 | platform_driver_unregister(&twl4030_madc_hwmon_driver); | ||
150 | } | ||
151 | |||
152 | module_exit(twl4030_madc_hwmon_exit); | ||
153 | |||
154 | MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver"); | ||
155 | MODULE_LICENSE("GPL"); | ||
156 | MODULE_AUTHOR("J Keerthy"); | ||
157 | MODULE_ALIAS("twl4030_madc_hwmon"); | ||
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 1b46a9d9f907..fee1a2613861 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/init.h> | 49 | #include <linux/init.h> |
50 | #include <linux/errno.h> | 50 | #include <linux/errno.h> |
51 | #include <linux/platform_device.h> | 51 | #include <linux/platform_device.h> |
52 | #include <linux/mfd/core.h> | ||
52 | #include <linux/i2c.h> | 53 | #include <linux/i2c.h> |
53 | #include <linux/interrupt.h> | 54 | #include <linux/interrupt.h> |
54 | #include <linux/wait.h> | 55 | #include <linux/wait.h> |
@@ -305,7 +306,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) | |||
305 | return -EIO; | 306 | return -EIO; |
306 | } | 307 | } |
307 | 308 | ||
308 | pdata = pdev->dev.platform_data; | 309 | pdata = mfd_get_data(pdev); |
309 | if (pdata) { | 310 | if (pdata) { |
310 | i2c->regstep = pdata->regstep; | 311 | i2c->regstep = pdata->regstep; |
311 | i2c->clock_khz = pdata->clock_khz; | 312 | i2c->clock_khz = pdata->clock_khz; |
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index a9c419e075a5..9fbd7e6fe32e 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mfd/core.h> | ||
37 | #include <linux/i2c.h> | 38 | #include <linux/i2c.h> |
38 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
39 | #include <linux/wait.h> | 40 | #include <linux/wait.h> |
@@ -704,7 +705,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) | |||
704 | if (irq < 0) | 705 | if (irq < 0) |
705 | goto resource_missing; | 706 | goto resource_missing; |
706 | 707 | ||
707 | pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; | 708 | pdata = mfd_get_data(pdev); |
708 | if (!pdata) | 709 | if (!pdata) |
709 | return -EINVAL; | 710 | return -EINVAL; |
710 | 711 | ||
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c index 4cc82826ea6b..3dca3c14510e 100644 --- a/drivers/input/misc/88pm860x_onkey.c +++ b/drivers/input/misc/88pm860x_onkey.c | |||
@@ -74,7 +74,7 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev) | |||
74 | info->chip = chip; | 74 | info->chip = chip; |
75 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | 75 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
76 | info->dev = &pdev->dev; | 76 | info->dev = &pdev->dev; |
77 | info->irq = irq + chip->irq_base; | 77 | info->irq = irq; |
78 | 78 | ||
79 | info->idev = input_allocate_device(); | 79 | info->idev = input_allocate_device(); |
80 | if (!info->idev) { | 80 | if (!info->idev) { |
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 014dd4ad0d4f..6a11694e3fc7 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
30 | #include <linux/i2c/twl.h> | 30 | #include <linux/i2c/twl.h> |
31 | #include <linux/mfd/twl4030-codec.h> | 31 | #include <linux/mfd/twl4030-codec.h> |
32 | #include <linux/mfd/core.h> | ||
32 | #include <linux/input.h> | 33 | #include <linux/input.h> |
33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
34 | 35 | ||
@@ -196,7 +197,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, | |||
196 | 197 | ||
197 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) | 198 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) |
198 | { | 199 | { |
199 | struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; | 200 | struct twl4030_codec_vibra_data *pdata = mfd_get_data(pdev); |
200 | struct vibra_info *info; | 201 | struct vibra_info *info; |
201 | int ret; | 202 | int ret; |
202 | 203 | ||
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index e672b44ee172..416def84d045 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/leds.h> | 17 | #include <linux/leds.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
20 | #include <linux/mfd/core.h> | ||
20 | #include <linux/mfd/88pm860x.h> | 21 | #include <linux/mfd/88pm860x.h> |
21 | 22 | ||
22 | #define LED_PWM_SHIFT (3) | 23 | #define LED_PWM_SHIFT (3) |
@@ -118,7 +119,8 @@ static void pm860x_led_work(struct work_struct *work) | |||
118 | 119 | ||
119 | struct pm860x_led *led; | 120 | struct pm860x_led *led; |
120 | struct pm860x_chip *chip; | 121 | struct pm860x_chip *chip; |
121 | int mask; | 122 | unsigned char buf[3]; |
123 | int mask, ret; | ||
122 | 124 | ||
123 | led = container_of(work, struct pm860x_led, work); | 125 | led = container_of(work, struct pm860x_led, work); |
124 | chip = led->chip; | 126 | chip = led->chip; |
@@ -128,16 +130,27 @@ static void pm860x_led_work(struct work_struct *work) | |||
128 | pm860x_set_bits(led->i2c, __led_off(led->port), | 130 | pm860x_set_bits(led->i2c, __led_off(led->port), |
129 | LED_CURRENT_MASK, led->iset); | 131 | LED_CURRENT_MASK, led->iset); |
130 | } | 132 | } |
133 | pm860x_set_bits(led->i2c, __blink_off(led->port), | ||
134 | LED_BLINK_MASK, LED_ON_CONTINUOUS); | ||
131 | mask = __blink_ctl_mask(led->port); | 135 | mask = __blink_ctl_mask(led->port); |
132 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); | 136 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); |
133 | } else if (led->brightness == 0) { | ||
134 | pm860x_set_bits(led->i2c, __led_off(led->port), | ||
135 | LED_CURRENT_MASK, 0); | ||
136 | mask = __blink_ctl_mask(led->port); | ||
137 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); | ||
138 | } | 137 | } |
139 | pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, | 138 | pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, |
140 | led->brightness); | 139 | led->brightness); |
140 | |||
141 | if (led->brightness == 0) { | ||
142 | pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf); | ||
143 | ret = buf[0] & LED_PWM_MASK; | ||
144 | ret |= buf[1] & LED_PWM_MASK; | ||
145 | ret |= buf[2] & LED_PWM_MASK; | ||
146 | if (ret == 0) { | ||
147 | /* unset current since no led is lighting */ | ||
148 | pm860x_set_bits(led->i2c, __led_off(led->port), | ||
149 | LED_CURRENT_MASK, 0); | ||
150 | mask = __blink_ctl_mask(led->port); | ||
151 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); | ||
152 | } | ||
153 | } | ||
141 | led->current_brightness = led->brightness; | 154 | led->current_brightness = led->brightness; |
142 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", | 155 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", |
143 | __led_off(led->port), led->brightness); | 156 | __led_off(led->port), led->brightness); |
@@ -153,31 +166,12 @@ static void pm860x_led_set(struct led_classdev *cdev, | |||
153 | schedule_work(&data->work); | 166 | schedule_work(&data->work); |
154 | } | 167 | } |
155 | 168 | ||
156 | static int __check_device(struct pm860x_led_pdata *pdata, char *name) | ||
157 | { | ||
158 | struct pm860x_led_pdata *p = pdata; | ||
159 | int ret = -EINVAL; | ||
160 | |||
161 | while (p && p->id) { | ||
162 | if ((p->id != PM8606_ID_LED) || (p->flags < 0)) | ||
163 | break; | ||
164 | |||
165 | if (!strncmp(name, pm860x_led_name[p->flags], | ||
166 | MFD_NAME_SIZE)) { | ||
167 | ret = (int)p->flags; | ||
168 | break; | ||
169 | } | ||
170 | p++; | ||
171 | } | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static int pm860x_led_probe(struct platform_device *pdev) | 169 | static int pm860x_led_probe(struct platform_device *pdev) |
176 | { | 170 | { |
177 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 171 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
178 | struct pm860x_platform_data *pm860x_pdata; | ||
179 | struct pm860x_led_pdata *pdata; | 172 | struct pm860x_led_pdata *pdata; |
180 | struct pm860x_led *data; | 173 | struct pm860x_led *data; |
174 | struct mfd_cell *cell; | ||
181 | struct resource *res; | 175 | struct resource *res; |
182 | int ret; | 176 | int ret; |
183 | 177 | ||
@@ -187,10 +181,11 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
187 | return -EINVAL; | 181 | return -EINVAL; |
188 | } | 182 | } |
189 | 183 | ||
190 | if (pdev->dev.parent->platform_data) { | 184 | cell = pdev->dev.platform_data; |
191 | pm860x_pdata = pdev->dev.parent->platform_data; | 185 | if (cell == NULL) |
192 | pdata = pm860x_pdata->led; | 186 | return -ENODEV; |
193 | } else { | 187 | pdata = cell->mfd_data; |
188 | if (pdata == NULL) { | ||
194 | dev_err(&pdev->dev, "No platform data!\n"); | 189 | dev_err(&pdev->dev, "No platform data!\n"); |
195 | return -EINVAL; | 190 | return -EINVAL; |
196 | } | 191 | } |
@@ -198,12 +193,12 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
198 | data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); | 193 | data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); |
199 | if (data == NULL) | 194 | if (data == NULL) |
200 | return -ENOMEM; | 195 | return -ENOMEM; |
201 | strncpy(data->name, res->name, MFD_NAME_SIZE); | 196 | strncpy(data->name, res->name, MFD_NAME_SIZE - 1); |
202 | dev_set_drvdata(&pdev->dev, data); | 197 | dev_set_drvdata(&pdev->dev, data); |
203 | data->chip = chip; | 198 | data->chip = chip; |
204 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; | 199 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; |
205 | data->iset = pdata->iset; | 200 | data->iset = pdata->iset; |
206 | data->port = __check_device(pdata, data->name); | 201 | data->port = pdata->flags; |
207 | if (data->port < 0) { | 202 | if (data->port < 0) { |
208 | dev_err(&pdev->dev, "check device failed\n"); | 203 | dev_err(&pdev->dev, "check device failed\n"); |
209 | kfree(data); | 204 | kfree(data); |
@@ -221,6 +216,7 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
221 | dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); | 216 | dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); |
222 | goto out; | 217 | goto out; |
223 | } | 218 | } |
219 | pm860x_led_set(&data->cdev, 0); | ||
224 | return 0; | 220 | return 0; |
225 | out: | 221 | out: |
226 | kfree(data); | 222 | kfree(data); |
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index f05bb08d0f09..06a5bb484707 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/leds.h> | 22 | #include <linux/leds.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <linux/mfd/mc13783.h> | 24 | #include <linux/mfd/mc13783.h> |
25 | #include <linux/mfd/core.h> | ||
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | 27 | ||
27 | struct mc13783_led { | 28 | struct mc13783_led { |
@@ -183,7 +184,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current) | |||
183 | 184 | ||
184 | static int __devinit mc13783_leds_prepare(struct platform_device *pdev) | 185 | static int __devinit mc13783_leds_prepare(struct platform_device *pdev) |
185 | { | 186 | { |
186 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | 187 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); |
187 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | 188 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); |
188 | int ret = 0; | 189 | int ret = 0; |
189 | int reg = 0; | 190 | int reg = 0; |
@@ -264,7 +265,7 @@ out: | |||
264 | 265 | ||
265 | static int __devinit mc13783_led_probe(struct platform_device *pdev) | 266 | static int __devinit mc13783_led_probe(struct platform_device *pdev) |
266 | { | 267 | { |
267 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | 268 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); |
268 | struct mc13783_led_platform_data *led_cur; | 269 | struct mc13783_led_platform_data *led_cur; |
269 | struct mc13783_led *led, *led_dat; | 270 | struct mc13783_led *led, *led_dat; |
270 | int ret, i; | 271 | int ret, i; |
@@ -351,7 +352,7 @@ err_free: | |||
351 | 352 | ||
352 | static int __devexit mc13783_led_remove(struct platform_device *pdev) | 353 | static int __devexit mc13783_led_remove(struct platform_device *pdev) |
353 | { | 354 | { |
354 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | 355 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); |
355 | struct mc13783_led *led = platform_get_drvdata(pdev); | 356 | struct mc13783_led *led = platform_get_drvdata(pdev); |
356 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | 357 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); |
357 | int i; | 358 | int i; |
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index a185610b376b..1e3a8dd820a4 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <media/v4l2-ioctl.h> | 21 | #include <media/v4l2-ioctl.h> |
22 | #include <media/v4l2-device.h> | 22 | #include <media/v4l2-device.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/mfd/core.h> | ||
24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
@@ -148,7 +149,7 @@ static const struct v4l2_file_operations timbradio_fops = { | |||
148 | 149 | ||
149 | static int __devinit timbradio_probe(struct platform_device *pdev) | 150 | static int __devinit timbradio_probe(struct platform_device *pdev) |
150 | { | 151 | { |
151 | struct timb_radio_platform_data *pdata = pdev->dev.platform_data; | 152 | struct timb_radio_platform_data *pdata = mfd_get_data(pdev); |
152 | struct timbradio *tr; | 153 | struct timbradio *tr; |
153 | int err; | 154 | int err; |
154 | 155 | ||
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 7ecc8e657663..4698eb00b59f 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c | |||
@@ -2138,7 +2138,7 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev) | |||
2138 | 2138 | ||
2139 | static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) | 2139 | static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) |
2140 | { | 2140 | { |
2141 | struct wl1273_core **core = pdev->dev.platform_data; | 2141 | struct wl1273_core **core = mfd_get_data(pdev); |
2142 | struct wl1273_device *radio; | 2142 | struct wl1273_device *radio; |
2143 | struct v4l2_ctrl *ctrl; | 2143 | struct v4l2_ctrl *ctrl; |
2144 | int r = 0; | 2144 | int r = 0; |
diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index fc611ebeb82c..84d4c7c83435 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/dmaengine.h> | 26 | #include <linux/dmaengine.h> |
27 | #include <linux/mfd/core.h> | ||
27 | #include <linux/scatterlist.h> | 28 | #include <linux/scatterlist.h> |
28 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
29 | #include <linux/list.h> | 30 | #include <linux/list.h> |
@@ -790,7 +791,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev) | |||
790 | { | 791 | { |
791 | int err; | 792 | int err; |
792 | struct timblogiw *lw = NULL; | 793 | struct timblogiw *lw = NULL; |
793 | struct timb_video_platform_data *pdata = pdev->dev.platform_data; | 794 | struct timb_video_platform_data *pdata = mfd_get_data(pdev); |
794 | 795 | ||
795 | if (!pdata) { | 796 | if (!pdata) { |
796 | dev_err(&pdev->dev, "No platform data\n"); | 797 | dev_err(&pdev->dev, "No platform data\n"); |
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 793300c554b4..9c511c1604a5 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -17,230 +17,138 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
19 | #include <linux/mfd/88pm860x.h> | 19 | #include <linux/mfd/88pm860x.h> |
20 | #include <linux/regulator/machine.h> | ||
20 | 21 | ||
21 | #define INT_STATUS_NUM 3 | 22 | #define INT_STATUS_NUM 3 |
22 | 23 | ||
23 | char pm860x_backlight_name[][MFD_NAME_SIZE] = { | 24 | static struct resource bk_resources[] __initdata = { |
24 | "backlight-0", | 25 | {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, |
25 | "backlight-1", | 26 | {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, |
26 | "backlight-2", | 27 | {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, |
27 | }; | 28 | }; |
28 | EXPORT_SYMBOL(pm860x_backlight_name); | ||
29 | |||
30 | char pm860x_led_name[][MFD_NAME_SIZE] = { | ||
31 | "led0-red", | ||
32 | "led0-green", | ||
33 | "led0-blue", | ||
34 | "led1-red", | ||
35 | "led1-green", | ||
36 | "led1-blue", | ||
37 | }; | ||
38 | EXPORT_SYMBOL(pm860x_led_name); | ||
39 | |||
40 | #define PM8606_BACKLIGHT_RESOURCE(_i, _x) \ | ||
41 | { \ | ||
42 | .name = pm860x_backlight_name[_i], \ | ||
43 | .start = PM8606_##_x, \ | ||
44 | .end = PM8606_##_x, \ | ||
45 | .flags = IORESOURCE_IO, \ | ||
46 | } | ||
47 | 29 | ||
48 | static struct resource backlight_resources[] = { | 30 | static struct resource led_resources[] __initdata = { |
49 | PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT1, WLED1A), | 31 | {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, |
50 | PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT2, WLED2A), | 32 | {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, |
51 | PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT3, WLED3A), | 33 | {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, |
34 | {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,}, | ||
35 | {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,}, | ||
36 | {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, | ||
52 | }; | 37 | }; |
53 | 38 | ||
54 | #define PM8606_BACKLIGHT_DEVS(_i) \ | 39 | static struct resource regulator_resources[] __initdata = { |
55 | { \ | 40 | {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, |
56 | .name = "88pm860x-backlight", \ | 41 | {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, |
57 | .num_resources = 1, \ | 42 | {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, |
58 | .resources = &backlight_resources[_i], \ | 43 | {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,}, |
59 | .id = _i, \ | 44 | {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,}, |
60 | } | 45 | {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,}, |
61 | 46 | {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,}, | |
62 | static struct mfd_cell backlight_devs[] = { | 47 | {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,}, |
63 | PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT1), | 48 | {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,}, |
64 | PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT2), | 49 | {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,}, |
65 | PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT3), | 50 | {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,}, |
51 | {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,}, | ||
52 | {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,}, | ||
53 | {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,}, | ||
54 | {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,}, | ||
55 | {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,}, | ||
56 | {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,}, | ||
57 | {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, | ||
66 | }; | 58 | }; |
67 | 59 | ||
68 | #define PM8606_LED_RESOURCE(_i, _x) \ | 60 | static struct resource touch_resources[] __initdata = { |
69 | { \ | 61 | {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, |
70 | .name = pm860x_led_name[_i], \ | ||
71 | .start = PM8606_##_x, \ | ||
72 | .end = PM8606_##_x, \ | ||
73 | .flags = IORESOURCE_IO, \ | ||
74 | } | ||
75 | |||
76 | static struct resource led_resources[] = { | ||
77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B), | ||
78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C), | ||
79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D), | ||
80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B), | ||
81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C), | ||
82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D), | ||
83 | }; | 62 | }; |
84 | 63 | ||
85 | #define PM8606_LED_DEVS(_i) \ | 64 | static struct resource onkey_resources[] __initdata = { |
86 | { \ | 65 | {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, |
87 | .name = "88pm860x-led", \ | ||
88 | .num_resources = 1, \ | ||
89 | .resources = &led_resources[_i], \ | ||
90 | .id = _i, \ | ||
91 | } | ||
92 | |||
93 | static struct mfd_cell led_devs[] = { | ||
94 | PM8606_LED_DEVS(PM8606_LED1_RED), | ||
95 | PM8606_LED_DEVS(PM8606_LED1_GREEN), | ||
96 | PM8606_LED_DEVS(PM8606_LED1_BLUE), | ||
97 | PM8606_LED_DEVS(PM8606_LED2_RED), | ||
98 | PM8606_LED_DEVS(PM8606_LED2_GREEN), | ||
99 | PM8606_LED_DEVS(PM8606_LED2_BLUE), | ||
100 | }; | 66 | }; |
101 | 67 | ||
102 | static struct resource touch_resources[] = { | 68 | static struct resource codec_resources[] __initdata = { |
103 | { | 69 | /* Headset microphone insertion or removal */ |
104 | .start = PM8607_IRQ_PEN, | 70 | {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, |
105 | .end = PM8607_IRQ_PEN, | 71 | /* Hook-switch press or release */ |
106 | .flags = IORESOURCE_IRQ, | 72 | {PM8607_IRQ_HOOK, PM8607_IRQ_HOOK, "hook", IORESOURCE_IRQ,}, |
107 | }, | 73 | /* Headset insertion or removal */ |
74 | {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,}, | ||
75 | /* Audio short */ | ||
76 | {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, | ||
108 | }; | 77 | }; |
109 | 78 | ||
110 | static struct mfd_cell touch_devs[] = { | 79 | static struct resource battery_resources[] __initdata = { |
111 | { | 80 | {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, |
112 | .name = "88pm860x-touch", | 81 | {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, |
113 | .num_resources = 1, | ||
114 | .resources = &touch_resources[0], | ||
115 | }, | ||
116 | }; | 82 | }; |
117 | 83 | ||
118 | #define PM8607_REG_RESOURCE(_start, _end) \ | 84 | static struct resource charger_resources[] __initdata = { |
119 | { \ | 85 | {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, |
120 | .start = PM8607_##_start, \ | 86 | {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, |
121 | .end = PM8607_##_end, \ | 87 | {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, |
122 | .flags = IORESOURCE_IO, \ | 88 | {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,}, |
123 | } | 89 | {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,}, |
124 | 90 | {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, | |
125 | static struct resource power_supply_resources[] = { | ||
126 | { | ||
127 | .name = "88pm860x-power", | ||
128 | .start = PM8607_IRQ_CHG, | ||
129 | .end = PM8607_IRQ_CHG, | ||
130 | .flags = IORESOURCE_IRQ, | ||
131 | }, | ||
132 | }; | 91 | }; |
133 | 92 | ||
134 | static struct mfd_cell power_devs[] = { | 93 | static struct mfd_cell bk_devs[] __initdata = { |
135 | { | 94 | {"88pm860x-backlight", 0,}, |
136 | .name = "88pm860x-power", | 95 | {"88pm860x-backlight", 1,}, |
137 | .num_resources = 1, | 96 | {"88pm860x-backlight", 2,}, |
138 | .resources = &power_supply_resources[0], | ||
139 | .id = -1, | ||
140 | }, | ||
141 | }; | 97 | }; |
142 | 98 | ||
143 | static struct resource onkey_resources[] = { | 99 | static struct mfd_cell led_devs[] __initdata = { |
144 | { | 100 | {"88pm860x-led", 0,}, |
145 | .name = "88pm860x-onkey", | 101 | {"88pm860x-led", 1,}, |
146 | .start = PM8607_IRQ_ONKEY, | 102 | {"88pm860x-led", 2,}, |
147 | .end = PM8607_IRQ_ONKEY, | 103 | {"88pm860x-led", 3,}, |
148 | .flags = IORESOURCE_IRQ, | 104 | {"88pm860x-led", 4,}, |
149 | }, | 105 | {"88pm860x-led", 5,}, |
150 | }; | 106 | }; |
151 | 107 | ||
152 | static struct mfd_cell onkey_devs[] = { | 108 | static struct mfd_cell regulator_devs[] __initdata = { |
153 | { | 109 | {"88pm860x-regulator", 0,}, |
154 | .name = "88pm860x-onkey", | 110 | {"88pm860x-regulator", 1,}, |
155 | .num_resources = 1, | 111 | {"88pm860x-regulator", 2,}, |
156 | .resources = &onkey_resources[0], | 112 | {"88pm860x-regulator", 3,}, |
157 | .id = -1, | 113 | {"88pm860x-regulator", 4,}, |
158 | }, | 114 | {"88pm860x-regulator", 5,}, |
115 | {"88pm860x-regulator", 6,}, | ||
116 | {"88pm860x-regulator", 7,}, | ||
117 | {"88pm860x-regulator", 8,}, | ||
118 | {"88pm860x-regulator", 9,}, | ||
119 | {"88pm860x-regulator", 10,}, | ||
120 | {"88pm860x-regulator", 11,}, | ||
121 | {"88pm860x-regulator", 12,}, | ||
122 | {"88pm860x-regulator", 13,}, | ||
123 | {"88pm860x-regulator", 14,}, | ||
124 | {"88pm860x-regulator", 15,}, | ||
125 | {"88pm860x-regulator", 16,}, | ||
126 | {"88pm860x-regulator", 17,}, | ||
159 | }; | 127 | }; |
160 | 128 | ||
161 | static struct resource codec_resources[] = { | 129 | static struct mfd_cell touch_devs[] __initdata = { |
162 | { | 130 | {"88pm860x-touch", -1,}, |
163 | /* Headset microphone insertion or removal */ | ||
164 | .name = "micin", | ||
165 | .start = PM8607_IRQ_MICIN, | ||
166 | .end = PM8607_IRQ_MICIN, | ||
167 | .flags = IORESOURCE_IRQ, | ||
168 | }, { | ||
169 | /* Hook-switch press or release */ | ||
170 | .name = "hook", | ||
171 | .start = PM8607_IRQ_HOOK, | ||
172 | .end = PM8607_IRQ_HOOK, | ||
173 | .flags = IORESOURCE_IRQ, | ||
174 | }, { | ||
175 | /* Headset insertion or removal */ | ||
176 | .name = "headset", | ||
177 | .start = PM8607_IRQ_HEADSET, | ||
178 | .end = PM8607_IRQ_HEADSET, | ||
179 | .flags = IORESOURCE_IRQ, | ||
180 | }, { | ||
181 | /* Audio short */ | ||
182 | .name = "audio-short", | ||
183 | .start = PM8607_IRQ_AUDIO_SHORT, | ||
184 | .end = PM8607_IRQ_AUDIO_SHORT, | ||
185 | .flags = IORESOURCE_IRQ, | ||
186 | }, | ||
187 | }; | 131 | }; |
188 | 132 | ||
189 | static struct mfd_cell codec_devs[] = { | 133 | static struct mfd_cell onkey_devs[] __initdata = { |
190 | { | 134 | {"88pm860x-onkey", -1,}, |
191 | .name = "88pm860x-codec", | ||
192 | .num_resources = ARRAY_SIZE(codec_resources), | ||
193 | .resources = &codec_resources[0], | ||
194 | .id = -1, | ||
195 | }, | ||
196 | }; | 135 | }; |
197 | 136 | ||
198 | static struct resource regulator_resources[] = { | 137 | static struct mfd_cell codec_devs[] __initdata = { |
199 | PM8607_REG_RESOURCE(BUCK1, BUCK1), | 138 | {"88pm860x-codec", -1,}, |
200 | PM8607_REG_RESOURCE(BUCK2, BUCK2), | ||
201 | PM8607_REG_RESOURCE(BUCK3, BUCK3), | ||
202 | PM8607_REG_RESOURCE(LDO1, LDO1), | ||
203 | PM8607_REG_RESOURCE(LDO2, LDO2), | ||
204 | PM8607_REG_RESOURCE(LDO3, LDO3), | ||
205 | PM8607_REG_RESOURCE(LDO4, LDO4), | ||
206 | PM8607_REG_RESOURCE(LDO5, LDO5), | ||
207 | PM8607_REG_RESOURCE(LDO6, LDO6), | ||
208 | PM8607_REG_RESOURCE(LDO7, LDO7), | ||
209 | PM8607_REG_RESOURCE(LDO8, LDO8), | ||
210 | PM8607_REG_RESOURCE(LDO9, LDO9), | ||
211 | PM8607_REG_RESOURCE(LDO10, LDO10), | ||
212 | PM8607_REG_RESOURCE(LDO12, LDO12), | ||
213 | PM8607_REG_RESOURCE(VIBRATOR_SET, VIBRATOR_SET), | ||
214 | PM8607_REG_RESOURCE(LDO14, LDO14), | ||
215 | }; | 139 | }; |
216 | 140 | ||
217 | #define PM8607_REG_DEVS(_id) \ | 141 | static struct mfd_cell power_devs[] = { |
218 | { \ | 142 | {"88pm860x-battery", -1,}, |
219 | .name = "88pm860x-regulator", \ | 143 | {"88pm860x-charger", -1,}, |
220 | .num_resources = 1, \ | ||
221 | .resources = ®ulator_resources[PM8607_ID_##_id], \ | ||
222 | .id = PM8607_ID_##_id, \ | ||
223 | } | ||
224 | |||
225 | static struct mfd_cell regulator_devs[] = { | ||
226 | PM8607_REG_DEVS(BUCK1), | ||
227 | PM8607_REG_DEVS(BUCK2), | ||
228 | PM8607_REG_DEVS(BUCK3), | ||
229 | PM8607_REG_DEVS(LDO1), | ||
230 | PM8607_REG_DEVS(LDO2), | ||
231 | PM8607_REG_DEVS(LDO3), | ||
232 | PM8607_REG_DEVS(LDO4), | ||
233 | PM8607_REG_DEVS(LDO5), | ||
234 | PM8607_REG_DEVS(LDO6), | ||
235 | PM8607_REG_DEVS(LDO7), | ||
236 | PM8607_REG_DEVS(LDO8), | ||
237 | PM8607_REG_DEVS(LDO9), | ||
238 | PM8607_REG_DEVS(LDO10), | ||
239 | PM8607_REG_DEVS(LDO12), | ||
240 | PM8607_REG_DEVS(LDO13), | ||
241 | PM8607_REG_DEVS(LDO14), | ||
242 | }; | 144 | }; |
243 | 145 | ||
146 | static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)]; | ||
147 | static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)]; | ||
148 | static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)]; | ||
149 | static struct pm860x_touch_pdata touch_pdata; | ||
150 | static struct pm860x_power_pdata power_pdata; | ||
151 | |||
244 | struct pm860x_irq_data { | 152 | struct pm860x_irq_data { |
245 | int reg; | 153 | int reg; |
246 | int mask_reg; | 154 | int mask_reg; |
@@ -595,37 +503,212 @@ static void device_irq_exit(struct pm860x_chip *chip) | |||
595 | free_irq(chip->core_irq, chip); | 503 | free_irq(chip->core_irq, chip); |
596 | } | 504 | } |
597 | 505 | ||
598 | static void __devinit device_8606_init(struct pm860x_chip *chip, | 506 | static void __devinit device_bk_init(struct pm860x_chip *chip, |
599 | struct i2c_client *i2c, | 507 | struct i2c_client *i2c, |
600 | struct pm860x_platform_data *pdata) | 508 | struct pm860x_platform_data *pdata) |
601 | { | 509 | { |
602 | int ret; | 510 | int ret; |
511 | int i, j, id; | ||
512 | |||
513 | if ((pdata == NULL) || (pdata->backlight == NULL)) | ||
514 | return; | ||
515 | |||
516 | if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) | ||
517 | pdata->num_backlights = ARRAY_SIZE(bk_devs); | ||
518 | |||
519 | for (i = 0; i < pdata->num_backlights; i++) { | ||
520 | memcpy(&bk_pdata[i], &pdata->backlight[i], | ||
521 | sizeof(struct pm860x_backlight_pdata)); | ||
522 | bk_devs[i].mfd_data = &bk_pdata[i]; | ||
523 | |||
524 | for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { | ||
525 | id = bk_resources[j].start; | ||
526 | if (bk_pdata[i].flags != id) | ||
527 | continue; | ||
528 | |||
529 | bk_devs[i].num_resources = 1; | ||
530 | bk_devs[i].resources = &bk_resources[j]; | ||
531 | ret = mfd_add_devices(chip->dev, 0, | ||
532 | &bk_devs[i], 1, | ||
533 | &bk_resources[j], 0); | ||
534 | if (ret < 0) { | ||
535 | dev_err(chip->dev, "Failed to add " | ||
536 | "backlight subdev\n"); | ||
537 | return; | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | } | ||
603 | 542 | ||
604 | if (pdata && pdata->backlight) { | 543 | static void __devinit device_led_init(struct pm860x_chip *chip, |
605 | ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0], | 544 | struct i2c_client *i2c, |
606 | ARRAY_SIZE(backlight_devs), | 545 | struct pm860x_platform_data *pdata) |
607 | &backlight_resources[0], 0); | 546 | { |
608 | if (ret < 0) { | 547 | int ret; |
609 | dev_err(chip->dev, "Failed to add backlight " | 548 | int i, j, id; |
610 | "subdev\n"); | 549 | |
611 | goto out_dev; | 550 | if ((pdata == NULL) || (pdata->led == NULL)) |
551 | return; | ||
552 | |||
553 | if (pdata->num_leds > ARRAY_SIZE(led_devs)) | ||
554 | pdata->num_leds = ARRAY_SIZE(led_devs); | ||
555 | |||
556 | for (i = 0; i < pdata->num_leds; i++) { | ||
557 | memcpy(&led_pdata[i], &pdata->led[i], | ||
558 | sizeof(struct pm860x_led_pdata)); | ||
559 | led_devs[i].mfd_data = &led_pdata[i]; | ||
560 | |||
561 | for (j = 0; j < ARRAY_SIZE(led_devs); j++) { | ||
562 | id = led_resources[j].start; | ||
563 | if (led_pdata[i].flags != id) | ||
564 | continue; | ||
565 | |||
566 | led_devs[i].num_resources = 1; | ||
567 | led_devs[i].resources = &led_resources[j], | ||
568 | ret = mfd_add_devices(chip->dev, 0, | ||
569 | &led_devs[i], 1, | ||
570 | &led_resources[j], 0); | ||
571 | if (ret < 0) { | ||
572 | dev_err(chip->dev, "Failed to add " | ||
573 | "led subdev\n"); | ||
574 | return; | ||
575 | } | ||
612 | } | 576 | } |
613 | } | 577 | } |
578 | } | ||
614 | 579 | ||
615 | if (pdata && pdata->led) { | 580 | static void __devinit device_regulator_init(struct pm860x_chip *chip, |
616 | ret = mfd_add_devices(chip->dev, 0, &led_devs[0], | 581 | struct i2c_client *i2c, |
617 | ARRAY_SIZE(led_devs), | 582 | struct pm860x_platform_data *pdata) |
618 | &led_resources[0], 0); | 583 | { |
584 | struct regulator_init_data *initdata; | ||
585 | int ret; | ||
586 | int i, j; | ||
587 | |||
588 | if ((pdata == NULL) || (pdata->regulator == NULL)) | ||
589 | return; | ||
590 | |||
591 | if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) | ||
592 | pdata->num_regulators = ARRAY_SIZE(regulator_devs); | ||
593 | |||
594 | for (i = 0, j = -1; i < pdata->num_regulators; i++) { | ||
595 | initdata = &pdata->regulator[i]; | ||
596 | if (strstr(initdata->constraints.name, "BUCK")) { | ||
597 | sscanf(initdata->constraints.name, "BUCK%d", &j); | ||
598 | /* BUCK1 ~ BUCK3 */ | ||
599 | if ((j < 1) || (j > 3)) { | ||
600 | dev_err(chip->dev, "Failed to add constraint " | ||
601 | "(%s)\n", initdata->constraints.name); | ||
602 | goto out; | ||
603 | } | ||
604 | j = (j - 1) + PM8607_ID_BUCK1; | ||
605 | } | ||
606 | if (strstr(initdata->constraints.name, "LDO")) { | ||
607 | sscanf(initdata->constraints.name, "LDO%d", &j); | ||
608 | /* LDO1 ~ LDO15 */ | ||
609 | if ((j < 1) || (j > 15)) { | ||
610 | dev_err(chip->dev, "Failed to add constraint " | ||
611 | "(%s)\n", initdata->constraints.name); | ||
612 | goto out; | ||
613 | } | ||
614 | j = (j - 1) + PM8607_ID_LDO1; | ||
615 | } | ||
616 | if (j == -1) { | ||
617 | dev_err(chip->dev, "Failed to add constraint (%s)\n", | ||
618 | initdata->constraints.name); | ||
619 | goto out; | ||
620 | } | ||
621 | memcpy(®ulator_pdata[i], &pdata->regulator[i], | ||
622 | sizeof(struct regulator_init_data)); | ||
623 | regulator_devs[i].mfd_data = ®ulator_pdata[i]; | ||
624 | regulator_devs[i].num_resources = 1; | ||
625 | regulator_devs[i].resources = ®ulator_resources[j]; | ||
626 | |||
627 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, | ||
628 | ®ulator_resources[j], 0); | ||
619 | if (ret < 0) { | 629 | if (ret < 0) { |
620 | dev_err(chip->dev, "Failed to add led " | 630 | dev_err(chip->dev, "Failed to add regulator subdev\n"); |
621 | "subdev\n"); | 631 | goto out; |
622 | goto out_dev; | ||
623 | } | 632 | } |
624 | } | 633 | } |
634 | out: | ||
625 | return; | 635 | return; |
626 | out_dev: | 636 | } |
627 | mfd_remove_devices(chip->dev); | 637 | |
628 | device_irq_exit(chip); | 638 | static void __devinit device_touch_init(struct pm860x_chip *chip, |
639 | struct i2c_client *i2c, | ||
640 | struct pm860x_platform_data *pdata) | ||
641 | { | ||
642 | int ret; | ||
643 | |||
644 | if ((pdata == NULL) || (pdata->touch == NULL)) | ||
645 | return; | ||
646 | |||
647 | memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata)); | ||
648 | touch_devs[0].mfd_data = &touch_pdata; | ||
649 | touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); | ||
650 | touch_devs[0].resources = &touch_resources[0]; | ||
651 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], | ||
652 | ARRAY_SIZE(touch_devs), &touch_resources[0], | ||
653 | chip->irq_base); | ||
654 | if (ret < 0) | ||
655 | dev_err(chip->dev, "Failed to add touch subdev\n"); | ||
656 | } | ||
657 | |||
658 | static void __devinit device_power_init(struct pm860x_chip *chip, | ||
659 | struct i2c_client *i2c, | ||
660 | struct pm860x_platform_data *pdata) | ||
661 | { | ||
662 | int ret; | ||
663 | |||
664 | if ((pdata == NULL) || (pdata->power == NULL)) | ||
665 | return; | ||
666 | |||
667 | memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata)); | ||
668 | power_devs[0].mfd_data = &power_pdata; | ||
669 | power_devs[0].num_resources = ARRAY_SIZE(battery_resources); | ||
670 | power_devs[0].resources = &battery_resources[0], | ||
671 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, | ||
672 | &battery_resources[0], chip->irq_base); | ||
673 | if (ret < 0) | ||
674 | dev_err(chip->dev, "Failed to add battery subdev\n"); | ||
675 | |||
676 | power_devs[1].mfd_data = &power_pdata; | ||
677 | power_devs[1].num_resources = ARRAY_SIZE(charger_resources); | ||
678 | power_devs[1].resources = &charger_resources[0], | ||
679 | ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, | ||
680 | &charger_resources[0], chip->irq_base); | ||
681 | if (ret < 0) | ||
682 | dev_err(chip->dev, "Failed to add charger subdev\n"); | ||
683 | } | ||
684 | |||
685 | static void __devinit device_onkey_init(struct pm860x_chip *chip, | ||
686 | struct i2c_client *i2c, | ||
687 | struct pm860x_platform_data *pdata) | ||
688 | { | ||
689 | int ret; | ||
690 | |||
691 | onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); | ||
692 | onkey_devs[0].resources = &onkey_resources[0], | ||
693 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
694 | ARRAY_SIZE(onkey_devs), &onkey_resources[0], | ||
695 | chip->irq_base); | ||
696 | if (ret < 0) | ||
697 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
698 | } | ||
699 | |||
700 | static void __devinit device_codec_init(struct pm860x_chip *chip, | ||
701 | struct i2c_client *i2c, | ||
702 | struct pm860x_platform_data *pdata) | ||
703 | { | ||
704 | int ret; | ||
705 | |||
706 | codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); | ||
707 | codec_devs[0].resources = &codec_resources[0], | ||
708 | ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], | ||
709 | ARRAY_SIZE(codec_devs), &codec_resources[0], 0); | ||
710 | if (ret < 0) | ||
711 | dev_err(chip->dev, "Failed to add codec subdev\n"); | ||
629 | } | 712 | } |
630 | 713 | ||
631 | static void __devinit device_8607_init(struct pm860x_chip *chip, | 714 | static void __devinit device_8607_init(struct pm860x_chip *chip, |
@@ -683,55 +766,11 @@ static void __devinit device_8607_init(struct pm860x_chip *chip, | |||
683 | if (ret < 0) | 766 | if (ret < 0) |
684 | goto out; | 767 | goto out; |
685 | 768 | ||
686 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], | 769 | device_regulator_init(chip, i2c, pdata); |
687 | ARRAY_SIZE(regulator_devs), | 770 | device_onkey_init(chip, i2c, pdata); |
688 | ®ulator_resources[0], 0); | 771 | device_touch_init(chip, i2c, pdata); |
689 | if (ret < 0) { | 772 | device_power_init(chip, i2c, pdata); |
690 | dev_err(chip->dev, "Failed to add regulator subdev\n"); | 773 | device_codec_init(chip, i2c, pdata); |
691 | goto out_dev; | ||
692 | } | ||
693 | |||
694 | if (pdata && pdata->touch) { | ||
695 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], | ||
696 | ARRAY_SIZE(touch_devs), | ||
697 | &touch_resources[0], 0); | ||
698 | if (ret < 0) { | ||
699 | dev_err(chip->dev, "Failed to add touch " | ||
700 | "subdev\n"); | ||
701 | goto out_dev; | ||
702 | } | ||
703 | } | ||
704 | |||
705 | if (pdata && pdata->power) { | ||
706 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], | ||
707 | ARRAY_SIZE(power_devs), | ||
708 | &power_supply_resources[0], 0); | ||
709 | if (ret < 0) { | ||
710 | dev_err(chip->dev, "Failed to add power supply " | ||
711 | "subdev\n"); | ||
712 | goto out_dev; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
717 | ARRAY_SIZE(onkey_devs), | ||
718 | &onkey_resources[0], 0); | ||
719 | if (ret < 0) { | ||
720 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
721 | goto out_dev; | ||
722 | } | ||
723 | |||
724 | ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], | ||
725 | ARRAY_SIZE(codec_devs), | ||
726 | &codec_resources[0], 0); | ||
727 | if (ret < 0) { | ||
728 | dev_err(chip->dev, "Failed to add codec subdev\n"); | ||
729 | goto out_dev; | ||
730 | } | ||
731 | return; | ||
732 | out_dev: | ||
733 | mfd_remove_devices(chip->dev); | ||
734 | device_irq_exit(chip); | ||
735 | out: | 774 | out: |
736 | return; | 775 | return; |
737 | } | 776 | } |
@@ -743,7 +782,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
743 | 782 | ||
744 | switch (chip->id) { | 783 | switch (chip->id) { |
745 | case CHIP_PM8606: | 784 | case CHIP_PM8606: |
746 | device_8606_init(chip, chip->client, pdata); | 785 | device_bk_init(chip, chip->client, pdata); |
786 | device_led_init(chip, chip->client, pdata); | ||
747 | break; | 787 | break; |
748 | case CHIP_PM8607: | 788 | case CHIP_PM8607: |
749 | device_8607_init(chip, chip->client, pdata); | 789 | device_8607_init(chip, chip->client, pdata); |
@@ -753,7 +793,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
753 | if (chip->companion) { | 793 | if (chip->companion) { |
754 | switch (chip->id) { | 794 | switch (chip->id) { |
755 | case CHIP_PM8607: | 795 | case CHIP_PM8607: |
756 | device_8606_init(chip, chip->companion, pdata); | 796 | device_bk_init(chip, chip->companion, pdata); |
797 | device_led_init(chip, chip->companion, pdata); | ||
757 | break; | 798 | break; |
758 | case CHIP_PM8606: | 799 | case CHIP_PM8606: |
759 | device_8607_init(chip, chip->companion, pdata); | 800 | device_8607_init(chip, chip->companion, pdata); |
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c index bc02e6b21608..e017dc88622a 100644 --- a/drivers/mfd/88pm860x-i2c.c +++ b/drivers/mfd/88pm860x-i2c.c | |||
@@ -126,6 +126,109 @@ out: | |||
126 | } | 126 | } |
127 | EXPORT_SYMBOL(pm860x_set_bits); | 127 | EXPORT_SYMBOL(pm860x_set_bits); |
128 | 128 | ||
129 | int pm860x_page_reg_read(struct i2c_client *i2c, int reg) | ||
130 | { | ||
131 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); | ||
132 | unsigned char zero = 0; | ||
133 | unsigned char data; | ||
134 | int ret; | ||
135 | |||
136 | mutex_lock(&chip->io_lock); | ||
137 | pm860x_write_device(i2c, 0xFA, 0, &zero); | ||
138 | pm860x_write_device(i2c, 0xFB, 0, &zero); | ||
139 | pm860x_write_device(i2c, 0xFF, 0, &zero); | ||
140 | ret = pm860x_read_device(i2c, reg, 1, &data); | ||
141 | if (ret >= 0) | ||
142 | ret = (int)data; | ||
143 | pm860x_write_device(i2c, 0xFE, 0, &zero); | ||
144 | pm860x_write_device(i2c, 0xFC, 0, &zero); | ||
145 | mutex_unlock(&chip->io_lock); | ||
146 | return ret; | ||
147 | } | ||
148 | EXPORT_SYMBOL(pm860x_page_reg_read); | ||
149 | |||
150 | int pm860x_page_reg_write(struct i2c_client *i2c, int reg, | ||
151 | unsigned char data) | ||
152 | { | ||
153 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); | ||
154 | unsigned char zero; | ||
155 | int ret; | ||
156 | |||
157 | mutex_lock(&chip->io_lock); | ||
158 | pm860x_write_device(i2c, 0xFA, 0, &zero); | ||
159 | pm860x_write_device(i2c, 0xFB, 0, &zero); | ||
160 | pm860x_write_device(i2c, 0xFF, 0, &zero); | ||
161 | ret = pm860x_write_device(i2c, reg, 1, &data); | ||
162 | pm860x_write_device(i2c, 0xFE, 0, &zero); | ||
163 | pm860x_write_device(i2c, 0xFC, 0, &zero); | ||
164 | mutex_unlock(&chip->io_lock); | ||
165 | return ret; | ||
166 | } | ||
167 | EXPORT_SYMBOL(pm860x_page_reg_write); | ||
168 | |||
169 | int pm860x_page_bulk_read(struct i2c_client *i2c, int reg, | ||
170 | int count, unsigned char *buf) | ||
171 | { | ||
172 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); | ||
173 | unsigned char zero = 0; | ||
174 | int ret; | ||
175 | |||
176 | mutex_lock(&chip->io_lock); | ||
177 | pm860x_write_device(i2c, 0xFA, 0, &zero); | ||
178 | pm860x_write_device(i2c, 0xFB, 0, &zero); | ||
179 | pm860x_write_device(i2c, 0xFF, 0, &zero); | ||
180 | ret = pm860x_read_device(i2c, reg, count, buf); | ||
181 | pm860x_write_device(i2c, 0xFE, 0, &zero); | ||
182 | pm860x_write_device(i2c, 0xFC, 0, &zero); | ||
183 | mutex_unlock(&chip->io_lock); | ||
184 | return ret; | ||
185 | } | ||
186 | EXPORT_SYMBOL(pm860x_page_bulk_read); | ||
187 | |||
188 | int pm860x_page_bulk_write(struct i2c_client *i2c, int reg, | ||
189 | int count, unsigned char *buf) | ||
190 | { | ||
191 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); | ||
192 | unsigned char zero = 0; | ||
193 | int ret; | ||
194 | |||
195 | mutex_lock(&chip->io_lock); | ||
196 | pm860x_write_device(i2c, 0xFA, 0, &zero); | ||
197 | pm860x_write_device(i2c, 0xFB, 0, &zero); | ||
198 | pm860x_write_device(i2c, 0xFF, 0, &zero); | ||
199 | ret = pm860x_write_device(i2c, reg, count, buf); | ||
200 | pm860x_write_device(i2c, 0xFE, 0, &zero); | ||
201 | pm860x_write_device(i2c, 0xFC, 0, &zero); | ||
202 | mutex_unlock(&chip->io_lock); | ||
203 | return ret; | ||
204 | } | ||
205 | EXPORT_SYMBOL(pm860x_page_bulk_write); | ||
206 | |||
207 | int pm860x_page_set_bits(struct i2c_client *i2c, int reg, | ||
208 | unsigned char mask, unsigned char data) | ||
209 | { | ||
210 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); | ||
211 | unsigned char zero; | ||
212 | unsigned char value; | ||
213 | int ret; | ||
214 | |||
215 | mutex_lock(&chip->io_lock); | ||
216 | pm860x_write_device(i2c, 0xFA, 0, &zero); | ||
217 | pm860x_write_device(i2c, 0xFB, 0, &zero); | ||
218 | pm860x_write_device(i2c, 0xFF, 0, &zero); | ||
219 | ret = pm860x_read_device(i2c, reg, 1, &value); | ||
220 | if (ret < 0) | ||
221 | goto out; | ||
222 | value &= ~mask; | ||
223 | value |= data; | ||
224 | ret = pm860x_write_device(i2c, reg, 1, &value); | ||
225 | out: | ||
226 | pm860x_write_device(i2c, 0xFE, 0, &zero); | ||
227 | pm860x_write_device(i2c, 0xFC, 0, &zero); | ||
228 | mutex_unlock(&chip->io_lock); | ||
229 | return ret; | ||
230 | } | ||
231 | EXPORT_SYMBOL(pm860x_page_set_bits); | ||
129 | 232 | ||
130 | static const struct i2c_device_id pm860x_id_table[] = { | 233 | static const struct i2c_device_id pm860x_id_table[] = { |
131 | { "88PM860x", 0 }, | 234 | { "88PM860x", 0 }, |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index fdca643249e1..8d7d098f7a03 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -129,6 +129,17 @@ config UCB1400_CORE | |||
129 | To compile this driver as a module, choose M here: the | 129 | To compile this driver as a module, choose M here: the |
130 | module will be called ucb1400_core. | 130 | module will be called ucb1400_core. |
131 | 131 | ||
132 | config TPS6105X | ||
133 | tristate "TPS61050/61052 Boost Converters" | ||
134 | depends on I2C | ||
135 | select REGULATOR | ||
136 | select REGULATOR_FIXED_VOLTAGE | ||
137 | help | ||
138 | This option enables a driver for the TP61050/TPS61052 | ||
139 | high-power "white LED driver". This boost converter is | ||
140 | sometimes used for other things than white LEDs, and | ||
141 | also contains a GPIO pin. | ||
142 | |||
132 | config TPS65010 | 143 | config TPS65010 |
133 | tristate "TPS6501x Power Management chips" | 144 | tristate "TPS6501x Power Management chips" |
134 | depends on I2C && GPIOLIB | 145 | depends on I2C && GPIOLIB |
@@ -178,6 +189,16 @@ config TWL4030_CORE | |||
178 | high speed USB OTG transceiver, an audio codec (on most | 189 | high speed USB OTG transceiver, an audio codec (on most |
179 | versions) and many other features. | 190 | versions) and many other features. |
180 | 191 | ||
192 | config TWL4030_MADC | ||
193 | tristate "Texas Instruments TWL4030 MADC" | ||
194 | depends on TWL4030_CORE | ||
195 | help | ||
196 | This driver provides support for triton TWL4030-MADC. The | ||
197 | driver supports both RT and SW conversion methods. | ||
198 | |||
199 | This driver can be built as a module. If so it will be | ||
200 | named twl4030-madc | ||
201 | |||
181 | config TWL4030_POWER | 202 | config TWL4030_POWER |
182 | bool "Support power resources on TWL4030 family chips" | 203 | bool "Support power resources on TWL4030 family chips" |
183 | depends on TWL4030_CORE && ARM | 204 | depends on TWL4030_CORE && ARM |
@@ -304,6 +325,18 @@ config MFD_MAX8925 | |||
304 | accessing the device, additional drivers must be enabled in order | 325 | accessing the device, additional drivers must be enabled in order |
305 | to use the functionality of the device. | 326 | to use the functionality of the device. |
306 | 327 | ||
328 | config MFD_MAX8997 | ||
329 | bool "Maxim Semiconductor MAX8997/8966 PMIC Support" | ||
330 | depends on I2C=y && GENERIC_HARDIRQS | ||
331 | select MFD_CORE | ||
332 | help | ||
333 | Say yes here to support for Maxim Semiconductor MAX8998/8966. | ||
334 | This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic, | ||
335 | MUIC controls on chip. | ||
336 | This driver provides common support for accessing the device; | ||
337 | additional drivers must be enabled in order to use the functionality | ||
338 | of the device. | ||
339 | |||
307 | config MFD_MAX8998 | 340 | config MFD_MAX8998 |
308 | bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" | 341 | bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" |
309 | depends on I2C=y && GENERIC_HARDIRQS | 342 | depends on I2C=y && GENERIC_HARDIRQS |
@@ -534,6 +567,13 @@ config AB8500_DEBUG | |||
534 | Select this option if you want debug information using the debug | 567 | Select this option if you want debug information using the debug |
535 | filesystem, debugfs. | 568 | filesystem, debugfs. |
536 | 569 | ||
570 | config AB8500_GPADC | ||
571 | bool "AB8500 GPADC driver" | ||
572 | depends on AB8500_CORE && REGULATOR_AB8500 | ||
573 | default y | ||
574 | help | ||
575 | AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage | ||
576 | |||
537 | config AB3550_CORE | 577 | config AB3550_CORE |
538 | bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions" | 578 | bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions" |
539 | select MFD_CORE | 579 | select MFD_CORE |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f0e25cad762e..47f5709f3828 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -33,11 +33,13 @@ obj-$(CONFIG_MFD_WM8350) += wm8350.o | |||
33 | obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o | 33 | obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o |
34 | obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o | 34 | obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o |
35 | 35 | ||
36 | obj-$(CONFIG_TPS6105X) += tps6105x.o | ||
36 | obj-$(CONFIG_TPS65010) += tps65010.o | 37 | obj-$(CONFIG_TPS65010) += tps65010.o |
37 | obj-$(CONFIG_TPS6507X) += tps6507x.o | 38 | obj-$(CONFIG_TPS6507X) += tps6507x.o |
38 | obj-$(CONFIG_MENELAUS) += menelaus.o | 39 | obj-$(CONFIG_MENELAUS) += menelaus.o |
39 | 40 | ||
40 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o | 41 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o |
42 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o | ||
41 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | 43 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o |
42 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | 44 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o |
43 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | 45 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o |
@@ -61,6 +63,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o | |||
61 | obj-$(CONFIG_PMIC_DA903X) += da903x.o | 63 | obj-$(CONFIG_PMIC_DA903X) += da903x.o |
62 | max8925-objs := max8925-core.o max8925-i2c.o | 64 | max8925-objs := max8925-core.o max8925-i2c.o |
63 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 65 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
66 | obj-$(CONFIG_MFD_MAX8997) += max8997.o | ||
64 | obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o | 67 | obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o |
65 | 68 | ||
66 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o | 69 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o |
@@ -71,9 +74,10 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o | |||
71 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o | 74 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o |
72 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o | 75 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o |
73 | obj-$(CONFIG_AB3550_CORE) += ab3550-core.o | 76 | obj-$(CONFIG_AB3550_CORE) += ab3550-core.o |
74 | obj-$(CONFIG_AB8500_CORE) += ab8500-core.o | 77 | obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o |
75 | obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o | 78 | obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o |
76 | obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o | 79 | obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o |
80 | obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o | ||
77 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o | 81 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o |
78 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | 82 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o |
79 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o | 83 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o |
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 4193af5f2743..a751927047ac 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -613,7 +613,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) | |||
613 | ab3100_get_priv.ab3100 = ab3100; | 613 | ab3100_get_priv.ab3100 = ab3100; |
614 | ab3100_get_priv.mode = false; | 614 | ab3100_get_priv.mode = false; |
615 | ab3100_get_reg_file = debugfs_create_file("get_reg", | 615 | ab3100_get_reg_file = debugfs_create_file("get_reg", |
616 | S_IWUGO, ab3100_dir, &ab3100_get_priv, | 616 | S_IWUSR, ab3100_dir, &ab3100_get_priv, |
617 | &ab3100_get_set_reg_fops); | 617 | &ab3100_get_set_reg_fops); |
618 | if (!ab3100_get_reg_file) { | 618 | if (!ab3100_get_reg_file) { |
619 | err = -ENOMEM; | 619 | err = -ENOMEM; |
@@ -623,7 +623,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) | |||
623 | ab3100_set_priv.ab3100 = ab3100; | 623 | ab3100_set_priv.ab3100 = ab3100; |
624 | ab3100_set_priv.mode = true; | 624 | ab3100_set_priv.mode = true; |
625 | ab3100_set_reg_file = debugfs_create_file("set_reg", | 625 | ab3100_set_reg_file = debugfs_create_file("set_reg", |
626 | S_IWUGO, ab3100_dir, &ab3100_set_priv, | 626 | S_IWUSR, ab3100_dir, &ab3100_set_priv, |
627 | &ab3100_get_set_reg_fops); | 627 | &ab3100_get_set_reg_fops); |
628 | if (!ab3100_set_reg_file) { | 628 | if (!ab3100_set_reg_file) { |
629 | err = -ENOMEM; | 629 | err = -ENOMEM; |
@@ -949,10 +949,8 @@ static int __devinit ab3100_probe(struct i2c_client *client, | |||
949 | goto exit_no_ops; | 949 | goto exit_no_ops; |
950 | 950 | ||
951 | /* Set up and register the platform devices. */ | 951 | /* Set up and register the platform devices. */ |
952 | for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) { | 952 | for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) |
953 | ab3100_devs[i].platform_data = ab3100_plf_data; | 953 | ab3100_devs[i].mfd_data = ab3100_plf_data; |
954 | ab3100_devs[i].data_size = sizeof(struct ab3100_platform_data); | ||
955 | } | ||
956 | 954 | ||
957 | err = mfd_add_devices(&client->dev, 0, ab3100_devs, | 955 | err = mfd_add_devices(&client->dev, 0, ab3100_devs, |
958 | ARRAY_SIZE(ab3100_devs), NULL, 0); | 956 | ARRAY_SIZE(ab3100_devs), NULL, 0); |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index 5fbca346b998..c12d04285226 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c | |||
@@ -1053,17 +1053,17 @@ static inline void ab3550_setup_debugfs(struct ab3550 *ab) | |||
1053 | goto exit_destroy_dir; | 1053 | goto exit_destroy_dir; |
1054 | 1054 | ||
1055 | ab3550_bank_file = debugfs_create_file("register-bank", | 1055 | ab3550_bank_file = debugfs_create_file("register-bank", |
1056 | (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_bank_fops); | 1056 | (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_bank_fops); |
1057 | if (!ab3550_bank_file) | 1057 | if (!ab3550_bank_file) |
1058 | goto exit_destroy_reg; | 1058 | goto exit_destroy_reg; |
1059 | 1059 | ||
1060 | ab3550_address_file = debugfs_create_file("register-address", | 1060 | ab3550_address_file = debugfs_create_file("register-address", |
1061 | (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_address_fops); | 1061 | (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_address_fops); |
1062 | if (!ab3550_address_file) | 1062 | if (!ab3550_address_file) |
1063 | goto exit_destroy_bank; | 1063 | goto exit_destroy_bank; |
1064 | 1064 | ||
1065 | ab3550_val_file = debugfs_create_file("register-value", | 1065 | ab3550_val_file = debugfs_create_file("register-value", |
1066 | (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_val_fops); | 1066 | (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_val_fops); |
1067 | if (!ab3550_val_file) | 1067 | if (!ab3550_val_file) |
1068 | goto exit_destroy_address; | 1068 | goto exit_destroy_address; |
1069 | 1069 | ||
@@ -1320,10 +1320,8 @@ static int __init ab3550_probe(struct i2c_client *client, | |||
1320 | goto exit_no_ops; | 1320 | goto exit_no_ops; |
1321 | 1321 | ||
1322 | /* Set up and register the platform devices. */ | 1322 | /* Set up and register the platform devices. */ |
1323 | for (i = 0; i < AB3550_NUM_DEVICES; i++) { | 1323 | for (i = 0; i < AB3550_NUM_DEVICES; i++) |
1324 | ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i]; | 1324 | ab3550_devs[i].mfd_data = ab3550_plf_data->dev_data[i]; |
1325 | ab3550_devs[i].data_size = ab3550_plf_data->dev_data_sz[i]; | ||
1326 | } | ||
1327 | 1325 | ||
1328 | err = mfd_add_devices(&client->dev, 0, ab3550_devs, | 1326 | err = mfd_add_devices(&client->dev, 0, ab3550_devs, |
1329 | ARRAY_SIZE(ab3550_devs), NULL, | 1327 | ARRAY_SIZE(ab3550_devs), NULL, |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index b6887014d687..6e185b272d00 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * License Terms: GNU General Public License v2 | 4 | * License Terms: GNU General Public License v2 |
5 | * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | 5 | * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> |
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> | 6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> |
7 | * Changes: Mattias Wallin <mattias.wallin@stericsson.com> | 7 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -90,6 +90,7 @@ | |||
90 | #define AB8500_IT_MASK24_REG 0x57 | 90 | #define AB8500_IT_MASK24_REG 0x57 |
91 | 91 | ||
92 | #define AB8500_REV_REG 0x80 | 92 | #define AB8500_REV_REG 0x80 |
93 | #define AB8500_SWITCH_OFF_STATUS 0x00 | ||
93 | 94 | ||
94 | /* | 95 | /* |
95 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt | 96 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt |
@@ -652,10 +653,38 @@ static ssize_t show_chip_id(struct device *dev, | |||
652 | return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); | 653 | return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); |
653 | } | 654 | } |
654 | 655 | ||
656 | /* | ||
657 | * ab8500 has switched off due to (SWITCH_OFF_STATUS): | ||
658 | * 0x01 Swoff bit programming | ||
659 | * 0x02 Thermal protection activation | ||
660 | * 0x04 Vbat lower then BattOk falling threshold | ||
661 | * 0x08 Watchdog expired | ||
662 | * 0x10 Non presence of 32kHz clock | ||
663 | * 0x20 Battery level lower than power on reset threshold | ||
664 | * 0x40 Power on key 1 pressed longer than 10 seconds | ||
665 | * 0x80 DB8500 thermal shutdown | ||
666 | */ | ||
667 | static ssize_t show_switch_off_status(struct device *dev, | ||
668 | struct device_attribute *attr, char *buf) | ||
669 | { | ||
670 | int ret; | ||
671 | u8 value; | ||
672 | struct ab8500 *ab8500; | ||
673 | |||
674 | ab8500 = dev_get_drvdata(dev); | ||
675 | ret = get_register_interruptible(ab8500, AB8500_RTC, | ||
676 | AB8500_SWITCH_OFF_STATUS, &value); | ||
677 | if (ret < 0) | ||
678 | return ret; | ||
679 | return sprintf(buf, "%#x\n", value); | ||
680 | } | ||
681 | |||
655 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); | 682 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); |
683 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); | ||
656 | 684 | ||
657 | static struct attribute *ab8500_sysfs_entries[] = { | 685 | static struct attribute *ab8500_sysfs_entries[] = { |
658 | &dev_attr_chip_id.attr, | 686 | &dev_attr_chip_id.attr, |
687 | &dev_attr_switch_off_status.attr, | ||
659 | NULL, | 688 | NULL, |
660 | }; | 689 | }; |
661 | 690 | ||
@@ -686,9 +715,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
686 | * 0x10 - Cut 1.0 | 715 | * 0x10 - Cut 1.0 |
687 | * 0x11 - Cut 1.1 | 716 | * 0x11 - Cut 1.1 |
688 | * 0x20 - Cut 2.0 | 717 | * 0x20 - Cut 2.0 |
718 | * 0x30 - Cut 3.0 | ||
689 | */ | 719 | */ |
690 | if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20) { | 720 | if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20 || |
691 | ab8500->revision = value; | 721 | value == 0x30) { |
692 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); | 722 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); |
693 | } else { | 723 | } else { |
694 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); | 724 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); |
@@ -696,6 +726,24 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
696 | } | 726 | } |
697 | ab8500->chip_id = value; | 727 | ab8500->chip_id = value; |
698 | 728 | ||
729 | /* | ||
730 | * ab8500 has switched off due to (SWITCH_OFF_STATUS): | ||
731 | * 0x01 Swoff bit programming | ||
732 | * 0x02 Thermal protection activation | ||
733 | * 0x04 Vbat lower then BattOk falling threshold | ||
734 | * 0x08 Watchdog expired | ||
735 | * 0x10 Non presence of 32kHz clock | ||
736 | * 0x20 Battery level lower than power on reset threshold | ||
737 | * 0x40 Power on key 1 pressed longer than 10 seconds | ||
738 | * 0x80 DB8500 thermal shutdown | ||
739 | */ | ||
740 | |||
741 | ret = get_register_interruptible(ab8500, AB8500_RTC, | ||
742 | AB8500_SWITCH_OFF_STATUS, &value); | ||
743 | if (ret < 0) | ||
744 | return ret; | ||
745 | dev_info(ab8500->dev, "switch off status: %#x", value); | ||
746 | |||
699 | if (plat && plat->init) | 747 | if (plat && plat->init) |
700 | plat->init(ab8500); | 748 | plat->init(ab8500); |
701 | 749 | ||
@@ -764,6 +812,6 @@ int __devexit ab8500_exit(struct ab8500 *ab8500) | |||
764 | return 0; | 812 | return 0; |
765 | } | 813 | } |
766 | 814 | ||
767 | MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent"); | 815 | MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); |
768 | MODULE_DESCRIPTION("AB8500 MFD core"); | 816 | MODULE_DESCRIPTION("AB8500 MFD core"); |
769 | MODULE_LICENSE("GPL v2"); | 817 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 3c1541ae7223..64748e42ac03 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c | |||
@@ -585,18 +585,18 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) | |||
585 | goto exit_destroy_dir; | 585 | goto exit_destroy_dir; |
586 | 586 | ||
587 | ab8500_bank_file = debugfs_create_file("register-bank", | 587 | ab8500_bank_file = debugfs_create_file("register-bank", |
588 | (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops); | 588 | (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops); |
589 | if (!ab8500_bank_file) | 589 | if (!ab8500_bank_file) |
590 | goto exit_destroy_reg; | 590 | goto exit_destroy_reg; |
591 | 591 | ||
592 | ab8500_address_file = debugfs_create_file("register-address", | 592 | ab8500_address_file = debugfs_create_file("register-address", |
593 | (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, | 593 | (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, |
594 | &ab8500_address_fops); | 594 | &ab8500_address_fops); |
595 | if (!ab8500_address_file) | 595 | if (!ab8500_address_file) |
596 | goto exit_destroy_bank; | 596 | goto exit_destroy_bank; |
597 | 597 | ||
598 | ab8500_val_file = debugfs_create_file("register-value", | 598 | ab8500_val_file = debugfs_create_file("register-value", |
599 | (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops); | 599 | (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops); |
600 | if (!ab8500_val_file) | 600 | if (!ab8500_val_file) |
601 | goto exit_destroy_address; | 601 | goto exit_destroy_address; |
602 | 602 | ||
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c new file mode 100644 index 000000000000..bc93b2e8230c --- /dev/null +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -0,0 +1,614 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * Author: Arun R Murthy <arun.murthy@stericsson.com> | ||
6 | * Author: Daniel Willerud <daniel.willerud@stericsson.com> | ||
7 | * Author: Johan Palsson <johan.palsson@stericsson.com> | ||
8 | */ | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/completion.h> | ||
17 | #include <linux/regulator/consumer.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/list.h> | ||
21 | #include <linux/mfd/ab8500.h> | ||
22 | #include <linux/mfd/abx500.h> | ||
23 | #include <linux/mfd/ab8500/gpadc.h> | ||
24 | |||
25 | /* | ||
26 | * GPADC register offsets | ||
27 | * Bank : 0x0A | ||
28 | */ | ||
29 | #define AB8500_GPADC_CTRL1_REG 0x00 | ||
30 | #define AB8500_GPADC_CTRL2_REG 0x01 | ||
31 | #define AB8500_GPADC_CTRL3_REG 0x02 | ||
32 | #define AB8500_GPADC_AUTO_TIMER_REG 0x03 | ||
33 | #define AB8500_GPADC_STAT_REG 0x04 | ||
34 | #define AB8500_GPADC_MANDATAL_REG 0x05 | ||
35 | #define AB8500_GPADC_MANDATAH_REG 0x06 | ||
36 | #define AB8500_GPADC_AUTODATAL_REG 0x07 | ||
37 | #define AB8500_GPADC_AUTODATAH_REG 0x08 | ||
38 | #define AB8500_GPADC_MUX_CTRL_REG 0x09 | ||
39 | |||
40 | /* | ||
41 | * OTP register offsets | ||
42 | * Bank : 0x15 | ||
43 | */ | ||
44 | #define AB8500_GPADC_CAL_1 0x0F | ||
45 | #define AB8500_GPADC_CAL_2 0x10 | ||
46 | #define AB8500_GPADC_CAL_3 0x11 | ||
47 | #define AB8500_GPADC_CAL_4 0x12 | ||
48 | #define AB8500_GPADC_CAL_5 0x13 | ||
49 | #define AB8500_GPADC_CAL_6 0x14 | ||
50 | #define AB8500_GPADC_CAL_7 0x15 | ||
51 | |||
52 | /* gpadc constants */ | ||
53 | #define EN_VINTCORE12 0x04 | ||
54 | #define EN_VTVOUT 0x02 | ||
55 | #define EN_GPADC 0x01 | ||
56 | #define DIS_GPADC 0x00 | ||
57 | #define SW_AVG_16 0x60 | ||
58 | #define ADC_SW_CONV 0x04 | ||
59 | #define EN_ICHAR 0x80 | ||
60 | #define EN_BUF 0x40 | ||
61 | #define DIS_ZERO 0x00 | ||
62 | #define GPADC_BUSY 0x01 | ||
63 | |||
64 | /* GPADC constants from AB8500 spec, UM0836 */ | ||
65 | #define ADC_RESOLUTION 1024 | ||
66 | #define ADC_CH_BTEMP_MIN 0 | ||
67 | #define ADC_CH_BTEMP_MAX 1350 | ||
68 | #define ADC_CH_DIETEMP_MIN 0 | ||
69 | #define ADC_CH_DIETEMP_MAX 1350 | ||
70 | #define ADC_CH_CHG_V_MIN 0 | ||
71 | #define ADC_CH_CHG_V_MAX 20030 | ||
72 | #define ADC_CH_ACCDET2_MIN 0 | ||
73 | #define ADC_CH_ACCDET2_MAX 2500 | ||
74 | #define ADC_CH_VBAT_MIN 2300 | ||
75 | #define ADC_CH_VBAT_MAX 4800 | ||
76 | #define ADC_CH_CHG_I_MIN 0 | ||
77 | #define ADC_CH_CHG_I_MAX 1500 | ||
78 | #define ADC_CH_BKBAT_MIN 0 | ||
79 | #define ADC_CH_BKBAT_MAX 3200 | ||
80 | |||
81 | /* This is used to not lose precision when dividing to get gain and offset */ | ||
82 | #define CALIB_SCALE 1000 | ||
83 | |||
84 | enum cal_channels { | ||
85 | ADC_INPUT_VMAIN = 0, | ||
86 | ADC_INPUT_BTEMP, | ||
87 | ADC_INPUT_VBAT, | ||
88 | NBR_CAL_INPUTS, | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * struct adc_cal_data - Table for storing gain and offset for the calibrated | ||
93 | * ADC channels | ||
94 | * @gain: Gain of the ADC channel | ||
95 | * @offset: Offset of the ADC channel | ||
96 | */ | ||
97 | struct adc_cal_data { | ||
98 | u64 gain; | ||
99 | u64 offset; | ||
100 | }; | ||
101 | |||
102 | /** | ||
103 | * struct ab8500_gpadc - AB8500 GPADC device information | ||
104 | * @dev: pointer to the struct device | ||
105 | * @node: a list of AB8500 GPADCs, hence prepared for | ||
106 | reentrance | ||
107 | * @ab8500_gpadc_complete: pointer to the struct completion, to indicate | ||
108 | * the completion of gpadc conversion | ||
109 | * @ab8500_gpadc_lock: structure of type mutex | ||
110 | * @regu: pointer to the struct regulator | ||
111 | * @irq: interrupt number that is used by gpadc | ||
112 | * @cal_data array of ADC calibration data structs | ||
113 | */ | ||
114 | struct ab8500_gpadc { | ||
115 | struct device *dev; | ||
116 | struct list_head node; | ||
117 | struct completion ab8500_gpadc_complete; | ||
118 | struct mutex ab8500_gpadc_lock; | ||
119 | struct regulator *regu; | ||
120 | int irq; | ||
121 | struct adc_cal_data cal_data[NBR_CAL_INPUTS]; | ||
122 | }; | ||
123 | |||
124 | static LIST_HEAD(ab8500_gpadc_list); | ||
125 | |||
126 | /** | ||
127 | * ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC | ||
128 | * (i.e. the first GPADC in the instance list) | ||
129 | */ | ||
130 | struct ab8500_gpadc *ab8500_gpadc_get(char *name) | ||
131 | { | ||
132 | struct ab8500_gpadc *gpadc; | ||
133 | |||
134 | list_for_each_entry(gpadc, &ab8500_gpadc_list, node) { | ||
135 | if (!strcmp(name, dev_name(gpadc->dev))) | ||
136 | return gpadc; | ||
137 | } | ||
138 | |||
139 | return ERR_PTR(-ENOENT); | ||
140 | } | ||
141 | EXPORT_SYMBOL(ab8500_gpadc_get); | ||
142 | |||
143 | static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input, | ||
144 | int ad_value) | ||
145 | { | ||
146 | int res; | ||
147 | |||
148 | switch (input) { | ||
149 | case MAIN_CHARGER_V: | ||
150 | /* For some reason we don't have calibrated data */ | ||
151 | if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) { | ||
152 | res = ADC_CH_CHG_V_MIN + (ADC_CH_CHG_V_MAX - | ||
153 | ADC_CH_CHG_V_MIN) * ad_value / | ||
154 | ADC_RESOLUTION; | ||
155 | break; | ||
156 | } | ||
157 | /* Here we can use the calibrated data */ | ||
158 | res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VMAIN].gain + | ||
159 | gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE; | ||
160 | break; | ||
161 | |||
162 | case BAT_CTRL: | ||
163 | case BTEMP_BALL: | ||
164 | case ACC_DETECT1: | ||
165 | case ADC_AUX1: | ||
166 | case ADC_AUX2: | ||
167 | /* For some reason we don't have calibrated data */ | ||
168 | if (!gpadc->cal_data[ADC_INPUT_BTEMP].gain) { | ||
169 | res = ADC_CH_BTEMP_MIN + (ADC_CH_BTEMP_MAX - | ||
170 | ADC_CH_BTEMP_MIN) * ad_value / | ||
171 | ADC_RESOLUTION; | ||
172 | break; | ||
173 | } | ||
174 | /* Here we can use the calibrated data */ | ||
175 | res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_BTEMP].gain + | ||
176 | gpadc->cal_data[ADC_INPUT_BTEMP].offset) / CALIB_SCALE; | ||
177 | break; | ||
178 | |||
179 | case MAIN_BAT_V: | ||
180 | /* For some reason we don't have calibrated data */ | ||
181 | if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) { | ||
182 | res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX - | ||
183 | ADC_CH_VBAT_MIN) * ad_value / | ||
184 | ADC_RESOLUTION; | ||
185 | break; | ||
186 | } | ||
187 | /* Here we can use the calibrated data */ | ||
188 | res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VBAT].gain + | ||
189 | gpadc->cal_data[ADC_INPUT_VBAT].offset) / CALIB_SCALE; | ||
190 | break; | ||
191 | |||
192 | case DIE_TEMP: | ||
193 | res = ADC_CH_DIETEMP_MIN + | ||
194 | (ADC_CH_DIETEMP_MAX - ADC_CH_DIETEMP_MIN) * ad_value / | ||
195 | ADC_RESOLUTION; | ||
196 | break; | ||
197 | |||
198 | case ACC_DETECT2: | ||
199 | res = ADC_CH_ACCDET2_MIN + | ||
200 | (ADC_CH_ACCDET2_MAX - ADC_CH_ACCDET2_MIN) * ad_value / | ||
201 | ADC_RESOLUTION; | ||
202 | break; | ||
203 | |||
204 | case VBUS_V: | ||
205 | res = ADC_CH_CHG_V_MIN + | ||
206 | (ADC_CH_CHG_V_MAX - ADC_CH_CHG_V_MIN) * ad_value / | ||
207 | ADC_RESOLUTION; | ||
208 | break; | ||
209 | |||
210 | case MAIN_CHARGER_C: | ||
211 | case USB_CHARGER_C: | ||
212 | res = ADC_CH_CHG_I_MIN + | ||
213 | (ADC_CH_CHG_I_MAX - ADC_CH_CHG_I_MIN) * ad_value / | ||
214 | ADC_RESOLUTION; | ||
215 | break; | ||
216 | |||
217 | case BK_BAT_V: | ||
218 | res = ADC_CH_BKBAT_MIN + | ||
219 | (ADC_CH_BKBAT_MAX - ADC_CH_BKBAT_MIN) * ad_value / | ||
220 | ADC_RESOLUTION; | ||
221 | break; | ||
222 | |||
223 | default: | ||
224 | dev_err(gpadc->dev, | ||
225 | "unknown channel, not possible to convert\n"); | ||
226 | res = -EINVAL; | ||
227 | break; | ||
228 | |||
229 | } | ||
230 | return res; | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * ab8500_gpadc_convert() - gpadc conversion | ||
235 | * @input: analog input to be converted to digital data | ||
236 | * | ||
237 | * This function converts the selected analog i/p to digital | ||
238 | * data. | ||
239 | */ | ||
240 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | ||
241 | { | ||
242 | int ret; | ||
243 | u16 data = 0; | ||
244 | int looplimit = 0; | ||
245 | u8 val, low_data, high_data; | ||
246 | |||
247 | if (!gpadc) | ||
248 | return -ENODEV; | ||
249 | |||
250 | mutex_lock(&gpadc->ab8500_gpadc_lock); | ||
251 | /* Enable VTVout LDO this is required for GPADC */ | ||
252 | regulator_enable(gpadc->regu); | ||
253 | |||
254 | /* Check if ADC is not busy, lock and proceed */ | ||
255 | do { | ||
256 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
257 | AB8500_GPADC, AB8500_GPADC_STAT_REG, &val); | ||
258 | if (ret < 0) | ||
259 | goto out; | ||
260 | if (!(val & GPADC_BUSY)) | ||
261 | break; | ||
262 | msleep(10); | ||
263 | } while (++looplimit < 10); | ||
264 | if (looplimit >= 10 && (val & GPADC_BUSY)) { | ||
265 | dev_err(gpadc->dev, "gpadc_conversion: GPADC busy"); | ||
266 | ret = -EINVAL; | ||
267 | goto out; | ||
268 | } | ||
269 | |||
270 | /* Enable GPADC */ | ||
271 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
272 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_GPADC, EN_GPADC); | ||
273 | if (ret < 0) { | ||
274 | dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n"); | ||
275 | goto out; | ||
276 | } | ||
277 | /* Select the input source and set average samples to 16 */ | ||
278 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | ||
279 | AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16)); | ||
280 | if (ret < 0) { | ||
281 | dev_err(gpadc->dev, | ||
282 | "gpadc_conversion: set avg samples failed\n"); | ||
283 | goto out; | ||
284 | } | ||
285 | /* | ||
286 | * Enable ADC, buffering, select rising edge and enable ADC path | ||
287 | * charging current sense if it needed | ||
288 | */ | ||
289 | switch (input) { | ||
290 | case MAIN_CHARGER_C: | ||
291 | case USB_CHARGER_C: | ||
292 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
293 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
294 | EN_BUF | EN_ICHAR, | ||
295 | EN_BUF | EN_ICHAR); | ||
296 | break; | ||
297 | default: | ||
298 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
299 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); | ||
300 | break; | ||
301 | } | ||
302 | if (ret < 0) { | ||
303 | dev_err(gpadc->dev, | ||
304 | "gpadc_conversion: select falling edge failed\n"); | ||
305 | goto out; | ||
306 | } | ||
307 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
308 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV); | ||
309 | if (ret < 0) { | ||
310 | dev_err(gpadc->dev, | ||
311 | "gpadc_conversion: start s/w conversion failed\n"); | ||
312 | goto out; | ||
313 | } | ||
314 | /* wait for completion of conversion */ | ||
315 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, 2*HZ)) { | ||
316 | dev_err(gpadc->dev, | ||
317 | "timeout: didnt recieve GPADC conversion interrupt\n"); | ||
318 | ret = -EINVAL; | ||
319 | goto out; | ||
320 | } | ||
321 | |||
322 | /* Read the converted RAW data */ | ||
323 | ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC, | ||
324 | AB8500_GPADC_MANDATAL_REG, &low_data); | ||
325 | if (ret < 0) { | ||
326 | dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n"); | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC, | ||
331 | AB8500_GPADC_MANDATAH_REG, &high_data); | ||
332 | if (ret < 0) { | ||
333 | dev_err(gpadc->dev, | ||
334 | "gpadc_conversion: read high data failed\n"); | ||
335 | goto out; | ||
336 | } | ||
337 | |||
338 | data = (high_data << 8) | low_data; | ||
339 | /* Disable GPADC */ | ||
340 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | ||
341 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | ||
342 | if (ret < 0) { | ||
343 | dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); | ||
344 | goto out; | ||
345 | } | ||
346 | /* Disable VTVout LDO this is required for GPADC */ | ||
347 | regulator_disable(gpadc->regu); | ||
348 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | ||
349 | ret = ab8500_gpadc_ad_to_voltage(gpadc, input, data); | ||
350 | return ret; | ||
351 | |||
352 | out: | ||
353 | /* | ||
354 | * It has shown to be needed to turn off the GPADC if an error occurs, | ||
355 | * otherwise we might have problem when waiting for the busy bit in the | ||
356 | * GPADC status register to go low. In V1.1 there wait_for_completion | ||
357 | * seems to timeout when waiting for an interrupt.. Not seen in V2.0 | ||
358 | */ | ||
359 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | ||
360 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | ||
361 | regulator_disable(gpadc->regu); | ||
362 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | ||
363 | dev_err(gpadc->dev, | ||
364 | "gpadc_conversion: Failed to AD convert channel %d\n", input); | ||
365 | return ret; | ||
366 | } | ||
367 | EXPORT_SYMBOL(ab8500_gpadc_convert); | ||
368 | |||
369 | /** | ||
370 | * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion | ||
371 | * @irq: irq number | ||
372 | * @data: pointer to the data passed during request irq | ||
373 | * | ||
374 | * This is a interrupt service routine for s/w gpadc conversion completion. | ||
375 | * Notifies the gpadc completion is completed and the converted raw value | ||
376 | * can be read from the registers. | ||
377 | * Returns IRQ status(IRQ_HANDLED) | ||
378 | */ | ||
379 | static irqreturn_t ab8500_bm_gpswadcconvend_handler(int irq, void *_gpadc) | ||
380 | { | ||
381 | struct ab8500_gpadc *gpadc = _gpadc; | ||
382 | |||
383 | complete(&gpadc->ab8500_gpadc_complete); | ||
384 | |||
385 | return IRQ_HANDLED; | ||
386 | } | ||
387 | |||
388 | static int otp_cal_regs[] = { | ||
389 | AB8500_GPADC_CAL_1, | ||
390 | AB8500_GPADC_CAL_2, | ||
391 | AB8500_GPADC_CAL_3, | ||
392 | AB8500_GPADC_CAL_4, | ||
393 | AB8500_GPADC_CAL_5, | ||
394 | AB8500_GPADC_CAL_6, | ||
395 | AB8500_GPADC_CAL_7, | ||
396 | }; | ||
397 | |||
398 | static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | ||
399 | { | ||
400 | int i; | ||
401 | int ret[ARRAY_SIZE(otp_cal_regs)]; | ||
402 | u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)]; | ||
403 | |||
404 | int vmain_high, vmain_low; | ||
405 | int btemp_high, btemp_low; | ||
406 | int vbat_high, vbat_low; | ||
407 | |||
408 | /* First we read all OTP registers and store the error code */ | ||
409 | for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { | ||
410 | ret[i] = abx500_get_register_interruptible(gpadc->dev, | ||
411 | AB8500_OTP_EMUL, otp_cal_regs[i], &gpadc_cal[i]); | ||
412 | if (ret[i] < 0) | ||
413 | dev_err(gpadc->dev, "%s: read otp reg 0x%02x failed\n", | ||
414 | __func__, otp_cal_regs[i]); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * The ADC calibration data is stored in OTP registers. | ||
419 | * The layout of the calibration data is outlined below and a more | ||
420 | * detailed description can be found in UM0836 | ||
421 | * | ||
422 | * vm_h/l = vmain_high/low | ||
423 | * bt_h/l = btemp_high/low | ||
424 | * vb_h/l = vbat_high/low | ||
425 | * | ||
426 | * Data bits: | ||
427 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
428 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
429 | * | | vm_h9 | vm_h8 | ||
430 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
431 | * | | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2 | ||
432 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
433 | * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9 | ||
434 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
435 | * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1 | ||
436 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
437 | * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8 | ||
438 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
439 | * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0 | ||
440 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
441 | * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | | ||
442 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
443 | * | ||
444 | * | ||
445 | * Ideal output ADC codes corresponding to injected input voltages | ||
446 | * during manufacturing is: | ||
447 | * | ||
448 | * vmain_high: Vin = 19500mV / ADC ideal code = 997 | ||
449 | * vmain_low: Vin = 315mV / ADC ideal code = 16 | ||
450 | * btemp_high: Vin = 1300mV / ADC ideal code = 985 | ||
451 | * btemp_low: Vin = 21mV / ADC ideal code = 16 | ||
452 | * vbat_high: Vin = 4700mV / ADC ideal code = 982 | ||
453 | * vbat_low: Vin = 2380mV / ADC ideal code = 33 | ||
454 | */ | ||
455 | |||
456 | /* Calculate gain and offset for VMAIN if all reads succeeded */ | ||
457 | if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) { | ||
458 | vmain_high = (((gpadc_cal[0] & 0x03) << 8) | | ||
459 | ((gpadc_cal[1] & 0x3F) << 2) | | ||
460 | ((gpadc_cal[2] & 0xC0) >> 6)); | ||
461 | |||
462 | vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); | ||
463 | |||
464 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * | ||
465 | (19500 - 315) / (vmain_high - vmain_low); | ||
466 | |||
467 | gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * 19500 - | ||
468 | (CALIB_SCALE * (19500 - 315) / | ||
469 | (vmain_high - vmain_low)) * vmain_high; | ||
470 | } else { | ||
471 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; | ||
472 | } | ||
473 | |||
474 | /* Calculate gain and offset for BTEMP if all reads succeeded */ | ||
475 | if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) { | ||
476 | btemp_high = (((gpadc_cal[2] & 0x01) << 9) | | ||
477 | (gpadc_cal[3] << 1) | | ||
478 | ((gpadc_cal[4] & 0x80) >> 7)); | ||
479 | |||
480 | btemp_low = ((gpadc_cal[4] & 0x7C) >> 2); | ||
481 | |||
482 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = | ||
483 | CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low); | ||
484 | |||
485 | gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 - | ||
486 | (CALIB_SCALE * (1300 - 21) / | ||
487 | (btemp_high - btemp_low)) * btemp_high; | ||
488 | } else { | ||
489 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0; | ||
490 | } | ||
491 | |||
492 | /* Calculate gain and offset for VBAT if all reads succeeded */ | ||
493 | if (!(ret[4] < 0 || ret[5] < 0 || ret[6] < 0)) { | ||
494 | vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]); | ||
495 | vbat_low = ((gpadc_cal[6] & 0xFC) >> 2); | ||
496 | |||
497 | gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE * | ||
498 | (4700 - 2380) / (vbat_high - vbat_low); | ||
499 | |||
500 | gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 - | ||
501 | (CALIB_SCALE * (4700 - 2380) / | ||
502 | (vbat_high - vbat_low)) * vbat_high; | ||
503 | } else { | ||
504 | gpadc->cal_data[ADC_INPUT_VBAT].gain = 0; | ||
505 | } | ||
506 | |||
507 | dev_dbg(gpadc->dev, "VMAIN gain %llu offset %llu\n", | ||
508 | gpadc->cal_data[ADC_INPUT_VMAIN].gain, | ||
509 | gpadc->cal_data[ADC_INPUT_VMAIN].offset); | ||
510 | |||
511 | dev_dbg(gpadc->dev, "BTEMP gain %llu offset %llu\n", | ||
512 | gpadc->cal_data[ADC_INPUT_BTEMP].gain, | ||
513 | gpadc->cal_data[ADC_INPUT_BTEMP].offset); | ||
514 | |||
515 | dev_dbg(gpadc->dev, "VBAT gain %llu offset %llu\n", | ||
516 | gpadc->cal_data[ADC_INPUT_VBAT].gain, | ||
517 | gpadc->cal_data[ADC_INPUT_VBAT].offset); | ||
518 | } | ||
519 | |||
520 | static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) | ||
521 | { | ||
522 | int ret = 0; | ||
523 | struct ab8500_gpadc *gpadc; | ||
524 | |||
525 | gpadc = kzalloc(sizeof(struct ab8500_gpadc), GFP_KERNEL); | ||
526 | if (!gpadc) { | ||
527 | dev_err(&pdev->dev, "Error: No memory\n"); | ||
528 | return -ENOMEM; | ||
529 | } | ||
530 | |||
531 | gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END"); | ||
532 | if (gpadc->irq < 0) { | ||
533 | dev_err(gpadc->dev, "failed to get platform irq-%d\n", | ||
534 | gpadc->irq); | ||
535 | ret = gpadc->irq; | ||
536 | goto fail; | ||
537 | } | ||
538 | |||
539 | gpadc->dev = &pdev->dev; | ||
540 | mutex_init(&gpadc->ab8500_gpadc_lock); | ||
541 | |||
542 | /* Initialize completion used to notify completion of conversion */ | ||
543 | init_completion(&gpadc->ab8500_gpadc_complete); | ||
544 | |||
545 | /* Register interrupt - SwAdcComplete */ | ||
546 | ret = request_threaded_irq(gpadc->irq, NULL, | ||
547 | ab8500_bm_gpswadcconvend_handler, | ||
548 | IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc", gpadc); | ||
549 | if (ret < 0) { | ||
550 | dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", | ||
551 | gpadc->irq); | ||
552 | goto fail; | ||
553 | } | ||
554 | |||
555 | /* VTVout LDO used to power up ab8500-GPADC */ | ||
556 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); | ||
557 | if (IS_ERR(gpadc->regu)) { | ||
558 | ret = PTR_ERR(gpadc->regu); | ||
559 | dev_err(gpadc->dev, "failed to get vtvout LDO\n"); | ||
560 | goto fail_irq; | ||
561 | } | ||
562 | ab8500_gpadc_read_calibration_data(gpadc); | ||
563 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); | ||
564 | dev_dbg(gpadc->dev, "probe success\n"); | ||
565 | return 0; | ||
566 | fail_irq: | ||
567 | free_irq(gpadc->irq, gpadc); | ||
568 | fail: | ||
569 | kfree(gpadc); | ||
570 | gpadc = NULL; | ||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | static int __devexit ab8500_gpadc_remove(struct platform_device *pdev) | ||
575 | { | ||
576 | struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev); | ||
577 | |||
578 | /* remove this gpadc entry from the list */ | ||
579 | list_del(&gpadc->node); | ||
580 | /* remove interrupt - completion of Sw ADC conversion */ | ||
581 | free_irq(gpadc->irq, gpadc); | ||
582 | /* disable VTVout LDO that is being used by GPADC */ | ||
583 | regulator_put(gpadc->regu); | ||
584 | kfree(gpadc); | ||
585 | gpadc = NULL; | ||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static struct platform_driver ab8500_gpadc_driver = { | ||
590 | .probe = ab8500_gpadc_probe, | ||
591 | .remove = __devexit_p(ab8500_gpadc_remove), | ||
592 | .driver = { | ||
593 | .name = "ab8500-gpadc", | ||
594 | .owner = THIS_MODULE, | ||
595 | }, | ||
596 | }; | ||
597 | |||
598 | static int __init ab8500_gpadc_init(void) | ||
599 | { | ||
600 | return platform_driver_register(&ab8500_gpadc_driver); | ||
601 | } | ||
602 | |||
603 | static void __exit ab8500_gpadc_exit(void) | ||
604 | { | ||
605 | platform_driver_unregister(&ab8500_gpadc_driver); | ||
606 | } | ||
607 | |||
608 | subsys_initcall_sync(ab8500_gpadc_init); | ||
609 | module_exit(ab8500_gpadc_exit); | ||
610 | |||
611 | MODULE_LICENSE("GPL v2"); | ||
612 | MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson"); | ||
613 | MODULE_ALIAS("platform:ab8500_gpadc"); | ||
614 | MODULE_DESCRIPTION("AB8500 GPADC driver"); | ||
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c new file mode 100644 index 000000000000..392185965b39 --- /dev/null +++ b/drivers/mfd/ab8500-sysctrl.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST Ericsson. | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/err.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | #include <linux/mfd/ab8500.h> | ||
10 | #include <linux/mfd/abx500.h> | ||
11 | #include <linux/mfd/ab8500/sysctrl.h> | ||
12 | |||
13 | static struct device *sysctrl_dev; | ||
14 | |||
15 | static inline bool valid_bank(u8 bank) | ||
16 | { | ||
17 | return ((bank == AB8500_SYS_CTRL1_BLOCK) || | ||
18 | (bank == AB8500_SYS_CTRL2_BLOCK)); | ||
19 | } | ||
20 | |||
21 | int ab8500_sysctrl_read(u16 reg, u8 *value) | ||
22 | { | ||
23 | u8 bank; | ||
24 | |||
25 | if (sysctrl_dev == NULL) | ||
26 | return -EAGAIN; | ||
27 | |||
28 | bank = (reg >> 8); | ||
29 | if (!valid_bank(bank)) | ||
30 | return -EINVAL; | ||
31 | |||
32 | return abx500_get_register_interruptible(sysctrl_dev, bank, | ||
33 | (u8)(reg & 0xFF), value); | ||
34 | } | ||
35 | |||
36 | int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) | ||
37 | { | ||
38 | u8 bank; | ||
39 | |||
40 | if (sysctrl_dev == NULL) | ||
41 | return -EAGAIN; | ||
42 | |||
43 | bank = (reg >> 8); | ||
44 | if (!valid_bank(bank)) | ||
45 | return -EINVAL; | ||
46 | |||
47 | return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank, | ||
48 | (u8)(reg & 0xFF), mask, value); | ||
49 | } | ||
50 | |||
51 | static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev) | ||
52 | { | ||
53 | sysctrl_dev = &pdev->dev; | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev) | ||
58 | { | ||
59 | sysctrl_dev = NULL; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static struct platform_driver ab8500_sysctrl_driver = { | ||
64 | .driver = { | ||
65 | .name = "ab8500-sysctrl", | ||
66 | .owner = THIS_MODULE, | ||
67 | }, | ||
68 | .probe = ab8500_sysctrl_probe, | ||
69 | .remove = __devexit_p(ab8500_sysctrl_remove), | ||
70 | }; | ||
71 | |||
72 | static int __init ab8500_sysctrl_init(void) | ||
73 | { | ||
74 | return platform_driver_register(&ab8500_sysctrl_driver); | ||
75 | } | ||
76 | subsys_initcall(ab8500_sysctrl_init); | ||
77 | |||
78 | MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com"); | ||
79 | MODULE_DESCRIPTION("AB8500 system control driver"); | ||
80 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 3122139b4300..f1d88483112c 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c | |||
@@ -321,27 +321,27 @@ static int __devexit adp5520_remove(struct i2c_client *client) | |||
321 | } | 321 | } |
322 | 322 | ||
323 | #ifdef CONFIG_PM | 323 | #ifdef CONFIG_PM |
324 | static int adp5520_suspend(struct i2c_client *client, | 324 | static int adp5520_suspend(struct device *dev) |
325 | pm_message_t state) | ||
326 | { | 325 | { |
326 | struct i2c_client *client = to_i2c_client(dev); | ||
327 | struct adp5520_chip *chip = dev_get_drvdata(&client->dev); | 327 | struct adp5520_chip *chip = dev_get_drvdata(&client->dev); |
328 | 328 | ||
329 | adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); | 329 | adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); |
330 | return 0; | 330 | return 0; |
331 | } | 331 | } |
332 | 332 | ||
333 | static int adp5520_resume(struct i2c_client *client) | 333 | static int adp5520_resume(struct device *dev) |
334 | { | 334 | { |
335 | struct i2c_client *client = to_i2c_client(dev); | ||
335 | struct adp5520_chip *chip = dev_get_drvdata(&client->dev); | 336 | struct adp5520_chip *chip = dev_get_drvdata(&client->dev); |
336 | 337 | ||
337 | adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); | 338 | adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); |
338 | return 0; | 339 | return 0; |
339 | } | 340 | } |
340 | #else | ||
341 | #define adp5520_suspend NULL | ||
342 | #define adp5520_resume NULL | ||
343 | #endif | 341 | #endif |
344 | 342 | ||
343 | static SIMPLE_DEV_PM_OPS(adp5520_pm, adp5520_suspend, adp5520_resume); | ||
344 | |||
345 | static const struct i2c_device_id adp5520_id[] = { | 345 | static const struct i2c_device_id adp5520_id[] = { |
346 | { "pmic-adp5520", ID_ADP5520 }, | 346 | { "pmic-adp5520", ID_ADP5520 }, |
347 | { "pmic-adp5501", ID_ADP5501 }, | 347 | { "pmic-adp5501", ID_ADP5501 }, |
@@ -353,11 +353,10 @@ static struct i2c_driver adp5520_driver = { | |||
353 | .driver = { | 353 | .driver = { |
354 | .name = "adp5520", | 354 | .name = "adp5520", |
355 | .owner = THIS_MODULE, | 355 | .owner = THIS_MODULE, |
356 | .pm = &adp5520_pm, | ||
356 | }, | 357 | }, |
357 | .probe = adp5520_probe, | 358 | .probe = adp5520_probe, |
358 | .remove = __devexit_p(adp5520_remove), | 359 | .remove = __devexit_p(adp5520_remove), |
359 | .suspend = adp5520_suspend, | ||
360 | .resume = adp5520_resume, | ||
361 | .id_table = adp5520_id, | 360 | .id_table = adp5520_id, |
362 | }; | 361 | }; |
363 | 362 | ||
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index c45e6305b26f..0241f08fc00d 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
@@ -682,7 +682,7 @@ static struct mfd_cell asic3_cell_ds1wm = { | |||
682 | .name = "ds1wm", | 682 | .name = "ds1wm", |
683 | .enable = ds1wm_enable, | 683 | .enable = ds1wm_enable, |
684 | .disable = ds1wm_disable, | 684 | .disable = ds1wm_disable, |
685 | .driver_data = &ds1wm_pdata, | 685 | .mfd_data = &ds1wm_pdata, |
686 | .num_resources = ARRAY_SIZE(ds1wm_resources), | 686 | .num_resources = ARRAY_SIZE(ds1wm_resources), |
687 | .resources = ds1wm_resources, | 687 | .resources = ds1wm_resources, |
688 | }; | 688 | }; |
@@ -783,7 +783,7 @@ static struct mfd_cell asic3_cell_mmc = { | |||
783 | .name = "tmio-mmc", | 783 | .name = "tmio-mmc", |
784 | .enable = asic3_mmc_enable, | 784 | .enable = asic3_mmc_enable, |
785 | .disable = asic3_mmc_disable, | 785 | .disable = asic3_mmc_disable, |
786 | .driver_data = &asic3_mmc_data, | 786 | .mfd_data = &asic3_mmc_data, |
787 | .num_resources = ARRAY_SIZE(asic3_mmc_resources), | 787 | .num_resources = ARRAY_SIZE(asic3_mmc_resources), |
788 | .resources = asic3_mmc_resources, | 788 | .resources = asic3_mmc_resources, |
789 | }; | 789 | }; |
@@ -810,9 +810,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, | |||
810 | ds1wm_resources[0].start >>= asic->bus_shift; | 810 | ds1wm_resources[0].start >>= asic->bus_shift; |
811 | ds1wm_resources[0].end >>= asic->bus_shift; | 811 | ds1wm_resources[0].end >>= asic->bus_shift; |
812 | 812 | ||
813 | asic3_cell_ds1wm.platform_data = &asic3_cell_ds1wm; | ||
814 | asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm); | ||
815 | |||
816 | /* MMC */ | 813 | /* MMC */ |
817 | asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + | 814 | asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + |
818 | mem_sdio->start, 0x400 >> asic->bus_shift); | 815 | mem_sdio->start, 0x400 >> asic->bus_shift); |
@@ -824,9 +821,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, | |||
824 | asic3_mmc_resources[0].start >>= asic->bus_shift; | 821 | asic3_mmc_resources[0].start >>= asic->bus_shift; |
825 | asic3_mmc_resources[0].end >>= asic->bus_shift; | 822 | asic3_mmc_resources[0].end >>= asic->bus_shift; |
826 | 823 | ||
827 | asic3_cell_mmc.platform_data = &asic3_cell_mmc; | ||
828 | asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc); | ||
829 | |||
830 | ret = mfd_add_devices(&pdev->dev, pdev->id, | 824 | ret = mfd_add_devices(&pdev->dev, pdev->id, |
831 | &asic3_cell_ds1wm, 1, mem, asic->irq_base); | 825 | &asic3_cell_ds1wm, 1, mem, asic->irq_base); |
832 | if (ret < 0) | 826 | if (ret < 0) |
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index 59ca6f151e78..886a06871065 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c | |||
@@ -39,6 +39,37 @@ enum cs5535_mfd_bars { | |||
39 | NR_BARS, | 39 | NR_BARS, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static int cs5535_mfd_res_enable(struct platform_device *pdev) | ||
43 | { | ||
44 | struct resource *res; | ||
45 | |||
46 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
47 | if (!res) { | ||
48 | dev_err(&pdev->dev, "can't fetch device resource info\n"); | ||
49 | return -EIO; | ||
50 | } | ||
51 | |||
52 | if (!request_region(res->start, resource_size(res), DRV_NAME)) { | ||
53 | dev_err(&pdev->dev, "can't request region\n"); | ||
54 | return -EIO; | ||
55 | } | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int cs5535_mfd_res_disable(struct platform_device *pdev) | ||
61 | { | ||
62 | struct resource *res; | ||
63 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
64 | if (!res) { | ||
65 | dev_err(&pdev->dev, "can't fetch device resource info\n"); | ||
66 | return -EIO; | ||
67 | } | ||
68 | |||
69 | release_region(res->start, resource_size(res)); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
42 | static __devinitdata struct resource cs5535_mfd_resources[NR_BARS]; | 73 | static __devinitdata struct resource cs5535_mfd_resources[NR_BARS]; |
43 | 74 | ||
44 | static __devinitdata struct mfd_cell cs5535_mfd_cells[] = { | 75 | static __devinitdata struct mfd_cell cs5535_mfd_cells[] = { |
@@ -65,12 +96,18 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = { | |||
65 | .name = "cs5535-pms", | 96 | .name = "cs5535-pms", |
66 | .num_resources = 1, | 97 | .num_resources = 1, |
67 | .resources = &cs5535_mfd_resources[PMS_BAR], | 98 | .resources = &cs5535_mfd_resources[PMS_BAR], |
99 | |||
100 | .enable = cs5535_mfd_res_enable, | ||
101 | .disable = cs5535_mfd_res_disable, | ||
68 | }, | 102 | }, |
69 | { | 103 | { |
70 | .id = ACPI_BAR, | 104 | .id = ACPI_BAR, |
71 | .name = "cs5535-acpi", | 105 | .name = "cs5535-acpi", |
72 | .num_resources = 1, | 106 | .num_resources = 1, |
73 | .resources = &cs5535_mfd_resources[ACPI_BAR], | 107 | .resources = &cs5535_mfd_resources[ACPI_BAR], |
108 | |||
109 | .enable = cs5535_mfd_res_enable, | ||
110 | .disable = cs5535_mfd_res_disable, | ||
74 | }, | 111 | }, |
75 | }; | 112 | }; |
76 | 113 | ||
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index fdd8a1b8bc67..414783b04849 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c | |||
@@ -119,12 +119,12 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
119 | /* Voice codec interface client */ | 119 | /* Voice codec interface client */ |
120 | cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL]; | 120 | cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL]; |
121 | cell->name = "davinci-vcif"; | 121 | cell->name = "davinci-vcif"; |
122 | cell->driver_data = davinci_vc; | 122 | cell->mfd_data = davinci_vc; |
123 | 123 | ||
124 | /* Voice codec CQ93VC client */ | 124 | /* Voice codec CQ93VC client */ |
125 | cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL]; | 125 | cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL]; |
126 | cell->name = "cq93vc-codec"; | 126 | cell->name = "cq93vc-codec"; |
127 | cell->driver_data = davinci_vc; | 127 | cell->mfd_data = davinci_vc; |
128 | 128 | ||
129 | ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, | 129 | ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, |
130 | DAVINCI_VC_CELLS, NULL, 0); | 130 | DAVINCI_VC_CELLS, NULL, 0); |
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 7bc752272dc1..fb9770b39a32 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c | |||
@@ -117,7 +117,7 @@ static struct mfd_cell ds1wm_cell __initdata = { | |||
117 | .name = "ds1wm", | 117 | .name = "ds1wm", |
118 | .enable = ds1wm_enable, | 118 | .enable = ds1wm_enable, |
119 | .disable = ds1wm_disable, | 119 | .disable = ds1wm_disable, |
120 | .driver_data = &ds1wm_pdata, | 120 | .mfd_data = &ds1wm_pdata, |
121 | .num_resources = 2, | 121 | .num_resources = 2, |
122 | .resources = ds1wm_resources, | 122 | .resources = ds1wm_resources, |
123 | }; | 123 | }; |
@@ -165,8 +165,6 @@ static int __init pasic3_probe(struct platform_device *pdev) | |||
165 | ds1wm_pdata.clock_rate = pdata->clock_rate; | 165 | ds1wm_pdata.clock_rate = pdata->clock_rate; |
166 | /* the first 5 PASIC3 registers control the DS1WM */ | 166 | /* the first 5 PASIC3 registers control the DS1WM */ |
167 | ds1wm_resources[0].end = (5 << asic->bus_shift) - 1; | 167 | ds1wm_resources[0].end = (5 << asic->bus_shift) - 1; |
168 | ds1wm_cell.platform_data = &ds1wm_cell; | ||
169 | ds1wm_cell.data_size = sizeof(ds1wm_cell); | ||
170 | ret = mfd_add_devices(&pdev->dev, pdev->id, | 168 | ret = mfd_add_devices(&pdev->dev, pdev->id, |
171 | &ds1wm_cell, 1, r, irq); | 169 | &ds1wm_cell, 1, r, irq); |
172 | if (ret < 0) | 170 | if (ret < 0) |
@@ -174,9 +172,6 @@ static int __init pasic3_probe(struct platform_device *pdev) | |||
174 | } | 172 | } |
175 | 173 | ||
176 | if (pdata && pdata->led_pdata) { | 174 | if (pdata && pdata->led_pdata) { |
177 | led_cell.driver_data = pdata->led_pdata; | ||
178 | led_cell.platform_data = &led_cell; | ||
179 | led_cell.data_size = sizeof(ds1wm_cell); | ||
180 | ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); | 175 | ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); |
181 | if (ret < 0) | 176 | if (ret < 0) |
182 | dev_warn(dev, "failed to register LED device\n"); | 177 | dev_warn(dev, "failed to register LED device\n"); |
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 36a166bcdb08..fc4191137e90 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c | |||
@@ -86,8 +86,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv, | |||
86 | 86 | ||
87 | /* Add platform data */ | 87 | /* Add platform data */ |
88 | pdata->modno = modno; | 88 | pdata->modno = modno; |
89 | cell->platform_data = pdata; | 89 | cell->mfd_data = pdata; |
90 | cell->data_size = sizeof(*pdata); | ||
91 | 90 | ||
92 | /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ | 91 | /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ |
93 | res->flags = IORESOURCE_MEM; | 92 | res->flags = IORESOURCE_MEM; |
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 0cc59795f600..aa518b9beaf5 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -232,8 +232,6 @@ const struct mfd_cell jz4740_adc_cells[] = { | |||
232 | .name = "jz4740-hwmon", | 232 | .name = "jz4740-hwmon", |
233 | .num_resources = ARRAY_SIZE(jz4740_hwmon_resources), | 233 | .num_resources = ARRAY_SIZE(jz4740_hwmon_resources), |
234 | .resources = jz4740_hwmon_resources, | 234 | .resources = jz4740_hwmon_resources, |
235 | .platform_data = (void *)&jz4740_adc_cells[0], | ||
236 | .data_size = sizeof(struct mfd_cell), | ||
237 | 235 | ||
238 | .enable = jz4740_adc_cell_enable, | 236 | .enable = jz4740_adc_cell_enable, |
239 | .disable = jz4740_adc_cell_disable, | 237 | .disable = jz4740_adc_cell_disable, |
@@ -243,8 +241,6 @@ const struct mfd_cell jz4740_adc_cells[] = { | |||
243 | .name = "jz4740-battery", | 241 | .name = "jz4740-battery", |
244 | .num_resources = ARRAY_SIZE(jz4740_battery_resources), | 242 | .num_resources = ARRAY_SIZE(jz4740_battery_resources), |
245 | .resources = jz4740_battery_resources, | 243 | .resources = jz4740_battery_resources, |
246 | .platform_data = (void *)&jz4740_adc_cells[1], | ||
247 | .data_size = sizeof(struct mfd_cell), | ||
248 | 244 | ||
249 | .enable = jz4740_adc_cell_enable, | 245 | .enable = jz4740_adc_cell_enable, |
250 | .disable = jz4740_adc_cell_disable, | 246 | .disable = jz4740_adc_cell_disable, |
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index 51b2f6065a0b..ea3f52c07ef7 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c | |||
@@ -61,6 +61,7 @@ static struct mfd_cell lpc_sch_cells[] = { | |||
61 | 61 | ||
62 | static struct pci_device_id lpc_sch_ids[] = { | 62 | static struct pci_device_id lpc_sch_ids[] = { |
63 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, | 63 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, |
64 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) }, | ||
64 | { 0, } | 65 | { 0, } |
65 | }; | 66 | }; |
66 | MODULE_DEVICE_TABLE(pci, lpc_sch_ids); | 67 | MODULE_DEVICE_TABLE(pci, lpc_sch_ids); |
@@ -70,6 +71,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, | |||
70 | { | 71 | { |
71 | unsigned int base_addr_cfg; | 72 | unsigned int base_addr_cfg; |
72 | unsigned short base_addr; | 73 | unsigned short base_addr; |
74 | int i; | ||
73 | 75 | ||
74 | pci_read_config_dword(dev, SMBASE, &base_addr_cfg); | 76 | pci_read_config_dword(dev, SMBASE, &base_addr_cfg); |
75 | if (!(base_addr_cfg & (1 << 31))) { | 77 | if (!(base_addr_cfg & (1 << 31))) { |
@@ -99,7 +101,10 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, | |||
99 | gpio_sch_resource.start = base_addr; | 101 | gpio_sch_resource.start = base_addr; |
100 | gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; | 102 | gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; |
101 | 103 | ||
102 | return mfd_add_devices(&dev->dev, -1, | 104 | for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++) |
105 | lpc_sch_cells[i].id = id->device; | ||
106 | |||
107 | return mfd_add_devices(&dev->dev, 0, | ||
103 | lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); | 108 | lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); |
104 | } | 109 | } |
105 | 110 | ||
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c new file mode 100644 index 000000000000..5d1fca0277ef --- /dev/null +++ b/drivers/mfd/max8997.c | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * max8997.c - mfd core driver for the Maxim 8966 and 8997 | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@smasung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | * This driver is based on max8998.c | ||
22 | */ | ||
23 | |||
24 | #include <linux/slab.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/pm_runtime.h> | ||
27 | #include <linux/mutex.h> | ||
28 | #include <linux/mfd/core.h> | ||
29 | #include <linux/mfd/max8997.h> | ||
30 | #include <linux/mfd/max8997-private.h> | ||
31 | |||
32 | #define I2C_ADDR_PMIC (0xCC >> 1) | ||
33 | #define I2C_ADDR_MUIC (0x4A >> 1) | ||
34 | #define I2C_ADDR_BATTERY (0x6C >> 1) | ||
35 | #define I2C_ADDR_RTC (0x0C >> 1) | ||
36 | #define I2C_ADDR_HAPTIC (0x90 >> 1) | ||
37 | |||
38 | static struct mfd_cell max8997_devs[] = { | ||
39 | { .name = "max8997-pmic", }, | ||
40 | { .name = "max8997-rtc", }, | ||
41 | { .name = "max8997-battery", }, | ||
42 | { .name = "max8997-haptic", }, | ||
43 | { .name = "max8997-muic", }, | ||
44 | { .name = "max8997-flash", }, | ||
45 | }; | ||
46 | |||
47 | int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) | ||
48 | { | ||
49 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
50 | int ret; | ||
51 | |||
52 | mutex_lock(&max8997->iolock); | ||
53 | ret = i2c_smbus_read_byte_data(i2c, reg); | ||
54 | mutex_unlock(&max8997->iolock); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | |||
58 | ret &= 0xff; | ||
59 | *dest = ret; | ||
60 | return 0; | ||
61 | } | ||
62 | EXPORT_SYMBOL_GPL(max8997_read_reg); | ||
63 | |||
64 | int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf) | ||
65 | { | ||
66 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
67 | int ret; | ||
68 | |||
69 | mutex_lock(&max8997->iolock); | ||
70 | ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf); | ||
71 | mutex_unlock(&max8997->iolock); | ||
72 | if (ret < 0) | ||
73 | return ret; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | EXPORT_SYMBOL_GPL(max8997_bulk_read); | ||
78 | |||
79 | int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value) | ||
80 | { | ||
81 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
82 | int ret; | ||
83 | |||
84 | mutex_lock(&max8997->iolock); | ||
85 | ret = i2c_smbus_write_byte_data(i2c, reg, value); | ||
86 | mutex_unlock(&max8997->iolock); | ||
87 | return ret; | ||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(max8997_write_reg); | ||
90 | |||
91 | int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf) | ||
92 | { | ||
93 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
94 | int ret; | ||
95 | |||
96 | mutex_lock(&max8997->iolock); | ||
97 | ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf); | ||
98 | mutex_unlock(&max8997->iolock); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(max8997_bulk_write); | ||
105 | |||
106 | int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) | ||
107 | { | ||
108 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
109 | int ret; | ||
110 | |||
111 | mutex_lock(&max8997->iolock); | ||
112 | ret = i2c_smbus_read_byte_data(i2c, reg); | ||
113 | if (ret >= 0) { | ||
114 | u8 old_val = ret & 0xff; | ||
115 | u8 new_val = (val & mask) | (old_val & (~mask)); | ||
116 | ret = i2c_smbus_write_byte_data(i2c, reg, new_val); | ||
117 | } | ||
118 | mutex_unlock(&max8997->iolock); | ||
119 | return ret; | ||
120 | } | ||
121 | EXPORT_SYMBOL_GPL(max8997_update_reg); | ||
122 | |||
123 | static int max8997_i2c_probe(struct i2c_client *i2c, | ||
124 | const struct i2c_device_id *id) | ||
125 | { | ||
126 | struct max8997_dev *max8997; | ||
127 | struct max8997_platform_data *pdata = i2c->dev.platform_data; | ||
128 | int ret = 0; | ||
129 | |||
130 | max8997 = kzalloc(sizeof(struct max8997_dev), GFP_KERNEL); | ||
131 | if (max8997 == NULL) | ||
132 | return -ENOMEM; | ||
133 | |||
134 | i2c_set_clientdata(i2c, max8997); | ||
135 | max8997->dev = &i2c->dev; | ||
136 | max8997->i2c = i2c; | ||
137 | max8997->type = id->driver_data; | ||
138 | |||
139 | if (!pdata) | ||
140 | goto err; | ||
141 | |||
142 | max8997->wakeup = pdata->wakeup; | ||
143 | |||
144 | mutex_init(&max8997->iolock); | ||
145 | |||
146 | max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC); | ||
147 | i2c_set_clientdata(max8997->rtc, max8997); | ||
148 | max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); | ||
149 | i2c_set_clientdata(max8997->haptic, max8997); | ||
150 | max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC); | ||
151 | i2c_set_clientdata(max8997->muic, max8997); | ||
152 | |||
153 | pm_runtime_set_active(max8997->dev); | ||
154 | |||
155 | mfd_add_devices(max8997->dev, -1, max8997_devs, | ||
156 | ARRAY_SIZE(max8997_devs), | ||
157 | NULL, 0); | ||
158 | |||
159 | /* | ||
160 | * TODO: enable others (flash, muic, rtc, battery, ...) and | ||
161 | * check the return value | ||
162 | */ | ||
163 | |||
164 | if (ret < 0) | ||
165 | goto err_mfd; | ||
166 | |||
167 | return ret; | ||
168 | |||
169 | err_mfd: | ||
170 | mfd_remove_devices(max8997->dev); | ||
171 | i2c_unregister_device(max8997->muic); | ||
172 | i2c_unregister_device(max8997->haptic); | ||
173 | i2c_unregister_device(max8997->rtc); | ||
174 | err: | ||
175 | kfree(max8997); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static int max8997_i2c_remove(struct i2c_client *i2c) | ||
180 | { | ||
181 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
182 | |||
183 | mfd_remove_devices(max8997->dev); | ||
184 | i2c_unregister_device(max8997->muic); | ||
185 | i2c_unregister_device(max8997->haptic); | ||
186 | i2c_unregister_device(max8997->rtc); | ||
187 | kfree(max8997); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static const struct i2c_device_id max8997_i2c_id[] = { | ||
193 | { "max8997", TYPE_MAX8997 }, | ||
194 | { "max8966", TYPE_MAX8966 }, | ||
195 | { } | ||
196 | }; | ||
197 | MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); | ||
198 | |||
199 | u8 max8997_dumpaddr_pmic[] = { | ||
200 | MAX8997_REG_INT1MSK, | ||
201 | MAX8997_REG_INT2MSK, | ||
202 | MAX8997_REG_INT3MSK, | ||
203 | MAX8997_REG_INT4MSK, | ||
204 | MAX8997_REG_MAINCON1, | ||
205 | MAX8997_REG_MAINCON2, | ||
206 | MAX8997_REG_BUCKRAMP, | ||
207 | MAX8997_REG_BUCK1CTRL, | ||
208 | MAX8997_REG_BUCK1DVS1, | ||
209 | MAX8997_REG_BUCK1DVS2, | ||
210 | MAX8997_REG_BUCK1DVS3, | ||
211 | MAX8997_REG_BUCK1DVS4, | ||
212 | MAX8997_REG_BUCK1DVS5, | ||
213 | MAX8997_REG_BUCK1DVS6, | ||
214 | MAX8997_REG_BUCK1DVS7, | ||
215 | MAX8997_REG_BUCK1DVS8, | ||
216 | MAX8997_REG_BUCK2CTRL, | ||
217 | MAX8997_REG_BUCK2DVS1, | ||
218 | MAX8997_REG_BUCK2DVS2, | ||
219 | MAX8997_REG_BUCK2DVS3, | ||
220 | MAX8997_REG_BUCK2DVS4, | ||
221 | MAX8997_REG_BUCK2DVS5, | ||
222 | MAX8997_REG_BUCK2DVS6, | ||
223 | MAX8997_REG_BUCK2DVS7, | ||
224 | MAX8997_REG_BUCK2DVS8, | ||
225 | MAX8997_REG_BUCK3CTRL, | ||
226 | MAX8997_REG_BUCK3DVS, | ||
227 | MAX8997_REG_BUCK4CTRL, | ||
228 | MAX8997_REG_BUCK4DVS, | ||
229 | MAX8997_REG_BUCK5CTRL, | ||
230 | MAX8997_REG_BUCK5DVS1, | ||
231 | MAX8997_REG_BUCK5DVS2, | ||
232 | MAX8997_REG_BUCK5DVS3, | ||
233 | MAX8997_REG_BUCK5DVS4, | ||
234 | MAX8997_REG_BUCK5DVS5, | ||
235 | MAX8997_REG_BUCK5DVS6, | ||
236 | MAX8997_REG_BUCK5DVS7, | ||
237 | MAX8997_REG_BUCK5DVS8, | ||
238 | MAX8997_REG_BUCK6CTRL, | ||
239 | MAX8997_REG_BUCK6BPSKIPCTRL, | ||
240 | MAX8997_REG_BUCK7CTRL, | ||
241 | MAX8997_REG_BUCK7DVS, | ||
242 | MAX8997_REG_LDO1CTRL, | ||
243 | MAX8997_REG_LDO2CTRL, | ||
244 | MAX8997_REG_LDO3CTRL, | ||
245 | MAX8997_REG_LDO4CTRL, | ||
246 | MAX8997_REG_LDO5CTRL, | ||
247 | MAX8997_REG_LDO6CTRL, | ||
248 | MAX8997_REG_LDO7CTRL, | ||
249 | MAX8997_REG_LDO8CTRL, | ||
250 | MAX8997_REG_LDO9CTRL, | ||
251 | MAX8997_REG_LDO10CTRL, | ||
252 | MAX8997_REG_LDO11CTRL, | ||
253 | MAX8997_REG_LDO12CTRL, | ||
254 | MAX8997_REG_LDO13CTRL, | ||
255 | MAX8997_REG_LDO14CTRL, | ||
256 | MAX8997_REG_LDO15CTRL, | ||
257 | MAX8997_REG_LDO16CTRL, | ||
258 | MAX8997_REG_LDO17CTRL, | ||
259 | MAX8997_REG_LDO18CTRL, | ||
260 | MAX8997_REG_LDO21CTRL, | ||
261 | MAX8997_REG_MBCCTRL1, | ||
262 | MAX8997_REG_MBCCTRL2, | ||
263 | MAX8997_REG_MBCCTRL3, | ||
264 | MAX8997_REG_MBCCTRL4, | ||
265 | MAX8997_REG_MBCCTRL5, | ||
266 | MAX8997_REG_MBCCTRL6, | ||
267 | MAX8997_REG_OTPCGHCVS, | ||
268 | MAX8997_REG_SAFEOUTCTRL, | ||
269 | MAX8997_REG_LBCNFG1, | ||
270 | MAX8997_REG_LBCNFG2, | ||
271 | MAX8997_REG_BBCCTRL, | ||
272 | |||
273 | MAX8997_REG_FLASH1_CUR, | ||
274 | MAX8997_REG_FLASH2_CUR, | ||
275 | MAX8997_REG_MOVIE_CUR, | ||
276 | MAX8997_REG_GSMB_CUR, | ||
277 | MAX8997_REG_BOOST_CNTL, | ||
278 | MAX8997_REG_LEN_CNTL, | ||
279 | MAX8997_REG_FLASH_CNTL, | ||
280 | MAX8997_REG_WDT_CNTL, | ||
281 | MAX8997_REG_MAXFLASH1, | ||
282 | MAX8997_REG_MAXFLASH2, | ||
283 | MAX8997_REG_FLASHSTATUSMASK, | ||
284 | |||
285 | MAX8997_REG_GPIOCNTL1, | ||
286 | MAX8997_REG_GPIOCNTL2, | ||
287 | MAX8997_REG_GPIOCNTL3, | ||
288 | MAX8997_REG_GPIOCNTL4, | ||
289 | MAX8997_REG_GPIOCNTL5, | ||
290 | MAX8997_REG_GPIOCNTL6, | ||
291 | MAX8997_REG_GPIOCNTL7, | ||
292 | MAX8997_REG_GPIOCNTL8, | ||
293 | MAX8997_REG_GPIOCNTL9, | ||
294 | MAX8997_REG_GPIOCNTL10, | ||
295 | MAX8997_REG_GPIOCNTL11, | ||
296 | MAX8997_REG_GPIOCNTL12, | ||
297 | |||
298 | MAX8997_REG_LDO1CONFIG, | ||
299 | MAX8997_REG_LDO2CONFIG, | ||
300 | MAX8997_REG_LDO3CONFIG, | ||
301 | MAX8997_REG_LDO4CONFIG, | ||
302 | MAX8997_REG_LDO5CONFIG, | ||
303 | MAX8997_REG_LDO6CONFIG, | ||
304 | MAX8997_REG_LDO7CONFIG, | ||
305 | MAX8997_REG_LDO8CONFIG, | ||
306 | MAX8997_REG_LDO9CONFIG, | ||
307 | MAX8997_REG_LDO10CONFIG, | ||
308 | MAX8997_REG_LDO11CONFIG, | ||
309 | MAX8997_REG_LDO12CONFIG, | ||
310 | MAX8997_REG_LDO13CONFIG, | ||
311 | MAX8997_REG_LDO14CONFIG, | ||
312 | MAX8997_REG_LDO15CONFIG, | ||
313 | MAX8997_REG_LDO16CONFIG, | ||
314 | MAX8997_REG_LDO17CONFIG, | ||
315 | MAX8997_REG_LDO18CONFIG, | ||
316 | MAX8997_REG_LDO21CONFIG, | ||
317 | |||
318 | MAX8997_REG_DVSOKTIMER1, | ||
319 | MAX8997_REG_DVSOKTIMER2, | ||
320 | MAX8997_REG_DVSOKTIMER4, | ||
321 | MAX8997_REG_DVSOKTIMER5, | ||
322 | }; | ||
323 | |||
324 | u8 max8997_dumpaddr_muic[] = { | ||
325 | MAX8997_MUIC_REG_INTMASK1, | ||
326 | MAX8997_MUIC_REG_INTMASK2, | ||
327 | MAX8997_MUIC_REG_INTMASK3, | ||
328 | MAX8997_MUIC_REG_CDETCTRL, | ||
329 | MAX8997_MUIC_REG_CONTROL1, | ||
330 | MAX8997_MUIC_REG_CONTROL2, | ||
331 | MAX8997_MUIC_REG_CONTROL3, | ||
332 | }; | ||
333 | |||
334 | u8 max8997_dumpaddr_haptic[] = { | ||
335 | MAX8997_HAPTIC_REG_CONF1, | ||
336 | MAX8997_HAPTIC_REG_CONF2, | ||
337 | MAX8997_HAPTIC_REG_DRVCONF, | ||
338 | MAX8997_HAPTIC_REG_CYCLECONF1, | ||
339 | MAX8997_HAPTIC_REG_CYCLECONF2, | ||
340 | MAX8997_HAPTIC_REG_SIGCONF1, | ||
341 | MAX8997_HAPTIC_REG_SIGCONF2, | ||
342 | MAX8997_HAPTIC_REG_SIGCONF3, | ||
343 | MAX8997_HAPTIC_REG_SIGCONF4, | ||
344 | MAX8997_HAPTIC_REG_SIGDC1, | ||
345 | MAX8997_HAPTIC_REG_SIGDC2, | ||
346 | MAX8997_HAPTIC_REG_SIGPWMDC1, | ||
347 | MAX8997_HAPTIC_REG_SIGPWMDC2, | ||
348 | MAX8997_HAPTIC_REG_SIGPWMDC3, | ||
349 | MAX8997_HAPTIC_REG_SIGPWMDC4, | ||
350 | }; | ||
351 | |||
352 | static int max8997_freeze(struct device *dev) | ||
353 | { | ||
354 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | ||
355 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
356 | int i; | ||
357 | |||
358 | for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) | ||
359 | max8997_read_reg(i2c, max8997_dumpaddr_pmic[i], | ||
360 | &max8997->reg_dump[i]); | ||
361 | |||
362 | for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) | ||
363 | max8997_read_reg(i2c, max8997_dumpaddr_muic[i], | ||
364 | &max8997->reg_dump[i + MAX8997_REG_PMIC_END]); | ||
365 | |||
366 | for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) | ||
367 | max8997_read_reg(i2c, max8997_dumpaddr_haptic[i], | ||
368 | &max8997->reg_dump[i + MAX8997_REG_PMIC_END + | ||
369 | MAX8997_MUIC_REG_END]); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int max8997_restore(struct device *dev) | ||
375 | { | ||
376 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | ||
377 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
378 | int i; | ||
379 | |||
380 | for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) | ||
381 | max8997_write_reg(i2c, max8997_dumpaddr_pmic[i], | ||
382 | max8997->reg_dump[i]); | ||
383 | |||
384 | for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) | ||
385 | max8997_write_reg(i2c, max8997_dumpaddr_muic[i], | ||
386 | max8997->reg_dump[i + MAX8997_REG_PMIC_END]); | ||
387 | |||
388 | for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) | ||
389 | max8997_write_reg(i2c, max8997_dumpaddr_haptic[i], | ||
390 | max8997->reg_dump[i + MAX8997_REG_PMIC_END + | ||
391 | MAX8997_MUIC_REG_END]); | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | const struct dev_pm_ops max8997_pm = { | ||
397 | .freeze = max8997_freeze, | ||
398 | .restore = max8997_restore, | ||
399 | }; | ||
400 | |||
401 | static struct i2c_driver max8997_i2c_driver = { | ||
402 | .driver = { | ||
403 | .name = "max8997", | ||
404 | .owner = THIS_MODULE, | ||
405 | .pm = &max8997_pm, | ||
406 | }, | ||
407 | .probe = max8997_i2c_probe, | ||
408 | .remove = max8997_i2c_remove, | ||
409 | .id_table = max8997_i2c_id, | ||
410 | }; | ||
411 | |||
412 | static int __init max8997_i2c_init(void) | ||
413 | { | ||
414 | return i2c_add_driver(&max8997_i2c_driver); | ||
415 | } | ||
416 | /* init early so consumer devices can complete system boot */ | ||
417 | subsys_initcall(max8997_i2c_init); | ||
418 | |||
419 | static void __exit max8997_i2c_exit(void) | ||
420 | { | ||
421 | i2c_del_driver(&max8997_i2c_driver); | ||
422 | } | ||
423 | module_exit(max8997_i2c_exit); | ||
424 | |||
425 | MODULE_DESCRIPTION("MAXIM 8997 multi-function core driver"); | ||
426 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
427 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index bbfe86732602..c00214257da2 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c | |||
@@ -233,7 +233,7 @@ struct max8998_reg_dump { | |||
233 | u8 val; | 233 | u8 val; |
234 | }; | 234 | }; |
235 | #define SAVE_ITEM(x) { .addr = (x), .val = 0x0, } | 235 | #define SAVE_ITEM(x) { .addr = (x), .val = 0x0, } |
236 | struct max8998_reg_dump max8998_dump[] = { | 236 | static struct max8998_reg_dump max8998_dump[] = { |
237 | SAVE_ITEM(MAX8998_REG_IRQM1), | 237 | SAVE_ITEM(MAX8998_REG_IRQM1), |
238 | SAVE_ITEM(MAX8998_REG_IRQM2), | 238 | SAVE_ITEM(MAX8998_REG_IRQM2), |
239 | SAVE_ITEM(MAX8998_REG_IRQM3), | 239 | SAVE_ITEM(MAX8998_REG_IRQM3), |
@@ -298,7 +298,7 @@ static int max8998_restore(struct device *dev) | |||
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
301 | const struct dev_pm_ops max8998_pm = { | 301 | static const struct dev_pm_ops max8998_pm = { |
302 | .suspend = max8998_suspend, | 302 | .suspend = max8998_suspend, |
303 | .resume = max8998_resume, | 303 | .resume = max8998_resume, |
304 | .freeze = max8998_freeze, | 304 | .freeze = max8998_freeze, |
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index b9fcaf0004da..668634e89e81 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c | |||
@@ -683,14 +683,13 @@ out: | |||
683 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); | 683 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); |
684 | 684 | ||
685 | static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, | 685 | static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, |
686 | const char *format, void *pdata, size_t pdata_size) | 686 | const char *format, void *pdata) |
687 | { | 687 | { |
688 | char buf[30]; | 688 | char buf[30]; |
689 | const char *name = mc13xxx_get_chipname(mc13xxx); | 689 | const char *name = mc13xxx_get_chipname(mc13xxx); |
690 | 690 | ||
691 | struct mfd_cell cell = { | 691 | struct mfd_cell cell = { |
692 | .platform_data = pdata, | 692 | .mfd_data = pdata, |
693 | .data_size = pdata_size, | ||
694 | }; | 693 | }; |
695 | 694 | ||
696 | /* there is no asnprintf in the kernel :-( */ | 695 | /* there is no asnprintf in the kernel :-( */ |
@@ -706,7 +705,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, | |||
706 | 705 | ||
707 | static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) | 706 | static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) |
708 | { | 707 | { |
709 | return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0); | 708 | return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL); |
710 | } | 709 | } |
711 | 710 | ||
712 | static int mc13xxx_probe(struct spi_device *spi) | 711 | static int mc13xxx_probe(struct spi_device *spi) |
@@ -764,13 +763,8 @@ err_revision: | |||
764 | mc13xxx_add_subdevice(mc13xxx, "%s-codec"); | 763 | mc13xxx_add_subdevice(mc13xxx, "%s-codec"); |
765 | 764 | ||
766 | if (pdata->flags & MC13XXX_USE_REGULATOR) { | 765 | if (pdata->flags & MC13XXX_USE_REGULATOR) { |
767 | struct mc13xxx_regulator_platform_data regulator_pdata = { | ||
768 | .num_regulators = pdata->num_regulators, | ||
769 | .regulators = pdata->regulators, | ||
770 | }; | ||
771 | |||
772 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", | 766 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", |
773 | ®ulator_pdata, sizeof(regulator_pdata)); | 767 | &pdata->regulators); |
774 | } | 768 | } |
775 | 769 | ||
776 | if (pdata->flags & MC13XXX_USE_RTC) | 770 | if (pdata->flags & MC13XXX_USE_RTC) |
@@ -779,10 +773,8 @@ err_revision: | |||
779 | if (pdata->flags & MC13XXX_USE_TOUCHSCREEN) | 773 | if (pdata->flags & MC13XXX_USE_TOUCHSCREEN) |
780 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); | 774 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); |
781 | 775 | ||
782 | if (pdata->flags & MC13XXX_USE_LED) { | 776 | if (pdata->flags & MC13XXX_USE_LED) |
783 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", | 777 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds); |
784 | pdata->leds, sizeof(*pdata->leds)); | ||
785 | } | ||
786 | 778 | ||
787 | return 0; | 779 | return 0; |
788 | } | 780 | } |
@@ -811,6 +803,7 @@ static const struct spi_device_id mc13xxx_device_id[] = { | |||
811 | /* sentinel */ | 803 | /* sentinel */ |
812 | } | 804 | } |
813 | }; | 805 | }; |
806 | MODULE_DEVICE_TABLE(spi, mc13xxx_device_id); | ||
814 | 807 | ||
815 | static struct spi_driver mc13xxx_driver = { | 808 | static struct spi_driver mc13xxx_driver = { |
816 | .id_table = mc13xxx_device_id, | 809 | .id_table = mc13xxx_device_id, |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index d83ad0f141af..79eda0264fb2 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -18,6 +18,43 @@ | |||
18 | #include <linux/pm_runtime.h> | 18 | #include <linux/pm_runtime.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | 20 | ||
21 | int mfd_cell_enable(struct platform_device *pdev) | ||
22 | { | ||
23 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
24 | int err = 0; | ||
25 | |||
26 | /* only call enable hook if the cell wasn't previously enabled */ | ||
27 | if (atomic_inc_return(cell->usage_count) == 1) | ||
28 | err = cell->enable(pdev); | ||
29 | |||
30 | /* if the enable hook failed, decrement counter to allow retries */ | ||
31 | if (err) | ||
32 | atomic_dec(cell->usage_count); | ||
33 | |||
34 | return err; | ||
35 | } | ||
36 | EXPORT_SYMBOL(mfd_cell_enable); | ||
37 | |||
38 | int mfd_cell_disable(struct platform_device *pdev) | ||
39 | { | ||
40 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
41 | int err = 0; | ||
42 | |||
43 | /* only disable if no other clients are using it */ | ||
44 | if (atomic_dec_return(cell->usage_count) == 0) | ||
45 | err = cell->disable(pdev); | ||
46 | |||
47 | /* if the disable hook failed, increment to allow retries */ | ||
48 | if (err) | ||
49 | atomic_inc(cell->usage_count); | ||
50 | |||
51 | /* sanity check; did someone call disable too many times? */ | ||
52 | WARN_ON(atomic_read(cell->usage_count) < 0); | ||
53 | |||
54 | return err; | ||
55 | } | ||
56 | EXPORT_SYMBOL(mfd_cell_disable); | ||
57 | |||
21 | static int mfd_add_device(struct device *parent, int id, | 58 | static int mfd_add_device(struct device *parent, int id, |
22 | const struct mfd_cell *cell, | 59 | const struct mfd_cell *cell, |
23 | struct resource *mem_base, | 60 | struct resource *mem_base, |
@@ -37,14 +74,10 @@ static int mfd_add_device(struct device *parent, int id, | |||
37 | goto fail_device; | 74 | goto fail_device; |
38 | 75 | ||
39 | pdev->dev.parent = parent; | 76 | pdev->dev.parent = parent; |
40 | platform_set_drvdata(pdev, cell->driver_data); | ||
41 | 77 | ||
42 | if (cell->data_size) { | 78 | ret = platform_device_add_data(pdev, cell, sizeof(*cell)); |
43 | ret = platform_device_add_data(pdev, | 79 | if (ret) |
44 | cell->platform_data, cell->data_size); | 80 | goto fail_res; |
45 | if (ret) | ||
46 | goto fail_res; | ||
47 | } | ||
48 | 81 | ||
49 | for (r = 0; r < cell->num_resources; r++) { | 82 | for (r = 0; r < cell->num_resources; r++) { |
50 | res[r].name = cell->resources[r].name; | 83 | res[r].name = cell->resources[r].name; |
@@ -100,14 +133,22 @@ fail_alloc: | |||
100 | } | 133 | } |
101 | 134 | ||
102 | int mfd_add_devices(struct device *parent, int id, | 135 | int mfd_add_devices(struct device *parent, int id, |
103 | const struct mfd_cell *cells, int n_devs, | 136 | struct mfd_cell *cells, int n_devs, |
104 | struct resource *mem_base, | 137 | struct resource *mem_base, |
105 | int irq_base) | 138 | int irq_base) |
106 | { | 139 | { |
107 | int i; | 140 | int i; |
108 | int ret = 0; | 141 | int ret = 0; |
142 | atomic_t *cnts; | ||
143 | |||
144 | /* initialize reference counting for all cells */ | ||
145 | cnts = kcalloc(sizeof(*cnts), n_devs, GFP_KERNEL); | ||
146 | if (!cnts) | ||
147 | return -ENOMEM; | ||
109 | 148 | ||
110 | for (i = 0; i < n_devs; i++) { | 149 | for (i = 0; i < n_devs; i++) { |
150 | atomic_set(&cnts[i], 0); | ||
151 | cells[i].usage_count = &cnts[i]; | ||
111 | ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); | 152 | ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); |
112 | if (ret) | 153 | if (ret) |
113 | break; | 154 | break; |
@@ -120,17 +161,89 @@ int mfd_add_devices(struct device *parent, int id, | |||
120 | } | 161 | } |
121 | EXPORT_SYMBOL(mfd_add_devices); | 162 | EXPORT_SYMBOL(mfd_add_devices); |
122 | 163 | ||
123 | static int mfd_remove_devices_fn(struct device *dev, void *unused) | 164 | static int mfd_remove_devices_fn(struct device *dev, void *c) |
124 | { | 165 | { |
125 | platform_device_unregister(to_platform_device(dev)); | 166 | struct platform_device *pdev = to_platform_device(dev); |
167 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
168 | atomic_t **usage_count = c; | ||
169 | |||
170 | /* find the base address of usage_count pointers (for freeing) */ | ||
171 | if (!*usage_count || (cell->usage_count < *usage_count)) | ||
172 | *usage_count = cell->usage_count; | ||
173 | |||
174 | platform_device_unregister(pdev); | ||
126 | return 0; | 175 | return 0; |
127 | } | 176 | } |
128 | 177 | ||
129 | void mfd_remove_devices(struct device *parent) | 178 | void mfd_remove_devices(struct device *parent) |
130 | { | 179 | { |
131 | device_for_each_child(parent, NULL, mfd_remove_devices_fn); | 180 | atomic_t *cnts = NULL; |
181 | |||
182 | device_for_each_child(parent, &cnts, mfd_remove_devices_fn); | ||
183 | kfree(cnts); | ||
132 | } | 184 | } |
133 | EXPORT_SYMBOL(mfd_remove_devices); | 185 | EXPORT_SYMBOL(mfd_remove_devices); |
134 | 186 | ||
187 | static int add_shared_platform_device(const char *cell, const char *name) | ||
188 | { | ||
189 | struct mfd_cell cell_entry; | ||
190 | struct device *dev; | ||
191 | struct platform_device *pdev; | ||
192 | int err; | ||
193 | |||
194 | /* check if we've already registered a device (don't fail if we have) */ | ||
195 | if (bus_find_device_by_name(&platform_bus_type, NULL, name)) | ||
196 | return 0; | ||
197 | |||
198 | /* fetch the parent cell's device (should already be registered!) */ | ||
199 | dev = bus_find_device_by_name(&platform_bus_type, NULL, cell); | ||
200 | if (!dev) { | ||
201 | printk(KERN_ERR "failed to find device for cell %s\n", cell); | ||
202 | return -ENODEV; | ||
203 | } | ||
204 | pdev = to_platform_device(dev); | ||
205 | memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry)); | ||
206 | |||
207 | WARN_ON(!cell_entry.enable); | ||
208 | |||
209 | cell_entry.name = name; | ||
210 | err = mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0); | ||
211 | if (err) | ||
212 | dev_err(dev, "MFD add devices failed: %d\n", err); | ||
213 | return err; | ||
214 | } | ||
215 | |||
216 | int mfd_shared_platform_driver_register(struct platform_driver *drv, | ||
217 | const char *cellname) | ||
218 | { | ||
219 | int err; | ||
220 | |||
221 | err = add_shared_platform_device(cellname, drv->driver.name); | ||
222 | if (err) | ||
223 | printk(KERN_ERR "failed to add platform device %s\n", | ||
224 | drv->driver.name); | ||
225 | |||
226 | err = platform_driver_register(drv); | ||
227 | if (err) | ||
228 | printk(KERN_ERR "failed to add platform driver %s\n", | ||
229 | drv->driver.name); | ||
230 | |||
231 | return err; | ||
232 | } | ||
233 | EXPORT_SYMBOL(mfd_shared_platform_driver_register); | ||
234 | |||
235 | void mfd_shared_platform_driver_unregister(struct platform_driver *drv) | ||
236 | { | ||
237 | struct device *dev; | ||
238 | |||
239 | dev = bus_find_device_by_name(&platform_bus_type, NULL, | ||
240 | drv->driver.name); | ||
241 | if (dev) | ||
242 | platform_device_unregister(to_platform_device(dev)); | ||
243 | |||
244 | platform_driver_unregister(drv); | ||
245 | } | ||
246 | EXPORT_SYMBOL(mfd_shared_platform_driver_unregister); | ||
247 | |||
135 | MODULE_LICENSE("GPL"); | 248 | MODULE_LICENSE("GPL"); |
136 | MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); | 249 | MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); |
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 501ce13b693e..c1306ed43e3c 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include <linux/pm.h> | ||
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | 26 | ||
26 | #include <linux/mfd/pcf50633/core.h> | 27 | #include <linux/mfd/pcf50633/core.h> |
@@ -230,27 +231,26 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, | |||
230 | } | 231 | } |
231 | } | 232 | } |
232 | 233 | ||
233 | #ifdef CONFIG_PM | 234 | #ifdef CONFIG_PM_SLEEP |
234 | static int pcf50633_suspend(struct i2c_client *client, pm_message_t state) | 235 | static int pcf50633_suspend(struct device *dev) |
235 | { | 236 | { |
236 | struct pcf50633 *pcf; | 237 | struct i2c_client *client = to_i2c_client(dev); |
237 | pcf = i2c_get_clientdata(client); | 238 | struct pcf50633 *pcf = i2c_get_clientdata(client); |
238 | 239 | ||
239 | return pcf50633_irq_suspend(pcf); | 240 | return pcf50633_irq_suspend(pcf); |
240 | } | 241 | } |
241 | 242 | ||
242 | static int pcf50633_resume(struct i2c_client *client) | 243 | static int pcf50633_resume(struct device *dev) |
243 | { | 244 | { |
244 | struct pcf50633 *pcf; | 245 | struct i2c_client *client = to_i2c_client(dev); |
245 | pcf = i2c_get_clientdata(client); | 246 | struct pcf50633 *pcf = i2c_get_clientdata(client); |
246 | 247 | ||
247 | return pcf50633_irq_resume(pcf); | 248 | return pcf50633_irq_resume(pcf); |
248 | } | 249 | } |
249 | #else | ||
250 | #define pcf50633_suspend NULL | ||
251 | #define pcf50633_resume NULL | ||
252 | #endif | 250 | #endif |
253 | 251 | ||
252 | static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume); | ||
253 | |||
254 | static int __devinit pcf50633_probe(struct i2c_client *client, | 254 | static int __devinit pcf50633_probe(struct i2c_client *client, |
255 | const struct i2c_device_id *ids) | 255 | const struct i2c_device_id *ids) |
256 | { | 256 | { |
@@ -360,16 +360,16 @@ static struct i2c_device_id pcf50633_id_table[] = { | |||
360 | {"pcf50633", 0x73}, | 360 | {"pcf50633", 0x73}, |
361 | {/* end of list */} | 361 | {/* end of list */} |
362 | }; | 362 | }; |
363 | MODULE_DEVICE_TABLE(i2c, pcf50633_id_table); | ||
363 | 364 | ||
364 | static struct i2c_driver pcf50633_driver = { | 365 | static struct i2c_driver pcf50633_driver = { |
365 | .driver = { | 366 | .driver = { |
366 | .name = "pcf50633", | 367 | .name = "pcf50633", |
368 | .pm = &pcf50633_pm, | ||
367 | }, | 369 | }, |
368 | .id_table = pcf50633_id_table, | 370 | .id_table = pcf50633_id_table, |
369 | .probe = pcf50633_probe, | 371 | .probe = pcf50633_probe, |
370 | .remove = __devexit_p(pcf50633_remove), | 372 | .remove = __devexit_p(pcf50633_remove), |
371 | .suspend = pcf50633_suspend, | ||
372 | .resume = pcf50633_resume, | ||
373 | }; | 373 | }; |
374 | 374 | ||
375 | static int __init pcf50633_init(void) | 375 | static int __init pcf50633_init(void) |
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 50922975bda3..193c940225b5 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c | |||
@@ -61,12 +61,12 @@ static struct mfd_cell rdc321x_sb_cells[] = { | |||
61 | .name = "rdc321x-wdt", | 61 | .name = "rdc321x-wdt", |
62 | .resources = rdc321x_wdt_resource, | 62 | .resources = rdc321x_wdt_resource, |
63 | .num_resources = ARRAY_SIZE(rdc321x_wdt_resource), | 63 | .num_resources = ARRAY_SIZE(rdc321x_wdt_resource), |
64 | .driver_data = &rdc321x_wdt_pdata, | 64 | .mfd_data = &rdc321x_wdt_pdata, |
65 | }, { | 65 | }, { |
66 | .name = "rdc321x-gpio", | 66 | .name = "rdc321x-gpio", |
67 | .resources = rdc321x_gpio_resources, | 67 | .resources = rdc321x_gpio_resources, |
68 | .num_resources = ARRAY_SIZE(rdc321x_gpio_resources), | 68 | .num_resources = ARRAY_SIZE(rdc321x_gpio_resources), |
69 | .driver_data = &rdc321x_gpio_pdata, | 69 | .mfd_data = &rdc321x_gpio_pdata, |
70 | }, | 70 | }, |
71 | }; | 71 | }; |
72 | 72 | ||
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c index 0a7df44a93c0..53a63024bf11 100644 --- a/drivers/mfd/sh_mobile_sdhi.c +++ b/drivers/mfd/sh_mobile_sdhi.c | |||
@@ -146,9 +146,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
146 | } | 146 | } |
147 | 147 | ||
148 | memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc)); | 148 | memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc)); |
149 | priv->cell_mmc.driver_data = mmc_data; | 149 | priv->cell_mmc.mfd_data = mmc_data; |
150 | priv->cell_mmc.platform_data = &priv->cell_mmc; | ||
151 | priv->cell_mmc.data_size = sizeof(priv->cell_mmc); | ||
152 | 150 | ||
153 | platform_set_drvdata(pdev, priv); | 151 | platform_set_drvdata(pdev, priv); |
154 | 152 | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 9caeb4ac6ea6..af57fc706a4c 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -170,7 +170,7 @@ static struct mfd_cell t7l66xb_cells[] = { | |||
170 | .name = "tmio-mmc", | 170 | .name = "tmio-mmc", |
171 | .enable = t7l66xb_mmc_enable, | 171 | .enable = t7l66xb_mmc_enable, |
172 | .disable = t7l66xb_mmc_disable, | 172 | .disable = t7l66xb_mmc_disable, |
173 | .driver_data = &t7166xb_mmc_data, | 173 | .mfd_data = &t7166xb_mmc_data, |
174 | .num_resources = ARRAY_SIZE(t7l66xb_mmc_resources), | 174 | .num_resources = ARRAY_SIZE(t7l66xb_mmc_resources), |
175 | .resources = t7l66xb_mmc_resources, | 175 | .resources = t7l66xb_mmc_resources, |
176 | }, | 176 | }, |
@@ -383,16 +383,7 @@ static int t7l66xb_probe(struct platform_device *dev) | |||
383 | 383 | ||
384 | t7l66xb_attach_irq(dev); | 384 | t7l66xb_attach_irq(dev); |
385 | 385 | ||
386 | t7l66xb_cells[T7L66XB_CELL_NAND].driver_data = pdata->nand_data; | 386 | t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data; |
387 | t7l66xb_cells[T7L66XB_CELL_NAND].platform_data = | ||
388 | &t7l66xb_cells[T7L66XB_CELL_NAND]; | ||
389 | t7l66xb_cells[T7L66XB_CELL_NAND].data_size = | ||
390 | sizeof(t7l66xb_cells[T7L66XB_CELL_NAND]); | ||
391 | |||
392 | t7l66xb_cells[T7L66XB_CELL_MMC].platform_data = | ||
393 | &t7l66xb_cells[T7L66XB_CELL_MMC]; | ||
394 | t7l66xb_cells[T7L66XB_CELL_MMC].data_size = | ||
395 | sizeof(t7l66xb_cells[T7L66XB_CELL_MMC]); | ||
396 | 387 | ||
397 | ret = mfd_add_devices(&dev->dev, dev->id, | 388 | ret = mfd_add_devices(&dev->dev, dev->id, |
398 | t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), | 389 | t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), |
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 6315f63f017d..b006f7cee952 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
@@ -131,7 +131,7 @@ static struct mfd_cell tc6387xb_cells[] = { | |||
131 | .name = "tmio-mmc", | 131 | .name = "tmio-mmc", |
132 | .enable = tc6387xb_mmc_enable, | 132 | .enable = tc6387xb_mmc_enable, |
133 | .disable = tc6387xb_mmc_disable, | 133 | .disable = tc6387xb_mmc_disable, |
134 | .driver_data = &tc6387xb_mmc_data, | 134 | .mfd_data = &tc6387xb_mmc_data, |
135 | .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources), | 135 | .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources), |
136 | .resources = tc6387xb_mmc_resources, | 136 | .resources = tc6387xb_mmc_resources, |
137 | }, | 137 | }, |
@@ -190,11 +190,6 @@ static int __devinit tc6387xb_probe(struct platform_device *dev) | |||
190 | 190 | ||
191 | printk(KERN_INFO "Toshiba tc6387xb initialised\n"); | 191 | printk(KERN_INFO "Toshiba tc6387xb initialised\n"); |
192 | 192 | ||
193 | tc6387xb_cells[TC6387XB_CELL_MMC].platform_data = | ||
194 | &tc6387xb_cells[TC6387XB_CELL_MMC]; | ||
195 | tc6387xb_cells[TC6387XB_CELL_MMC].data_size = | ||
196 | sizeof(tc6387xb_cells[TC6387XB_CELL_MMC]); | ||
197 | |||
198 | ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, | 193 | ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, |
199 | ARRAY_SIZE(tc6387xb_cells), iomem, irq); | 194 | ARRAY_SIZE(tc6387xb_cells), iomem, irq); |
200 | 195 | ||
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 9a238633a54d..3d62ded86a8f 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -393,7 +393,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { | |||
393 | .name = "tmio-mmc", | 393 | .name = "tmio-mmc", |
394 | .enable = tc6393xb_mmc_enable, | 394 | .enable = tc6393xb_mmc_enable, |
395 | .resume = tc6393xb_mmc_resume, | 395 | .resume = tc6393xb_mmc_resume, |
396 | .driver_data = &tc6393xb_mmc_data, | 396 | .mfd_data = &tc6393xb_mmc_data, |
397 | .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), | 397 | .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), |
398 | .resources = tc6393xb_mmc_resources, | 398 | .resources = tc6393xb_mmc_resources, |
399 | }, | 399 | }, |
@@ -693,27 +693,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) | |||
693 | goto err_setup; | 693 | goto err_setup; |
694 | } | 694 | } |
695 | 695 | ||
696 | tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data; | 696 | tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data; |
697 | tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = | 697 | tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data; |
698 | &tc6393xb_cells[TC6393XB_CELL_NAND]; | ||
699 | tc6393xb_cells[TC6393XB_CELL_NAND].data_size = | ||
700 | sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]); | ||
701 | |||
702 | tc6393xb_cells[TC6393XB_CELL_MMC].platform_data = | ||
703 | &tc6393xb_cells[TC6393XB_CELL_MMC]; | ||
704 | tc6393xb_cells[TC6393XB_CELL_MMC].data_size = | ||
705 | sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]); | ||
706 | |||
707 | tc6393xb_cells[TC6393XB_CELL_OHCI].platform_data = | ||
708 | &tc6393xb_cells[TC6393XB_CELL_OHCI]; | ||
709 | tc6393xb_cells[TC6393XB_CELL_OHCI].data_size = | ||
710 | sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]); | ||
711 | |||
712 | tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data; | ||
713 | tc6393xb_cells[TC6393XB_CELL_FB].platform_data = | ||
714 | &tc6393xb_cells[TC6393XB_CELL_FB]; | ||
715 | tc6393xb_cells[TC6393XB_CELL_FB].data_size = | ||
716 | sizeof(tc6393xb_cells[TC6393XB_CELL_FB]); | ||
717 | 698 | ||
718 | ret = mfd_add_devices(&dev->dev, dev->id, | 699 | ret = mfd_add_devices(&dev->dev, dev->id, |
719 | tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), | 700 | tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), |
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index 6ad8a7f8d390..94c6c8afad12 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c | |||
@@ -384,8 +384,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { | |||
384 | .name = "timb-dma", | 384 | .name = "timb-dma", |
385 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 385 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
386 | .resources = timberdale_dma_resources, | 386 | .resources = timberdale_dma_resources, |
387 | .platform_data = &timb_dma_platform_data, | 387 | .mfd_data = &timb_dma_platform_data, |
388 | .data_size = sizeof(timb_dma_platform_data), | ||
389 | }, | 388 | }, |
390 | { | 389 | { |
391 | .name = "timb-uart", | 390 | .name = "timb-uart", |
@@ -396,43 +395,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { | |||
396 | .name = "xiic-i2c", | 395 | .name = "xiic-i2c", |
397 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | 396 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), |
398 | .resources = timberdale_xiic_resources, | 397 | .resources = timberdale_xiic_resources, |
399 | .platform_data = &timberdale_xiic_platform_data, | 398 | .mfd_data = &timberdale_xiic_platform_data, |
400 | .data_size = sizeof(timberdale_xiic_platform_data), | ||
401 | }, | 399 | }, |
402 | { | 400 | { |
403 | .name = "timb-gpio", | 401 | .name = "timb-gpio", |
404 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 402 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
405 | .resources = timberdale_gpio_resources, | 403 | .resources = timberdale_gpio_resources, |
406 | .platform_data = &timberdale_gpio_platform_data, | 404 | .mfd_data = &timberdale_gpio_platform_data, |
407 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
408 | }, | 405 | }, |
409 | { | 406 | { |
410 | .name = "timb-video", | 407 | .name = "timb-video", |
411 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 408 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
412 | .resources = timberdale_video_resources, | 409 | .resources = timberdale_video_resources, |
413 | .platform_data = &timberdale_video_platform_data, | 410 | .mfd_data = &timberdale_video_platform_data, |
414 | .data_size = sizeof(timberdale_video_platform_data), | ||
415 | }, | 411 | }, |
416 | { | 412 | { |
417 | .name = "timb-radio", | 413 | .name = "timb-radio", |
418 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 414 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
419 | .resources = timberdale_radio_resources, | 415 | .resources = timberdale_radio_resources, |
420 | .platform_data = &timberdale_radio_platform_data, | 416 | .mfd_data = &timberdale_radio_platform_data, |
421 | .data_size = sizeof(timberdale_radio_platform_data), | ||
422 | }, | 417 | }, |
423 | { | 418 | { |
424 | .name = "xilinx_spi", | 419 | .name = "xilinx_spi", |
425 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 420 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
426 | .resources = timberdale_spi_resources, | 421 | .resources = timberdale_spi_resources, |
427 | .platform_data = &timberdale_xspi_platform_data, | 422 | .mfd_data = &timberdale_xspi_platform_data, |
428 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
429 | }, | 423 | }, |
430 | { | 424 | { |
431 | .name = "ks8842", | 425 | .name = "ks8842", |
432 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 426 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
433 | .resources = timberdale_eth_resources, | 427 | .resources = timberdale_eth_resources, |
434 | .platform_data = &timberdale_ks8842_platform_data, | 428 | .mfd_data = &timberdale_ks8842_platform_data, |
435 | .data_size = sizeof(timberdale_ks8842_platform_data) | ||
436 | }, | 429 | }, |
437 | }; | 430 | }; |
438 | 431 | ||
@@ -441,8 +434,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
441 | .name = "timb-dma", | 434 | .name = "timb-dma", |
442 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 435 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
443 | .resources = timberdale_dma_resources, | 436 | .resources = timberdale_dma_resources, |
444 | .platform_data = &timb_dma_platform_data, | 437 | .mfd_data = &timb_dma_platform_data, |
445 | .data_size = sizeof(timb_dma_platform_data), | ||
446 | }, | 438 | }, |
447 | { | 439 | { |
448 | .name = "timb-uart", | 440 | .name = "timb-uart", |
@@ -458,15 +450,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
458 | .name = "xiic-i2c", | 450 | .name = "xiic-i2c", |
459 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | 451 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), |
460 | .resources = timberdale_xiic_resources, | 452 | .resources = timberdale_xiic_resources, |
461 | .platform_data = &timberdale_xiic_platform_data, | 453 | .mfd_data = &timberdale_xiic_platform_data, |
462 | .data_size = sizeof(timberdale_xiic_platform_data), | ||
463 | }, | 454 | }, |
464 | { | 455 | { |
465 | .name = "timb-gpio", | 456 | .name = "timb-gpio", |
466 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 457 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
467 | .resources = timberdale_gpio_resources, | 458 | .resources = timberdale_gpio_resources, |
468 | .platform_data = &timberdale_gpio_platform_data, | 459 | .mfd_data = &timberdale_gpio_platform_data, |
469 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
470 | }, | 460 | }, |
471 | { | 461 | { |
472 | .name = "timb-mlogicore", | 462 | .name = "timb-mlogicore", |
@@ -477,29 +467,25 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
477 | .name = "timb-video", | 467 | .name = "timb-video", |
478 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 468 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
479 | .resources = timberdale_video_resources, | 469 | .resources = timberdale_video_resources, |
480 | .platform_data = &timberdale_video_platform_data, | 470 | .mfd_data = &timberdale_video_platform_data, |
481 | .data_size = sizeof(timberdale_video_platform_data), | ||
482 | }, | 471 | }, |
483 | { | 472 | { |
484 | .name = "timb-radio", | 473 | .name = "timb-radio", |
485 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 474 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
486 | .resources = timberdale_radio_resources, | 475 | .resources = timberdale_radio_resources, |
487 | .platform_data = &timberdale_radio_platform_data, | 476 | .mfd_data = &timberdale_radio_platform_data, |
488 | .data_size = sizeof(timberdale_radio_platform_data), | ||
489 | }, | 477 | }, |
490 | { | 478 | { |
491 | .name = "xilinx_spi", | 479 | .name = "xilinx_spi", |
492 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 480 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
493 | .resources = timberdale_spi_resources, | 481 | .resources = timberdale_spi_resources, |
494 | .platform_data = &timberdale_xspi_platform_data, | 482 | .mfd_data = &timberdale_xspi_platform_data, |
495 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
496 | }, | 483 | }, |
497 | { | 484 | { |
498 | .name = "ks8842", | 485 | .name = "ks8842", |
499 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 486 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
500 | .resources = timberdale_eth_resources, | 487 | .resources = timberdale_eth_resources, |
501 | .platform_data = &timberdale_ks8842_platform_data, | 488 | .mfd_data = &timberdale_ks8842_platform_data, |
502 | .data_size = sizeof(timberdale_ks8842_platform_data) | ||
503 | }, | 489 | }, |
504 | }; | 490 | }; |
505 | 491 | ||
@@ -508,8 +494,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | |||
508 | .name = "timb-dma", | 494 | .name = "timb-dma", |
509 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 495 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
510 | .resources = timberdale_dma_resources, | 496 | .resources = timberdale_dma_resources, |
511 | .platform_data = &timb_dma_platform_data, | 497 | .mfd_data = &timb_dma_platform_data, |
512 | .data_size = sizeof(timb_dma_platform_data), | ||
513 | }, | 498 | }, |
514 | { | 499 | { |
515 | .name = "timb-uart", | 500 | .name = "timb-uart", |
@@ -520,36 +505,31 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | |||
520 | .name = "xiic-i2c", | 505 | .name = "xiic-i2c", |
521 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | 506 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), |
522 | .resources = timberdale_xiic_resources, | 507 | .resources = timberdale_xiic_resources, |
523 | .platform_data = &timberdale_xiic_platform_data, | 508 | .mfd_data = &timberdale_xiic_platform_data, |
524 | .data_size = sizeof(timberdale_xiic_platform_data), | ||
525 | }, | 509 | }, |
526 | { | 510 | { |
527 | .name = "timb-gpio", | 511 | .name = "timb-gpio", |
528 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 512 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
529 | .resources = timberdale_gpio_resources, | 513 | .resources = timberdale_gpio_resources, |
530 | .platform_data = &timberdale_gpio_platform_data, | 514 | .mfd_data = &timberdale_gpio_platform_data, |
531 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
532 | }, | 515 | }, |
533 | { | 516 | { |
534 | .name = "timb-video", | 517 | .name = "timb-video", |
535 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 518 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
536 | .resources = timberdale_video_resources, | 519 | .resources = timberdale_video_resources, |
537 | .platform_data = &timberdale_video_platform_data, | 520 | .mfd_data = &timberdale_video_platform_data, |
538 | .data_size = sizeof(timberdale_video_platform_data), | ||
539 | }, | 521 | }, |
540 | { | 522 | { |
541 | .name = "timb-radio", | 523 | .name = "timb-radio", |
542 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 524 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
543 | .resources = timberdale_radio_resources, | 525 | .resources = timberdale_radio_resources, |
544 | .platform_data = &timberdale_radio_platform_data, | 526 | .mfd_data = &timberdale_radio_platform_data, |
545 | .data_size = sizeof(timberdale_radio_platform_data), | ||
546 | }, | 527 | }, |
547 | { | 528 | { |
548 | .name = "xilinx_spi", | 529 | .name = "xilinx_spi", |
549 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 530 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
550 | .resources = timberdale_spi_resources, | 531 | .resources = timberdale_spi_resources, |
551 | .platform_data = &timberdale_xspi_platform_data, | 532 | .mfd_data = &timberdale_xspi_platform_data, |
552 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
553 | }, | 533 | }, |
554 | }; | 534 | }; |
555 | 535 | ||
@@ -558,8 +538,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | |||
558 | .name = "timb-dma", | 538 | .name = "timb-dma", |
559 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 539 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
560 | .resources = timberdale_dma_resources, | 540 | .resources = timberdale_dma_resources, |
561 | .platform_data = &timb_dma_platform_data, | 541 | .mfd_data = &timb_dma_platform_data, |
562 | .data_size = sizeof(timb_dma_platform_data), | ||
563 | }, | 542 | }, |
564 | { | 543 | { |
565 | .name = "timb-uart", | 544 | .name = "timb-uart", |
@@ -570,43 +549,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | |||
570 | .name = "ocores-i2c", | 549 | .name = "ocores-i2c", |
571 | .num_resources = ARRAY_SIZE(timberdale_ocores_resources), | 550 | .num_resources = ARRAY_SIZE(timberdale_ocores_resources), |
572 | .resources = timberdale_ocores_resources, | 551 | .resources = timberdale_ocores_resources, |
573 | .platform_data = &timberdale_ocores_platform_data, | 552 | .mfd_data = &timberdale_ocores_platform_data, |
574 | .data_size = sizeof(timberdale_ocores_platform_data), | ||
575 | }, | 553 | }, |
576 | { | 554 | { |
577 | .name = "timb-gpio", | 555 | .name = "timb-gpio", |
578 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 556 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
579 | .resources = timberdale_gpio_resources, | 557 | .resources = timberdale_gpio_resources, |
580 | .platform_data = &timberdale_gpio_platform_data, | 558 | .mfd_data = &timberdale_gpio_platform_data, |
581 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
582 | }, | 559 | }, |
583 | { | 560 | { |
584 | .name = "timb-video", | 561 | .name = "timb-video", |
585 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 562 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
586 | .resources = timberdale_video_resources, | 563 | .resources = timberdale_video_resources, |
587 | .platform_data = &timberdale_video_platform_data, | 564 | .mfd_data = &timberdale_video_platform_data, |
588 | .data_size = sizeof(timberdale_video_platform_data), | ||
589 | }, | 565 | }, |
590 | { | 566 | { |
591 | .name = "timb-radio", | 567 | .name = "timb-radio", |
592 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 568 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
593 | .resources = timberdale_radio_resources, | 569 | .resources = timberdale_radio_resources, |
594 | .platform_data = &timberdale_radio_platform_data, | 570 | .mfd_data = &timberdale_radio_platform_data, |
595 | .data_size = sizeof(timberdale_radio_platform_data), | ||
596 | }, | 571 | }, |
597 | { | 572 | { |
598 | .name = "xilinx_spi", | 573 | .name = "xilinx_spi", |
599 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 574 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
600 | .resources = timberdale_spi_resources, | 575 | .resources = timberdale_spi_resources, |
601 | .platform_data = &timberdale_xspi_platform_data, | 576 | .mfd_data = &timberdale_xspi_platform_data, |
602 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
603 | }, | 577 | }, |
604 | { | 578 | { |
605 | .name = "ks8842", | 579 | .name = "ks8842", |
606 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 580 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
607 | .resources = timberdale_eth_resources, | 581 | .resources = timberdale_eth_resources, |
608 | .platform_data = &timberdale_ks8842_platform_data, | 582 | .mfd_data = &timberdale_ks8842_platform_data, |
609 | .data_size = sizeof(timberdale_ks8842_platform_data) | ||
610 | }, | 583 | }, |
611 | }; | 584 | }; |
612 | 585 | ||
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c new file mode 100644 index 000000000000..46d8205646b6 --- /dev/null +++ b/drivers/mfd/tps6105x.c | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * Core driver for TPS61050/61052 boost converters, used for while LED | ||
3 | * driving, audio power amplification, white LED flash, and generic | ||
4 | * boost conversion. Additionally it provides a 1-bit GPIO pin (out or in) | ||
5 | * and a flash synchronization pin to synchronize flash events when used as | ||
6 | * flashgun. | ||
7 | * | ||
8 | * Copyright (C) 2011 ST-Ericsson SA | ||
9 | * Written on behalf of Linaro for ST-Ericsson | ||
10 | * | ||
11 | * Author: Linus Walleij <linus.walleij@linaro.org> | ||
12 | * | ||
13 | * License terms: GNU General Public License (GPL) version 2 | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/regulator/driver.h> | ||
25 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/tps6105x.h> | ||
27 | |||
28 | int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value) | ||
29 | { | ||
30 | int ret; | ||
31 | |||
32 | ret = mutex_lock_interruptible(&tps6105x->lock); | ||
33 | if (ret) | ||
34 | return ret; | ||
35 | ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value); | ||
36 | mutex_unlock(&tps6105x->lock); | ||
37 | if (ret < 0) | ||
38 | return ret; | ||
39 | |||
40 | return 0; | ||
41 | } | ||
42 | EXPORT_SYMBOL(tps6105x_set); | ||
43 | |||
44 | int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf) | ||
45 | { | ||
46 | int ret; | ||
47 | |||
48 | ret = mutex_lock_interruptible(&tps6105x->lock); | ||
49 | if (ret) | ||
50 | return ret; | ||
51 | ret = i2c_smbus_read_byte_data(tps6105x->client, reg); | ||
52 | mutex_unlock(&tps6105x->lock); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | *buf = ret; | ||
57 | return 0; | ||
58 | } | ||
59 | EXPORT_SYMBOL(tps6105x_get); | ||
60 | |||
61 | /* | ||
62 | * Masks off the bits in the mask and sets the bits in the bitvalues | ||
63 | * parameter in one atomic operation | ||
64 | */ | ||
65 | int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg, | ||
66 | u8 bitmask, u8 bitvalues) | ||
67 | { | ||
68 | int ret; | ||
69 | u8 regval; | ||
70 | |||
71 | ret = mutex_lock_interruptible(&tps6105x->lock); | ||
72 | if (ret) | ||
73 | return ret; | ||
74 | ret = i2c_smbus_read_byte_data(tps6105x->client, reg); | ||
75 | if (ret < 0) | ||
76 | goto fail; | ||
77 | regval = ret; | ||
78 | regval = (~bitmask & regval) | (bitmask & bitvalues); | ||
79 | ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval); | ||
80 | fail: | ||
81 | mutex_unlock(&tps6105x->lock); | ||
82 | if (ret < 0) | ||
83 | return ret; | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | EXPORT_SYMBOL(tps6105x_mask_and_set); | ||
88 | |||
89 | static int __devinit tps6105x_startup(struct tps6105x *tps6105x) | ||
90 | { | ||
91 | int ret; | ||
92 | u8 regval; | ||
93 | |||
94 | ret = tps6105x_get(tps6105x, TPS6105X_REG_0, ®val); | ||
95 | if (ret) | ||
96 | return ret; | ||
97 | switch (regval >> TPS6105X_REG0_MODE_SHIFT) { | ||
98 | case TPS6105X_REG0_MODE_SHUTDOWN: | ||
99 | dev_info(&tps6105x->client->dev, | ||
100 | "TPS6105x found in SHUTDOWN mode\n"); | ||
101 | break; | ||
102 | case TPS6105X_REG0_MODE_TORCH: | ||
103 | dev_info(&tps6105x->client->dev, | ||
104 | "TPS6105x found in TORCH mode\n"); | ||
105 | break; | ||
106 | case TPS6105X_REG0_MODE_TORCH_FLASH: | ||
107 | dev_info(&tps6105x->client->dev, | ||
108 | "TPS6105x found in FLASH mode\n"); | ||
109 | break; | ||
110 | case TPS6105X_REG0_MODE_VOLTAGE: | ||
111 | dev_info(&tps6105x->client->dev, | ||
112 | "TPS6105x found in VOLTAGE mode\n"); | ||
113 | break; | ||
114 | default: | ||
115 | break; | ||
116 | } | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * MFD cells - we have one cell which is selected operation | ||
123 | * mode, and we always have a GPIO cell. | ||
124 | */ | ||
125 | static struct mfd_cell tps6105x_cells[] = { | ||
126 | { | ||
127 | /* name will be runtime assigned */ | ||
128 | .id = -1, | ||
129 | }, | ||
130 | { | ||
131 | .name = "tps6105x-gpio", | ||
132 | .id = -1, | ||
133 | }, | ||
134 | }; | ||
135 | |||
136 | static int __devinit tps6105x_probe(struct i2c_client *client, | ||
137 | const struct i2c_device_id *id) | ||
138 | { | ||
139 | struct tps6105x *tps6105x; | ||
140 | struct tps6105x_platform_data *pdata; | ||
141 | int ret; | ||
142 | int i; | ||
143 | |||
144 | tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL); | ||
145 | if (!tps6105x) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | i2c_set_clientdata(client, tps6105x); | ||
149 | tps6105x->client = client; | ||
150 | pdata = client->dev.platform_data; | ||
151 | tps6105x->pdata = pdata; | ||
152 | mutex_init(&tps6105x->lock); | ||
153 | |||
154 | ret = tps6105x_startup(tps6105x); | ||
155 | if (ret) { | ||
156 | dev_err(&client->dev, "chip initialization failed\n"); | ||
157 | goto fail; | ||
158 | } | ||
159 | |||
160 | /* Remove warning texts when you implement new cell drivers */ | ||
161 | switch (pdata->mode) { | ||
162 | case TPS6105X_MODE_SHUTDOWN: | ||
163 | dev_info(&client->dev, | ||
164 | "present, not used for anything, only GPIO\n"); | ||
165 | break; | ||
166 | case TPS6105X_MODE_TORCH: | ||
167 | tps6105x_cells[0].name = "tps6105x-leds"; | ||
168 | dev_warn(&client->dev, | ||
169 | "torch mode is unsupported\n"); | ||
170 | break; | ||
171 | case TPS6105X_MODE_TORCH_FLASH: | ||
172 | tps6105x_cells[0].name = "tps6105x-flash"; | ||
173 | dev_warn(&client->dev, | ||
174 | "flash mode is unsupported\n"); | ||
175 | break; | ||
176 | case TPS6105X_MODE_VOLTAGE: | ||
177 | tps6105x_cells[0].name ="tps6105x-regulator"; | ||
178 | break; | ||
179 | default: | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | /* Set up and register the platform devices. */ | ||
184 | for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) { | ||
185 | /* One state holder for all drivers, this is simple */ | ||
186 | tps6105x_cells[i].mfd_data = tps6105x; | ||
187 | } | ||
188 | |||
189 | ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, | ||
190 | ARRAY_SIZE(tps6105x_cells), NULL, 0); | ||
191 | if (ret) | ||
192 | goto fail; | ||
193 | |||
194 | return 0; | ||
195 | |||
196 | fail: | ||
197 | kfree(tps6105x); | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | static int __devexit tps6105x_remove(struct i2c_client *client) | ||
202 | { | ||
203 | struct tps6105x *tps6105x = i2c_get_clientdata(client); | ||
204 | |||
205 | mfd_remove_devices(&client->dev); | ||
206 | |||
207 | /* Put chip in shutdown mode */ | ||
208 | tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, | ||
209 | TPS6105X_REG0_MODE_MASK, | ||
210 | TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT); | ||
211 | |||
212 | kfree(tps6105x); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static const struct i2c_device_id tps6105x_id[] = { | ||
217 | { "tps61050", 0 }, | ||
218 | { "tps61052", 0 }, | ||
219 | { } | ||
220 | }; | ||
221 | MODULE_DEVICE_TABLE(i2c, tps6105x_id); | ||
222 | |||
223 | static struct i2c_driver tps6105x_driver = { | ||
224 | .driver = { | ||
225 | .name = "tps6105x", | ||
226 | }, | ||
227 | .probe = tps6105x_probe, | ||
228 | .remove = __devexit_p(tps6105x_remove), | ||
229 | .id_table = tps6105x_id, | ||
230 | }; | ||
231 | |||
232 | static int __init tps6105x_init(void) | ||
233 | { | ||
234 | return i2c_add_driver(&tps6105x_driver); | ||
235 | } | ||
236 | subsys_initcall(tps6105x_init); | ||
237 | |||
238 | static void __exit tps6105x_exit(void) | ||
239 | { | ||
240 | i2c_del_driver(&tps6105x_driver); | ||
241 | } | ||
242 | module_exit(tps6105x_exit); | ||
243 | |||
244 | MODULE_AUTHOR("Linus Walleij"); | ||
245 | MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver"); | ||
246 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index e9018d1394ee..0aa9186aec19 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c | |||
@@ -288,12 +288,10 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, | |||
288 | return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); | 288 | return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); |
289 | } | 289 | } |
290 | 290 | ||
291 | static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) | 291 | static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) |
292 | { | 292 | { |
293 | int ret; | ||
294 | |||
295 | if (!gpio_base) | 293 | if (!gpio_base) |
296 | return; | 294 | return 0; |
297 | 295 | ||
298 | tps6586x->gpio.owner = THIS_MODULE; | 296 | tps6586x->gpio.owner = THIS_MODULE; |
299 | tps6586x->gpio.label = tps6586x->client->name; | 297 | tps6586x->gpio.label = tps6586x->client->name; |
@@ -307,9 +305,7 @@ static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) | |||
307 | tps6586x->gpio.set = tps6586x_gpio_set; | 305 | tps6586x->gpio.set = tps6586x_gpio_set; |
308 | tps6586x->gpio.get = tps6586x_gpio_get; | 306 | tps6586x->gpio.get = tps6586x_gpio_get; |
309 | 307 | ||
310 | ret = gpiochip_add(&tps6586x->gpio); | 308 | return gpiochip_add(&tps6586x->gpio); |
311 | if (ret) | ||
312 | dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret); | ||
313 | } | 309 | } |
314 | 310 | ||
315 | static int __remove_subdev(struct device *dev, void *unused) | 311 | static int __remove_subdev(struct device *dev, void *unused) |
@@ -517,17 +513,28 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | |||
517 | } | 513 | } |
518 | } | 514 | } |
519 | 515 | ||
516 | ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base); | ||
517 | if (ret) { | ||
518 | dev_err(&client->dev, "GPIO registration failed: %d\n", ret); | ||
519 | goto err_gpio_init; | ||
520 | } | ||
521 | |||
520 | ret = tps6586x_add_subdevs(tps6586x, pdata); | 522 | ret = tps6586x_add_subdevs(tps6586x, pdata); |
521 | if (ret) { | 523 | if (ret) { |
522 | dev_err(&client->dev, "add devices failed: %d\n", ret); | 524 | dev_err(&client->dev, "add devices failed: %d\n", ret); |
523 | goto err_add_devs; | 525 | goto err_add_devs; |
524 | } | 526 | } |
525 | 527 | ||
526 | tps6586x_gpio_init(tps6586x, pdata->gpio_base); | ||
527 | |||
528 | return 0; | 528 | return 0; |
529 | 529 | ||
530 | err_add_devs: | 530 | err_add_devs: |
531 | if (pdata->gpio_base) { | ||
532 | ret = gpiochip_remove(&tps6586x->gpio); | ||
533 | if (ret) | ||
534 | dev_err(&client->dev, "Can't remove gpio chip: %d\n", | ||
535 | ret); | ||
536 | } | ||
537 | err_gpio_init: | ||
531 | if (client->irq) | 538 | if (client->irq) |
532 | free_irq(client->irq, tps6586x); | 539 | free_irq(client->irq, tps6586x); |
533 | err_irq_init: | 540 | err_irq_init: |
@@ -587,4 +594,3 @@ module_exit(tps6586x_exit); | |||
587 | MODULE_DESCRIPTION("TPS6586X core driver"); | 594 | MODULE_DESCRIPTION("TPS6586X core driver"); |
588 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | 595 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); |
589 | MODULE_LICENSE("GPL"); | 596 | MODULE_LICENSE("GPL"); |
590 | |||
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index a35fa7dcbf53..960b5bed7f52 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -721,13 +721,13 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
721 | 721 | ||
722 | } | 722 | } |
723 | 723 | ||
724 | if (twl_has_watchdog()) { | 724 | if (twl_has_watchdog() && twl_class_is_4030()) { |
725 | child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0); | 725 | child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0); |
726 | if (IS_ERR(child)) | 726 | if (IS_ERR(child)) |
727 | return PTR_ERR(child); | 727 | return PTR_ERR(child); |
728 | } | 728 | } |
729 | 729 | ||
730 | if (twl_has_pwrbutton()) { | 730 | if (twl_has_pwrbutton() && twl_class_is_4030()) { |
731 | child = add_child(1, "twl4030_pwrbutton", | 731 | child = add_child(1, "twl4030_pwrbutton", |
732 | NULL, 0, true, pdata->irq_base + 8 + 0, 0); | 732 | NULL, 0, true, pdata->irq_base + 8 + 0, 0); |
733 | if (IS_ERR(child)) | 733 | if (IS_ERR(child)) |
@@ -864,6 +864,10 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
864 | child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); | 864 | child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); |
865 | if (IS_ERR(child)) | 865 | if (IS_ERR(child)) |
866 | return PTR_ERR(child); | 866 | return PTR_ERR(child); |
867 | |||
868 | child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg); | ||
869 | if (IS_ERR(child)) | ||
870 | return PTR_ERR(child); | ||
867 | } | 871 | } |
868 | 872 | ||
869 | if (twl_has_bci() && pdata->bci && | 873 | if (twl_has_bci() && pdata->bci && |
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c index 9a4b196d6deb..c02fded316c9 100644 --- a/drivers/mfd/twl4030-codec.c +++ b/drivers/mfd/twl4030-codec.c | |||
@@ -208,15 +208,13 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev) | |||
208 | if (pdata->audio) { | 208 | if (pdata->audio) { |
209 | cell = &codec->cells[childs]; | 209 | cell = &codec->cells[childs]; |
210 | cell->name = "twl4030-codec"; | 210 | cell->name = "twl4030-codec"; |
211 | cell->platform_data = pdata->audio; | 211 | cell->mfd_data = pdata->audio; |
212 | cell->data_size = sizeof(*pdata->audio); | ||
213 | childs++; | 212 | childs++; |
214 | } | 213 | } |
215 | if (pdata->vibra) { | 214 | if (pdata->vibra) { |
216 | cell = &codec->cells[childs]; | 215 | cell = &codec->cells[childs]; |
217 | cell->name = "twl4030-vibra"; | 216 | cell->name = "twl4030-vibra"; |
218 | cell->platform_data = pdata->vibra; | 217 | cell->mfd_data = pdata->vibra; |
219 | cell->data_size = sizeof(*pdata->vibra); | ||
220 | childs++; | 218 | childs++; |
221 | } | 219 | } |
222 | 220 | ||
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c new file mode 100644 index 000000000000..3941ddcf15fe --- /dev/null +++ b/drivers/mfd/twl4030-madc.c | |||
@@ -0,0 +1,802 @@ | |||
1 | /* | ||
2 | * | ||
3 | * TWL4030 MADC module driver-This driver monitors the real time | ||
4 | * conversion of analog signals like battery temperature, | ||
5 | * battery type, battery level etc. | ||
6 | * | ||
7 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
8 | * J Keerthy <j-keerthy@ti.com> | ||
9 | * | ||
10 | * Based on twl4030-madc.c | ||
11 | * Copyright (C) 2008 Nokia Corporation | ||
12 | * Mikko Ylinen <mikko.k.ylinen@nokia.com> | ||
13 | * | ||
14 | * Amit Kucheria <amit.kucheria@canonical.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License | ||
18 | * version 2 as published by the Free Software Foundation. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, but | ||
21 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
23 | * General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
28 | * 02110-1301 USA | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/init.h> | ||
33 | #include <linux/device.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/platform_device.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/i2c/twl.h> | ||
40 | #include <linux/i2c/twl4030-madc.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/stddef.h> | ||
43 | #include <linux/mutex.h> | ||
44 | #include <linux/bitops.h> | ||
45 | #include <linux/jiffies.h> | ||
46 | #include <linux/types.h> | ||
47 | #include <linux/gfp.h> | ||
48 | #include <linux/err.h> | ||
49 | |||
50 | /* | ||
51 | * struct twl4030_madc_data - a container for madc info | ||
52 | * @dev - pointer to device structure for madc | ||
53 | * @lock - mutex protecting this data structure | ||
54 | * @requests - Array of request struct corresponding to SW1, SW2 and RT | ||
55 | * @imr - Interrupt mask register of MADC | ||
56 | * @isr - Interrupt status register of MADC | ||
57 | */ | ||
58 | struct twl4030_madc_data { | ||
59 | struct device *dev; | ||
60 | struct mutex lock; /* mutex protecting this data structure */ | ||
61 | struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS]; | ||
62 | int imr; | ||
63 | int isr; | ||
64 | }; | ||
65 | |||
66 | static struct twl4030_madc_data *twl4030_madc; | ||
67 | |||
68 | struct twl4030_prescale_divider_ratios { | ||
69 | s16 numerator; | ||
70 | s16 denominator; | ||
71 | }; | ||
72 | |||
73 | static const struct twl4030_prescale_divider_ratios | ||
74 | twl4030_divider_ratios[16] = { | ||
75 | {1, 1}, /* CHANNEL 0 No Prescaler */ | ||
76 | {1, 1}, /* CHANNEL 1 No Prescaler */ | ||
77 | {6, 10}, /* CHANNEL 2 */ | ||
78 | {6, 10}, /* CHANNEL 3 */ | ||
79 | {6, 10}, /* CHANNEL 4 */ | ||
80 | {6, 10}, /* CHANNEL 5 */ | ||
81 | {6, 10}, /* CHANNEL 6 */ | ||
82 | {6, 10}, /* CHANNEL 7 */ | ||
83 | {3, 14}, /* CHANNEL 8 */ | ||
84 | {1, 3}, /* CHANNEL 9 */ | ||
85 | {1, 1}, /* CHANNEL 10 No Prescaler */ | ||
86 | {15, 100}, /* CHANNEL 11 */ | ||
87 | {1, 4}, /* CHANNEL 12 */ | ||
88 | {1, 1}, /* CHANNEL 13 Reserved channels */ | ||
89 | {1, 1}, /* CHANNEL 14 Reseved channels */ | ||
90 | {5, 11}, /* CHANNEL 15 */ | ||
91 | }; | ||
92 | |||
93 | |||
94 | /* | ||
95 | * Conversion table from -3 to 55 degree Celcius | ||
96 | */ | ||
97 | static int therm_tbl[] = { | ||
98 | 30800, 29500, 28300, 27100, | ||
99 | 26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900, | ||
100 | 17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100, | ||
101 | 11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310, | ||
102 | 8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830, | ||
103 | 5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170, | ||
104 | 4040, 3910, 3790, 3670, 3550 | ||
105 | }; | ||
106 | |||
107 | /* | ||
108 | * Structure containing the registers | ||
109 | * of different conversion methods supported by MADC. | ||
110 | * Hardware or RT real time conversion request initiated by external host | ||
111 | * processor for RT Signal conversions. | ||
112 | * External host processors can also request for non RT conversions | ||
113 | * SW1 and SW2 software conversions also called asynchronous or GPC request. | ||
114 | */ | ||
115 | static | ||
116 | const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = { | ||
117 | [TWL4030_MADC_RT] = { | ||
118 | .sel = TWL4030_MADC_RTSELECT_LSB, | ||
119 | .avg = TWL4030_MADC_RTAVERAGE_LSB, | ||
120 | .rbase = TWL4030_MADC_RTCH0_LSB, | ||
121 | }, | ||
122 | [TWL4030_MADC_SW1] = { | ||
123 | .sel = TWL4030_MADC_SW1SELECT_LSB, | ||
124 | .avg = TWL4030_MADC_SW1AVERAGE_LSB, | ||
125 | .rbase = TWL4030_MADC_GPCH0_LSB, | ||
126 | .ctrl = TWL4030_MADC_CTRL_SW1, | ||
127 | }, | ||
128 | [TWL4030_MADC_SW2] = { | ||
129 | .sel = TWL4030_MADC_SW2SELECT_LSB, | ||
130 | .avg = TWL4030_MADC_SW2AVERAGE_LSB, | ||
131 | .rbase = TWL4030_MADC_GPCH0_LSB, | ||
132 | .ctrl = TWL4030_MADC_CTRL_SW2, | ||
133 | }, | ||
134 | }; | ||
135 | |||
136 | /* | ||
137 | * Function to read a particular channel value. | ||
138 | * @madc - pointer to struct twl4030_madc_data | ||
139 | * @reg - lsb of ADC Channel | ||
140 | * If the i2c read fails it returns an error else returns 0. | ||
141 | */ | ||
142 | static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg) | ||
143 | { | ||
144 | u8 msb, lsb; | ||
145 | int ret; | ||
146 | /* | ||
147 | * For each ADC channel, we have MSB and LSB register pair. MSB address | ||
148 | * is always LSB address+1. reg parameter is the address of LSB register | ||
149 | */ | ||
150 | ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &msb, reg + 1); | ||
151 | if (ret) { | ||
152 | dev_err(madc->dev, "unable to read MSB register 0x%X\n", | ||
153 | reg + 1); | ||
154 | return ret; | ||
155 | } | ||
156 | ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &lsb, reg); | ||
157 | if (ret) { | ||
158 | dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | return (int)(((msb << 8) | lsb) >> 6); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Return battery temperature | ||
167 | * Or < 0 on failure. | ||
168 | */ | ||
169 | static int twl4030battery_temperature(int raw_volt) | ||
170 | { | ||
171 | u8 val; | ||
172 | int temp, curr, volt, res, ret; | ||
173 | |||
174 | volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R; | ||
175 | /* Getting and calculating the supply current in micro ampers */ | ||
176 | ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val, | ||
177 | REG_BCICTL2); | ||
178 | if (ret < 0) | ||
179 | return ret; | ||
180 | curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10; | ||
181 | /* Getting and calculating the thermistor resistance in ohms */ | ||
182 | res = volt * 1000 / curr; | ||
183 | /* calculating temperature */ | ||
184 | for (temp = 58; temp >= 0; temp--) { | ||
185 | int actual = therm_tbl[temp]; | ||
186 | |||
187 | if ((actual - res) >= 0) | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | return temp + 1; | ||
192 | } | ||
193 | |||
194 | static int twl4030battery_current(int raw_volt) | ||
195 | { | ||
196 | int ret; | ||
197 | u8 val; | ||
198 | |||
199 | ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val, | ||
200 | TWL4030_BCI_BCICTL1); | ||
201 | if (ret) | ||
202 | return ret; | ||
203 | if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */ | ||
204 | return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1; | ||
205 | else /* slope of 0.88 mV/mA */ | ||
206 | return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2; | ||
207 | } | ||
208 | /* | ||
209 | * Function to read channel values | ||
210 | * @madc - pointer to twl4030_madc_data struct | ||
211 | * @reg_base - Base address of the first channel | ||
212 | * @Channels - 16 bit bitmap. If the bit is set, channel value is read | ||
213 | * @buf - The channel values are stored here. if read fails error | ||
214 | * value is stored | ||
215 | * Returns the number of successfully read channels. | ||
216 | */ | ||
217 | static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, | ||
218 | u8 reg_base, unsigned | ||
219 | long channels, int *buf) | ||
220 | { | ||
221 | int count = 0, count_req = 0, i; | ||
222 | u8 reg; | ||
223 | |||
224 | for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) { | ||
225 | reg = reg_base + 2 * i; | ||
226 | buf[i] = twl4030_madc_channel_raw_read(madc, reg); | ||
227 | if (buf[i] < 0) { | ||
228 | dev_err(madc->dev, | ||
229 | "Unable to read register 0x%X\n", reg); | ||
230 | count_req++; | ||
231 | continue; | ||
232 | } | ||
233 | switch (i) { | ||
234 | case 10: | ||
235 | buf[i] = twl4030battery_current(buf[i]); | ||
236 | if (buf[i] < 0) { | ||
237 | dev_err(madc->dev, "err reading current\n"); | ||
238 | count_req++; | ||
239 | } else { | ||
240 | count++; | ||
241 | buf[i] = buf[i] - 750; | ||
242 | } | ||
243 | break; | ||
244 | case 1: | ||
245 | buf[i] = twl4030battery_temperature(buf[i]); | ||
246 | if (buf[i] < 0) { | ||
247 | dev_err(madc->dev, "err reading temperature\n"); | ||
248 | count_req++; | ||
249 | } else { | ||
250 | buf[i] -= 3; | ||
251 | count++; | ||
252 | } | ||
253 | break; | ||
254 | default: | ||
255 | count++; | ||
256 | /* Analog Input (V) = conv_result * step_size / R | ||
257 | * conv_result = decimal value of 10-bit conversion | ||
258 | * result | ||
259 | * step size = 1.5 / (2 ^ 10 -1) | ||
260 | * R = Prescaler ratio for input channels. | ||
261 | * Result given in mV hence multiplied by 1000. | ||
262 | */ | ||
263 | buf[i] = (buf[i] * 3 * 1000 * | ||
264 | twl4030_divider_ratios[i].denominator) | ||
265 | / (2 * 1023 * | ||
266 | twl4030_divider_ratios[i].numerator); | ||
267 | } | ||
268 | } | ||
269 | if (count_req) | ||
270 | dev_err(madc->dev, "%d channel conversion failed\n", count_req); | ||
271 | |||
272 | return count; | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | * Enables irq. | ||
277 | * @madc - pointer to twl4030_madc_data struct | ||
278 | * @id - irq number to be enabled | ||
279 | * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2 | ||
280 | * corresponding to RT, SW1, SW2 conversion requests. | ||
281 | * If the i2c read fails it returns an error else returns 0. | ||
282 | */ | ||
283 | static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id) | ||
284 | { | ||
285 | u8 val; | ||
286 | int ret; | ||
287 | |||
288 | ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr); | ||
289 | if (ret) { | ||
290 | dev_err(madc->dev, "unable to read imr register 0x%X\n", | ||
291 | madc->imr); | ||
292 | return ret; | ||
293 | } | ||
294 | val &= ~(1 << id); | ||
295 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr); | ||
296 | if (ret) { | ||
297 | dev_err(madc->dev, | ||
298 | "unable to write imr register 0x%X\n", madc->imr); | ||
299 | return ret; | ||
300 | |||
301 | } | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * Disables irq. | ||
308 | * @madc - pointer to twl4030_madc_data struct | ||
309 | * @id - irq number to be disabled | ||
310 | * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2 | ||
311 | * corresponding to RT, SW1, SW2 conversion requests. | ||
312 | * Returns error if i2c read/write fails. | ||
313 | */ | ||
314 | static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id) | ||
315 | { | ||
316 | u8 val; | ||
317 | int ret; | ||
318 | |||
319 | ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr); | ||
320 | if (ret) { | ||
321 | dev_err(madc->dev, "unable to read imr register 0x%X\n", | ||
322 | madc->imr); | ||
323 | return ret; | ||
324 | } | ||
325 | val |= (1 << id); | ||
326 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr); | ||
327 | if (ret) { | ||
328 | dev_err(madc->dev, | ||
329 | "unable to write imr register 0x%X\n", madc->imr); | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) | ||
337 | { | ||
338 | struct twl4030_madc_data *madc = _madc; | ||
339 | const struct twl4030_madc_conversion_method *method; | ||
340 | u8 isr_val, imr_val; | ||
341 | int i, len, ret; | ||
342 | struct twl4030_madc_request *r; | ||
343 | |||
344 | mutex_lock(&madc->lock); | ||
345 | ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr); | ||
346 | if (ret) { | ||
347 | dev_err(madc->dev, "unable to read isr register 0x%X\n", | ||
348 | madc->isr); | ||
349 | goto err_i2c; | ||
350 | } | ||
351 | ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr); | ||
352 | if (ret) { | ||
353 | dev_err(madc->dev, "unable to read imr register 0x%X\n", | ||
354 | madc->imr); | ||
355 | goto err_i2c; | ||
356 | } | ||
357 | isr_val &= ~imr_val; | ||
358 | for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { | ||
359 | if (!(isr_val & (1 << i))) | ||
360 | continue; | ||
361 | ret = twl4030_madc_disable_irq(madc, i); | ||
362 | if (ret < 0) | ||
363 | dev_dbg(madc->dev, "Disable interrupt failed%d\n", i); | ||
364 | madc->requests[i].result_pending = 1; | ||
365 | } | ||
366 | for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { | ||
367 | r = &madc->requests[i]; | ||
368 | /* No pending results for this method, move to next one */ | ||
369 | if (!r->result_pending) | ||
370 | continue; | ||
371 | method = &twl4030_conversion_methods[r->method]; | ||
372 | /* Read results */ | ||
373 | len = twl4030_madc_read_channels(madc, method->rbase, | ||
374 | r->channels, r->rbuf); | ||
375 | /* Return results to caller */ | ||
376 | if (r->func_cb != NULL) { | ||
377 | r->func_cb(len, r->channels, r->rbuf); | ||
378 | r->func_cb = NULL; | ||
379 | } | ||
380 | /* Free request */ | ||
381 | r->result_pending = 0; | ||
382 | r->active = 0; | ||
383 | } | ||
384 | mutex_unlock(&madc->lock); | ||
385 | |||
386 | return IRQ_HANDLED; | ||
387 | |||
388 | err_i2c: | ||
389 | /* | ||
390 | * In case of error check whichever request is active | ||
391 | * and service the same. | ||
392 | */ | ||
393 | for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { | ||
394 | r = &madc->requests[i]; | ||
395 | if (r->active == 0) | ||
396 | continue; | ||
397 | method = &twl4030_conversion_methods[r->method]; | ||
398 | /* Read results */ | ||
399 | len = twl4030_madc_read_channels(madc, method->rbase, | ||
400 | r->channels, r->rbuf); | ||
401 | /* Return results to caller */ | ||
402 | if (r->func_cb != NULL) { | ||
403 | r->func_cb(len, r->channels, r->rbuf); | ||
404 | r->func_cb = NULL; | ||
405 | } | ||
406 | /* Free request */ | ||
407 | r->result_pending = 0; | ||
408 | r->active = 0; | ||
409 | } | ||
410 | mutex_unlock(&madc->lock); | ||
411 | |||
412 | return IRQ_HANDLED; | ||
413 | } | ||
414 | |||
415 | static int twl4030_madc_set_irq(struct twl4030_madc_data *madc, | ||
416 | struct twl4030_madc_request *req) | ||
417 | { | ||
418 | struct twl4030_madc_request *p; | ||
419 | int ret; | ||
420 | |||
421 | p = &madc->requests[req->method]; | ||
422 | memcpy(p, req, sizeof(*req)); | ||
423 | ret = twl4030_madc_enable_irq(madc, req->method); | ||
424 | if (ret < 0) { | ||
425 | dev_err(madc->dev, "enable irq failed!!\n"); | ||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * Function which enables the madc conversion | ||
434 | * by writing to the control register. | ||
435 | * @madc - pointer to twl4030_madc_data struct | ||
436 | * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1 | ||
437 | * corresponding to RT SW1 or SW2 conversion methods. | ||
438 | * Returns 0 if succeeds else a negative error value | ||
439 | */ | ||
440 | static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc, | ||
441 | int conv_method) | ||
442 | { | ||
443 | const struct twl4030_madc_conversion_method *method; | ||
444 | int ret = 0; | ||
445 | method = &twl4030_conversion_methods[conv_method]; | ||
446 | switch (conv_method) { | ||
447 | case TWL4030_MADC_SW1: | ||
448 | case TWL4030_MADC_SW2: | ||
449 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, | ||
450 | TWL4030_MADC_SW_START, method->ctrl); | ||
451 | if (ret) { | ||
452 | dev_err(madc->dev, | ||
453 | "unable to write ctrl register 0x%X\n", | ||
454 | method->ctrl); | ||
455 | return ret; | ||
456 | } | ||
457 | break; | ||
458 | default: | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | * Function that waits for conversion to be ready | ||
467 | * @madc - pointer to twl4030_madc_data struct | ||
468 | * @timeout_ms - timeout value in milliseconds | ||
469 | * @status_reg - ctrl register | ||
470 | * returns 0 if succeeds else a negative error value | ||
471 | */ | ||
472 | static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc, | ||
473 | unsigned int timeout_ms, | ||
474 | u8 status_reg) | ||
475 | { | ||
476 | unsigned long timeout; | ||
477 | int ret; | ||
478 | |||
479 | timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
480 | do { | ||
481 | u8 reg; | ||
482 | |||
483 | ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, ®, status_reg); | ||
484 | if (ret) { | ||
485 | dev_err(madc->dev, | ||
486 | "unable to read status register 0x%X\n", | ||
487 | status_reg); | ||
488 | return ret; | ||
489 | } | ||
490 | if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW)) | ||
491 | return 0; | ||
492 | usleep_range(500, 2000); | ||
493 | } while (!time_after(jiffies, timeout)); | ||
494 | dev_err(madc->dev, "conversion timeout!\n"); | ||
495 | |||
496 | return -EAGAIN; | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * An exported function which can be called from other kernel drivers. | ||
501 | * @req twl4030_madc_request structure | ||
502 | * req->rbuf will be filled with read values of channels based on the | ||
503 | * channel index. If a particular channel reading fails there will | ||
504 | * be a negative error value in the corresponding array element. | ||
505 | * returns 0 if succeeds else error value | ||
506 | */ | ||
507 | int twl4030_madc_conversion(struct twl4030_madc_request *req) | ||
508 | { | ||
509 | const struct twl4030_madc_conversion_method *method; | ||
510 | u8 ch_msb, ch_lsb; | ||
511 | int ret; | ||
512 | |||
513 | if (!req) | ||
514 | return -EINVAL; | ||
515 | mutex_lock(&twl4030_madc->lock); | ||
516 | if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) { | ||
517 | ret = -EINVAL; | ||
518 | goto out; | ||
519 | } | ||
520 | /* Do we have a conversion request ongoing */ | ||
521 | if (twl4030_madc->requests[req->method].active) { | ||
522 | ret = -EBUSY; | ||
523 | goto out; | ||
524 | } | ||
525 | ch_msb = (req->channels >> 8) & 0xff; | ||
526 | ch_lsb = req->channels & 0xff; | ||
527 | method = &twl4030_conversion_methods[req->method]; | ||
528 | /* Select channels to be converted */ | ||
529 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1); | ||
530 | if (ret) { | ||
531 | dev_err(twl4030_madc->dev, | ||
532 | "unable to write sel register 0x%X\n", method->sel + 1); | ||
533 | return ret; | ||
534 | } | ||
535 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel); | ||
536 | if (ret) { | ||
537 | dev_err(twl4030_madc->dev, | ||
538 | "unable to write sel register 0x%X\n", method->sel + 1); | ||
539 | return ret; | ||
540 | } | ||
541 | /* Select averaging for all channels if do_avg is set */ | ||
542 | if (req->do_avg) { | ||
543 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, | ||
544 | ch_msb, method->avg + 1); | ||
545 | if (ret) { | ||
546 | dev_err(twl4030_madc->dev, | ||
547 | "unable to write avg register 0x%X\n", | ||
548 | method->avg + 1); | ||
549 | return ret; | ||
550 | } | ||
551 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, | ||
552 | ch_lsb, method->avg); | ||
553 | if (ret) { | ||
554 | dev_err(twl4030_madc->dev, | ||
555 | "unable to write sel reg 0x%X\n", | ||
556 | method->sel + 1); | ||
557 | return ret; | ||
558 | } | ||
559 | } | ||
560 | if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) { | ||
561 | ret = twl4030_madc_set_irq(twl4030_madc, req); | ||
562 | if (ret < 0) | ||
563 | goto out; | ||
564 | ret = twl4030_madc_start_conversion(twl4030_madc, req->method); | ||
565 | if (ret < 0) | ||
566 | goto out; | ||
567 | twl4030_madc->requests[req->method].active = 1; | ||
568 | ret = 0; | ||
569 | goto out; | ||
570 | } | ||
571 | /* With RT method we should not be here anymore */ | ||
572 | if (req->method == TWL4030_MADC_RT) { | ||
573 | ret = -EINVAL; | ||
574 | goto out; | ||
575 | } | ||
576 | ret = twl4030_madc_start_conversion(twl4030_madc, req->method); | ||
577 | if (ret < 0) | ||
578 | goto out; | ||
579 | twl4030_madc->requests[req->method].active = 1; | ||
580 | /* Wait until conversion is ready (ctrl register returns EOC) */ | ||
581 | ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl); | ||
582 | if (ret) { | ||
583 | twl4030_madc->requests[req->method].active = 0; | ||
584 | goto out; | ||
585 | } | ||
586 | ret = twl4030_madc_read_channels(twl4030_madc, method->rbase, | ||
587 | req->channels, req->rbuf); | ||
588 | twl4030_madc->requests[req->method].active = 0; | ||
589 | |||
590 | out: | ||
591 | mutex_unlock(&twl4030_madc->lock); | ||
592 | |||
593 | return ret; | ||
594 | } | ||
595 | EXPORT_SYMBOL_GPL(twl4030_madc_conversion); | ||
596 | |||
597 | /* | ||
598 | * Return channel value | ||
599 | * Or < 0 on failure. | ||
600 | */ | ||
601 | int twl4030_get_madc_conversion(int channel_no) | ||
602 | { | ||
603 | struct twl4030_madc_request req; | ||
604 | int temp = 0; | ||
605 | int ret; | ||
606 | |||
607 | req.channels = (1 << channel_no); | ||
608 | req.method = TWL4030_MADC_SW2; | ||
609 | req.active = 0; | ||
610 | req.func_cb = NULL; | ||
611 | ret = twl4030_madc_conversion(&req); | ||
612 | if (ret < 0) | ||
613 | return ret; | ||
614 | if (req.rbuf[channel_no] > 0) | ||
615 | temp = req.rbuf[channel_no]; | ||
616 | |||
617 | return temp; | ||
618 | } | ||
619 | EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion); | ||
620 | |||
621 | /* | ||
622 | * Function to enable or disable bias current for | ||
623 | * main battery type reading or temperature sensing | ||
624 | * @madc - pointer to twl4030_madc_data struct | ||
625 | * @chan - can be one of the two values | ||
626 | * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading | ||
627 | * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature | ||
628 | * sensing | ||
629 | * @on - enable or disable chan. | ||
630 | */ | ||
631 | static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc, | ||
632 | int chan, int on) | ||
633 | { | ||
634 | int ret; | ||
635 | u8 regval; | ||
636 | |||
637 | ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, | ||
638 | ®val, TWL4030_BCI_BCICTL1); | ||
639 | if (ret) { | ||
640 | dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X", | ||
641 | TWL4030_BCI_BCICTL1); | ||
642 | return ret; | ||
643 | } | ||
644 | if (on) | ||
645 | regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN; | ||
646 | else | ||
647 | regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN; | ||
648 | ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, | ||
649 | regval, TWL4030_BCI_BCICTL1); | ||
650 | if (ret) { | ||
651 | dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n", | ||
652 | TWL4030_BCI_BCICTL1); | ||
653 | return ret; | ||
654 | } | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | /* | ||
660 | * Function that sets MADC software power on bit to enable MADC | ||
661 | * @madc - pointer to twl4030_madc_data struct | ||
662 | * @on - Enable or disable MADC software powen on bit. | ||
663 | * returns error if i2c read/write fails else 0 | ||
664 | */ | ||
665 | static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on) | ||
666 | { | ||
667 | u8 regval; | ||
668 | int ret; | ||
669 | |||
670 | ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, | ||
671 | ®val, TWL4030_MADC_CTRL1); | ||
672 | if (ret) { | ||
673 | dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n", | ||
674 | TWL4030_MADC_CTRL1); | ||
675 | return ret; | ||
676 | } | ||
677 | if (on) | ||
678 | regval |= TWL4030_MADC_MADCON; | ||
679 | else | ||
680 | regval &= ~TWL4030_MADC_MADCON; | ||
681 | ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1); | ||
682 | if (ret) { | ||
683 | dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n", | ||
684 | TWL4030_MADC_CTRL1); | ||
685 | return ret; | ||
686 | } | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * Initialize MADC and request for threaded irq | ||
693 | */ | ||
694 | static int __devinit twl4030_madc_probe(struct platform_device *pdev) | ||
695 | { | ||
696 | struct twl4030_madc_data *madc; | ||
697 | struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data; | ||
698 | int ret; | ||
699 | u8 regval; | ||
700 | |||
701 | if (!pdata) { | ||
702 | dev_err(&pdev->dev, "platform_data not available\n"); | ||
703 | return -EINVAL; | ||
704 | } | ||
705 | madc = kzalloc(sizeof(*madc), GFP_KERNEL); | ||
706 | if (!madc) | ||
707 | return -ENOMEM; | ||
708 | |||
709 | /* | ||
710 | * Phoenix provides 2 interrupt lines. The first one is connected to | ||
711 | * the OMAP. The other one can be connected to the other processor such | ||
712 | * as modem. Hence two separate ISR and IMR registers. | ||
713 | */ | ||
714 | madc->imr = (pdata->irq_line == 1) ? | ||
715 | TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2; | ||
716 | madc->isr = (pdata->irq_line == 1) ? | ||
717 | TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2; | ||
718 | ret = twl4030_madc_set_power(madc, 1); | ||
719 | if (ret < 0) | ||
720 | goto err_power; | ||
721 | ret = twl4030_madc_set_current_generator(madc, 0, 1); | ||
722 | if (ret < 0) | ||
723 | goto err_current_generator; | ||
724 | |||
725 | ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, | ||
726 | ®val, TWL4030_BCI_BCICTL1); | ||
727 | if (ret) { | ||
728 | dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n", | ||
729 | TWL4030_BCI_BCICTL1); | ||
730 | goto err_i2c; | ||
731 | } | ||
732 | regval |= TWL4030_BCI_MESBAT; | ||
733 | ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, | ||
734 | regval, TWL4030_BCI_BCICTL1); | ||
735 | if (ret) { | ||
736 | dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n", | ||
737 | TWL4030_BCI_BCICTL1); | ||
738 | goto err_i2c; | ||
739 | } | ||
740 | platform_set_drvdata(pdev, madc); | ||
741 | mutex_init(&madc->lock); | ||
742 | ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL, | ||
743 | twl4030_madc_threaded_irq_handler, | ||
744 | IRQF_TRIGGER_RISING, "twl4030_madc", madc); | ||
745 | if (ret) { | ||
746 | dev_dbg(&pdev->dev, "could not request irq\n"); | ||
747 | goto err_irq; | ||
748 | } | ||
749 | twl4030_madc = madc; | ||
750 | return 0; | ||
751 | err_irq: | ||
752 | platform_set_drvdata(pdev, NULL); | ||
753 | err_i2c: | ||
754 | twl4030_madc_set_current_generator(madc, 0, 0); | ||
755 | err_current_generator: | ||
756 | twl4030_madc_set_power(madc, 0); | ||
757 | err_power: | ||
758 | kfree(madc); | ||
759 | |||
760 | return ret; | ||
761 | } | ||
762 | |||
763 | static int __devexit twl4030_madc_remove(struct platform_device *pdev) | ||
764 | { | ||
765 | struct twl4030_madc_data *madc = platform_get_drvdata(pdev); | ||
766 | |||
767 | free_irq(platform_get_irq(pdev, 0), madc); | ||
768 | platform_set_drvdata(pdev, NULL); | ||
769 | twl4030_madc_set_current_generator(madc, 0, 0); | ||
770 | twl4030_madc_set_power(madc, 0); | ||
771 | kfree(madc); | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static struct platform_driver twl4030_madc_driver = { | ||
777 | .probe = twl4030_madc_probe, | ||
778 | .remove = __exit_p(twl4030_madc_remove), | ||
779 | .driver = { | ||
780 | .name = "twl4030_madc", | ||
781 | .owner = THIS_MODULE, | ||
782 | }, | ||
783 | }; | ||
784 | |||
785 | static int __init twl4030_madc_init(void) | ||
786 | { | ||
787 | return platform_driver_register(&twl4030_madc_driver); | ||
788 | } | ||
789 | |||
790 | module_init(twl4030_madc_init); | ||
791 | |||
792 | static void __exit twl4030_madc_exit(void) | ||
793 | { | ||
794 | platform_driver_unregister(&twl4030_madc_driver); | ||
795 | } | ||
796 | |||
797 | module_exit(twl4030_madc_exit); | ||
798 | |||
799 | MODULE_DESCRIPTION("TWL4030 ADC driver"); | ||
800 | MODULE_LICENSE("GPL"); | ||
801 | MODULE_AUTHOR("J Keerthy"); | ||
802 | MODULE_ALIAS("platform:twl4030_madc"); | ||
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 92b85e28a15e..38ffbd50a0d2 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c | |||
@@ -60,6 +60,7 @@ static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x | |||
60 | input_report_abs(idev, ABS_X, x); | 60 | input_report_abs(idev, ABS_X, x); |
61 | input_report_abs(idev, ABS_Y, y); | 61 | input_report_abs(idev, ABS_Y, y); |
62 | input_report_abs(idev, ABS_PRESSURE, pressure); | 62 | input_report_abs(idev, ABS_PRESSURE, pressure); |
63 | input_report_key(idev, BTN_TOUCH, 1); | ||
63 | input_sync(idev); | 64 | input_sync(idev); |
64 | } | 65 | } |
65 | 66 | ||
@@ -68,6 +69,7 @@ static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) | |||
68 | struct input_dev *idev = ts->idev; | 69 | struct input_dev *idev = ts->idev; |
69 | 70 | ||
70 | input_report_abs(idev, ABS_PRESSURE, 0); | 71 | input_report_abs(idev, ABS_PRESSURE, 0); |
72 | input_report_key(idev, BTN_TOUCH, 0); | ||
71 | input_sync(idev); | 73 | input_sync(idev); |
72 | } | 74 | } |
73 | 75 | ||
@@ -384,7 +386,8 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) | |||
384 | idev->open = ucb1x00_ts_open; | 386 | idev->open = ucb1x00_ts_open; |
385 | idev->close = ucb1x00_ts_close; | 387 | idev->close = ucb1x00_ts_close; |
386 | 388 | ||
387 | __set_bit(EV_ABS, idev->evbit); | 389 | idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); |
390 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
388 | 391 | ||
389 | input_set_drvdata(idev, ts); | 392 | input_set_drvdata(idev, ts); |
390 | 393 | ||
diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c index 348052aa5dbf..d698703dbd46 100644 --- a/drivers/mfd/vx855.c +++ b/drivers/mfd/vx855.c | |||
@@ -122,6 +122,7 @@ static struct pci_device_id vx855_pci_tbl[] = { | |||
122 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) }, | 122 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) }, |
123 | { 0, } | 123 | { 0, } |
124 | }; | 124 | }; |
125 | MODULE_DEVICE_TABLE(pci, vx855_pci_tbl); | ||
125 | 126 | ||
126 | static struct pci_driver vx855_pci_driver = { | 127 | static struct pci_driver vx855_pci_driver = { |
127 | .name = "vx855", | 128 | .name = "vx855", |
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index d2ecc2435736..529d65ba5353 100644 --- a/drivers/mfd/wl1273-core.c +++ b/drivers/mfd/wl1273-core.c | |||
@@ -38,7 +38,6 @@ static int wl1273_core_remove(struct i2c_client *client) | |||
38 | dev_dbg(&client->dev, "%s\n", __func__); | 38 | dev_dbg(&client->dev, "%s\n", __func__); |
39 | 39 | ||
40 | mfd_remove_devices(&client->dev); | 40 | mfd_remove_devices(&client->dev); |
41 | i2c_set_clientdata(client, NULL); | ||
42 | kfree(core); | 41 | kfree(core); |
43 | 42 | ||
44 | return 0; | 43 | return 0; |
@@ -79,8 +78,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, | |||
79 | 78 | ||
80 | cell = &core->cells[children]; | 79 | cell = &core->cells[children]; |
81 | cell->name = "wl1273_fm_radio"; | 80 | cell->name = "wl1273_fm_radio"; |
82 | cell->platform_data = &core; | 81 | cell->mfd_data = &core; |
83 | cell->data_size = sizeof(core); | ||
84 | children++; | 82 | children++; |
85 | 83 | ||
86 | if (pdata->children & WL1273_CODEC_CHILD) { | 84 | if (pdata->children & WL1273_CODEC_CHILD) { |
@@ -88,8 +86,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, | |||
88 | 86 | ||
89 | dev_dbg(&client->dev, "%s: Have codec.\n", __func__); | 87 | dev_dbg(&client->dev, "%s: Have codec.\n", __func__); |
90 | cell->name = "wl1273-codec"; | 88 | cell->name = "wl1273-codec"; |
91 | cell->platform_data = &core; | 89 | cell->mfd_data = &core; |
92 | cell->data_size = sizeof(core); | ||
93 | children++; | 90 | children++; |
94 | } | 91 | } |
95 | 92 | ||
@@ -104,7 +101,6 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, | |||
104 | return 0; | 101 | return 0; |
105 | 102 | ||
106 | err: | 103 | err: |
107 | i2c_set_clientdata(client, NULL); | ||
108 | pdata->free_resources(); | 104 | pdata->free_resources(); |
109 | kfree(core); | 105 | kfree(core); |
110 | 106 | ||
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c index 3853fa8e7cc2..a06cbc739716 100644 --- a/drivers/mfd/wm831x-i2c.c +++ b/drivers/mfd/wm831x-i2c.c | |||
@@ -51,17 +51,25 @@ static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg, | |||
51 | int bytes, void *src) | 51 | int bytes, void *src) |
52 | { | 52 | { |
53 | struct i2c_client *i2c = wm831x->control_data; | 53 | struct i2c_client *i2c = wm831x->control_data; |
54 | unsigned char msg[bytes + 2]; | 54 | struct i2c_msg xfer[2]; |
55 | int ret; | 55 | int ret; |
56 | 56 | ||
57 | reg = cpu_to_be16(reg); | 57 | reg = cpu_to_be16(reg); |
58 | memcpy(&msg[0], ®, 2); | ||
59 | memcpy(&msg[2], src, bytes); | ||
60 | 58 | ||
61 | ret = i2c_master_send(i2c, msg, bytes + 2); | 59 | xfer[0].addr = i2c->addr; |
60 | xfer[0].flags = 0; | ||
61 | xfer[0].len = 2; | ||
62 | xfer[0].buf = (char *)® | ||
63 | |||
64 | xfer[1].addr = i2c->addr; | ||
65 | xfer[1].flags = I2C_M_NOSTART; | ||
66 | xfer[1].len = bytes; | ||
67 | xfer[1].buf = (char *)src; | ||
68 | |||
69 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
62 | if (ret < 0) | 70 | if (ret < 0) |
63 | return ret; | 71 | return ret; |
64 | if (ret < bytes + 2) | 72 | if (ret != 2) |
65 | return -EIO; | 73 | return -EIO; |
66 | 74 | ||
67 | return 0; | 75 | return 0; |
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index f7192d438aab..a5cd17e18d09 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -26,15 +26,6 @@ | |||
26 | 26 | ||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | 28 | ||
29 | /* | ||
30 | * Since generic IRQs don't currently support interrupt controllers on | ||
31 | * interrupt driven buses we don't use genirq but instead provide an | ||
32 | * interface that looks very much like the standard ones. This leads | ||
33 | * to some bodges, including storing interrupt handler information in | ||
34 | * the static irq_data table we use to look up the data for individual | ||
35 | * interrupts, but hopefully won't last too long. | ||
36 | */ | ||
37 | |||
38 | struct wm831x_irq_data { | 29 | struct wm831x_irq_data { |
39 | int primary; | 30 | int primary; |
40 | int reg; | 31 | int reg; |
@@ -361,6 +352,10 @@ static void wm831x_irq_sync_unlock(struct irq_data *data) | |||
361 | /* If there's been a change in the mask write it back | 352 | /* If there's been a change in the mask write it back |
362 | * to the hardware. */ | 353 | * to the hardware. */ |
363 | if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) { | 354 | if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) { |
355 | dev_dbg(wm831x->dev, "IRQ mask sync: %x = %x\n", | ||
356 | WM831X_INTERRUPT_STATUS_1_MASK + i, | ||
357 | wm831x->irq_masks_cur[i]); | ||
358 | |||
364 | wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i]; | 359 | wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i]; |
365 | wm831x_reg_write(wm831x, | 360 | wm831x_reg_write(wm831x, |
366 | WM831X_INTERRUPT_STATUS_1_MASK + i, | 361 | WM831X_INTERRUPT_STATUS_1_MASK + i, |
@@ -371,7 +366,7 @@ static void wm831x_irq_sync_unlock(struct irq_data *data) | |||
371 | mutex_unlock(&wm831x->irq_lock); | 366 | mutex_unlock(&wm831x->irq_lock); |
372 | } | 367 | } |
373 | 368 | ||
374 | static void wm831x_irq_unmask(struct irq_data *data) | 369 | static void wm831x_irq_enable(struct irq_data *data) |
375 | { | 370 | { |
376 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); | 371 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); |
377 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, | 372 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, |
@@ -380,7 +375,7 @@ static void wm831x_irq_unmask(struct irq_data *data) | |||
380 | wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; | 375 | wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; |
381 | } | 376 | } |
382 | 377 | ||
383 | static void wm831x_irq_mask(struct irq_data *data) | 378 | static void wm831x_irq_disable(struct irq_data *data) |
384 | { | 379 | { |
385 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); | 380 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); |
386 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, | 381 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, |
@@ -426,8 +421,8 @@ static struct irq_chip wm831x_irq_chip = { | |||
426 | .name = "wm831x", | 421 | .name = "wm831x", |
427 | .irq_bus_lock = wm831x_irq_lock, | 422 | .irq_bus_lock = wm831x_irq_lock, |
428 | .irq_bus_sync_unlock = wm831x_irq_sync_unlock, | 423 | .irq_bus_sync_unlock = wm831x_irq_sync_unlock, |
429 | .irq_mask = wm831x_irq_mask, | 424 | .irq_disable = wm831x_irq_disable, |
430 | .irq_unmask = wm831x_irq_unmask, | 425 | .irq_enable = wm831x_irq_enable, |
431 | .irq_set_type = wm831x_irq_set_type, | 426 | .irq_set_type = wm831x_irq_set_type, |
432 | }; | 427 | }; |
433 | 428 | ||
@@ -449,6 +444,18 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
449 | goto out; | 444 | goto out; |
450 | } | 445 | } |
451 | 446 | ||
447 | /* The touch interrupts are visible in the primary register as | ||
448 | * an optimisation; open code this to avoid complicating the | ||
449 | * main handling loop and so we can also skip iterating the | ||
450 | * descriptors. | ||
451 | */ | ||
452 | if (primary & WM831X_TCHPD_INT) | ||
453 | handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD); | ||
454 | if (primary & WM831X_TCHDATA_INT) | ||
455 | handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA); | ||
456 | if (primary & (WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT)) | ||
457 | goto out; | ||
458 | |||
452 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { | 459 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { |
453 | int offset = wm831x_irqs[i].reg - 1; | 460 | int offset = wm831x_irqs[i].reg - 1; |
454 | 461 | ||
@@ -481,6 +488,9 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
481 | } | 488 | } |
482 | 489 | ||
483 | out: | 490 | out: |
491 | /* Touchscreen interrupts are handled specially in the driver */ | ||
492 | status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT); | ||
493 | |||
484 | for (i = 0; i < ARRAY_SIZE(status_regs); i++) { | 494 | for (i = 0; i < ARRAY_SIZE(status_regs); i++) { |
485 | if (status_regs[i]) | 495 | if (status_regs[i]) |
486 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i, | 496 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i, |
@@ -517,6 +527,14 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
517 | return 0; | 527 | return 0; |
518 | } | 528 | } |
519 | 529 | ||
530 | if (pdata->irq_cmos) | ||
531 | i = 0; | ||
532 | else | ||
533 | i = WM831X_IRQ_OD; | ||
534 | |||
535 | wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG, | ||
536 | WM831X_IRQ_OD, i); | ||
537 | |||
520 | /* Try to flag /IRQ as a wake source; there are a number of | 538 | /* Try to flag /IRQ as a wake source; there are a number of |
521 | * unconditional wake sources in the PMIC so this isn't | 539 | * unconditional wake sources in the PMIC so this isn't |
522 | * conditional but we don't actually care *too* much if it | 540 | * conditional but we don't actually care *too* much if it |
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index 0a8f772be88c..eed8e4f7a5a1 100644 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/pm.h> | ||
17 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
18 | 19 | ||
19 | #include <linux/mfd/wm831x/core.h> | 20 | #include <linux/mfd/wm831x/core.h> |
@@ -113,22 +114,27 @@ static int __devexit wm831x_spi_remove(struct spi_device *spi) | |||
113 | return 0; | 114 | return 0; |
114 | } | 115 | } |
115 | 116 | ||
116 | static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m) | 117 | static int wm831x_spi_suspend(struct device *dev) |
117 | { | 118 | { |
118 | struct wm831x *wm831x = dev_get_drvdata(&spi->dev); | 119 | struct wm831x *wm831x = dev_get_drvdata(dev); |
119 | 120 | ||
120 | return wm831x_device_suspend(wm831x); | 121 | return wm831x_device_suspend(wm831x); |
121 | } | 122 | } |
122 | 123 | ||
124 | static const struct dev_pm_ops wm831x_spi_pm = { | ||
125 | .freeze = wm831x_spi_suspend, | ||
126 | .suspend = wm831x_spi_suspend, | ||
127 | }; | ||
128 | |||
123 | static struct spi_driver wm8310_spi_driver = { | 129 | static struct spi_driver wm8310_spi_driver = { |
124 | .driver = { | 130 | .driver = { |
125 | .name = "wm8310", | 131 | .name = "wm8310", |
126 | .bus = &spi_bus_type, | 132 | .bus = &spi_bus_type, |
127 | .owner = THIS_MODULE, | 133 | .owner = THIS_MODULE, |
134 | .pm = &wm831x_spi_pm, | ||
128 | }, | 135 | }, |
129 | .probe = wm831x_spi_probe, | 136 | .probe = wm831x_spi_probe, |
130 | .remove = __devexit_p(wm831x_spi_remove), | 137 | .remove = __devexit_p(wm831x_spi_remove), |
131 | .suspend = wm831x_spi_suspend, | ||
132 | }; | 138 | }; |
133 | 139 | ||
134 | static struct spi_driver wm8311_spi_driver = { | 140 | static struct spi_driver wm8311_spi_driver = { |
@@ -136,10 +142,10 @@ static struct spi_driver wm8311_spi_driver = { | |||
136 | .name = "wm8311", | 142 | .name = "wm8311", |
137 | .bus = &spi_bus_type, | 143 | .bus = &spi_bus_type, |
138 | .owner = THIS_MODULE, | 144 | .owner = THIS_MODULE, |
145 | .pm = &wm831x_spi_pm, | ||
139 | }, | 146 | }, |
140 | .probe = wm831x_spi_probe, | 147 | .probe = wm831x_spi_probe, |
141 | .remove = __devexit_p(wm831x_spi_remove), | 148 | .remove = __devexit_p(wm831x_spi_remove), |
142 | .suspend = wm831x_spi_suspend, | ||
143 | }; | 149 | }; |
144 | 150 | ||
145 | static struct spi_driver wm8312_spi_driver = { | 151 | static struct spi_driver wm8312_spi_driver = { |
@@ -147,10 +153,10 @@ static struct spi_driver wm8312_spi_driver = { | |||
147 | .name = "wm8312", | 153 | .name = "wm8312", |
148 | .bus = &spi_bus_type, | 154 | .bus = &spi_bus_type, |
149 | .owner = THIS_MODULE, | 155 | .owner = THIS_MODULE, |
156 | .pm = &wm831x_spi_pm, | ||
150 | }, | 157 | }, |
151 | .probe = wm831x_spi_probe, | 158 | .probe = wm831x_spi_probe, |
152 | .remove = __devexit_p(wm831x_spi_remove), | 159 | .remove = __devexit_p(wm831x_spi_remove), |
153 | .suspend = wm831x_spi_suspend, | ||
154 | }; | 160 | }; |
155 | 161 | ||
156 | static struct spi_driver wm8320_spi_driver = { | 162 | static struct spi_driver wm8320_spi_driver = { |
@@ -158,10 +164,10 @@ static struct spi_driver wm8320_spi_driver = { | |||
158 | .name = "wm8320", | 164 | .name = "wm8320", |
159 | .bus = &spi_bus_type, | 165 | .bus = &spi_bus_type, |
160 | .owner = THIS_MODULE, | 166 | .owner = THIS_MODULE, |
167 | .pm = &wm831x_spi_pm, | ||
161 | }, | 168 | }, |
162 | .probe = wm831x_spi_probe, | 169 | .probe = wm831x_spi_probe, |
163 | .remove = __devexit_p(wm831x_spi_remove), | 170 | .remove = __devexit_p(wm831x_spi_remove), |
164 | .suspend = wm831x_spi_suspend, | ||
165 | }; | 171 | }; |
166 | 172 | ||
167 | static struct spi_driver wm8321_spi_driver = { | 173 | static struct spi_driver wm8321_spi_driver = { |
@@ -169,10 +175,10 @@ static struct spi_driver wm8321_spi_driver = { | |||
169 | .name = "wm8321", | 175 | .name = "wm8321", |
170 | .bus = &spi_bus_type, | 176 | .bus = &spi_bus_type, |
171 | .owner = THIS_MODULE, | 177 | .owner = THIS_MODULE, |
178 | .pm = &wm831x_spi_pm, | ||
172 | }, | 179 | }, |
173 | .probe = wm831x_spi_probe, | 180 | .probe = wm831x_spi_probe, |
174 | .remove = __devexit_p(wm831x_spi_remove), | 181 | .remove = __devexit_p(wm831x_spi_remove), |
175 | .suspend = wm831x_spi_suspend, | ||
176 | }; | 182 | }; |
177 | 183 | ||
178 | static struct spi_driver wm8325_spi_driver = { | 184 | static struct spi_driver wm8325_spi_driver = { |
@@ -180,10 +186,10 @@ static struct spi_driver wm8325_spi_driver = { | |||
180 | .name = "wm8325", | 186 | .name = "wm8325", |
181 | .bus = &spi_bus_type, | 187 | .bus = &spi_bus_type, |
182 | .owner = THIS_MODULE, | 188 | .owner = THIS_MODULE, |
189 | .pm = &wm831x_spi_pm, | ||
183 | }, | 190 | }, |
184 | .probe = wm831x_spi_probe, | 191 | .probe = wm831x_spi_probe, |
185 | .remove = __devexit_p(wm831x_spi_remove), | 192 | .remove = __devexit_p(wm831x_spi_remove), |
186 | .suspend = wm831x_spi_suspend, | ||
187 | }; | 193 | }; |
188 | 194 | ||
189 | static struct spi_driver wm8326_spi_driver = { | 195 | static struct spi_driver wm8326_spi_driver = { |
@@ -191,10 +197,10 @@ static struct spi_driver wm8326_spi_driver = { | |||
191 | .name = "wm8326", | 197 | .name = "wm8326", |
192 | .bus = &spi_bus_type, | 198 | .bus = &spi_bus_type, |
193 | .owner = THIS_MODULE, | 199 | .owner = THIS_MODULE, |
200 | .pm = &wm831x_spi_pm, | ||
194 | }, | 201 | }, |
195 | .probe = wm831x_spi_probe, | 202 | .probe = wm831x_spi_probe, |
196 | .remove = __devexit_p(wm831x_spi_remove), | 203 | .remove = __devexit_p(wm831x_spi_remove), |
197 | .suspend = wm831x_spi_suspend, | ||
198 | }; | 204 | }; |
199 | 205 | ||
200 | static int __init wm831x_spi_init(void) | 206 | static int __init wm831x_spi_init(void) |
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 1bfef4846b07..3a6e78cb0384 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c | |||
@@ -245,7 +245,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) | |||
245 | { | 245 | { |
246 | struct mfd_cell cell = { | 246 | struct mfd_cell cell = { |
247 | .name = "wm8400-codec", | 247 | .name = "wm8400-codec", |
248 | .driver_data = wm8400, | 248 | .mfd_data = wm8400, |
249 | }; | 249 | }; |
250 | 250 | ||
251 | return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); | 251 | return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index f4016a075fd6..e198d40292e7 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -40,10 +40,8 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, | |||
40 | return ret; | 40 | return ret; |
41 | 41 | ||
42 | for (i = 0; i < bytes / 2; i++) { | 42 | for (i = 0; i < bytes / 2; i++) { |
43 | buf[i] = be16_to_cpu(buf[i]); | ||
44 | |||
45 | dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n", | 43 | dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n", |
46 | buf[i], reg + i, reg + i); | 44 | be16_to_cpu(buf[i]), reg + i, reg + i); |
47 | } | 45 | } |
48 | 46 | ||
49 | return 0; | 47 | return 0; |
@@ -69,7 +67,7 @@ int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg) | |||
69 | if (ret < 0) | 67 | if (ret < 0) |
70 | return ret; | 68 | return ret; |
71 | else | 69 | else |
72 | return val; | 70 | return be16_to_cpu(val); |
73 | } | 71 | } |
74 | EXPORT_SYMBOL_GPL(wm8994_reg_read); | 72 | EXPORT_SYMBOL_GPL(wm8994_reg_read); |
75 | 73 | ||
@@ -79,7 +77,7 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read); | |||
79 | * @wm8994: Device to read from | 77 | * @wm8994: Device to read from |
80 | * @reg: First register | 78 | * @reg: First register |
81 | * @count: Number of registers | 79 | * @count: Number of registers |
82 | * @buf: Buffer to fill. | 80 | * @buf: Buffer to fill. The data will be returned big endian. |
83 | */ | 81 | */ |
84 | int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, | 82 | int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, |
85 | int count, u16 *buf) | 83 | int count, u16 *buf) |
@@ -97,9 +95,9 @@ int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, | |||
97 | EXPORT_SYMBOL_GPL(wm8994_bulk_read); | 95 | EXPORT_SYMBOL_GPL(wm8994_bulk_read); |
98 | 96 | ||
99 | static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, | 97 | static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, |
100 | int bytes, void *src) | 98 | int bytes, const void *src) |
101 | { | 99 | { |
102 | u16 *buf = src; | 100 | const u16 *buf = src; |
103 | int i; | 101 | int i; |
104 | 102 | ||
105 | BUG_ON(bytes % 2); | 103 | BUG_ON(bytes % 2); |
@@ -107,9 +105,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, | |||
107 | 105 | ||
108 | for (i = 0; i < bytes / 2; i++) { | 106 | for (i = 0; i < bytes / 2; i++) { |
109 | dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n", | 107 | dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n", |
110 | buf[i], reg + i, reg + i); | 108 | be16_to_cpu(buf[i]), reg + i, reg + i); |
111 | |||
112 | buf[i] = cpu_to_be16(buf[i]); | ||
113 | } | 109 | } |
114 | 110 | ||
115 | return wm8994->write_dev(wm8994, reg, bytes, src); | 111 | return wm8994->write_dev(wm8994, reg, bytes, src); |
@@ -127,6 +123,8 @@ int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, | |||
127 | { | 123 | { |
128 | int ret; | 124 | int ret; |
129 | 125 | ||
126 | val = cpu_to_be16(val); | ||
127 | |||
130 | mutex_lock(&wm8994->io_lock); | 128 | mutex_lock(&wm8994->io_lock); |
131 | 129 | ||
132 | ret = wm8994_write(wm8994, reg, 2, &val); | 130 | ret = wm8994_write(wm8994, reg, 2, &val); |
@@ -138,6 +136,29 @@ int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, | |||
138 | EXPORT_SYMBOL_GPL(wm8994_reg_write); | 136 | EXPORT_SYMBOL_GPL(wm8994_reg_write); |
139 | 137 | ||
140 | /** | 138 | /** |
139 | * wm8994_bulk_write: Write multiple WM8994 registers | ||
140 | * | ||
141 | * @wm8994: Device to write to | ||
142 | * @reg: First register | ||
143 | * @count: Number of registers | ||
144 | * @buf: Buffer to write from. Data must be big-endian formatted. | ||
145 | */ | ||
146 | int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg, | ||
147 | int count, const u16 *buf) | ||
148 | { | ||
149 | int ret; | ||
150 | |||
151 | mutex_lock(&wm8994->io_lock); | ||
152 | |||
153 | ret = wm8994_write(wm8994, reg, count * 2, buf); | ||
154 | |||
155 | mutex_unlock(&wm8994->io_lock); | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(wm8994_bulk_write); | ||
160 | |||
161 | /** | ||
141 | * wm8994_set_bits: Set the value of a bitfield in a WM8994 register | 162 | * wm8994_set_bits: Set the value of a bitfield in a WM8994 register |
142 | * | 163 | * |
143 | * @wm8994: Device to write to. | 164 | * @wm8994: Device to write to. |
@@ -157,9 +178,13 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, | |||
157 | if (ret < 0) | 178 | if (ret < 0) |
158 | goto out; | 179 | goto out; |
159 | 180 | ||
181 | r = be16_to_cpu(r); | ||
182 | |||
160 | r &= ~mask; | 183 | r &= ~mask; |
161 | r |= val; | 184 | r |= val; |
162 | 185 | ||
186 | r = cpu_to_be16(r); | ||
187 | |||
163 | ret = wm8994_write(wm8994, reg, 2, &r); | 188 | ret = wm8994_write(wm8994, reg, 2, &r); |
164 | 189 | ||
165 | out: | 190 | out: |
@@ -271,6 +296,11 @@ static int wm8994_suspend(struct device *dev) | |||
271 | if (ret < 0) | 296 | if (ret < 0) |
272 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); | 297 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); |
273 | 298 | ||
299 | /* Explicitly put the device into reset in case regulators | ||
300 | * don't get disabled in order to ensure consistent restart. | ||
301 | */ | ||
302 | wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994); | ||
303 | |||
274 | wm8994->suspended = true; | 304 | wm8994->suspended = true; |
275 | 305 | ||
276 | ret = regulator_bulk_disable(wm8994->num_supplies, | 306 | ret = regulator_bulk_disable(wm8994->num_supplies, |
@@ -552,25 +582,29 @@ static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg, | |||
552 | return 0; | 582 | return 0; |
553 | } | 583 | } |
554 | 584 | ||
555 | /* Currently we allocate the write buffer on the stack; this is OK for | ||
556 | * small writes - if we need to do large writes this will need to be | ||
557 | * revised. | ||
558 | */ | ||
559 | static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg, | 585 | static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg, |
560 | int bytes, void *src) | 586 | int bytes, const void *src) |
561 | { | 587 | { |
562 | struct i2c_client *i2c = wm8994->control_data; | 588 | struct i2c_client *i2c = wm8994->control_data; |
563 | unsigned char msg[bytes + 2]; | 589 | struct i2c_msg xfer[2]; |
564 | int ret; | 590 | int ret; |
565 | 591 | ||
566 | reg = cpu_to_be16(reg); | 592 | reg = cpu_to_be16(reg); |
567 | memcpy(&msg[0], ®, 2); | ||
568 | memcpy(&msg[2], src, bytes); | ||
569 | 593 | ||
570 | ret = i2c_master_send(i2c, msg, bytes + 2); | 594 | xfer[0].addr = i2c->addr; |
595 | xfer[0].flags = 0; | ||
596 | xfer[0].len = 2; | ||
597 | xfer[0].buf = (char *)® | ||
598 | |||
599 | xfer[1].addr = i2c->addr; | ||
600 | xfer[1].flags = I2C_M_NOSTART; | ||
601 | xfer[1].len = bytes; | ||
602 | xfer[1].buf = (char *)src; | ||
603 | |||
604 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
571 | if (ret < 0) | 605 | if (ret < 0) |
572 | return ret; | 606 | return ret; |
573 | if (ret < bytes + 2) | 607 | if (ret != 2) |
574 | return -EIO; | 608 | return -EIO; |
575 | 609 | ||
576 | return 0; | 610 | return 0; |
@@ -612,7 +646,8 @@ static const struct i2c_device_id wm8994_i2c_id[] = { | |||
612 | }; | 646 | }; |
613 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); | 647 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); |
614 | 648 | ||
615 | UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, NULL); | 649 | static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, |
650 | NULL); | ||
616 | 651 | ||
617 | static struct i2c_driver wm8994_i2c_driver = { | 652 | static struct i2c_driver wm8994_i2c_driver = { |
618 | .driver = { | 653 | .driver = { |
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c index 29e8faf9c01c..1e3bf4a2ff8e 100644 --- a/drivers/mfd/wm8994-irq.c +++ b/drivers/mfd/wm8994-irq.c | |||
@@ -182,7 +182,7 @@ static void wm8994_irq_sync_unlock(struct irq_data *data) | |||
182 | mutex_unlock(&wm8994->irq_lock); | 182 | mutex_unlock(&wm8994->irq_lock); |
183 | } | 183 | } |
184 | 184 | ||
185 | static void wm8994_irq_unmask(struct irq_data *data) | 185 | static void wm8994_irq_enable(struct irq_data *data) |
186 | { | 186 | { |
187 | struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data); | 187 | struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data); |
188 | struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, | 188 | struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, |
@@ -191,7 +191,7 @@ static void wm8994_irq_unmask(struct irq_data *data) | |||
191 | wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; | 191 | wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; |
192 | } | 192 | } |
193 | 193 | ||
194 | static void wm8994_irq_mask(struct irq_data *data) | 194 | static void wm8994_irq_disable(struct irq_data *data) |
195 | { | 195 | { |
196 | struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data); | 196 | struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data); |
197 | struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, | 197 | struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, |
@@ -204,8 +204,8 @@ static struct irq_chip wm8994_irq_chip = { | |||
204 | .name = "wm8994", | 204 | .name = "wm8994", |
205 | .irq_bus_lock = wm8994_irq_lock, | 205 | .irq_bus_lock = wm8994_irq_lock, |
206 | .irq_bus_sync_unlock = wm8994_irq_sync_unlock, | 206 | .irq_bus_sync_unlock = wm8994_irq_sync_unlock, |
207 | .irq_mask = wm8994_irq_mask, | 207 | .irq_disable = wm8994_irq_disable, |
208 | .irq_unmask = wm8994_irq_unmask, | 208 | .irq_enable = wm8994_irq_enable, |
209 | }; | 209 | }; |
210 | 210 | ||
211 | /* The processing of the primary interrupt occurs in a thread so that | 211 | /* The processing of the primary interrupt occurs in a thread so that |
@@ -225,9 +225,11 @@ static irqreturn_t wm8994_irq_thread(int irq, void *data) | |||
225 | return IRQ_NONE; | 225 | return IRQ_NONE; |
226 | } | 226 | } |
227 | 227 | ||
228 | /* Apply masking */ | 228 | /* Bit swap and apply masking */ |
229 | for (i = 0; i < WM8994_NUM_IRQ_REGS; i++) | 229 | for (i = 0; i < WM8994_NUM_IRQ_REGS; i++) { |
230 | status[i] = be16_to_cpu(status[i]); | ||
230 | status[i] &= ~wm8994->irq_masks_cur[i]; | 231 | status[i] &= ~wm8994->irq_masks_cur[i]; |
232 | } | ||
231 | 233 | ||
232 | /* Report */ | 234 | /* Report */ |
233 | for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) { | 235 | for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) { |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index ac52eb65395e..ab1adeabdd22 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
@@ -303,8 +303,7 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) | |||
303 | 303 | ||
304 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | 304 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) |
305 | { | 305 | { |
306 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 306 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
307 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
308 | 307 | ||
309 | /* | 308 | /* |
310 | * Testing on sh-mobile showed that SDIO IRQs are unmasked when | 309 | * Testing on sh-mobile showed that SDIO IRQs are unmasked when |
@@ -327,8 +326,7 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | |||
327 | 326 | ||
328 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) | 327 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) |
329 | { | 328 | { |
330 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 329 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
331 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
332 | 330 | ||
333 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | | 331 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | |
334 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); | 332 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); |
@@ -669,8 +667,7 @@ out: | |||
669 | static irqreturn_t tmio_mmc_irq(int irq, void *devid) | 667 | static irqreturn_t tmio_mmc_irq(int irq, void *devid) |
670 | { | 668 | { |
671 | struct tmio_mmc_host *host = devid; | 669 | struct tmio_mmc_host *host = devid; |
672 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 670 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
673 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
674 | unsigned int ireg, irq_mask, status; | 671 | unsigned int ireg, irq_mask, status; |
675 | unsigned int sdio_ireg, sdio_irq_mask, sdio_status; | 672 | unsigned int sdio_ireg, sdio_irq_mask, sdio_status; |
676 | 673 | ||
@@ -799,8 +796,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) | |||
799 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; | 796 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
800 | struct dma_async_tx_descriptor *desc = NULL; | 797 | struct dma_async_tx_descriptor *desc = NULL; |
801 | struct dma_chan *chan = host->chan_rx; | 798 | struct dma_chan *chan = host->chan_rx; |
802 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 799 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
803 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
804 | dma_cookie_t cookie; | 800 | dma_cookie_t cookie; |
805 | int ret, i; | 801 | int ret, i; |
806 | bool aligned = true, multiple = true; | 802 | bool aligned = true, multiple = true; |
@@ -869,8 +865,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) | |||
869 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; | 865 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
870 | struct dma_async_tx_descriptor *desc = NULL; | 866 | struct dma_async_tx_descriptor *desc = NULL; |
871 | struct dma_chan *chan = host->chan_tx; | 867 | struct dma_chan *chan = host->chan_tx; |
872 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 868 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
873 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
874 | dma_cookie_t cookie; | 869 | dma_cookie_t cookie; |
875 | int ret, i; | 870 | int ret, i; |
876 | bool aligned = true, multiple = true; | 871 | bool aligned = true, multiple = true; |
@@ -1063,8 +1058,7 @@ static void tmio_mmc_release_dma(struct tmio_mmc_host *host) | |||
1063 | static int tmio_mmc_start_data(struct tmio_mmc_host *host, | 1058 | static int tmio_mmc_start_data(struct tmio_mmc_host *host, |
1064 | struct mmc_data *data) | 1059 | struct mmc_data *data) |
1065 | { | 1060 | { |
1066 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 1061 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
1067 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
1068 | 1062 | ||
1069 | pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n", | 1063 | pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n", |
1070 | data->blksz, data->blocks); | 1064 | data->blksz, data->blocks); |
@@ -1169,8 +1163,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1169 | static int tmio_mmc_get_ro(struct mmc_host *mmc) | 1163 | static int tmio_mmc_get_ro(struct mmc_host *mmc) |
1170 | { | 1164 | { |
1171 | struct tmio_mmc_host *host = mmc_priv(mmc); | 1165 | struct tmio_mmc_host *host = mmc_priv(mmc); |
1172 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 1166 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
1173 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
1174 | 1167 | ||
1175 | return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || | 1168 | return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || |
1176 | (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1; | 1169 | (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1; |
@@ -1179,8 +1172,7 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) | |||
1179 | static int tmio_mmc_get_cd(struct mmc_host *mmc) | 1172 | static int tmio_mmc_get_cd(struct mmc_host *mmc) |
1180 | { | 1173 | { |
1181 | struct tmio_mmc_host *host = mmc_priv(mmc); | 1174 | struct tmio_mmc_host *host = mmc_priv(mmc); |
1182 | struct mfd_cell *cell = host->pdev->dev.platform_data; | 1175 | struct tmio_mmc_data *pdata = mfd_get_data(host->pdev); |
1183 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
1184 | 1176 | ||
1185 | if (!pdata->get_cd) | 1177 | if (!pdata->get_cd) |
1186 | return -ENOSYS; | 1178 | return -ENOSYS; |
@@ -1199,7 +1191,7 @@ static const struct mmc_host_ops tmio_mmc_ops = { | |||
1199 | #ifdef CONFIG_PM | 1191 | #ifdef CONFIG_PM |
1200 | static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) | 1192 | static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) |
1201 | { | 1193 | { |
1202 | struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; | 1194 | const struct mfd_cell *cell = mfd_get_cell(dev); |
1203 | struct mmc_host *mmc = platform_get_drvdata(dev); | 1195 | struct mmc_host *mmc = platform_get_drvdata(dev); |
1204 | int ret; | 1196 | int ret; |
1205 | 1197 | ||
@@ -1214,7 +1206,7 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) | |||
1214 | 1206 | ||
1215 | static int tmio_mmc_resume(struct platform_device *dev) | 1207 | static int tmio_mmc_resume(struct platform_device *dev) |
1216 | { | 1208 | { |
1217 | struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; | 1209 | const struct mfd_cell *cell = mfd_get_cell(dev); |
1218 | struct mmc_host *mmc = platform_get_drvdata(dev); | 1210 | struct mmc_host *mmc = platform_get_drvdata(dev); |
1219 | int ret = 0; | 1211 | int ret = 0; |
1220 | 1212 | ||
@@ -1237,7 +1229,7 @@ out: | |||
1237 | 1229 | ||
1238 | static int __devinit tmio_mmc_probe(struct platform_device *dev) | 1230 | static int __devinit tmio_mmc_probe(struct platform_device *dev) |
1239 | { | 1231 | { |
1240 | struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; | 1232 | const struct mfd_cell *cell = mfd_get_cell(dev); |
1241 | struct tmio_mmc_data *pdata; | 1233 | struct tmio_mmc_data *pdata; |
1242 | struct resource *res_ctl; | 1234 | struct resource *res_ctl; |
1243 | struct tmio_mmc_host *host; | 1235 | struct tmio_mmc_host *host; |
@@ -1252,7 +1244,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) | |||
1252 | if (!res_ctl) | 1244 | if (!res_ctl) |
1253 | goto out; | 1245 | goto out; |
1254 | 1246 | ||
1255 | pdata = cell->driver_data; | 1247 | pdata = mfd_get_data(dev); |
1256 | if (!pdata || !pdata->hclk) | 1248 | if (!pdata || !pdata->hclk) |
1257 | goto out; | 1249 | goto out; |
1258 | 1250 | ||
@@ -1352,7 +1344,7 @@ out: | |||
1352 | 1344 | ||
1353 | static int __devexit tmio_mmc_remove(struct platform_device *dev) | 1345 | static int __devexit tmio_mmc_remove(struct platform_device *dev) |
1354 | { | 1346 | { |
1355 | struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; | 1347 | const struct mfd_cell *cell = mfd_get_cell(dev); |
1356 | struct mmc_host *mmc = platform_get_drvdata(dev); | 1348 | struct mmc_host *mmc = platform_get_drvdata(dev); |
1357 | 1349 | ||
1358 | platform_set_drvdata(dev, NULL); | 1350 | platform_set_drvdata(dev, NULL); |
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index 3041d1f7ae3f..38fb16771f85 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c | |||
@@ -319,7 +319,7 @@ static int tmio_nand_correct_data(struct mtd_info *mtd, unsigned char *buf, | |||
319 | 319 | ||
320 | static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio) | 320 | static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio) |
321 | { | 321 | { |
322 | struct mfd_cell *cell = dev_get_platdata(&dev->dev); | 322 | const struct mfd_cell *cell = mfd_get_cell(dev); |
323 | int ret; | 323 | int ret; |
324 | 324 | ||
325 | if (cell->enable) { | 325 | if (cell->enable) { |
@@ -363,7 +363,7 @@ static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio) | |||
363 | 363 | ||
364 | static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) | 364 | static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) |
365 | { | 365 | { |
366 | struct mfd_cell *cell = dev_get_platdata(&dev->dev); | 366 | const struct mfd_cell *cell = mfd_get_cell(dev); |
367 | 367 | ||
368 | tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE); | 368 | tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE); |
369 | if (cell->disable) | 369 | if (cell->disable) |
@@ -372,8 +372,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) | |||
372 | 372 | ||
373 | static int tmio_probe(struct platform_device *dev) | 373 | static int tmio_probe(struct platform_device *dev) |
374 | { | 374 | { |
375 | struct mfd_cell *cell = dev_get_platdata(&dev->dev); | 375 | struct tmio_nand_data *data = mfd_get_data(dev); |
376 | struct tmio_nand_data *data = cell->driver_data; | ||
377 | struct resource *fcr = platform_get_resource(dev, | 376 | struct resource *fcr = platform_get_resource(dev, |
378 | IORESOURCE_MEM, 0); | 377 | IORESOURCE_MEM, 0); |
379 | struct resource *ccr = platform_get_resource(dev, | 378 | struct resource *ccr = platform_get_resource(dev, |
@@ -516,7 +515,7 @@ static int tmio_remove(struct platform_device *dev) | |||
516 | #ifdef CONFIG_PM | 515 | #ifdef CONFIG_PM |
517 | static int tmio_suspend(struct platform_device *dev, pm_message_t state) | 516 | static int tmio_suspend(struct platform_device *dev, pm_message_t state) |
518 | { | 517 | { |
519 | struct mfd_cell *cell = dev_get_platdata(&dev->dev); | 518 | const struct mfd_cell *cell = mfd_get_cell(dev); |
520 | 519 | ||
521 | if (cell->suspend) | 520 | if (cell->suspend) |
522 | cell->suspend(dev); | 521 | cell->suspend(dev); |
@@ -527,7 +526,7 @@ static int tmio_suspend(struct platform_device *dev, pm_message_t state) | |||
527 | 526 | ||
528 | static int tmio_resume(struct platform_device *dev) | 527 | static int tmio_resume(struct platform_device *dev) |
529 | { | 528 | { |
530 | struct mfd_cell *cell = dev_get_platdata(&dev->dev); | 529 | const struct mfd_cell *cell = mfd_get_cell(dev); |
531 | 530 | ||
532 | /* FIXME - is this required or merely another attack of the broken | 531 | /* FIXME - is this required or merely another attack of the broken |
533 | * SHARP platform? Looks suspicious. | 532 | * SHARP platform? Looks suspicious. |
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 366f5cc050ae..102b16c6cc97 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/mfd/core.h> | ||
18 | 19 | ||
19 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
20 | #include <linux/can.h> | 21 | #include <linux/can.h> |
@@ -1643,7 +1644,7 @@ static int __devinit ican3_probe(struct platform_device *pdev) | |||
1643 | struct device *dev; | 1644 | struct device *dev; |
1644 | int ret; | 1645 | int ret; |
1645 | 1646 | ||
1646 | pdata = pdev->dev.platform_data; | 1647 | pdata = mfd_get_data(pdev); |
1647 | if (!pdata) | 1648 | if (!pdata) |
1648 | return -ENXIO; | 1649 | return -ENXIO; |
1649 | 1650 | ||
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index 928b2b83cef5..efd44afeae83 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/mfd/core.h> | ||
29 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
30 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
31 | #include <linux/ethtool.h> | 32 | #include <linux/ethtool.h> |
@@ -1145,7 +1146,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev) | |||
1145 | struct resource *iomem; | 1146 | struct resource *iomem; |
1146 | struct net_device *netdev; | 1147 | struct net_device *netdev; |
1147 | struct ks8842_adapter *adapter; | 1148 | struct ks8842_adapter *adapter; |
1148 | struct ks8842_platform_data *pdata = pdev->dev.platform_data; | 1149 | struct ks8842_platform_data *pdata = mfd_get_data(pdev); |
1149 | u16 id; | 1150 | u16 id; |
1150 | unsigned i; | 1151 | unsigned i; |
1151 | 1152 | ||
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c index 02414db6a94c..763f894ed188 100644 --- a/drivers/power/jz4740-battery.c +++ b/drivers/power/jz4740-battery.c | |||
@@ -39,7 +39,7 @@ struct jz_battery { | |||
39 | int irq; | 39 | int irq; |
40 | int charge_irq; | 40 | int charge_irq; |
41 | 41 | ||
42 | struct mfd_cell *cell; | 42 | const struct mfd_cell *cell; |
43 | 43 | ||
44 | int status; | 44 | int status; |
45 | long voltage; | 45 | long voltage; |
@@ -258,7 +258,7 @@ static int __devinit jz_battery_probe(struct platform_device *pdev) | |||
258 | return -ENOMEM; | 258 | return -ENOMEM; |
259 | } | 259 | } |
260 | 260 | ||
261 | jz_battery->cell = pdev->dev.platform_data; | 261 | jz_battery->cell = mfd_get_cell(pdev); |
262 | 262 | ||
263 | jz_battery->irq = platform_get_irq(pdev, 0); | 263 | jz_battery->irq = platform_get_irq(pdev, 0); |
264 | if (jz_battery->irq < 0) { | 264 | if (jz_battery->irq < 0) { |
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index dd6308499bd4..859251250b55 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/regulator/driver.h> | 16 | #include <linux/regulator/driver.h> |
17 | #include <linux/regulator/machine.h> | 17 | #include <linux/regulator/machine.h> |
18 | #include <linux/mfd/core.h> | ||
18 | #include <linux/mfd/88pm860x.h> | 19 | #include <linux/mfd/88pm860x.h> |
19 | 20 | ||
20 | struct pm8607_regulator_info { | 21 | struct pm8607_regulator_info { |
@@ -394,47 +395,48 @@ static struct pm8607_regulator_info pm8607_regulator_info[] = { | |||
394 | PM8607_LDO(14, LDO14, 0, 4, SUPPLIES_EN12, 6), | 395 | PM8607_LDO(14, LDO14, 0, 4, SUPPLIES_EN12, 6), |
395 | }; | 396 | }; |
396 | 397 | ||
397 | static inline struct pm8607_regulator_info *find_regulator_info(int id) | 398 | static int __devinit pm8607_regulator_probe(struct platform_device *pdev) |
398 | { | 399 | { |
399 | struct pm8607_regulator_info *info; | 400 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
401 | struct pm8607_regulator_info *info = NULL; | ||
402 | struct regulator_init_data *pdata; | ||
403 | struct mfd_cell *cell; | ||
400 | int i; | 404 | int i; |
401 | 405 | ||
406 | cell = pdev->dev.platform_data; | ||
407 | if (cell == NULL) | ||
408 | return -ENODEV; | ||
409 | pdata = cell->mfd_data; | ||
410 | if (pdata == NULL) | ||
411 | return -EINVAL; | ||
412 | |||
402 | for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { | 413 | for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { |
403 | info = &pm8607_regulator_info[i]; | 414 | info = &pm8607_regulator_info[i]; |
404 | if (info->desc.id == id) | 415 | if (!strcmp(info->desc.name, pdata->constraints.name)) |
405 | return info; | 416 | break; |
406 | } | 417 | } |
407 | return NULL; | 418 | if (i > ARRAY_SIZE(pm8607_regulator_info)) { |
408 | } | 419 | dev_err(&pdev->dev, "Failed to find regulator %s\n", |
409 | 420 | pdata->constraints.name); | |
410 | static int __devinit pm8607_regulator_probe(struct platform_device *pdev) | ||
411 | { | ||
412 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
413 | struct pm860x_platform_data *pdata = chip->dev->platform_data; | ||
414 | struct pm8607_regulator_info *info = NULL; | ||
415 | |||
416 | info = find_regulator_info(pdev->id); | ||
417 | if (info == NULL) { | ||
418 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); | ||
419 | return -EINVAL; | 421 | return -EINVAL; |
420 | } | 422 | } |
421 | 423 | ||
422 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | 424 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
423 | info->chip = chip; | 425 | info->chip = chip; |
424 | 426 | ||
427 | /* check DVC ramp slope double */ | ||
428 | if (!strcmp(info->desc.name, "BUCK3")) | ||
429 | if (info->chip->buck3_double) | ||
430 | info->slope_double = 1; | ||
431 | |||
425 | info->regulator = regulator_register(&info->desc, &pdev->dev, | 432 | info->regulator = regulator_register(&info->desc, &pdev->dev, |
426 | pdata->regulator[pdev->id], info); | 433 | pdata, info); |
427 | if (IS_ERR(info->regulator)) { | 434 | if (IS_ERR(info->regulator)) { |
428 | dev_err(&pdev->dev, "failed to register regulator %s\n", | 435 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
429 | info->desc.name); | 436 | info->desc.name); |
430 | return PTR_ERR(info->regulator); | 437 | return PTR_ERR(info->regulator); |
431 | } | 438 | } |
432 | 439 | ||
433 | /* check DVC ramp slope double */ | ||
434 | if (info->desc.id == PM8607_ID_BUCK3) | ||
435 | if (info->chip->buck3_double) | ||
436 | info->slope_double = 1; | ||
437 | |||
438 | platform_set_drvdata(pdev, info); | 440 | platform_set_drvdata(pdev, info); |
439 | return 0; | 441 | return 0; |
440 | } | 442 | } |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index e1d943619ab8..de75f67f4cc3 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -108,6 +108,15 @@ config REGULATOR_MAX8952 | |||
108 | via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS | 108 | via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS |
109 | modes ranging from 0.77V to 1.40V by 0.01V steps. | 109 | modes ranging from 0.77V to 1.40V by 0.01V steps. |
110 | 110 | ||
111 | config REGULATOR_MAX8997 | ||
112 | tristate "Maxim 8997/8966 regulator" | ||
113 | depends on MFD_MAX8997 | ||
114 | help | ||
115 | This driver controls a Maxim 8997/8966 regulator | ||
116 | via I2C bus. The provided regulator is suitable for S5PC110, | ||
117 | S5PV210, and Exynos-4 chips to control VCC_CORE and | ||
118 | VCC_USIM voltages. | ||
119 | |||
111 | config REGULATOR_MAX8998 | 120 | config REGULATOR_MAX8998 |
112 | tristate "Maxim 8998 voltage regulator" | 121 | tristate "Maxim 8998 voltage regulator" |
113 | depends on MFD_MAX8998 | 122 | depends on MFD_MAX8998 |
@@ -214,6 +223,15 @@ config REGULATOR_AB3100 | |||
214 | AB3100 analog baseband dealing with power regulators | 223 | AB3100 analog baseband dealing with power regulators |
215 | for the system. | 224 | for the system. |
216 | 225 | ||
226 | config REGULATOR_TPS6105X | ||
227 | tristate "TI TPS6105X Power regulators" | ||
228 | depends on TPS6105X | ||
229 | default y if TPS6105X | ||
230 | help | ||
231 | This driver supports TPS61050/TPS61052 voltage regulator chips. | ||
232 | It is a single boost converter primarily for white LEDs and | ||
233 | audio amplifiers. | ||
234 | |||
217 | config REGULATOR_TPS65023 | 235 | config REGULATOR_TPS65023 |
218 | tristate "TI TPS65023 Power regulators" | 236 | tristate "TI TPS65023 Power regulators" |
219 | depends on I2C | 237 | depends on I2C |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 0b5e88c2b8d7..d72a42756778 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o | |||
18 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o | 18 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o |
19 | obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o | 19 | obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o |
20 | obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o | 20 | obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o |
21 | obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o | ||
21 | obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o | 22 | obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o |
22 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o | 23 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o |
23 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o | 24 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o |
@@ -33,7 +34,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o | |||
33 | obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o | 34 | obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o |
34 | obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o | 35 | obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o |
35 | obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o | 36 | obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o |
36 | 37 | obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o | |
37 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o | 38 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o |
38 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o | 39 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o |
39 | obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o | 40 | obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o |
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index ed6feaf9398d..2dec589a8908 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/regulator/driver.h> | 18 | #include <linux/regulator/driver.h> |
19 | #include <linux/mfd/abx500.h> | 19 | #include <linux/mfd/abx500.h> |
20 | #include <linux/mfd/core.h> | ||
20 | 21 | ||
21 | /* LDO registers and some handy masking definitions for AB3100 */ | 22 | /* LDO registers and some handy masking definitions for AB3100 */ |
22 | #define AB3100_LDO_A 0x40 | 23 | #define AB3100_LDO_A 0x40 |
@@ -576,7 +577,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { | |||
576 | 577 | ||
577 | static int __devinit ab3100_regulators_probe(struct platform_device *pdev) | 578 | static int __devinit ab3100_regulators_probe(struct platform_device *pdev) |
578 | { | 579 | { |
579 | struct ab3100_platform_data *plfdata = pdev->dev.platform_data; | 580 | struct ab3100_platform_data *plfdata = mfd_get_data(pdev); |
580 | int err = 0; | 581 | int err = 0; |
581 | u8 data; | 582 | u8 data; |
582 | int i; | 583 | int i; |
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c new file mode 100644 index 000000000000..01ef7e9903bb --- /dev/null +++ b/drivers/regulator/max8997.c | |||
@@ -0,0 +1,1213 @@ | |||
1 | /* | ||
2 | * max8997.c - Regulator driver for the Maxim 8997/8966 | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@smasung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | * This driver is based on max8998.c | ||
22 | */ | ||
23 | |||
24 | #include <linux/bug.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/regulator/driver.h> | ||
31 | #include <linux/regulator/machine.h> | ||
32 | #include <linux/mfd/max8997.h> | ||
33 | #include <linux/mfd/max8997-private.h> | ||
34 | |||
35 | struct max8997_data { | ||
36 | struct device *dev; | ||
37 | struct max8997_dev *iodev; | ||
38 | int num_regulators; | ||
39 | struct regulator_dev **rdev; | ||
40 | int ramp_delay; /* in mV/us */ | ||
41 | |||
42 | u8 buck1_vol[8]; | ||
43 | u8 buck2_vol[8]; | ||
44 | u8 buck5_vol[8]; | ||
45 | int buck125_gpioindex; | ||
46 | |||
47 | u8 saved_states[MAX8997_REG_MAX]; | ||
48 | }; | ||
49 | |||
50 | static inline void max8997_set_gpio(struct max8997_data *max8997) | ||
51 | { | ||
52 | struct max8997_platform_data *pdata = | ||
53 | dev_get_platdata(max8997->iodev->dev); | ||
54 | int set3 = (max8997->buck125_gpioindex) & 0x1; | ||
55 | int set2 = ((max8997->buck125_gpioindex) >> 1) & 0x1; | ||
56 | int set1 = ((max8997->buck125_gpioindex) >> 2) & 0x1; | ||
57 | |||
58 | gpio_set_value(pdata->buck125_gpios[0], set1); | ||
59 | gpio_set_value(pdata->buck125_gpios[1], set2); | ||
60 | gpio_set_value(pdata->buck125_gpios[2], set3); | ||
61 | } | ||
62 | |||
63 | struct voltage_map_desc { | ||
64 | int min; | ||
65 | int max; | ||
66 | int step; | ||
67 | unsigned int n_bits; | ||
68 | }; | ||
69 | |||
70 | /* Voltage maps in mV */ | ||
71 | static const struct voltage_map_desc ldo_voltage_map_desc = { | ||
72 | .min = 800, .max = 3950, .step = 50, .n_bits = 6, | ||
73 | }; /* LDO1 ~ 18, 21 all */ | ||
74 | |||
75 | static const struct voltage_map_desc buck1245_voltage_map_desc = { | ||
76 | .min = 650, .max = 2225, .step = 25, .n_bits = 6, | ||
77 | }; /* Buck1, 2, 4, 5 */ | ||
78 | |||
79 | static const struct voltage_map_desc buck37_voltage_map_desc = { | ||
80 | .min = 750, .max = 3900, .step = 50, .n_bits = 6, | ||
81 | }; /* Buck3, 7 */ | ||
82 | |||
83 | /* current map in mA */ | ||
84 | static const struct voltage_map_desc charger_current_map_desc = { | ||
85 | .min = 200, .max = 950, .step = 50, .n_bits = 4, | ||
86 | }; | ||
87 | |||
88 | static const struct voltage_map_desc topoff_current_map_desc = { | ||
89 | .min = 50, .max = 200, .step = 10, .n_bits = 4, | ||
90 | }; | ||
91 | |||
92 | static const struct voltage_map_desc *reg_voltage_map[] = { | ||
93 | [MAX8997_LDO1] = &ldo_voltage_map_desc, | ||
94 | [MAX8997_LDO2] = &ldo_voltage_map_desc, | ||
95 | [MAX8997_LDO3] = &ldo_voltage_map_desc, | ||
96 | [MAX8997_LDO4] = &ldo_voltage_map_desc, | ||
97 | [MAX8997_LDO5] = &ldo_voltage_map_desc, | ||
98 | [MAX8997_LDO6] = &ldo_voltage_map_desc, | ||
99 | [MAX8997_LDO7] = &ldo_voltage_map_desc, | ||
100 | [MAX8997_LDO8] = &ldo_voltage_map_desc, | ||
101 | [MAX8997_LDO9] = &ldo_voltage_map_desc, | ||
102 | [MAX8997_LDO10] = &ldo_voltage_map_desc, | ||
103 | [MAX8997_LDO11] = &ldo_voltage_map_desc, | ||
104 | [MAX8997_LDO12] = &ldo_voltage_map_desc, | ||
105 | [MAX8997_LDO13] = &ldo_voltage_map_desc, | ||
106 | [MAX8997_LDO14] = &ldo_voltage_map_desc, | ||
107 | [MAX8997_LDO15] = &ldo_voltage_map_desc, | ||
108 | [MAX8997_LDO16] = &ldo_voltage_map_desc, | ||
109 | [MAX8997_LDO17] = &ldo_voltage_map_desc, | ||
110 | [MAX8997_LDO18] = &ldo_voltage_map_desc, | ||
111 | [MAX8997_LDO21] = &ldo_voltage_map_desc, | ||
112 | [MAX8997_BUCK1] = &buck1245_voltage_map_desc, | ||
113 | [MAX8997_BUCK2] = &buck1245_voltage_map_desc, | ||
114 | [MAX8997_BUCK3] = &buck37_voltage_map_desc, | ||
115 | [MAX8997_BUCK4] = &buck1245_voltage_map_desc, | ||
116 | [MAX8997_BUCK5] = &buck1245_voltage_map_desc, | ||
117 | [MAX8997_BUCK6] = NULL, | ||
118 | [MAX8997_BUCK7] = &buck37_voltage_map_desc, | ||
119 | [MAX8997_EN32KHZ_AP] = NULL, | ||
120 | [MAX8997_EN32KHZ_CP] = NULL, | ||
121 | [MAX8997_ENVICHG] = NULL, | ||
122 | [MAX8997_ESAFEOUT1] = NULL, | ||
123 | [MAX8997_ESAFEOUT2] = NULL, | ||
124 | [MAX8997_CHARGER_CV] = NULL, | ||
125 | [MAX8997_CHARGER] = &charger_current_map_desc, | ||
126 | [MAX8997_CHARGER_TOPOFF] = &topoff_current_map_desc, | ||
127 | }; | ||
128 | |||
129 | static inline int max8997_get_rid(struct regulator_dev *rdev) | ||
130 | { | ||
131 | return rdev_get_id(rdev); | ||
132 | } | ||
133 | |||
134 | static int max8997_list_voltage_safeout(struct regulator_dev *rdev, | ||
135 | unsigned int selector) | ||
136 | { | ||
137 | int rid = max8997_get_rid(rdev); | ||
138 | |||
139 | if (rid == MAX8997_ESAFEOUT1 || rid == MAX8997_ESAFEOUT2) { | ||
140 | switch (selector) { | ||
141 | case 0: | ||
142 | return 4850000; | ||
143 | case 1: | ||
144 | return 4900000; | ||
145 | case 2: | ||
146 | return 4950000; | ||
147 | case 3: | ||
148 | return 3300000; | ||
149 | default: | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | static int max8997_list_voltage_charger_cv(struct regulator_dev *rdev, | ||
158 | unsigned int selector) | ||
159 | { | ||
160 | int rid = max8997_get_rid(rdev); | ||
161 | |||
162 | if (rid != MAX8997_CHARGER_CV) | ||
163 | goto err; | ||
164 | |||
165 | switch (selector) { | ||
166 | case 0x00: | ||
167 | return 4200000; | ||
168 | case 0x01 ... 0x0E: | ||
169 | return 4000000 + 20000 * (selector - 0x01); | ||
170 | case 0x0F: | ||
171 | return 4350000; | ||
172 | default: | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | err: | ||
176 | return -EINVAL; | ||
177 | } | ||
178 | |||
179 | static int max8997_list_voltage(struct regulator_dev *rdev, | ||
180 | unsigned int selector) | ||
181 | { | ||
182 | const struct voltage_map_desc *desc; | ||
183 | int rid = max8997_get_rid(rdev); | ||
184 | int val; | ||
185 | |||
186 | if (rid >= ARRAY_SIZE(reg_voltage_map) || | ||
187 | rid < 0) | ||
188 | return -EINVAL; | ||
189 | |||
190 | desc = reg_voltage_map[rid]; | ||
191 | if (desc == NULL) | ||
192 | return -EINVAL; | ||
193 | |||
194 | val = desc->min + desc->step * selector; | ||
195 | if (val > desc->max) | ||
196 | return -EINVAL; | ||
197 | |||
198 | return val * 1000; | ||
199 | } | ||
200 | |||
201 | static int max8997_get_enable_register(struct regulator_dev *rdev, | ||
202 | int *reg, int *mask, int *pattern) | ||
203 | { | ||
204 | int rid = max8997_get_rid(rdev); | ||
205 | |||
206 | switch (rid) { | ||
207 | case MAX8997_LDO1 ... MAX8997_LDO21: | ||
208 | *reg = MAX8997_REG_LDO1CTRL + (rid - MAX8997_LDO1); | ||
209 | *mask = 0xC0; | ||
210 | *pattern = 0xC0; | ||
211 | break; | ||
212 | case MAX8997_BUCK1: | ||
213 | *reg = MAX8997_REG_BUCK1CTRL; | ||
214 | *mask = 0x01; | ||
215 | *pattern = 0x01; | ||
216 | break; | ||
217 | case MAX8997_BUCK2: | ||
218 | *reg = MAX8997_REG_BUCK2CTRL; | ||
219 | *mask = 0x01; | ||
220 | *pattern = 0x01; | ||
221 | break; | ||
222 | case MAX8997_BUCK3: | ||
223 | *reg = MAX8997_REG_BUCK3CTRL; | ||
224 | *mask = 0x01; | ||
225 | *pattern = 0x01; | ||
226 | break; | ||
227 | case MAX8997_BUCK4: | ||
228 | *reg = MAX8997_REG_BUCK4CTRL; | ||
229 | *mask = 0x01; | ||
230 | *pattern = 0x01; | ||
231 | break; | ||
232 | case MAX8997_BUCK5: | ||
233 | *reg = MAX8997_REG_BUCK5CTRL; | ||
234 | *mask = 0x01; | ||
235 | *pattern = 0x01; | ||
236 | break; | ||
237 | case MAX8997_BUCK6: | ||
238 | *reg = MAX8997_REG_BUCK6CTRL; | ||
239 | *mask = 0x01; | ||
240 | *pattern = 0x01; | ||
241 | break; | ||
242 | case MAX8997_BUCK7: | ||
243 | *reg = MAX8997_REG_BUCK7CTRL; | ||
244 | *mask = 0x01; | ||
245 | *pattern = 0x01; | ||
246 | break; | ||
247 | case MAX8997_EN32KHZ_AP ... MAX8997_EN32KHZ_CP: | ||
248 | *reg = MAX8997_REG_MAINCON1; | ||
249 | *mask = 0x01 << (rid - MAX8997_EN32KHZ_AP); | ||
250 | *pattern = 0x01 << (rid - MAX8997_EN32KHZ_AP); | ||
251 | break; | ||
252 | case MAX8997_ENVICHG: | ||
253 | *reg = MAX8997_REG_MBCCTRL1; | ||
254 | *mask = 0x80; | ||
255 | *pattern = 0x80; | ||
256 | break; | ||
257 | case MAX8997_ESAFEOUT1 ... MAX8997_ESAFEOUT2: | ||
258 | *reg = MAX8997_REG_SAFEOUTCTRL; | ||
259 | *mask = 0x40 << (rid - MAX8997_ESAFEOUT1); | ||
260 | *pattern = 0x40 << (rid - MAX8997_ESAFEOUT1); | ||
261 | break; | ||
262 | case MAX8997_CHARGER: | ||
263 | *reg = MAX8997_REG_MBCCTRL2; | ||
264 | *mask = 0x40; | ||
265 | *pattern = 0x40; | ||
266 | break; | ||
267 | default: | ||
268 | /* Not controllable or not exists */ | ||
269 | return -EINVAL; | ||
270 | break; | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int max8997_reg_is_enabled(struct regulator_dev *rdev) | ||
277 | { | ||
278 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
279 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
280 | int ret, reg, mask, pattern; | ||
281 | u8 val; | ||
282 | |||
283 | ret = max8997_get_enable_register(rdev, ®, &mask, &pattern); | ||
284 | if (ret == -EINVAL) | ||
285 | return 1; /* "not controllable" */ | ||
286 | else if (ret) | ||
287 | return ret; | ||
288 | |||
289 | ret = max8997_read_reg(i2c, reg, &val); | ||
290 | if (ret) | ||
291 | return ret; | ||
292 | |||
293 | return (val & mask) == pattern; | ||
294 | } | ||
295 | |||
296 | static int max8997_reg_enable(struct regulator_dev *rdev) | ||
297 | { | ||
298 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
299 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
300 | int ret, reg, mask, pattern; | ||
301 | |||
302 | ret = max8997_get_enable_register(rdev, ®, &mask, &pattern); | ||
303 | if (ret) | ||
304 | return ret; | ||
305 | |||
306 | return max8997_update_reg(i2c, reg, pattern, mask); | ||
307 | } | ||
308 | |||
309 | static int max8997_reg_disable(struct regulator_dev *rdev) | ||
310 | { | ||
311 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
312 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
313 | int ret, reg, mask, pattern; | ||
314 | |||
315 | ret = max8997_get_enable_register(rdev, ®, &mask, &pattern); | ||
316 | if (ret) | ||
317 | return ret; | ||
318 | |||
319 | return max8997_update_reg(i2c, reg, ~pattern, mask); | ||
320 | } | ||
321 | |||
322 | static int max8997_get_voltage_register(struct regulator_dev *rdev, | ||
323 | int *_reg, int *_shift, int *_mask) | ||
324 | { | ||
325 | int rid = max8997_get_rid(rdev); | ||
326 | int reg, shift = 0, mask = 0x3f; | ||
327 | |||
328 | switch (rid) { | ||
329 | case MAX8997_LDO1 ... MAX8997_LDO21: | ||
330 | reg = MAX8997_REG_LDO1CTRL + (rid - MAX8997_LDO1); | ||
331 | break; | ||
332 | case MAX8997_BUCK1: | ||
333 | reg = MAX8997_REG_BUCK1DVS1; | ||
334 | break; | ||
335 | case MAX8997_BUCK2: | ||
336 | reg = MAX8997_REG_BUCK2DVS1; | ||
337 | break; | ||
338 | case MAX8997_BUCK3: | ||
339 | reg = MAX8997_REG_BUCK3DVS; | ||
340 | break; | ||
341 | case MAX8997_BUCK4: | ||
342 | reg = MAX8997_REG_BUCK4DVS; | ||
343 | break; | ||
344 | case MAX8997_BUCK5: | ||
345 | reg = MAX8997_REG_BUCK5DVS1; | ||
346 | break; | ||
347 | case MAX8997_BUCK7: | ||
348 | reg = MAX8997_REG_BUCK7DVS; | ||
349 | break; | ||
350 | case MAX8997_ESAFEOUT1 ... MAX8997_ESAFEOUT2: | ||
351 | reg = MAX8997_REG_SAFEOUTCTRL; | ||
352 | shift = (rid == MAX8997_ESAFEOUT2) ? 2 : 0; | ||
353 | mask = 0x3; | ||
354 | break; | ||
355 | case MAX8997_CHARGER_CV: | ||
356 | reg = MAX8997_REG_MBCCTRL3; | ||
357 | shift = 0; | ||
358 | mask = 0xf; | ||
359 | break; | ||
360 | case MAX8997_CHARGER: | ||
361 | reg = MAX8997_REG_MBCCTRL4; | ||
362 | shift = 0; | ||
363 | mask = 0xf; | ||
364 | break; | ||
365 | case MAX8997_CHARGER_TOPOFF: | ||
366 | reg = MAX8997_REG_MBCCTRL5; | ||
367 | shift = 0; | ||
368 | mask = 0xf; | ||
369 | break; | ||
370 | default: | ||
371 | return -EINVAL; | ||
372 | } | ||
373 | |||
374 | *_reg = reg; | ||
375 | *_shift = shift; | ||
376 | *_mask = mask; | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int max8997_get_voltage(struct regulator_dev *rdev) | ||
382 | { | ||
383 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
384 | struct max8997_platform_data *pdata = | ||
385 | dev_get_platdata(max8997->iodev->dev); | ||
386 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
387 | int reg, shift, mask, ret; | ||
388 | int rid = max8997_get_rid(rdev); | ||
389 | u8 val; | ||
390 | |||
391 | ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); | ||
392 | if (ret) | ||
393 | return ret; | ||
394 | |||
395 | if ((rid == MAX8997_BUCK1 && pdata->buck1_gpiodvs) || | ||
396 | (rid == MAX8997_BUCK2 && pdata->buck2_gpiodvs) || | ||
397 | (rid == MAX8997_BUCK5 && pdata->buck5_gpiodvs)) | ||
398 | reg += max8997->buck125_gpioindex; | ||
399 | |||
400 | ret = max8997_read_reg(i2c, reg, &val); | ||
401 | if (ret) | ||
402 | return ret; | ||
403 | |||
404 | val >>= shift; | ||
405 | val &= mask; | ||
406 | |||
407 | if (rdev->desc && rdev->desc->ops && rdev->desc->ops->list_voltage) | ||
408 | return rdev->desc->ops->list_voltage(rdev, val); | ||
409 | |||
410 | /* | ||
411 | * max8997_list_voltage returns value for any rdev with voltage_map, | ||
412 | * which works for "CHARGER" and "CHARGER TOPOFF" that do not have | ||
413 | * list_voltage ops (they are current regulators). | ||
414 | */ | ||
415 | return max8997_list_voltage(rdev, val); | ||
416 | } | ||
417 | |||
418 | static inline int max8997_get_voltage_proper_val( | ||
419 | const struct voltage_map_desc *desc, | ||
420 | int min_vol, int max_vol) | ||
421 | { | ||
422 | int i = 0; | ||
423 | |||
424 | if (desc == NULL) | ||
425 | return -EINVAL; | ||
426 | |||
427 | if (max_vol < desc->min || min_vol > desc->max) | ||
428 | return -EINVAL; | ||
429 | |||
430 | while (desc->min + desc->step * i < min_vol && | ||
431 | desc->min + desc->step * i < desc->max) | ||
432 | i++; | ||
433 | |||
434 | if (desc->min + desc->step * i > max_vol) | ||
435 | return -EINVAL; | ||
436 | |||
437 | if (i >= (1 << desc->n_bits)) | ||
438 | return -EINVAL; | ||
439 | |||
440 | return i; | ||
441 | } | ||
442 | |||
443 | static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev, | ||
444 | int min_uV, int max_uV, unsigned *selector) | ||
445 | { | ||
446 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
447 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
448 | int rid = max8997_get_rid(rdev); | ||
449 | int lb, ub; | ||
450 | int reg, shift = 0, mask, ret = 0; | ||
451 | u8 val = 0x0; | ||
452 | |||
453 | if (rid != MAX8997_CHARGER_CV) | ||
454 | return -EINVAL; | ||
455 | |||
456 | ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); | ||
457 | if (ret) | ||
458 | return ret; | ||
459 | |||
460 | if (max_uV < 4000000 || min_uV > 4350000) | ||
461 | return -EINVAL; | ||
462 | |||
463 | if (min_uV <= 4000000) { | ||
464 | if (max_uV >= 4000000) | ||
465 | return -EINVAL; | ||
466 | else | ||
467 | val = 0x1; | ||
468 | } else if (min_uV <= 4200000 && max_uV >= 4200000) | ||
469 | val = 0x0; | ||
470 | else { | ||
471 | lb = (min_uV - 4000001) / 20000 + 2; | ||
472 | ub = (max_uV - 4000000) / 20000 + 1; | ||
473 | |||
474 | if (lb > ub) | ||
475 | return -EINVAL; | ||
476 | |||
477 | if (lb < 0xf) | ||
478 | val = lb; | ||
479 | else { | ||
480 | if (ub >= 0xf) | ||
481 | val = 0xf; | ||
482 | else | ||
483 | return -EINVAL; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | *selector = val; | ||
488 | |||
489 | ret = max8997_update_reg(i2c, reg, val << shift, mask); | ||
490 | |||
491 | return ret; | ||
492 | } | ||
493 | |||
494 | /* | ||
495 | * For LDO1 ~ LDO21, BUCK1~5, BUCK7, CHARGER, CHARGER_TOPOFF | ||
496 | * BUCK1, 2, and 5 are available if they are not controlled by gpio | ||
497 | */ | ||
498 | static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, | ||
499 | int min_uV, int max_uV, unsigned *selector) | ||
500 | { | ||
501 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
502 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
503 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
504 | const struct voltage_map_desc *desc; | ||
505 | int rid = max8997_get_rid(rdev); | ||
506 | int reg, shift = 0, mask, ret; | ||
507 | int i; | ||
508 | u8 org; | ||
509 | |||
510 | switch (rid) { | ||
511 | case MAX8997_LDO1 ... MAX8997_LDO21: | ||
512 | break; | ||
513 | case MAX8997_BUCK1 ... MAX8997_BUCK5: | ||
514 | break; | ||
515 | case MAX8997_BUCK6: | ||
516 | return -EINVAL; | ||
517 | case MAX8997_BUCK7: | ||
518 | break; | ||
519 | case MAX8997_CHARGER: | ||
520 | break; | ||
521 | case MAX8997_CHARGER_TOPOFF: | ||
522 | break; | ||
523 | default: | ||
524 | return -EINVAL; | ||
525 | } | ||
526 | |||
527 | desc = reg_voltage_map[rid]; | ||
528 | |||
529 | i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); | ||
530 | if (i < 0) | ||
531 | return i; | ||
532 | |||
533 | ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); | ||
534 | if (ret) | ||
535 | return ret; | ||
536 | |||
537 | max8997_read_reg(i2c, reg, &org); | ||
538 | org = (org & mask) >> shift; | ||
539 | |||
540 | ret = max8997_update_reg(i2c, reg, i << shift, mask << shift); | ||
541 | *selector = i; | ||
542 | |||
543 | if (rid == MAX8997_BUCK1 || rid == MAX8997_BUCK2 || | ||
544 | rid == MAX8997_BUCK4 || rid == MAX8997_BUCK5) { | ||
545 | /* If the voltage is increasing */ | ||
546 | if (org < i) | ||
547 | udelay(desc->step * (i - org) / max8997->ramp_delay); | ||
548 | } | ||
549 | |||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | /* | ||
554 | * Assess the damage on the voltage setting of BUCK1,2,5 by the change. | ||
555 | * | ||
556 | * When GPIO-DVS mode is used for multiple bucks, changing the voltage value | ||
557 | * of one of the bucks may affect that of another buck, which is the side | ||
558 | * effect of the change (set_voltage). This function examines the GPIO-DVS | ||
559 | * configurations and checks whether such side-effect exists. | ||
560 | */ | ||
561 | static int max8997_assess_side_effect(struct regulator_dev *rdev, | ||
562 | u8 new_val, int *best) | ||
563 | { | ||
564 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
565 | struct max8997_platform_data *pdata = | ||
566 | dev_get_platdata(max8997->iodev->dev); | ||
567 | int rid = max8997_get_rid(rdev); | ||
568 | u8 *buckx_val[3]; | ||
569 | bool buckx_gpiodvs[3]; | ||
570 | int side_effect[8]; | ||
571 | int min_side_effect = INT_MAX; | ||
572 | int i; | ||
573 | |||
574 | *best = -1; | ||
575 | |||
576 | switch (rid) { | ||
577 | case MAX8997_BUCK1: | ||
578 | rid = 0; | ||
579 | break; | ||
580 | case MAX8997_BUCK2: | ||
581 | rid = 1; | ||
582 | break; | ||
583 | case MAX8997_BUCK5: | ||
584 | rid = 2; | ||
585 | break; | ||
586 | default: | ||
587 | return -EINVAL; | ||
588 | } | ||
589 | |||
590 | buckx_val[0] = max8997->buck1_vol; | ||
591 | buckx_val[1] = max8997->buck2_vol; | ||
592 | buckx_val[2] = max8997->buck5_vol; | ||
593 | buckx_gpiodvs[0] = pdata->buck1_gpiodvs; | ||
594 | buckx_gpiodvs[1] = pdata->buck2_gpiodvs; | ||
595 | buckx_gpiodvs[2] = pdata->buck5_gpiodvs; | ||
596 | |||
597 | for (i = 0; i < 8; i++) { | ||
598 | int others; | ||
599 | |||
600 | if (new_val != (buckx_val[rid])[i]) { | ||
601 | side_effect[i] = -1; | ||
602 | continue; | ||
603 | } | ||
604 | |||
605 | side_effect[i] = 0; | ||
606 | for (others = 0; others < 3; others++) { | ||
607 | int diff; | ||
608 | |||
609 | if (others == rid) | ||
610 | continue; | ||
611 | if (buckx_gpiodvs[others] == false) | ||
612 | continue; /* Not affected */ | ||
613 | diff = (buckx_val[others])[i] - | ||
614 | (buckx_val[others])[max8997->buck125_gpioindex]; | ||
615 | if (diff > 0) | ||
616 | side_effect[i] += diff; | ||
617 | else if (diff < 0) | ||
618 | side_effect[i] -= diff; | ||
619 | } | ||
620 | if (side_effect[i] == 0) { | ||
621 | *best = i; | ||
622 | return 0; /* NO SIDE EFFECT! Use This! */ | ||
623 | } | ||
624 | if (side_effect[i] < min_side_effect) { | ||
625 | min_side_effect = side_effect[i]; | ||
626 | *best = i; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | if (*best == -1) | ||
631 | return -EINVAL; | ||
632 | |||
633 | return side_effect[*best]; | ||
634 | } | ||
635 | |||
636 | /* | ||
637 | * For Buck 1 ~ 5 and 7. If it is not controlled by GPIO, this calls | ||
638 | * max8997_set_voltage_ldobuck to do the job. | ||
639 | */ | ||
640 | static int max8997_set_voltage_buck(struct regulator_dev *rdev, | ||
641 | int min_uV, int max_uV, unsigned *selector) | ||
642 | { | ||
643 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
644 | struct max8997_platform_data *pdata = | ||
645 | dev_get_platdata(max8997->iodev->dev); | ||
646 | int rid = max8997_get_rid(rdev); | ||
647 | const struct voltage_map_desc *desc; | ||
648 | int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; | ||
649 | bool gpio_dvs_mode = false; | ||
650 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
651 | |||
652 | if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) | ||
653 | return -EINVAL; | ||
654 | |||
655 | switch (rid) { | ||
656 | case MAX8997_BUCK1: | ||
657 | if (pdata->buck1_gpiodvs) | ||
658 | gpio_dvs_mode = true; | ||
659 | break; | ||
660 | case MAX8997_BUCK2: | ||
661 | if (pdata->buck2_gpiodvs) | ||
662 | gpio_dvs_mode = true; | ||
663 | break; | ||
664 | case MAX8997_BUCK5: | ||
665 | if (pdata->buck5_gpiodvs) | ||
666 | gpio_dvs_mode = true; | ||
667 | break; | ||
668 | } | ||
669 | |||
670 | if (!gpio_dvs_mode) | ||
671 | return max8997_set_voltage_ldobuck(rdev, min_uV, max_uV, | ||
672 | selector); | ||
673 | |||
674 | desc = reg_voltage_map[rid]; | ||
675 | new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); | ||
676 | if (new_val < 0) | ||
677 | return new_val; | ||
678 | |||
679 | tmp_dmg = INT_MAX; | ||
680 | tmp_idx = -1; | ||
681 | tmp_val = -1; | ||
682 | do { | ||
683 | damage = max8997_assess_side_effect(rdev, new_val, &new_idx); | ||
684 | if (damage == 0) | ||
685 | goto out; | ||
686 | |||
687 | if (tmp_dmg > damage) { | ||
688 | tmp_idx = new_idx; | ||
689 | tmp_val = new_val; | ||
690 | tmp_dmg = damage; | ||
691 | } | ||
692 | |||
693 | new_val++; | ||
694 | } while (desc->min + desc->step + new_val <= desc->max); | ||
695 | |||
696 | new_idx = tmp_idx; | ||
697 | new_val = tmp_val; | ||
698 | |||
699 | if (pdata->ignore_gpiodvs_side_effect == false) | ||
700 | return -EINVAL; | ||
701 | |||
702 | dev_warn(&rdev->dev, "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:" | ||
703 | " %d -> %d\n", max8997->buck125_gpioindex, tmp_idx); | ||
704 | |||
705 | out: | ||
706 | if (new_idx < 0 || new_val < 0) | ||
707 | return -EINVAL; | ||
708 | |||
709 | max8997->buck125_gpioindex = new_idx; | ||
710 | max8997_set_gpio(max8997); | ||
711 | *selector = new_val; | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static const int safeoutvolt[] = { | ||
717 | 3300000, | ||
718 | 4850000, | ||
719 | 4900000, | ||
720 | 4950000, | ||
721 | }; | ||
722 | |||
723 | /* For SAFEOUT1 and SAFEOUT2 */ | ||
724 | static int max8997_set_voltage_safeout(struct regulator_dev *rdev, | ||
725 | int min_uV, int max_uV, unsigned *selector) | ||
726 | { | ||
727 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
728 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
729 | int rid = max8997_get_rid(rdev); | ||
730 | int reg, shift = 0, mask, ret; | ||
731 | int i = 0; | ||
732 | u8 val; | ||
733 | |||
734 | if (rid != MAX8997_ESAFEOUT1 && rid != MAX8997_ESAFEOUT2) | ||
735 | return -EINVAL; | ||
736 | |||
737 | for (i = 0; i < ARRAY_SIZE(safeoutvolt); i++) { | ||
738 | if (min_uV <= safeoutvolt[i] && | ||
739 | max_uV >= safeoutvolt[i]) | ||
740 | break; | ||
741 | } | ||
742 | |||
743 | if (i >= ARRAY_SIZE(safeoutvolt)) | ||
744 | return -EINVAL; | ||
745 | |||
746 | if (i == 0) | ||
747 | val = 0x3; | ||
748 | else | ||
749 | val = i - 1; | ||
750 | |||
751 | ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); | ||
752 | if (ret) | ||
753 | return ret; | ||
754 | |||
755 | ret = max8997_update_reg(i2c, reg, val << shift, mask << shift); | ||
756 | *selector = val; | ||
757 | |||
758 | return ret; | ||
759 | } | ||
760 | |||
761 | static int max8997_reg_enable_suspend(struct regulator_dev *rdev) | ||
762 | { | ||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | static int max8997_reg_disable_suspend(struct regulator_dev *rdev) | ||
767 | { | ||
768 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | ||
769 | struct i2c_client *i2c = max8997->iodev->i2c; | ||
770 | int ret, reg, mask, pattern; | ||
771 | int rid = max8997_get_rid(rdev); | ||
772 | |||
773 | ret = max8997_get_enable_register(rdev, ®, &mask, &pattern); | ||
774 | if (ret) | ||
775 | return ret; | ||
776 | |||
777 | max8997_read_reg(i2c, reg, &max8997->saved_states[rid]); | ||
778 | |||
779 | if (rid == MAX8997_LDO1 || | ||
780 | rid == MAX8997_LDO10 || | ||
781 | rid == MAX8997_LDO21) { | ||
782 | dev_dbg(&rdev->dev, "Conditional Power-Off for %s\n", | ||
783 | rdev->desc->name); | ||
784 | return max8997_update_reg(i2c, reg, 0x40, mask); | ||
785 | } | ||
786 | |||
787 | dev_dbg(&rdev->dev, "Full Power-Off for %s (%xh -> %xh)\n", | ||
788 | rdev->desc->name, max8997->saved_states[rid] & mask, | ||
789 | (~pattern) & mask); | ||
790 | return max8997_update_reg(i2c, reg, ~pattern, mask); | ||
791 | } | ||
792 | |||
793 | static struct regulator_ops max8997_ldo_ops = { | ||
794 | .list_voltage = max8997_list_voltage, | ||
795 | .is_enabled = max8997_reg_is_enabled, | ||
796 | .enable = max8997_reg_enable, | ||
797 | .disable = max8997_reg_disable, | ||
798 | .get_voltage = max8997_get_voltage, | ||
799 | .set_voltage = max8997_set_voltage_ldobuck, | ||
800 | .set_suspend_enable = max8997_reg_enable_suspend, | ||
801 | .set_suspend_disable = max8997_reg_disable_suspend, | ||
802 | }; | ||
803 | |||
804 | static struct regulator_ops max8997_buck_ops = { | ||
805 | .list_voltage = max8997_list_voltage, | ||
806 | .is_enabled = max8997_reg_is_enabled, | ||
807 | .enable = max8997_reg_enable, | ||
808 | .disable = max8997_reg_disable, | ||
809 | .get_voltage = max8997_get_voltage, | ||
810 | .set_voltage = max8997_set_voltage_buck, | ||
811 | .set_suspend_enable = max8997_reg_enable_suspend, | ||
812 | .set_suspend_disable = max8997_reg_disable_suspend, | ||
813 | }; | ||
814 | |||
815 | static struct regulator_ops max8997_fixedvolt_ops = { | ||
816 | .list_voltage = max8997_list_voltage, | ||
817 | .is_enabled = max8997_reg_is_enabled, | ||
818 | .enable = max8997_reg_enable, | ||
819 | .disable = max8997_reg_disable, | ||
820 | .set_suspend_enable = max8997_reg_enable_suspend, | ||
821 | .set_suspend_disable = max8997_reg_disable_suspend, | ||
822 | }; | ||
823 | |||
824 | static struct regulator_ops max8997_safeout_ops = { | ||
825 | .list_voltage = max8997_list_voltage_safeout, | ||
826 | .is_enabled = max8997_reg_is_enabled, | ||
827 | .enable = max8997_reg_enable, | ||
828 | .disable = max8997_reg_disable, | ||
829 | .get_voltage = max8997_get_voltage, | ||
830 | .set_voltage = max8997_set_voltage_safeout, | ||
831 | .set_suspend_enable = max8997_reg_enable_suspend, | ||
832 | .set_suspend_disable = max8997_reg_disable_suspend, | ||
833 | }; | ||
834 | |||
835 | static struct regulator_ops max8997_fixedstate_ops = { | ||
836 | .list_voltage = max8997_list_voltage_charger_cv, | ||
837 | .get_voltage = max8997_get_voltage, | ||
838 | .set_voltage = max8997_set_voltage_charger_cv, | ||
839 | }; | ||
840 | |||
841 | static int max8997_set_voltage_ldobuck_wrap(struct regulator_dev *rdev, | ||
842 | int min_uV, int max_uV) | ||
843 | { | ||
844 | unsigned dummy; | ||
845 | |||
846 | return max8997_set_voltage_ldobuck(rdev, min_uV, max_uV, &dummy); | ||
847 | } | ||
848 | |||
849 | |||
850 | static struct regulator_ops max8997_charger_ops = { | ||
851 | .is_enabled = max8997_reg_is_enabled, | ||
852 | .enable = max8997_reg_enable, | ||
853 | .disable = max8997_reg_disable, | ||
854 | .get_current_limit = max8997_get_voltage, | ||
855 | .set_current_limit = max8997_set_voltage_ldobuck_wrap, | ||
856 | }; | ||
857 | |||
858 | static struct regulator_ops max8997_charger_fixedstate_ops = { | ||
859 | .is_enabled = max8997_reg_is_enabled, | ||
860 | .get_current_limit = max8997_get_voltage, | ||
861 | .set_current_limit = max8997_set_voltage_ldobuck_wrap, | ||
862 | }; | ||
863 | |||
864 | #define regulator_desc_ldo(num) { \ | ||
865 | .name = "LDO"#num, \ | ||
866 | .id = MAX8997_LDO##num, \ | ||
867 | .ops = &max8997_ldo_ops, \ | ||
868 | .type = REGULATOR_VOLTAGE, \ | ||
869 | .owner = THIS_MODULE, \ | ||
870 | } | ||
871 | #define regulator_desc_buck(num) { \ | ||
872 | .name = "BUCK"#num, \ | ||
873 | .id = MAX8997_BUCK##num, \ | ||
874 | .ops = &max8997_buck_ops, \ | ||
875 | .type = REGULATOR_VOLTAGE, \ | ||
876 | .owner = THIS_MODULE, \ | ||
877 | } | ||
878 | |||
879 | static struct regulator_desc regulators[] = { | ||
880 | regulator_desc_ldo(1), | ||
881 | regulator_desc_ldo(2), | ||
882 | regulator_desc_ldo(3), | ||
883 | regulator_desc_ldo(4), | ||
884 | regulator_desc_ldo(5), | ||
885 | regulator_desc_ldo(6), | ||
886 | regulator_desc_ldo(7), | ||
887 | regulator_desc_ldo(8), | ||
888 | regulator_desc_ldo(9), | ||
889 | regulator_desc_ldo(10), | ||
890 | regulator_desc_ldo(11), | ||
891 | regulator_desc_ldo(12), | ||
892 | regulator_desc_ldo(13), | ||
893 | regulator_desc_ldo(14), | ||
894 | regulator_desc_ldo(15), | ||
895 | regulator_desc_ldo(16), | ||
896 | regulator_desc_ldo(17), | ||
897 | regulator_desc_ldo(18), | ||
898 | regulator_desc_ldo(21), | ||
899 | regulator_desc_buck(1), | ||
900 | regulator_desc_buck(2), | ||
901 | regulator_desc_buck(3), | ||
902 | regulator_desc_buck(4), | ||
903 | regulator_desc_buck(5), | ||
904 | { | ||
905 | .name = "BUCK6", | ||
906 | .id = MAX8997_BUCK6, | ||
907 | .ops = &max8997_fixedvolt_ops, | ||
908 | .type = REGULATOR_VOLTAGE, | ||
909 | .owner = THIS_MODULE, | ||
910 | }, | ||
911 | regulator_desc_buck(7), | ||
912 | { | ||
913 | .name = "EN32KHz AP", | ||
914 | .id = MAX8997_EN32KHZ_AP, | ||
915 | .ops = &max8997_fixedvolt_ops, | ||
916 | .type = REGULATOR_VOLTAGE, | ||
917 | .owner = THIS_MODULE, | ||
918 | }, { | ||
919 | .name = "EN32KHz CP", | ||
920 | .id = MAX8997_EN32KHZ_CP, | ||
921 | .ops = &max8997_fixedvolt_ops, | ||
922 | .type = REGULATOR_VOLTAGE, | ||
923 | .owner = THIS_MODULE, | ||
924 | }, { | ||
925 | .name = "ENVICHG", | ||
926 | .id = MAX8997_ENVICHG, | ||
927 | .ops = &max8997_fixedvolt_ops, | ||
928 | .type = REGULATOR_VOLTAGE, | ||
929 | .owner = THIS_MODULE, | ||
930 | }, { | ||
931 | .name = "ESAFEOUT1", | ||
932 | .id = MAX8997_ESAFEOUT1, | ||
933 | .ops = &max8997_safeout_ops, | ||
934 | .type = REGULATOR_VOLTAGE, | ||
935 | .owner = THIS_MODULE, | ||
936 | }, { | ||
937 | .name = "ESAFEOUT2", | ||
938 | .id = MAX8997_ESAFEOUT2, | ||
939 | .ops = &max8997_safeout_ops, | ||
940 | .type = REGULATOR_VOLTAGE, | ||
941 | .owner = THIS_MODULE, | ||
942 | }, { | ||
943 | .name = "CHARGER CV", | ||
944 | .id = MAX8997_CHARGER_CV, | ||
945 | .ops = &max8997_fixedstate_ops, | ||
946 | .type = REGULATOR_VOLTAGE, | ||
947 | .owner = THIS_MODULE, | ||
948 | }, { | ||
949 | .name = "CHARGER", | ||
950 | .id = MAX8997_CHARGER, | ||
951 | .ops = &max8997_charger_ops, | ||
952 | .type = REGULATOR_CURRENT, | ||
953 | .owner = THIS_MODULE, | ||
954 | }, { | ||
955 | .name = "CHARGER TOPOFF", | ||
956 | .id = MAX8997_CHARGER_TOPOFF, | ||
957 | .ops = &max8997_charger_fixedstate_ops, | ||
958 | .type = REGULATOR_CURRENT, | ||
959 | .owner = THIS_MODULE, | ||
960 | }, | ||
961 | }; | ||
962 | |||
963 | static __devinit int max8997_pmic_probe(struct platform_device *pdev) | ||
964 | { | ||
965 | struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
966 | struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); | ||
967 | struct regulator_dev **rdev; | ||
968 | struct max8997_data *max8997; | ||
969 | struct i2c_client *i2c; | ||
970 | int i, ret, size; | ||
971 | u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0; | ||
972 | |||
973 | if (!pdata) { | ||
974 | dev_err(pdev->dev.parent, "No platform init data supplied.\n"); | ||
975 | return -ENODEV; | ||
976 | } | ||
977 | |||
978 | max8997 = kzalloc(sizeof(struct max8997_data), GFP_KERNEL); | ||
979 | if (!max8997) | ||
980 | return -ENOMEM; | ||
981 | |||
982 | size = sizeof(struct regulator_dev *) * pdata->num_regulators; | ||
983 | max8997->rdev = kzalloc(size, GFP_KERNEL); | ||
984 | if (!max8997->rdev) { | ||
985 | kfree(max8997); | ||
986 | return -ENOMEM; | ||
987 | } | ||
988 | |||
989 | rdev = max8997->rdev; | ||
990 | max8997->dev = &pdev->dev; | ||
991 | max8997->iodev = iodev; | ||
992 | max8997->num_regulators = pdata->num_regulators; | ||
993 | platform_set_drvdata(pdev, max8997); | ||
994 | i2c = max8997->iodev->i2c; | ||
995 | |||
996 | max8997->buck125_gpioindex = pdata->buck125_default_idx; | ||
997 | |||
998 | for (i = 0; i < 8; i++) { | ||
999 | max8997->buck1_vol[i] = ret = | ||
1000 | max8997_get_voltage_proper_val( | ||
1001 | &buck1245_voltage_map_desc, | ||
1002 | pdata->buck1_voltage[i] / 1000, | ||
1003 | pdata->buck1_voltage[i] / 1000 + | ||
1004 | buck1245_voltage_map_desc.step); | ||
1005 | if (ret < 0) | ||
1006 | goto err_alloc; | ||
1007 | |||
1008 | max8997->buck2_vol[i] = ret = | ||
1009 | max8997_get_voltage_proper_val( | ||
1010 | &buck1245_voltage_map_desc, | ||
1011 | pdata->buck2_voltage[i] / 1000, | ||
1012 | pdata->buck2_voltage[i] / 1000 + | ||
1013 | buck1245_voltage_map_desc.step); | ||
1014 | if (ret < 0) | ||
1015 | goto err_alloc; | ||
1016 | |||
1017 | max8997->buck5_vol[i] = ret = | ||
1018 | max8997_get_voltage_proper_val( | ||
1019 | &buck1245_voltage_map_desc, | ||
1020 | pdata->buck5_voltage[i] / 1000, | ||
1021 | pdata->buck5_voltage[i] / 1000 + | ||
1022 | buck1245_voltage_map_desc.step); | ||
1023 | if (ret < 0) | ||
1024 | goto err_alloc; | ||
1025 | |||
1026 | if (max_buck1 < max8997->buck1_vol[i]) | ||
1027 | max_buck1 = max8997->buck1_vol[i]; | ||
1028 | if (max_buck2 < max8997->buck2_vol[i]) | ||
1029 | max_buck2 = max8997->buck2_vol[i]; | ||
1030 | if (max_buck5 < max8997->buck5_vol[i]) | ||
1031 | max_buck5 = max8997->buck5_vol[i]; | ||
1032 | } | ||
1033 | |||
1034 | /* For the safety, set max voltage before setting up */ | ||
1035 | for (i = 0; i < 8; i++) { | ||
1036 | max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), | ||
1037 | max_buck1, 0x3f); | ||
1038 | max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), | ||
1039 | max_buck2, 0x3f); | ||
1040 | max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), | ||
1041 | max_buck5, 0x3f); | ||
1042 | } | ||
1043 | |||
1044 | /* | ||
1045 | * If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them. | ||
1046 | * If at least one of them cares, set gpios. | ||
1047 | */ | ||
1048 | if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs || | ||
1049 | pdata->buck5_gpiodvs) { | ||
1050 | bool gpio1set = false, gpio2set = false; | ||
1051 | |||
1052 | if (!gpio_is_valid(pdata->buck125_gpios[0]) || | ||
1053 | !gpio_is_valid(pdata->buck125_gpios[1]) || | ||
1054 | !gpio_is_valid(pdata->buck125_gpios[2])) { | ||
1055 | dev_err(&pdev->dev, "GPIO NOT VALID\n"); | ||
1056 | ret = -EINVAL; | ||
1057 | goto err_alloc; | ||
1058 | } | ||
1059 | |||
1060 | ret = gpio_request(pdata->buck125_gpios[0], | ||
1061 | "MAX8997 SET1"); | ||
1062 | if (ret == -EBUSY) | ||
1063 | dev_warn(&pdev->dev, "Duplicated gpio request" | ||
1064 | " on SET1\n"); | ||
1065 | else if (ret) | ||
1066 | goto err_alloc; | ||
1067 | else | ||
1068 | gpio1set = true; | ||
1069 | |||
1070 | ret = gpio_request(pdata->buck125_gpios[1], | ||
1071 | "MAX8997 SET2"); | ||
1072 | if (ret == -EBUSY) | ||
1073 | dev_warn(&pdev->dev, "Duplicated gpio request" | ||
1074 | " on SET2\n"); | ||
1075 | else if (ret) { | ||
1076 | if (gpio1set) | ||
1077 | gpio_free(pdata->buck125_gpios[0]); | ||
1078 | goto err_alloc; | ||
1079 | } else | ||
1080 | gpio2set = true; | ||
1081 | |||
1082 | ret = gpio_request(pdata->buck125_gpios[2], | ||
1083 | "MAX8997 SET3"); | ||
1084 | if (ret == -EBUSY) | ||
1085 | dev_warn(&pdev->dev, "Duplicated gpio request" | ||
1086 | " on SET3\n"); | ||
1087 | else if (ret) { | ||
1088 | if (gpio1set) | ||
1089 | gpio_free(pdata->buck125_gpios[0]); | ||
1090 | if (gpio2set) | ||
1091 | gpio_free(pdata->buck125_gpios[1]); | ||
1092 | goto err_alloc; | ||
1093 | } | ||
1094 | |||
1095 | gpio_direction_output(pdata->buck125_gpios[0], | ||
1096 | (max8997->buck125_gpioindex >> 2) | ||
1097 | & 0x1); /* SET1 */ | ||
1098 | gpio_direction_output(pdata->buck125_gpios[1], | ||
1099 | (max8997->buck125_gpioindex >> 1) | ||
1100 | & 0x1); /* SET2 */ | ||
1101 | gpio_direction_output(pdata->buck125_gpios[2], | ||
1102 | (max8997->buck125_gpioindex >> 0) | ||
1103 | & 0x1); /* SET3 */ | ||
1104 | ret = 0; | ||
1105 | } | ||
1106 | |||
1107 | /* DVS-GPIO disabled */ | ||
1108 | max8997_update_reg(i2c, MAX8997_REG_BUCK1CTRL, (pdata->buck1_gpiodvs) ? | ||
1109 | (1 << 1) : (0 << 1), 1 << 1); | ||
1110 | max8997_update_reg(i2c, MAX8997_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ? | ||
1111 | (1 << 1) : (0 << 1), 1 << 1); | ||
1112 | max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ? | ||
1113 | (1 << 1) : (0 << 1), 1 << 1); | ||
1114 | |||
1115 | /* Initialize all the DVS related BUCK registers */ | ||
1116 | for (i = 0; i < 8; i++) { | ||
1117 | max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), | ||
1118 | max8997->buck1_vol[i], | ||
1119 | 0x3f); | ||
1120 | max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), | ||
1121 | max8997->buck2_vol[i], | ||
1122 | 0x3f); | ||
1123 | max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), | ||
1124 | max8997->buck5_vol[i], | ||
1125 | 0x3f); | ||
1126 | } | ||
1127 | |||
1128 | for (i = 0; i < pdata->num_regulators; i++) { | ||
1129 | const struct voltage_map_desc *desc; | ||
1130 | int id = pdata->regulators[i].id; | ||
1131 | |||
1132 | desc = reg_voltage_map[id]; | ||
1133 | if (desc) | ||
1134 | regulators[id].n_voltages = | ||
1135 | (desc->max - desc->min) / desc->step + 1; | ||
1136 | else if (id == MAX8997_ESAFEOUT1 || id == MAX8997_ESAFEOUT2) | ||
1137 | regulators[id].n_voltages = 4; | ||
1138 | else if (id == MAX8997_CHARGER_CV) | ||
1139 | regulators[id].n_voltages = 16; | ||
1140 | |||
1141 | rdev[i] = regulator_register(®ulators[id], max8997->dev, | ||
1142 | pdata->regulators[i].initdata, max8997); | ||
1143 | if (IS_ERR(rdev[i])) { | ||
1144 | ret = PTR_ERR(rdev[i]); | ||
1145 | dev_err(max8997->dev, "regulator init failed for %d\n", | ||
1146 | id); | ||
1147 | rdev[i] = NULL; | ||
1148 | goto err; | ||
1149 | } | ||
1150 | } | ||
1151 | |||
1152 | /* Misc Settings */ | ||
1153 | max8997->ramp_delay = 10; /* set 10mV/us, which is the default */ | ||
1154 | max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9); | ||
1155 | |||
1156 | return 0; | ||
1157 | err: | ||
1158 | for (i = 0; i < max8997->num_regulators; i++) | ||
1159 | if (rdev[i]) | ||
1160 | regulator_unregister(rdev[i]); | ||
1161 | err_alloc: | ||
1162 | kfree(max8997->rdev); | ||
1163 | kfree(max8997); | ||
1164 | |||
1165 | return ret; | ||
1166 | } | ||
1167 | |||
1168 | static int __devexit max8997_pmic_remove(struct platform_device *pdev) | ||
1169 | { | ||
1170 | struct max8997_data *max8997 = platform_get_drvdata(pdev); | ||
1171 | struct regulator_dev **rdev = max8997->rdev; | ||
1172 | int i; | ||
1173 | |||
1174 | for (i = 0; i < max8997->num_regulators; i++) | ||
1175 | if (rdev[i]) | ||
1176 | regulator_unregister(rdev[i]); | ||
1177 | |||
1178 | kfree(max8997->rdev); | ||
1179 | kfree(max8997); | ||
1180 | |||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static const struct platform_device_id max8997_pmic_id[] = { | ||
1185 | { "max8997-pmic", 0}, | ||
1186 | { }, | ||
1187 | }; | ||
1188 | |||
1189 | static struct platform_driver max8997_pmic_driver = { | ||
1190 | .driver = { | ||
1191 | .name = "max8997-pmic", | ||
1192 | .owner = THIS_MODULE, | ||
1193 | }, | ||
1194 | .probe = max8997_pmic_probe, | ||
1195 | .remove = __devexit_p(max8997_pmic_remove), | ||
1196 | .id_table = max8997_pmic_id, | ||
1197 | }; | ||
1198 | |||
1199 | static int __init max8997_pmic_init(void) | ||
1200 | { | ||
1201 | return platform_driver_register(&max8997_pmic_driver); | ||
1202 | } | ||
1203 | subsys_initcall(max8997_pmic_init); | ||
1204 | |||
1205 | static void __exit max8997_pmic_cleanup(void) | ||
1206 | { | ||
1207 | platform_driver_unregister(&max8997_pmic_driver); | ||
1208 | } | ||
1209 | module_exit(max8997_pmic_cleanup); | ||
1210 | |||
1211 | MODULE_DESCRIPTION("MAXIM 8997/8966 Regulator Driver"); | ||
1212 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
1213 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 3e5d0c3b4e53..23249cb0a8bd 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/regulator/driver.h> | 15 | #include <linux/regulator/driver.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/mfd/core.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/err.h> | 21 | #include <linux/err.h> |
@@ -336,8 +337,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) | |||
336 | { | 337 | { |
337 | struct mc13xxx_regulator_priv *priv; | 338 | struct mc13xxx_regulator_priv *priv; |
338 | struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); | 339 | struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); |
339 | struct mc13783_regulator_platform_data *pdata = | 340 | struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev); |
340 | dev_get_platdata(&pdev->dev); | ||
341 | struct mc13783_regulator_init_data *init_data; | 341 | struct mc13783_regulator_init_data *init_data; |
342 | int i, ret; | 342 | int i, ret; |
343 | 343 | ||
@@ -381,8 +381,7 @@ err: | |||
381 | static int __devexit mc13783_regulator_remove(struct platform_device *pdev) | 381 | static int __devexit mc13783_regulator_remove(struct platform_device *pdev) |
382 | { | 382 | { |
383 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); | 383 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); |
384 | struct mc13783_regulator_platform_data *pdata = | 384 | struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev); |
385 | dev_get_platdata(&pdev->dev); | ||
386 | int i; | 385 | int i; |
387 | 386 | ||
388 | platform_set_drvdata(pdev, NULL); | 387 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 1b8f7398a4a8..6f15168e5ed4 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/regulator/driver.h> | 15 | #include <linux/regulator/driver.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/mfd/core.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/err.h> | 21 | #include <linux/err.h> |
@@ -520,8 +521,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) | |||
520 | { | 521 | { |
521 | struct mc13xxx_regulator_priv *priv; | 522 | struct mc13xxx_regulator_priv *priv; |
522 | struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); | 523 | struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); |
523 | struct mc13xxx_regulator_platform_data *pdata = | 524 | struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev); |
524 | dev_get_platdata(&pdev->dev); | ||
525 | struct mc13xxx_regulator_init_data *init_data; | 525 | struct mc13xxx_regulator_init_data *init_data; |
526 | int i, ret; | 526 | int i, ret; |
527 | u32 val; | 527 | u32 val; |
@@ -595,8 +595,7 @@ err_free: | |||
595 | static int __devexit mc13892_regulator_remove(struct platform_device *pdev) | 595 | static int __devexit mc13892_regulator_remove(struct platform_device *pdev) |
596 | { | 596 | { |
597 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); | 597 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); |
598 | struct mc13xxx_regulator_platform_data *pdata = | 598 | struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev); |
599 | dev_get_platdata(&pdev->dev); | ||
600 | int i; | 599 | int i; |
601 | 600 | ||
602 | platform_set_drvdata(pdev, NULL); | 601 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c new file mode 100644 index 000000000000..1661499feda4 --- /dev/null +++ b/drivers/regulator/tps6105x-regulator.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * Driver for TPS61050/61052 boost converters, typically used for white LEDs | ||
3 | * or audio amplifiers. | ||
4 | * | ||
5 | * Copyright (C) 2011 ST-Ericsson SA | ||
6 | * Written on behalf of Linaro for ST-Ericsson | ||
7 | * | ||
8 | * Author: Linus Walleij <linus.walleij@linaro.org> | ||
9 | * | ||
10 | * License terms: GNU General Public License (GPL) version 2 | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/regulator/driver.h> | ||
20 | #include <linux/mfd/core.h> | ||
21 | #include <linux/mfd/tps6105x.h> | ||
22 | |||
23 | static const int tps6105x_voltages[] = { | ||
24 | 4500000, | ||
25 | 5000000, | ||
26 | 5250000, | ||
27 | 5000000, /* There is an additional 5V */ | ||
28 | }; | ||
29 | |||
30 | static int tps6105x_regulator_enable(struct regulator_dev *rdev) | ||
31 | { | ||
32 | struct tps6105x *tps6105x = rdev_get_drvdata(rdev); | ||
33 | int ret; | ||
34 | |||
35 | /* Activate voltage mode */ | ||
36 | ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, | ||
37 | TPS6105X_REG0_MODE_MASK, | ||
38 | TPS6105X_REG0_MODE_VOLTAGE << TPS6105X_REG0_MODE_SHIFT); | ||
39 | if (ret) | ||
40 | return ret; | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int tps6105x_regulator_disable(struct regulator_dev *rdev) | ||
46 | { | ||
47 | struct tps6105x *tps6105x = rdev_get_drvdata(rdev); | ||
48 | int ret; | ||
49 | |||
50 | /* Set into shutdown mode */ | ||
51 | ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, | ||
52 | TPS6105X_REG0_MODE_MASK, | ||
53 | TPS6105X_REG0_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT); | ||
54 | if (ret) | ||
55 | return ret; | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev) | ||
61 | { | ||
62 | struct tps6105x *tps6105x = rdev_get_drvdata(rdev); | ||
63 | u8 regval; | ||
64 | int ret; | ||
65 | |||
66 | ret = tps6105x_get(tps6105x, TPS6105X_REG_0, ®val); | ||
67 | if (ret) | ||
68 | return ret; | ||
69 | regval &= TPS6105X_REG0_MODE_MASK; | ||
70 | regval >>= TPS6105X_REG0_MODE_SHIFT; | ||
71 | |||
72 | if (regval == TPS6105X_REG0_MODE_VOLTAGE) | ||
73 | return 1; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int tps6105x_regulator_get_voltage_sel(struct regulator_dev *rdev) | ||
79 | { | ||
80 | struct tps6105x *tps6105x = rdev_get_drvdata(rdev); | ||
81 | u8 regval; | ||
82 | int ret; | ||
83 | |||
84 | ret = tps6105x_get(tps6105x, TPS6105X_REG_0, ®val); | ||
85 | if (ret) | ||
86 | return ret; | ||
87 | |||
88 | regval &= TPS6105X_REG0_VOLTAGE_MASK; | ||
89 | regval >>= TPS6105X_REG0_VOLTAGE_SHIFT; | ||
90 | return (int) regval; | ||
91 | } | ||
92 | |||
93 | static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev, | ||
94 | unsigned selector) | ||
95 | { | ||
96 | struct tps6105x *tps6105x = rdev_get_drvdata(rdev); | ||
97 | int ret; | ||
98 | |||
99 | ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, | ||
100 | TPS6105X_REG0_VOLTAGE_MASK, | ||
101 | selector << TPS6105X_REG0_VOLTAGE_SHIFT); | ||
102 | if (ret) | ||
103 | return ret; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int tps6105x_regulator_list_voltage(struct regulator_dev *rdev, | ||
109 | unsigned selector) | ||
110 | { | ||
111 | if (selector >= ARRAY_SIZE(tps6105x_voltages)) | ||
112 | return -EINVAL; | ||
113 | |||
114 | return tps6105x_voltages[selector]; | ||
115 | } | ||
116 | |||
117 | static struct regulator_ops tps6105x_regulator_ops = { | ||
118 | .enable = tps6105x_regulator_enable, | ||
119 | .disable = tps6105x_regulator_disable, | ||
120 | .is_enabled = tps6105x_regulator_is_enabled, | ||
121 | .get_voltage_sel = tps6105x_regulator_get_voltage_sel, | ||
122 | .set_voltage_sel = tps6105x_regulator_set_voltage_sel, | ||
123 | .list_voltage = tps6105x_regulator_list_voltage, | ||
124 | }; | ||
125 | |||
126 | static struct regulator_desc tps6105x_regulator_desc = { | ||
127 | .name = "tps6105x-boost", | ||
128 | .ops = &tps6105x_regulator_ops, | ||
129 | .type = REGULATOR_VOLTAGE, | ||
130 | .id = 0, | ||
131 | .owner = THIS_MODULE, | ||
132 | .n_voltages = ARRAY_SIZE(tps6105x_voltages), | ||
133 | }; | ||
134 | |||
135 | /* | ||
136 | * Registers the chip as a voltage regulator | ||
137 | */ | ||
138 | static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) | ||
139 | { | ||
140 | struct tps6105x *tps6105x = mfd_get_data(pdev); | ||
141 | struct tps6105x_platform_data *pdata = tps6105x->pdata; | ||
142 | int ret; | ||
143 | |||
144 | /* This instance is not set for regulator mode so bail out */ | ||
145 | if (pdata->mode != TPS6105X_MODE_VOLTAGE) { | ||
146 | dev_info(&pdev->dev, | ||
147 | "chip not in voltage mode mode, exit probe \n"); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /* Register regulator with framework */ | ||
152 | tps6105x->regulator = regulator_register(&tps6105x_regulator_desc, | ||
153 | &tps6105x->client->dev, | ||
154 | pdata->regulator_data, tps6105x); | ||
155 | if (IS_ERR(tps6105x->regulator)) { | ||
156 | ret = PTR_ERR(tps6105x->regulator); | ||
157 | dev_err(&tps6105x->client->dev, | ||
158 | "failed to register regulator\n"); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int __devexit tps6105x_regulator_remove(struct platform_device *pdev) | ||
166 | { | ||
167 | struct tps6105x *tps6105x = platform_get_drvdata(pdev); | ||
168 | regulator_unregister(tps6105x->regulator); | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static struct platform_driver tps6105x_regulator_driver = { | ||
173 | .driver = { | ||
174 | .name = "tps6105x-regulator", | ||
175 | .owner = THIS_MODULE, | ||
176 | }, | ||
177 | .probe = tps6105x_regulator_probe, | ||
178 | .remove = __devexit_p(tps6105x_regulator_remove), | ||
179 | }; | ||
180 | |||
181 | static __init int tps6105x_regulator_init(void) | ||
182 | { | ||
183 | return platform_driver_register(&tps6105x_regulator_driver); | ||
184 | } | ||
185 | subsys_initcall(tps6105x_regulator_init); | ||
186 | |||
187 | static __exit void tps6105x_regulator_exit(void) | ||
188 | { | ||
189 | platform_driver_unregister(&tps6105x_regulator_driver); | ||
190 | } | ||
191 | module_exit(tps6105x_regulator_exit); | ||
192 | |||
193 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); | ||
194 | MODULE_DESCRIPTION("TPS6105x regulator driver"); | ||
195 | MODULE_LICENSE("GPL v2"); | ||
196 | MODULE_ALIAS("platform:tps6105x-regulator"); | ||
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index bd332cf1cc3f..6a292852a358 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
@@ -475,6 +475,13 @@ static struct regulator_ops twlfixed_ops = { | |||
475 | .get_status = twlreg_get_status, | 475 | .get_status = twlreg_get_status, |
476 | }; | 476 | }; |
477 | 477 | ||
478 | static struct regulator_ops twl6030_fixed_resource = { | ||
479 | .enable = twlreg_enable, | ||
480 | .disable = twlreg_disable, | ||
481 | .is_enabled = twlreg_is_enabled, | ||
482 | .get_status = twlreg_get_status, | ||
483 | }; | ||
484 | |||
478 | /*----------------------------------------------------------------------*/ | 485 | /*----------------------------------------------------------------------*/ |
479 | 486 | ||
480 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ | 487 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ |
@@ -538,6 +545,20 @@ static struct regulator_ops twlfixed_ops = { | |||
538 | }, \ | 545 | }, \ |
539 | } | 546 | } |
540 | 547 | ||
548 | #define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay, remap_conf) { \ | ||
549 | .base = offset, \ | ||
550 | .id = num, \ | ||
551 | .delay = turnon_delay, \ | ||
552 | .remap = remap_conf, \ | ||
553 | .desc = { \ | ||
554 | .name = #label, \ | ||
555 | .id = TWL6030_REG_##label, \ | ||
556 | .ops = &twl6030_fixed_resource, \ | ||
557 | .type = REGULATOR_VOLTAGE, \ | ||
558 | .owner = THIS_MODULE, \ | ||
559 | }, \ | ||
560 | } | ||
561 | |||
541 | /* | 562 | /* |
542 | * We list regulators here if systems need some level of | 563 | * We list regulators here if systems need some level of |
543 | * software control over them after boot. | 564 | * software control over them after boot. |
@@ -577,7 +598,8 @@ static struct twlreg_info twl_regs[] = { | |||
577 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21), | 598 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21), |
578 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21), | 599 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21), |
579 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21), | 600 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21), |
580 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21) | 601 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21), |
602 | TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0, 0x21), | ||
581 | }; | 603 | }; |
582 | 604 | ||
583 | static int __devinit twlreg_probe(struct platform_device *pdev) | 605 | static int __devinit twlreg_probe(struct platform_device *pdev) |
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 4d2c75df886c..c69c6f2c2c5c 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/mfd/core.h> | ||
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> |
23 | #include <linux/spi/xilinx_spi.h> | 24 | #include <linux/spi/xilinx_spi.h> |
@@ -470,7 +471,7 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev) | |||
470 | struct spi_master *master; | 471 | struct spi_master *master; |
471 | u8 i; | 472 | u8 i; |
472 | 473 | ||
473 | pdata = dev->dev.platform_data; | 474 | pdata = mfd_get_data(dev); |
474 | if (pdata) { | 475 | if (pdata) { |
475 | num_cs = pdata->num_chipselect; | 476 | num_cs = pdata->num_chipselect; |
476 | little_endian = pdata->little_endian; | 477 | little_endian = pdata->little_endian; |
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index 8dabe8e31d8c..3558491dd87d 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c | |||
@@ -185,7 +185,7 @@ static struct platform_driver ohci_hcd_tmio_driver; | |||
185 | 185 | ||
186 | static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) | 186 | static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) |
187 | { | 187 | { |
188 | struct mfd_cell *cell = dev->dev.platform_data; | 188 | const struct mfd_cell *cell = mfd_get_cell(dev); |
189 | struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0); | 189 | struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0); |
190 | struct resource *config = platform_get_resource(dev, IORESOURCE_MEM, 1); | 190 | struct resource *config = platform_get_resource(dev, IORESOURCE_MEM, 1); |
191 | struct resource *sram = platform_get_resource(dev, IORESOURCE_MEM, 2); | 191 | struct resource *sram = platform_get_resource(dev, IORESOURCE_MEM, 2); |
@@ -274,7 +274,7 @@ static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev) | |||
274 | { | 274 | { |
275 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 275 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
276 | struct tmio_hcd *tmio = hcd_to_tmio(hcd); | 276 | struct tmio_hcd *tmio = hcd_to_tmio(hcd); |
277 | struct mfd_cell *cell = dev->dev.platform_data; | 277 | const struct mfd_cell *cell = mfd_get_cell(dev); |
278 | 278 | ||
279 | usb_remove_hcd(hcd); | 279 | usb_remove_hcd(hcd); |
280 | tmio_stop_hc(dev); | 280 | tmio_stop_hc(dev); |
@@ -293,7 +293,7 @@ static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev) | |||
293 | #ifdef CONFIG_PM | 293 | #ifdef CONFIG_PM |
294 | static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t state) | 294 | static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t state) |
295 | { | 295 | { |
296 | struct mfd_cell *cell = dev->dev.platform_data; | 296 | const struct mfd_cell *cell = mfd_get_cell(dev); |
297 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 297 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
298 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | 298 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
299 | struct tmio_hcd *tmio = hcd_to_tmio(hcd); | 299 | struct tmio_hcd *tmio = hcd_to_tmio(hcd); |
@@ -326,7 +326,7 @@ static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t s | |||
326 | 326 | ||
327 | static int ohci_hcd_tmio_drv_resume(struct platform_device *dev) | 327 | static int ohci_hcd_tmio_drv_resume(struct platform_device *dev) |
328 | { | 328 | { |
329 | struct mfd_cell *cell = dev->dev.platform_data; | 329 | const struct mfd_cell *cell = mfd_get_cell(dev); |
330 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 330 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
331 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | 331 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
332 | struct tmio_hcd *tmio = hcd_to_tmio(hcd); | 332 | struct tmio_hcd *tmio = hcd_to_tmio(hcd); |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index e59623a15f3f..c8b520e9a11a 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
@@ -12,11 +12,12 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
16 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
17 | #include <linux/backlight.h> | 18 | #include <linux/backlight.h> |
19 | #include <linux/mfd/core.h> | ||
18 | #include <linux/mfd/88pm860x.h> | 20 | #include <linux/mfd/88pm860x.h> |
19 | #include <linux/slab.h> | ||
20 | 21 | ||
21 | #define MAX_BRIGHTNESS (0xFF) | 22 | #define MAX_BRIGHTNESS (0xFF) |
22 | #define MIN_BRIGHTNESS (0) | 23 | #define MIN_BRIGHTNESS (0) |
@@ -161,32 +162,13 @@ static const struct backlight_ops pm860x_backlight_ops = { | |||
161 | .get_brightness = pm860x_backlight_get_brightness, | 162 | .get_brightness = pm860x_backlight_get_brightness, |
162 | }; | 163 | }; |
163 | 164 | ||
164 | static int __check_device(struct pm860x_backlight_pdata *pdata, char *name) | ||
165 | { | ||
166 | struct pm860x_backlight_pdata *p = pdata; | ||
167 | int ret = -EINVAL; | ||
168 | |||
169 | while (p && p->id) { | ||
170 | if ((p->id != PM8606_ID_BACKLIGHT) || (p->flags < 0)) | ||
171 | break; | ||
172 | |||
173 | if (!strncmp(name, pm860x_backlight_name[p->flags], | ||
174 | MFD_NAME_SIZE)) { | ||
175 | ret = (int)p->flags; | ||
176 | break; | ||
177 | } | ||
178 | p++; | ||
179 | } | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | static int pm860x_backlight_probe(struct platform_device *pdev) | 165 | static int pm860x_backlight_probe(struct platform_device *pdev) |
184 | { | 166 | { |
185 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 167 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
186 | struct pm860x_platform_data *pm860x_pdata; | ||
187 | struct pm860x_backlight_pdata *pdata = NULL; | 168 | struct pm860x_backlight_pdata *pdata = NULL; |
188 | struct pm860x_backlight_data *data; | 169 | struct pm860x_backlight_data *data; |
189 | struct backlight_device *bl; | 170 | struct backlight_device *bl; |
171 | struct mfd_cell *cell; | ||
190 | struct resource *res; | 172 | struct resource *res; |
191 | struct backlight_properties props; | 173 | struct backlight_properties props; |
192 | unsigned char value; | 174 | unsigned char value; |
@@ -199,10 +181,10 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
199 | return -EINVAL; | 181 | return -EINVAL; |
200 | } | 182 | } |
201 | 183 | ||
202 | if (pdev->dev.parent->platform_data) { | 184 | cell = pdev->dev.platform_data; |
203 | pm860x_pdata = pdev->dev.parent->platform_data; | 185 | if (cell == NULL) |
204 | pdata = pm860x_pdata->backlight; | 186 | return -ENODEV; |
205 | } | 187 | pdata = cell->mfd_data; |
206 | if (pdata == NULL) { | 188 | if (pdata == NULL) { |
207 | dev_err(&pdev->dev, "platform data isn't assigned to " | 189 | dev_err(&pdev->dev, "platform data isn't assigned to " |
208 | "backlight\n"); | 190 | "backlight\n"); |
@@ -219,7 +201,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
219 | data->current_brightness = MAX_BRIGHTNESS; | 201 | data->current_brightness = MAX_BRIGHTNESS; |
220 | data->pwm = pdata->pwm; | 202 | data->pwm = pdata->pwm; |
221 | data->iset = pdata->iset; | 203 | data->iset = pdata->iset; |
222 | data->port = __check_device(pdata, name); | 204 | data->port = pdata->flags; |
223 | if (data->port < 0) { | 205 | if (data->port < 0) { |
224 | dev_err(&pdev->dev, "wrong platform data is assigned"); | 206 | dev_err(&pdev->dev, "wrong platform data is assigned"); |
225 | kfree(data); | 207 | kfree(data); |
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index dfef88c803d4..9710bf8caeae 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c | |||
@@ -250,8 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) | |||
250 | */ | 250 | */ |
251 | static int tmiofb_hw_stop(struct platform_device *dev) | 251 | static int tmiofb_hw_stop(struct platform_device *dev) |
252 | { | 252 | { |
253 | struct mfd_cell *cell = dev->dev.platform_data; | 253 | struct tmio_fb_data *data = mfd_get_data(dev); |
254 | struct tmio_fb_data *data = cell->driver_data; | ||
255 | struct fb_info *info = platform_get_drvdata(dev); | 254 | struct fb_info *info = platform_get_drvdata(dev); |
256 | struct tmiofb_par *par = info->par; | 255 | struct tmiofb_par *par = info->par; |
257 | 256 | ||
@@ -268,7 +267,7 @@ static int tmiofb_hw_stop(struct platform_device *dev) | |||
268 | */ | 267 | */ |
269 | static int tmiofb_hw_init(struct platform_device *dev) | 268 | static int tmiofb_hw_init(struct platform_device *dev) |
270 | { | 269 | { |
271 | struct mfd_cell *cell = dev->dev.platform_data; | 270 | const struct mfd_cell *cell = mfd_get_cell(dev); |
272 | struct fb_info *info = platform_get_drvdata(dev); | 271 | struct fb_info *info = platform_get_drvdata(dev); |
273 | struct tmiofb_par *par = info->par; | 272 | struct tmiofb_par *par = info->par; |
274 | const struct resource *nlcr = &cell->resources[0]; | 273 | const struct resource *nlcr = &cell->resources[0]; |
@@ -312,8 +311,7 @@ static int tmiofb_hw_init(struct platform_device *dev) | |||
312 | */ | 311 | */ |
313 | static void tmiofb_hw_mode(struct platform_device *dev) | 312 | static void tmiofb_hw_mode(struct platform_device *dev) |
314 | { | 313 | { |
315 | struct mfd_cell *cell = dev->dev.platform_data; | 314 | struct tmio_fb_data *data = mfd_get_data(dev); |
316 | struct tmio_fb_data *data = cell->driver_data; | ||
317 | struct fb_info *info = platform_get_drvdata(dev); | 315 | struct fb_info *info = platform_get_drvdata(dev); |
318 | struct fb_videomode *mode = info->mode; | 316 | struct fb_videomode *mode = info->mode; |
319 | struct tmiofb_par *par = info->par; | 317 | struct tmiofb_par *par = info->par; |
@@ -559,9 +557,8 @@ static int tmiofb_ioctl(struct fb_info *fbi, | |||
559 | static struct fb_videomode * | 557 | static struct fb_videomode * |
560 | tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var) | 558 | tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var) |
561 | { | 559 | { |
562 | struct mfd_cell *cell = | 560 | struct tmio_fb_data *data = |
563 | info->device->platform_data; | 561 | mfd_get_data(to_platform_device(info->device)); |
564 | struct tmio_fb_data *data = cell->driver_data; | ||
565 | struct fb_videomode *best = NULL; | 562 | struct fb_videomode *best = NULL; |
566 | int i; | 563 | int i; |
567 | 564 | ||
@@ -581,9 +578,8 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
581 | { | 578 | { |
582 | 579 | ||
583 | struct fb_videomode *mode; | 580 | struct fb_videomode *mode; |
584 | struct mfd_cell *cell = | 581 | struct tmio_fb_data *data = |
585 | info->device->platform_data; | 582 | mfd_get_data(to_platform_device(info->device)); |
586 | struct tmio_fb_data *data = cell->driver_data; | ||
587 | 583 | ||
588 | mode = tmiofb_find_mode(info, var); | 584 | mode = tmiofb_find_mode(info, var); |
589 | if (!mode || var->bits_per_pixel > 16) | 585 | if (!mode || var->bits_per_pixel > 16) |
@@ -683,8 +679,8 @@ static struct fb_ops tmiofb_ops = { | |||
683 | 679 | ||
684 | static int __devinit tmiofb_probe(struct platform_device *dev) | 680 | static int __devinit tmiofb_probe(struct platform_device *dev) |
685 | { | 681 | { |
686 | struct mfd_cell *cell = dev->dev.platform_data; | 682 | const struct mfd_cell *cell = mfd_get_cell(dev); |
687 | struct tmio_fb_data *data = cell->driver_data; | 683 | struct tmio_fb_data *data = mfd_get_data(dev); |
688 | struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); | 684 | struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); |
689 | struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); | 685 | struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); |
690 | struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); | 686 | struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); |
@@ -811,7 +807,7 @@ err_ioremap_ccr: | |||
811 | 807 | ||
812 | static int __devexit tmiofb_remove(struct platform_device *dev) | 808 | static int __devexit tmiofb_remove(struct platform_device *dev) |
813 | { | 809 | { |
814 | struct mfd_cell *cell = dev->dev.platform_data; | 810 | const struct mfd_cell *cell = mfd_get_cell(dev); |
815 | struct fb_info *info = platform_get_drvdata(dev); | 811 | struct fb_info *info = platform_get_drvdata(dev); |
816 | int irq = platform_get_irq(dev, 0); | 812 | int irq = platform_get_irq(dev, 0); |
817 | struct tmiofb_par *par; | 813 | struct tmiofb_par *par; |
@@ -941,7 +937,7 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) | |||
941 | #ifdef CONFIG_FB_TMIO_ACCELL | 937 | #ifdef CONFIG_FB_TMIO_ACCELL |
942 | struct tmiofb_par *par = info->par; | 938 | struct tmiofb_par *par = info->par; |
943 | #endif | 939 | #endif |
944 | struct mfd_cell *cell = dev->dev.platform_data; | 940 | const struct mfd_cell *cell = mfd_get_cell(dev); |
945 | int retval = 0; | 941 | int retval = 0; |
946 | 942 | ||
947 | console_lock(); | 943 | console_lock(); |
@@ -973,7 +969,7 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) | |||
973 | static int tmiofb_resume(struct platform_device *dev) | 969 | static int tmiofb_resume(struct platform_device *dev) |
974 | { | 970 | { |
975 | struct fb_info *info = platform_get_drvdata(dev); | 971 | struct fb_info *info = platform_get_drvdata(dev); |
976 | struct mfd_cell *cell = dev->dev.platform_data; | 972 | const struct mfd_cell *cell = mfd_get_cell(dev); |
977 | int retval = 0; | 973 | int retval = 0; |
978 | 974 | ||
979 | console_lock(); | 975 | console_lock(); |
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index 6b85e7fefa43..95921b77cf86 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c | |||
@@ -90,7 +90,7 @@ struct ds1wm_data { | |||
90 | void __iomem *map; | 90 | void __iomem *map; |
91 | int bus_shift; /* # of shifts to calc register offsets */ | 91 | int bus_shift; /* # of shifts to calc register offsets */ |
92 | struct platform_device *pdev; | 92 | struct platform_device *pdev; |
93 | struct mfd_cell *cell; | 93 | const struct mfd_cell *cell; |
94 | int irq; | 94 | int irq; |
95 | int active_high; | 95 | int active_high; |
96 | int slave_present; | 96 | int slave_present; |
@@ -216,7 +216,7 @@ static int ds1wm_find_divisor(int gclk) | |||
216 | static void ds1wm_up(struct ds1wm_data *ds1wm_data) | 216 | static void ds1wm_up(struct ds1wm_data *ds1wm_data) |
217 | { | 217 | { |
218 | int divisor; | 218 | int divisor; |
219 | struct ds1wm_driver_data *plat = ds1wm_data->cell->driver_data; | 219 | struct ds1wm_driver_data *plat = mfd_get_data(ds1wm_data->pdev); |
220 | 220 | ||
221 | if (ds1wm_data->cell->enable) | 221 | if (ds1wm_data->cell->enable) |
222 | ds1wm_data->cell->enable(ds1wm_data->pdev); | 222 | ds1wm_data->cell->enable(ds1wm_data->pdev); |
@@ -330,16 +330,11 @@ static int ds1wm_probe(struct platform_device *pdev) | |||
330 | struct ds1wm_data *ds1wm_data; | 330 | struct ds1wm_data *ds1wm_data; |
331 | struct ds1wm_driver_data *plat; | 331 | struct ds1wm_driver_data *plat; |
332 | struct resource *res; | 332 | struct resource *res; |
333 | struct mfd_cell *cell; | ||
334 | int ret; | 333 | int ret; |
335 | 334 | ||
336 | if (!pdev) | 335 | if (!pdev) |
337 | return -ENODEV; | 336 | return -ENODEV; |
338 | 337 | ||
339 | cell = pdev->dev.platform_data; | ||
340 | if (!cell) | ||
341 | return -ENODEV; | ||
342 | |||
343 | ds1wm_data = kzalloc(sizeof(*ds1wm_data), GFP_KERNEL); | 338 | ds1wm_data = kzalloc(sizeof(*ds1wm_data), GFP_KERNEL); |
344 | if (!ds1wm_data) | 339 | if (!ds1wm_data) |
345 | return -ENOMEM; | 340 | return -ENOMEM; |
@@ -356,13 +351,13 @@ static int ds1wm_probe(struct platform_device *pdev) | |||
356 | ret = -ENOMEM; | 351 | ret = -ENOMEM; |
357 | goto err0; | 352 | goto err0; |
358 | } | 353 | } |
359 | plat = cell->driver_data; | 354 | plat = mfd_get_data(pdev); |
360 | 355 | ||
361 | /* calculate bus shift from mem resource */ | 356 | /* calculate bus shift from mem resource */ |
362 | ds1wm_data->bus_shift = resource_size(res) >> 3; | 357 | ds1wm_data->bus_shift = resource_size(res) >> 3; |
363 | 358 | ||
364 | ds1wm_data->pdev = pdev; | 359 | ds1wm_data->pdev = pdev; |
365 | ds1wm_data->cell = cell; | 360 | ds1wm_data->cell = mfd_get_cell(pdev); |
366 | 361 | ||
367 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 362 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
368 | if (!res) { | 363 | if (!res) { |
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 3939e53f5f98..d8e725082fdc 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | #include <linux/mfd/rdc321x.h> | 39 | #include <linux/mfd/rdc321x.h> |
40 | #include <linux/mfd/core.h> | ||
40 | 41 | ||
41 | #define RDC_WDT_MASK 0x80000000 /* Mask */ | 42 | #define RDC_WDT_MASK 0x80000000 /* Mask */ |
42 | #define RDC_WDT_EN 0x00800000 /* Enable bit */ | 43 | #define RDC_WDT_EN 0x00800000 /* Enable bit */ |
@@ -231,7 +232,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) | |||
231 | struct resource *r; | 232 | struct resource *r; |
232 | struct rdc321x_wdt_pdata *pdata; | 233 | struct rdc321x_wdt_pdata *pdata; |
233 | 234 | ||
234 | pdata = platform_get_drvdata(pdev); | 235 | pdata = mfd_get_data(pdev); |
235 | if (!pdata) { | 236 | if (!pdata) { |
236 | dev_err(&pdev->dev, "no platform data supplied\n"); | 237 | dev_err(&pdev->dev, "no platform data supplied\n"); |
237 | return -ENODEV; | 238 | return -ENODEV; |
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 58afd9d2c438..0c0d1ae79981 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
@@ -698,6 +698,7 @@ struct twl4030_platform_data { | |||
698 | struct regulator_init_data *vana; | 698 | struct regulator_init_data *vana; |
699 | struct regulator_init_data *vcxio; | 699 | struct regulator_init_data *vcxio; |
700 | struct regulator_init_data *vusb; | 700 | struct regulator_init_data *vusb; |
701 | struct regulator_init_data *clk32kg; | ||
701 | }; | 702 | }; |
702 | 703 | ||
703 | /*----------------------------------------------------------------------*/ | 704 | /*----------------------------------------------------------------------*/ |
@@ -777,5 +778,6 @@ static inline int twl4030charger_usb_en(int enable) { return 0; } | |||
777 | 778 | ||
778 | /* INTERNAL LDOs */ | 779 | /* INTERNAL LDOs */ |
779 | #define TWL6030_REG_VRTC 47 | 780 | #define TWL6030_REG_VRTC 47 |
781 | #define TWL6030_REG_CLK32KG 48 | ||
780 | 782 | ||
781 | #endif /* End of __TWL4030_H */ | 783 | #endif /* End of __TWL4030_H */ |
diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h new file mode 100644 index 000000000000..6427d298fbfc --- /dev/null +++ b/include/linux/i2c/twl4030-madc.h | |||
@@ -0,0 +1,141 @@ | |||
1 | /* | ||
2 | * twl4030_madc.h - Header for TWL4030 MADC | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * J Keerthy <j-keerthy@ti.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _TWL4030_MADC_H | ||
24 | #define _TWL4030_MADC_H | ||
25 | |||
26 | struct twl4030_madc_conversion_method { | ||
27 | u8 sel; | ||
28 | u8 avg; | ||
29 | u8 rbase; | ||
30 | u8 ctrl; | ||
31 | }; | ||
32 | |||
33 | #define TWL4030_MADC_MAX_CHANNELS 16 | ||
34 | |||
35 | |||
36 | /* | ||
37 | * twl4030_madc_request- madc request packet for channel conversion | ||
38 | * @channels: 16 bit bitmap for individual channels | ||
39 | * @do_avgP: sample the input channel for 4 consecutive cycles | ||
40 | * @method: RT, SW1, SW2 | ||
41 | * @type: Polling or interrupt based method | ||
42 | */ | ||
43 | |||
44 | struct twl4030_madc_request { | ||
45 | unsigned long channels; | ||
46 | u16 do_avg; | ||
47 | u16 method; | ||
48 | u16 type; | ||
49 | bool active; | ||
50 | bool result_pending; | ||
51 | int rbuf[TWL4030_MADC_MAX_CHANNELS]; | ||
52 | void (*func_cb)(int len, int channels, int *buf); | ||
53 | }; | ||
54 | |||
55 | enum conversion_methods { | ||
56 | TWL4030_MADC_RT, | ||
57 | TWL4030_MADC_SW1, | ||
58 | TWL4030_MADC_SW2, | ||
59 | TWL4030_MADC_NUM_METHODS | ||
60 | }; | ||
61 | |||
62 | enum sample_type { | ||
63 | TWL4030_MADC_WAIT, | ||
64 | TWL4030_MADC_IRQ_ONESHOT, | ||
65 | TWL4030_MADC_IRQ_REARM | ||
66 | }; | ||
67 | |||
68 | #define TWL4030_MADC_CTRL1 0x00 | ||
69 | #define TWL4030_MADC_CTRL2 0x01 | ||
70 | |||
71 | #define TWL4030_MADC_RTSELECT_LSB 0x02 | ||
72 | #define TWL4030_MADC_SW1SELECT_LSB 0x06 | ||
73 | #define TWL4030_MADC_SW2SELECT_LSB 0x0A | ||
74 | |||
75 | #define TWL4030_MADC_RTAVERAGE_LSB 0x04 | ||
76 | #define TWL4030_MADC_SW1AVERAGE_LSB 0x08 | ||
77 | #define TWL4030_MADC_SW2AVERAGE_LSB 0x0C | ||
78 | |||
79 | #define TWL4030_MADC_CTRL_SW1 0x12 | ||
80 | #define TWL4030_MADC_CTRL_SW2 0x13 | ||
81 | |||
82 | #define TWL4030_MADC_RTCH0_LSB 0x17 | ||
83 | #define TWL4030_MADC_GPCH0_LSB 0x37 | ||
84 | |||
85 | #define TWL4030_MADC_MADCON (1 << 0) /* MADC power on */ | ||
86 | #define TWL4030_MADC_BUSY (1 << 0) /* MADC busy */ | ||
87 | /* MADC conversion completion */ | ||
88 | #define TWL4030_MADC_EOC_SW (1 << 1) | ||
89 | /* MADC SWx start conversion */ | ||
90 | #define TWL4030_MADC_SW_START (1 << 5) | ||
91 | #define TWL4030_MADC_ADCIN0 (1 << 0) | ||
92 | #define TWL4030_MADC_ADCIN1 (1 << 1) | ||
93 | #define TWL4030_MADC_ADCIN2 (1 << 2) | ||
94 | #define TWL4030_MADC_ADCIN3 (1 << 3) | ||
95 | #define TWL4030_MADC_ADCIN4 (1 << 4) | ||
96 | #define TWL4030_MADC_ADCIN5 (1 << 5) | ||
97 | #define TWL4030_MADC_ADCIN6 (1 << 6) | ||
98 | #define TWL4030_MADC_ADCIN7 (1 << 7) | ||
99 | #define TWL4030_MADC_ADCIN8 (1 << 8) | ||
100 | #define TWL4030_MADC_ADCIN9 (1 << 9) | ||
101 | #define TWL4030_MADC_ADCIN10 (1 << 10) | ||
102 | #define TWL4030_MADC_ADCIN11 (1 << 11) | ||
103 | #define TWL4030_MADC_ADCIN12 (1 << 12) | ||
104 | #define TWL4030_MADC_ADCIN13 (1 << 13) | ||
105 | #define TWL4030_MADC_ADCIN14 (1 << 14) | ||
106 | #define TWL4030_MADC_ADCIN15 (1 << 15) | ||
107 | |||
108 | /* Fixed channels */ | ||
109 | #define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1 | ||
110 | #define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8 | ||
111 | #define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9 | ||
112 | #define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10 | ||
113 | #define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11 | ||
114 | #define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12 | ||
115 | |||
116 | /* Step size and prescaler ratio */ | ||
117 | #define TEMP_STEP_SIZE 147 | ||
118 | #define TEMP_PSR_R 100 | ||
119 | #define CURR_STEP_SIZE 147 | ||
120 | #define CURR_PSR_R1 44 | ||
121 | #define CURR_PSR_R2 88 | ||
122 | |||
123 | #define TWL4030_BCI_BCICTL1 0x23 | ||
124 | #define TWL4030_BCI_CGAIN 0x020 | ||
125 | #define TWL4030_BCI_MESBAT (1 << 1) | ||
126 | #define TWL4030_BCI_TYPEN (1 << 4) | ||
127 | #define TWL4030_BCI_ITHEN (1 << 3) | ||
128 | |||
129 | #define REG_BCICTL2 0x024 | ||
130 | #define TWL4030_BCI_ITHSENS 0x007 | ||
131 | |||
132 | struct twl4030_madc_user_parms { | ||
133 | int channel; | ||
134 | int average; | ||
135 | int status; | ||
136 | u16 result; | ||
137 | }; | ||
138 | |||
139 | int twl4030_madc_conversion(struct twl4030_madc_request *conv); | ||
140 | int twl4030_get_madc_conversion(int channel_no); | ||
141 | #endif | ||
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h index 4db1fbd8969e..8fba7972ff5f 100644 --- a/include/linux/mfd/88pm860x.h +++ b/include/linux/mfd/88pm860x.h | |||
@@ -131,9 +131,11 @@ enum { | |||
131 | PM8607_ID_LDO8, | 131 | PM8607_ID_LDO8, |
132 | PM8607_ID_LDO9, | 132 | PM8607_ID_LDO9, |
133 | PM8607_ID_LDO10, | 133 | PM8607_ID_LDO10, |
134 | PM8607_ID_LDO11, | ||
134 | PM8607_ID_LDO12, | 135 | PM8607_ID_LDO12, |
135 | PM8607_ID_LDO13, | 136 | PM8607_ID_LDO13, |
136 | PM8607_ID_LDO14, | 137 | PM8607_ID_LDO14, |
138 | PM8607_ID_LDO15, | ||
137 | 139 | ||
138 | PM8607_ID_RG_MAX, | 140 | PM8607_ID_RG_MAX, |
139 | }; | 141 | }; |
@@ -310,8 +312,6 @@ struct pm860x_chip { | |||
310 | 312 | ||
311 | }; | 313 | }; |
312 | 314 | ||
313 | #define PM8607_MAX_REGULATOR PM8607_ID_RG_MAX /* 3 Bucks, 13 LDOs */ | ||
314 | |||
315 | enum { | 315 | enum { |
316 | GI2C_PORT = 0, | 316 | GI2C_PORT = 0, |
317 | PI2C_PORT, | 317 | PI2C_PORT, |
@@ -351,23 +351,31 @@ struct pm860x_platform_data { | |||
351 | struct pm860x_led_pdata *led; | 351 | struct pm860x_led_pdata *led; |
352 | struct pm860x_touch_pdata *touch; | 352 | struct pm860x_touch_pdata *touch; |
353 | struct pm860x_power_pdata *power; | 353 | struct pm860x_power_pdata *power; |
354 | struct regulator_init_data *regulator; | ||
354 | 355 | ||
355 | unsigned short companion_addr; /* I2C address of companion chip */ | 356 | unsigned short companion_addr; /* I2C address of companion chip */ |
356 | int i2c_port; /* Controlled by GI2C or PI2C */ | 357 | int i2c_port; /* Controlled by GI2C or PI2C */ |
357 | int irq_mode; /* Clear interrupt by read/write(0/1) */ | 358 | int irq_mode; /* Clear interrupt by read/write(0/1) */ |
358 | int irq_base; /* IRQ base number of 88pm860x */ | 359 | int irq_base; /* IRQ base number of 88pm860x */ |
359 | struct regulator_init_data *regulator[PM8607_MAX_REGULATOR]; | 360 | int num_leds; |
361 | int num_backlights; | ||
362 | int num_regulators; | ||
360 | }; | 363 | }; |
361 | 364 | ||
362 | extern char pm860x_backlight_name[][MFD_NAME_SIZE]; | ||
363 | extern char pm860x_led_name[][MFD_NAME_SIZE]; | ||
364 | |||
365 | extern int pm860x_reg_read(struct i2c_client *, int); | 365 | extern int pm860x_reg_read(struct i2c_client *, int); |
366 | extern int pm860x_reg_write(struct i2c_client *, int, unsigned char); | 366 | extern int pm860x_reg_write(struct i2c_client *, int, unsigned char); |
367 | extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *); | 367 | extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *); |
368 | extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *); | 368 | extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *); |
369 | extern int pm860x_set_bits(struct i2c_client *, int, unsigned char, | 369 | extern int pm860x_set_bits(struct i2c_client *, int, unsigned char, |
370 | unsigned char); | 370 | unsigned char); |
371 | extern int pm860x_page_reg_read(struct i2c_client *, int); | ||
372 | extern int pm860x_page_reg_write(struct i2c_client *, int, unsigned char); | ||
373 | extern int pm860x_page_bulk_read(struct i2c_client *, int, int, | ||
374 | unsigned char *); | ||
375 | extern int pm860x_page_bulk_write(struct i2c_client *, int, int, | ||
376 | unsigned char *); | ||
377 | extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char, | ||
378 | unsigned char); | ||
371 | 379 | ||
372 | extern int pm860x_device_init(struct pm860x_chip *chip, | 380 | extern int pm860x_device_init(struct pm860x_chip *chip, |
373 | struct pm860x_platform_data *pdata) __devinit ; | 381 | struct pm860x_platform_data *pdata) __devinit ; |
diff --git a/include/linux/mfd/ab8500.h b/include/linux/mfd/ab8500.h index 37f56b7c4c15..56f8dea72152 100644 --- a/include/linux/mfd/ab8500.h +++ b/include/linux/mfd/ab8500.h | |||
@@ -111,8 +111,8 @@ | |||
111 | * @dev: parent device | 111 | * @dev: parent device |
112 | * @lock: read/write operations lock | 112 | * @lock: read/write operations lock |
113 | * @irq_lock: genirq bus lock | 113 | * @irq_lock: genirq bus lock |
114 | * @revision: chip revision | ||
115 | * @irq: irq line | 114 | * @irq: irq line |
115 | * @chip_id: chip revision id | ||
116 | * @write: register write | 116 | * @write: register write |
117 | * @read: register read | 117 | * @read: register read |
118 | * @rx_buf: rx buf for SPI | 118 | * @rx_buf: rx buf for SPI |
@@ -124,7 +124,7 @@ struct ab8500 { | |||
124 | struct device *dev; | 124 | struct device *dev; |
125 | struct mutex lock; | 125 | struct mutex lock; |
126 | struct mutex irq_lock; | 126 | struct mutex irq_lock; |
127 | int revision; | 127 | |
128 | int irq_base; | 128 | int irq_base; |
129 | int irq; | 129 | int irq; |
130 | u8 chip_id; | 130 | u8 chip_id; |
diff --git a/include/linux/mfd/ab8500/gpadc.h b/include/linux/mfd/ab8500/gpadc.h new file mode 100644 index 000000000000..46b954011f16 --- /dev/null +++ b/include/linux/mfd/ab8500/gpadc.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 ST-Ericsson SA | ||
3 | * Licensed under GPLv2. | ||
4 | * | ||
5 | * Author: Arun R Murthy <arun.murthy@stericsson.com> | ||
6 | * Author: Daniel Willerud <daniel.willerud@stericsson.com> | ||
7 | */ | ||
8 | |||
9 | #ifndef _AB8500_GPADC_H | ||
10 | #define _AB8500_GPADC_H | ||
11 | |||
12 | /* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2) */ | ||
13 | #define BAT_CTRL 0x01 | ||
14 | #define BTEMP_BALL 0x02 | ||
15 | #define MAIN_CHARGER_V 0x03 | ||
16 | #define ACC_DETECT1 0x04 | ||
17 | #define ACC_DETECT2 0x05 | ||
18 | #define ADC_AUX1 0x06 | ||
19 | #define ADC_AUX2 0x07 | ||
20 | #define MAIN_BAT_V 0x08 | ||
21 | #define VBUS_V 0x09 | ||
22 | #define MAIN_CHARGER_C 0x0A | ||
23 | #define USB_CHARGER_C 0x0B | ||
24 | #define BK_BAT_V 0x0C | ||
25 | #define DIE_TEMP 0x0D | ||
26 | |||
27 | struct ab8500_gpadc; | ||
28 | |||
29 | struct ab8500_gpadc *ab8500_gpadc_get(char *name); | ||
30 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input); | ||
31 | |||
32 | #endif /* _AB8500_GPADC_H */ | ||
diff --git a/include/linux/mfd/ab8500/sysctrl.h b/include/linux/mfd/ab8500/sysctrl.h new file mode 100644 index 000000000000..10da0291f8f8 --- /dev/null +++ b/include/linux/mfd/ab8500/sysctrl.h | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST Ericsson. | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | #ifndef __AB8500_SYSCTRL_H | ||
7 | #define __AB8500_SYSCTRL_H | ||
8 | |||
9 | #include <linux/bitops.h> | ||
10 | |||
11 | #ifdef CONFIG_AB8500_CORE | ||
12 | |||
13 | int ab8500_sysctrl_read(u16 reg, u8 *value); | ||
14 | int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value); | ||
15 | |||
16 | #else | ||
17 | |||
18 | static inline int ab8500_sysctrl_read(u16 reg, u8 *value) | ||
19 | { | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | static inline int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) | ||
24 | { | ||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | #endif /* CONFIG_AB8500_CORE */ | ||
29 | |||
30 | static inline int ab8500_sysctrl_set(u16 reg, u8 bits) | ||
31 | { | ||
32 | return ab8500_sysctrl_write(reg, bits, bits); | ||
33 | } | ||
34 | |||
35 | static inline int ab8500_sysctrl_clear(u16 reg, u8 bits) | ||
36 | { | ||
37 | return ab8500_sysctrl_write(reg, bits, 0); | ||
38 | } | ||
39 | |||
40 | /* Registers */ | ||
41 | #define AB8500_TURNONSTATUS 0x100 | ||
42 | #define AB8500_RESETSTATUS 0x101 | ||
43 | #define AB8500_PONKEY1PRESSSTATUS 0x102 | ||
44 | #define AB8500_SYSCLKREQSTATUS 0x142 | ||
45 | #define AB8500_STW4500CTRL1 0x180 | ||
46 | #define AB8500_STW4500CTRL2 0x181 | ||
47 | #define AB8500_STW4500CTRL3 0x200 | ||
48 | #define AB8500_MAINWDOGCTRL 0x201 | ||
49 | #define AB8500_MAINWDOGTIMER 0x202 | ||
50 | #define AB8500_LOWBAT 0x203 | ||
51 | #define AB8500_BATTOK 0x204 | ||
52 | #define AB8500_SYSCLKTIMER 0x205 | ||
53 | #define AB8500_SMPSCLKCTRL 0x206 | ||
54 | #define AB8500_SMPSCLKSEL1 0x207 | ||
55 | #define AB8500_SMPSCLKSEL2 0x208 | ||
56 | #define AB8500_SMPSCLKSEL3 0x209 | ||
57 | #define AB8500_SYSULPCLKCONF 0x20A | ||
58 | #define AB8500_SYSULPCLKCTRL1 0x20B | ||
59 | #define AB8500_SYSCLKCTRL 0x20C | ||
60 | #define AB8500_SYSCLKREQ1VALID 0x20D | ||
61 | #define AB8500_SYSTEMCTRLSUP 0x20F | ||
62 | #define AB8500_SYSCLKREQ1RFCLKBUF 0x210 | ||
63 | #define AB8500_SYSCLKREQ2RFCLKBUF 0x211 | ||
64 | #define AB8500_SYSCLKREQ3RFCLKBUF 0x212 | ||
65 | #define AB8500_SYSCLKREQ4RFCLKBUF 0x213 | ||
66 | #define AB8500_SYSCLKREQ5RFCLKBUF 0x214 | ||
67 | #define AB8500_SYSCLKREQ6RFCLKBUF 0x215 | ||
68 | #define AB8500_SYSCLKREQ7RFCLKBUF 0x216 | ||
69 | #define AB8500_SYSCLKREQ8RFCLKBUF 0x217 | ||
70 | #define AB8500_DITHERCLKCTRL 0x220 | ||
71 | #define AB8500_SWATCTRL 0x230 | ||
72 | #define AB8500_HIQCLKCTRL 0x232 | ||
73 | #define AB8500_VSIMSYSCLKCTRL 0x233 | ||
74 | |||
75 | /* Bits */ | ||
76 | #define AB8500_TURNONSTATUS_PORNVBAT BIT(0) | ||
77 | #define AB8500_TURNONSTATUS_PONKEY1DBF BIT(1) | ||
78 | #define AB8500_TURNONSTATUS_PONKEY2DBF BIT(2) | ||
79 | #define AB8500_TURNONSTATUS_RTCALARM BIT(3) | ||
80 | #define AB8500_TURNONSTATUS_MAINCHDET BIT(4) | ||
81 | #define AB8500_TURNONSTATUS_VBUSDET BIT(5) | ||
82 | #define AB8500_TURNONSTATUS_USBIDDETECT BIT(6) | ||
83 | |||
84 | #define AB8500_RESETSTATUS_RESETN4500NSTATUS BIT(0) | ||
85 | #define AB8500_RESETSTATUS_SWRESETN4500NSTATUS BIT(2) | ||
86 | |||
87 | #define AB8500_PONKEY1PRESSSTATUS_PONKEY1PRESSTIME_MASK 0x7F | ||
88 | #define AB8500_PONKEY1PRESSSTATUS_PONKEY1PRESSTIME_SHIFT 0 | ||
89 | |||
90 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ1STATUS BIT(0) | ||
91 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ2STATUS BIT(1) | ||
92 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ3STATUS BIT(2) | ||
93 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ4STATUS BIT(3) | ||
94 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ5STATUS BIT(4) | ||
95 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ6STATUS BIT(5) | ||
96 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ7STATUS BIT(6) | ||
97 | #define AB8500_SYSCLKREQSTATUS_SYSCLKREQ8STATUS BIT(7) | ||
98 | |||
99 | #define AB8500_STW4500CTRL1_SWOFF BIT(0) | ||
100 | #define AB8500_STW4500CTRL1_SWRESET4500N BIT(1) | ||
101 | #define AB8500_STW4500CTRL1_THDB8500SWOFF BIT(2) | ||
102 | |||
103 | #define AB8500_STW4500CTRL2_RESETNVAUX1VALID BIT(0) | ||
104 | #define AB8500_STW4500CTRL2_RESETNVAUX2VALID BIT(1) | ||
105 | #define AB8500_STW4500CTRL2_RESETNVAUX3VALID BIT(2) | ||
106 | #define AB8500_STW4500CTRL2_RESETNVMODVALID BIT(3) | ||
107 | #define AB8500_STW4500CTRL2_RESETNVEXTSUPPLY1VALID BIT(4) | ||
108 | #define AB8500_STW4500CTRL2_RESETNVEXTSUPPLY2VALID BIT(5) | ||
109 | #define AB8500_STW4500CTRL2_RESETNVEXTSUPPLY3VALID BIT(6) | ||
110 | #define AB8500_STW4500CTRL2_RESETNVSMPS1VALID BIT(7) | ||
111 | |||
112 | #define AB8500_STW4500CTRL3_CLK32KOUT2DIS BIT(0) | ||
113 | #define AB8500_STW4500CTRL3_RESETAUDN BIT(1) | ||
114 | #define AB8500_STW4500CTRL3_RESETDENCN BIT(2) | ||
115 | #define AB8500_STW4500CTRL3_THSDENA BIT(3) | ||
116 | |||
117 | #define AB8500_MAINWDOGCTRL_MAINWDOGENA BIT(0) | ||
118 | #define AB8500_MAINWDOGCTRL_MAINWDOGKICK BIT(1) | ||
119 | #define AB8500_MAINWDOGCTRL_WDEXPTURNONVALID BIT(4) | ||
120 | |||
121 | #define AB8500_MAINWDOGTIMER_MAINWDOGTIMER_MASK 0x7F | ||
122 | #define AB8500_MAINWDOGTIMER_MAINWDOGTIMER_SHIFT 0 | ||
123 | |||
124 | #define AB8500_LOWBAT_LOWBATENA BIT(0) | ||
125 | #define AB8500_LOWBAT_LOWBAT_MASK 0x7E | ||
126 | #define AB8500_LOWBAT_LOWBAT_SHIFT 1 | ||
127 | |||
128 | #define AB8500_BATTOK_BATTOKSEL0THF_MASK 0x0F | ||
129 | #define AB8500_BATTOK_BATTOKSEL0THF_SHIFT 0 | ||
130 | #define AB8500_BATTOK_BATTOKSEL1THF_MASK 0xF0 | ||
131 | #define AB8500_BATTOK_BATTOKSEL1THF_SHIFT 4 | ||
132 | |||
133 | #define AB8500_SYSCLKTIMER_SYSCLKTIMER_MASK 0x0F | ||
134 | #define AB8500_SYSCLKTIMER_SYSCLKTIMER_SHIFT 0 | ||
135 | #define AB8500_SYSCLKTIMER_SYSCLKTIMERADJ_MASK 0xF0 | ||
136 | #define AB8500_SYSCLKTIMER_SYSCLKTIMERADJ_SHIFT 4 | ||
137 | |||
138 | #define AB8500_SMPSCLKCTRL_SMPSCLKINTSEL_MASK 0x03 | ||
139 | #define AB8500_SMPSCLKCTRL_SMPSCLKINTSEL_SHIFT 0 | ||
140 | #define AB8500_SMPSCLKCTRL_3M2CLKINTENA BIT(2) | ||
141 | |||
142 | #define AB8500_SMPSCLKSEL1_VARMCLKSEL_MASK 0x07 | ||
143 | #define AB8500_SMPSCLKSEL1_VARMCLKSEL_SHIFT 0 | ||
144 | #define AB8500_SMPSCLKSEL1_VAPECLKSEL_MASK 0x38 | ||
145 | #define AB8500_SMPSCLKSEL1_VAPECLKSEL_SHIFT 3 | ||
146 | |||
147 | #define AB8500_SMPSCLKSEL2_VMODCLKSEL_MASK 0x07 | ||
148 | #define AB8500_SMPSCLKSEL2_VMODCLKSEL_SHIFT 0 | ||
149 | #define AB8500_SMPSCLKSEL2_VSMPS1CLKSEL_MASK 0x38 | ||
150 | #define AB8500_SMPSCLKSEL2_VSMPS1CLKSEL_SHIFT 3 | ||
151 | |||
152 | #define AB8500_SMPSCLKSEL3_VSMPS2CLKSEL_MASK 0x07 | ||
153 | #define AB8500_SMPSCLKSEL3_VSMPS2CLKSEL_SHIFT 0 | ||
154 | #define AB8500_SMPSCLKSEL3_VSMPS3CLKSEL_MASK 0x38 | ||
155 | #define AB8500_SMPSCLKSEL3_VSMPS3CLKSEL_SHIFT 3 | ||
156 | |||
157 | #define AB8500_SYSULPCLKCONF_ULPCLKCONF_MASK 0x03 | ||
158 | #define AB8500_SYSULPCLKCONF_ULPCLKCONF_SHIFT 0 | ||
159 | #define AB8500_SYSULPCLKCONF_CLK27MHZSTRE BIT(2) | ||
160 | #define AB8500_SYSULPCLKCONF_TVOUTCLKDELN BIT(3) | ||
161 | #define AB8500_SYSULPCLKCONF_TVOUTCLKINV BIT(4) | ||
162 | #define AB8500_SYSULPCLKCONF_ULPCLKSTRE BIT(5) | ||
163 | #define AB8500_SYSULPCLKCONF_CLK27MHZBUFENA BIT(6) | ||
164 | #define AB8500_SYSULPCLKCONF_CLK27MHZPDENA BIT(7) | ||
165 | |||
166 | #define AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK 0x03 | ||
167 | #define AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT 0 | ||
168 | #define AB8500_SYSULPCLKCTRL1_ULPCLKREQ BIT(2) | ||
169 | #define AB8500_SYSULPCLKCTRL1_4500SYSCLKREQ BIT(3) | ||
170 | #define AB8500_SYSULPCLKCTRL1_AUDIOCLKENA BIT(4) | ||
171 | #define AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ BIT(5) | ||
172 | #define AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ BIT(6) | ||
173 | #define AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ BIT(7) | ||
174 | |||
175 | #define AB8500_SYSCLKCTRL_TVOUTPLLENA BIT(0) | ||
176 | #define AB8500_SYSCLKCTRL_TVOUTCLKENA BIT(1) | ||
177 | #define AB8500_SYSCLKCTRL_USBCLKENA BIT(2) | ||
178 | |||
179 | #define AB8500_SYSCLKREQ1VALID_SYSCLKREQ1VALID BIT(0) | ||
180 | #define AB8500_SYSCLKREQ1VALID_ULPCLKREQ1VALID BIT(1) | ||
181 | #define AB8500_SYSCLKREQ1VALID_USBSYSCLKREQ1VALID BIT(2) | ||
182 | |||
183 | #define AB8500_SYSTEMCTRLSUP_EXTSUP12LPNCLKSEL_MASK 0x03 | ||
184 | #define AB8500_SYSTEMCTRLSUP_EXTSUP12LPNCLKSEL_SHIFT 0 | ||
185 | #define AB8500_SYSTEMCTRLSUP_EXTSUP3LPNCLKSEL_MASK 0x0C | ||
186 | #define AB8500_SYSTEMCTRLSUP_EXTSUP3LPNCLKSEL_SHIFT 2 | ||
187 | #define AB8500_SYSTEMCTRLSUP_INTDB8500NOD BIT(4) | ||
188 | |||
189 | #define AB8500_SYSCLKREQ1RFCLKBUF_SYSCLKREQ1RFCLKBUF2 BIT(2) | ||
190 | #define AB8500_SYSCLKREQ1RFCLKBUF_SYSCLKREQ1RFCLKBUF3 BIT(3) | ||
191 | #define AB8500_SYSCLKREQ1RFCLKBUF_SYSCLKREQ1RFCLKBUF4 BIT(4) | ||
192 | |||
193 | #define AB8500_SYSCLKREQ2RFCLKBUF_SYSCLKREQ2RFCLKBUF2 BIT(2) | ||
194 | #define AB8500_SYSCLKREQ2RFCLKBUF_SYSCLKREQ2RFCLKBUF3 BIT(3) | ||
195 | #define AB8500_SYSCLKREQ2RFCLKBUF_SYSCLKREQ2RFCLKBUF4 BIT(4) | ||
196 | |||
197 | #define AB8500_SYSCLKREQ3RFCLKBUF_SYSCLKREQ3RFCLKBUF2 BIT(2) | ||
198 | #define AB8500_SYSCLKREQ3RFCLKBUF_SYSCLKREQ3RFCLKBUF3 BIT(3) | ||
199 | #define AB8500_SYSCLKREQ3RFCLKBUF_SYSCLKREQ3RFCLKBUF4 BIT(4) | ||
200 | |||
201 | #define AB8500_SYSCLKREQ4RFCLKBUF_SYSCLKREQ4RFCLKBUF2 BIT(2) | ||
202 | #define AB8500_SYSCLKREQ4RFCLKBUF_SYSCLKREQ4RFCLKBUF3 BIT(3) | ||
203 | #define AB8500_SYSCLKREQ4RFCLKBUF_SYSCLKREQ4RFCLKBUF4 BIT(4) | ||
204 | |||
205 | #define AB8500_SYSCLKREQ5RFCLKBUF_SYSCLKREQ5RFCLKBUF2 BIT(2) | ||
206 | #define AB8500_SYSCLKREQ5RFCLKBUF_SYSCLKREQ5RFCLKBUF3 BIT(3) | ||
207 | #define AB8500_SYSCLKREQ5RFCLKBUF_SYSCLKREQ5RFCLKBUF4 BIT(4) | ||
208 | |||
209 | #define AB8500_SYSCLKREQ6RFCLKBUF_SYSCLKREQ6RFCLKBUF2 BIT(2) | ||
210 | #define AB8500_SYSCLKREQ6RFCLKBUF_SYSCLKREQ6RFCLKBUF3 BIT(3) | ||
211 | #define AB8500_SYSCLKREQ6RFCLKBUF_SYSCLKREQ6RFCLKBUF4 BIT(4) | ||
212 | |||
213 | #define AB8500_SYSCLKREQ7RFCLKBUF_SYSCLKREQ7RFCLKBUF2 BIT(2) | ||
214 | #define AB8500_SYSCLKREQ7RFCLKBUF_SYSCLKREQ7RFCLKBUF3 BIT(3) | ||
215 | #define AB8500_SYSCLKREQ7RFCLKBUF_SYSCLKREQ7RFCLKBUF4 BIT(4) | ||
216 | |||
217 | #define AB8500_SYSCLKREQ8RFCLKBUF_SYSCLKREQ8RFCLKBUF2 BIT(2) | ||
218 | #define AB8500_SYSCLKREQ8RFCLKBUF_SYSCLKREQ8RFCLKBUF3 BIT(3) | ||
219 | #define AB8500_SYSCLKREQ8RFCLKBUF_SYSCLKREQ8RFCLKBUF4 BIT(4) | ||
220 | |||
221 | #define AB8500_DITHERCLKCTRL_VARMDITHERENA BIT(0) | ||
222 | #define AB8500_DITHERCLKCTRL_VSMPS3DITHERENA BIT(1) | ||
223 | #define AB8500_DITHERCLKCTRL_VSMPS1DITHERENA BIT(2) | ||
224 | #define AB8500_DITHERCLKCTRL_VSMPS2DITHERENA BIT(3) | ||
225 | #define AB8500_DITHERCLKCTRL_VMODDITHERENA BIT(4) | ||
226 | #define AB8500_DITHERCLKCTRL_VAPEDITHERENA BIT(5) | ||
227 | #define AB8500_DITHERCLKCTRL_DITHERDEL_MASK 0xC0 | ||
228 | #define AB8500_DITHERCLKCTRL_DITHERDEL_SHIFT 6 | ||
229 | |||
230 | #define AB8500_SWATCTRL_UPDATERF BIT(0) | ||
231 | #define AB8500_SWATCTRL_SWATENABLE BIT(1) | ||
232 | #define AB8500_SWATCTRL_RFOFFTIMER_MASK 0x1C | ||
233 | #define AB8500_SWATCTRL_RFOFFTIMER_SHIFT 2 | ||
234 | #define AB8500_SWATCTRL_SWATBIT5 BIT(6) | ||
235 | |||
236 | #define AB8500_HIQCLKCTRL_SYSCLKREQ1HIQENAVALID BIT(0) | ||
237 | #define AB8500_HIQCLKCTRL_SYSCLKREQ2HIQENAVALID BIT(1) | ||
238 | #define AB8500_HIQCLKCTRL_SYSCLKREQ3HIQENAVALID BIT(2) | ||
239 | #define AB8500_HIQCLKCTRL_SYSCLKREQ4HIQENAVALID BIT(3) | ||
240 | #define AB8500_HIQCLKCTRL_SYSCLKREQ5HIQENAVALID BIT(4) | ||
241 | #define AB8500_HIQCLKCTRL_SYSCLKREQ6HIQENAVALID BIT(5) | ||
242 | #define AB8500_HIQCLKCTRL_SYSCLKREQ7HIQENAVALID BIT(6) | ||
243 | #define AB8500_HIQCLKCTRL_SYSCLKREQ8HIQENAVALID BIT(7) | ||
244 | |||
245 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ1VALID BIT(0) | ||
246 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ2VALID BIT(1) | ||
247 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ3VALID BIT(2) | ||
248 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ4VALID BIT(3) | ||
249 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ5VALID BIT(4) | ||
250 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ6VALID BIT(5) | ||
251 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ7VALID BIT(6) | ||
252 | #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ8VALID BIT(7) | ||
253 | |||
254 | #endif /* __AB8500_SYSCTRL_H */ | ||
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 67bd6f7ecf32..7d9b6ae1c203 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h | |||
@@ -186,7 +186,6 @@ struct abx500_init_settings { | |||
186 | struct ab3550_platform_data { | 186 | struct ab3550_platform_data { |
187 | struct {unsigned int base; unsigned int count; } irq; | 187 | struct {unsigned int base; unsigned int count; } irq; |
188 | void *dev_data[AB3550_NUM_DEVICES]; | 188 | void *dev_data[AB3550_NUM_DEVICES]; |
189 | size_t dev_data_sz[AB3550_NUM_DEVICES]; | ||
190 | struct abx500_init_settings *init_settings; | 189 | struct abx500_init_settings *init_settings; |
191 | unsigned int init_settings_sz; | 190 | unsigned int init_settings_sz; |
192 | }; | 191 | }; |
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 835996e167e1..1408bf8eed5f 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h | |||
@@ -25,22 +25,20 @@ struct mfd_cell { | |||
25 | const char *name; | 25 | const char *name; |
26 | int id; | 26 | int id; |
27 | 27 | ||
28 | /* refcounting for multiple drivers to use a single cell */ | ||
29 | atomic_t *usage_count; | ||
28 | int (*enable)(struct platform_device *dev); | 30 | int (*enable)(struct platform_device *dev); |
29 | int (*disable)(struct platform_device *dev); | 31 | int (*disable)(struct platform_device *dev); |
32 | |||
30 | int (*suspend)(struct platform_device *dev); | 33 | int (*suspend)(struct platform_device *dev); |
31 | int (*resume)(struct platform_device *dev); | 34 | int (*resume)(struct platform_device *dev); |
32 | 35 | ||
33 | /* driver-specific data for MFD-aware "cell" drivers */ | 36 | /* mfd_data can be used to pass data to client drivers */ |
34 | void *driver_data; | 37 | void *mfd_data; |
35 | |||
36 | /* platform_data can be used to either pass data to "generic" | ||
37 | driver or as a hook to mfd_cell for the "cell" drivers */ | ||
38 | void *platform_data; | ||
39 | size_t data_size; | ||
40 | 38 | ||
41 | /* | 39 | /* |
42 | * This resources can be specified relatively to the parent device. | 40 | * These resources can be specified relative to the parent device. |
43 | * For accessing device you should use resources from device | 41 | * For accessing hardware you should use resources from the platform dev |
44 | */ | 42 | */ |
45 | int num_resources; | 43 | int num_resources; |
46 | const struct resource *resources; | 44 | const struct resource *resources; |
@@ -55,11 +53,47 @@ struct mfd_cell { | |||
55 | bool pm_runtime_no_callbacks; | 53 | bool pm_runtime_no_callbacks; |
56 | }; | 54 | }; |
57 | 55 | ||
56 | /* | ||
57 | * Convenience functions for clients using shared cells. Refcounting | ||
58 | * happens automatically, with the cell's enable/disable callbacks | ||
59 | * being called only when a device is first being enabled or no other | ||
60 | * clients are making use of it. | ||
61 | */ | ||
62 | extern int mfd_cell_enable(struct platform_device *pdev); | ||
63 | extern int mfd_cell_disable(struct platform_device *pdev); | ||
64 | |||
65 | /* | ||
66 | * Given a platform device that's been created by mfd_add_devices(), fetch | ||
67 | * the mfd_cell that created it. | ||
68 | */ | ||
69 | static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) | ||
70 | { | ||
71 | return pdev->dev.platform_data; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Given a platform device that's been created by mfd_add_devices(), fetch | ||
76 | * the .mfd_data entry from the mfd_cell that created it. | ||
77 | */ | ||
78 | static inline void *mfd_get_data(struct platform_device *pdev) | ||
79 | { | ||
80 | return mfd_get_cell(pdev)->mfd_data; | ||
81 | } | ||
82 | |||
58 | extern int mfd_add_devices(struct device *parent, int id, | 83 | extern int mfd_add_devices(struct device *parent, int id, |
59 | const struct mfd_cell *cells, int n_devs, | 84 | struct mfd_cell *cells, int n_devs, |
60 | struct resource *mem_base, | 85 | struct resource *mem_base, |
61 | int irq_base); | 86 | int irq_base); |
62 | 87 | ||
63 | extern void mfd_remove_devices(struct device *parent); | 88 | extern void mfd_remove_devices(struct device *parent); |
64 | 89 | ||
90 | /* | ||
91 | * For MFD drivers with clients sharing access to resources, these create | ||
92 | * multiple platform devices per cell. Contention handling must still be | ||
93 | * handled via drivers (ie, with enable/disable hooks). | ||
94 | */ | ||
95 | extern int mfd_shared_platform_driver_register(struct platform_driver *drv, | ||
96 | const char *cellname); | ||
97 | extern void mfd_shared_platform_driver_unregister(struct platform_driver *drv); | ||
98 | |||
65 | #endif | 99 | #endif |
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h new file mode 100644 index 000000000000..93a9477e075f --- /dev/null +++ b/include/linux/mfd/max8997-private.h | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * max8997.h - Voltage regulator driver for the Maxim 8997 | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electrnoics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef __LINUX_MFD_MAX8997_PRIV_H | ||
23 | #define __LINUX_MFD_MAX8997_PRIV_H | ||
24 | |||
25 | #include <linux/i2c.h> | ||
26 | |||
27 | enum max8997_pmic_reg { | ||
28 | MAX8997_REG_PMIC_ID0 = 0x00, | ||
29 | MAX8997_REG_PMIC_ID1 = 0x01, | ||
30 | MAX8997_REG_INTSRC = 0x02, | ||
31 | MAX8997_REG_INT1 = 0x03, | ||
32 | MAX8997_REG_INT2 = 0x04, | ||
33 | MAX8997_REG_INT3 = 0x05, | ||
34 | MAX8997_REG_INT4 = 0x06, | ||
35 | |||
36 | MAX8997_REG_INT1MSK = 0x08, | ||
37 | MAX8997_REG_INT2MSK = 0x09, | ||
38 | MAX8997_REG_INT3MSK = 0x0a, | ||
39 | MAX8997_REG_INT4MSK = 0x0b, | ||
40 | |||
41 | MAX8997_REG_STATUS1 = 0x0d, | ||
42 | MAX8997_REG_STATUS2 = 0x0e, | ||
43 | MAX8997_REG_STATUS3 = 0x0f, | ||
44 | MAX8997_REG_STATUS4 = 0x10, | ||
45 | |||
46 | MAX8997_REG_MAINCON1 = 0x13, | ||
47 | MAX8997_REG_MAINCON2 = 0x14, | ||
48 | MAX8997_REG_BUCKRAMP = 0x15, | ||
49 | |||
50 | MAX8997_REG_BUCK1CTRL = 0x18, | ||
51 | MAX8997_REG_BUCK1DVS1 = 0x19, | ||
52 | MAX8997_REG_BUCK1DVS2 = 0x1a, | ||
53 | MAX8997_REG_BUCK1DVS3 = 0x1b, | ||
54 | MAX8997_REG_BUCK1DVS4 = 0x1c, | ||
55 | MAX8997_REG_BUCK1DVS5 = 0x1d, | ||
56 | MAX8997_REG_BUCK1DVS6 = 0x1e, | ||
57 | MAX8997_REG_BUCK1DVS7 = 0x1f, | ||
58 | MAX8997_REG_BUCK1DVS8 = 0x20, | ||
59 | MAX8997_REG_BUCK2CTRL = 0x21, | ||
60 | MAX8997_REG_BUCK2DVS1 = 0x22, | ||
61 | MAX8997_REG_BUCK2DVS2 = 0x23, | ||
62 | MAX8997_REG_BUCK2DVS3 = 0x24, | ||
63 | MAX8997_REG_BUCK2DVS4 = 0x25, | ||
64 | MAX8997_REG_BUCK2DVS5 = 0x26, | ||
65 | MAX8997_REG_BUCK2DVS6 = 0x27, | ||
66 | MAX8997_REG_BUCK2DVS7 = 0x28, | ||
67 | MAX8997_REG_BUCK2DVS8 = 0x29, | ||
68 | MAX8997_REG_BUCK3CTRL = 0x2a, | ||
69 | MAX8997_REG_BUCK3DVS = 0x2b, | ||
70 | MAX8997_REG_BUCK4CTRL = 0x2c, | ||
71 | MAX8997_REG_BUCK4DVS = 0x2d, | ||
72 | MAX8997_REG_BUCK5CTRL = 0x2e, | ||
73 | MAX8997_REG_BUCK5DVS1 = 0x2f, | ||
74 | MAX8997_REG_BUCK5DVS2 = 0x30, | ||
75 | MAX8997_REG_BUCK5DVS3 = 0x31, | ||
76 | MAX8997_REG_BUCK5DVS4 = 0x32, | ||
77 | MAX8997_REG_BUCK5DVS5 = 0x33, | ||
78 | MAX8997_REG_BUCK5DVS6 = 0x34, | ||
79 | MAX8997_REG_BUCK5DVS7 = 0x35, | ||
80 | MAX8997_REG_BUCK5DVS8 = 0x36, | ||
81 | MAX8997_REG_BUCK6CTRL = 0x37, | ||
82 | MAX8997_REG_BUCK6BPSKIPCTRL = 0x38, | ||
83 | MAX8997_REG_BUCK7CTRL = 0x39, | ||
84 | MAX8997_REG_BUCK7DVS = 0x3a, | ||
85 | MAX8997_REG_LDO1CTRL = 0x3b, | ||
86 | MAX8997_REG_LDO2CTRL = 0x3c, | ||
87 | MAX8997_REG_LDO3CTRL = 0x3d, | ||
88 | MAX8997_REG_LDO4CTRL = 0x3e, | ||
89 | MAX8997_REG_LDO5CTRL = 0x3f, | ||
90 | MAX8997_REG_LDO6CTRL = 0x40, | ||
91 | MAX8997_REG_LDO7CTRL = 0x41, | ||
92 | MAX8997_REG_LDO8CTRL = 0x42, | ||
93 | MAX8997_REG_LDO9CTRL = 0x43, | ||
94 | MAX8997_REG_LDO10CTRL = 0x44, | ||
95 | MAX8997_REG_LDO11CTRL = 0x45, | ||
96 | MAX8997_REG_LDO12CTRL = 0x46, | ||
97 | MAX8997_REG_LDO13CTRL = 0x47, | ||
98 | MAX8997_REG_LDO14CTRL = 0x48, | ||
99 | MAX8997_REG_LDO15CTRL = 0x49, | ||
100 | MAX8997_REG_LDO16CTRL = 0x4a, | ||
101 | MAX8997_REG_LDO17CTRL = 0x4b, | ||
102 | MAX8997_REG_LDO18CTRL = 0x4c, | ||
103 | MAX8997_REG_LDO21CTRL = 0x4d, | ||
104 | |||
105 | MAX8997_REG_MBCCTRL1 = 0x50, | ||
106 | MAX8997_REG_MBCCTRL2 = 0x51, | ||
107 | MAX8997_REG_MBCCTRL3 = 0x52, | ||
108 | MAX8997_REG_MBCCTRL4 = 0x53, | ||
109 | MAX8997_REG_MBCCTRL5 = 0x54, | ||
110 | MAX8997_REG_MBCCTRL6 = 0x55, | ||
111 | MAX8997_REG_OTPCGHCVS = 0x56, | ||
112 | |||
113 | MAX8997_REG_SAFEOUTCTRL = 0x5a, | ||
114 | |||
115 | MAX8997_REG_LBCNFG1 = 0x5e, | ||
116 | MAX8997_REG_LBCNFG2 = 0x5f, | ||
117 | MAX8997_REG_BBCCTRL = 0x60, | ||
118 | |||
119 | MAX8997_REG_FLASH1_CUR = 0x63, /* 0x63 ~ 0x6e for FLASH */ | ||
120 | MAX8997_REG_FLASH2_CUR = 0x64, | ||
121 | MAX8997_REG_MOVIE_CUR = 0x65, | ||
122 | MAX8997_REG_GSMB_CUR = 0x66, | ||
123 | MAX8997_REG_BOOST_CNTL = 0x67, | ||
124 | MAX8997_REG_LEN_CNTL = 0x68, | ||
125 | MAX8997_REG_FLASH_CNTL = 0x69, | ||
126 | MAX8997_REG_WDT_CNTL = 0x6a, | ||
127 | MAX8997_REG_MAXFLASH1 = 0x6b, | ||
128 | MAX8997_REG_MAXFLASH2 = 0x6c, | ||
129 | MAX8997_REG_FLASHSTATUS = 0x6d, | ||
130 | MAX8997_REG_FLASHSTATUSMASK = 0x6e, | ||
131 | |||
132 | MAX8997_REG_GPIOCNTL1 = 0x70, | ||
133 | MAX8997_REG_GPIOCNTL2 = 0x71, | ||
134 | MAX8997_REG_GPIOCNTL3 = 0x72, | ||
135 | MAX8997_REG_GPIOCNTL4 = 0x73, | ||
136 | MAX8997_REG_GPIOCNTL5 = 0x74, | ||
137 | MAX8997_REG_GPIOCNTL6 = 0x75, | ||
138 | MAX8997_REG_GPIOCNTL7 = 0x76, | ||
139 | MAX8997_REG_GPIOCNTL8 = 0x77, | ||
140 | MAX8997_REG_GPIOCNTL9 = 0x78, | ||
141 | MAX8997_REG_GPIOCNTL10 = 0x79, | ||
142 | MAX8997_REG_GPIOCNTL11 = 0x7a, | ||
143 | MAX8997_REG_GPIOCNTL12 = 0x7b, | ||
144 | |||
145 | MAX8997_REG_LDO1CONFIG = 0x80, | ||
146 | MAX8997_REG_LDO2CONFIG = 0x81, | ||
147 | MAX8997_REG_LDO3CONFIG = 0x82, | ||
148 | MAX8997_REG_LDO4CONFIG = 0x83, | ||
149 | MAX8997_REG_LDO5CONFIG = 0x84, | ||
150 | MAX8997_REG_LDO6CONFIG = 0x85, | ||
151 | MAX8997_REG_LDO7CONFIG = 0x86, | ||
152 | MAX8997_REG_LDO8CONFIG = 0x87, | ||
153 | MAX8997_REG_LDO9CONFIG = 0x88, | ||
154 | MAX8997_REG_LDO10CONFIG = 0x89, | ||
155 | MAX8997_REG_LDO11CONFIG = 0x8a, | ||
156 | MAX8997_REG_LDO12CONFIG = 0x8b, | ||
157 | MAX8997_REG_LDO13CONFIG = 0x8c, | ||
158 | MAX8997_REG_LDO14CONFIG = 0x8d, | ||
159 | MAX8997_REG_LDO15CONFIG = 0x8e, | ||
160 | MAX8997_REG_LDO16CONFIG = 0x8f, | ||
161 | MAX8997_REG_LDO17CONFIG = 0x90, | ||
162 | MAX8997_REG_LDO18CONFIG = 0x91, | ||
163 | MAX8997_REG_LDO21CONFIG = 0x92, | ||
164 | |||
165 | MAX8997_REG_DVSOKTIMER1 = 0x97, | ||
166 | MAX8997_REG_DVSOKTIMER2 = 0x98, | ||
167 | MAX8997_REG_DVSOKTIMER4 = 0x99, | ||
168 | MAX8997_REG_DVSOKTIMER5 = 0x9a, | ||
169 | |||
170 | MAX8997_REG_PMIC_END = 0x9b, | ||
171 | }; | ||
172 | |||
173 | enum max8997_muic_reg { | ||
174 | MAX8997_MUIC_REG_ID = 0x0, | ||
175 | MAX8997_MUIC_REG_INT1 = 0x1, | ||
176 | MAX8997_MUIC_REG_INT2 = 0x2, | ||
177 | MAX8997_MUIC_REG_INT3 = 0x3, | ||
178 | MAX8997_MUIC_REG_STATUS1 = 0x4, | ||
179 | MAX8997_MUIC_REG_STATUS2 = 0x5, | ||
180 | MAX8997_MUIC_REG_STATUS3 = 0x6, | ||
181 | MAX8997_MUIC_REG_INTMASK1 = 0x7, | ||
182 | MAX8997_MUIC_REG_INTMASK2 = 0x8, | ||
183 | MAX8997_MUIC_REG_INTMASK3 = 0x9, | ||
184 | MAX8997_MUIC_REG_CDETCTRL = 0xa, | ||
185 | |||
186 | MAX8997_MUIC_REG_CONTROL1 = 0xc, | ||
187 | MAX8997_MUIC_REG_CONTROL2 = 0xd, | ||
188 | MAX8997_MUIC_REG_CONTROL3 = 0xe, | ||
189 | |||
190 | MAX8997_MUIC_REG_END = 0xf, | ||
191 | }; | ||
192 | |||
193 | enum max8997_haptic_reg { | ||
194 | MAX8997_HAPTIC_REG_GENERAL = 0x00, | ||
195 | MAX8997_HAPTIC_REG_CONF1 = 0x01, | ||
196 | MAX8997_HAPTIC_REG_CONF2 = 0x02, | ||
197 | MAX8997_HAPTIC_REG_DRVCONF = 0x03, | ||
198 | MAX8997_HAPTIC_REG_CYCLECONF1 = 0x04, | ||
199 | MAX8997_HAPTIC_REG_CYCLECONF2 = 0x05, | ||
200 | MAX8997_HAPTIC_REG_SIGCONF1 = 0x06, | ||
201 | MAX8997_HAPTIC_REG_SIGCONF2 = 0x07, | ||
202 | MAX8997_HAPTIC_REG_SIGCONF3 = 0x08, | ||
203 | MAX8997_HAPTIC_REG_SIGCONF4 = 0x09, | ||
204 | MAX8997_HAPTIC_REG_SIGDC1 = 0x0a, | ||
205 | MAX8997_HAPTIC_REG_SIGDC2 = 0x0b, | ||
206 | MAX8997_HAPTIC_REG_SIGPWMDC1 = 0x0c, | ||
207 | MAX8997_HAPTIC_REG_SIGPWMDC2 = 0x0d, | ||
208 | MAX8997_HAPTIC_REG_SIGPWMDC3 = 0x0e, | ||
209 | MAX8997_HAPTIC_REG_SIGPWMDC4 = 0x0f, | ||
210 | MAX8997_HAPTIC_REG_MTR_REV = 0x10, | ||
211 | |||
212 | MAX8997_HAPTIC_REG_END = 0x11, | ||
213 | }; | ||
214 | |||
215 | /* slave addr = 0x0c: using "2nd part" of rev4 datasheet */ | ||
216 | enum max8997_rtc_reg { | ||
217 | MAX8997_RTC_CTRLMASK = 0x02, | ||
218 | MAX8997_RTC_CTRL = 0x03, | ||
219 | MAX8997_RTC_UPDATE1 = 0x04, | ||
220 | MAX8997_RTC_UPDATE2 = 0x05, | ||
221 | MAX8997_RTC_WTSR_SMPL = 0x06, | ||
222 | |||
223 | MAX8997_RTC_SEC = 0x10, | ||
224 | MAX8997_RTC_MIN = 0x11, | ||
225 | MAX8997_RTC_HOUR = 0x12, | ||
226 | MAX8997_RTC_DAY_OF_WEEK = 0x13, | ||
227 | MAX8997_RTC_MONTH = 0x14, | ||
228 | MAX8997_RTC_YEAR = 0x15, | ||
229 | MAX8997_RTC_DAY_OF_MONTH = 0x16, | ||
230 | MAX8997_RTC_ALARM1_SEC = 0x17, | ||
231 | MAX8997_RTC_ALARM1_MIN = 0x18, | ||
232 | MAX8997_RTC_ALARM1_HOUR = 0x19, | ||
233 | MAX8997_RTC_ALARM1_DAY_OF_WEEK = 0x1a, | ||
234 | MAX8997_RTC_ALARM1_MONTH = 0x1b, | ||
235 | MAX8997_RTC_ALARM1_YEAR = 0x1c, | ||
236 | MAX8997_RTC_ALARM1_DAY_OF_MONTH = 0x1d, | ||
237 | MAX8997_RTC_ALARM2_SEC = 0x1e, | ||
238 | MAX8997_RTC_ALARM2_MIN = 0x1f, | ||
239 | MAX8997_RTC_ALARM2_HOUR = 0x20, | ||
240 | MAX8997_RTC_ALARM2_DAY_OF_WEEK = 0x21, | ||
241 | MAX8997_RTC_ALARM2_MONTH = 0x22, | ||
242 | MAX8997_RTC_ALARM2_YEAR = 0x23, | ||
243 | MAX8997_RTC_ALARM2_DAY_OF_MONTH = 0x24, | ||
244 | }; | ||
245 | |||
246 | enum max8997_irq_source { | ||
247 | PMIC_INT1 = 0, | ||
248 | PMIC_INT2, | ||
249 | PMIC_INT3, | ||
250 | PMIC_INT4, | ||
251 | |||
252 | FUEL_GAUGE, /* Ignored (MAX17042 driver handles) */ | ||
253 | |||
254 | MUIC_INT1, | ||
255 | MUIC_INT2, | ||
256 | MUIC_INT3, | ||
257 | |||
258 | GPIO_LOW, /* Not implemented */ | ||
259 | GPIO_HI, /* Not implemented */ | ||
260 | |||
261 | FLASH_STATUS, /* Not implemented */ | ||
262 | |||
263 | MAX8997_IRQ_GROUP_NR, | ||
264 | }; | ||
265 | |||
266 | enum max8997_irq { | ||
267 | MAX8997_PMICIRQ_PWRONR, | ||
268 | MAX8997_PMICIRQ_PWRONF, | ||
269 | MAX8997_PMICIRQ_PWRON1SEC, | ||
270 | MAX8997_PMICIRQ_JIGONR, | ||
271 | MAX8997_PMICIRQ_JIGONF, | ||
272 | MAX8997_PMICIRQ_LOWBAT2, | ||
273 | MAX8997_PMICIRQ_LOWBAT1, | ||
274 | |||
275 | MAX8997_PMICIRQ_JIGR, | ||
276 | MAX8997_PMICIRQ_JIGF, | ||
277 | MAX8997_PMICIRQ_MR, | ||
278 | MAX8997_PMICIRQ_DVS1OK, | ||
279 | MAX8997_PMICIRQ_DVS2OK, | ||
280 | MAX8997_PMICIRQ_DVS3OK, | ||
281 | MAX8997_PMICIRQ_DVS4OK, | ||
282 | |||
283 | MAX8997_PMICIRQ_CHGINS, | ||
284 | MAX8997_PMICIRQ_CHGRM, | ||
285 | MAX8997_PMICIRQ_DCINOVP, | ||
286 | MAX8997_PMICIRQ_TOPOFFR, | ||
287 | MAX8997_PMICIRQ_CHGRSTF, | ||
288 | MAX8997_PMICIRQ_MBCHGTMEXPD, | ||
289 | |||
290 | MAX8997_PMICIRQ_RTC60S, | ||
291 | MAX8997_PMICIRQ_RTCA1, | ||
292 | MAX8997_PMICIRQ_RTCA2, | ||
293 | MAX8997_PMICIRQ_SMPL_INT, | ||
294 | MAX8997_PMICIRQ_RTC1S, | ||
295 | MAX8997_PMICIRQ_WTSR, | ||
296 | |||
297 | MAX8997_MUICIRQ_ADCError, | ||
298 | MAX8997_MUICIRQ_ADCLow, | ||
299 | MAX8997_MUICIRQ_ADC, | ||
300 | |||
301 | MAX8997_MUICIRQ_VBVolt, | ||
302 | MAX8997_MUICIRQ_DBChg, | ||
303 | MAX8997_MUICIRQ_DCDTmr, | ||
304 | MAX8997_MUICIRQ_ChgDetRun, | ||
305 | MAX8997_MUICIRQ_ChgTyp, | ||
306 | |||
307 | MAX8997_MUICIRQ_OVP, | ||
308 | |||
309 | MAX8997_IRQ_NR, | ||
310 | }; | ||
311 | |||
312 | #define MAX8997_REG_BUCK1DVS(x) (MAX8997_REG_BUCK1DVS1 + (x) - 1) | ||
313 | #define MAX8997_REG_BUCK2DVS(x) (MAX8997_REG_BUCK2DVS1 + (x) - 1) | ||
314 | #define MAX8997_REG_BUCK5DVS(x) (MAX8997_REG_BUCK5DVS1 + (x) - 1) | ||
315 | |||
316 | struct max8997_dev { | ||
317 | struct device *dev; | ||
318 | struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */ | ||
319 | struct i2c_client *rtc; /* slave addr 0x0c */ | ||
320 | struct i2c_client *haptic; /* slave addr 0x90 */ | ||
321 | struct i2c_client *muic; /* slave addr 0x4a */ | ||
322 | struct mutex iolock; | ||
323 | |||
324 | int type; | ||
325 | struct platform_device *battery; /* battery control (not fuel gauge) */ | ||
326 | |||
327 | bool wakeup; | ||
328 | |||
329 | /* For hibernation */ | ||
330 | u8 reg_dump[MAX8997_REG_PMIC_END + MAX8997_MUIC_REG_END + | ||
331 | MAX8997_HAPTIC_REG_END]; | ||
332 | }; | ||
333 | |||
334 | enum max8997_types { | ||
335 | TYPE_MAX8997, | ||
336 | TYPE_MAX8966, | ||
337 | }; | ||
338 | |||
339 | extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest); | ||
340 | extern int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, | ||
341 | u8 *buf); | ||
342 | extern int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value); | ||
343 | extern int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, | ||
344 | u8 *buf); | ||
345 | extern int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask); | ||
346 | |||
347 | #endif /* __LINUX_MFD_MAX8997_PRIV_H */ | ||
diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h new file mode 100644 index 000000000000..cb671b3451bf --- /dev/null +++ b/include/linux/mfd/max8997.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * max8997.h - Driver for the Maxim 8997/8966 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electrnoics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | * This driver is based on max8998.h | ||
22 | * | ||
23 | * MAX8997 has PMIC, MUIC, HAPTIC, RTC, FLASH, and Fuel Gauge devices. | ||
24 | * Except Fuel Gauge, every device shares the same I2C bus and included in | ||
25 | * this mfd driver. Although the fuel gauge is included in the chip, it is | ||
26 | * excluded from the driver because a) it has a different I2C bus from | ||
27 | * others and b) it can be enabled simply by using MAX17042 driver. | ||
28 | */ | ||
29 | |||
30 | #ifndef __LINUX_MFD_MAX8998_H | ||
31 | #define __LINUX_MFD_MAX8998_H | ||
32 | |||
33 | #include <linux/regulator/consumer.h> | ||
34 | |||
35 | /* MAX8997/8966 regulator IDs */ | ||
36 | enum max8998_regulators { | ||
37 | MAX8997_LDO1 = 0, | ||
38 | MAX8997_LDO2, | ||
39 | MAX8997_LDO3, | ||
40 | MAX8997_LDO4, | ||
41 | MAX8997_LDO5, | ||
42 | MAX8997_LDO6, | ||
43 | MAX8997_LDO7, | ||
44 | MAX8997_LDO8, | ||
45 | MAX8997_LDO9, | ||
46 | MAX8997_LDO10, | ||
47 | MAX8997_LDO11, | ||
48 | MAX8997_LDO12, | ||
49 | MAX8997_LDO13, | ||
50 | MAX8997_LDO14, | ||
51 | MAX8997_LDO15, | ||
52 | MAX8997_LDO16, | ||
53 | MAX8997_LDO17, | ||
54 | MAX8997_LDO18, | ||
55 | MAX8997_LDO21, | ||
56 | MAX8997_BUCK1, | ||
57 | MAX8997_BUCK2, | ||
58 | MAX8997_BUCK3, | ||
59 | MAX8997_BUCK4, | ||
60 | MAX8997_BUCK5, | ||
61 | MAX8997_BUCK6, | ||
62 | MAX8997_BUCK7, | ||
63 | MAX8997_EN32KHZ_AP, | ||
64 | MAX8997_EN32KHZ_CP, | ||
65 | MAX8997_ENVICHG, | ||
66 | MAX8997_ESAFEOUT1, | ||
67 | MAX8997_ESAFEOUT2, | ||
68 | MAX8997_CHARGER_CV, /* control MBCCV of MBCCTRL3 */ | ||
69 | MAX8997_CHARGER, /* charger current, MBCCTRL4 */ | ||
70 | MAX8997_CHARGER_TOPOFF, /* MBCCTRL5 */ | ||
71 | |||
72 | MAX8997_REG_MAX, | ||
73 | }; | ||
74 | |||
75 | struct max8997_regulator_data { | ||
76 | int id; | ||
77 | struct regulator_init_data *initdata; | ||
78 | }; | ||
79 | |||
80 | struct max8997_platform_data { | ||
81 | bool wakeup; | ||
82 | /* IRQ: Not implemented */ | ||
83 | /* ---- PMIC ---- */ | ||
84 | struct max8997_regulator_data *regulators; | ||
85 | int num_regulators; | ||
86 | |||
87 | /* | ||
88 | * SET1~3 DVS GPIOs control Buck1, 2, and 5 simultaneously. Therefore, | ||
89 | * With buckx_gpiodvs enabled, the buckx cannot be controlled | ||
90 | * independently. To control buckx (of 1, 2, and 5) independently, | ||
91 | * disable buckx_gpiodvs and control with BUCKxDVS1 register. | ||
92 | * | ||
93 | * When buckx_gpiodvs and bucky_gpiodvs are both enabled, set_voltage | ||
94 | * on buckx will change the voltage of bucky at the same time. | ||
95 | * | ||
96 | */ | ||
97 | bool ignore_gpiodvs_side_effect; | ||
98 | int buck125_gpios[3]; /* GPIO of [0]SET1, [1]SET2, [2]SET3 */ | ||
99 | int buck125_default_idx; /* Default value of SET1, 2, 3 */ | ||
100 | unsigned int buck1_voltage[8]; /* buckx_voltage in uV */ | ||
101 | bool buck1_gpiodvs; | ||
102 | unsigned int buck2_voltage[8]; | ||
103 | bool buck2_gpiodvs; | ||
104 | unsigned int buck5_voltage[8]; | ||
105 | bool buck5_gpiodvs; | ||
106 | |||
107 | /* MUIC: Not implemented */ | ||
108 | /* HAPTIC: Not implemented */ | ||
109 | /* RTC: Not implemented */ | ||
110 | /* Flash: Not implemented */ | ||
111 | /* Charger control: Not implemented */ | ||
112 | }; | ||
113 | |||
114 | #endif /* __LINUX_MFD_MAX8998_H */ | ||
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h index a1d391b40e68..c064beaaccb7 100644 --- a/include/linux/mfd/mc13xxx.h +++ b/include/linux/mfd/mc13xxx.h | |||
@@ -146,8 +146,7 @@ struct mc13xxx_platform_data { | |||
146 | #define MC13XXX_USE_LED (1 << 5) | 146 | #define MC13XXX_USE_LED (1 << 5) |
147 | unsigned int flags; | 147 | unsigned int flags; |
148 | 148 | ||
149 | int num_regulators; | 149 | struct mc13xxx_regulator_platform_data regulators; |
150 | struct mc13xxx_regulator_init_data *regulators; | ||
151 | struct mc13xxx_leds_platform_data *leds; | 150 | struct mc13xxx_leds_platform_data *leds; |
152 | }; | 151 | }; |
153 | 152 | ||
diff --git a/include/linux/mfd/tps6105x.h b/include/linux/mfd/tps6105x.h new file mode 100644 index 000000000000..386743dd931c --- /dev/null +++ b/include/linux/mfd/tps6105x.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 ST-Ericsson SA | ||
3 | * Written on behalf of Linaro for ST-Ericsson | ||
4 | * | ||
5 | * Author: Linus Walleij <linus.walleij@linaro.org> | ||
6 | * | ||
7 | * License terms: GNU General Public License (GPL) version 2 | ||
8 | */ | ||
9 | #ifndef MFD_TPS6105X_H | ||
10 | #define MFD_TPS6105X_H | ||
11 | |||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/regulator/machine.h> | ||
14 | |||
15 | /* | ||
16 | * Register definitions to all subdrivers | ||
17 | */ | ||
18 | #define TPS6105X_REG_0 0x00 | ||
19 | #define TPS6105X_REG0_MODE_SHIFT 6 | ||
20 | #define TPS6105X_REG0_MODE_MASK (0x03<<6) | ||
21 | /* These defines for both reg0 and reg1 */ | ||
22 | #define TPS6105X_REG0_MODE_SHUTDOWN 0x00 | ||
23 | #define TPS6105X_REG0_MODE_TORCH 0x01 | ||
24 | #define TPS6105X_REG0_MODE_TORCH_FLASH 0x02 | ||
25 | #define TPS6105X_REG0_MODE_VOLTAGE 0x03 | ||
26 | #define TPS6105X_REG0_VOLTAGE_SHIFT 4 | ||
27 | #define TPS6105X_REG0_VOLTAGE_MASK (3<<4) | ||
28 | #define TPS6105X_REG0_VOLTAGE_450 0 | ||
29 | #define TPS6105X_REG0_VOLTAGE_500 1 | ||
30 | #define TPS6105X_REG0_VOLTAGE_525 2 | ||
31 | #define TPS6105X_REG0_VOLTAGE_500_2 3 | ||
32 | #define TPS6105X_REG0_DIMMING_SHIFT 3 | ||
33 | #define TPS6105X_REG0_TORCHC_SHIFT 0 | ||
34 | #define TPS6105X_REG0_TORCHC_MASK (7<<0) | ||
35 | #define TPS6105X_REG0_TORCHC_0 0x00 | ||
36 | #define TPS6105X_REG0_TORCHC_50 0x01 | ||
37 | #define TPS6105X_REG0_TORCHC_75 0x02 | ||
38 | #define TPS6105X_REG0_TORCHC_100 0x03 | ||
39 | #define TPS6105X_REG0_TORCHC_150 0x04 | ||
40 | #define TPS6105X_REG0_TORCHC_200 0x05 | ||
41 | #define TPS6105X_REG0_TORCHC_250_400 0x06 | ||
42 | #define TPS6105X_REG0_TORCHC_250_500 0x07 | ||
43 | #define TPS6105X_REG_1 0x01 | ||
44 | #define TPS6105X_REG1_MODE_SHIFT 6 | ||
45 | #define TPS6105X_REG1_MODE_MASK (0x03<<6) | ||
46 | #define TPS6105X_REG1_MODE_SHUTDOWN 0x00 | ||
47 | #define TPS6105X_REG1_MODE_TORCH 0x01 | ||
48 | #define TPS6105X_REG1_MODE_TORCH_FLASH 0x02 | ||
49 | #define TPS6105X_REG1_MODE_VOLTAGE 0x03 | ||
50 | #define TPS6105X_REG_2 0x02 | ||
51 | #define TPS6105X_REG_3 0x03 | ||
52 | |||
53 | /** | ||
54 | * enum tps6105x_mode - desired mode for the TPS6105x | ||
55 | * @TPS6105X_MODE_SHUTDOWN: this instance is inactive, not used for anything | ||
56 | * @TPS61905X_MODE_TORCH: this instance is used as a LED, usually a while | ||
57 | * LED, for example as backlight or flashlight. If this is set, the | ||
58 | * TPS6105X will register to the LED framework | ||
59 | * @TPS6105X_MODE_TORCH_FLASH: this instance is used as a flashgun, usually | ||
60 | * in a camera | ||
61 | * @TPS6105X_MODE_VOLTAGE: this instance is used as a voltage regulator and | ||
62 | * will register to the regulator framework | ||
63 | */ | ||
64 | enum tps6105x_mode { | ||
65 | TPS6105X_MODE_SHUTDOWN, | ||
66 | TPS6105X_MODE_TORCH, | ||
67 | TPS6105X_MODE_TORCH_FLASH, | ||
68 | TPS6105X_MODE_VOLTAGE, | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * struct tps6105x_platform_data - TPS61905x platform data | ||
73 | * @mode: what mode this instance shall be operated in, | ||
74 | * this is not selectable at runtime | ||
75 | * @regulator_data: initialization data for the voltage | ||
76 | * regulator if used as a voltage source | ||
77 | */ | ||
78 | struct tps6105x_platform_data { | ||
79 | enum tps6105x_mode mode; | ||
80 | struct regulator_init_data *regulator_data; | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * struct tps6105x - state holder for the TPS6105x drivers | ||
85 | * @mutex: mutex to serialize I2C accesses | ||
86 | * @i2c_client: corresponding I2C client | ||
87 | * @regulator: regulator device if used in voltage mode | ||
88 | */ | ||
89 | struct tps6105x { | ||
90 | struct tps6105x_platform_data *pdata; | ||
91 | struct mutex lock; | ||
92 | struct i2c_client *client; | ||
93 | struct regulator_dev *regulator; | ||
94 | }; | ||
95 | |||
96 | extern int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value); | ||
97 | extern int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf); | ||
98 | extern int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg, | ||
99 | u8 bitmask, u8 bitvalues); | ||
100 | |||
101 | #endif | ||
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 173086d42af4..afe4db49402d 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h | |||
@@ -104,11 +104,17 @@ struct wm831x_watchdog_pdata { | |||
104 | #define WM831X_MAX_ISINK 2 | 104 | #define WM831X_MAX_ISINK 2 |
105 | 105 | ||
106 | struct wm831x_pdata { | 106 | struct wm831x_pdata { |
107 | /** Used to distinguish multiple WM831x chips */ | ||
108 | int wm831x_num; | ||
109 | |||
107 | /** Called before subdevices are set up */ | 110 | /** Called before subdevices are set up */ |
108 | int (*pre_init)(struct wm831x *wm831x); | 111 | int (*pre_init)(struct wm831x *wm831x); |
109 | /** Called after subdevices are set up */ | 112 | /** Called after subdevices are set up */ |
110 | int (*post_init)(struct wm831x *wm831x); | 113 | int (*post_init)(struct wm831x *wm831x); |
111 | 114 | ||
115 | /** Put the /IRQ line into CMOS mode */ | ||
116 | bool irq_cmos; | ||
117 | |||
112 | int irq_base; | 118 | int irq_base; |
113 | int gpio_base; | 119 | int gpio_base; |
114 | struct wm831x_backlight_pdata *backlight; | 120 | struct wm831x_backlight_pdata *backlight; |
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h index ef4f0b6083a3..f0b69cdae41c 100644 --- a/include/linux/mfd/wm8994/core.h +++ b/include/linux/mfd/wm8994/core.h | |||
@@ -59,7 +59,7 @@ struct wm8994 { | |||
59 | int (*read_dev)(struct wm8994 *wm8994, unsigned short reg, | 59 | int (*read_dev)(struct wm8994 *wm8994, unsigned short reg, |
60 | int bytes, void *dest); | 60 | int bytes, void *dest); |
61 | int (*write_dev)(struct wm8994 *wm8994, unsigned short reg, | 61 | int (*write_dev)(struct wm8994 *wm8994, unsigned short reg, |
62 | int bytes, void *src); | 62 | int bytes, const void *src); |
63 | 63 | ||
64 | void *control_data; | 64 | void *control_data; |
65 | 65 | ||
@@ -88,6 +88,8 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, | |||
88 | unsigned short mask, unsigned short val); | 88 | unsigned short mask, unsigned short val); |
89 | int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, | 89 | int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, |
90 | int count, u16 *buf); | 90 | int count, u16 *buf); |
91 | int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg, | ||
92 | int count, const u16 *buf); | ||
91 | 93 | ||
92 | 94 | ||
93 | /* Helper to save on boilerplate */ | 95 | /* Helper to save on boilerplate */ |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bda221dfaf0a..11fd38151cc9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2737,6 +2737,7 @@ | |||
2737 | #define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 | 2737 | #define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 |
2738 | #define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119 | 2738 | #define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119 |
2739 | #define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a | 2739 | #define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a |
2740 | #define PCI_DEVICE_ID_INTEL_ITC_LPC 0x8186 | ||
2740 | #define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 | 2741 | #define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 |
2741 | #define PCI_DEVICE_ID_INTEL_82450GX 0x84c5 | 2742 | #define PCI_DEVICE_ID_INTEL_82450GX 0x84c5 |
2742 | #define PCI_DEVICE_ID_INTEL_82451NX 0x84ca | 2743 | #define PCI_DEVICE_ID_INTEL_82451NX 0x84ca |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 347a567b01e1..b8066ef10bb0 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -153,7 +153,8 @@ static int cq93vc_resume(struct snd_soc_codec *codec) | |||
153 | 153 | ||
154 | static int cq93vc_probe(struct snd_soc_codec *codec) | 154 | static int cq93vc_probe(struct snd_soc_codec *codec) |
155 | { | 155 | { |
156 | struct davinci_vc *davinci_vc = snd_soc_codec_get_drvdata(codec); | 156 | struct davinci_vc *davinci_vc = |
157 | mfd_get_data(to_platform_device(codec->dev)); | ||
157 | 158 | ||
158 | davinci_vc->cq93vc.codec = codec; | 159 | davinci_vc->cq93vc.codec = codec; |
159 | codec->control_data = davinci_vc; | 160 | codec->control_data = davinci_vc; |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index e4d464b937d6..8512800f6326 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/mfd/core.h> | ||
29 | #include <linux/i2c/twl.h> | 30 | #include <linux/i2c/twl.h> |
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
31 | #include <sound/core.h> | 32 | #include <sound/core.h> |
@@ -732,7 +733,8 @@ static int aif_event(struct snd_soc_dapm_widget *w, | |||
732 | 733 | ||
733 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 734 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
734 | { | 735 | { |
735 | struct twl4030_codec_audio_data *pdata = codec->dev->platform_data; | 736 | struct twl4030_codec_audio_data *pdata = |
737 | mfd_get_data(to_platform_device(codec->dev)); | ||
736 | unsigned char hs_gain, hs_pop; | 738 | unsigned char hs_gain, hs_pop; |
737 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 739 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
738 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ | 740 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ |
@@ -2297,7 +2299,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | |||
2297 | 2299 | ||
2298 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) | 2300 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) |
2299 | { | 2301 | { |
2300 | struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; | 2302 | struct twl4030_codec_audio_data *pdata = mfd_get_data(pdev); |
2301 | 2303 | ||
2302 | if (!pdata) { | 2304 | if (!pdata) { |
2303 | dev_err(&pdev->dev, "platform_data is missing\n"); | 2305 | dev_err(&pdev->dev, "platform_data is missing\n"); |
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index 861b28f543d2..1ad0d5aecece 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c | |||
@@ -436,7 +436,8 @@ EXPORT_SYMBOL_GPL(wl1273_get_format); | |||
436 | 436 | ||
437 | static int wl1273_probe(struct snd_soc_codec *codec) | 437 | static int wl1273_probe(struct snd_soc_codec *codec) |
438 | { | 438 | { |
439 | struct wl1273_core **core = codec->dev->platform_data; | 439 | struct wl1273_core **core = |
440 | mfd_get_data(to_platform_device(codec->dev)); | ||
440 | struct wl1273_priv *wl1273; | 441 | struct wl1273_priv *wl1273; |
441 | int r; | 442 | int r; |
442 | 443 | ||
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 3c3bc079167e..736b785e3756 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
23 | #include <linux/mfd/wm8400-audio.h> | 23 | #include <linux/mfd/wm8400-audio.h> |
24 | #include <linux/mfd/wm8400-private.h> | 24 | #include <linux/mfd/wm8400-private.h> |
25 | #include <linux/mfd/core.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
27 | #include <sound/pcm_params.h> | 28 | #include <sound/pcm_params.h> |
@@ -1377,7 +1378,7 @@ static void wm8400_probe_deferred(struct work_struct *work) | |||
1377 | 1378 | ||
1378 | static int wm8400_codec_probe(struct snd_soc_codec *codec) | 1379 | static int wm8400_codec_probe(struct snd_soc_codec *codec) |
1379 | { | 1380 | { |
1380 | struct wm8400 *wm8400 = dev_get_platdata(codec->dev); | 1381 | struct wm8400 *wm8400 = mfd_get_data(to_platform_device(codec->dev)); |
1381 | struct wm8400_priv *priv; | 1382 | struct wm8400_priv *priv; |
1382 | int ret; | 1383 | int ret; |
1383 | u16 reg; | 1384 | u16 reg; |
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 9d2afccc3a2d..13e05a302a92 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
@@ -205,7 +205,7 @@ static struct snd_soc_dai_driver davinci_vcif_dai = { | |||
205 | 205 | ||
206 | static int davinci_vcif_probe(struct platform_device *pdev) | 206 | static int davinci_vcif_probe(struct platform_device *pdev) |
207 | { | 207 | { |
208 | struct davinci_vc *davinci_vc = platform_get_drvdata(pdev); | 208 | struct davinci_vc *davinci_vc = mfd_get_data(pdev); |
209 | struct davinci_vcif_dev *davinci_vcif_dev; | 209 | struct davinci_vcif_dev *davinci_vcif_dev; |
210 | int ret; | 210 | int ret; |
211 | 211 | ||