diff options
93 files changed, 3330 insertions, 534 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d54d551004f7..21a871c0527a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -931,6 +931,8 @@ F: drivers/mmc/host/msm_sdcc.h | |||
931 | F: drivers/tty/serial/msm_serial.h | 931 | F: drivers/tty/serial/msm_serial.h |
932 | F: drivers/tty/serial/msm_serial.c | 932 | F: drivers/tty/serial/msm_serial.c |
933 | F: drivers/platform/msm/ | 933 | F: drivers/platform/msm/ |
934 | F: drivers/*/pm8???-* | ||
935 | F: include/linux/mfd/pm8xxx/ | ||
934 | T: git git://codeaurora.org/quic/kernel/davidb/linux-msm.git | 936 | T: git git://codeaurora.org/quic/kernel/davidb/linux-msm.git |
935 | S: Maintained | 937 | S: Maintained |
936 | 938 | ||
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 2e509f9149e2..2b00f72e8e36 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c | |||
@@ -729,7 +729,7 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = { | |||
729 | { .resource = RES_RESET, .devgroup = -1, | 729 | { .resource = RES_RESET, .devgroup = -1, |
730 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | 730 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 |
731 | }, | 731 | }, |
732 | { .resource = RES_Main_Ref, .devgroup = -1, | 732 | { .resource = RES_MAIN_REF, .devgroup = -1, |
733 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | 733 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 |
734 | }, | 734 | }, |
735 | { 0, 0}, | 735 | { 0, 0}, |
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index d2c75feff7df..f69f90a61873 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c | |||
@@ -27,7 +27,6 @@ | |||
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> | ||
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
32 | 31 | ||
33 | #include <linux/timb_dma.h> | 32 | #include <linux/timb_dma.h> |
@@ -685,7 +684,7 @@ static irqreturn_t td_irq(int irq, void *devid) | |||
685 | 684 | ||
686 | static int __devinit td_probe(struct platform_device *pdev) | 685 | static int __devinit td_probe(struct platform_device *pdev) |
687 | { | 686 | { |
688 | struct timb_dma_platform_data *pdata = mfd_get_data(pdev); | 687 | struct timb_dma_platform_data *pdata = pdev->dev.platform_data; |
689 | struct timb_dma *td; | 688 | struct timb_dma *td; |
690 | struct resource *iomem; | 689 | struct resource *iomem; |
691 | int irq; | 690 | int irq; |
diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/janz-ttl.c index 2514fb075f4a..813ac077e5d7 100644 --- a/drivers/gpio/janz-ttl.c +++ b/drivers/gpio/janz-ttl.c | |||
@@ -15,7 +15,6 @@ | |||
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> | ||
19 | #include <linux/io.h> | 18 | #include <linux/io.h> |
20 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
@@ -150,7 +149,7 @@ static int __devinit ttl_probe(struct platform_device *pdev) | |||
150 | struct resource *res; | 149 | struct resource *res; |
151 | int ret; | 150 | int ret; |
152 | 151 | ||
153 | pdata = mfd_get_data(pdev); | 152 | pdata = pdev->dev.platform_data; |
154 | if (!pdata) { | 153 | if (!pdata) { |
155 | dev_err(dev, "no platform data\n"); | 154 | dev_err(dev, "no platform data\n"); |
156 | ret = -ENXIO; | 155 | ret = -ENXIO; |
diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c index a9bda881935a..2762698e0204 100644 --- a/drivers/gpio/rdc321x-gpio.c +++ b/drivers/gpio/rdc321x-gpio.c | |||
@@ -27,7 +27,6 @@ | |||
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> | ||
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
32 | 31 | ||
33 | struct rdc321x_gpio { | 32 | struct rdc321x_gpio { |
@@ -136,7 +135,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) | |||
136 | struct rdc321x_gpio *rdc321x_gpio_dev; | 135 | struct rdc321x_gpio *rdc321x_gpio_dev; |
137 | struct rdc321x_gpio_pdata *pdata; | 136 | struct rdc321x_gpio_pdata *pdata; |
138 | 137 | ||
139 | pdata = mfd_get_data(pdev); | 138 | pdata = pdev->dev.platform_data; |
140 | if (!pdata) { | 139 | if (!pdata) { |
141 | dev_err(&pdev->dev, "no platform data supplied\n"); | 140 | dev_err(&pdev->dev, "no platform data supplied\n"); |
142 | return -ENODEV; | 141 | return -ENODEV; |
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index edbe1eae531f..0265872e57d1 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/timbgpio.c | |||
@@ -23,7 +23,6 @@ | |||
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> | ||
27 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
28 | #include <linux/io.h> | 27 | #include <linux/io.h> |
29 | #include <linux/timb_gpio.h> | 28 | #include <linux/timb_gpio.h> |
@@ -229,7 +228,7 @@ static int __devinit timbgpio_probe(struct platform_device *pdev) | |||
229 | struct gpio_chip *gc; | 228 | struct gpio_chip *gc; |
230 | struct timbgpio *tgpio; | 229 | struct timbgpio *tgpio; |
231 | struct resource *iomem; | 230 | struct resource *iomem; |
232 | struct timbgpio_platform_data *pdata = mfd_get_data(pdev); | 231 | struct timbgpio_platform_data *pdata = pdev->dev.platform_data; |
233 | int irq = platform_get_irq(pdev, 0); | 232 | int irq = platform_get_irq(pdev, 0); |
234 | 233 | ||
235 | if (!pdata || pdata->nr_pins > 32) { | 234 | if (!pdata || pdata->nr_pins > 32) { |
@@ -320,13 +319,14 @@ err_mem: | |||
320 | static int __devexit timbgpio_remove(struct platform_device *pdev) | 319 | static int __devexit timbgpio_remove(struct platform_device *pdev) |
321 | { | 320 | { |
322 | int err; | 321 | 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 < tgpio->gpio.ngpio; i++) { | 329 | for (i = 0; i < pdata->nr_pins; i++) { |
330 | irq_set_chip(tgpio->irq_base + i, NULL); | 330 | irq_set_chip(tgpio->irq_base + i, NULL); |
331 | irq_set_chip_data(tgpio->irq_base + i, NULL); | 331 | irq_set_chip_data(tgpio->irq_base + i, NULL); |
332 | } | 332 | } |
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index fee1a2613861..1b46a9d9f907 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c | |||
@@ -49,7 +49,6 @@ | |||
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> | ||
53 | #include <linux/i2c.h> | 52 | #include <linux/i2c.h> |
54 | #include <linux/interrupt.h> | 53 | #include <linux/interrupt.h> |
55 | #include <linux/wait.h> | 54 | #include <linux/wait.h> |
@@ -306,7 +305,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) | |||
306 | return -EIO; | 305 | return -EIO; |
307 | } | 306 | } |
308 | 307 | ||
309 | pdata = mfd_get_data(pdev); | 308 | pdata = pdev->dev.platform_data; |
310 | if (pdata) { | 309 | if (pdata) { |
311 | i2c->regstep = pdata->regstep; | 310 | i2c->regstep = pdata->regstep; |
312 | i2c->clock_khz = pdata->clock_khz; | 311 | i2c->clock_khz = pdata->clock_khz; |
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index e9d5ff4d1496..4bb68f35caf2 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c | |||
@@ -34,7 +34,6 @@ | |||
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> | ||
38 | #include <linux/i2c.h> | 37 | #include <linux/i2c.h> |
39 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
40 | #include <linux/wait.h> | 39 | #include <linux/wait.h> |
@@ -705,7 +704,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) | |||
705 | if (irq < 0) | 704 | if (irq < 0) |
706 | goto resource_missing; | 705 | goto resource_missing; |
707 | 706 | ||
708 | pdata = mfd_get_data(pdev); | 707 | pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; |
709 | if (!pdata) | 708 | if (!pdata) |
710 | return -EINVAL; | 709 | return -EINVAL; |
711 | 710 | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 69badb4e06aa..b4dee9d5a055 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -412,6 +412,17 @@ config KEYBOARD_PXA930_ROTARY | |||
412 | To compile this driver as a module, choose M here: the | 412 | To compile this driver as a module, choose M here: the |
413 | module will be called pxa930_rotary. | 413 | module will be called pxa930_rotary. |
414 | 414 | ||
415 | config KEYBOARD_PMIC8XXX | ||
416 | tristate "Qualcomm PMIC8XXX keypad support" | ||
417 | depends on MFD_PM8XXX | ||
418 | help | ||
419 | Say Y here if you want to enable the driver for the PMIC8XXX | ||
420 | keypad provided as a reference design from Qualcomm. This is intended | ||
421 | to support upto 18x8 matrix based keypad design. | ||
422 | |||
423 | To compile this driver as a module, choose M here: the module will | ||
424 | be called pmic8xxx-keypad. | ||
425 | |||
415 | config KEYBOARD_SAMSUNG | 426 | config KEYBOARD_SAMSUNG |
416 | tristate "Samsung keypad support" | 427 | tristate "Samsung keypad support" |
417 | depends on SAMSUNG_DEV_KEYPAD | 428 | depends on SAMSUNG_DEV_KEYPAD |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index c49cf8e04cd7..ddde0fd476f7 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -34,6 +34,7 @@ obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o | |||
34 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 34 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
35 | obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o | 35 | obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o |
36 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o | 36 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o |
37 | obj-$(CONFIG_KEYBOARD_PMIC8XXX) += pmic8xxx-keypad.o | ||
37 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | 38 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
38 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 39 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
39 | obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o | 40 | obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o |
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c new file mode 100644 index 000000000000..40b02ae96f86 --- /dev/null +++ b/drivers/input/keyboard/pmic8xxx-keypad.c | |||
@@ -0,0 +1,799 @@ | |||
1 | /* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/bitops.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/mutex.h> | ||
22 | |||
23 | #include <linux/mfd/pm8xxx/core.h> | ||
24 | #include <linux/mfd/pm8xxx/gpio.h> | ||
25 | #include <linux/input/pmic8xxx-keypad.h> | ||
26 | |||
27 | #define PM8XXX_MAX_ROWS 18 | ||
28 | #define PM8XXX_MAX_COLS 8 | ||
29 | #define PM8XXX_ROW_SHIFT 3 | ||
30 | #define PM8XXX_MATRIX_MAX_SIZE (PM8XXX_MAX_ROWS * PM8XXX_MAX_COLS) | ||
31 | |||
32 | #define PM8XXX_MIN_ROWS 5 | ||
33 | #define PM8XXX_MIN_COLS 5 | ||
34 | |||
35 | #define MAX_SCAN_DELAY 128 | ||
36 | #define MIN_SCAN_DELAY 1 | ||
37 | |||
38 | /* in nanoseconds */ | ||
39 | #define MAX_ROW_HOLD_DELAY 122000 | ||
40 | #define MIN_ROW_HOLD_DELAY 30500 | ||
41 | |||
42 | #define MAX_DEBOUNCE_TIME 20 | ||
43 | #define MIN_DEBOUNCE_TIME 5 | ||
44 | |||
45 | #define KEYP_CTRL 0x148 | ||
46 | |||
47 | #define KEYP_CTRL_EVNTS BIT(0) | ||
48 | #define KEYP_CTRL_EVNTS_MASK 0x3 | ||
49 | |||
50 | #define KEYP_CTRL_SCAN_COLS_SHIFT 5 | ||
51 | #define KEYP_CTRL_SCAN_COLS_MIN 5 | ||
52 | #define KEYP_CTRL_SCAN_COLS_BITS 0x3 | ||
53 | |||
54 | #define KEYP_CTRL_SCAN_ROWS_SHIFT 2 | ||
55 | #define KEYP_CTRL_SCAN_ROWS_MIN 5 | ||
56 | #define KEYP_CTRL_SCAN_ROWS_BITS 0x7 | ||
57 | |||
58 | #define KEYP_CTRL_KEYP_EN BIT(7) | ||
59 | |||
60 | #define KEYP_SCAN 0x149 | ||
61 | |||
62 | #define KEYP_SCAN_READ_STATE BIT(0) | ||
63 | #define KEYP_SCAN_DBOUNCE_SHIFT 1 | ||
64 | #define KEYP_SCAN_PAUSE_SHIFT 3 | ||
65 | #define KEYP_SCAN_ROW_HOLD_SHIFT 6 | ||
66 | |||
67 | #define KEYP_TEST 0x14A | ||
68 | |||
69 | #define KEYP_TEST_CLEAR_RECENT_SCAN BIT(6) | ||
70 | #define KEYP_TEST_CLEAR_OLD_SCAN BIT(5) | ||
71 | #define KEYP_TEST_READ_RESET BIT(4) | ||
72 | #define KEYP_TEST_DTEST_EN BIT(3) | ||
73 | #define KEYP_TEST_ABORT_READ BIT(0) | ||
74 | |||
75 | #define KEYP_TEST_DBG_SELECT_SHIFT 1 | ||
76 | |||
77 | /* bits of these registers represent | ||
78 | * '0' for key press | ||
79 | * '1' for key release | ||
80 | */ | ||
81 | #define KEYP_RECENT_DATA 0x14B | ||
82 | #define KEYP_OLD_DATA 0x14C | ||
83 | |||
84 | #define KEYP_CLOCK_FREQ 32768 | ||
85 | |||
86 | /** | ||
87 | * struct pmic8xxx_kp - internal keypad data structure | ||
88 | * @pdata - keypad platform data pointer | ||
89 | * @input - input device pointer for keypad | ||
90 | * @key_sense_irq - key press/release irq number | ||
91 | * @key_stuck_irq - key stuck notification irq number | ||
92 | * @keycodes - array to hold the key codes | ||
93 | * @dev - parent device pointer | ||
94 | * @keystate - present key press/release state | ||
95 | * @stuckstate - present state when key stuck irq | ||
96 | * @ctrl_reg - control register value | ||
97 | */ | ||
98 | struct pmic8xxx_kp { | ||
99 | const struct pm8xxx_keypad_platform_data *pdata; | ||
100 | struct input_dev *input; | ||
101 | int key_sense_irq; | ||
102 | int key_stuck_irq; | ||
103 | |||
104 | unsigned short keycodes[PM8XXX_MATRIX_MAX_SIZE]; | ||
105 | |||
106 | struct device *dev; | ||
107 | u16 keystate[PM8XXX_MAX_ROWS]; | ||
108 | u16 stuckstate[PM8XXX_MAX_ROWS]; | ||
109 | |||
110 | u8 ctrl_reg; | ||
111 | }; | ||
112 | |||
113 | static int pmic8xxx_kp_write_u8(struct pmic8xxx_kp *kp, | ||
114 | u8 data, u16 reg) | ||
115 | { | ||
116 | int rc; | ||
117 | |||
118 | rc = pm8xxx_writeb(kp->dev->parent, reg, data); | ||
119 | return rc; | ||
120 | } | ||
121 | |||
122 | static int pmic8xxx_kp_read(struct pmic8xxx_kp *kp, | ||
123 | u8 *data, u16 reg, unsigned num_bytes) | ||
124 | { | ||
125 | int rc; | ||
126 | |||
127 | rc = pm8xxx_read_buf(kp->dev->parent, reg, data, num_bytes); | ||
128 | return rc; | ||
129 | } | ||
130 | |||
131 | static int pmic8xxx_kp_read_u8(struct pmic8xxx_kp *kp, | ||
132 | u8 *data, u16 reg) | ||
133 | { | ||
134 | int rc; | ||
135 | |||
136 | rc = pmic8xxx_kp_read(kp, data, reg, 1); | ||
137 | return rc; | ||
138 | } | ||
139 | |||
140 | static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) | ||
141 | { | ||
142 | /* all keys pressed on that particular row? */ | ||
143 | if (col == 0x00) | ||
144 | return 1 << kp->pdata->num_cols; | ||
145 | else | ||
146 | return col & ((1 << kp->pdata->num_cols) - 1); | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Synchronous read protocol for RevB0 onwards: | ||
151 | * | ||
152 | * 1. Write '1' to ReadState bit in KEYP_SCAN register | ||
153 | * 2. Wait 2*32KHz clocks, so that HW can successfully enter read mode | ||
154 | * synchronously | ||
155 | * 3. Read rows in old array first if events are more than one | ||
156 | * 4. Read rows in recent array | ||
157 | * 5. Wait 4*32KHz clocks | ||
158 | * 6. Write '0' to ReadState bit of KEYP_SCAN register so that hw can | ||
159 | * synchronously exit read mode. | ||
160 | */ | ||
161 | static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) | ||
162 | { | ||
163 | int rc; | ||
164 | u8 scan_val; | ||
165 | |||
166 | rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); | ||
167 | if (rc < 0) { | ||
168 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | ||
169 | return rc; | ||
170 | } | ||
171 | |||
172 | scan_val |= 0x1; | ||
173 | |||
174 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | ||
175 | if (rc < 0) { | ||
176 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | ||
177 | return rc; | ||
178 | } | ||
179 | |||
180 | /* 2 * 32KHz clocks */ | ||
181 | udelay((2 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); | ||
182 | |||
183 | return rc; | ||
184 | } | ||
185 | |||
186 | static int pmic8xxx_kp_read_data(struct pmic8xxx_kp *kp, u16 *state, | ||
187 | u16 data_reg, int read_rows) | ||
188 | { | ||
189 | int rc, row; | ||
190 | u8 new_data[PM8XXX_MAX_ROWS]; | ||
191 | |||
192 | rc = pmic8xxx_kp_read(kp, new_data, data_reg, read_rows); | ||
193 | if (rc) | ||
194 | return rc; | ||
195 | |||
196 | for (row = 0; row < kp->pdata->num_rows; row++) { | ||
197 | dev_dbg(kp->dev, "new_data[%d] = %d\n", row, | ||
198 | new_data[row]); | ||
199 | state[row] = pmic8xxx_col_state(kp, new_data[row]); | ||
200 | } | ||
201 | |||
202 | return rc; | ||
203 | } | ||
204 | |||
205 | static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | ||
206 | u16 *old_state) | ||
207 | { | ||
208 | int rc, read_rows; | ||
209 | u8 scan_val; | ||
210 | |||
211 | if (kp->pdata->num_rows < PM8XXX_MIN_ROWS) | ||
212 | read_rows = PM8XXX_MIN_ROWS; | ||
213 | else | ||
214 | read_rows = kp->pdata->num_rows; | ||
215 | |||
216 | pmic8xxx_chk_sync_read(kp); | ||
217 | |||
218 | if (old_state) { | ||
219 | rc = pmic8xxx_kp_read_data(kp, old_state, KEYP_OLD_DATA, | ||
220 | read_rows); | ||
221 | if (rc < 0) { | ||
222 | dev_err(kp->dev, | ||
223 | "Error reading KEYP_OLD_DATA, rc=%d\n", rc); | ||
224 | return rc; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | rc = pmic8xxx_kp_read_data(kp, new_state, KEYP_RECENT_DATA, | ||
229 | read_rows); | ||
230 | if (rc < 0) { | ||
231 | dev_err(kp->dev, | ||
232 | "Error reading KEYP_RECENT_DATA, rc=%d\n", rc); | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | /* 4 * 32KHz clocks */ | ||
237 | udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); | ||
238 | |||
239 | rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); | ||
240 | if (rc < 0) { | ||
241 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | ||
242 | return rc; | ||
243 | } | ||
244 | |||
245 | scan_val &= 0xFE; | ||
246 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | ||
247 | if (rc < 0) | ||
248 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | ||
249 | |||
250 | return rc; | ||
251 | } | ||
252 | |||
253 | static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | ||
254 | u16 *old_state) | ||
255 | { | ||
256 | int row, col, code; | ||
257 | |||
258 | for (row = 0; row < kp->pdata->num_rows; row++) { | ||
259 | int bits_changed = new_state[row] ^ old_state[row]; | ||
260 | |||
261 | if (!bits_changed) | ||
262 | continue; | ||
263 | |||
264 | for (col = 0; col < kp->pdata->num_cols; col++) { | ||
265 | if (!(bits_changed & (1 << col))) | ||
266 | continue; | ||
267 | |||
268 | dev_dbg(kp->dev, "key [%d:%d] %s\n", row, col, | ||
269 | !(new_state[row] & (1 << col)) ? | ||
270 | "pressed" : "released"); | ||
271 | |||
272 | code = MATRIX_SCAN_CODE(row, col, PM8XXX_ROW_SHIFT); | ||
273 | |||
274 | input_event(kp->input, EV_MSC, MSC_SCAN, code); | ||
275 | input_report_key(kp->input, | ||
276 | kp->keycodes[code], | ||
277 | !(new_state[row] & (1 << col))); | ||
278 | |||
279 | input_sync(kp->input); | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) | ||
285 | { | ||
286 | int row, found_first = -1; | ||
287 | u16 check, row_state; | ||
288 | |||
289 | check = 0; | ||
290 | for (row = 0; row < kp->pdata->num_rows; row++) { | ||
291 | row_state = (~new_state[row]) & | ||
292 | ((1 << kp->pdata->num_cols) - 1); | ||
293 | |||
294 | if (hweight16(row_state) > 1) { | ||
295 | if (found_first == -1) | ||
296 | found_first = row; | ||
297 | if (check & row_state) { | ||
298 | dev_dbg(kp->dev, "detected ghost key on row[%d]" | ||
299 | " and row[%d]\n", found_first, row); | ||
300 | return true; | ||
301 | } | ||
302 | } | ||
303 | check |= row_state; | ||
304 | } | ||
305 | return false; | ||
306 | } | ||
307 | |||
308 | static int pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, unsigned int events) | ||
309 | { | ||
310 | u16 new_state[PM8XXX_MAX_ROWS]; | ||
311 | u16 old_state[PM8XXX_MAX_ROWS]; | ||
312 | int rc; | ||
313 | |||
314 | switch (events) { | ||
315 | case 0x1: | ||
316 | rc = pmic8xxx_kp_read_matrix(kp, new_state, NULL); | ||
317 | if (rc < 0) | ||
318 | return rc; | ||
319 | |||
320 | /* detecting ghost key is not an error */ | ||
321 | if (pmic8xxx_detect_ghost_keys(kp, new_state)) | ||
322 | return 0; | ||
323 | __pmic8xxx_kp_scan_matrix(kp, new_state, kp->keystate); | ||
324 | memcpy(kp->keystate, new_state, sizeof(new_state)); | ||
325 | break; | ||
326 | case 0x3: /* two events - eventcounter is gray-coded */ | ||
327 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | ||
328 | if (rc < 0) | ||
329 | return rc; | ||
330 | |||
331 | __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); | ||
332 | __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); | ||
333 | memcpy(kp->keystate, new_state, sizeof(new_state)); | ||
334 | break; | ||
335 | case 0x2: | ||
336 | dev_dbg(kp->dev, "Some key events were lost\n"); | ||
337 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | ||
338 | if (rc < 0) | ||
339 | return rc; | ||
340 | __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); | ||
341 | __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); | ||
342 | memcpy(kp->keystate, new_state, sizeof(new_state)); | ||
343 | break; | ||
344 | default: | ||
345 | rc = -EINVAL; | ||
346 | } | ||
347 | return rc; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * NOTE: We are reading recent and old data registers blindly | ||
352 | * whenever key-stuck interrupt happens, because events counter doesn't | ||
353 | * get updated when this interrupt happens due to key stuck doesn't get | ||
354 | * considered as key state change. | ||
355 | * | ||
356 | * We are not using old data register contents after they are being read | ||
357 | * because it might report the key which was pressed before the key being stuck | ||
358 | * as stuck key because it's pressed status is stored in the old data | ||
359 | * register. | ||
360 | */ | ||
361 | static irqreturn_t pmic8xxx_kp_stuck_irq(int irq, void *data) | ||
362 | { | ||
363 | u16 new_state[PM8XXX_MAX_ROWS]; | ||
364 | u16 old_state[PM8XXX_MAX_ROWS]; | ||
365 | int rc; | ||
366 | struct pmic8xxx_kp *kp = data; | ||
367 | |||
368 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | ||
369 | if (rc < 0) { | ||
370 | dev_err(kp->dev, "failed to read keypad matrix\n"); | ||
371 | return IRQ_HANDLED; | ||
372 | } | ||
373 | |||
374 | __pmic8xxx_kp_scan_matrix(kp, new_state, kp->stuckstate); | ||
375 | |||
376 | return IRQ_HANDLED; | ||
377 | } | ||
378 | |||
379 | static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) | ||
380 | { | ||
381 | struct pmic8xxx_kp *kp = data; | ||
382 | u8 ctrl_val, events; | ||
383 | int rc; | ||
384 | |||
385 | rc = pmic8xxx_kp_read(kp, &ctrl_val, KEYP_CTRL, 1); | ||
386 | if (rc < 0) { | ||
387 | dev_err(kp->dev, "failed to read keyp_ctrl register\n"); | ||
388 | return IRQ_HANDLED; | ||
389 | } | ||
390 | |||
391 | events = ctrl_val & KEYP_CTRL_EVNTS_MASK; | ||
392 | |||
393 | rc = pmic8xxx_kp_scan_matrix(kp, events); | ||
394 | if (rc < 0) | ||
395 | dev_err(kp->dev, "failed to scan matrix\n"); | ||
396 | |||
397 | return IRQ_HANDLED; | ||
398 | } | ||
399 | |||
400 | static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | ||
401 | { | ||
402 | int bits, rc, cycles; | ||
403 | u8 scan_val = 0, ctrl_val = 0; | ||
404 | static const u8 row_bits[] = { | ||
405 | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, | ||
406 | }; | ||
407 | |||
408 | /* Find column bits */ | ||
409 | if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN) | ||
410 | bits = 0; | ||
411 | else | ||
412 | bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN; | ||
413 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << | ||
414 | KEYP_CTRL_SCAN_COLS_SHIFT; | ||
415 | |||
416 | /* Find row bits */ | ||
417 | if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) | ||
418 | bits = 0; | ||
419 | else | ||
420 | bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; | ||
421 | |||
422 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); | ||
423 | |||
424 | rc = pmic8xxx_kp_write_u8(kp, ctrl_val, KEYP_CTRL); | ||
425 | if (rc < 0) { | ||
426 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | ||
427 | return rc; | ||
428 | } | ||
429 | |||
430 | bits = (kp->pdata->debounce_ms / 5) - 1; | ||
431 | |||
432 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); | ||
433 | |||
434 | bits = fls(kp->pdata->scan_delay_ms) - 1; | ||
435 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); | ||
436 | |||
437 | /* Row hold time is a multiple of 32KHz cycles. */ | ||
438 | cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; | ||
439 | |||
440 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); | ||
441 | |||
442 | rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); | ||
443 | if (rc) | ||
444 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | ||
445 | |||
446 | return rc; | ||
447 | |||
448 | } | ||
449 | |||
450 | static int __devinit pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios, | ||
451 | struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config) | ||
452 | { | ||
453 | int rc, i; | ||
454 | |||
455 | if (gpio_start < 0 || num_gpios < 0) | ||
456 | return -EINVAL; | ||
457 | |||
458 | for (i = 0; i < num_gpios; i++) { | ||
459 | rc = pm8xxx_gpio_config(gpio_start + i, gpio_config); | ||
460 | if (rc) { | ||
461 | dev_err(kp->dev, "%s: FAIL pm8xxx_gpio_config():" | ||
462 | "for PM GPIO [%d] rc=%d.\n", | ||
463 | __func__, gpio_start + i, rc); | ||
464 | return rc; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int pmic8xxx_kp_enable(struct pmic8xxx_kp *kp) | ||
472 | { | ||
473 | int rc; | ||
474 | |||
475 | kp->ctrl_reg |= KEYP_CTRL_KEYP_EN; | ||
476 | |||
477 | rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); | ||
478 | if (rc < 0) | ||
479 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | ||
480 | |||
481 | return rc; | ||
482 | } | ||
483 | |||
484 | static int pmic8xxx_kp_disable(struct pmic8xxx_kp *kp) | ||
485 | { | ||
486 | int rc; | ||
487 | |||
488 | kp->ctrl_reg &= ~KEYP_CTRL_KEYP_EN; | ||
489 | |||
490 | rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); | ||
491 | if (rc < 0) | ||
492 | return rc; | ||
493 | |||
494 | return rc; | ||
495 | } | ||
496 | |||
497 | static int pmic8xxx_kp_open(struct input_dev *dev) | ||
498 | { | ||
499 | struct pmic8xxx_kp *kp = input_get_drvdata(dev); | ||
500 | |||
501 | return pmic8xxx_kp_enable(kp); | ||
502 | } | ||
503 | |||
504 | static void pmic8xxx_kp_close(struct input_dev *dev) | ||
505 | { | ||
506 | struct pmic8xxx_kp *kp = input_get_drvdata(dev); | ||
507 | |||
508 | pmic8xxx_kp_disable(kp); | ||
509 | } | ||
510 | |||
511 | /* | ||
512 | * keypad controller should be initialized in the following sequence | ||
513 | * only, otherwise it might get into FSM stuck state. | ||
514 | * | ||
515 | * - Initialize keypad control parameters, like no. of rows, columns, | ||
516 | * timing values etc., | ||
517 | * - configure rows and column gpios pull up/down. | ||
518 | * - set irq edge type. | ||
519 | * - enable the keypad controller. | ||
520 | */ | ||
521 | static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) | ||
522 | { | ||
523 | const struct pm8xxx_keypad_platform_data *pdata = mfd_get_data(pdev); | ||
524 | const struct matrix_keymap_data *keymap_data; | ||
525 | struct pmic8xxx_kp *kp; | ||
526 | int rc; | ||
527 | u8 ctrl_val; | ||
528 | |||
529 | struct pm_gpio kypd_drv = { | ||
530 | .direction = PM_GPIO_DIR_OUT, | ||
531 | .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, | ||
532 | .output_value = 0, | ||
533 | .pull = PM_GPIO_PULL_NO, | ||
534 | .vin_sel = PM_GPIO_VIN_S3, | ||
535 | .out_strength = PM_GPIO_STRENGTH_LOW, | ||
536 | .function = PM_GPIO_FUNC_1, | ||
537 | .inv_int_pol = 1, | ||
538 | }; | ||
539 | |||
540 | struct pm_gpio kypd_sns = { | ||
541 | .direction = PM_GPIO_DIR_IN, | ||
542 | .pull = PM_GPIO_PULL_UP_31P5, | ||
543 | .vin_sel = PM_GPIO_VIN_S3, | ||
544 | .out_strength = PM_GPIO_STRENGTH_NO, | ||
545 | .function = PM_GPIO_FUNC_NORMAL, | ||
546 | .inv_int_pol = 1, | ||
547 | }; | ||
548 | |||
549 | |||
550 | if (!pdata || !pdata->num_cols || !pdata->num_rows || | ||
551 | pdata->num_cols > PM8XXX_MAX_COLS || | ||
552 | pdata->num_rows > PM8XXX_MAX_ROWS || | ||
553 | pdata->num_cols < PM8XXX_MIN_COLS) { | ||
554 | dev_err(&pdev->dev, "invalid platform data\n"); | ||
555 | return -EINVAL; | ||
556 | } | ||
557 | |||
558 | if (!pdata->scan_delay_ms || | ||
559 | pdata->scan_delay_ms > MAX_SCAN_DELAY || | ||
560 | pdata->scan_delay_ms < MIN_SCAN_DELAY || | ||
561 | !is_power_of_2(pdata->scan_delay_ms)) { | ||
562 | dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); | ||
563 | return -EINVAL; | ||
564 | } | ||
565 | |||
566 | if (!pdata->row_hold_ns || | ||
567 | pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || | ||
568 | pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || | ||
569 | ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { | ||
570 | dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); | ||
571 | return -EINVAL; | ||
572 | } | ||
573 | |||
574 | if (!pdata->debounce_ms || | ||
575 | ((pdata->debounce_ms % 5) != 0) || | ||
576 | pdata->debounce_ms > MAX_DEBOUNCE_TIME || | ||
577 | pdata->debounce_ms < MIN_DEBOUNCE_TIME) { | ||
578 | dev_err(&pdev->dev, "invalid debounce time supplied\n"); | ||
579 | return -EINVAL; | ||
580 | } | ||
581 | |||
582 | keymap_data = pdata->keymap_data; | ||
583 | if (!keymap_data) { | ||
584 | dev_err(&pdev->dev, "no keymap data supplied\n"); | ||
585 | return -EINVAL; | ||
586 | } | ||
587 | |||
588 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | ||
589 | if (!kp) | ||
590 | return -ENOMEM; | ||
591 | |||
592 | platform_set_drvdata(pdev, kp); | ||
593 | |||
594 | kp->pdata = pdata; | ||
595 | kp->dev = &pdev->dev; | ||
596 | |||
597 | kp->input = input_allocate_device(); | ||
598 | if (!kp->input) { | ||
599 | dev_err(&pdev->dev, "unable to allocate input device\n"); | ||
600 | rc = -ENOMEM; | ||
601 | goto err_alloc_device; | ||
602 | } | ||
603 | |||
604 | kp->key_sense_irq = platform_get_irq(pdev, 0); | ||
605 | if (kp->key_sense_irq < 0) { | ||
606 | dev_err(&pdev->dev, "unable to get keypad sense irq\n"); | ||
607 | rc = -ENXIO; | ||
608 | goto err_get_irq; | ||
609 | } | ||
610 | |||
611 | kp->key_stuck_irq = platform_get_irq(pdev, 1); | ||
612 | if (kp->key_stuck_irq < 0) { | ||
613 | dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); | ||
614 | rc = -ENXIO; | ||
615 | goto err_get_irq; | ||
616 | } | ||
617 | |||
618 | kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; | ||
619 | kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; | ||
620 | |||
621 | kp->input->dev.parent = &pdev->dev; | ||
622 | |||
623 | kp->input->id.bustype = BUS_I2C; | ||
624 | kp->input->id.version = 0x0001; | ||
625 | kp->input->id.product = 0x0001; | ||
626 | kp->input->id.vendor = 0x0001; | ||
627 | |||
628 | kp->input->evbit[0] = BIT_MASK(EV_KEY); | ||
629 | |||
630 | if (pdata->rep) | ||
631 | __set_bit(EV_REP, kp->input->evbit); | ||
632 | |||
633 | kp->input->keycode = kp->keycodes; | ||
634 | kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE; | ||
635 | kp->input->keycodesize = sizeof(kp->keycodes); | ||
636 | kp->input->open = pmic8xxx_kp_open; | ||
637 | kp->input->close = pmic8xxx_kp_close; | ||
638 | |||
639 | matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, | ||
640 | kp->input->keycode, kp->input->keybit); | ||
641 | |||
642 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); | ||
643 | input_set_drvdata(kp->input, kp); | ||
644 | |||
645 | /* initialize keypad state */ | ||
646 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); | ||
647 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); | ||
648 | |||
649 | rc = pmic8xxx_kpd_init(kp); | ||
650 | if (rc < 0) { | ||
651 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); | ||
652 | goto err_get_irq; | ||
653 | } | ||
654 | |||
655 | rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, | ||
656 | pdata->num_cols, kp, &kypd_sns); | ||
657 | if (rc < 0) { | ||
658 | dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); | ||
659 | goto err_gpio_config; | ||
660 | } | ||
661 | |||
662 | rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, | ||
663 | pdata->num_rows, kp, &kypd_drv); | ||
664 | if (rc < 0) { | ||
665 | dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); | ||
666 | goto err_gpio_config; | ||
667 | } | ||
668 | |||
669 | rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, | ||
670 | IRQF_TRIGGER_RISING, "pmic-keypad", kp); | ||
671 | if (rc < 0) { | ||
672 | dev_err(&pdev->dev, "failed to request keypad sense irq\n"); | ||
673 | goto err_get_irq; | ||
674 | } | ||
675 | |||
676 | rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, | ||
677 | IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); | ||
678 | if (rc < 0) { | ||
679 | dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); | ||
680 | goto err_req_stuck_irq; | ||
681 | } | ||
682 | |||
683 | rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); | ||
684 | if (rc < 0) { | ||
685 | dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); | ||
686 | goto err_pmic_reg_read; | ||
687 | } | ||
688 | |||
689 | kp->ctrl_reg = ctrl_val; | ||
690 | |||
691 | rc = input_register_device(kp->input); | ||
692 | if (rc < 0) { | ||
693 | dev_err(&pdev->dev, "unable to register keypad input device\n"); | ||
694 | goto err_pmic_reg_read; | ||
695 | } | ||
696 | |||
697 | device_init_wakeup(&pdev->dev, pdata->wakeup); | ||
698 | |||
699 | return 0; | ||
700 | |||
701 | err_pmic_reg_read: | ||
702 | free_irq(kp->key_stuck_irq, NULL); | ||
703 | err_req_stuck_irq: | ||
704 | free_irq(kp->key_sense_irq, NULL); | ||
705 | err_gpio_config: | ||
706 | err_get_irq: | ||
707 | input_free_device(kp->input); | ||
708 | err_alloc_device: | ||
709 | platform_set_drvdata(pdev, NULL); | ||
710 | kfree(kp); | ||
711 | return rc; | ||
712 | } | ||
713 | |||
714 | static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) | ||
715 | { | ||
716 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | ||
717 | |||
718 | device_init_wakeup(&pdev->dev, 0); | ||
719 | free_irq(kp->key_stuck_irq, NULL); | ||
720 | free_irq(kp->key_sense_irq, NULL); | ||
721 | input_unregister_device(kp->input); | ||
722 | kfree(kp); | ||
723 | |||
724 | platform_set_drvdata(pdev, NULL); | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | #ifdef CONFIG_PM_SLEEP | ||
729 | static int pmic8xxx_kp_suspend(struct device *dev) | ||
730 | { | ||
731 | struct platform_device *pdev = to_platform_device(dev); | ||
732 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | ||
733 | struct input_dev *input_dev = kp->input; | ||
734 | |||
735 | if (device_may_wakeup(dev)) { | ||
736 | enable_irq_wake(kp->key_sense_irq); | ||
737 | } else { | ||
738 | mutex_lock(&input_dev->mutex); | ||
739 | |||
740 | if (input_dev->users) | ||
741 | pmic8xxx_kp_disable(kp); | ||
742 | |||
743 | mutex_unlock(&input_dev->mutex); | ||
744 | } | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static int pmic8xxx_kp_resume(struct device *dev) | ||
750 | { | ||
751 | struct platform_device *pdev = to_platform_device(dev); | ||
752 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | ||
753 | struct input_dev *input_dev = kp->input; | ||
754 | |||
755 | if (device_may_wakeup(dev)) { | ||
756 | disable_irq_wake(kp->key_sense_irq); | ||
757 | } else { | ||
758 | mutex_lock(&input_dev->mutex); | ||
759 | |||
760 | if (input_dev->users) | ||
761 | pmic8xxx_kp_enable(kp); | ||
762 | |||
763 | mutex_unlock(&input_dev->mutex); | ||
764 | } | ||
765 | |||
766 | return 0; | ||
767 | } | ||
768 | #endif | ||
769 | |||
770 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, | ||
771 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); | ||
772 | |||
773 | static struct platform_driver pmic8xxx_kp_driver = { | ||
774 | .probe = pmic8xxx_kp_probe, | ||
775 | .remove = __devexit_p(pmic8xxx_kp_remove), | ||
776 | .driver = { | ||
777 | .name = PM8XXX_KEYPAD_DEV_NAME, | ||
778 | .owner = THIS_MODULE, | ||
779 | .pm = &pm8xxx_kp_pm_ops, | ||
780 | }, | ||
781 | }; | ||
782 | |||
783 | static int __init pmic8xxx_kp_init(void) | ||
784 | { | ||
785 | return platform_driver_register(&pmic8xxx_kp_driver); | ||
786 | } | ||
787 | module_init(pmic8xxx_kp_init); | ||
788 | |||
789 | static void __exit pmic8xxx_kp_exit(void) | ||
790 | { | ||
791 | platform_driver_unregister(&pmic8xxx_kp_driver); | ||
792 | } | ||
793 | module_exit(pmic8xxx_kp_exit); | ||
794 | |||
795 | MODULE_LICENSE("GPL v2"); | ||
796 | MODULE_DESCRIPTION("PMIC8XXX keypad driver"); | ||
797 | MODULE_VERSION("1.0"); | ||
798 | MODULE_ALIAS("platform:pmic8xxx_keypad"); | ||
799 | MODULE_AUTHOR("Trilok Soni <tsoni@codeaurora.org>"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index f9cf0881b0e3..45dc6aa62ba4 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -330,6 +330,17 @@ config INPUT_PWM_BEEPER | |||
330 | To compile this driver as a module, choose M here: the module will be | 330 | To compile this driver as a module, choose M here: the module will be |
331 | called pwm-beeper. | 331 | called pwm-beeper. |
332 | 332 | ||
333 | config INPUT_PMIC8XXX_PWRKEY | ||
334 | tristate "PMIC8XXX power key support" | ||
335 | depends on MFD_PM8XXX | ||
336 | help | ||
337 | Say Y here if you want support for the PMIC8XXX power key. | ||
338 | |||
339 | If unsure, say N. | ||
340 | |||
341 | To compile this driver as a module, choose M here: the | ||
342 | module will be called pmic8xxx-pwrkey. | ||
343 | |||
333 | config INPUT_GPIO_ROTARY_ENCODER | 344 | config INPUT_GPIO_ROTARY_ENCODER |
334 | tristate "Rotary encoders connected to GPIO pins" | 345 | tristate "Rotary encoders connected to GPIO pins" |
335 | depends on GPIOLIB && GENERIC_GPIO | 346 | depends on GPIOLIB && GENERIC_GPIO |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index e3f7984e6274..38efb2cb182b 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o | |||
33 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | 33 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o |
34 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | 34 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o |
35 | obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o | 35 | obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o |
36 | obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o | ||
36 | obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o | 37 | obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o |
37 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | 38 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o |
38 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 39 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o |
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c new file mode 100644 index 000000000000..97e07e786e41 --- /dev/null +++ b/drivers/input/misc/pmic8xxx-pwrkey.c | |||
@@ -0,0 +1,231 @@ | |||
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/log2.h> | ||
22 | |||
23 | #include <linux/mfd/pm8xxx/core.h> | ||
24 | #include <linux/input/pmic8xxx-pwrkey.h> | ||
25 | |||
26 | #define PON_CNTL_1 0x1C | ||
27 | #define PON_CNTL_PULL_UP BIT(7) | ||
28 | #define PON_CNTL_TRIG_DELAY_MASK (0x7) | ||
29 | |||
30 | /** | ||
31 | * struct pmic8xxx_pwrkey - pmic8xxx pwrkey information | ||
32 | * @key_press_irq: key press irq number | ||
33 | */ | ||
34 | struct pmic8xxx_pwrkey { | ||
35 | struct input_dev *pwr; | ||
36 | int key_press_irq; | ||
37 | }; | ||
38 | |||
39 | static irqreturn_t pwrkey_press_irq(int irq, void *_pwrkey) | ||
40 | { | ||
41 | struct pmic8xxx_pwrkey *pwrkey = _pwrkey; | ||
42 | |||
43 | input_report_key(pwrkey->pwr, KEY_POWER, 1); | ||
44 | input_sync(pwrkey->pwr); | ||
45 | |||
46 | return IRQ_HANDLED; | ||
47 | } | ||
48 | |||
49 | static irqreturn_t pwrkey_release_irq(int irq, void *_pwrkey) | ||
50 | { | ||
51 | struct pmic8xxx_pwrkey *pwrkey = _pwrkey; | ||
52 | |||
53 | input_report_key(pwrkey->pwr, KEY_POWER, 0); | ||
54 | input_sync(pwrkey->pwr); | ||
55 | |||
56 | return IRQ_HANDLED; | ||
57 | } | ||
58 | |||
59 | #ifdef CONFIG_PM_SLEEP | ||
60 | static int pmic8xxx_pwrkey_suspend(struct device *dev) | ||
61 | { | ||
62 | struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev); | ||
63 | |||
64 | if (device_may_wakeup(dev)) | ||
65 | enable_irq_wake(pwrkey->key_press_irq); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int pmic8xxx_pwrkey_resume(struct device *dev) | ||
71 | { | ||
72 | struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev); | ||
73 | |||
74 | if (device_may_wakeup(dev)) | ||
75 | disable_irq_wake(pwrkey->key_press_irq); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | #endif | ||
80 | |||
81 | static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops, | ||
82 | pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume); | ||
83 | |||
84 | static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) | ||
85 | { | ||
86 | struct input_dev *pwr; | ||
87 | int key_release_irq = platform_get_irq(pdev, 0); | ||
88 | int key_press_irq = platform_get_irq(pdev, 1); | ||
89 | int err; | ||
90 | unsigned int delay; | ||
91 | u8 pon_cntl; | ||
92 | struct pmic8xxx_pwrkey *pwrkey; | ||
93 | const struct pm8xxx_pwrkey_platform_data *pdata = mfd_get_data(pdev); | ||
94 | |||
95 | if (!pdata) { | ||
96 | dev_err(&pdev->dev, "power key platform data not supplied\n"); | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | if (pdata->kpd_trigger_delay_us > 62500) { | ||
101 | dev_err(&pdev->dev, "invalid power key trigger delay\n"); | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); | ||
106 | if (!pwrkey) | ||
107 | return -ENOMEM; | ||
108 | |||
109 | pwr = input_allocate_device(); | ||
110 | if (!pwr) { | ||
111 | dev_dbg(&pdev->dev, "Can't allocate power button\n"); | ||
112 | err = -ENOMEM; | ||
113 | goto free_pwrkey; | ||
114 | } | ||
115 | |||
116 | input_set_capability(pwr, EV_KEY, KEY_POWER); | ||
117 | |||
118 | pwr->name = "pmic8xxx_pwrkey"; | ||
119 | pwr->phys = "pmic8xxx_pwrkey/input0"; | ||
120 | pwr->dev.parent = &pdev->dev; | ||
121 | |||
122 | delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; | ||
123 | delay = 1 + ilog2(delay); | ||
124 | |||
125 | err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); | ||
126 | if (err < 0) { | ||
127 | dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); | ||
128 | goto free_input_dev; | ||
129 | } | ||
130 | |||
131 | pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; | ||
132 | pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); | ||
133 | if (pdata->pull_up) | ||
134 | pon_cntl |= PON_CNTL_PULL_UP; | ||
135 | else | ||
136 | pon_cntl &= ~PON_CNTL_PULL_UP; | ||
137 | |||
138 | err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); | ||
139 | if (err < 0) { | ||
140 | dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); | ||
141 | goto free_input_dev; | ||
142 | } | ||
143 | |||
144 | err = input_register_device(pwr); | ||
145 | if (err) { | ||
146 | dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); | ||
147 | goto free_input_dev; | ||
148 | } | ||
149 | |||
150 | pwrkey->key_press_irq = key_press_irq; | ||
151 | pwrkey->pwr = pwr; | ||
152 | |||
153 | platform_set_drvdata(pdev, pwrkey); | ||
154 | |||
155 | err = request_irq(key_press_irq, pwrkey_press_irq, | ||
156 | IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); | ||
157 | if (err < 0) { | ||
158 | dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", | ||
159 | key_press_irq, err); | ||
160 | goto unreg_input_dev; | ||
161 | } | ||
162 | |||
163 | err = request_irq(key_release_irq, pwrkey_release_irq, | ||
164 | IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); | ||
165 | if (err < 0) { | ||
166 | dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", | ||
167 | key_release_irq, err); | ||
168 | |||
169 | goto free_press_irq; | ||
170 | } | ||
171 | |||
172 | device_init_wakeup(&pdev->dev, pdata->wakeup); | ||
173 | |||
174 | return 0; | ||
175 | |||
176 | free_press_irq: | ||
177 | free_irq(key_press_irq, NULL); | ||
178 | unreg_input_dev: | ||
179 | platform_set_drvdata(pdev, NULL); | ||
180 | input_unregister_device(pwr); | ||
181 | pwr = NULL; | ||
182 | free_input_dev: | ||
183 | input_free_device(pwr); | ||
184 | free_pwrkey: | ||
185 | kfree(pwrkey); | ||
186 | return err; | ||
187 | } | ||
188 | |||
189 | static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev) | ||
190 | { | ||
191 | struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev); | ||
192 | int key_release_irq = platform_get_irq(pdev, 0); | ||
193 | int key_press_irq = platform_get_irq(pdev, 1); | ||
194 | |||
195 | device_init_wakeup(&pdev->dev, 0); | ||
196 | |||
197 | free_irq(key_press_irq, pwrkey); | ||
198 | free_irq(key_release_irq, pwrkey); | ||
199 | input_unregister_device(pwrkey->pwr); | ||
200 | platform_set_drvdata(pdev, NULL); | ||
201 | kfree(pwrkey); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static struct platform_driver pmic8xxx_pwrkey_driver = { | ||
207 | .probe = pmic8xxx_pwrkey_probe, | ||
208 | .remove = __devexit_p(pmic8xxx_pwrkey_remove), | ||
209 | .driver = { | ||
210 | .name = PM8XXX_PWRKEY_DEV_NAME, | ||
211 | .owner = THIS_MODULE, | ||
212 | .pm = &pm8xxx_pwr_key_pm_ops, | ||
213 | }, | ||
214 | }; | ||
215 | |||
216 | static int __init pmic8xxx_pwrkey_init(void) | ||
217 | { | ||
218 | return platform_driver_register(&pmic8xxx_pwrkey_driver); | ||
219 | } | ||
220 | module_init(pmic8xxx_pwrkey_init); | ||
221 | |||
222 | static void __exit pmic8xxx_pwrkey_exit(void) | ||
223 | { | ||
224 | platform_driver_unregister(&pmic8xxx_pwrkey_driver); | ||
225 | } | ||
226 | module_exit(pmic8xxx_pwrkey_exit); | ||
227 | |||
228 | MODULE_ALIAS("platform:pmic8xxx_pwrkey"); | ||
229 | MODULE_DESCRIPTION("PMIC8XXX Power Key driver"); | ||
230 | MODULE_LICENSE("GPL v2"); | ||
231 | MODULE_AUTHOR("Trilok Soni <tsoni@codeaurora.org>"); | ||
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 6a11694e3fc7..014dd4ad0d4f 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c | |||
@@ -29,7 +29,6 @@ | |||
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> | ||
33 | #include <linux/input.h> | 32 | #include <linux/input.h> |
34 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
35 | 34 | ||
@@ -197,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, | |||
197 | 196 | ||
198 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) | 197 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) |
199 | { | 198 | { |
200 | struct twl4030_codec_vibra_data *pdata = mfd_get_data(pdev); | 199 | struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; |
201 | struct vibra_info *info; | 200 | struct vibra_info *info; |
202 | int ret; | 201 | int ret; |
203 | 202 | ||
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1d027b475b22..23f0d5e99f35 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -389,6 +389,16 @@ config LEDS_NETXBIG | |||
389 | and 5Big Network v2 boards. The LEDs are wired to a CPLD and are | 389 | and 5Big Network v2 boards. The LEDs are wired to a CPLD and are |
390 | controlled through a GPIO extension bus. | 390 | controlled through a GPIO extension bus. |
391 | 391 | ||
392 | config LEDS_ASIC3 | ||
393 | bool "LED support for the HTC ASIC3" | ||
394 | depends on MFD_ASIC3 | ||
395 | default y | ||
396 | help | ||
397 | This option enables support for the LEDs on the HTC ASIC3. The HTC | ||
398 | ASIC3 LED GPIOs are inputs, not outputs, thus the leds-gpio driver | ||
399 | cannot be used. This driver supports hardware blinking with an on+off | ||
400 | period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700. | ||
401 | |||
392 | config LEDS_TRIGGERS | 402 | config LEDS_TRIGGERS |
393 | bool "LED Trigger support" | 403 | bool "LED Trigger support" |
394 | depends on LEDS_CLASS | 404 | depends on LEDS_CLASS |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index bccb96c9bb45..bbfd2e367dc0 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -42,6 +42,7 @@ obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o | |||
42 | obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o | 42 | obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o |
43 | obj-$(CONFIG_LEDS_NS2) += leds-ns2.o | 43 | obj-$(CONFIG_LEDS_NS2) += leds-ns2.o |
44 | obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o | 44 | obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o |
45 | obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o | ||
45 | 46 | ||
46 | # LED SPI Drivers | 47 | # LED SPI Drivers |
47 | obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o | 48 | obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 416def84d045..0d4c16678ace 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -17,7 +17,6 @@ | |||
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> | ||
21 | #include <linux/mfd/88pm860x.h> | 20 | #include <linux/mfd/88pm860x.h> |
22 | 21 | ||
23 | #define LED_PWM_SHIFT (3) | 22 | #define LED_PWM_SHIFT (3) |
@@ -171,7 +170,6 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
171 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 170 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
172 | struct pm860x_led_pdata *pdata; | 171 | struct pm860x_led_pdata *pdata; |
173 | struct pm860x_led *data; | 172 | struct pm860x_led *data; |
174 | struct mfd_cell *cell; | ||
175 | struct resource *res; | 173 | struct resource *res; |
176 | int ret; | 174 | int ret; |
177 | 175 | ||
@@ -181,10 +179,7 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
181 | return -EINVAL; | 179 | return -EINVAL; |
182 | } | 180 | } |
183 | 181 | ||
184 | cell = pdev->dev.platform_data; | 182 | pdata = pdev->dev.platform_data; |
185 | if (cell == NULL) | ||
186 | return -ENODEV; | ||
187 | pdata = cell->mfd_data; | ||
188 | if (pdata == NULL) { | 183 | if (pdata == NULL) { |
189 | dev_err(&pdev->dev, "No platform data!\n"); | 184 | dev_err(&pdev->dev, "No platform data!\n"); |
190 | return -EINVAL; | 185 | return -EINVAL; |
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c new file mode 100644 index 000000000000..22f847c890c9 --- /dev/null +++ b/drivers/leds/leds-asic3.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Paul Parsons <lost.distance@yahoo.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/leds.h> | ||
13 | #include <linux/slab.h> | ||
14 | |||
15 | #include <linux/mfd/asic3.h> | ||
16 | #include <linux/mfd/core.h> | ||
17 | |||
18 | /* | ||
19 | * The HTC ASIC3 LED GPIOs are inputs, not outputs. | ||
20 | * Hence we turn the LEDs on/off via the TimeBase register. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * When TimeBase is 4 the clock resolution is about 32Hz. | ||
25 | * This driver supports hardware blinking with an on+off | ||
26 | * period from 62ms (2 clocks) to 125s (4000 clocks). | ||
27 | */ | ||
28 | #define MS_TO_CLK(ms) DIV_ROUND_CLOSEST(((ms)*1024), 32000) | ||
29 | #define CLK_TO_MS(clk) (((clk)*32000)/1024) | ||
30 | #define MAX_CLK 4000 /* Fits into 12-bit Time registers */ | ||
31 | #define MAX_MS CLK_TO_MS(MAX_CLK) | ||
32 | |||
33 | static const unsigned int led_n_base[ASIC3_NUM_LEDS] = { | ||
34 | [0] = ASIC3_LED_0_Base, | ||
35 | [1] = ASIC3_LED_1_Base, | ||
36 | [2] = ASIC3_LED_2_Base, | ||
37 | }; | ||
38 | |||
39 | static void brightness_set(struct led_classdev *cdev, | ||
40 | enum led_brightness value) | ||
41 | { | ||
42 | struct platform_device *pdev = to_platform_device(cdev->dev->parent); | ||
43 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
44 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
45 | u32 timebase; | ||
46 | unsigned int base; | ||
47 | |||
48 | timebase = (value == LED_OFF) ? 0 : (LED_EN|0x4); | ||
49 | |||
50 | base = led_n_base[cell->id]; | ||
51 | asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), 32); | ||
52 | asic3_write_register(asic, (base + ASIC3_LED_DutyTime), 32); | ||
53 | asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0); | ||
54 | asic3_write_register(asic, (base + ASIC3_LED_TimeBase), timebase); | ||
55 | } | ||
56 | |||
57 | static int blink_set(struct led_classdev *cdev, | ||
58 | unsigned long *delay_on, | ||
59 | unsigned long *delay_off) | ||
60 | { | ||
61 | struct platform_device *pdev = to_platform_device(cdev->dev->parent); | ||
62 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
63 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
64 | u32 on; | ||
65 | u32 off; | ||
66 | unsigned int base; | ||
67 | |||
68 | if (*delay_on > MAX_MS || *delay_off > MAX_MS) | ||
69 | return -EINVAL; | ||
70 | |||
71 | if (*delay_on == 0 && *delay_off == 0) { | ||
72 | /* If both are zero then a sensible default should be chosen */ | ||
73 | on = MS_TO_CLK(500); | ||
74 | off = MS_TO_CLK(500); | ||
75 | } else { | ||
76 | on = MS_TO_CLK(*delay_on); | ||
77 | off = MS_TO_CLK(*delay_off); | ||
78 | if ((on + off) > MAX_CLK) | ||
79 | return -EINVAL; | ||
80 | } | ||
81 | |||
82 | base = led_n_base[cell->id]; | ||
83 | asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), (on + off)); | ||
84 | asic3_write_register(asic, (base + ASIC3_LED_DutyTime), on); | ||
85 | asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0); | ||
86 | asic3_write_register(asic, (base + ASIC3_LED_TimeBase), (LED_EN|0x4)); | ||
87 | |||
88 | *delay_on = CLK_TO_MS(on); | ||
89 | *delay_off = CLK_TO_MS(off); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int __devinit asic3_led_probe(struct platform_device *pdev) | ||
95 | { | ||
96 | struct asic3_led *led = pdev->dev.platform_data; | ||
97 | int ret; | ||
98 | |||
99 | ret = mfd_cell_enable(pdev); | ||
100 | if (ret < 0) | ||
101 | goto ret0; | ||
102 | |||
103 | led->cdev = kzalloc(sizeof(struct led_classdev), GFP_KERNEL); | ||
104 | if (!led->cdev) { | ||
105 | ret = -ENOMEM; | ||
106 | goto ret1; | ||
107 | } | ||
108 | |||
109 | led->cdev->name = led->name; | ||
110 | led->cdev->default_trigger = led->default_trigger; | ||
111 | led->cdev->brightness_set = brightness_set; | ||
112 | led->cdev->blink_set = blink_set; | ||
113 | |||
114 | ret = led_classdev_register(&pdev->dev, led->cdev); | ||
115 | if (ret < 0) | ||
116 | goto ret2; | ||
117 | |||
118 | return 0; | ||
119 | |||
120 | ret2: | ||
121 | kfree(led->cdev); | ||
122 | ret1: | ||
123 | (void) mfd_cell_disable(pdev); | ||
124 | ret0: | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | static int __devexit asic3_led_remove(struct platform_device *pdev) | ||
129 | { | ||
130 | struct asic3_led *led = pdev->dev.platform_data; | ||
131 | |||
132 | led_classdev_unregister(led->cdev); | ||
133 | |||
134 | kfree(led->cdev); | ||
135 | |||
136 | return mfd_cell_disable(pdev); | ||
137 | } | ||
138 | |||
139 | static struct platform_driver asic3_led_driver = { | ||
140 | .probe = asic3_led_probe, | ||
141 | .remove = __devexit_p(asic3_led_remove), | ||
142 | .driver = { | ||
143 | .name = "leds-asic3", | ||
144 | .owner = THIS_MODULE, | ||
145 | }, | ||
146 | }; | ||
147 | |||
148 | MODULE_ALIAS("platform:leds-asic3"); | ||
149 | |||
150 | static int __init asic3_led_init(void) | ||
151 | { | ||
152 | return platform_driver_register(&asic3_led_driver); | ||
153 | } | ||
154 | |||
155 | static void __exit asic3_led_exit(void) | ||
156 | { | ||
157 | platform_driver_unregister(&asic3_led_driver); | ||
158 | } | ||
159 | |||
160 | module_init(asic3_led_init); | ||
161 | module_exit(asic3_led_exit); | ||
162 | |||
163 | MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>"); | ||
164 | MODULE_DESCRIPTION("HTC ASIC3 LED driver"); | ||
165 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index 126ca7955f6e..f369e56d6547 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c | |||
@@ -22,7 +22,6 @@ | |||
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> | ||
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | 26 | ||
28 | struct mc13783_led { | 27 | struct mc13783_led { |
@@ -184,7 +183,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current) | |||
184 | 183 | ||
185 | static int __devinit mc13783_leds_prepare(struct platform_device *pdev) | 184 | static int __devinit mc13783_leds_prepare(struct platform_device *pdev) |
186 | { | 185 | { |
187 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); | 186 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); |
188 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | 187 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); |
189 | int ret = 0; | 188 | int ret = 0; |
190 | int reg = 0; | 189 | int reg = 0; |
@@ -265,7 +264,7 @@ out: | |||
265 | 264 | ||
266 | static int __devinit mc13783_led_probe(struct platform_device *pdev) | 265 | static int __devinit mc13783_led_probe(struct platform_device *pdev) |
267 | { | 266 | { |
268 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); | 267 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); |
269 | struct mc13783_led_platform_data *led_cur; | 268 | struct mc13783_led_platform_data *led_cur; |
270 | struct mc13783_led *led, *led_dat; | 269 | struct mc13783_led *led, *led_dat; |
271 | int ret, i; | 270 | int ret, i; |
@@ -352,7 +351,7 @@ err_free: | |||
352 | 351 | ||
353 | static int __devexit mc13783_led_remove(struct platform_device *pdev) | 352 | static int __devexit mc13783_led_remove(struct platform_device *pdev) |
354 | { | 353 | { |
355 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); | 354 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); |
356 | struct mc13783_led *led = platform_get_drvdata(pdev); | 355 | struct mc13783_led *led = platform_get_drvdata(pdev); |
357 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | 356 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); |
358 | int i; | 357 | int i; |
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index 1e3a8dd820a4..a185610b376b 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c | |||
@@ -21,7 +21,6 @@ | |||
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> | ||
25 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
@@ -149,7 +148,7 @@ static const struct v4l2_file_operations timbradio_fops = { | |||
149 | 148 | ||
150 | static int __devinit timbradio_probe(struct platform_device *pdev) | 149 | static int __devinit timbradio_probe(struct platform_device *pdev) |
151 | { | 150 | { |
152 | struct timb_radio_platform_data *pdata = mfd_get_data(pdev); | 151 | struct timb_radio_platform_data *pdata = pdev->dev.platform_data; |
153 | struct timbradio *tr; | 152 | struct timbradio *tr; |
154 | int err; | 153 | int err; |
155 | 154 | ||
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index e2550dc2944f..46cacf845049 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c | |||
@@ -1990,7 +1990,7 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev) | |||
1990 | 1990 | ||
1991 | static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) | 1991 | static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) |
1992 | { | 1992 | { |
1993 | struct wl1273_core **core = mfd_get_data(pdev); | 1993 | struct wl1273_core **core = pdev->dev.platform_data; |
1994 | struct wl1273_device *radio; | 1994 | struct wl1273_device *radio; |
1995 | struct v4l2_ctrl *ctrl; | 1995 | struct v4l2_ctrl *ctrl; |
1996 | int r = 0; | 1996 | int r = 0; |
diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index 84d4c7c83435..fc611ebeb82c 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c | |||
@@ -24,7 +24,6 @@ | |||
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> | ||
28 | #include <linux/scatterlist.h> | 27 | #include <linux/scatterlist.h> |
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
30 | #include <linux/list.h> | 29 | #include <linux/list.h> |
@@ -791,7 +790,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev) | |||
791 | { | 790 | { |
792 | int err; | 791 | int err; |
793 | struct timblogiw *lw = NULL; | 792 | struct timblogiw *lw = NULL; |
794 | struct timb_video_platform_data *pdata = mfd_get_data(pdev); | 793 | struct timb_video_platform_data *pdata = pdev->dev.platform_data; |
795 | 794 | ||
796 | if (!pdata) { | 795 | if (!pdata) { |
797 | dev_err(&pdev->dev, "No platform data\n"); | 796 | dev_err(&pdev->dev, "No platform data\n"); |
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 011cb6ce861b..17dfe9bb6d27 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -21,13 +21,13 @@ | |||
21 | 21 | ||
22 | #define INT_STATUS_NUM 3 | 22 | #define INT_STATUS_NUM 3 |
23 | 23 | ||
24 | static struct resource bk_resources[] __initdata = { | 24 | static struct resource bk_resources[] __devinitdata = { |
25 | {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, | 25 | {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, |
26 | {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, | 26 | {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, |
27 | {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, | 27 | {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, |
28 | }; | 28 | }; |
29 | 29 | ||
30 | static struct resource led_resources[] __initdata = { | 30 | static struct resource led_resources[] __devinitdata = { |
31 | {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, | 31 | {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, |
32 | {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, | 32 | {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, |
33 | {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, | 33 | {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, |
@@ -36,7 +36,7 @@ static struct resource led_resources[] __initdata = { | |||
36 | {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, | 36 | {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static struct resource regulator_resources[] __initdata = { | 39 | static struct resource regulator_resources[] __devinitdata = { |
40 | {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, | 40 | {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, |
41 | {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, | 41 | {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, |
42 | {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, | 42 | {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, |
@@ -57,15 +57,15 @@ static struct resource regulator_resources[] __initdata = { | |||
57 | {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, | 57 | {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct resource touch_resources[] __initdata = { | 60 | static struct resource touch_resources[] __devinitdata = { |
61 | {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, | 61 | {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static struct resource onkey_resources[] __initdata = { | 64 | static struct resource onkey_resources[] __devinitdata = { |
65 | {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, | 65 | {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static struct resource codec_resources[] __initdata = { | 68 | static struct resource codec_resources[] __devinitdata = { |
69 | /* Headset microphone insertion or removal */ | 69 | /* Headset microphone insertion or removal */ |
70 | {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, | 70 | {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, |
71 | /* Hook-switch press or release */ | 71 | /* Hook-switch press or release */ |
@@ -76,12 +76,12 @@ static struct resource codec_resources[] __initdata = { | |||
76 | {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, | 76 | {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct resource battery_resources[] __initdata = { | 79 | static struct resource battery_resources[] __devinitdata = { |
80 | {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, | 80 | {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, |
81 | {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, | 81 | {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static struct resource charger_resources[] __initdata = { | 84 | static struct resource charger_resources[] __devinitdata = { |
85 | {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, | 85 | {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, |
86 | {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, | 86 | {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, |
87 | {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, | 87 | {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, |
@@ -90,13 +90,17 @@ static struct resource charger_resources[] __initdata = { | |||
90 | {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, | 90 | {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static struct mfd_cell bk_devs[] __initdata = { | 93 | static struct resource rtc_resources[] __devinitdata = { |
94 | {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, | ||
95 | }; | ||
96 | |||
97 | static struct mfd_cell bk_devs[] = { | ||
94 | {"88pm860x-backlight", 0,}, | 98 | {"88pm860x-backlight", 0,}, |
95 | {"88pm860x-backlight", 1,}, | 99 | {"88pm860x-backlight", 1,}, |
96 | {"88pm860x-backlight", 2,}, | 100 | {"88pm860x-backlight", 2,}, |
97 | }; | 101 | }; |
98 | 102 | ||
99 | static struct mfd_cell led_devs[] __initdata = { | 103 | static struct mfd_cell led_devs[] = { |
100 | {"88pm860x-led", 0,}, | 104 | {"88pm860x-led", 0,}, |
101 | {"88pm860x-led", 1,}, | 105 | {"88pm860x-led", 1,}, |
102 | {"88pm860x-led", 2,}, | 106 | {"88pm860x-led", 2,}, |
@@ -105,7 +109,7 @@ static struct mfd_cell led_devs[] __initdata = { | |||
105 | {"88pm860x-led", 5,}, | 109 | {"88pm860x-led", 5,}, |
106 | }; | 110 | }; |
107 | 111 | ||
108 | static struct mfd_cell regulator_devs[] __initdata = { | 112 | static struct mfd_cell regulator_devs[] = { |
109 | {"88pm860x-regulator", 0,}, | 113 | {"88pm860x-regulator", 0,}, |
110 | {"88pm860x-regulator", 1,}, | 114 | {"88pm860x-regulator", 1,}, |
111 | {"88pm860x-regulator", 2,}, | 115 | {"88pm860x-regulator", 2,}, |
@@ -126,15 +130,15 @@ static struct mfd_cell regulator_devs[] __initdata = { | |||
126 | {"88pm860x-regulator", 17,}, | 130 | {"88pm860x-regulator", 17,}, |
127 | }; | 131 | }; |
128 | 132 | ||
129 | static struct mfd_cell touch_devs[] __initdata = { | 133 | static struct mfd_cell touch_devs[] = { |
130 | {"88pm860x-touch", -1,}, | 134 | {"88pm860x-touch", -1,}, |
131 | }; | 135 | }; |
132 | 136 | ||
133 | static struct mfd_cell onkey_devs[] __initdata = { | 137 | static struct mfd_cell onkey_devs[] = { |
134 | {"88pm860x-onkey", -1,}, | 138 | {"88pm860x-onkey", -1,}, |
135 | }; | 139 | }; |
136 | 140 | ||
137 | static struct mfd_cell codec_devs[] __initdata = { | 141 | static struct mfd_cell codec_devs[] = { |
138 | {"88pm860x-codec", -1,}, | 142 | {"88pm860x-codec", -1,}, |
139 | }; | 143 | }; |
140 | 144 | ||
@@ -143,11 +147,10 @@ static struct mfd_cell power_devs[] = { | |||
143 | {"88pm860x-charger", -1,}, | 147 | {"88pm860x-charger", -1,}, |
144 | }; | 148 | }; |
145 | 149 | ||
146 | static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)]; | 150 | static struct mfd_cell rtc_devs[] = { |
147 | static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)]; | 151 | {"88pm860x-rtc", -1,}, |
148 | static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)]; | 152 | }; |
149 | static struct pm860x_touch_pdata touch_pdata; | 153 | |
150 | static struct pm860x_power_pdata power_pdata; | ||
151 | 154 | ||
152 | struct pm860x_irq_data { | 155 | struct pm860x_irq_data { |
153 | int reg; | 156 | int reg; |
@@ -501,7 +504,6 @@ static void device_irq_exit(struct pm860x_chip *chip) | |||
501 | } | 504 | } |
502 | 505 | ||
503 | static void __devinit device_bk_init(struct pm860x_chip *chip, | 506 | static void __devinit device_bk_init(struct pm860x_chip *chip, |
504 | struct i2c_client *i2c, | ||
505 | struct pm860x_platform_data *pdata) | 507 | struct pm860x_platform_data *pdata) |
506 | { | 508 | { |
507 | int ret; | 509 | int ret; |
@@ -514,13 +516,12 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, | |||
514 | pdata->num_backlights = ARRAY_SIZE(bk_devs); | 516 | pdata->num_backlights = ARRAY_SIZE(bk_devs); |
515 | 517 | ||
516 | for (i = 0; i < pdata->num_backlights; i++) { | 518 | for (i = 0; i < pdata->num_backlights; i++) { |
517 | memcpy(&bk_pdata[i], &pdata->backlight[i], | 519 | bk_devs[i].platform_data = &pdata->backlight[i]; |
518 | sizeof(struct pm860x_backlight_pdata)); | 520 | bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata); |
519 | bk_devs[i].mfd_data = &bk_pdata[i]; | ||
520 | 521 | ||
521 | for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { | 522 | for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { |
522 | id = bk_resources[j].start; | 523 | id = bk_resources[j].start; |
523 | if (bk_pdata[i].flags != id) | 524 | if (pdata->backlight[i].flags != id) |
524 | continue; | 525 | continue; |
525 | 526 | ||
526 | bk_devs[i].num_resources = 1; | 527 | bk_devs[i].num_resources = 1; |
@@ -538,7 +539,6 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, | |||
538 | } | 539 | } |
539 | 540 | ||
540 | static void __devinit device_led_init(struct pm860x_chip *chip, | 541 | static void __devinit device_led_init(struct pm860x_chip *chip, |
541 | struct i2c_client *i2c, | ||
542 | struct pm860x_platform_data *pdata) | 542 | struct pm860x_platform_data *pdata) |
543 | { | 543 | { |
544 | int ret; | 544 | int ret; |
@@ -551,13 +551,12 @@ static void __devinit device_led_init(struct pm860x_chip *chip, | |||
551 | pdata->num_leds = ARRAY_SIZE(led_devs); | 551 | pdata->num_leds = ARRAY_SIZE(led_devs); |
552 | 552 | ||
553 | for (i = 0; i < pdata->num_leds; i++) { | 553 | for (i = 0; i < pdata->num_leds; i++) { |
554 | memcpy(&led_pdata[i], &pdata->led[i], | 554 | led_devs[i].platform_data = &pdata->led[i]; |
555 | sizeof(struct pm860x_led_pdata)); | 555 | led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata); |
556 | led_devs[i].mfd_data = &led_pdata[i]; | ||
557 | 556 | ||
558 | for (j = 0; j < ARRAY_SIZE(led_devs); j++) { | 557 | for (j = 0; j < ARRAY_SIZE(led_devs); j++) { |
559 | id = led_resources[j].start; | 558 | id = led_resources[j].start; |
560 | if (led_pdata[i].flags != id) | 559 | if (pdata->led[i].flags != id) |
561 | continue; | 560 | continue; |
562 | 561 | ||
563 | led_devs[i].num_resources = 1; | 562 | led_devs[i].num_resources = 1; |
@@ -575,12 +574,11 @@ static void __devinit device_led_init(struct pm860x_chip *chip, | |||
575 | } | 574 | } |
576 | 575 | ||
577 | static void __devinit device_regulator_init(struct pm860x_chip *chip, | 576 | static void __devinit device_regulator_init(struct pm860x_chip *chip, |
578 | struct i2c_client *i2c, | ||
579 | struct pm860x_platform_data *pdata) | 577 | struct pm860x_platform_data *pdata) |
580 | { | 578 | { |
581 | struct regulator_init_data *initdata; | 579 | struct regulator_init_data *initdata; |
582 | int ret; | 580 | int ret; |
583 | int i, j; | 581 | int i, seq; |
584 | 582 | ||
585 | if ((pdata == NULL) || (pdata->regulator == NULL)) | 583 | if ((pdata == NULL) || (pdata->regulator == NULL)) |
586 | return; | 584 | return; |
@@ -588,41 +586,21 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip, | |||
588 | if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) | 586 | if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) |
589 | pdata->num_regulators = ARRAY_SIZE(regulator_devs); | 587 | pdata->num_regulators = ARRAY_SIZE(regulator_devs); |
590 | 588 | ||
591 | for (i = 0, j = -1; i < pdata->num_regulators; i++) { | 589 | for (i = 0, seq = -1; i < pdata->num_regulators; i++) { |
592 | initdata = &pdata->regulator[i]; | 590 | initdata = &pdata->regulator[i]; |
593 | if (strstr(initdata->constraints.name, "BUCK")) { | 591 | seq = *(unsigned int *)initdata->driver_data; |
594 | sscanf(initdata->constraints.name, "BUCK%d", &j); | 592 | if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) { |
595 | /* BUCK1 ~ BUCK3 */ | 593 | dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n", |
596 | if ((j < 1) || (j > 3)) { | 594 | seq, initdata->constraints.name); |
597 | dev_err(chip->dev, "Failed to add constraint " | ||
598 | "(%s)\n", initdata->constraints.name); | ||
599 | goto out; | ||
600 | } | ||
601 | j = (j - 1) + PM8607_ID_BUCK1; | ||
602 | } | ||
603 | if (strstr(initdata->constraints.name, "LDO")) { | ||
604 | sscanf(initdata->constraints.name, "LDO%d", &j); | ||
605 | /* LDO1 ~ LDO15 */ | ||
606 | if ((j < 1) || (j > 15)) { | ||
607 | dev_err(chip->dev, "Failed to add constraint " | ||
608 | "(%s)\n", initdata->constraints.name); | ||
609 | goto out; | ||
610 | } | ||
611 | j = (j - 1) + PM8607_ID_LDO1; | ||
612 | } | ||
613 | if (j == -1) { | ||
614 | dev_err(chip->dev, "Failed to add constraint (%s)\n", | ||
615 | initdata->constraints.name); | ||
616 | goto out; | 595 | goto out; |
617 | } | 596 | } |
618 | memcpy(®ulator_pdata[i], &pdata->regulator[i], | 597 | regulator_devs[i].platform_data = &pdata->regulator[i]; |
619 | sizeof(struct regulator_init_data)); | 598 | regulator_devs[i].pdata_size = sizeof(struct regulator_init_data); |
620 | regulator_devs[i].mfd_data = ®ulator_pdata[i]; | ||
621 | regulator_devs[i].num_resources = 1; | 599 | regulator_devs[i].num_resources = 1; |
622 | regulator_devs[i].resources = ®ulator_resources[j]; | 600 | regulator_devs[i].resources = ®ulator_resources[seq]; |
623 | 601 | ||
624 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, | 602 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, |
625 | ®ulator_resources[j], 0); | 603 | ®ulator_resources[seq], 0); |
626 | if (ret < 0) { | 604 | if (ret < 0) { |
627 | dev_err(chip->dev, "Failed to add regulator subdev\n"); | 605 | dev_err(chip->dev, "Failed to add regulator subdev\n"); |
628 | goto out; | 606 | goto out; |
@@ -632,17 +610,35 @@ out: | |||
632 | return; | 610 | return; |
633 | } | 611 | } |
634 | 612 | ||
613 | static void __devinit device_rtc_init(struct pm860x_chip *chip, | ||
614 | struct pm860x_platform_data *pdata) | ||
615 | { | ||
616 | int ret; | ||
617 | |||
618 | if ((pdata == NULL)) | ||
619 | return; | ||
620 | |||
621 | rtc_devs[0].platform_data = pdata->rtc; | ||
622 | rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); | ||
623 | rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); | ||
624 | rtc_devs[0].resources = &rtc_resources[0]; | ||
625 | ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], | ||
626 | ARRAY_SIZE(rtc_devs), &rtc_resources[0], | ||
627 | chip->irq_base); | ||
628 | if (ret < 0) | ||
629 | dev_err(chip->dev, "Failed to add rtc subdev\n"); | ||
630 | } | ||
631 | |||
635 | static void __devinit device_touch_init(struct pm860x_chip *chip, | 632 | static void __devinit device_touch_init(struct pm860x_chip *chip, |
636 | struct i2c_client *i2c, | ||
637 | struct pm860x_platform_data *pdata) | 633 | struct pm860x_platform_data *pdata) |
638 | { | 634 | { |
639 | int ret; | 635 | int ret; |
640 | 636 | ||
641 | if ((pdata == NULL) || (pdata->touch == NULL)) | 637 | if (pdata == NULL) |
642 | return; | 638 | return; |
643 | 639 | ||
644 | memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata)); | 640 | touch_devs[0].platform_data = pdata->touch; |
645 | touch_devs[0].mfd_data = &touch_pdata; | 641 | touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata); |
646 | touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); | 642 | touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); |
647 | touch_devs[0].resources = &touch_resources[0]; | 643 | touch_devs[0].resources = &touch_resources[0]; |
648 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], | 644 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], |
@@ -653,16 +649,15 @@ static void __devinit device_touch_init(struct pm860x_chip *chip, | |||
653 | } | 649 | } |
654 | 650 | ||
655 | static void __devinit device_power_init(struct pm860x_chip *chip, | 651 | static void __devinit device_power_init(struct pm860x_chip *chip, |
656 | struct i2c_client *i2c, | ||
657 | struct pm860x_platform_data *pdata) | 652 | struct pm860x_platform_data *pdata) |
658 | { | 653 | { |
659 | int ret; | 654 | int ret; |
660 | 655 | ||
661 | if ((pdata == NULL) || (pdata->power == NULL)) | 656 | if (pdata == NULL) |
662 | return; | 657 | return; |
663 | 658 | ||
664 | memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata)); | 659 | power_devs[0].platform_data = pdata->power; |
665 | power_devs[0].mfd_data = &power_pdata; | 660 | power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata); |
666 | power_devs[0].num_resources = ARRAY_SIZE(battery_resources); | 661 | power_devs[0].num_resources = ARRAY_SIZE(battery_resources); |
667 | power_devs[0].resources = &battery_resources[0], | 662 | power_devs[0].resources = &battery_resources[0], |
668 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, | 663 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, |
@@ -670,7 +665,8 @@ static void __devinit device_power_init(struct pm860x_chip *chip, | |||
670 | if (ret < 0) | 665 | if (ret < 0) |
671 | dev_err(chip->dev, "Failed to add battery subdev\n"); | 666 | dev_err(chip->dev, "Failed to add battery subdev\n"); |
672 | 667 | ||
673 | power_devs[1].mfd_data = &power_pdata; | 668 | power_devs[1].platform_data = pdata->power; |
669 | power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata); | ||
674 | power_devs[1].num_resources = ARRAY_SIZE(charger_resources); | 670 | power_devs[1].num_resources = ARRAY_SIZE(charger_resources); |
675 | power_devs[1].resources = &charger_resources[0], | 671 | power_devs[1].resources = &charger_resources[0], |
676 | ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, | 672 | ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, |
@@ -680,7 +676,6 @@ static void __devinit device_power_init(struct pm860x_chip *chip, | |||
680 | } | 676 | } |
681 | 677 | ||
682 | static void __devinit device_onkey_init(struct pm860x_chip *chip, | 678 | static void __devinit device_onkey_init(struct pm860x_chip *chip, |
683 | struct i2c_client *i2c, | ||
684 | struct pm860x_platform_data *pdata) | 679 | struct pm860x_platform_data *pdata) |
685 | { | 680 | { |
686 | int ret; | 681 | int ret; |
@@ -695,7 +690,6 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip, | |||
695 | } | 690 | } |
696 | 691 | ||
697 | static void __devinit device_codec_init(struct pm860x_chip *chip, | 692 | static void __devinit device_codec_init(struct pm860x_chip *chip, |
698 | struct i2c_client *i2c, | ||
699 | struct pm860x_platform_data *pdata) | 693 | struct pm860x_platform_data *pdata) |
700 | { | 694 | { |
701 | int ret; | 695 | int ret; |
@@ -763,11 +757,12 @@ static void __devinit device_8607_init(struct pm860x_chip *chip, | |||
763 | if (ret < 0) | 757 | if (ret < 0) |
764 | goto out; | 758 | goto out; |
765 | 759 | ||
766 | device_regulator_init(chip, i2c, pdata); | 760 | device_regulator_init(chip, pdata); |
767 | device_onkey_init(chip, i2c, pdata); | 761 | device_rtc_init(chip, pdata); |
768 | device_touch_init(chip, i2c, pdata); | 762 | device_onkey_init(chip, pdata); |
769 | device_power_init(chip, i2c, pdata); | 763 | device_touch_init(chip, pdata); |
770 | device_codec_init(chip, i2c, pdata); | 764 | device_power_init(chip, pdata); |
765 | device_codec_init(chip, pdata); | ||
771 | out: | 766 | out: |
772 | return; | 767 | return; |
773 | } | 768 | } |
@@ -779,8 +774,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
779 | 774 | ||
780 | switch (chip->id) { | 775 | switch (chip->id) { |
781 | case CHIP_PM8606: | 776 | case CHIP_PM8606: |
782 | device_bk_init(chip, chip->client, pdata); | 777 | device_bk_init(chip, pdata); |
783 | device_led_init(chip, chip->client, pdata); | 778 | device_led_init(chip, pdata); |
784 | break; | 779 | break; |
785 | case CHIP_PM8607: | 780 | case CHIP_PM8607: |
786 | device_8607_init(chip, chip->client, pdata); | 781 | device_8607_init(chip, chip->client, pdata); |
@@ -790,8 +785,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
790 | if (chip->companion) { | 785 | if (chip->companion) { |
791 | switch (chip->id) { | 786 | switch (chip->id) { |
792 | case CHIP_PM8607: | 787 | case CHIP_PM8607: |
793 | device_bk_init(chip, chip->companion, pdata); | 788 | device_bk_init(chip, pdata); |
794 | device_led_init(chip, chip->companion, pdata); | 789 | device_led_init(chip, pdata); |
795 | break; | 790 | break; |
796 | case CHIP_PM8606: | 791 | case CHIP_PM8606: |
797 | device_8607_init(chip, chip->companion, pdata); | 792 | device_8607_init(chip, chip->companion, pdata); |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 481770ab2716..8344fc0ab858 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -157,6 +157,20 @@ config TPS6507X | |||
157 | This driver can also be built as a module. If so, the module | 157 | This driver can also be built as a module. If so, the module |
158 | will be called tps6507x. | 158 | will be called tps6507x. |
159 | 159 | ||
160 | config MFD_TPS6586X | ||
161 | bool "TPS6586x Power Management chips" | ||
162 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS | ||
163 | select MFD_CORE | ||
164 | help | ||
165 | If you say yes here you get support for the TPS6586X series of | ||
166 | Power Management chips. | ||
167 | This driver provides common support for accessing the device, | ||
168 | additional drivers must be enabled in order to use the | ||
169 | functionality of the device. | ||
170 | |||
171 | This driver can also be built as a module. If so, the module | ||
172 | will be called tps6586x. | ||
173 | |||
160 | config MENELAUS | 174 | config MENELAUS |
161 | bool "Texas Instruments TWL92330/Menelaus PM chip" | 175 | bool "Texas Instruments TWL92330/Menelaus PM chip" |
162 | depends on I2C=y && ARCH_OMAP2 | 176 | depends on I2C=y && ARCH_OMAP2 |
@@ -455,6 +469,20 @@ config MFD_PCF50633 | |||
455 | facilities, and registers devices for the various functions | 469 | facilities, and registers devices for the various functions |
456 | so that function-specific drivers can bind to them. | 470 | so that function-specific drivers can bind to them. |
457 | 471 | ||
472 | config PCF50633_ADC | ||
473 | tristate "Support for NXP PCF50633 ADC" | ||
474 | depends on MFD_PCF50633 | ||
475 | help | ||
476 | Say yes here if you want to include support for ADC in the | ||
477 | NXP PCF50633 chip. | ||
478 | |||
479 | config PCF50633_GPIO | ||
480 | tristate "Support for NXP PCF50633 GPIO" | ||
481 | depends on MFD_PCF50633 | ||
482 | help | ||
483 | Say yes here if you want to include support GPIO for pins on | ||
484 | the PCF50633 chip. | ||
485 | |||
458 | config MFD_MC13783 | 486 | config MFD_MC13783 |
459 | tristate | 487 | tristate |
460 | 488 | ||
@@ -470,20 +498,6 @@ config MFD_MC13XXX | |||
470 | additional drivers must be enabled in order to use the | 498 | additional drivers must be enabled in order to use the |
471 | functionality of the device. | 499 | functionality of the device. |
472 | 500 | ||
473 | config PCF50633_ADC | ||
474 | tristate "Support for NXP PCF50633 ADC" | ||
475 | depends on MFD_PCF50633 | ||
476 | help | ||
477 | Say yes here if you want to include support for ADC in the | ||
478 | NXP PCF50633 chip. | ||
479 | |||
480 | config PCF50633_GPIO | ||
481 | tristate "Support for NXP PCF50633 GPIO" | ||
482 | depends on MFD_PCF50633 | ||
483 | help | ||
484 | Say yes here if you want to include support GPIO for pins on | ||
485 | the PCF50633 chip. | ||
486 | |||
487 | config ABX500_CORE | 501 | config ABX500_CORE |
488 | bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" | 502 | bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" |
489 | default y if ARCH_U300 || ARCH_U8500 | 503 | default y if ARCH_U300 || ARCH_U8500 |
@@ -649,20 +663,6 @@ config MFD_JZ4740_ADC | |||
649 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. | 663 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. |
650 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. | 664 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. |
651 | 665 | ||
652 | config MFD_TPS6586X | ||
653 | bool "TPS6586x Power Management chips" | ||
654 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS | ||
655 | select MFD_CORE | ||
656 | help | ||
657 | If you say yes here you get support for the TPS6586X series of | ||
658 | Power Management chips. | ||
659 | This driver provides common support for accessing the device, | ||
660 | additional drivers must be enabled in order to use the | ||
661 | functionality of the device. | ||
662 | |||
663 | This driver can also be built as a module. If so, the module | ||
664 | will be called tps6586x. | ||
665 | |||
666 | config MFD_VX855 | 666 | config MFD_VX855 |
667 | tristate "Support for VIA VX855/VX875 integrated south bridge" | 667 | tristate "Support for VIA VX855/VX875 integrated south bridge" |
668 | depends on PCI | 668 | depends on PCI |
@@ -691,6 +691,34 @@ config MFD_OMAP_USB_HOST | |||
691 | This MFD driver does the required setup functionalities for | 691 | This MFD driver does the required setup functionalities for |
692 | OMAP USB Host drivers. | 692 | OMAP USB Host drivers. |
693 | 693 | ||
694 | config MFD_PM8XXX | ||
695 | tristate | ||
696 | |||
697 | config MFD_PM8921_CORE | ||
698 | tristate "Qualcomm PM8921 PMIC chip" | ||
699 | depends on MSM_SSBI | ||
700 | select MFD_CORE | ||
701 | select MFD_PM8XXX | ||
702 | help | ||
703 | If you say yes to this option, support will be included for the | ||
704 | built-in PM8921 PMIC chip. | ||
705 | |||
706 | This is required if your board has a PM8921 and uses its features, | ||
707 | such as: MPPs, GPIOs, regulators, interrupts, and PWM. | ||
708 | |||
709 | Say M here if you want to include support for PM8921 chip as a module. | ||
710 | This will build a module called "pm8921-core". | ||
711 | |||
712 | config MFD_PM8XXX_IRQ | ||
713 | bool "Support for Qualcomm PM8xxx IRQ features" | ||
714 | depends on MFD_PM8XXX | ||
715 | default y if MFD_PM8XXX | ||
716 | help | ||
717 | This is the IRQ driver for Qualcomm PM 8xxx PMIC chips. | ||
718 | |||
719 | This is required to use certain other PM 8xxx features, such as GPIO | ||
720 | and MPP. | ||
721 | |||
694 | endif # MFD_SUPPORT | 722 | endif # MFD_SUPPORT |
695 | 723 | ||
696 | menu "Multimedia Capabilities Port drivers" | 724 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 24aa44448daf..1acb8f29a96c 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -91,3 +91,5 @@ obj-$(CONFIG_MFD_VX855) += vx855.o | |||
91 | obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o | 91 | obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o |
92 | obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o | 92 | obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o |
93 | obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o | 93 | obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o |
94 | obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o | ||
95 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o | ||
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index a751927047ac..a20e1c41bed2 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -949,8 +949,10 @@ 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].mfd_data = ab3100_plf_data; | 953 | ab3100_devs[i].platform_data = ab3100_plf_data; |
954 | ab3100_devs[i].pdata_size = sizeof(struct ab3100_platform_data); | ||
955 | } | ||
954 | 956 | ||
955 | err = mfd_add_devices(&client->dev, 0, ab3100_devs, | 957 | err = mfd_add_devices(&client->dev, 0, ab3100_devs, |
956 | ARRAY_SIZE(ab3100_devs), NULL, 0); | 958 | ARRAY_SIZE(ab3100_devs), NULL, 0); |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index ff86acf3e6bd..3d7dce671b93 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c | |||
@@ -1320,8 +1320,10 @@ 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].mfd_data = ab3550_plf_data->dev_data[i]; | 1324 | ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i]; |
1325 | ab3550_devs[i].pdata_size = ab3550_plf_data->dev_data_sz[i]; | ||
1326 | } | ||
1325 | 1327 | ||
1326 | err = mfd_add_devices(&client->dev, 0, ab3550_devs, | 1328 | err = mfd_add_devices(&client->dev, 0, ab3550_devs, |
1327 | ARRAY_SIZE(ab3550_devs), NULL, | 1329 | ARRAY_SIZE(ab3550_devs), NULL, |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 67d01c938284..fc0c1af1566e 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -254,8 +254,9 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) | |||
254 | if (new == old) | 254 | if (new == old) |
255 | continue; | 255 | continue; |
256 | 256 | ||
257 | /* Interrupt register 12 does'nt exist prior to version 0x20 */ | 257 | /* Interrupt register 12 doesn't exist prior to version 2.0 */ |
258 | if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20) | 258 | if (ab8500_irq_regoffset[i] == 11 && |
259 | ab8500->chip_id < AB8500_CUT2P0) | ||
259 | continue; | 260 | continue; |
260 | 261 | ||
261 | ab8500->oldmask[i] = new; | 262 | ab8500->oldmask[i] = new; |
@@ -307,8 +308,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev) | |||
307 | int status; | 308 | int status; |
308 | u8 value; | 309 | u8 value; |
309 | 310 | ||
310 | /* Interrupt register 12 does'nt exist prior to version 0x20 */ | 311 | /* Interrupt register 12 doesn't exist prior to version 2.0 */ |
311 | if (regoffset == 11 && ab8500->chip_id < 0x20) | 312 | if (regoffset == 11 && ab8500->chip_id < AB8500_CUT2P0) |
312 | continue; | 313 | continue; |
313 | 314 | ||
314 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, | 315 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, |
@@ -724,17 +725,15 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
724 | if (ret < 0) | 725 | if (ret < 0) |
725 | return ret; | 726 | return ret; |
726 | 727 | ||
727 | /* | 728 | switch (value) { |
728 | * 0x0 - Early Drop | 729 | case AB8500_CUTEARLY: |
729 | * 0x10 - Cut 1.0 | 730 | case AB8500_CUT1P0: |
730 | * 0x11 - Cut 1.1 | 731 | case AB8500_CUT1P1: |
731 | * 0x20 - Cut 2.0 | 732 | case AB8500_CUT2P0: |
732 | * 0x30 - Cut 3.0 | 733 | case AB8500_CUT3P0: |
733 | */ | ||
734 | if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20 || | ||
735 | value == 0x30) { | ||
736 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); | 734 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); |
737 | } else { | 735 | break; |
736 | default: | ||
738 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); | 737 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); |
739 | return -EINVAL; | 738 | return -EINVAL; |
740 | } | 739 | } |
@@ -763,8 +762,9 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
763 | 762 | ||
764 | /* Clear and mask all interrupts */ | 763 | /* Clear and mask all interrupts */ |
765 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { | 764 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { |
766 | /* Interrupt register 12 does'nt exist prior to version 0x20 */ | 765 | /* Interrupt register 12 doesn't exist prior to version 2.0 */ |
767 | if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20) | 766 | if (ab8500_irq_regoffset[i] == 11 && |
767 | ab8500->chip_id < AB8500_CUT2P0) | ||
768 | continue; | 768 | continue; |
769 | 769 | ||
770 | get_register_interruptible(ab8500, AB8500_INTERRUPT, | 770 | get_register_interruptible(ab8500, AB8500_INTERRUPT, |
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 6421ad1160de..f16afb234ff9 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #define SW_AVG_16 0x60 | 57 | #define SW_AVG_16 0x60 |
58 | #define ADC_SW_CONV 0x04 | 58 | #define ADC_SW_CONV 0x04 |
59 | #define EN_ICHAR 0x80 | 59 | #define EN_ICHAR 0x80 |
60 | #define BTEMP_PULL_UP 0x08 | ||
60 | #define EN_BUF 0x40 | 61 | #define EN_BUF 0x40 |
61 | #define DIS_ZERO 0x00 | 62 | #define DIS_ZERO 0x00 |
62 | #define GPADC_BUSY 0x01 | 63 | #define GPADC_BUSY 0x01 |
@@ -101,6 +102,7 @@ struct adc_cal_data { | |||
101 | 102 | ||
102 | /** | 103 | /** |
103 | * struct ab8500_gpadc - AB8500 GPADC device information | 104 | * struct ab8500_gpadc - AB8500 GPADC device information |
105 | * @chip_id ABB chip id | ||
104 | * @dev: pointer to the struct device | 106 | * @dev: pointer to the struct device |
105 | * @node: a list of AB8500 GPADCs, hence prepared for | 107 | * @node: a list of AB8500 GPADCs, hence prepared for |
106 | reentrance | 108 | reentrance |
@@ -112,6 +114,7 @@ struct adc_cal_data { | |||
112 | * @cal_data array of ADC calibration data structs | 114 | * @cal_data array of ADC calibration data structs |
113 | */ | 115 | */ |
114 | struct ab8500_gpadc { | 116 | struct ab8500_gpadc { |
117 | u8 chip_id; | ||
115 | struct device *dev; | 118 | struct device *dev; |
116 | struct list_head node; | 119 | struct list_head node; |
117 | struct completion ab8500_gpadc_complete; | 120 | struct completion ab8500_gpadc_complete; |
@@ -274,6 +277,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
274 | dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n"); | 277 | dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n"); |
275 | goto out; | 278 | goto out; |
276 | } | 279 | } |
280 | |||
277 | /* Select the input source and set average samples to 16 */ | 281 | /* Select the input source and set average samples to 16 */ |
278 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 282 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
279 | AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16)); | 283 | AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16)); |
@@ -282,9 +286,11 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
282 | "gpadc_conversion: set avg samples failed\n"); | 286 | "gpadc_conversion: set avg samples failed\n"); |
283 | goto out; | 287 | goto out; |
284 | } | 288 | } |
289 | |||
285 | /* | 290 | /* |
286 | * Enable ADC, buffering, select rising edge and enable ADC path | 291 | * Enable ADC, buffering, select rising edge and enable ADC path |
287 | * charging current sense if it needed | 292 | * charging current sense if it needed, ABB 3.0 needs some special |
293 | * treatment too. | ||
288 | */ | 294 | */ |
289 | switch (input) { | 295 | switch (input) { |
290 | case MAIN_CHARGER_C: | 296 | case MAIN_CHARGER_C: |
@@ -294,6 +300,23 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
294 | EN_BUF | EN_ICHAR, | 300 | EN_BUF | EN_ICHAR, |
295 | EN_BUF | EN_ICHAR); | 301 | EN_BUF | EN_ICHAR); |
296 | break; | 302 | break; |
303 | case BTEMP_BALL: | ||
304 | if (gpadc->chip_id >= AB8500_CUT3P0) { | ||
305 | /* Turn on btemp pull-up on ABB 3.0 */ | ||
306 | ret = abx500_mask_and_set_register_interruptible( | ||
307 | gpadc->dev, | ||
308 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
309 | EN_BUF | BTEMP_PULL_UP, | ||
310 | EN_BUF | BTEMP_PULL_UP); | ||
311 | |||
312 | /* | ||
313 | * Delay might be needed for ABB8500 cut 3.0, if not, remove | ||
314 | * when hardware will be availible | ||
315 | */ | ||
316 | msleep(1); | ||
317 | break; | ||
318 | } | ||
319 | /* Intentional fallthrough */ | ||
297 | default: | 320 | default: |
298 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 321 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, |
299 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); | 322 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); |
@@ -304,6 +327,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
304 | "gpadc_conversion: select falling edge failed\n"); | 327 | "gpadc_conversion: select falling edge failed\n"); |
305 | goto out; | 328 | goto out; |
306 | } | 329 | } |
330 | |||
307 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 331 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, |
308 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV); | 332 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV); |
309 | if (ret < 0) { | 333 | if (ret < 0) { |
@@ -552,6 +576,14 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) | |||
552 | goto fail; | 576 | goto fail; |
553 | } | 577 | } |
554 | 578 | ||
579 | /* Get Chip ID of the ABB ASIC */ | ||
580 | ret = abx500_get_chip_id(gpadc->dev); | ||
581 | if (ret < 0) { | ||
582 | dev_err(gpadc->dev, "failed to get chip ID\n"); | ||
583 | goto fail_irq; | ||
584 | } | ||
585 | gpadc->chip_id = (u8) ret; | ||
586 | |||
555 | /* VTVout LDO used to power up ab8500-GPADC */ | 587 | /* VTVout LDO used to power up ab8500-GPADC */ |
556 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); | 588 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); |
557 | if (IS_ERR(gpadc->regu)) { | 589 | if (IS_ERR(gpadc->regu)) { |
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 0b4d5b23bec9..c27fd1fc3b86 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
@@ -88,19 +88,19 @@ struct asic3 { | |||
88 | 88 | ||
89 | static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); | 89 | static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); |
90 | 90 | ||
91 | static inline void asic3_write_register(struct asic3 *asic, | 91 | void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 value) |
92 | unsigned int reg, u32 value) | ||
93 | { | 92 | { |
94 | iowrite16(value, asic->mapping + | 93 | iowrite16(value, asic->mapping + |
95 | (reg >> asic->bus_shift)); | 94 | (reg >> asic->bus_shift)); |
96 | } | 95 | } |
96 | EXPORT_SYMBOL_GPL(asic3_write_register); | ||
97 | 97 | ||
98 | static inline u32 asic3_read_register(struct asic3 *asic, | 98 | u32 asic3_read_register(struct asic3 *asic, unsigned int reg) |
99 | unsigned int reg) | ||
100 | { | 99 | { |
101 | return ioread16(asic->mapping + | 100 | return ioread16(asic->mapping + |
102 | (reg >> asic->bus_shift)); | 101 | (reg >> asic->bus_shift)); |
103 | } | 102 | } |
103 | EXPORT_SYMBOL_GPL(asic3_read_register); | ||
104 | 104 | ||
105 | static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set) | 105 | static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set) |
106 | { | 106 | { |
@@ -676,7 +676,8 @@ static struct mfd_cell asic3_cell_ds1wm = { | |||
676 | .name = "ds1wm", | 676 | .name = "ds1wm", |
677 | .enable = ds1wm_enable, | 677 | .enable = ds1wm_enable, |
678 | .disable = ds1wm_disable, | 678 | .disable = ds1wm_disable, |
679 | .mfd_data = &ds1wm_pdata, | 679 | .platform_data = &ds1wm_pdata, |
680 | .pdata_size = sizeof(ds1wm_pdata), | ||
680 | .num_resources = ARRAY_SIZE(ds1wm_resources), | 681 | .num_resources = ARRAY_SIZE(ds1wm_resources), |
681 | .resources = ds1wm_resources, | 682 | .resources = ds1wm_resources, |
682 | }; | 683 | }; |
@@ -777,12 +778,61 @@ static struct mfd_cell asic3_cell_mmc = { | |||
777 | .name = "tmio-mmc", | 778 | .name = "tmio-mmc", |
778 | .enable = asic3_mmc_enable, | 779 | .enable = asic3_mmc_enable, |
779 | .disable = asic3_mmc_disable, | 780 | .disable = asic3_mmc_disable, |
780 | .mfd_data = &asic3_mmc_data, | 781 | .platform_data = &asic3_mmc_data, |
782 | .pdata_size = sizeof(asic3_mmc_data), | ||
781 | .num_resources = ARRAY_SIZE(asic3_mmc_resources), | 783 | .num_resources = ARRAY_SIZE(asic3_mmc_resources), |
782 | .resources = asic3_mmc_resources, | 784 | .resources = asic3_mmc_resources, |
783 | }; | 785 | }; |
784 | 786 | ||
787 | static const int clock_ledn[ASIC3_NUM_LEDS] = { | ||
788 | [0] = ASIC3_CLOCK_LED0, | ||
789 | [1] = ASIC3_CLOCK_LED1, | ||
790 | [2] = ASIC3_CLOCK_LED2, | ||
791 | }; | ||
792 | |||
793 | static int asic3_leds_enable(struct platform_device *pdev) | ||
794 | { | ||
795 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
796 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
797 | |||
798 | asic3_clk_enable(asic, &asic->clocks[clock_ledn[cell->id]]); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static int asic3_leds_disable(struct platform_device *pdev) | ||
804 | { | ||
805 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
806 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
807 | |||
808 | asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]); | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = { | ||
814 | [0] = { | ||
815 | .name = "leds-asic3", | ||
816 | .id = 0, | ||
817 | .enable = asic3_leds_enable, | ||
818 | .disable = asic3_leds_disable, | ||
819 | }, | ||
820 | [1] = { | ||
821 | .name = "leds-asic3", | ||
822 | .id = 1, | ||
823 | .enable = asic3_leds_enable, | ||
824 | .disable = asic3_leds_disable, | ||
825 | }, | ||
826 | [2] = { | ||
827 | .name = "leds-asic3", | ||
828 | .id = 2, | ||
829 | .enable = asic3_leds_enable, | ||
830 | .disable = asic3_leds_disable, | ||
831 | }, | ||
832 | }; | ||
833 | |||
785 | static int __init asic3_mfd_probe(struct platform_device *pdev, | 834 | static int __init asic3_mfd_probe(struct platform_device *pdev, |
835 | struct asic3_platform_data *pdata, | ||
786 | struct resource *mem) | 836 | struct resource *mem) |
787 | { | 837 | { |
788 | struct asic3 *asic = platform_get_drvdata(pdev); | 838 | struct asic3 *asic = platform_get_drvdata(pdev); |
@@ -806,7 +856,8 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, | |||
806 | 856 | ||
807 | /* MMC */ | 857 | /* MMC */ |
808 | asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + | 858 | asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + |
809 | mem_sdio->start, 0x400 >> asic->bus_shift); | 859 | mem_sdio->start, |
860 | ASIC3_SD_CONFIG_SIZE >> asic->bus_shift); | ||
810 | if (!asic->tmio_cnf) { | 861 | if (!asic->tmio_cnf) { |
811 | ret = -ENOMEM; | 862 | ret = -ENOMEM; |
812 | dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n"); | 863 | dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n"); |
@@ -820,9 +871,23 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, | |||
820 | if (ret < 0) | 871 | if (ret < 0) |
821 | goto out; | 872 | goto out; |
822 | 873 | ||
823 | if (mem_sdio && (irq >= 0)) | 874 | if (mem_sdio && (irq >= 0)) { |
824 | ret = mfd_add_devices(&pdev->dev, pdev->id, | 875 | ret = mfd_add_devices(&pdev->dev, pdev->id, |
825 | &asic3_cell_mmc, 1, mem_sdio, irq); | 876 | &asic3_cell_mmc, 1, mem_sdio, irq); |
877 | if (ret < 0) | ||
878 | goto out; | ||
879 | } | ||
880 | |||
881 | if (pdata->leds) { | ||
882 | int i; | ||
883 | |||
884 | for (i = 0; i < ASIC3_NUM_LEDS; ++i) { | ||
885 | asic3_cell_leds[i].platform_data = &pdata->leds[i]; | ||
886 | asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]); | ||
887 | } | ||
888 | ret = mfd_add_devices(&pdev->dev, 0, | ||
889 | asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0); | ||
890 | } | ||
826 | 891 | ||
827 | out: | 892 | out: |
828 | return ret; | 893 | return ret; |
@@ -903,7 +968,7 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
903 | */ | 968 | */ |
904 | memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init)); | 969 | memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init)); |
905 | 970 | ||
906 | asic3_mfd_probe(pdev, mem); | 971 | asic3_mfd_probe(pdev, pdata, mem); |
907 | 972 | ||
908 | dev_info(asic->dev, "ASIC3 Core driver\n"); | 973 | dev_info(asic->dev, "ASIC3 Core driver\n"); |
909 | 974 | ||
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 414783b04849..4e2af2cb2d26 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c | |||
@@ -119,12 +119,14 @@ 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->mfd_data = davinci_vc; | 122 | cell->platform_data = davinci_vc; |
123 | cell->pdata_size = sizeof(*davinci_vc); | ||
123 | 124 | ||
124 | /* Voice codec CQ93VC client */ | 125 | /* Voice codec CQ93VC client */ |
125 | cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL]; | 126 | cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL]; |
126 | cell->name = "cq93vc-codec"; | 127 | cell->name = "cq93vc-codec"; |
127 | cell->mfd_data = davinci_vc; | 128 | cell->platform_data = davinci_vc; |
129 | cell->pdata_size = sizeof(*davinci_vc); | ||
128 | 130 | ||
129 | ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, | 131 | ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, |
130 | DAVINCI_VC_CELLS, NULL, 0); | 132 | DAVINCI_VC_CELLS, NULL, 0); |
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index fb9770b39a32..2808bd125d13 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c | |||
@@ -117,7 +117,8 @@ 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 | .mfd_data = &ds1wm_pdata, | 120 | .platform_data = &ds1wm_pdata, |
121 | .pdata_size = sizeof(ds1wm_pdata), | ||
121 | .num_resources = 2, | 122 | .num_resources = 2, |
122 | .resources = ds1wm_resources, | 123 | .resources = ds1wm_resources, |
123 | }; | 124 | }; |
@@ -172,6 +173,8 @@ static int __init pasic3_probe(struct platform_device *pdev) | |||
172 | } | 173 | } |
173 | 174 | ||
174 | if (pdata && pdata->led_pdata) { | 175 | if (pdata && pdata->led_pdata) { |
176 | led_cell.platform_data = pdata->led_pdata; | ||
177 | led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); | ||
175 | ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); | 178 | ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); |
176 | if (ret < 0) | 179 | if (ret < 0) |
177 | dev_warn(dev, "failed to register LED device\n"); | 180 | dev_warn(dev, "failed to register LED device\n"); |
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index fc4191137e90..5c2a06acb77f 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c | |||
@@ -86,7 +86,8 @@ 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->mfd_data = pdata; | 89 | cell->platform_data = pdata; |
90 | cell->pdata_size = sizeof(*pdata); | ||
90 | 91 | ||
91 | /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ | 92 | /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ |
92 | res->flags = IORESOURCE_MEM; | 93 | res->flags = IORESOURCE_MEM; |
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 58cc5fdde016..e1e59c92f758 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -627,7 +627,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, | |||
627 | goto out_dev; | 627 | goto out_dev; |
628 | } | 628 | } |
629 | 629 | ||
630 | if (pdata && pdata->regulator[0]) { | 630 | if (pdata) { |
631 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], | 631 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], |
632 | ARRAY_SIZE(regulator_devs), | 632 | ARRAY_SIZE(regulator_devs), |
633 | ®ulator_resources[0], 0); | 633 | ®ulator_resources[0], 0); |
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 668634e89e81..7e4d44bf92ab 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c | |||
@@ -683,13 +683,14 @@ 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) | 686 | const char *format, void *pdata, size_t pdata_size) |
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 | .mfd_data = pdata, | 692 | .platform_data = pdata, |
693 | .pdata_size = pdata_size, | ||
693 | }; | 694 | }; |
694 | 695 | ||
695 | /* there is no asnprintf in the kernel :-( */ | 696 | /* there is no asnprintf in the kernel :-( */ |
@@ -705,7 +706,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, | |||
705 | 706 | ||
706 | static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) | 707 | static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) |
707 | { | 708 | { |
708 | return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL); | 709 | return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0); |
709 | } | 710 | } |
710 | 711 | ||
711 | static int mc13xxx_probe(struct spi_device *spi) | 712 | static int mc13xxx_probe(struct spi_device *spi) |
@@ -764,7 +765,7 @@ err_revision: | |||
764 | 765 | ||
765 | if (pdata->flags & MC13XXX_USE_REGULATOR) { | 766 | if (pdata->flags & MC13XXX_USE_REGULATOR) { |
766 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", | 767 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", |
767 | &pdata->regulators); | 768 | &pdata->regulators, sizeof(pdata->regulators)); |
768 | } | 769 | } |
769 | 770 | ||
770 | if (pdata->flags & MC13XXX_USE_RTC) | 771 | if (pdata->flags & MC13XXX_USE_RTC) |
@@ -774,7 +775,8 @@ err_revision: | |||
774 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); | 775 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); |
775 | 776 | ||
776 | if (pdata->flags & MC13XXX_USE_LED) | 777 | if (pdata->flags & MC13XXX_USE_LED) |
777 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds); | 778 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", |
779 | pdata->leds, sizeof(*pdata->leds)); | ||
778 | 780 | ||
779 | return 0; | 781 | return 0; |
780 | } | 782 | } |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index f4c8c844b913..0902523af62d 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -88,6 +88,13 @@ static int mfd_add_device(struct device *parent, int id, | |||
88 | 88 | ||
89 | pdev->dev.parent = parent; | 89 | pdev->dev.parent = parent; |
90 | 90 | ||
91 | if (cell->pdata_size) { | ||
92 | ret = platform_device_add_data(pdev, | ||
93 | cell->platform_data, cell->pdata_size); | ||
94 | if (ret) | ||
95 | goto fail_res; | ||
96 | } | ||
97 | |||
91 | ret = mfd_platform_add_cell(pdev, cell); | 98 | ret = mfd_platform_add_cell(pdev, cell); |
92 | if (ret) | 99 | if (ret) |
93 | goto fail_res; | 100 | goto fail_res; |
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 3ab9ffa00aad..855219526ccb 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <plat/usb.h> | 28 | #include <plat/usb.h> |
29 | #include <linux/pm_runtime.h> | ||
29 | 30 | ||
30 | #define USBHS_DRIVER_NAME "usbhs-omap" | 31 | #define USBHS_DRIVER_NAME "usbhs-omap" |
31 | #define OMAP_EHCI_DEVICE "ehci-omap" | 32 | #define OMAP_EHCI_DEVICE "ehci-omap" |
@@ -146,9 +147,6 @@ | |||
146 | 147 | ||
147 | 148 | ||
148 | struct usbhs_hcd_omap { | 149 | struct usbhs_hcd_omap { |
149 | struct clk *usbhost_ick; | ||
150 | struct clk *usbhost_hs_fck; | ||
151 | struct clk *usbhost_fs_fck; | ||
152 | struct clk *xclk60mhsp1_ck; | 150 | struct clk *xclk60mhsp1_ck; |
153 | struct clk *xclk60mhsp2_ck; | 151 | struct clk *xclk60mhsp2_ck; |
154 | struct clk *utmi_p1_fck; | 152 | struct clk *utmi_p1_fck; |
@@ -158,8 +156,6 @@ struct usbhs_hcd_omap { | |||
158 | struct clk *usbhost_p2_fck; | 156 | struct clk *usbhost_p2_fck; |
159 | struct clk *usbtll_p2_fck; | 157 | struct clk *usbtll_p2_fck; |
160 | struct clk *init_60m_fclk; | 158 | struct clk *init_60m_fclk; |
161 | struct clk *usbtll_fck; | ||
162 | struct clk *usbtll_ick; | ||
163 | 159 | ||
164 | void __iomem *uhh_base; | 160 | void __iomem *uhh_base; |
165 | void __iomem *tll_base; | 161 | void __iomem *tll_base; |
@@ -281,6 +277,7 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) | |||
281 | 277 | ||
282 | if (!ehci) { | 278 | if (!ehci) { |
283 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); | 279 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); |
280 | ret = -ENOMEM; | ||
284 | goto err_end; | 281 | goto err_end; |
285 | } | 282 | } |
286 | 283 | ||
@@ -304,13 +301,14 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) | |||
304 | sizeof(*ohci_data), dev); | 301 | sizeof(*ohci_data), dev); |
305 | if (!ohci) { | 302 | if (!ohci) { |
306 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); | 303 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); |
304 | ret = -ENOMEM; | ||
307 | goto err_ehci; | 305 | goto err_ehci; |
308 | } | 306 | } |
309 | 307 | ||
310 | return 0; | 308 | return 0; |
311 | 309 | ||
312 | err_ehci: | 310 | err_ehci: |
313 | platform_device_put(ehci); | 311 | platform_device_unregister(ehci); |
314 | 312 | ||
315 | err_end: | 313 | err_end: |
316 | return ret; | 314 | return ret; |
@@ -351,46 +349,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) | |||
351 | omap->platdata.ehci_data = pdata->ehci_data; | 349 | omap->platdata.ehci_data = pdata->ehci_data; |
352 | omap->platdata.ohci_data = pdata->ohci_data; | 350 | omap->platdata.ohci_data = pdata->ohci_data; |
353 | 351 | ||
354 | omap->usbhost_ick = clk_get(dev, "usbhost_ick"); | 352 | pm_runtime_enable(&pdev->dev); |
355 | if (IS_ERR(omap->usbhost_ick)) { | ||
356 | ret = PTR_ERR(omap->usbhost_ick); | ||
357 | dev_err(dev, "usbhost_ick failed error:%d\n", ret); | ||
358 | goto err_end; | ||
359 | } | ||
360 | |||
361 | omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); | ||
362 | if (IS_ERR(omap->usbhost_hs_fck)) { | ||
363 | ret = PTR_ERR(omap->usbhost_hs_fck); | ||
364 | dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); | ||
365 | goto err_usbhost_ick; | ||
366 | } | ||
367 | |||
368 | omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); | ||
369 | if (IS_ERR(omap->usbhost_fs_fck)) { | ||
370 | ret = PTR_ERR(omap->usbhost_fs_fck); | ||
371 | dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); | ||
372 | goto err_usbhost_hs_fck; | ||
373 | } | ||
374 | |||
375 | omap->usbtll_fck = clk_get(dev, "usbtll_fck"); | ||
376 | if (IS_ERR(omap->usbtll_fck)) { | ||
377 | ret = PTR_ERR(omap->usbtll_fck); | ||
378 | dev_err(dev, "usbtll_fck failed error:%d\n", ret); | ||
379 | goto err_usbhost_fs_fck; | ||
380 | } | ||
381 | |||
382 | omap->usbtll_ick = clk_get(dev, "usbtll_ick"); | ||
383 | if (IS_ERR(omap->usbtll_ick)) { | ||
384 | ret = PTR_ERR(omap->usbtll_ick); | ||
385 | dev_err(dev, "usbtll_ick failed error:%d\n", ret); | ||
386 | goto err_usbtll_fck; | ||
387 | } | ||
388 | 353 | ||
389 | omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); | 354 | omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); |
390 | if (IS_ERR(omap->utmi_p1_fck)) { | 355 | if (IS_ERR(omap->utmi_p1_fck)) { |
391 | ret = PTR_ERR(omap->utmi_p1_fck); | 356 | ret = PTR_ERR(omap->utmi_p1_fck); |
392 | dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); | 357 | dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); |
393 | goto err_usbtll_ick; | 358 | goto err_end; |
394 | } | 359 | } |
395 | 360 | ||
396 | omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); | 361 | omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); |
@@ -520,22 +485,8 @@ err_xclk60mhsp1_ck: | |||
520 | err_utmi_p1_fck: | 485 | err_utmi_p1_fck: |
521 | clk_put(omap->utmi_p1_fck); | 486 | clk_put(omap->utmi_p1_fck); |
522 | 487 | ||
523 | err_usbtll_ick: | ||
524 | clk_put(omap->usbtll_ick); | ||
525 | |||
526 | err_usbtll_fck: | ||
527 | clk_put(omap->usbtll_fck); | ||
528 | |||
529 | err_usbhost_fs_fck: | ||
530 | clk_put(omap->usbhost_fs_fck); | ||
531 | |||
532 | err_usbhost_hs_fck: | ||
533 | clk_put(omap->usbhost_hs_fck); | ||
534 | |||
535 | err_usbhost_ick: | ||
536 | clk_put(omap->usbhost_ick); | ||
537 | |||
538 | err_end: | 488 | err_end: |
489 | pm_runtime_disable(&pdev->dev); | ||
539 | kfree(omap); | 490 | kfree(omap); |
540 | 491 | ||
541 | end_probe: | 492 | end_probe: |
@@ -569,11 +520,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) | |||
569 | clk_put(omap->utmi_p2_fck); | 520 | clk_put(omap->utmi_p2_fck); |
570 | clk_put(omap->xclk60mhsp1_ck); | 521 | clk_put(omap->xclk60mhsp1_ck); |
571 | clk_put(omap->utmi_p1_fck); | 522 | clk_put(omap->utmi_p1_fck); |
572 | clk_put(omap->usbtll_ick); | 523 | pm_runtime_disable(&pdev->dev); |
573 | clk_put(omap->usbtll_fck); | ||
574 | clk_put(omap->usbhost_fs_fck); | ||
575 | clk_put(omap->usbhost_hs_fck); | ||
576 | clk_put(omap->usbhost_ick); | ||
577 | kfree(omap); | 524 | kfree(omap); |
578 | 525 | ||
579 | return 0; | 526 | return 0; |
@@ -693,7 +640,6 @@ static int usbhs_enable(struct device *dev) | |||
693 | struct usbhs_omap_platform_data *pdata = &omap->platdata; | 640 | struct usbhs_omap_platform_data *pdata = &omap->platdata; |
694 | unsigned long flags = 0; | 641 | unsigned long flags = 0; |
695 | int ret = 0; | 642 | int ret = 0; |
696 | unsigned long timeout; | ||
697 | unsigned reg; | 643 | unsigned reg; |
698 | 644 | ||
699 | dev_dbg(dev, "starting TI HSUSB Controller\n"); | 645 | dev_dbg(dev, "starting TI HSUSB Controller\n"); |
@@ -706,11 +652,7 @@ static int usbhs_enable(struct device *dev) | |||
706 | if (omap->count > 0) | 652 | if (omap->count > 0) |
707 | goto end_count; | 653 | goto end_count; |
708 | 654 | ||
709 | clk_enable(omap->usbhost_ick); | 655 | pm_runtime_get_sync(dev); |
710 | clk_enable(omap->usbhost_hs_fck); | ||
711 | clk_enable(omap->usbhost_fs_fck); | ||
712 | clk_enable(omap->usbtll_fck); | ||
713 | clk_enable(omap->usbtll_ick); | ||
714 | 656 | ||
715 | if (pdata->ehci_data->phy_reset) { | 657 | if (pdata->ehci_data->phy_reset) { |
716 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { | 658 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { |
@@ -734,50 +676,6 @@ static int usbhs_enable(struct device *dev) | |||
734 | omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); | 676 | omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); |
735 | dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); | 677 | dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); |
736 | 678 | ||
737 | /* perform TLL soft reset, and wait until reset is complete */ | ||
738 | usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
739 | OMAP_USBTLL_SYSCONFIG_SOFTRESET); | ||
740 | |||
741 | /* Wait for TLL reset to complete */ | ||
742 | timeout = jiffies + msecs_to_jiffies(1000); | ||
743 | while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) | ||
744 | & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { | ||
745 | cpu_relax(); | ||
746 | |||
747 | if (time_after(jiffies, timeout)) { | ||
748 | dev_dbg(dev, "operation timed out\n"); | ||
749 | ret = -EINVAL; | ||
750 | goto err_tll; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | dev_dbg(dev, "TLL RESET DONE\n"); | ||
755 | |||
756 | /* (1<<3) = no idle mode only for initial debugging */ | ||
757 | usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
758 | OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | | ||
759 | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | | ||
760 | OMAP_USBTLL_SYSCONFIG_AUTOIDLE); | ||
761 | |||
762 | /* Put UHH in NoIdle/NoStandby mode */ | ||
763 | reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); | ||
764 | if (is_omap_usbhs_rev1(omap)) { | ||
765 | reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | ||
766 | | OMAP_UHH_SYSCONFIG_SIDLEMODE | ||
767 | | OMAP_UHH_SYSCONFIG_CACTIVITY | ||
768 | | OMAP_UHH_SYSCONFIG_MIDLEMODE); | ||
769 | reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | ||
770 | |||
771 | |||
772 | } else if (is_omap_usbhs_rev2(omap)) { | ||
773 | reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; | ||
774 | reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; | ||
775 | reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; | ||
776 | reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; | ||
777 | } | ||
778 | |||
779 | usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); | ||
780 | |||
781 | reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); | 679 | reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); |
782 | /* setup ULPI bypass and burst configurations */ | 680 | /* setup ULPI bypass and burst configurations */ |
783 | reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | 681 | reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN |
@@ -917,6 +815,8 @@ end_count: | |||
917 | return 0; | 815 | return 0; |
918 | 816 | ||
919 | err_tll: | 817 | err_tll: |
818 | pm_runtime_put_sync(dev); | ||
819 | spin_unlock_irqrestore(&omap->lock, flags); | ||
920 | if (pdata->ehci_data->phy_reset) { | 820 | if (pdata->ehci_data->phy_reset) { |
921 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | 821 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) |
922 | gpio_free(pdata->ehci_data->reset_gpio_port[0]); | 822 | gpio_free(pdata->ehci_data->reset_gpio_port[0]); |
@@ -924,13 +824,6 @@ err_tll: | |||
924 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | 824 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) |
925 | gpio_free(pdata->ehci_data->reset_gpio_port[1]); | 825 | gpio_free(pdata->ehci_data->reset_gpio_port[1]); |
926 | } | 826 | } |
927 | |||
928 | clk_disable(omap->usbtll_ick); | ||
929 | clk_disable(omap->usbtll_fck); | ||
930 | clk_disable(omap->usbhost_fs_fck); | ||
931 | clk_disable(omap->usbhost_hs_fck); | ||
932 | clk_disable(omap->usbhost_ick); | ||
933 | spin_unlock_irqrestore(&omap->lock, flags); | ||
934 | return ret; | 827 | return ret; |
935 | } | 828 | } |
936 | 829 | ||
@@ -994,6 +887,20 @@ static void usbhs_disable(struct device *dev) | |||
994 | dev_dbg(dev, "operation timed out\n"); | 887 | dev_dbg(dev, "operation timed out\n"); |
995 | } | 888 | } |
996 | 889 | ||
890 | if (is_omap_usbhs_rev2(omap)) { | ||
891 | if (is_ehci_tll_mode(pdata->port_mode[0])) | ||
892 | clk_enable(omap->usbtll_p1_fck); | ||
893 | if (is_ehci_tll_mode(pdata->port_mode[1])) | ||
894 | clk_enable(omap->usbtll_p2_fck); | ||
895 | clk_disable(omap->utmi_p2_fck); | ||
896 | clk_disable(omap->utmi_p1_fck); | ||
897 | } | ||
898 | |||
899 | pm_runtime_put_sync(dev); | ||
900 | |||
901 | /* The gpio_free migh sleep; so unlock the spinlock */ | ||
902 | spin_unlock_irqrestore(&omap->lock, flags); | ||
903 | |||
997 | if (pdata->ehci_data->phy_reset) { | 904 | if (pdata->ehci_data->phy_reset) { |
998 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | 905 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) |
999 | gpio_free(pdata->ehci_data->reset_gpio_port[0]); | 906 | gpio_free(pdata->ehci_data->reset_gpio_port[0]); |
@@ -1001,14 +908,7 @@ static void usbhs_disable(struct device *dev) | |||
1001 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | 908 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) |
1002 | gpio_free(pdata->ehci_data->reset_gpio_port[1]); | 909 | gpio_free(pdata->ehci_data->reset_gpio_port[1]); |
1003 | } | 910 | } |
1004 | 911 | return; | |
1005 | clk_disable(omap->utmi_p2_fck); | ||
1006 | clk_disable(omap->utmi_p1_fck); | ||
1007 | clk_disable(omap->usbtll_ick); | ||
1008 | clk_disable(omap->usbtll_fck); | ||
1009 | clk_disable(omap->usbhost_fs_fck); | ||
1010 | clk_disable(omap->usbhost_hs_fck); | ||
1011 | clk_disable(omap->usbhost_ick); | ||
1012 | 912 | ||
1013 | end_disble: | 913 | end_disble: |
1014 | spin_unlock_irqrestore(&omap->lock, flags); | 914 | spin_unlock_irqrestore(&omap->lock, flags); |
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c new file mode 100644 index 000000000000..e873b15753d8 --- /dev/null +++ b/drivers/mfd/pm8921-core.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #define pr_fmt(fmt) "%s: " fmt, __func__ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/msm_ssbi.h> | ||
21 | #include <linux/mfd/core.h> | ||
22 | #include <linux/mfd/pm8xxx/pm8921.h> | ||
23 | #include <linux/mfd/pm8xxx/core.h> | ||
24 | |||
25 | #define REG_HWREV 0x002 /* PMIC4 revision */ | ||
26 | #define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */ | ||
27 | |||
28 | struct pm8921 { | ||
29 | struct device *dev; | ||
30 | struct pm_irq_chip *irq_chip; | ||
31 | }; | ||
32 | |||
33 | static int pm8921_readb(const struct device *dev, u16 addr, u8 *val) | ||
34 | { | ||
35 | const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); | ||
36 | const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; | ||
37 | |||
38 | return msm_ssbi_read(pmic->dev->parent, addr, val, 1); | ||
39 | } | ||
40 | |||
41 | static int pm8921_writeb(const struct device *dev, u16 addr, u8 val) | ||
42 | { | ||
43 | const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); | ||
44 | const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; | ||
45 | |||
46 | return msm_ssbi_write(pmic->dev->parent, addr, &val, 1); | ||
47 | } | ||
48 | |||
49 | static int pm8921_read_buf(const struct device *dev, u16 addr, u8 *buf, | ||
50 | int cnt) | ||
51 | { | ||
52 | const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); | ||
53 | const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; | ||
54 | |||
55 | return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt); | ||
56 | } | ||
57 | |||
58 | static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf, | ||
59 | int cnt) | ||
60 | { | ||
61 | const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); | ||
62 | const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; | ||
63 | |||
64 | return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt); | ||
65 | } | ||
66 | |||
67 | static int pm8921_read_irq_stat(const struct device *dev, int irq) | ||
68 | { | ||
69 | const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev); | ||
70 | const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data; | ||
71 | |||
72 | return pm8xxx_get_irq_stat(pmic->irq_chip, irq); | ||
73 | } | ||
74 | |||
75 | static struct pm8xxx_drvdata pm8921_drvdata = { | ||
76 | .pmic_readb = pm8921_readb, | ||
77 | .pmic_writeb = pm8921_writeb, | ||
78 | .pmic_read_buf = pm8921_read_buf, | ||
79 | .pmic_write_buf = pm8921_write_buf, | ||
80 | .pmic_read_irq_stat = pm8921_read_irq_stat, | ||
81 | }; | ||
82 | |||
83 | static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data | ||
84 | *pdata, | ||
85 | struct pm8921 *pmic, | ||
86 | u32 rev) | ||
87 | { | ||
88 | int ret = 0, irq_base = 0; | ||
89 | struct pm_irq_chip *irq_chip; | ||
90 | |||
91 | if (pdata->irq_pdata) { | ||
92 | pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS; | ||
93 | pdata->irq_pdata->irq_cdata.rev = rev; | ||
94 | irq_base = pdata->irq_pdata->irq_base; | ||
95 | irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata); | ||
96 | |||
97 | if (IS_ERR(irq_chip)) { | ||
98 | pr_err("Failed to init interrupts ret=%ld\n", | ||
99 | PTR_ERR(irq_chip)); | ||
100 | return PTR_ERR(irq_chip); | ||
101 | } | ||
102 | pmic->irq_chip = irq_chip; | ||
103 | } | ||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static int __devinit pm8921_probe(struct platform_device *pdev) | ||
108 | { | ||
109 | const struct pm8921_platform_data *pdata = pdev->dev.platform_data; | ||
110 | struct pm8921 *pmic; | ||
111 | int rc; | ||
112 | u8 val; | ||
113 | u32 rev; | ||
114 | |||
115 | if (!pdata) { | ||
116 | pr_err("missing platform data\n"); | ||
117 | return -EINVAL; | ||
118 | } | ||
119 | |||
120 | pmic = kzalloc(sizeof(struct pm8921), GFP_KERNEL); | ||
121 | if (!pmic) { | ||
122 | pr_err("Cannot alloc pm8921 struct\n"); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | |||
126 | /* Read PMIC chip revision */ | ||
127 | rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val)); | ||
128 | if (rc) { | ||
129 | pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc); | ||
130 | goto err_read_rev; | ||
131 | } | ||
132 | pr_info("PMIC revision 1: %02X\n", val); | ||
133 | rev = val; | ||
134 | |||
135 | /* Read PMIC chip revision 2 */ | ||
136 | rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val)); | ||
137 | if (rc) { | ||
138 | pr_err("Failed to read hw rev 2 reg %d:rc=%d\n", | ||
139 | REG_HWREV_2, rc); | ||
140 | goto err_read_rev; | ||
141 | } | ||
142 | pr_info("PMIC revision 2: %02X\n", val); | ||
143 | rev |= val << BITS_PER_BYTE; | ||
144 | |||
145 | pmic->dev = &pdev->dev; | ||
146 | pm8921_drvdata.pm_chip_data = pmic; | ||
147 | platform_set_drvdata(pdev, &pm8921_drvdata); | ||
148 | |||
149 | rc = pm8921_add_subdevices(pdata, pmic, rev); | ||
150 | if (rc) { | ||
151 | pr_err("Cannot add subdevices rc=%d\n", rc); | ||
152 | goto err; | ||
153 | } | ||
154 | |||
155 | /* gpio might not work if no irq device is found */ | ||
156 | WARN_ON(pmic->irq_chip == NULL); | ||
157 | |||
158 | return 0; | ||
159 | |||
160 | err: | ||
161 | mfd_remove_devices(pmic->dev); | ||
162 | platform_set_drvdata(pdev, NULL); | ||
163 | err_read_rev: | ||
164 | kfree(pmic); | ||
165 | return rc; | ||
166 | } | ||
167 | |||
168 | static int __devexit pm8921_remove(struct platform_device *pdev) | ||
169 | { | ||
170 | struct pm8xxx_drvdata *drvdata; | ||
171 | struct pm8921 *pmic = NULL; | ||
172 | |||
173 | drvdata = platform_get_drvdata(pdev); | ||
174 | if (drvdata) | ||
175 | pmic = drvdata->pm_chip_data; | ||
176 | if (pmic) | ||
177 | mfd_remove_devices(pmic->dev); | ||
178 | if (pmic->irq_chip) { | ||
179 | pm8xxx_irq_exit(pmic->irq_chip); | ||
180 | pmic->irq_chip = NULL; | ||
181 | } | ||
182 | platform_set_drvdata(pdev, NULL); | ||
183 | kfree(pmic); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static struct platform_driver pm8921_driver = { | ||
189 | .probe = pm8921_probe, | ||
190 | .remove = __devexit_p(pm8921_remove), | ||
191 | .driver = { | ||
192 | .name = "pm8921-core", | ||
193 | .owner = THIS_MODULE, | ||
194 | }, | ||
195 | }; | ||
196 | |||
197 | static int __init pm8921_init(void) | ||
198 | { | ||
199 | return platform_driver_register(&pm8921_driver); | ||
200 | } | ||
201 | subsys_initcall(pm8921_init); | ||
202 | |||
203 | static void __exit pm8921_exit(void) | ||
204 | { | ||
205 | platform_driver_unregister(&pm8921_driver); | ||
206 | } | ||
207 | module_exit(pm8921_exit); | ||
208 | |||
209 | MODULE_LICENSE("GPL v2"); | ||
210 | MODULE_DESCRIPTION("PMIC 8921 core driver"); | ||
211 | MODULE_VERSION("1.0"); | ||
212 | MODULE_ALIAS("platform:pm8921-core"); | ||
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c new file mode 100644 index 000000000000..d452dd013081 --- /dev/null +++ b/drivers/mfd/pm8xxx-irq.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #define pr_fmt(fmt) "%s: " fmt, __func__ | ||
15 | |||
16 | #include <linux/err.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/mfd/pm8xxx/core.h> | ||
21 | #include <linux/mfd/pm8xxx/irq.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/slab.h> | ||
24 | |||
25 | /* PMIC8xxx IRQ */ | ||
26 | |||
27 | #define SSBI_REG_ADDR_IRQ_BASE 0x1BB | ||
28 | |||
29 | #define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0) | ||
30 | #define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1) | ||
31 | #define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2) | ||
32 | #define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3) | ||
33 | #define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4) | ||
34 | #define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5) | ||
35 | #define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6) | ||
36 | #define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7) | ||
37 | #define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8) | ||
38 | |||
39 | #define PM_IRQF_LVL_SEL 0x01 /* level select */ | ||
40 | #define PM_IRQF_MASK_FE 0x02 /* mask falling edge */ | ||
41 | #define PM_IRQF_MASK_RE 0x04 /* mask rising edge */ | ||
42 | #define PM_IRQF_CLR 0x08 /* clear interrupt */ | ||
43 | #define PM_IRQF_BITS_MASK 0x70 | ||
44 | #define PM_IRQF_BITS_SHIFT 4 | ||
45 | #define PM_IRQF_WRITE 0x80 | ||
46 | |||
47 | #define PM_IRQF_MASK_ALL (PM_IRQF_MASK_FE | \ | ||
48 | PM_IRQF_MASK_RE) | ||
49 | |||
50 | struct pm_irq_chip { | ||
51 | struct device *dev; | ||
52 | spinlock_t pm_irq_lock; | ||
53 | unsigned int devirq; | ||
54 | unsigned int irq_base; | ||
55 | unsigned int num_irqs; | ||
56 | unsigned int num_blocks; | ||
57 | unsigned int num_masters; | ||
58 | u8 config[0]; | ||
59 | }; | ||
60 | |||
61 | static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp) | ||
62 | { | ||
63 | return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp); | ||
64 | } | ||
65 | |||
66 | static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp) | ||
67 | { | ||
68 | return pm8xxx_readb(chip->dev, | ||
69 | SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp); | ||
70 | } | ||
71 | |||
72 | static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip) | ||
73 | { | ||
74 | int rc; | ||
75 | |||
76 | spin_lock(&chip->pm_irq_lock); | ||
77 | rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); | ||
78 | if (rc) { | ||
79 | pr_err("Failed Selecting Block %d rc=%d\n", bp, rc); | ||
80 | goto bail; | ||
81 | } | ||
82 | |||
83 | rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip); | ||
84 | if (rc) | ||
85 | pr_err("Failed Reading Status rc=%d\n", rc); | ||
86 | bail: | ||
87 | spin_unlock(&chip->pm_irq_lock); | ||
88 | return rc; | ||
89 | } | ||
90 | |||
91 | static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp) | ||
92 | { | ||
93 | int rc; | ||
94 | |||
95 | spin_lock(&chip->pm_irq_lock); | ||
96 | rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); | ||
97 | if (rc) { | ||
98 | pr_err("Failed Selecting Block %d rc=%d\n", bp, rc); | ||
99 | goto bail; | ||
100 | } | ||
101 | |||
102 | cp |= PM_IRQF_WRITE; | ||
103 | rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp); | ||
104 | if (rc) | ||
105 | pr_err("Failed Configuring IRQ rc=%d\n", rc); | ||
106 | bail: | ||
107 | spin_unlock(&chip->pm_irq_lock); | ||
108 | return rc; | ||
109 | } | ||
110 | |||
111 | static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block) | ||
112 | { | ||
113 | int pmirq, irq, i, ret = 0; | ||
114 | u8 bits; | ||
115 | |||
116 | ret = pm8xxx_read_block_irq(chip, block, &bits); | ||
117 | if (ret) { | ||
118 | pr_err("Failed reading %d block ret=%d", block, ret); | ||
119 | return ret; | ||
120 | } | ||
121 | if (!bits) { | ||
122 | pr_err("block bit set in master but no irqs: %d", block); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | /* Check IRQ bits */ | ||
127 | for (i = 0; i < 8; i++) { | ||
128 | if (bits & (1 << i)) { | ||
129 | pmirq = block * 8 + i; | ||
130 | irq = pmirq + chip->irq_base; | ||
131 | generic_handle_irq(irq); | ||
132 | } | ||
133 | } | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master) | ||
138 | { | ||
139 | u8 blockbits; | ||
140 | int block_number, i, ret = 0; | ||
141 | |||
142 | ret = pm8xxx_read_master_irq(chip, master, &blockbits); | ||
143 | if (ret) { | ||
144 | pr_err("Failed to read master %d ret=%d\n", master, ret); | ||
145 | return ret; | ||
146 | } | ||
147 | if (!blockbits) { | ||
148 | pr_err("master bit set in root but no blocks: %d", master); | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | for (i = 0; i < 8; i++) | ||
153 | if (blockbits & (1 << i)) { | ||
154 | block_number = master * 8 + i; /* block # */ | ||
155 | ret |= pm8xxx_irq_block_handler(chip, block_number); | ||
156 | } | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
161 | { | ||
162 | struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); | ||
163 | struct irq_chip *irq_chip = irq_desc_get_chip(desc); | ||
164 | u8 root; | ||
165 | int i, ret, masters = 0; | ||
166 | |||
167 | ret = pm8xxx_read_root_irq(chip, &root); | ||
168 | if (ret) { | ||
169 | pr_err("Can't read root status ret=%d\n", ret); | ||
170 | return; | ||
171 | } | ||
172 | |||
173 | /* on pm8xxx series masters start from bit 1 of the root */ | ||
174 | masters = root >> 1; | ||
175 | |||
176 | /* Read allowed masters for blocks. */ | ||
177 | for (i = 0; i < chip->num_masters; i++) | ||
178 | if (masters & (1 << i)) | ||
179 | pm8xxx_irq_master_handler(chip, i); | ||
180 | |||
181 | irq_chip->irq_ack(&desc->irq_data); | ||
182 | } | ||
183 | |||
184 | static void pm8xxx_irq_mask_ack(struct irq_data *d) | ||
185 | { | ||
186 | struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); | ||
187 | unsigned int pmirq = d->irq - chip->irq_base; | ||
188 | int master, irq_bit; | ||
189 | u8 block, config; | ||
190 | |||
191 | block = pmirq / 8; | ||
192 | master = block / 8; | ||
193 | irq_bit = pmirq % 8; | ||
194 | |||
195 | config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR; | ||
196 | pm8xxx_config_irq(chip, block, config); | ||
197 | } | ||
198 | |||
199 | static void pm8xxx_irq_unmask(struct irq_data *d) | ||
200 | { | ||
201 | struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); | ||
202 | unsigned int pmirq = d->irq - chip->irq_base; | ||
203 | int master, irq_bit; | ||
204 | u8 block, config; | ||
205 | |||
206 | block = pmirq / 8; | ||
207 | master = block / 8; | ||
208 | irq_bit = pmirq % 8; | ||
209 | |||
210 | config = chip->config[pmirq]; | ||
211 | pm8xxx_config_irq(chip, block, config); | ||
212 | } | ||
213 | |||
214 | static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) | ||
215 | { | ||
216 | struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); | ||
217 | unsigned int pmirq = d->irq - chip->irq_base; | ||
218 | int master, irq_bit; | ||
219 | u8 block, config; | ||
220 | |||
221 | block = pmirq / 8; | ||
222 | master = block / 8; | ||
223 | irq_bit = pmirq % 8; | ||
224 | |||
225 | chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT) | ||
226 | | PM_IRQF_MASK_ALL; | ||
227 | if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { | ||
228 | if (flow_type & IRQF_TRIGGER_RISING) | ||
229 | chip->config[pmirq] &= ~PM_IRQF_MASK_RE; | ||
230 | if (flow_type & IRQF_TRIGGER_FALLING) | ||
231 | chip->config[pmirq] &= ~PM_IRQF_MASK_FE; | ||
232 | } else { | ||
233 | chip->config[pmirq] |= PM_IRQF_LVL_SEL; | ||
234 | |||
235 | if (flow_type & IRQF_TRIGGER_HIGH) | ||
236 | chip->config[pmirq] &= ~PM_IRQF_MASK_RE; | ||
237 | else | ||
238 | chip->config[pmirq] &= ~PM_IRQF_MASK_FE; | ||
239 | } | ||
240 | |||
241 | config = chip->config[pmirq] | PM_IRQF_CLR; | ||
242 | return pm8xxx_config_irq(chip, block, config); | ||
243 | } | ||
244 | |||
245 | static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on) | ||
246 | { | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static struct irq_chip pm8xxx_irq_chip = { | ||
251 | .name = "pm8xxx", | ||
252 | .irq_mask_ack = pm8xxx_irq_mask_ack, | ||
253 | .irq_unmask = pm8xxx_irq_unmask, | ||
254 | .irq_set_type = pm8xxx_irq_set_type, | ||
255 | .irq_set_wake = pm8xxx_irq_set_wake, | ||
256 | .flags = IRQCHIP_MASK_ON_SUSPEND, | ||
257 | }; | ||
258 | |||
259 | /** | ||
260 | * pm8xxx_get_irq_stat - get the status of the irq line | ||
261 | * @chip: pointer to identify a pmic irq controller | ||
262 | * @irq: the irq number | ||
263 | * | ||
264 | * The pm8xxx gpio and mpp rely on the interrupt block to read | ||
265 | * the values on their pins. This function is to facilitate reading | ||
266 | * the status of a gpio or an mpp line. The caller has to convert the | ||
267 | * gpio number to irq number. | ||
268 | * | ||
269 | * RETURNS: | ||
270 | * an int indicating the value read on that line | ||
271 | */ | ||
272 | int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq) | ||
273 | { | ||
274 | int pmirq, rc; | ||
275 | u8 block, bits, bit; | ||
276 | unsigned long flags; | ||
277 | |||
278 | if (chip == NULL || irq < chip->irq_base || | ||
279 | irq >= chip->irq_base + chip->num_irqs) | ||
280 | return -EINVAL; | ||
281 | |||
282 | pmirq = irq - chip->irq_base; | ||
283 | |||
284 | block = pmirq / 8; | ||
285 | bit = pmirq % 8; | ||
286 | |||
287 | spin_lock_irqsave(&chip->pm_irq_lock, flags); | ||
288 | |||
289 | rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block); | ||
290 | if (rc) { | ||
291 | pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n", | ||
292 | irq, pmirq, block, rc); | ||
293 | goto bail_out; | ||
294 | } | ||
295 | |||
296 | rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits); | ||
297 | if (rc) { | ||
298 | pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n", | ||
299 | irq, pmirq, block, rc); | ||
300 | goto bail_out; | ||
301 | } | ||
302 | |||
303 | rc = (bits & (1 << bit)) ? 1 : 0; | ||
304 | |||
305 | bail_out: | ||
306 | spin_unlock_irqrestore(&chip->pm_irq_lock, flags); | ||
307 | |||
308 | return rc; | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat); | ||
311 | |||
312 | struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev, | ||
313 | const struct pm8xxx_irq_platform_data *pdata) | ||
314 | { | ||
315 | struct pm_irq_chip *chip; | ||
316 | int devirq, rc; | ||
317 | unsigned int pmirq; | ||
318 | |||
319 | if (!pdata) { | ||
320 | pr_err("No platform data\n"); | ||
321 | return ERR_PTR(-EINVAL); | ||
322 | } | ||
323 | |||
324 | devirq = pdata->devirq; | ||
325 | if (devirq < 0) { | ||
326 | pr_err("missing devirq\n"); | ||
327 | rc = devirq; | ||
328 | return ERR_PTR(-EINVAL); | ||
329 | } | ||
330 | |||
331 | chip = kzalloc(sizeof(struct pm_irq_chip) | ||
332 | + sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL); | ||
333 | if (!chip) { | ||
334 | pr_err("Cannot alloc pm_irq_chip struct\n"); | ||
335 | return ERR_PTR(-EINVAL); | ||
336 | } | ||
337 | |||
338 | chip->dev = dev; | ||
339 | chip->devirq = devirq; | ||
340 | chip->irq_base = pdata->irq_base; | ||
341 | chip->num_irqs = pdata->irq_cdata.nirqs; | ||
342 | chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8); | ||
343 | chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8); | ||
344 | spin_lock_init(&chip->pm_irq_lock); | ||
345 | |||
346 | for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) { | ||
347 | irq_set_chip_and_handler(chip->irq_base + pmirq, | ||
348 | &pm8xxx_irq_chip, | ||
349 | handle_level_irq); | ||
350 | irq_set_chip_data(chip->irq_base + pmirq, chip); | ||
351 | #ifdef CONFIG_ARM | ||
352 | set_irq_flags(chip->irq_base + pmirq, IRQF_VALID); | ||
353 | #else | ||
354 | irq_set_noprobe(chip->irq_base + pmirq); | ||
355 | #endif | ||
356 | } | ||
357 | |||
358 | irq_set_irq_type(devirq, pdata->irq_trigger_flag); | ||
359 | irq_set_handler_data(devirq, chip); | ||
360 | irq_set_chained_handler(devirq, pm8xxx_irq_handler); | ||
361 | set_irq_wake(devirq, 1); | ||
362 | |||
363 | return chip; | ||
364 | } | ||
365 | |||
366 | int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip) | ||
367 | { | ||
368 | irq_set_chained_handler(chip->devirq, NULL); | ||
369 | kfree(chip); | ||
370 | return 0; | ||
371 | } | ||
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 10dbe6374a89..809bd4a61089 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c | |||
@@ -61,12 +61,14 @@ 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 | .mfd_data = &rdc321x_wdt_pdata, | 64 | .platform_data = &rdc321x_wdt_pdata, |
65 | .pdata_size = sizeof(rdc321x_wdt_pdata), | ||
65 | }, { | 66 | }, { |
66 | .name = "rdc321x-gpio", | 67 | .name = "rdc321x-gpio", |
67 | .resources = rdc321x_gpio_resources, | 68 | .resources = rdc321x_gpio_resources, |
68 | .num_resources = ARRAY_SIZE(rdc321x_gpio_resources), | 69 | .num_resources = ARRAY_SIZE(rdc321x_gpio_resources), |
69 | .mfd_data = &rdc321x_gpio_pdata, | 70 | .platform_data = &rdc321x_gpio_pdata, |
71 | .pdata_size = sizeof(rdc321x_gpio_pdata), | ||
70 | }, | 72 | }, |
71 | }; | 73 | }; |
72 | 74 | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 42830e692964..91ad21ef7721 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -170,7 +170,8 @@ 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 | .mfd_data = &t7166xb_mmc_data, | 173 | .platform_data = &t7166xb_mmc_data, |
174 | .pdata_size = sizeof(t7166xb_mmc_data), | ||
174 | .num_resources = ARRAY_SIZE(t7l66xb_mmc_resources), | 175 | .num_resources = ARRAY_SIZE(t7l66xb_mmc_resources), |
175 | .resources = t7l66xb_mmc_resources, | 176 | .resources = t7l66xb_mmc_resources, |
176 | }, | 177 | }, |
@@ -382,7 +383,8 @@ static int t7l66xb_probe(struct platform_device *dev) | |||
382 | 383 | ||
383 | t7l66xb_attach_irq(dev); | 384 | t7l66xb_attach_irq(dev); |
384 | 385 | ||
385 | t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data; | 386 | t7l66xb_cells[T7L66XB_CELL_NAND].platform_data = pdata->nand_data; |
387 | t7l66xb_cells[T7L66XB_CELL_NAND].pdata_size = sizeof(*pdata->nand_data); | ||
386 | 388 | ||
387 | ret = mfd_add_devices(&dev->dev, dev->id, | 389 | ret = mfd_add_devices(&dev->dev, dev->id, |
388 | t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), | 390 | t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), |
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index b006f7cee952..ad715bf49cac 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
@@ -131,7 +131,8 @@ 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 | .mfd_data = &tc6387xb_mmc_data, | 134 | .platform_data = &tc6387xb_mmc_data, |
135 | .pdata_size = sizeof(tc6387xb_mmc_data), | ||
135 | .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources), | 136 | .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources), |
136 | .resources = tc6387xb_mmc_resources, | 137 | .resources = tc6387xb_mmc_resources, |
137 | }, | 138 | }, |
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index fc53ce287601..9612264f0e6d 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -393,7 +393,8 @@ 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 | .mfd_data = &tc6393xb_mmc_data, | 396 | .platform_data = &tc6393xb_mmc_data, |
397 | .pdata_size = sizeof(tc6393xb_mmc_data), | ||
397 | .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), | 398 | .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), |
398 | .resources = tc6393xb_mmc_resources, | 399 | .resources = tc6393xb_mmc_resources, |
399 | }, | 400 | }, |
@@ -692,8 +693,11 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) | |||
692 | goto err_setup; | 693 | goto err_setup; |
693 | } | 694 | } |
694 | 695 | ||
695 | tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data; | 696 | tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = tcpd->nand_data; |
696 | tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data; | 697 | tc6393xb_cells[TC6393XB_CELL_NAND].pdata_size = |
698 | sizeof(*tcpd->nand_data); | ||
699 | tc6393xb_cells[TC6393XB_CELL_FB].platform_data = tcpd->fb_data; | ||
700 | tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data); | ||
697 | 701 | ||
698 | ret = mfd_add_devices(&dev->dev, dev->id, | 702 | ret = mfd_add_devices(&dev->dev, dev->id, |
699 | tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), | 703 | tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), |
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index 94c6c8afad12..69272e4e3459 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c | |||
@@ -384,7 +384,8 @@ 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 | .mfd_data = &timb_dma_platform_data, | 387 | .platform_data = &timb_dma_platform_data, |
388 | .pdata_size = sizeof(timb_dma_platform_data), | ||
388 | }, | 389 | }, |
389 | { | 390 | { |
390 | .name = "timb-uart", | 391 | .name = "timb-uart", |
@@ -395,37 +396,43 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { | |||
395 | .name = "xiic-i2c", | 396 | .name = "xiic-i2c", |
396 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | 397 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), |
397 | .resources = timberdale_xiic_resources, | 398 | .resources = timberdale_xiic_resources, |
398 | .mfd_data = &timberdale_xiic_platform_data, | 399 | .platform_data = &timberdale_xiic_platform_data, |
400 | .pdata_size = sizeof(timberdale_xiic_platform_data), | ||
399 | }, | 401 | }, |
400 | { | 402 | { |
401 | .name = "timb-gpio", | 403 | .name = "timb-gpio", |
402 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 404 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
403 | .resources = timberdale_gpio_resources, | 405 | .resources = timberdale_gpio_resources, |
404 | .mfd_data = &timberdale_gpio_platform_data, | 406 | .platform_data = &timberdale_gpio_platform_data, |
407 | .pdata_size = sizeof(timberdale_gpio_platform_data), | ||
405 | }, | 408 | }, |
406 | { | 409 | { |
407 | .name = "timb-video", | 410 | .name = "timb-video", |
408 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 411 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
409 | .resources = timberdale_video_resources, | 412 | .resources = timberdale_video_resources, |
410 | .mfd_data = &timberdale_video_platform_data, | 413 | .platform_data = &timberdale_video_platform_data, |
414 | .pdata_size = sizeof(timberdale_video_platform_data), | ||
411 | }, | 415 | }, |
412 | { | 416 | { |
413 | .name = "timb-radio", | 417 | .name = "timb-radio", |
414 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 418 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
415 | .resources = timberdale_radio_resources, | 419 | .resources = timberdale_radio_resources, |
416 | .mfd_data = &timberdale_radio_platform_data, | 420 | .platform_data = &timberdale_radio_platform_data, |
421 | .pdata_size = sizeof(timberdale_radio_platform_data), | ||
417 | }, | 422 | }, |
418 | { | 423 | { |
419 | .name = "xilinx_spi", | 424 | .name = "xilinx_spi", |
420 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 425 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
421 | .resources = timberdale_spi_resources, | 426 | .resources = timberdale_spi_resources, |
422 | .mfd_data = &timberdale_xspi_platform_data, | 427 | .platform_data = &timberdale_xspi_platform_data, |
428 | .pdata_size = sizeof(timberdale_xspi_platform_data), | ||
423 | }, | 429 | }, |
424 | { | 430 | { |
425 | .name = "ks8842", | 431 | .name = "ks8842", |
426 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 432 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
427 | .resources = timberdale_eth_resources, | 433 | .resources = timberdale_eth_resources, |
428 | .mfd_data = &timberdale_ks8842_platform_data, | 434 | .platform_data = &timberdale_ks8842_platform_data, |
435 | .pdata_size = sizeof(timberdale_ks8842_platform_data), | ||
429 | }, | 436 | }, |
430 | }; | 437 | }; |
431 | 438 | ||
@@ -434,7 +441,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
434 | .name = "timb-dma", | 441 | .name = "timb-dma", |
435 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 442 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
436 | .resources = timberdale_dma_resources, | 443 | .resources = timberdale_dma_resources, |
437 | .mfd_data = &timb_dma_platform_data, | 444 | .platform_data = &timb_dma_platform_data, |
445 | .pdata_size = sizeof(timb_dma_platform_data), | ||
438 | }, | 446 | }, |
439 | { | 447 | { |
440 | .name = "timb-uart", | 448 | .name = "timb-uart", |
@@ -450,13 +458,15 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
450 | .name = "xiic-i2c", | 458 | .name = "xiic-i2c", |
451 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | 459 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), |
452 | .resources = timberdale_xiic_resources, | 460 | .resources = timberdale_xiic_resources, |
453 | .mfd_data = &timberdale_xiic_platform_data, | 461 | .platform_data = &timberdale_xiic_platform_data, |
462 | .pdata_size = sizeof(timberdale_xiic_platform_data), | ||
454 | }, | 463 | }, |
455 | { | 464 | { |
456 | .name = "timb-gpio", | 465 | .name = "timb-gpio", |
457 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 466 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
458 | .resources = timberdale_gpio_resources, | 467 | .resources = timberdale_gpio_resources, |
459 | .mfd_data = &timberdale_gpio_platform_data, | 468 | .platform_data = &timberdale_gpio_platform_data, |
469 | .pdata_size = sizeof(timberdale_gpio_platform_data), | ||
460 | }, | 470 | }, |
461 | { | 471 | { |
462 | .name = "timb-mlogicore", | 472 | .name = "timb-mlogicore", |
@@ -467,25 +477,29 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
467 | .name = "timb-video", | 477 | .name = "timb-video", |
468 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 478 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
469 | .resources = timberdale_video_resources, | 479 | .resources = timberdale_video_resources, |
470 | .mfd_data = &timberdale_video_platform_data, | 480 | .platform_data = &timberdale_video_platform_data, |
481 | .pdata_size = sizeof(timberdale_video_platform_data), | ||
471 | }, | 482 | }, |
472 | { | 483 | { |
473 | .name = "timb-radio", | 484 | .name = "timb-radio", |
474 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 485 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
475 | .resources = timberdale_radio_resources, | 486 | .resources = timberdale_radio_resources, |
476 | .mfd_data = &timberdale_radio_platform_data, | 487 | .platform_data = &timberdale_radio_platform_data, |
488 | .pdata_size = sizeof(timberdale_radio_platform_data), | ||
477 | }, | 489 | }, |
478 | { | 490 | { |
479 | .name = "xilinx_spi", | 491 | .name = "xilinx_spi", |
480 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 492 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
481 | .resources = timberdale_spi_resources, | 493 | .resources = timberdale_spi_resources, |
482 | .mfd_data = &timberdale_xspi_platform_data, | 494 | .platform_data = &timberdale_xspi_platform_data, |
495 | .pdata_size = sizeof(timberdale_xspi_platform_data), | ||
483 | }, | 496 | }, |
484 | { | 497 | { |
485 | .name = "ks8842", | 498 | .name = "ks8842", |
486 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 499 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
487 | .resources = timberdale_eth_resources, | 500 | .resources = timberdale_eth_resources, |
488 | .mfd_data = &timberdale_ks8842_platform_data, | 501 | .platform_data = &timberdale_ks8842_platform_data, |
502 | .pdata_size = sizeof(timberdale_ks8842_platform_data), | ||
489 | }, | 503 | }, |
490 | }; | 504 | }; |
491 | 505 | ||
@@ -494,7 +508,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | |||
494 | .name = "timb-dma", | 508 | .name = "timb-dma", |
495 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 509 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
496 | .resources = timberdale_dma_resources, | 510 | .resources = timberdale_dma_resources, |
497 | .mfd_data = &timb_dma_platform_data, | 511 | .platform_data = &timb_dma_platform_data, |
512 | .pdata_size = sizeof(timb_dma_platform_data), | ||
498 | }, | 513 | }, |
499 | { | 514 | { |
500 | .name = "timb-uart", | 515 | .name = "timb-uart", |
@@ -505,31 +520,36 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | |||
505 | .name = "xiic-i2c", | 520 | .name = "xiic-i2c", |
506 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | 521 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), |
507 | .resources = timberdale_xiic_resources, | 522 | .resources = timberdale_xiic_resources, |
508 | .mfd_data = &timberdale_xiic_platform_data, | 523 | .platform_data = &timberdale_xiic_platform_data, |
524 | .pdata_size = sizeof(timberdale_xiic_platform_data), | ||
509 | }, | 525 | }, |
510 | { | 526 | { |
511 | .name = "timb-gpio", | 527 | .name = "timb-gpio", |
512 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 528 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
513 | .resources = timberdale_gpio_resources, | 529 | .resources = timberdale_gpio_resources, |
514 | .mfd_data = &timberdale_gpio_platform_data, | 530 | .platform_data = &timberdale_gpio_platform_data, |
531 | .pdata_size = sizeof(timberdale_gpio_platform_data), | ||
515 | }, | 532 | }, |
516 | { | 533 | { |
517 | .name = "timb-video", | 534 | .name = "timb-video", |
518 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 535 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
519 | .resources = timberdale_video_resources, | 536 | .resources = timberdale_video_resources, |
520 | .mfd_data = &timberdale_video_platform_data, | 537 | .platform_data = &timberdale_video_platform_data, |
538 | .pdata_size = sizeof(timberdale_video_platform_data), | ||
521 | }, | 539 | }, |
522 | { | 540 | { |
523 | .name = "timb-radio", | 541 | .name = "timb-radio", |
524 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 542 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
525 | .resources = timberdale_radio_resources, | 543 | .resources = timberdale_radio_resources, |
526 | .mfd_data = &timberdale_radio_platform_data, | 544 | .platform_data = &timberdale_radio_platform_data, |
545 | .pdata_size = sizeof(timberdale_radio_platform_data), | ||
527 | }, | 546 | }, |
528 | { | 547 | { |
529 | .name = "xilinx_spi", | 548 | .name = "xilinx_spi", |
530 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 549 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
531 | .resources = timberdale_spi_resources, | 550 | .resources = timberdale_spi_resources, |
532 | .mfd_data = &timberdale_xspi_platform_data, | 551 | .platform_data = &timberdale_xspi_platform_data, |
552 | .pdata_size = sizeof(timberdale_xspi_platform_data), | ||
533 | }, | 553 | }, |
534 | }; | 554 | }; |
535 | 555 | ||
@@ -538,7 +558,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | |||
538 | .name = "timb-dma", | 558 | .name = "timb-dma", |
539 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 559 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
540 | .resources = timberdale_dma_resources, | 560 | .resources = timberdale_dma_resources, |
541 | .mfd_data = &timb_dma_platform_data, | 561 | .platform_data = &timb_dma_platform_data, |
562 | .pdata_size = sizeof(timb_dma_platform_data), | ||
542 | }, | 563 | }, |
543 | { | 564 | { |
544 | .name = "timb-uart", | 565 | .name = "timb-uart", |
@@ -549,37 +570,43 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | |||
549 | .name = "ocores-i2c", | 570 | .name = "ocores-i2c", |
550 | .num_resources = ARRAY_SIZE(timberdale_ocores_resources), | 571 | .num_resources = ARRAY_SIZE(timberdale_ocores_resources), |
551 | .resources = timberdale_ocores_resources, | 572 | .resources = timberdale_ocores_resources, |
552 | .mfd_data = &timberdale_ocores_platform_data, | 573 | .platform_data = &timberdale_ocores_platform_data, |
574 | .pdata_size = sizeof(timberdale_ocores_platform_data), | ||
553 | }, | 575 | }, |
554 | { | 576 | { |
555 | .name = "timb-gpio", | 577 | .name = "timb-gpio", |
556 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 578 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
557 | .resources = timberdale_gpio_resources, | 579 | .resources = timberdale_gpio_resources, |
558 | .mfd_data = &timberdale_gpio_platform_data, | 580 | .platform_data = &timberdale_gpio_platform_data, |
581 | .pdata_size = sizeof(timberdale_gpio_platform_data), | ||
559 | }, | 582 | }, |
560 | { | 583 | { |
561 | .name = "timb-video", | 584 | .name = "timb-video", |
562 | .num_resources = ARRAY_SIZE(timberdale_video_resources), | 585 | .num_resources = ARRAY_SIZE(timberdale_video_resources), |
563 | .resources = timberdale_video_resources, | 586 | .resources = timberdale_video_resources, |
564 | .mfd_data = &timberdale_video_platform_data, | 587 | .platform_data = &timberdale_video_platform_data, |
588 | .pdata_size = sizeof(timberdale_video_platform_data), | ||
565 | }, | 589 | }, |
566 | { | 590 | { |
567 | .name = "timb-radio", | 591 | .name = "timb-radio", |
568 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | 592 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), |
569 | .resources = timberdale_radio_resources, | 593 | .resources = timberdale_radio_resources, |
570 | .mfd_data = &timberdale_radio_platform_data, | 594 | .platform_data = &timberdale_radio_platform_data, |
595 | .pdata_size = sizeof(timberdale_radio_platform_data), | ||
571 | }, | 596 | }, |
572 | { | 597 | { |
573 | .name = "xilinx_spi", | 598 | .name = "xilinx_spi", |
574 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | 599 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), |
575 | .resources = timberdale_spi_resources, | 600 | .resources = timberdale_spi_resources, |
576 | .mfd_data = &timberdale_xspi_platform_data, | 601 | .platform_data = &timberdale_xspi_platform_data, |
602 | .pdata_size = sizeof(timberdale_xspi_platform_data), | ||
577 | }, | 603 | }, |
578 | { | 604 | { |
579 | .name = "ks8842", | 605 | .name = "ks8842", |
580 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 606 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
581 | .resources = timberdale_eth_resources, | 607 | .resources = timberdale_eth_resources, |
582 | .mfd_data = &timberdale_ks8842_platform_data, | 608 | .platform_data = &timberdale_ks8842_platform_data, |
609 | .pdata_size = sizeof(timberdale_ks8842_platform_data), | ||
583 | }, | 610 | }, |
584 | }; | 611 | }; |
585 | 612 | ||
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index 46d8205646b6..a293b978e27c 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c | |||
@@ -183,7 +183,8 @@ static int __devinit tps6105x_probe(struct i2c_client *client, | |||
183 | /* Set up and register the platform devices. */ | 183 | /* Set up and register the platform devices. */ |
184 | for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) { | 184 | for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) { |
185 | /* One state holder for all drivers, this is simple */ | 185 | /* One state holder for all drivers, this is simple */ |
186 | tps6105x_cells[i].mfd_data = tps6105x; | 186 | tps6105x_cells[i].platform_data = tps6105x; |
187 | tps6105x_cells[i].pdata_size = sizeof(*tps6105x); | ||
187 | } | 188 | } |
188 | 189 | ||
189 | ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, | 190 | ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index b600808690c1..bba26d96c240 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c | |||
@@ -270,8 +270,8 @@ static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, | |||
270 | { | 270 | { |
271 | struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); | 271 | struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); |
272 | 272 | ||
273 | __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, | 273 | tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2, |
274 | value << offset); | 274 | value << offset, 1 << offset); |
275 | } | 275 | } |
276 | 276 | ||
277 | static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, | 277 | static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, |
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 960b5bed7f52..b8f2a4e7f6e7 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -198,6 +198,7 @@ | |||
198 | #define TWL6030_BASEADD_GASGAUGE 0x00C0 | 198 | #define TWL6030_BASEADD_GASGAUGE 0x00C0 |
199 | #define TWL6030_BASEADD_PIH 0x00D0 | 199 | #define TWL6030_BASEADD_PIH 0x00D0 |
200 | #define TWL6030_BASEADD_CHARGER 0x00E0 | 200 | #define TWL6030_BASEADD_CHARGER 0x00E0 |
201 | #define TWL6025_BASEADD_CHARGER 0x00DA | ||
201 | 202 | ||
202 | /* subchip/slave 2 0x4A - DFT */ | 203 | /* subchip/slave 2 0x4A - DFT */ |
203 | #define TWL6030_BASEADD_DIEID 0x00C0 | 204 | #define TWL6030_BASEADD_DIEID 0x00C0 |
@@ -229,6 +230,9 @@ | |||
229 | /* is driver active, bound to a chip? */ | 230 | /* is driver active, bound to a chip? */ |
230 | static bool inuse; | 231 | static bool inuse; |
231 | 232 | ||
233 | /* TWL IDCODE Register value */ | ||
234 | static u32 twl_idcode; | ||
235 | |||
232 | static unsigned int twl_id; | 236 | static unsigned int twl_id; |
233 | unsigned int twl_rev(void) | 237 | unsigned int twl_rev(void) |
234 | { | 238 | { |
@@ -328,6 +332,7 @@ static struct twl_mapping twl6030_map[] = { | |||
328 | 332 | ||
329 | { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, | 333 | { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, |
330 | { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, | 334 | { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, |
335 | { SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER }, | ||
331 | }; | 336 | }; |
332 | 337 | ||
333 | /*----------------------------------------------------------------------*/ | 338 | /*----------------------------------------------------------------------*/ |
@@ -487,6 +492,58 @@ EXPORT_SYMBOL(twl_i2c_read_u8); | |||
487 | 492 | ||
488 | /*----------------------------------------------------------------------*/ | 493 | /*----------------------------------------------------------------------*/ |
489 | 494 | ||
495 | /** | ||
496 | * twl_read_idcode_register - API to read the IDCODE register. | ||
497 | * | ||
498 | * Unlocks the IDCODE register and read the 32 bit value. | ||
499 | */ | ||
500 | static int twl_read_idcode_register(void) | ||
501 | { | ||
502 | int err; | ||
503 | |||
504 | err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK, | ||
505 | REG_UNLOCK_TEST_REG); | ||
506 | if (err) { | ||
507 | pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err); | ||
508 | goto fail; | ||
509 | } | ||
510 | |||
511 | err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode), | ||
512 | REG_IDCODE_7_0, 4); | ||
513 | if (err) { | ||
514 | pr_err("TWL4030: unable to read IDCODE -%d\n", err); | ||
515 | goto fail; | ||
516 | } | ||
517 | |||
518 | err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG); | ||
519 | if (err) | ||
520 | pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err); | ||
521 | fail: | ||
522 | return err; | ||
523 | } | ||
524 | |||
525 | /** | ||
526 | * twl_get_type - API to get TWL Si type. | ||
527 | * | ||
528 | * Api to get the TWL Si type from IDCODE value. | ||
529 | */ | ||
530 | int twl_get_type(void) | ||
531 | { | ||
532 | return TWL_SIL_TYPE(twl_idcode); | ||
533 | } | ||
534 | EXPORT_SYMBOL_GPL(twl_get_type); | ||
535 | |||
536 | /** | ||
537 | * twl_get_version - API to get TWL Si version. | ||
538 | * | ||
539 | * Api to get the TWL Si version from IDCODE value. | ||
540 | */ | ||
541 | int twl_get_version(void) | ||
542 | { | ||
543 | return TWL_SIL_REV(twl_idcode); | ||
544 | } | ||
545 | EXPORT_SYMBOL_GPL(twl_get_version); | ||
546 | |||
490 | static struct device * | 547 | static struct device * |
491 | add_numbered_child(unsigned chip, const char *name, int num, | 548 | add_numbered_child(unsigned chip, const char *name, int num, |
492 | void *pdata, unsigned pdata_len, | 549 | void *pdata, unsigned pdata_len, |
@@ -549,7 +606,7 @@ static inline struct device *add_child(unsigned chip, const char *name, | |||
549 | static struct device * | 606 | static struct device * |
550 | add_regulator_linked(int num, struct regulator_init_data *pdata, | 607 | add_regulator_linked(int num, struct regulator_init_data *pdata, |
551 | struct regulator_consumer_supply *consumers, | 608 | struct regulator_consumer_supply *consumers, |
552 | unsigned num_consumers) | 609 | unsigned num_consumers, unsigned long features) |
553 | { | 610 | { |
554 | unsigned sub_chip_id; | 611 | unsigned sub_chip_id; |
555 | /* regulator framework demands init_data ... */ | 612 | /* regulator framework demands init_data ... */ |
@@ -561,6 +618,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
561 | pdata->num_consumer_supplies = num_consumers; | 618 | pdata->num_consumer_supplies = num_consumers; |
562 | } | 619 | } |
563 | 620 | ||
621 | pdata->driver_data = (void *)features; | ||
622 | |||
564 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ | 623 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ |
565 | sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; | 624 | sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; |
566 | return add_numbered_child(sub_chip_id, "twl_reg", num, | 625 | return add_numbered_child(sub_chip_id, "twl_reg", num, |
@@ -568,9 +627,10 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
568 | } | 627 | } |
569 | 628 | ||
570 | static struct device * | 629 | static struct device * |
571 | add_regulator(int num, struct regulator_init_data *pdata) | 630 | add_regulator(int num, struct regulator_init_data *pdata, |
631 | unsigned long features) | ||
572 | { | 632 | { |
573 | return add_regulator_linked(num, pdata, NULL, 0); | 633 | return add_regulator_linked(num, pdata, NULL, 0, features); |
574 | } | 634 | } |
575 | 635 | ||
576 | /* | 636 | /* |
@@ -650,17 +710,20 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
650 | }; | 710 | }; |
651 | 711 | ||
652 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, | 712 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, |
653 | &usb_fixed, &usb1v5, 1); | 713 | &usb_fixed, &usb1v5, 1, |
714 | features); | ||
654 | if (IS_ERR(child)) | 715 | if (IS_ERR(child)) |
655 | return PTR_ERR(child); | 716 | return PTR_ERR(child); |
656 | 717 | ||
657 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, | 718 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, |
658 | &usb_fixed, &usb1v8, 1); | 719 | &usb_fixed, &usb1v8, 1, |
720 | features); | ||
659 | if (IS_ERR(child)) | 721 | if (IS_ERR(child)) |
660 | return PTR_ERR(child); | 722 | return PTR_ERR(child); |
661 | 723 | ||
662 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, | 724 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, |
663 | &usb_fixed, &usb3v1, 1); | 725 | &usb_fixed, &usb3v1, 1, |
726 | features); | ||
664 | if (IS_ERR(child)) | 727 | if (IS_ERR(child)) |
665 | return PTR_ERR(child); | 728 | return PTR_ERR(child); |
666 | 729 | ||
@@ -685,9 +748,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
685 | } | 748 | } |
686 | if (twl_has_usb() && pdata->usb && twl_class_is_6030()) { | 749 | if (twl_has_usb() && pdata->usb && twl_class_is_6030()) { |
687 | 750 | ||
688 | static struct regulator_consumer_supply usb3v3 = { | 751 | static struct regulator_consumer_supply usb3v3; |
689 | .supply = "vusb", | 752 | int regulator; |
690 | }; | ||
691 | 753 | ||
692 | if (twl_has_regulator()) { | 754 | if (twl_has_regulator()) { |
693 | /* this is a template that gets copied */ | 755 | /* this is a template that gets copied */ |
@@ -700,12 +762,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
700 | | REGULATOR_CHANGE_STATUS, | 762 | | REGULATOR_CHANGE_STATUS, |
701 | }; | 763 | }; |
702 | 764 | ||
703 | child = add_regulator_linked(TWL6030_REG_VUSB, | 765 | if (features & TWL6025_SUBCLASS) { |
704 | &usb_fixed, &usb3v3, 1); | 766 | usb3v3.supply = "ldousb"; |
767 | regulator = TWL6025_REG_LDOUSB; | ||
768 | } else { | ||
769 | usb3v3.supply = "vusb"; | ||
770 | regulator = TWL6030_REG_VUSB; | ||
771 | } | ||
772 | child = add_regulator_linked(regulator, &usb_fixed, | ||
773 | &usb3v3, 1, | ||
774 | features); | ||
705 | if (IS_ERR(child)) | 775 | if (IS_ERR(child)) |
706 | return PTR_ERR(child); | 776 | return PTR_ERR(child); |
707 | } | 777 | } |
708 | 778 | ||
779 | pdata->usb->features = features; | ||
780 | |||
709 | child = add_child(0, "twl6030_usb", | 781 | child = add_child(0, "twl6030_usb", |
710 | pdata->usb, sizeof(*pdata->usb), | 782 | pdata->usb, sizeof(*pdata->usb), |
711 | true, | 783 | true, |
@@ -718,7 +790,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
718 | /* we need to connect regulators to this transceiver */ | 790 | /* we need to connect regulators to this transceiver */ |
719 | if (twl_has_regulator() && child) | 791 | if (twl_has_regulator() && child) |
720 | usb3v3.dev = child; | 792 | usb3v3.dev = child; |
793 | } else if (twl_has_regulator() && twl_class_is_6030()) { | ||
794 | if (features & TWL6025_SUBCLASS) | ||
795 | child = add_regulator(TWL6025_REG_LDOUSB, | ||
796 | pdata->ldousb, features); | ||
797 | else | ||
798 | child = add_regulator(TWL6030_REG_VUSB, | ||
799 | pdata->vusb, features); | ||
721 | 800 | ||
801 | if (IS_ERR(child)) | ||
802 | return PTR_ERR(child); | ||
722 | } | 803 | } |
723 | 804 | ||
724 | if (twl_has_watchdog() && twl_class_is_4030()) { | 805 | if (twl_has_watchdog() && twl_class_is_4030()) { |
@@ -755,46 +836,55 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
755 | 836 | ||
756 | /* twl4030 regulators */ | 837 | /* twl4030 regulators */ |
757 | if (twl_has_regulator() && twl_class_is_4030()) { | 838 | if (twl_has_regulator() && twl_class_is_4030()) { |
758 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); | 839 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1, |
840 | features); | ||
759 | if (IS_ERR(child)) | 841 | if (IS_ERR(child)) |
760 | return PTR_ERR(child); | 842 | return PTR_ERR(child); |
761 | 843 | ||
762 | child = add_regulator(TWL4030_REG_VIO, pdata->vio); | 844 | child = add_regulator(TWL4030_REG_VIO, pdata->vio, |
845 | features); | ||
763 | if (IS_ERR(child)) | 846 | if (IS_ERR(child)) |
764 | return PTR_ERR(child); | 847 | return PTR_ERR(child); |
765 | 848 | ||
766 | child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1); | 849 | child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1, |
850 | features); | ||
767 | if (IS_ERR(child)) | 851 | if (IS_ERR(child)) |
768 | return PTR_ERR(child); | 852 | return PTR_ERR(child); |
769 | 853 | ||
770 | child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2); | 854 | child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2, |
855 | features); | ||
771 | if (IS_ERR(child)) | 856 | if (IS_ERR(child)) |
772 | return PTR_ERR(child); | 857 | return PTR_ERR(child); |
773 | 858 | ||
774 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); | 859 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1, |
860 | features); | ||
775 | if (IS_ERR(child)) | 861 | if (IS_ERR(child)) |
776 | return PTR_ERR(child); | 862 | return PTR_ERR(child); |
777 | 863 | ||
778 | child = add_regulator(TWL4030_REG_VDAC, pdata->vdac); | 864 | child = add_regulator(TWL4030_REG_VDAC, pdata->vdac, |
865 | features); | ||
779 | if (IS_ERR(child)) | 866 | if (IS_ERR(child)) |
780 | return PTR_ERR(child); | 867 | return PTR_ERR(child); |
781 | 868 | ||
782 | child = add_regulator((features & TWL4030_VAUX2) | 869 | child = add_regulator((features & TWL4030_VAUX2) |
783 | ? TWL4030_REG_VAUX2_4030 | 870 | ? TWL4030_REG_VAUX2_4030 |
784 | : TWL4030_REG_VAUX2, | 871 | : TWL4030_REG_VAUX2, |
785 | pdata->vaux2); | 872 | pdata->vaux2, features); |
786 | if (IS_ERR(child)) | 873 | if (IS_ERR(child)) |
787 | return PTR_ERR(child); | 874 | return PTR_ERR(child); |
788 | 875 | ||
789 | child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1); | 876 | child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1, |
877 | features); | ||
790 | if (IS_ERR(child)) | 878 | if (IS_ERR(child)) |
791 | return PTR_ERR(child); | 879 | return PTR_ERR(child); |
792 | 880 | ||
793 | child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2); | 881 | child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2, |
882 | features); | ||
794 | if (IS_ERR(child)) | 883 | if (IS_ERR(child)) |
795 | return PTR_ERR(child); | 884 | return PTR_ERR(child); |
796 | 885 | ||
797 | child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig); | 886 | child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig, |
887 | features); | ||
798 | if (IS_ERR(child)) | 888 | if (IS_ERR(child)) |
799 | return PTR_ERR(child); | 889 | return PTR_ERR(child); |
800 | } | 890 | } |
@@ -802,72 +892,152 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
802 | /* maybe add LDOs that are omitted on cost-reduced parts */ | 892 | /* maybe add LDOs that are omitted on cost-reduced parts */ |
803 | if (twl_has_regulator() && !(features & TPS_SUBSET) | 893 | if (twl_has_regulator() && !(features & TPS_SUBSET) |
804 | && twl_class_is_4030()) { | 894 | && twl_class_is_4030()) { |
805 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); | 895 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2, |
896 | features); | ||
806 | if (IS_ERR(child)) | 897 | if (IS_ERR(child)) |
807 | return PTR_ERR(child); | 898 | return PTR_ERR(child); |
808 | 899 | ||
809 | child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2); | 900 | child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2, |
901 | features); | ||
810 | if (IS_ERR(child)) | 902 | if (IS_ERR(child)) |
811 | return PTR_ERR(child); | 903 | return PTR_ERR(child); |
812 | 904 | ||
813 | child = add_regulator(TWL4030_REG_VSIM, pdata->vsim); | 905 | child = add_regulator(TWL4030_REG_VSIM, pdata->vsim, |
906 | features); | ||
814 | if (IS_ERR(child)) | 907 | if (IS_ERR(child)) |
815 | return PTR_ERR(child); | 908 | return PTR_ERR(child); |
816 | 909 | ||
817 | child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1); | 910 | child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1, |
911 | features); | ||
818 | if (IS_ERR(child)) | 912 | if (IS_ERR(child)) |
819 | return PTR_ERR(child); | 913 | return PTR_ERR(child); |
820 | 914 | ||
821 | child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3); | 915 | child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3, |
916 | features); | ||
822 | if (IS_ERR(child)) | 917 | if (IS_ERR(child)) |
823 | return PTR_ERR(child); | 918 | return PTR_ERR(child); |
824 | 919 | ||
825 | child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4); | 920 | child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4, |
921 | features); | ||
826 | if (IS_ERR(child)) | 922 | if (IS_ERR(child)) |
827 | return PTR_ERR(child); | 923 | return PTR_ERR(child); |
828 | } | 924 | } |
829 | 925 | ||
830 | /* twl6030 regulators */ | 926 | /* twl6030 regulators */ |
927 | if (twl_has_regulator() && twl_class_is_6030() && | ||
928 | !(features & TWL6025_SUBCLASS)) { | ||
929 | child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc, | ||
930 | features); | ||
931 | if (IS_ERR(child)) | ||
932 | return PTR_ERR(child); | ||
933 | |||
934 | child = add_regulator(TWL6030_REG_VPP, pdata->vpp, | ||
935 | features); | ||
936 | if (IS_ERR(child)) | ||
937 | return PTR_ERR(child); | ||
938 | |||
939 | child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim, | ||
940 | features); | ||
941 | if (IS_ERR(child)) | ||
942 | return PTR_ERR(child); | ||
943 | |||
944 | child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio, | ||
945 | features); | ||
946 | if (IS_ERR(child)) | ||
947 | return PTR_ERR(child); | ||
948 | |||
949 | child = add_regulator(TWL6030_REG_VDAC, pdata->vdac, | ||
950 | features); | ||
951 | if (IS_ERR(child)) | ||
952 | return PTR_ERR(child); | ||
953 | |||
954 | child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1, | ||
955 | features); | ||
956 | if (IS_ERR(child)) | ||
957 | return PTR_ERR(child); | ||
958 | |||
959 | child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2, | ||
960 | features); | ||
961 | if (IS_ERR(child)) | ||
962 | return PTR_ERR(child); | ||
963 | |||
964 | child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3, | ||
965 | features); | ||
966 | if (IS_ERR(child)) | ||
967 | return PTR_ERR(child); | ||
968 | |||
969 | child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg, | ||
970 | features); | ||
971 | if (IS_ERR(child)) | ||
972 | return PTR_ERR(child); | ||
973 | } | ||
974 | |||
975 | /* 6030 and 6025 share this regulator */ | ||
831 | if (twl_has_regulator() && twl_class_is_6030()) { | 976 | if (twl_has_regulator() && twl_class_is_6030()) { |
832 | child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc); | 977 | child = add_regulator(TWL6030_REG_VANA, pdata->vana, |
978 | features); | ||
833 | if (IS_ERR(child)) | 979 | if (IS_ERR(child)) |
834 | return PTR_ERR(child); | 980 | return PTR_ERR(child); |
981 | } | ||
835 | 982 | ||
836 | child = add_regulator(TWL6030_REG_VPP, pdata->vpp); | 983 | /* twl6025 regulators */ |
984 | if (twl_has_regulator() && twl_class_is_6030() && | ||
985 | (features & TWL6025_SUBCLASS)) { | ||
986 | child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5, | ||
987 | features); | ||
837 | if (IS_ERR(child)) | 988 | if (IS_ERR(child)) |
838 | return PTR_ERR(child); | 989 | return PTR_ERR(child); |
839 | 990 | ||
840 | child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim); | 991 | child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1, |
992 | features); | ||
841 | if (IS_ERR(child)) | 993 | if (IS_ERR(child)) |
842 | return PTR_ERR(child); | 994 | return PTR_ERR(child); |
843 | 995 | ||
844 | child = add_regulator(TWL6030_REG_VANA, pdata->vana); | 996 | child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7, |
997 | features); | ||
845 | if (IS_ERR(child)) | 998 | if (IS_ERR(child)) |
846 | return PTR_ERR(child); | 999 | return PTR_ERR(child); |
847 | 1000 | ||
848 | child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio); | 1001 | child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6, |
1002 | features); | ||
849 | if (IS_ERR(child)) | 1003 | if (IS_ERR(child)) |
850 | return PTR_ERR(child); | 1004 | return PTR_ERR(child); |
851 | 1005 | ||
852 | child = add_regulator(TWL6030_REG_VDAC, pdata->vdac); | 1006 | child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln, |
1007 | features); | ||
853 | if (IS_ERR(child)) | 1008 | if (IS_ERR(child)) |
854 | return PTR_ERR(child); | 1009 | return PTR_ERR(child); |
855 | 1010 | ||
856 | child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1); | 1011 | child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2, |
1012 | features); | ||
857 | if (IS_ERR(child)) | 1013 | if (IS_ERR(child)) |
858 | return PTR_ERR(child); | 1014 | return PTR_ERR(child); |
859 | 1015 | ||
860 | child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2); | 1016 | child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4, |
1017 | features); | ||
861 | if (IS_ERR(child)) | 1018 | if (IS_ERR(child)) |
862 | return PTR_ERR(child); | 1019 | return PTR_ERR(child); |
863 | 1020 | ||
864 | child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); | 1021 | child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3, |
1022 | features); | ||
865 | if (IS_ERR(child)) | 1023 | if (IS_ERR(child)) |
866 | return PTR_ERR(child); | 1024 | return PTR_ERR(child); |
867 | 1025 | ||
868 | child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg); | 1026 | child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3, |
1027 | features); | ||
869 | if (IS_ERR(child)) | 1028 | if (IS_ERR(child)) |
870 | return PTR_ERR(child); | 1029 | return PTR_ERR(child); |
1030 | |||
1031 | child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4, | ||
1032 | features); | ||
1033 | if (IS_ERR(child)) | ||
1034 | return PTR_ERR(child); | ||
1035 | |||
1036 | child = add_regulator(TWL6025_REG_VIO, pdata->vio6025, | ||
1037 | features); | ||
1038 | if (IS_ERR(child)) | ||
1039 | return PTR_ERR(child); | ||
1040 | |||
871 | } | 1041 | } |
872 | 1042 | ||
873 | if (twl_has_bci() && pdata->bci && | 1043 | if (twl_has_bci() && pdata->bci && |
@@ -1014,6 +1184,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1014 | unsigned i; | 1184 | unsigned i; |
1015 | struct twl4030_platform_data *pdata = client->dev.platform_data; | 1185 | struct twl4030_platform_data *pdata = client->dev.platform_data; |
1016 | u8 temp; | 1186 | u8 temp; |
1187 | int ret = 0; | ||
1017 | 1188 | ||
1018 | if (!pdata) { | 1189 | if (!pdata) { |
1019 | dev_dbg(&client->dev, "no platform data?\n"); | 1190 | dev_dbg(&client->dev, "no platform data?\n"); |
@@ -1060,6 +1231,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1060 | /* setup clock framework */ | 1231 | /* setup clock framework */ |
1061 | clocks_init(&client->dev, pdata->clock); | 1232 | clocks_init(&client->dev, pdata->clock); |
1062 | 1233 | ||
1234 | /* read TWL IDCODE Register */ | ||
1235 | if (twl_id == TWL4030_CLASS_ID) { | ||
1236 | ret = twl_read_idcode_register(); | ||
1237 | WARN(ret < 0, "Error: reading twl_idcode register value\n"); | ||
1238 | } | ||
1239 | |||
1063 | /* load power event scripts */ | 1240 | /* load power event scripts */ |
1064 | if (twl_has_power() && pdata->power) | 1241 | if (twl_has_power() && pdata->power) |
1065 | twl4030_power_init(pdata->power); | 1242 | twl4030_power_init(pdata->power); |
@@ -1108,6 +1285,7 @@ static const struct i2c_device_id twl_ids[] = { | |||
1108 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ | 1285 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ |
1109 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ | 1286 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ |
1110 | { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ | 1287 | { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ |
1288 | { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */ | ||
1111 | { /* end of list */ }, | 1289 | { /* end of list */ }, |
1112 | }; | 1290 | }; |
1113 | MODULE_DEVICE_TABLE(i2c, twl_ids); | 1291 | MODULE_DEVICE_TABLE(i2c, twl_ids); |
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c index c02fded316c9..2bf4136464c1 100644 --- a/drivers/mfd/twl4030-codec.c +++ b/drivers/mfd/twl4030-codec.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MFD driver for twl4030 codec submodule | 2 | * MFD driver for twl4030 codec submodule |
3 | * | 3 | * |
4 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | 4 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> |
5 | * | 5 | * |
6 | * Copyright: (C) 2009 Nokia Corporation | 6 | * Copyright: (C) 2009 Nokia Corporation |
7 | * | 7 | * |
@@ -208,13 +208,15 @@ 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->mfd_data = pdata->audio; | 211 | cell->platform_data = pdata->audio; |
212 | cell->pdata_size = sizeof(*pdata->audio); | ||
212 | childs++; | 213 | childs++; |
213 | } | 214 | } |
214 | if (pdata->vibra) { | 215 | if (pdata->vibra) { |
215 | cell = &codec->cells[childs]; | 216 | cell = &codec->cells[childs]; |
216 | cell->name = "twl4030-vibra"; | 217 | cell->name = "twl4030-vibra"; |
217 | cell->mfd_data = pdata->vibra; | 218 | cell->platform_data = pdata->vibra; |
219 | cell->pdata_size = sizeof(*pdata->vibra); | ||
218 | childs++; | 220 | childs++; |
219 | } | 221 | } |
220 | 222 | ||
@@ -270,6 +272,6 @@ static void __devexit twl4030_codec_exit(void) | |||
270 | } | 272 | } |
271 | module_exit(twl4030_codec_exit); | 273 | module_exit(twl4030_codec_exit); |
272 | 274 | ||
273 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>"); | 275 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
274 | MODULE_LICENSE("GPL"); | 276 | MODULE_LICENSE("GPL"); |
275 | 277 | ||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 2c0d4d16491a..a764676f0922 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c | |||
@@ -120,7 +120,7 @@ static u8 res_config_addrs[] = { | |||
120 | [RES_HFCLKOUT] = 0x8b, | 120 | [RES_HFCLKOUT] = 0x8b, |
121 | [RES_32KCLKOUT] = 0x8e, | 121 | [RES_32KCLKOUT] = 0x8e, |
122 | [RES_RESET] = 0x91, | 122 | [RES_RESET] = 0x91, |
123 | [RES_Main_Ref] = 0x94, | 123 | [RES_MAIN_REF] = 0x94, |
124 | }; | 124 | }; |
125 | 125 | ||
126 | static int __init twl4030_write_script_byte(u8 address, u8 byte) | 126 | static int __init twl4030_write_script_byte(u8 address, u8 byte) |
@@ -448,7 +448,7 @@ static int __init load_twl4030_script(struct twl4030_script *tscript, | |||
448 | goto out; | 448 | goto out; |
449 | } | 449 | } |
450 | if (tscript->flags & TWL4030_SLEEP_SCRIPT) { | 450 | if (tscript->flags & TWL4030_SLEEP_SCRIPT) { |
451 | if (order) | 451 | if (!order) |
452 | pr_warning("TWL4030: Bad order of scripts (sleep "\ | 452 | pr_warning("TWL4030: Bad order of scripts (sleep "\ |
453 | "script before wakeup) Leads to boot"\ | 453 | "script before wakeup) Leads to boot"\ |
454 | "failure on some boards\n"); | 454 | "failure on some boards\n"); |
@@ -485,9 +485,9 @@ int twl4030_remove_script(u8 flags) | |||
485 | return err; | 485 | return err; |
486 | } | 486 | } |
487 | if (flags & TWL4030_WAKEUP12_SCRIPT) { | 487 | if (flags & TWL4030_WAKEUP12_SCRIPT) { |
488 | if (err) | ||
489 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, | 488 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, |
490 | R_SEQ_ADD_S2A12); | 489 | R_SEQ_ADD_S2A12); |
490 | if (err) | ||
491 | return err; | 491 | return err; |
492 | } | 492 | } |
493 | if (flags & TWL4030_WAKEUP3_SCRIPT) { | 493 | if (flags & TWL4030_WAKEUP3_SCRIPT) { |
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index dfbae34e1804..eb3b5f88e566 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c | |||
@@ -76,8 +76,8 @@ static int twl6030_interrupt_mapping[24] = { | |||
76 | USBOTG_INTR_OFFSET, /* Bit 18 ID */ | 76 | USBOTG_INTR_OFFSET, /* Bit 18 ID */ |
77 | USB_PRES_INTR_OFFSET, /* Bit 19 VBUS */ | 77 | USB_PRES_INTR_OFFSET, /* Bit 19 VBUS */ |
78 | CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */ | 78 | CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */ |
79 | CHARGER_INTR_OFFSET, /* Bit 21 EXT_CHRG */ | 79 | CHARGERFAULT_INTR_OFFSET, /* Bit 21 EXT_CHRG */ |
80 | CHARGER_INTR_OFFSET, /* Bit 22 INT_CHRG */ | 80 | CHARGERFAULT_INTR_OFFSET, /* Bit 22 INT_CHRG */ |
81 | RSV_INTR_OFFSET, /* Bit 23 Reserved */ | 81 | RSV_INTR_OFFSET, /* Bit 23 Reserved */ |
82 | }; | 82 | }; |
83 | /*----------------------------------------------------------------------*/ | 83 | /*----------------------------------------------------------------------*/ |
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index 04914f2836c0..d97a86945174 100644 --- a/drivers/mfd/wl1273-core.c +++ b/drivers/mfd/wl1273-core.c | |||
@@ -153,7 +153,6 @@ out: | |||
153 | */ | 153 | */ |
154 | static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) | 154 | static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) |
155 | { | 155 | { |
156 | u16 val; | ||
157 | int r; | 156 | int r; |
158 | 157 | ||
159 | if (volume > WL1273_MAX_VOLUME) | 158 | if (volume > WL1273_MAX_VOLUME) |
@@ -217,7 +216,8 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, | |||
217 | 216 | ||
218 | cell = &core->cells[children]; | 217 | cell = &core->cells[children]; |
219 | cell->name = "wl1273_fm_radio"; | 218 | cell->name = "wl1273_fm_radio"; |
220 | cell->mfd_data = &core; | 219 | cell->platform_data = &core; |
220 | cell->pdata_size = sizeof(core); | ||
221 | children++; | 221 | children++; |
222 | 222 | ||
223 | core->read = wl1273_fm_read_reg; | 223 | core->read = wl1273_fm_read_reg; |
@@ -231,7 +231,8 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, | |||
231 | 231 | ||
232 | dev_dbg(&client->dev, "%s: Have codec.\n", __func__); | 232 | dev_dbg(&client->dev, "%s: Have codec.\n", __func__); |
233 | cell->name = "wl1273-codec"; | 233 | cell->name = "wl1273-codec"; |
234 | cell->mfd_data = &core; | 234 | cell->platform_data = &core; |
235 | cell->pdata_size = sizeof(core); | ||
235 | children++; | 236 | children++; |
236 | } | 237 | } |
237 | 238 | ||
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 3fe9a58fe6c7..265f75fc6a25 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -1442,7 +1442,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1442 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; | 1442 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; |
1443 | int rev; | 1443 | int rev; |
1444 | enum wm831x_parent parent; | 1444 | enum wm831x_parent parent; |
1445 | int ret; | 1445 | int ret, i; |
1446 | 1446 | ||
1447 | mutex_init(&wm831x->io_lock); | 1447 | mutex_init(&wm831x->io_lock); |
1448 | mutex_init(&wm831x->key_lock); | 1448 | mutex_init(&wm831x->key_lock); |
@@ -1581,6 +1581,17 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1581 | } | 1581 | } |
1582 | } | 1582 | } |
1583 | 1583 | ||
1584 | if (pdata) { | ||
1585 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { | ||
1586 | if (!pdata->gpio_defaults[i]) | ||
1587 | continue; | ||
1588 | |||
1589 | wm831x_reg_write(wm831x, | ||
1590 | WM831X_GPIO1_CONTROL + i, | ||
1591 | pdata->gpio_defaults[i] & 0xffff); | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1584 | ret = wm831x_irq_init(wm831x, irq); | 1595 | ret = wm831x_irq_init(wm831x, irq); |
1585 | if (ret != 0) | 1596 | if (ret != 0) |
1586 | goto err; | 1597 | goto err; |
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index 23e66af89dea..42b928ec891e 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -515,12 +515,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
515 | 0xffff); | 515 | 0xffff); |
516 | } | 516 | } |
517 | 517 | ||
518 | if (!irq) { | ||
519 | dev_warn(wm831x->dev, | ||
520 | "No interrupt specified - functionality limited\n"); | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | if (!pdata || !pdata->irq_base) { | 518 | if (!pdata || !pdata->irq_base) { |
525 | dev_err(wm831x->dev, | 519 | dev_err(wm831x->dev, |
526 | "No interrupt base specified, no interrupts\n"); | 520 | "No interrupt base specified, no interrupts\n"); |
@@ -567,15 +561,22 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
567 | #endif | 561 | #endif |
568 | } | 562 | } |
569 | 563 | ||
570 | ret = request_threaded_irq(irq, NULL, wm831x_irq_thread, | 564 | if (irq) { |
571 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 565 | ret = request_threaded_irq(irq, NULL, wm831x_irq_thread, |
572 | "wm831x", wm831x); | 566 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
573 | if (ret != 0) { | 567 | "wm831x", wm831x); |
574 | dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", | 568 | if (ret != 0) { |
575 | irq, ret); | 569 | dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", |
576 | return ret; | 570 | irq, ret); |
571 | return ret; | ||
572 | } | ||
573 | } else { | ||
574 | dev_warn(wm831x->dev, | ||
575 | "No interrupt specified - functionality limited\n"); | ||
577 | } | 576 | } |
578 | 577 | ||
578 | |||
579 | |||
579 | /* Enable top level interrupts, we mask at secondary level */ | 580 | /* Enable top level interrupts, we mask at secondary level */ |
580 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); | 581 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); |
581 | 582 | ||
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 3a6e78cb0384..597f82edacaa 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c | |||
@@ -245,7 +245,8 @@ 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 | .mfd_data = wm8400, | 248 | .platform_data = wm8400, |
249 | .pdata_size = sizeof(*wm8400), | ||
249 | }; | 250 | }; |
250 | 251 | ||
251 | return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); | 252 | return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 14479f9ef53f..8d185de90d20 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
@@ -69,7 +69,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *pdev) | |||
69 | if (pdev->num_resources != 2) | 69 | if (pdev->num_resources != 2) |
70 | goto out; | 70 | goto out; |
71 | 71 | ||
72 | pdata = mfd_get_data(pdev); | 72 | pdata = pdev->dev.platform_data; |
73 | if (!pdata || !pdata->hclk) | 73 | if (!pdata || !pdata->hclk) |
74 | goto out; | 74 | goto out; |
75 | 75 | ||
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index 14c578707824..c004e474631b 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c | |||
@@ -372,7 +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 tmio_nand_data *data = mfd_get_data(dev); | 375 | struct tmio_nand_data *data = dev->dev.platform_data; |
376 | struct resource *fcr = platform_get_resource(dev, | 376 | struct resource *fcr = platform_get_resource(dev, |
377 | IORESOURCE_MEM, 0); | 377 | IORESOURCE_MEM, 0); |
378 | struct resource *ccr = platform_get_resource(dev, | 378 | struct resource *ccr = platform_get_resource(dev, |
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 587fba48cdd9..f1942cab35f6 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c | |||
@@ -15,7 +15,6 @@ | |||
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> | ||
19 | 18 | ||
20 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
21 | #include <linux/can.h> | 20 | #include <linux/can.h> |
@@ -1644,7 +1643,7 @@ static int __devinit ican3_probe(struct platform_device *pdev) | |||
1644 | struct device *dev; | 1643 | struct device *dev; |
1645 | int ret; | 1644 | int ret; |
1646 | 1645 | ||
1647 | pdata = mfd_get_data(pdev); | 1646 | pdata = pdev->dev.platform_data; |
1648 | if (!pdata) | 1647 | if (!pdata) |
1649 | return -ENXIO; | 1648 | return -ENXIO; |
1650 | 1649 | ||
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index f0d8346d0fa5..4d40626b3bfa 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c | |||
@@ -26,7 +26,6 @@ | |||
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> | ||
30 | #include <linux/netdevice.h> | 29 | #include <linux/netdevice.h> |
31 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
32 | #include <linux/ethtool.h> | 31 | #include <linux/ethtool.h> |
@@ -1146,7 +1145,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev) | |||
1146 | struct resource *iomem; | 1145 | struct resource *iomem; |
1147 | struct net_device *netdev; | 1146 | struct net_device *netdev; |
1148 | struct ks8842_adapter *adapter; | 1147 | struct ks8842_adapter *adapter; |
1149 | struct ks8842_platform_data *pdata = mfd_get_data(pdev); | 1148 | struct ks8842_platform_data *pdata = pdev->dev.platform_data; |
1150 | u16 id; | 1149 | u16 id; |
1151 | unsigned i; | 1150 | unsigned i; |
1152 | 1151 | ||
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c index 8e5aec260866..a70e16d3a3dc 100644 --- a/drivers/power/max8925_power.c +++ b/drivers/power/max8925_power.c | |||
@@ -425,16 +425,11 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info) | |||
425 | static __devinit int max8925_power_probe(struct platform_device *pdev) | 425 | static __devinit int max8925_power_probe(struct platform_device *pdev) |
426 | { | 426 | { |
427 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | 427 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); |
428 | struct max8925_platform_data *max8925_pdata; | ||
429 | struct max8925_power_pdata *pdata = NULL; | 428 | struct max8925_power_pdata *pdata = NULL; |
430 | struct max8925_power_info *info; | 429 | struct max8925_power_info *info; |
431 | int ret; | 430 | int ret; |
432 | 431 | ||
433 | if (pdev->dev.parent->platform_data) { | 432 | pdata = pdev->dev.platform_data; |
434 | max8925_pdata = pdev->dev.parent->platform_data; | ||
435 | pdata = max8925_pdata->power; | ||
436 | } | ||
437 | |||
438 | if (!pdata) { | 433 | if (!pdata) { |
439 | dev_err(&pdev->dev, "platform data isn't assigned to " | 434 | dev_err(&pdev->dev, "platform data isn't assigned to " |
440 | "power supply\n"); | 435 | "power supply\n"); |
@@ -447,6 +442,7 @@ static __devinit int max8925_power_probe(struct platform_device *pdev) | |||
447 | info->chip = chip; | 442 | info->chip = chip; |
448 | info->gpm = chip->i2c; | 443 | info->gpm = chip->i2c; |
449 | info->adc = chip->adc; | 444 | info->adc = chip->adc; |
445 | platform_set_drvdata(pdev, info); | ||
450 | 446 | ||
451 | info->ac.name = "max8925-ac"; | 447 | info->ac.name = "max8925-ac"; |
452 | info->ac.type = POWER_SUPPLY_TYPE_MAINS; | 448 | info->ac.type = POWER_SUPPLY_TYPE_MAINS; |
@@ -482,8 +478,6 @@ static __devinit int max8925_power_probe(struct platform_device *pdev) | |||
482 | info->topoff_threshold = pdata->topoff_threshold; | 478 | info->topoff_threshold = pdata->topoff_threshold; |
483 | info->fast_charge = pdata->fast_charge; | 479 | info->fast_charge = pdata->fast_charge; |
484 | info->set_charger = pdata->set_charger; | 480 | info->set_charger = pdata->set_charger; |
485 | dev_set_drvdata(&pdev->dev, info); | ||
486 | platform_set_drvdata(pdev, info); | ||
487 | 481 | ||
488 | max8925_init_charger(chip, info); | 482 | max8925_init_charger(chip, info); |
489 | return 0; | 483 | return 0; |
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 859251250b55..d63fddb0fbb0 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c | |||
@@ -15,7 +15,6 @@ | |||
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> | ||
19 | #include <linux/mfd/88pm860x.h> | 18 | #include <linux/mfd/88pm860x.h> |
20 | 19 | ||
21 | struct pm8607_regulator_info { | 20 | struct pm8607_regulator_info { |
@@ -399,36 +398,33 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) | |||
399 | { | 398 | { |
400 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 399 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
401 | struct pm8607_regulator_info *info = NULL; | 400 | struct pm8607_regulator_info *info = NULL; |
402 | struct regulator_init_data *pdata; | 401 | struct regulator_init_data *pdata = pdev->dev.platform_data; |
403 | struct mfd_cell *cell; | 402 | struct resource *res; |
404 | int i; | 403 | int i; |
405 | 404 | ||
406 | cell = pdev->dev.platform_data; | 405 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
407 | if (cell == NULL) | 406 | if (res == NULL) { |
408 | return -ENODEV; | 407 | dev_err(&pdev->dev, "No I/O resource!\n"); |
409 | pdata = cell->mfd_data; | ||
410 | if (pdata == NULL) | ||
411 | return -EINVAL; | 408 | return -EINVAL; |
412 | 409 | } | |
413 | for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { | 410 | for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { |
414 | info = &pm8607_regulator_info[i]; | 411 | info = &pm8607_regulator_info[i]; |
415 | if (!strcmp(info->desc.name, pdata->constraints.name)) | 412 | if (info->desc.id == res->start) |
416 | break; | 413 | break; |
417 | } | 414 | } |
418 | if (i > ARRAY_SIZE(pm8607_regulator_info)) { | 415 | if ((i < 0) || (i > PM8607_ID_RG_MAX)) { |
419 | dev_err(&pdev->dev, "Failed to find regulator %s\n", | 416 | dev_err(&pdev->dev, "Failed to find regulator %llu\n", |
420 | pdata->constraints.name); | 417 | (unsigned long long)res->start); |
421 | return -EINVAL; | 418 | return -EINVAL; |
422 | } | 419 | } |
423 | |||
424 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | 420 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
425 | info->chip = chip; | 421 | info->chip = chip; |
426 | 422 | ||
427 | /* check DVC ramp slope double */ | 423 | /* check DVC ramp slope double */ |
428 | if (!strcmp(info->desc.name, "BUCK3")) | 424 | if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double) |
429 | if (info->chip->buck3_double) | 425 | info->slope_double = 1; |
430 | info->slope_double = 1; | ||
431 | 426 | ||
427 | /* replace driver_data with info */ | ||
432 | info->regulator = regulator_register(&info->desc, &pdev->dev, | 428 | info->regulator = regulator_register(&info->desc, &pdev->dev, |
433 | pdata, info); | 429 | pdata, info); |
434 | if (IS_ERR(info->regulator)) { | 430 | if (IS_ERR(info->regulator)) { |
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index b1d77946e9c6..585e4946fe0a 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c | |||
@@ -17,7 +17,6 @@ | |||
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> | ||
21 | 20 | ||
22 | /* LDO registers and some handy masking definitions for AB3100 */ | 21 | /* LDO registers and some handy masking definitions for AB3100 */ |
23 | #define AB3100_LDO_A 0x40 | 22 | #define AB3100_LDO_A 0x40 |
@@ -582,7 +581,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { | |||
582 | 581 | ||
583 | static int __devinit ab3100_regulators_probe(struct platform_device *pdev) | 582 | static int __devinit ab3100_regulators_probe(struct platform_device *pdev) |
584 | { | 583 | { |
585 | struct ab3100_platform_data *plfdata = mfd_get_data(pdev); | 584 | struct ab3100_platform_data *plfdata = pdev->dev.platform_data; |
586 | int err = 0; | 585 | int err = 0; |
587 | u8 data; | 586 | u8 data; |
588 | int i; | 587 | int i; |
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 1089a961616e..e5f7b8fe51f4 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/mfd/core.h> | ||
17 | #include <linux/mfd/db8500-prcmu.h> | 16 | #include <linux/mfd/db8500-prcmu.h> |
18 | #include <linux/regulator/driver.h> | 17 | #include <linux/regulator/driver.h> |
19 | #include <linux/regulator/machine.h> | 18 | #include <linux/regulator/machine.h> |
@@ -471,7 +470,8 @@ static struct db8500_regulator_info | |||
471 | 470 | ||
472 | static int __devinit db8500_regulator_probe(struct platform_device *pdev) | 471 | static int __devinit db8500_regulator_probe(struct platform_device *pdev) |
473 | { | 472 | { |
474 | struct regulator_init_data *db8500_init_data = mfd_get_data(pdev); | 473 | struct regulator_init_data *db8500_init_data = |
474 | dev_get_platdata(&pdev->dev); | ||
475 | int i, err; | 475 | int i, err; |
476 | 476 | ||
477 | /* register all regulators */ | 477 | /* register all regulators */ |
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 8ae147549c6a..e4dbd667c043 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c | |||
@@ -23,6 +23,10 @@ | |||
23 | #define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */ | 23 | #define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */ |
24 | #define SD1_DVM_EN 6 /* SDV1 bit 6 */ | 24 | #define SD1_DVM_EN 6 /* SDV1 bit 6 */ |
25 | 25 | ||
26 | /* bit definitions in SD & LDO control registers */ | ||
27 | #define OUT_ENABLE 0x1f /* Power U/D sequence as I2C */ | ||
28 | #define OUT_DISABLE 0x1e /* Power U/D sequence as I2C */ | ||
29 | |||
26 | struct max8925_regulator_info { | 30 | struct max8925_regulator_info { |
27 | struct regulator_desc desc; | 31 | struct regulator_desc desc; |
28 | struct regulator_dev *regulator; | 32 | struct regulator_dev *regulator; |
@@ -93,8 +97,8 @@ static int max8925_enable(struct regulator_dev *rdev) | |||
93 | struct max8925_regulator_info *info = rdev_get_drvdata(rdev); | 97 | struct max8925_regulator_info *info = rdev_get_drvdata(rdev); |
94 | 98 | ||
95 | return max8925_set_bits(info->i2c, info->enable_reg, | 99 | return max8925_set_bits(info->i2c, info->enable_reg, |
96 | 1 << info->enable_bit, | 100 | OUT_ENABLE << info->enable_bit, |
97 | 1 << info->enable_bit); | 101 | OUT_ENABLE << info->enable_bit); |
98 | } | 102 | } |
99 | 103 | ||
100 | static int max8925_disable(struct regulator_dev *rdev) | 104 | static int max8925_disable(struct regulator_dev *rdev) |
@@ -102,7 +106,8 @@ static int max8925_disable(struct regulator_dev *rdev) | |||
102 | struct max8925_regulator_info *info = rdev_get_drvdata(rdev); | 106 | struct max8925_regulator_info *info = rdev_get_drvdata(rdev); |
103 | 107 | ||
104 | return max8925_set_bits(info->i2c, info->enable_reg, | 108 | return max8925_set_bits(info->i2c, info->enable_reg, |
105 | 1 << info->enable_bit, 0); | 109 | OUT_ENABLE << info->enable_bit, |
110 | OUT_DISABLE << info->enable_bit); | ||
106 | } | 111 | } |
107 | 112 | ||
108 | static int max8925_is_enabled(struct regulator_dev *rdev) | 113 | static int max8925_is_enabled(struct regulator_dev *rdev) |
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index b8a00c7fa441..730f43ad415b 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c | |||
@@ -15,7 +15,6 @@ | |||
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> | ||
19 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
20 | #include <linux/init.h> | 19 | #include <linux/init.h> |
21 | #include <linux/err.h> | 20 | #include <linux/err.h> |
@@ -337,7 +336,8 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) | |||
337 | { | 336 | { |
338 | struct mc13xxx_regulator_priv *priv; | 337 | struct mc13xxx_regulator_priv *priv; |
339 | struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); | 338 | struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); |
340 | struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev); | 339 | struct mc13783_regulator_platform_data *pdata = |
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,7 +381,8 @@ 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 = mfd_get_data(pdev); | 384 | struct mc13783_regulator_platform_data *pdata = |
385 | dev_get_platdata(&pdev->dev); | ||
385 | int i; | 386 | int i; |
386 | 387 | ||
387 | platform_set_drvdata(pdev, NULL); | 388 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 6f15168e5ed4..1b8f7398a4a8 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c | |||
@@ -15,7 +15,6 @@ | |||
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> | ||
19 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
20 | #include <linux/init.h> | 19 | #include <linux/init.h> |
21 | #include <linux/err.h> | 20 | #include <linux/err.h> |
@@ -521,7 +520,8 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) | |||
521 | { | 520 | { |
522 | struct mc13xxx_regulator_priv *priv; | 521 | struct mc13xxx_regulator_priv *priv; |
523 | struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); | 522 | struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); |
524 | struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev); | 523 | struct mc13xxx_regulator_platform_data *pdata = |
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,7 +595,8 @@ 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 = mfd_get_data(pdev); | 598 | struct mc13xxx_regulator_platform_data *pdata = |
599 | dev_get_platdata(&pdev->dev); | ||
599 | int i; | 600 | int i; |
600 | 601 | ||
601 | platform_set_drvdata(pdev, NULL); | 602 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index 1661499feda4..a4d7f4540c18 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c | |||
@@ -137,7 +137,7 @@ static struct regulator_desc tps6105x_regulator_desc = { | |||
137 | */ | 137 | */ |
138 | static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) | 138 | static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) |
139 | { | 139 | { |
140 | struct tps6105x *tps6105x = mfd_get_data(pdev); | 140 | struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev); |
141 | struct tps6105x_platform_data *pdata = tps6105x->pdata; | 141 | struct tps6105x_platform_data *pdata = tps6105x->pdata; |
142 | int ret; | 142 | int ret; |
143 | 143 | ||
@@ -164,7 +164,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) | |||
164 | 164 | ||
165 | static int __devexit tps6105x_regulator_remove(struct platform_device *pdev) | 165 | static int __devexit tps6105x_regulator_remove(struct platform_device *pdev) |
166 | { | 166 | { |
167 | struct tps6105x *tps6105x = platform_get_drvdata(pdev); | 167 | struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev); |
168 | regulator_unregister(tps6105x->regulator); | 168 | regulator_unregister(tps6105x->regulator); |
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index b8f4e9e66cd5..8e437e2f6281 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -125,6 +125,16 @@ comment "I2C RTC drivers" | |||
125 | 125 | ||
126 | if I2C | 126 | if I2C |
127 | 127 | ||
128 | config RTC_DRV_88PM860X | ||
129 | tristate "Marvell 88PM860x" | ||
130 | depends on RTC_CLASS && I2C && MFD_88PM860X | ||
131 | help | ||
132 | If you say yes here you get support for RTC function in Marvell | ||
133 | 88PM860x chips. | ||
134 | |||
135 | This driver can also be built as a module. If so, the module | ||
136 | will be called rtc-88pm860x. | ||
137 | |||
128 | config RTC_DRV_DS1307 | 138 | config RTC_DRV_DS1307 |
129 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" | 139 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" |
130 | help | 140 | help |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 9574748d1c73..612f5a88a8ee 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -15,6 +15,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
15 | 15 | ||
16 | # Keep the list ordered. | 16 | # Keep the list ordered. |
17 | 17 | ||
18 | obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o | ||
18 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o | 19 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o |
19 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o | 20 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o |
20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 21 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c new file mode 100644 index 000000000000..64b847b7f970 --- /dev/null +++ b/drivers/rtc/rtc-88pm860x.c | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Marvell 88PM860x PMIC | ||
3 | * | ||
4 | * Copyright (c) 2010 Marvell International Ltd. | ||
5 | * Author: Haojian Zhuang <haojian.zhuang@marvell.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 version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/mutex.h> | ||
17 | #include <linux/rtc.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/mfd/core.h> | ||
20 | #include <linux/mfd/88pm860x.h> | ||
21 | |||
22 | #define VRTC_CALIBRATION | ||
23 | |||
24 | struct pm860x_rtc_info { | ||
25 | struct pm860x_chip *chip; | ||
26 | struct i2c_client *i2c; | ||
27 | struct rtc_device *rtc_dev; | ||
28 | struct device *dev; | ||
29 | struct delayed_work calib_work; | ||
30 | |||
31 | int irq; | ||
32 | int vrtc; | ||
33 | int (*sync)(unsigned int ticks); | ||
34 | }; | ||
35 | |||
36 | #define REG_VRTC_MEAS1 0x7D | ||
37 | |||
38 | #define REG0_ADDR 0xB0 | ||
39 | #define REG1_ADDR 0xB2 | ||
40 | #define REG2_ADDR 0xB4 | ||
41 | #define REG3_ADDR 0xB6 | ||
42 | |||
43 | #define REG0_DATA 0xB1 | ||
44 | #define REG1_DATA 0xB3 | ||
45 | #define REG2_DATA 0xB5 | ||
46 | #define REG3_DATA 0xB7 | ||
47 | |||
48 | /* bit definitions of Measurement Enable Register 2 (0x51) */ | ||
49 | #define MEAS2_VRTC (1 << 0) | ||
50 | |||
51 | /* bit definitions of RTC Register 1 (0xA0) */ | ||
52 | #define ALARM_EN (1 << 3) | ||
53 | #define ALARM_WAKEUP (1 << 4) | ||
54 | #define ALARM (1 << 5) | ||
55 | #define RTC1_USE_XO (1 << 7) | ||
56 | |||
57 | #define VRTC_CALIB_INTERVAL (HZ * 60 * 10) /* 10 minutes */ | ||
58 | |||
59 | static irqreturn_t rtc_update_handler(int irq, void *data) | ||
60 | { | ||
61 | struct pm860x_rtc_info *info = (struct pm860x_rtc_info *)data; | ||
62 | int mask; | ||
63 | |||
64 | mask = ALARM | ALARM_WAKEUP; | ||
65 | pm860x_set_bits(info->i2c, PM8607_RTC1, mask | ALARM_EN, mask); | ||
66 | rtc_update_irq(info->rtc_dev, 1, RTC_AF); | ||
67 | return IRQ_HANDLED; | ||
68 | } | ||
69 | |||
70 | static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
71 | { | ||
72 | struct pm860x_rtc_info *info = dev_get_drvdata(dev); | ||
73 | |||
74 | if (enabled) | ||
75 | pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM); | ||
76 | else | ||
77 | pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Calculate the next alarm time given the requested alarm time mask | ||
83 | * and the current time. | ||
84 | */ | ||
85 | static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, | ||
86 | struct rtc_time *alrm) | ||
87 | { | ||
88 | unsigned long next_time; | ||
89 | unsigned long now_time; | ||
90 | |||
91 | next->tm_year = now->tm_year; | ||
92 | next->tm_mon = now->tm_mon; | ||
93 | next->tm_mday = now->tm_mday; | ||
94 | next->tm_hour = alrm->tm_hour; | ||
95 | next->tm_min = alrm->tm_min; | ||
96 | next->tm_sec = alrm->tm_sec; | ||
97 | |||
98 | rtc_tm_to_time(now, &now_time); | ||
99 | rtc_tm_to_time(next, &next_time); | ||
100 | |||
101 | if (next_time < now_time) { | ||
102 | /* Advance one day */ | ||
103 | next_time += 60 * 60 * 24; | ||
104 | rtc_time_to_tm(next_time, next); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
109 | { | ||
110 | struct pm860x_rtc_info *info = dev_get_drvdata(dev); | ||
111 | unsigned char buf[8]; | ||
112 | unsigned long ticks, base, data; | ||
113 | |||
114 | pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); | ||
115 | dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], | ||
116 | buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); | ||
117 | base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; | ||
118 | |||
119 | /* load 32-bit read-only counter */ | ||
120 | pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); | ||
121 | data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
122 | ticks = base + data; | ||
123 | dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", | ||
124 | base, data, ticks); | ||
125 | |||
126 | rtc_time_to_tm(ticks, tm); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
132 | { | ||
133 | struct pm860x_rtc_info *info = dev_get_drvdata(dev); | ||
134 | unsigned char buf[4]; | ||
135 | unsigned long ticks, base, data; | ||
136 | |||
137 | if ((tm->tm_year < 70) || (tm->tm_year > 138)) { | ||
138 | dev_dbg(info->dev, "Set time %d out of range. " | ||
139 | "Please set time between 1970 to 2038.\n", | ||
140 | 1900 + tm->tm_year); | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | rtc_tm_to_time(tm, &ticks); | ||
144 | |||
145 | /* load 32-bit read-only counter */ | ||
146 | pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); | ||
147 | data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
148 | base = ticks - data; | ||
149 | dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", | ||
150 | base, data, ticks); | ||
151 | |||
152 | pm860x_page_reg_write(info->i2c, REG0_DATA, (base >> 24) & 0xFF); | ||
153 | pm860x_page_reg_write(info->i2c, REG1_DATA, (base >> 16) & 0xFF); | ||
154 | pm860x_page_reg_write(info->i2c, REG2_DATA, (base >> 8) & 0xFF); | ||
155 | pm860x_page_reg_write(info->i2c, REG3_DATA, base & 0xFF); | ||
156 | |||
157 | if (info->sync) | ||
158 | info->sync(ticks); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
163 | { | ||
164 | struct pm860x_rtc_info *info = dev_get_drvdata(dev); | ||
165 | unsigned char buf[8]; | ||
166 | unsigned long ticks, base, data; | ||
167 | int ret; | ||
168 | |||
169 | pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); | ||
170 | dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], | ||
171 | buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); | ||
172 | base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; | ||
173 | |||
174 | pm860x_bulk_read(info->i2c, PM8607_RTC_EXPIRE1, 4, buf); | ||
175 | data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
176 | ticks = base + data; | ||
177 | dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", | ||
178 | base, data, ticks); | ||
179 | |||
180 | rtc_time_to_tm(ticks, &alrm->time); | ||
181 | ret = pm860x_reg_read(info->i2c, PM8607_RTC1); | ||
182 | alrm->enabled = (ret & ALARM_EN) ? 1 : 0; | ||
183 | alrm->pending = (ret & (ALARM | ALARM_WAKEUP)) ? 1 : 0; | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
188 | { | ||
189 | struct pm860x_rtc_info *info = dev_get_drvdata(dev); | ||
190 | struct rtc_time now_tm, alarm_tm; | ||
191 | unsigned long ticks, base, data; | ||
192 | unsigned char buf[8]; | ||
193 | int mask; | ||
194 | |||
195 | pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0); | ||
196 | |||
197 | pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf); | ||
198 | dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1], | ||
199 | buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); | ||
200 | base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7]; | ||
201 | |||
202 | /* load 32-bit read-only counter */ | ||
203 | pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf); | ||
204 | data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
205 | ticks = base + data; | ||
206 | dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", | ||
207 | base, data, ticks); | ||
208 | |||
209 | rtc_time_to_tm(ticks, &now_tm); | ||
210 | rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); | ||
211 | /* get new ticks for alarm in 24 hours */ | ||
212 | rtc_tm_to_time(&alarm_tm, &ticks); | ||
213 | data = ticks - base; | ||
214 | |||
215 | buf[0] = data & 0xff; | ||
216 | buf[1] = (data >> 8) & 0xff; | ||
217 | buf[2] = (data >> 16) & 0xff; | ||
218 | buf[3] = (data >> 24) & 0xff; | ||
219 | pm860x_bulk_write(info->i2c, PM8607_RTC_EXPIRE1, 4, buf); | ||
220 | if (alrm->enabled) { | ||
221 | mask = ALARM | ALARM_WAKEUP | ALARM_EN; | ||
222 | pm860x_set_bits(info->i2c, PM8607_RTC1, mask, mask); | ||
223 | } else { | ||
224 | mask = ALARM | ALARM_WAKEUP | ALARM_EN; | ||
225 | pm860x_set_bits(info->i2c, PM8607_RTC1, mask, | ||
226 | ALARM | ALARM_WAKEUP); | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static const struct rtc_class_ops pm860x_rtc_ops = { | ||
232 | .read_time = pm860x_rtc_read_time, | ||
233 | .set_time = pm860x_rtc_set_time, | ||
234 | .read_alarm = pm860x_rtc_read_alarm, | ||
235 | .set_alarm = pm860x_rtc_set_alarm, | ||
236 | .alarm_irq_enable = pm860x_rtc_alarm_irq_enable, | ||
237 | }; | ||
238 | |||
239 | #ifdef VRTC_CALIBRATION | ||
240 | static void calibrate_vrtc_work(struct work_struct *work) | ||
241 | { | ||
242 | struct pm860x_rtc_info *info = container_of(work, | ||
243 | struct pm860x_rtc_info, calib_work.work); | ||
244 | unsigned char buf[2]; | ||
245 | unsigned int sum, data, mean, vrtc_set; | ||
246 | int i; | ||
247 | |||
248 | for (i = 0, sum = 0; i < 16; i++) { | ||
249 | msleep(100); | ||
250 | pm860x_bulk_read(info->i2c, REG_VRTC_MEAS1, 2, buf); | ||
251 | data = (buf[0] << 4) | buf[1]; | ||
252 | data = (data * 5400) >> 12; /* convert to mv */ | ||
253 | sum += data; | ||
254 | } | ||
255 | mean = sum >> 4; | ||
256 | vrtc_set = 2700 + (info->vrtc & 0x3) * 200; | ||
257 | dev_dbg(info->dev, "mean:%d, vrtc_set:%d\n", mean, vrtc_set); | ||
258 | |||
259 | sum = pm860x_reg_read(info->i2c, PM8607_RTC_MISC1); | ||
260 | data = sum & 0x3; | ||
261 | if ((mean + 200) < vrtc_set) { | ||
262 | /* try higher voltage */ | ||
263 | if (++data == 4) | ||
264 | goto out; | ||
265 | data = (sum & 0xf8) | (data & 0x3); | ||
266 | pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data); | ||
267 | } else if ((mean - 200) > vrtc_set) { | ||
268 | /* try lower voltage */ | ||
269 | if (data-- == 0) | ||
270 | goto out; | ||
271 | data = (sum & 0xf8) | (data & 0x3); | ||
272 | pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data); | ||
273 | } else | ||
274 | goto out; | ||
275 | dev_dbg(info->dev, "set 0x%x to RTC_MISC1\n", data); | ||
276 | /* trigger next calibration since VRTC is updated */ | ||
277 | schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); | ||
278 | return; | ||
279 | out: | ||
280 | /* disable measurement */ | ||
281 | pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0); | ||
282 | dev_dbg(info->dev, "finish VRTC calibration\n"); | ||
283 | return; | ||
284 | } | ||
285 | #endif | ||
286 | |||
287 | static int __devinit pm860x_rtc_probe(struct platform_device *pdev) | ||
288 | { | ||
289 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
290 | struct pm860x_rtc_pdata *pdata = NULL; | ||
291 | struct pm860x_rtc_info *info; | ||
292 | struct rtc_time tm; | ||
293 | unsigned long ticks = 0; | ||
294 | int ret; | ||
295 | |||
296 | pdata = pdev->dev.platform_data; | ||
297 | if (pdata == NULL) | ||
298 | dev_warn(&pdev->dev, "No platform data!\n"); | ||
299 | |||
300 | info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL); | ||
301 | if (!info) | ||
302 | return -ENOMEM; | ||
303 | info->irq = platform_get_irq(pdev, 0); | ||
304 | if (info->irq < 0) { | ||
305 | dev_err(&pdev->dev, "No IRQ resource!\n"); | ||
306 | ret = -EINVAL; | ||
307 | goto out; | ||
308 | } | ||
309 | |||
310 | info->chip = chip; | ||
311 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | ||
312 | info->dev = &pdev->dev; | ||
313 | dev_set_drvdata(&pdev->dev, info); | ||
314 | |||
315 | ret = request_threaded_irq(info->irq, NULL, rtc_update_handler, | ||
316 | IRQF_ONESHOT, "rtc", info); | ||
317 | if (ret < 0) { | ||
318 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
319 | info->irq, ret); | ||
320 | goto out; | ||
321 | } | ||
322 | |||
323 | /* set addresses of 32-bit base value for RTC time */ | ||
324 | pm860x_page_reg_write(info->i2c, REG0_ADDR, REG0_DATA); | ||
325 | pm860x_page_reg_write(info->i2c, REG1_ADDR, REG1_DATA); | ||
326 | pm860x_page_reg_write(info->i2c, REG2_ADDR, REG2_DATA); | ||
327 | pm860x_page_reg_write(info->i2c, REG3_ADDR, REG3_DATA); | ||
328 | |||
329 | ret = pm860x_rtc_read_time(&pdev->dev, &tm); | ||
330 | if (ret < 0) { | ||
331 | dev_err(&pdev->dev, "Failed to read initial time.\n"); | ||
332 | goto out_rtc; | ||
333 | } | ||
334 | if ((tm.tm_year < 70) || (tm.tm_year > 138)) { | ||
335 | tm.tm_year = 70; | ||
336 | tm.tm_mon = 0; | ||
337 | tm.tm_mday = 1; | ||
338 | tm.tm_hour = 0; | ||
339 | tm.tm_min = 0; | ||
340 | tm.tm_sec = 0; | ||
341 | ret = pm860x_rtc_set_time(&pdev->dev, &tm); | ||
342 | if (ret < 0) { | ||
343 | dev_err(&pdev->dev, "Failed to set initial time.\n"); | ||
344 | goto out_rtc; | ||
345 | } | ||
346 | } | ||
347 | rtc_tm_to_time(&tm, &ticks); | ||
348 | if (pdata && pdata->sync) { | ||
349 | pdata->sync(ticks); | ||
350 | info->sync = pdata->sync; | ||
351 | } | ||
352 | |||
353 | info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev, | ||
354 | &pm860x_rtc_ops, THIS_MODULE); | ||
355 | ret = PTR_ERR(info->rtc_dev); | ||
356 | if (IS_ERR(info->rtc_dev)) { | ||
357 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
358 | goto out_rtc; | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * enable internal XO instead of internal 3.25MHz clock since it can | ||
363 | * free running in PMIC power-down state. | ||
364 | */ | ||
365 | pm860x_set_bits(info->i2c, PM8607_RTC1, RTC1_USE_XO, RTC1_USE_XO); | ||
366 | |||
367 | #ifdef VRTC_CALIBRATION | ||
368 | /* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */ | ||
369 | if (pdata && pdata->vrtc) | ||
370 | info->vrtc = pdata->vrtc & 0x3; | ||
371 | else | ||
372 | info->vrtc = 1; | ||
373 | pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC); | ||
374 | |||
375 | /* calibrate VRTC */ | ||
376 | INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work); | ||
377 | schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); | ||
378 | #endif /* VRTC_CALIBRATION */ | ||
379 | return 0; | ||
380 | out_rtc: | ||
381 | free_irq(info->irq, info); | ||
382 | out: | ||
383 | kfree(info); | ||
384 | return ret; | ||
385 | } | ||
386 | |||
387 | static int __devexit pm860x_rtc_remove(struct platform_device *pdev) | ||
388 | { | ||
389 | struct pm860x_rtc_info *info = platform_get_drvdata(pdev); | ||
390 | |||
391 | #ifdef VRTC_CALIBRATION | ||
392 | flush_scheduled_work(); | ||
393 | /* disable measurement */ | ||
394 | pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0); | ||
395 | #endif /* VRTC_CALIBRATION */ | ||
396 | |||
397 | platform_set_drvdata(pdev, NULL); | ||
398 | rtc_device_unregister(info->rtc_dev); | ||
399 | free_irq(info->irq, info); | ||
400 | kfree(info); | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static struct platform_driver pm860x_rtc_driver = { | ||
405 | .driver = { | ||
406 | .name = "88pm860x-rtc", | ||
407 | .owner = THIS_MODULE, | ||
408 | }, | ||
409 | .probe = pm860x_rtc_probe, | ||
410 | .remove = __devexit_p(pm860x_rtc_remove), | ||
411 | }; | ||
412 | |||
413 | static int __init pm860x_rtc_init(void) | ||
414 | { | ||
415 | return platform_driver_register(&pm860x_rtc_driver); | ||
416 | } | ||
417 | module_init(pm860x_rtc_init); | ||
418 | |||
419 | static void __exit pm860x_rtc_exit(void) | ||
420 | { | ||
421 | platform_driver_unregister(&pm860x_rtc_driver); | ||
422 | } | ||
423 | module_exit(pm860x_rtc_exit); | ||
424 | |||
425 | MODULE_DESCRIPTION("Marvell 88PM860x RTC driver"); | ||
426 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
427 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index c69c6f2c2c5c..4d2c75df886c 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c | |||
@@ -18,7 +18,6 @@ | |||
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> | ||
22 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
23 | #include <linux/spi/spi_bitbang.h> | 22 | #include <linux/spi/spi_bitbang.h> |
24 | #include <linux/spi/xilinx_spi.h> | 23 | #include <linux/spi/xilinx_spi.h> |
@@ -471,7 +470,7 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev) | |||
471 | struct spi_master *master; | 470 | struct spi_master *master; |
472 | u8 i; | 471 | u8 i; |
473 | 472 | ||
474 | pdata = mfd_get_data(dev); | 473 | pdata = dev->dev.platform_data; |
475 | if (pdata) { | 474 | if (pdata) { |
476 | num_cs = pdata->num_chipselect; | 475 | num_cs = pdata->num_chipselect; |
477 | little_endian = pdata->little_endian; | 476 | little_endian = pdata->little_endian; |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index c8b520e9a11a..c04b94da81f7 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/backlight.h> | 18 | #include <linux/backlight.h> |
19 | #include <linux/mfd/core.h> | ||
20 | #include <linux/mfd/88pm860x.h> | 19 | #include <linux/mfd/88pm860x.h> |
21 | 20 | ||
22 | #define MAX_BRIGHTNESS (0xFF) | 21 | #define MAX_BRIGHTNESS (0xFF) |
@@ -168,7 +167,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
168 | struct pm860x_backlight_pdata *pdata = NULL; | 167 | struct pm860x_backlight_pdata *pdata = NULL; |
169 | struct pm860x_backlight_data *data; | 168 | struct pm860x_backlight_data *data; |
170 | struct backlight_device *bl; | 169 | struct backlight_device *bl; |
171 | struct mfd_cell *cell; | ||
172 | struct resource *res; | 170 | struct resource *res; |
173 | struct backlight_properties props; | 171 | struct backlight_properties props; |
174 | unsigned char value; | 172 | unsigned char value; |
@@ -181,10 +179,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
181 | return -EINVAL; | 179 | return -EINVAL; |
182 | } | 180 | } |
183 | 181 | ||
184 | cell = pdev->dev.platform_data; | 182 | pdata = pdev->dev.platform_data; |
185 | if (cell == NULL) | ||
186 | return -ENODEV; | ||
187 | pdata = cell->mfd_data; | ||
188 | if (pdata == NULL) { | 183 | if (pdata == NULL) { |
189 | dev_err(&pdev->dev, "platform data isn't assigned to " | 184 | dev_err(&pdev->dev, "platform data isn't assigned to " |
190 | "backlight\n"); | 185 | "backlight\n"); |
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 0c341d739604..cd1c4dcef8fd 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c | |||
@@ -250,7 +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 tmio_fb_data *data = mfd_get_data(dev); | 253 | struct tmio_fb_data *data = dev->dev.platform_data; |
254 | struct fb_info *info = platform_get_drvdata(dev); | 254 | struct fb_info *info = platform_get_drvdata(dev); |
255 | struct tmiofb_par *par = info->par; | 255 | struct tmiofb_par *par = info->par; |
256 | 256 | ||
@@ -311,7 +311,7 @@ static int tmiofb_hw_init(struct platform_device *dev) | |||
311 | */ | 311 | */ |
312 | static void tmiofb_hw_mode(struct platform_device *dev) | 312 | static void tmiofb_hw_mode(struct platform_device *dev) |
313 | { | 313 | { |
314 | struct tmio_fb_data *data = mfd_get_data(dev); | 314 | struct tmio_fb_data *data = dev->dev.platform_data; |
315 | struct fb_info *info = platform_get_drvdata(dev); | 315 | struct fb_info *info = platform_get_drvdata(dev); |
316 | struct fb_videomode *mode = info->mode; | 316 | struct fb_videomode *mode = info->mode; |
317 | struct tmiofb_par *par = info->par; | 317 | struct tmiofb_par *par = info->par; |
@@ -557,8 +557,7 @@ static int tmiofb_ioctl(struct fb_info *fbi, | |||
557 | static struct fb_videomode * | 557 | static struct fb_videomode * |
558 | 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) |
559 | { | 559 | { |
560 | struct tmio_fb_data *data = | 560 | struct tmio_fb_data *data = info->device->platform_data; |
561 | mfd_get_data(to_platform_device(info->device)); | ||
562 | struct fb_videomode *best = NULL; | 561 | struct fb_videomode *best = NULL; |
563 | int i; | 562 | int i; |
564 | 563 | ||
@@ -578,8 +577,7 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
578 | { | 577 | { |
579 | 578 | ||
580 | struct fb_videomode *mode; | 579 | struct fb_videomode *mode; |
581 | struct tmio_fb_data *data = | 580 | struct tmio_fb_data *data = info->device->platform_data; |
582 | mfd_get_data(to_platform_device(info->device)); | ||
583 | 581 | ||
584 | mode = tmiofb_find_mode(info, var); | 582 | mode = tmiofb_find_mode(info, var); |
585 | if (!mode || var->bits_per_pixel > 16) | 583 | if (!mode || var->bits_per_pixel > 16) |
@@ -680,7 +678,7 @@ static struct fb_ops tmiofb_ops = { | |||
680 | static int __devinit tmiofb_probe(struct platform_device *dev) | 678 | static int __devinit tmiofb_probe(struct platform_device *dev) |
681 | { | 679 | { |
682 | const struct mfd_cell *cell = mfd_get_cell(dev); | 680 | const struct mfd_cell *cell = mfd_get_cell(dev); |
683 | struct tmio_fb_data *data = mfd_get_data(dev); | 681 | struct tmio_fb_data *data = dev->dev.platform_data; |
684 | struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); | 682 | struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); |
685 | struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); | 683 | struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); |
686 | struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); | 684 | struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); |
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index 2f4fa02744a5..0855d6cce3c1 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c | |||
@@ -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 = mfd_get_data(ds1wm_data->pdev); | 219 | struct ds1wm_driver_data *plat = ds1wm_data->pdev->dev.platform_data; |
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); |
@@ -351,13 +351,21 @@ static int ds1wm_probe(struct platform_device *pdev) | |||
351 | ret = -ENOMEM; | 351 | ret = -ENOMEM; |
352 | goto err0; | 352 | goto err0; |
353 | } | 353 | } |
354 | plat = mfd_get_data(pdev); | ||
355 | 354 | ||
356 | /* calculate bus shift from mem resource */ | 355 | /* calculate bus shift from mem resource */ |
357 | ds1wm_data->bus_shift = resource_size(res) >> 3; | 356 | ds1wm_data->bus_shift = resource_size(res) >> 3; |
358 | 357 | ||
359 | ds1wm_data->pdev = pdev; | 358 | ds1wm_data->pdev = pdev; |
360 | ds1wm_data->cell = mfd_get_cell(pdev); | 359 | ds1wm_data->cell = mfd_get_cell(pdev); |
360 | if (!ds1wm_data->cell) { | ||
361 | ret = -ENODEV; | ||
362 | goto err1; | ||
363 | } | ||
364 | plat = pdev->dev.platform_data; | ||
365 | if (!plat) { | ||
366 | ret = -ENODEV; | ||
367 | goto err1; | ||
368 | } | ||
361 | 369 | ||
362 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 370 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
363 | if (!res) { | 371 | if (!res) { |
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index d8e725082fdc..428f8a1583e8 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c | |||
@@ -37,7 +37,6 @@ | |||
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> | ||
41 | 40 | ||
42 | #define RDC_WDT_MASK 0x80000000 /* Mask */ | 41 | #define RDC_WDT_MASK 0x80000000 /* Mask */ |
43 | #define RDC_WDT_EN 0x00800000 /* Enable bit */ | 42 | #define RDC_WDT_EN 0x00800000 /* Enable bit */ |
@@ -232,7 +231,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) | |||
232 | struct resource *r; | 231 | struct resource *r; |
233 | struct rdc321x_wdt_pdata *pdata; | 232 | struct rdc321x_wdt_pdata *pdata; |
234 | 233 | ||
235 | pdata = mfd_get_data(pdev); | 234 | pdata = pdev->dev.platform_data; |
236 | if (!pdata) { | 235 | if (!pdata) { |
237 | dev_err(&pdev->dev, "no platform data supplied\n"); | 236 | dev_err(&pdev->dev, "no platform data supplied\n"); |
238 | return -ENODEV; | 237 | return -ENODEV; |
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 0c0d1ae79981..ba4f88624fcd 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
@@ -91,6 +91,7 @@ | |||
91 | #define BCI_INTR_OFFSET 2 | 91 | #define BCI_INTR_OFFSET 2 |
92 | #define MADC_INTR_OFFSET 3 | 92 | #define MADC_INTR_OFFSET 3 |
93 | #define USB_INTR_OFFSET 4 | 93 | #define USB_INTR_OFFSET 4 |
94 | #define CHARGERFAULT_INTR_OFFSET 5 | ||
94 | #define BCI_PRES_INTR_OFFSET 9 | 95 | #define BCI_PRES_INTR_OFFSET 9 |
95 | #define USB_PRES_INTR_OFFSET 10 | 96 | #define USB_PRES_INTR_OFFSET 10 |
96 | #define RTC_INTR_OFFSET 11 | 97 | #define RTC_INTR_OFFSET 11 |
@@ -150,7 +151,12 @@ | |||
150 | #define MMC_PU (0x1 << 3) | 151 | #define MMC_PU (0x1 << 3) |
151 | #define MMC_PD (0x1 << 2) | 152 | #define MMC_PD (0x1 << 2) |
152 | 153 | ||
153 | 154 | #define TWL_SIL_TYPE(rev) ((rev) & 0x00FFFFFF) | |
155 | #define TWL_SIL_REV(rev) ((rev) >> 24) | ||
156 | #define TWL_SIL_5030 0x09002F | ||
157 | #define TWL5030_REV_1_0 0x00 | ||
158 | #define TWL5030_REV_1_1 0x10 | ||
159 | #define TWL5030_REV_1_2 0x30 | ||
154 | 160 | ||
155 | #define TWL4030_CLASS_ID 0x4030 | 161 | #define TWL4030_CLASS_ID 0x4030 |
156 | #define TWL6030_CLASS_ID 0x6030 | 162 | #define TWL6030_CLASS_ID 0x6030 |
@@ -165,6 +171,8 @@ static inline int twl_class_is_ ##class(void) \ | |||
165 | TWL_CLASS_IS(4030, TWL4030_CLASS_ID) | 171 | TWL_CLASS_IS(4030, TWL4030_CLASS_ID) |
166 | TWL_CLASS_IS(6030, TWL6030_CLASS_ID) | 172 | TWL_CLASS_IS(6030, TWL6030_CLASS_ID) |
167 | 173 | ||
174 | #define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */ | ||
175 | |||
168 | /* | 176 | /* |
169 | * Read and write single 8-bit registers | 177 | * Read and write single 8-bit registers |
170 | */ | 178 | */ |
@@ -180,6 +188,9 @@ int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); | |||
180 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | 188 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); |
181 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | 189 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); |
182 | 190 | ||
191 | int twl_get_type(void); | ||
192 | int twl_get_version(void); | ||
193 | |||
183 | int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); | 194 | int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); |
184 | int twl6030_interrupt_mask(u8 bit_mask, u8 offset); | 195 | int twl6030_interrupt_mask(u8 bit_mask, u8 offset); |
185 | 196 | ||
@@ -279,7 +290,12 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | |||
279 | *(Use TWL_4030_MODULE_INTBR) | 290 | *(Use TWL_4030_MODULE_INTBR) |
280 | */ | 291 | */ |
281 | 292 | ||
293 | #define REG_IDCODE_7_0 0x00 | ||
294 | #define REG_IDCODE_15_8 0x01 | ||
295 | #define REG_IDCODE_16_23 0x02 | ||
296 | #define REG_IDCODE_31_24 0x03 | ||
282 | #define REG_GPPUPDCTR1 0x0F | 297 | #define REG_GPPUPDCTR1 0x0F |
298 | #define REG_UNLOCK_TEST_REG 0x12 | ||
283 | 299 | ||
284 | /*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */ | 300 | /*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */ |
285 | 301 | ||
@@ -288,6 +304,8 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | |||
288 | #define SR_I2C_SCL_CTRL_PU BIT(4) | 304 | #define SR_I2C_SCL_CTRL_PU BIT(4) |
289 | #define SR_I2C_SDA_CTRL_PU BIT(6) | 305 | #define SR_I2C_SDA_CTRL_PU BIT(6) |
290 | 306 | ||
307 | #define TWL_EEPROM_R_UNLOCK 0x49 | ||
308 | |||
291 | /*----------------------------------------------------------------------*/ | 309 | /*----------------------------------------------------------------------*/ |
292 | 310 | ||
293 | /* | 311 | /* |
@@ -501,7 +519,7 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | |||
501 | #define RES_32KCLKOUT 26 | 519 | #define RES_32KCLKOUT 26 |
502 | #define RES_RESET 27 | 520 | #define RES_RESET 27 |
503 | /* Power Reference */ | 521 | /* Power Reference */ |
504 | #define RES_Main_Ref 28 | 522 | #define RES_MAIN_REF 28 |
505 | 523 | ||
506 | #define TOTAL_RESOURCES 28 | 524 | #define TOTAL_RESOURCES 28 |
507 | /* | 525 | /* |
@@ -593,6 +611,7 @@ enum twl4030_usb_mode { | |||
593 | 611 | ||
594 | struct twl4030_usb_data { | 612 | struct twl4030_usb_data { |
595 | enum twl4030_usb_mode usb_mode; | 613 | enum twl4030_usb_mode usb_mode; |
614 | unsigned long features; | ||
596 | 615 | ||
597 | int (*phy_init)(struct device *dev); | 616 | int (*phy_init)(struct device *dev); |
598 | int (*phy_exit)(struct device *dev); | 617 | int (*phy_exit)(struct device *dev); |
@@ -699,6 +718,20 @@ struct twl4030_platform_data { | |||
699 | struct regulator_init_data *vcxio; | 718 | struct regulator_init_data *vcxio; |
700 | struct regulator_init_data *vusb; | 719 | struct regulator_init_data *vusb; |
701 | struct regulator_init_data *clk32kg; | 720 | struct regulator_init_data *clk32kg; |
721 | /* TWL6025 LDO regulators */ | ||
722 | struct regulator_init_data *ldo1; | ||
723 | struct regulator_init_data *ldo2; | ||
724 | struct regulator_init_data *ldo3; | ||
725 | struct regulator_init_data *ldo4; | ||
726 | struct regulator_init_data *ldo5; | ||
727 | struct regulator_init_data *ldo6; | ||
728 | struct regulator_init_data *ldo7; | ||
729 | struct regulator_init_data *ldoln; | ||
730 | struct regulator_init_data *ldousb; | ||
731 | /* TWL6025 DCDC regulators */ | ||
732 | struct regulator_init_data *smps3; | ||
733 | struct regulator_init_data *smps4; | ||
734 | struct regulator_init_data *vio6025; | ||
702 | }; | 735 | }; |
703 | 736 | ||
704 | /*----------------------------------------------------------------------*/ | 737 | /*----------------------------------------------------------------------*/ |
@@ -780,4 +813,21 @@ static inline int twl4030charger_usb_en(int enable) { return 0; } | |||
780 | #define TWL6030_REG_VRTC 47 | 813 | #define TWL6030_REG_VRTC 47 |
781 | #define TWL6030_REG_CLK32KG 48 | 814 | #define TWL6030_REG_CLK32KG 48 |
782 | 815 | ||
816 | /* LDOs on 6025 have different names */ | ||
817 | #define TWL6025_REG_LDO2 49 | ||
818 | #define TWL6025_REG_LDO4 50 | ||
819 | #define TWL6025_REG_LDO3 51 | ||
820 | #define TWL6025_REG_LDO5 52 | ||
821 | #define TWL6025_REG_LDO1 53 | ||
822 | #define TWL6025_REG_LDO7 54 | ||
823 | #define TWL6025_REG_LDO6 55 | ||
824 | #define TWL6025_REG_LDOLN 56 | ||
825 | #define TWL6025_REG_LDOUSB 57 | ||
826 | |||
827 | /* 6025 DCDC supplies */ | ||
828 | #define TWL6025_REG_SMPS3 58 | ||
829 | #define TWL6025_REG_SMPS4 59 | ||
830 | #define TWL6025_REG_VIO 60 | ||
831 | |||
832 | |||
783 | #endif /* End of __TWL4030_H */ | 833 | #endif /* End of __TWL4030_H */ |
diff --git a/include/linux/input/pmic8xxx-keypad.h b/include/linux/input/pmic8xxx-keypad.h new file mode 100644 index 000000000000..5f1e2f9ad959 --- /dev/null +++ b/include/linux/input/pmic8xxx-keypad.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* Copyright (c) 2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #ifndef __PMIC8XXX_KEYPAD_H__ | ||
14 | #define __PMIC8XXX_KEYPAD_H__ | ||
15 | |||
16 | #include <linux/input/matrix_keypad.h> | ||
17 | |||
18 | #define PM8XXX_KEYPAD_DEV_NAME "pm8xxx-keypad" | ||
19 | |||
20 | /** | ||
21 | * struct pm8xxx_keypad_platform_data - platform data for keypad | ||
22 | * @keymap_data - matrix keymap data | ||
23 | * @input_name - input device name | ||
24 | * @input_phys_device - input device name | ||
25 | * @num_cols - number of columns of keypad | ||
26 | * @num_rows - number of row of keypad | ||
27 | * @debounce_ms - debounce period in milliseconds | ||
28 | * @scan_delay_ms - scan delay in milliseconds | ||
29 | * @row_hold_ns - row hold period in nanoseconds | ||
30 | * @wakeup - configure keypad as wakeup | ||
31 | * @rep - enable or disable key repeat bit | ||
32 | */ | ||
33 | struct pm8xxx_keypad_platform_data { | ||
34 | const struct matrix_keymap_data *keymap_data; | ||
35 | |||
36 | const char *input_name; | ||
37 | const char *input_phys_device; | ||
38 | |||
39 | unsigned int num_cols; | ||
40 | unsigned int num_rows; | ||
41 | unsigned int rows_gpio_start; | ||
42 | unsigned int cols_gpio_start; | ||
43 | |||
44 | unsigned int debounce_ms; | ||
45 | unsigned int scan_delay_ms; | ||
46 | unsigned int row_hold_ns; | ||
47 | |||
48 | bool wakeup; | ||
49 | bool rep; | ||
50 | }; | ||
51 | |||
52 | #endif /*__PMIC8XXX_KEYPAD_H__ */ | ||
diff --git a/include/linux/input/pmic8xxx-pwrkey.h b/include/linux/input/pmic8xxx-pwrkey.h new file mode 100644 index 000000000000..6d2974e57109 --- /dev/null +++ b/include/linux/input/pmic8xxx-pwrkey.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #ifndef __PMIC8XXX_PWRKEY_H__ | ||
14 | #define __PMIC8XXX_PWRKEY_H__ | ||
15 | |||
16 | #define PM8XXX_PWRKEY_DEV_NAME "pm8xxx-pwrkey" | ||
17 | |||
18 | /** | ||
19 | * struct pm8xxx_pwrkey_platform_data - platform data for pwrkey driver | ||
20 | * @pull up: power on register control for pull up/down configuration | ||
21 | * @kpd_trigger_delay_us: time delay for power key state change interrupt | ||
22 | * trigger. | ||
23 | * @wakeup: configure power key as wakeup source | ||
24 | */ | ||
25 | struct pm8xxx_pwrkey_platform_data { | ||
26 | bool pull_up; | ||
27 | u32 kpd_trigger_delay_us; | ||
28 | u32 wakeup; | ||
29 | }; | ||
30 | |||
31 | #endif /* __PMIC8XXX_PWRKEY_H__ */ | ||
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h index 8fba7972ff5f..63b4fb8e3b6f 100644 --- a/include/linux/mfd/88pm860x.h +++ b/include/linux/mfd/88pm860x.h | |||
@@ -330,6 +330,11 @@ struct pm860x_led_pdata { | |||
330 | unsigned long flags; | 330 | unsigned long flags; |
331 | }; | 331 | }; |
332 | 332 | ||
333 | struct pm860x_rtc_pdata { | ||
334 | int (*sync)(unsigned int ticks); | ||
335 | int vrtc; | ||
336 | }; | ||
337 | |||
333 | struct pm860x_touch_pdata { | 338 | struct pm860x_touch_pdata { |
334 | int gpadc_prebias; | 339 | int gpadc_prebias; |
335 | int slot_cycle; | 340 | int slot_cycle; |
@@ -349,6 +354,7 @@ struct pm860x_power_pdata { | |||
349 | struct pm860x_platform_data { | 354 | struct pm860x_platform_data { |
350 | struct pm860x_backlight_pdata *backlight; | 355 | struct pm860x_backlight_pdata *backlight; |
351 | struct pm860x_led_pdata *led; | 356 | struct pm860x_led_pdata *led; |
357 | struct pm860x_rtc_pdata *rtc; | ||
352 | struct pm860x_touch_pdata *touch; | 358 | struct pm860x_touch_pdata *touch; |
353 | struct pm860x_power_pdata *power; | 359 | struct pm860x_power_pdata *power; |
354 | struct regulator_init_data *regulator; | 360 | struct regulator_init_data *regulator; |
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 7d9b6ae1c203..896b5e47f16e 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h | |||
@@ -34,6 +34,13 @@ | |||
34 | #define AB5500_2_0 0x21 | 34 | #define AB5500_2_0 0x21 |
35 | #define AB5500_2_1 0x22 | 35 | #define AB5500_2_1 0x22 |
36 | 36 | ||
37 | /* AB8500 CIDs*/ | ||
38 | #define AB8500_CUTEARLY 0x00 | ||
39 | #define AB8500_CUT1P0 0x10 | ||
40 | #define AB8500_CUT1P1 0x11 | ||
41 | #define AB8500_CUT2P0 0x20 | ||
42 | #define AB8500_CUT3P0 0x30 | ||
43 | |||
37 | /* | 44 | /* |
38 | * AB3100, EVENTA1, A2 and A3 event register flags | 45 | * AB3100, EVENTA1, A2 and A3 event register flags |
39 | * these are catenated into a single 32-bit flag in the code | 46 | * these are catenated into a single 32-bit flag in the code |
@@ -186,6 +193,7 @@ struct abx500_init_settings { | |||
186 | struct ab3550_platform_data { | 193 | struct ab3550_platform_data { |
187 | struct {unsigned int base; unsigned int count; } irq; | 194 | struct {unsigned int base; unsigned int count; } irq; |
188 | void *dev_data[AB3550_NUM_DEVICES]; | 195 | void *dev_data[AB3550_NUM_DEVICES]; |
196 | size_t dev_data_sz[AB3550_NUM_DEVICES]; | ||
189 | struct abx500_init_settings *init_settings; | 197 | struct abx500_init_settings *init_settings; |
190 | unsigned int init_settings_sz; | 198 | unsigned int init_settings_sz; |
191 | }; | 199 | }; |
diff --git a/include/linux/mfd/asic3.h b/include/linux/mfd/asic3.h index de3c4ad19afb..ed793b77a1c5 100644 --- a/include/linux/mfd/asic3.h +++ b/include/linux/mfd/asic3.h | |||
@@ -16,6 +16,13 @@ | |||
16 | 16 | ||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | 18 | ||
19 | struct led_classdev; | ||
20 | struct asic3_led { | ||
21 | const char *name; | ||
22 | const char *default_trigger; | ||
23 | struct led_classdev *cdev; | ||
24 | }; | ||
25 | |||
19 | struct asic3_platform_data { | 26 | struct asic3_platform_data { |
20 | u16 *gpio_config; | 27 | u16 *gpio_config; |
21 | unsigned int gpio_config_num; | 28 | unsigned int gpio_config_num; |
@@ -23,6 +30,8 @@ struct asic3_platform_data { | |||
23 | unsigned int irq_base; | 30 | unsigned int irq_base; |
24 | 31 | ||
25 | unsigned int gpio_base; | 32 | unsigned int gpio_base; |
33 | |||
34 | struct asic3_led *leds; | ||
26 | }; | 35 | }; |
27 | 36 | ||
28 | #define ASIC3_NUM_GPIO_BANKS 4 | 37 | #define ASIC3_NUM_GPIO_BANKS 4 |
@@ -111,9 +120,9 @@ struct asic3_platform_data { | |||
111 | #define ASIC3_GPIOA11_PWM0 ASIC3_CONFIG_GPIO(11, 1, 1, 0) | 120 | #define ASIC3_GPIOA11_PWM0 ASIC3_CONFIG_GPIO(11, 1, 1, 0) |
112 | #define ASIC3_GPIOA12_PWM1 ASIC3_CONFIG_GPIO(12, 1, 1, 0) | 121 | #define ASIC3_GPIOA12_PWM1 ASIC3_CONFIG_GPIO(12, 1, 1, 0) |
113 | #define ASIC3_GPIOA15_CONTROL_CX ASIC3_CONFIG_GPIO(15, 1, 1, 0) | 122 | #define ASIC3_GPIOA15_CONTROL_CX ASIC3_CONFIG_GPIO(15, 1, 1, 0) |
114 | #define ASIC3_GPIOC0_LED0 ASIC3_CONFIG_GPIO(32, 1, 1, 0) | 123 | #define ASIC3_GPIOC0_LED0 ASIC3_CONFIG_GPIO(32, 1, 0, 0) |
115 | #define ASIC3_GPIOC1_LED1 ASIC3_CONFIG_GPIO(33, 1, 1, 0) | 124 | #define ASIC3_GPIOC1_LED1 ASIC3_CONFIG_GPIO(33, 1, 0, 0) |
116 | #define ASIC3_GPIOC2_LED2 ASIC3_CONFIG_GPIO(34, 1, 1, 0) | 125 | #define ASIC3_GPIOC2_LED2 ASIC3_CONFIG_GPIO(34, 1, 0, 0) |
117 | #define ASIC3_GPIOC3_SPI_RXD ASIC3_CONFIG_GPIO(35, 1, 0, 0) | 126 | #define ASIC3_GPIOC3_SPI_RXD ASIC3_CONFIG_GPIO(35, 1, 0, 0) |
118 | #define ASIC3_GPIOC4_CF_nCD ASIC3_CONFIG_GPIO(36, 1, 0, 0) | 127 | #define ASIC3_GPIOC4_CF_nCD ASIC3_CONFIG_GPIO(36, 1, 0, 0) |
119 | #define ASIC3_GPIOC4_SPI_TXD ASIC3_CONFIG_GPIO(36, 1, 1, 0) | 128 | #define ASIC3_GPIOC4_SPI_TXD ASIC3_CONFIG_GPIO(36, 1, 1, 0) |
@@ -152,6 +161,7 @@ struct asic3_platform_data { | |||
152 | #define PWM_TIMEBASE_VALUE(x) ((x)&0xf) /* Low 4 bits sets time base */ | 161 | #define PWM_TIMEBASE_VALUE(x) ((x)&0xf) /* Low 4 bits sets time base */ |
153 | #define PWM_TIMEBASE_ENABLE (1 << 4) /* Enable clock */ | 162 | #define PWM_TIMEBASE_ENABLE (1 << 4) /* Enable clock */ |
154 | 163 | ||
164 | #define ASIC3_NUM_LEDS 3 | ||
155 | #define ASIC3_LED_0_Base 0x0700 | 165 | #define ASIC3_LED_0_Base 0x0700 |
156 | #define ASIC3_LED_1_Base 0x0800 | 166 | #define ASIC3_LED_1_Base 0x0800 |
157 | #define ASIC3_LED_2_Base 0x0900 | 167 | #define ASIC3_LED_2_Base 0x0900 |
@@ -287,10 +297,17 @@ struct asic3_platform_data { | |||
287 | * | 297 | * |
288 | *****************************************************************************/ | 298 | *****************************************************************************/ |
289 | #define ASIC3_SD_CONFIG_BASE 0x0400 /* Assumes 32 bit addressing */ | 299 | #define ASIC3_SD_CONFIG_BASE 0x0400 /* Assumes 32 bit addressing */ |
300 | #define ASIC3_SD_CONFIG_SIZE 0x0200 /* Assumes 32 bit addressing */ | ||
290 | #define ASIC3_SD_CTRL_BASE 0x1000 | 301 | #define ASIC3_SD_CTRL_BASE 0x1000 |
291 | #define ASIC3_SDIO_CTRL_BASE 0x1200 | 302 | #define ASIC3_SDIO_CTRL_BASE 0x1200 |
292 | 303 | ||
293 | #define ASIC3_MAP_SIZE_32BIT 0x2000 | 304 | #define ASIC3_MAP_SIZE_32BIT 0x2000 |
294 | #define ASIC3_MAP_SIZE_16BIT 0x1000 | 305 | #define ASIC3_MAP_SIZE_16BIT 0x1000 |
295 | 306 | ||
307 | /* Functions needed by leds-asic3 */ | ||
308 | |||
309 | struct asic3; | ||
310 | extern void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 val); | ||
311 | extern u32 asic3_read_register(struct asic3 *asic, unsigned int reg); | ||
312 | |||
296 | #endif /* __ASIC3_H__ */ | 313 | #endif /* __ASIC3_H__ */ |
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index aef23309a742..4e76163dd862 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h | |||
@@ -33,8 +33,9 @@ struct mfd_cell { | |||
33 | int (*suspend)(struct platform_device *dev); | 33 | int (*suspend)(struct platform_device *dev); |
34 | int (*resume)(struct platform_device *dev); | 34 | int (*resume)(struct platform_device *dev); |
35 | 35 | ||
36 | /* mfd_data can be used to pass data to client drivers */ | 36 | /* platform data passed to the sub devices drivers */ |
37 | void *mfd_data; | 37 | void *platform_data; |
38 | size_t pdata_size; | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * These resources can be specified relative to the parent device. | 41 | * These resources can be specified relative to the parent device. |
@@ -89,24 +90,6 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) | |||
89 | return pdev->mfd_cell; | 90 | return pdev->mfd_cell; |
90 | } | 91 | } |
91 | 92 | ||
92 | /* | ||
93 | * Given a platform device that's been created by mfd_add_devices(), fetch | ||
94 | * the .mfd_data entry from the mfd_cell that created it. | ||
95 | * Otherwise just return the platform_data pointer. | ||
96 | * This maintains compatibility with platform drivers whose devices aren't | ||
97 | * created by the mfd layer, and expect platform_data to contain what would've | ||
98 | * otherwise been in mfd_data. | ||
99 | */ | ||
100 | static inline void *mfd_get_data(struct platform_device *pdev) | ||
101 | { | ||
102 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
103 | |||
104 | if (cell) | ||
105 | return cell->mfd_data; | ||
106 | else | ||
107 | return pdev->dev.platform_data; | ||
108 | } | ||
109 | |||
110 | extern int mfd_add_devices(struct device *parent, int id, | 93 | extern int mfd_add_devices(struct device *parent, int id, |
111 | struct mfd_cell *cells, int n_devs, | 94 | struct mfd_cell *cells, int n_devs, |
112 | struct resource *mem_base, | 95 | struct resource *mem_base, |
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h new file mode 100644 index 000000000000..bd2f4f64e931 --- /dev/null +++ b/include/linux/mfd/pm8xxx/core.h | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | /* | ||
14 | * Qualcomm PMIC 8xxx driver header file | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __MFD_PM8XXX_CORE_H | ||
19 | #define __MFD_PM8XXX_CORE_H | ||
20 | |||
21 | #include <linux/mfd/core.h> | ||
22 | |||
23 | struct pm8xxx_drvdata { | ||
24 | int (*pmic_readb) (const struct device *dev, u16 addr, u8 *val); | ||
25 | int (*pmic_writeb) (const struct device *dev, u16 addr, u8 val); | ||
26 | int (*pmic_read_buf) (const struct device *dev, u16 addr, u8 *buf, | ||
27 | int n); | ||
28 | int (*pmic_write_buf) (const struct device *dev, u16 addr, u8 *buf, | ||
29 | int n); | ||
30 | int (*pmic_read_irq_stat) (const struct device *dev, int irq); | ||
31 | void *pm_chip_data; | ||
32 | }; | ||
33 | |||
34 | static inline int pm8xxx_readb(const struct device *dev, u16 addr, u8 *val) | ||
35 | { | ||
36 | struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); | ||
37 | |||
38 | if (!dd) | ||
39 | return -EINVAL; | ||
40 | return dd->pmic_readb(dev, addr, val); | ||
41 | } | ||
42 | |||
43 | static inline int pm8xxx_writeb(const struct device *dev, u16 addr, u8 val) | ||
44 | { | ||
45 | struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); | ||
46 | |||
47 | if (!dd) | ||
48 | return -EINVAL; | ||
49 | return dd->pmic_writeb(dev, addr, val); | ||
50 | } | ||
51 | |||
52 | static inline int pm8xxx_read_buf(const struct device *dev, u16 addr, u8 *buf, | ||
53 | int n) | ||
54 | { | ||
55 | struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); | ||
56 | |||
57 | if (!dd) | ||
58 | return -EINVAL; | ||
59 | return dd->pmic_read_buf(dev, addr, buf, n); | ||
60 | } | ||
61 | |||
62 | static inline int pm8xxx_write_buf(const struct device *dev, u16 addr, u8 *buf, | ||
63 | int n) | ||
64 | { | ||
65 | struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); | ||
66 | |||
67 | if (!dd) | ||
68 | return -EINVAL; | ||
69 | return dd->pmic_write_buf(dev, addr, buf, n); | ||
70 | } | ||
71 | |||
72 | static inline int pm8xxx_read_irq_stat(const struct device *dev, int irq) | ||
73 | { | ||
74 | struct pm8xxx_drvdata *dd = dev_get_drvdata(dev); | ||
75 | |||
76 | if (!dd) | ||
77 | return -EINVAL; | ||
78 | return dd->pmic_read_irq_stat(dev, irq); | ||
79 | } | ||
80 | |||
81 | #endif | ||
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h new file mode 100644 index 000000000000..4b21769f4483 --- /dev/null +++ b/include/linux/mfd/pm8xxx/irq.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | /* | ||
14 | * Qualcomm PMIC irq 8xxx driver header file | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __MFD_PM8XXX_IRQ_H | ||
19 | #define __MFD_PM8XXX_IRQ_H | ||
20 | |||
21 | #include <linux/errno.h> | ||
22 | #include <linux/err.h> | ||
23 | |||
24 | struct pm8xxx_irq_core_data { | ||
25 | u32 rev; | ||
26 | int nirqs; | ||
27 | }; | ||
28 | |||
29 | struct pm8xxx_irq_platform_data { | ||
30 | int irq_base; | ||
31 | struct pm8xxx_irq_core_data irq_cdata; | ||
32 | int devirq; | ||
33 | int irq_trigger_flag; | ||
34 | }; | ||
35 | |||
36 | struct pm_irq_chip; | ||
37 | |||
38 | #ifdef CONFIG_MFD_PM8XXX_IRQ | ||
39 | int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq); | ||
40 | struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev, | ||
41 | const struct pm8xxx_irq_platform_data *pdata); | ||
42 | int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip); | ||
43 | #else | ||
44 | static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq) | ||
45 | { | ||
46 | return -ENXIO; | ||
47 | } | ||
48 | static inline struct pm_irq_chip * __devinit pm8xxx_irq_init( | ||
49 | const struct device *dev, | ||
50 | const struct pm8xxx_irq_platform_data *pdata) | ||
51 | { | ||
52 | return ERR_PTR(-ENXIO); | ||
53 | } | ||
54 | static inline int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip) | ||
55 | { | ||
56 | return -ENXIO; | ||
57 | } | ||
58 | #endif /* CONFIG_MFD_PM8XXX_IRQ */ | ||
59 | #endif /* __MFD_PM8XXX_IRQ_H */ | ||
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h new file mode 100644 index 000000000000..d5517fd32d1b --- /dev/null +++ b/include/linux/mfd/pm8xxx/pm8921.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | /* | ||
14 | * Qualcomm PMIC 8921 driver header file | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __MFD_PM8921_H | ||
19 | #define __MFD_PM8921_H | ||
20 | |||
21 | #include <linux/device.h> | ||
22 | #include <linux/mfd/pm8xxx/irq.h> | ||
23 | |||
24 | #define PM8921_NR_IRQS 256 | ||
25 | |||
26 | struct pm8921_platform_data { | ||
27 | int irq_base; | ||
28 | struct pm8xxx_irq_platform_data *irq_pdata; | ||
29 | }; | ||
30 | |||
31 | #endif | ||
diff --git a/include/linux/mfd/twl4030-codec.h b/include/linux/mfd/twl4030-codec.h index 2ec317c68e59..5cc16bbd1da1 100644 --- a/include/linux/mfd/twl4030-codec.h +++ b/include/linux/mfd/twl4030-codec.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MFD driver for twl4030 codec submodule | 2 | * MFD driver for twl4030 codec submodule |
3 | * | 3 | * |
4 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | 4 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> |
5 | * | 5 | * |
6 | * Copyright: (C) 2009 Nokia Corporation | 6 | * Copyright: (C) 2009 Nokia Corporation |
7 | * | 7 | * |
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 903280d21866..0d515ee1c247 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h | |||
@@ -301,30 +301,4 @@ int wm831x_device_suspend(struct wm831x *wm831x); | |||
301 | int wm831x_irq_init(struct wm831x *wm831x, int irq); | 301 | int wm831x_irq_init(struct wm831x *wm831x, int irq); |
302 | void wm831x_irq_exit(struct wm831x *wm831x); | 302 | void wm831x_irq_exit(struct wm831x *wm831x); |
303 | 303 | ||
304 | static inline int __must_check wm831x_request_irq(struct wm831x *wm831x, | ||
305 | unsigned int irq, | ||
306 | irq_handler_t handler, | ||
307 | unsigned long flags, | ||
308 | const char *name, | ||
309 | void *dev) | ||
310 | { | ||
311 | return request_threaded_irq(irq, NULL, handler, flags, name, dev); | ||
312 | } | ||
313 | |||
314 | static inline void wm831x_free_irq(struct wm831x *wm831x, | ||
315 | unsigned int irq, void *dev) | ||
316 | { | ||
317 | free_irq(irq, dev); | ||
318 | } | ||
319 | |||
320 | static inline void wm831x_disable_irq(struct wm831x *wm831x, int irq) | ||
321 | { | ||
322 | disable_irq(irq); | ||
323 | } | ||
324 | |||
325 | static inline void wm831x_enable_irq(struct wm831x *wm831x, int irq) | ||
326 | { | ||
327 | enable_irq(irq); | ||
328 | } | ||
329 | |||
330 | #endif | 304 | #endif |
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 632d1567a1b6..ff42d700293f 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h | |||
@@ -105,6 +105,9 @@ struct wm831x_watchdog_pdata { | |||
105 | #define WM831X_MAX_LDO 11 | 105 | #define WM831X_MAX_LDO 11 |
106 | #define WM831X_MAX_ISINK 2 | 106 | #define WM831X_MAX_ISINK 2 |
107 | 107 | ||
108 | #define WM831X_GPIO_CONFIGURE 0x10000 | ||
109 | #define WM831X_GPIO_NUM 16 | ||
110 | |||
108 | struct wm831x_pdata { | 111 | struct wm831x_pdata { |
109 | /** Used to distinguish multiple WM831x chips */ | 112 | /** Used to distinguish multiple WM831x chips */ |
110 | int wm831x_num; | 113 | int wm831x_num; |
@@ -119,6 +122,7 @@ struct wm831x_pdata { | |||
119 | 122 | ||
120 | int irq_base; | 123 | int irq_base; |
121 | int gpio_base; | 124 | int gpio_base; |
125 | int gpio_defaults[WM831X_GPIO_NUM]; | ||
122 | struct wm831x_backlight_pdata *backlight; | 126 | struct wm831x_backlight_pdata *backlight; |
123 | struct wm831x_backup_pdata *backup; | 127 | struct wm831x_backup_pdata *backup; |
124 | struct wm831x_battery_pdata *battery; | 128 | struct wm831x_battery_pdata *battery; |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index b8066ef10bb0..46dbfd067f79 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -153,8 +153,7 @@ 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 = | 156 | struct davinci_vc *davinci_vc = codec->dev->platform_data; |
157 | mfd_get_data(to_platform_device(codec->dev)); | ||
158 | 157 | ||
159 | davinci_vc->cq93vc.codec = codec; | 158 | davinci_vc->cq93vc.codec = codec; |
160 | codec->control_data = davinci_vc; | 159 | codec->control_data = davinci_vc; |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 575238d68e5e..bec788b12613 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -26,7 +26,6 @@ | |||
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> | ||
30 | #include <linux/i2c/twl.h> | 29 | #include <linux/i2c/twl.h> |
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
32 | #include <sound/core.h> | 31 | #include <sound/core.h> |
@@ -733,8 +732,7 @@ static int aif_event(struct snd_soc_dapm_widget *w, | |||
733 | 732 | ||
734 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 733 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
735 | { | 734 | { |
736 | struct twl4030_codec_audio_data *pdata = | 735 | struct twl4030_codec_audio_data *pdata = codec->dev->platform_data; |
737 | mfd_get_data(to_platform_device(codec->dev)); | ||
738 | unsigned char hs_gain, hs_pop; | 736 | unsigned char hs_gain, hs_pop; |
739 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 737 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
740 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ | 738 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ |
@@ -2299,7 +2297,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | |||
2299 | 2297 | ||
2300 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) | 2298 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) |
2301 | { | 2299 | { |
2302 | struct twl4030_codec_audio_data *pdata = mfd_get_data(pdev); | 2300 | struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; |
2303 | 2301 | ||
2304 | if (!pdata) { | 2302 | if (!pdata) { |
2305 | dev_err(&pdev->dev, "platform_data is missing\n"); | 2303 | dev_err(&pdev->dev, "platform_data is missing\n"); |
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index c8a874d0d4ca..5836201834d9 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c | |||
@@ -441,8 +441,7 @@ EXPORT_SYMBOL_GPL(wl1273_get_format); | |||
441 | 441 | ||
442 | static int wl1273_probe(struct snd_soc_codec *codec) | 442 | static int wl1273_probe(struct snd_soc_codec *codec) |
443 | { | 443 | { |
444 | struct wl1273_core **core = | 444 | struct wl1273_core **core = codec->dev->platform_data; |
445 | mfd_get_data(to_platform_device(codec->dev)); | ||
446 | struct wl1273_priv *wl1273; | 445 | struct wl1273_priv *wl1273; |
447 | int r; | 446 | int r; |
448 | 447 | ||
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 736b785e3756..fbee556cbf35 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -1378,7 +1378,7 @@ static void wm8400_probe_deferred(struct work_struct *work) | |||
1378 | 1378 | ||
1379 | static int wm8400_codec_probe(struct snd_soc_codec *codec) | 1379 | static int wm8400_codec_probe(struct snd_soc_codec *codec) |
1380 | { | 1380 | { |
1381 | struct wm8400 *wm8400 = mfd_get_data(to_platform_device(codec->dev)); | 1381 | struct wm8400 *wm8400 = dev_get_platdata(codec->dev); |
1382 | struct wm8400_priv *priv; | 1382 | struct wm8400_priv *priv; |
1383 | int ret; | 1383 | int ret; |
1384 | u16 reg; | 1384 | u16 reg; |
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 13e05a302a92..9259f1f34899 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 = mfd_get_data(pdev); | 208 | struct davinci_vc *davinci_vc = pdev->dev.platform_data; |
209 | struct davinci_vcif_dev *davinci_vcif_dev; | 209 | struct davinci_vcif_dev *davinci_vcif_dev; |
210 | int ret; | 210 | int ret; |
211 | 211 | ||