aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-03-07 18:56:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-07 18:56:04 -0500
commit6dc3eb5c1f96641cda7056aa34393e317076d6cf (patch)
tree9a615b884d7ff5375382b5a3f020f518f618c589 /drivers
parent8fe900b8c7aa6a307e552ff776e0c04c28dcf9c8 (diff)
parent2c08583c6a6b4c5f5dea4cb0931eca82af7db6fe (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (66 commits) mfd: Fix ucb1x00 build failure for collie_defconfig mfd: Fix lpc_sch related depends/selects, fix build error gpio: Fix sch_gpio warning gpio: add Intel SCH GPIO controller driver i2c: convert i2c-isch to platform_device mfd: Use completion interrupt for WM831x AUXADC mfd: Use completion interrupt for WM835x AUXADC mfd: Introduce remove_script function for twl4030 mfd/mmc: SDHI Kconfig update mfd: sh_mobile_sdhi MMC_CAP_MMC_HIGHSPEED support gpiolib: Force wm831x GPIOs into GPIO mode when requested mfd: Add WM831x revision B support gpiolib: Correct debugfs display of WM831x GPIO inversion gpiolib: Actually set output state in wm831x_gpio_direction_output() tmio_mmc: Balance cell enable()/disable() calls tmio_mmc: Remove const from platform data V3 tmio_mmc: Use 100ms mmc_detect_change() delay tmio_mmc: Add MMC_CAP_MMC_HIGHSPEED support V2 tmio_mmc: Keep card-detect interrupts enabled mfd: Add twl6030 base addr for ID0, ID1, ID2 ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig31
-rw-r--r--drivers/gpio/Makefile3
-rw-r--r--drivers/gpio/sch_gpio.c295
-rw-r--r--drivers/gpio/wm831x-gpio.c45
-rw-r--r--drivers/gpio/wm8350-gpiolib.c181
-rw-r--r--drivers/gpio/wm8994-gpio.c204
-rw-r--r--drivers/i2c/busses/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-isch.c68
-rw-r--r--drivers/input/misc/88pm860x_onkey.c155
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/touchscreen/88pm860x-ts.c236
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-88pm860x.c325
-rw-r--r--drivers/mfd/88pm8607.c302
-rw-r--r--drivers/mfd/88pm860x-core.c740
-rw-r--r--drivers/mfd/88pm860x-i2c.c236
-rw-r--r--drivers/mfd/Kconfig72
-rw-r--r--drivers/mfd/Makefile8
-rw-r--r--drivers/mfd/ab3100-core.c54
-rw-r--r--drivers/mfd/ab3100-otp.c13
-rw-r--r--drivers/mfd/htc-i2cpld.c710
-rw-r--r--drivers/mfd/lpc_sch.c133
-rw-r--r--drivers/mfd/max8925-core.c656
-rw-r--r--drivers/mfd/max8925-i2c.c211
-rw-r--r--drivers/mfd/mfd-core.c5
-rw-r--r--drivers/mfd/sh_mobile_sdhi.c6
-rw-r--r--drivers/mfd/sm501.c7
-rw-r--r--drivers/mfd/t7l66xb.c4
-rw-r--r--drivers/mfd/tc6393xb.c2
-rw-r--r--drivers/mfd/twl-core.c41
-rw-r--r--drivers/mfd/twl4030-power.c52
-rw-r--r--drivers/mfd/ucb1x00-core.c1
-rw-r--r--drivers/mfd/wm831x-core.c51
-rw-r--r--drivers/mfd/wm8350-core.c35
-rw-r--r--drivers/mfd/wm8350-irq.c155
-rw-r--r--drivers/mfd/wm8994-core.c537
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/mmc/host/tmio_mmc.c13
-rw-r--r--drivers/mmc/host/tmio_mmc.h6
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/max8925_power.c534
-rw-r--r--drivers/power/wm8350_power.c26
-rw-r--r--drivers/regulator/88pm8607.c318
-rw-r--r--drivers/regulator/Kconfig8
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/max8925-regulator.c306
-rw-r--r--drivers/regulator/wm8350-regulator.c2
-rw-r--r--drivers/rtc/Kconfig10
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-max8925.c314
-rw-r--r--drivers/rtc/rtc-wm8350.c11
-rw-r--r--drivers/video/backlight/88pm860x_bl.c304
-rw-r--r--drivers/video/backlight/Kconfig13
-rw-r--r--drivers/video/backlight/Makefile2
-rw-r--r--drivers/video/backlight/max8925_bl.c200
60 files changed, 6907 insertions, 780 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a4cdbd51b1c6..fee678f74a19 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -94,6 +94,23 @@ config GPIO_VR41XX
94 help 94 help
95 Say yes here to support the NEC VR4100 series General-purpose I/O Uint 95 Say yes here to support the NEC VR4100 series General-purpose I/O Uint
96 96
97config GPIO_SCH
98 tristate "Intel SCH GPIO"
99 depends on GPIOLIB && PCI
100 select MFD_CORE
101 select LPC_SCH
102 help
103 Say yes here to support GPIO interface on Intel Poulsbo SCH.
104 The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
105 powered by the core power rail and are turned off during sleep
106 modes (S3 and higher). The remaining four GPIOs are powered by
107 the Intel SCH suspend power supply. These GPIOs remain
108 active during S3. The suspend powered GPIOs can be used to wake the
109 system from the Suspend-to-RAM state.
110
111 This driver can also be built as a module. If so, the module
112 will be called sch-gpio.
113
97comment "I2C GPIO expanders:" 114comment "I2C GPIO expanders:"
98 115
99config GPIO_MAX7300 116config GPIO_MAX7300
@@ -185,6 +202,20 @@ config GPIO_WM831X
185 Say yes here to access the GPIO signals of WM831x power management 202 Say yes here to access the GPIO signals of WM831x power management
186 chips from Wolfson Microelectronics. 203 chips from Wolfson Microelectronics.
187 204
205config GPIO_WM8350
206 tristate "WM8350 GPIOs"
207 depends on MFD_WM8350
208 help
209 Say yes here to access the GPIO signals of WM8350 power management
210 chips from Wolfson Microelectronics.
211
212config GPIO_WM8994
213 tristate "WM8994 GPIOs"
214 depends on MFD_WM8994
215 help
216 Say yes here to access the GPIO signals of WM8994 audio hub
217 CODECs from Wolfson Microelectronics.
218
188config GPIO_ADP5520 219config GPIO_ADP5520
189 tristate "GPIO Support for ADP5520 PMIC" 220 tristate "GPIO Support for ADP5520 PMIC"
190 depends on PMIC_ADP5520 221 depends on PMIC_ADP5520
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 128abf8a98da..10f3f8d958b1 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -25,3 +25,6 @@ obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
25obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o 25obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o
26obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o 26obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
27obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o 27obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
28obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
29obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o
30obj-$(CONFIG_GPIO_SCH) += sch_gpio.o \ No newline at end of file
diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/sch_gpio.c
new file mode 100644
index 000000000000..583521352c16
--- /dev/null
+++ b/drivers/gpio/sch_gpio.c
@@ -0,0 +1,295 @@
1/*
2 * sch_gpio.c - GPIO interface for Intel Poulsbo SCH
3 *
4 * Copyright (c) 2010 CompuLab Ltd
5 * Author: Denis Turischev <denis@compulab.co.il>
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 2 as published
9 * by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING. If not, write to
18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/io.h>
25#include <linux/errno.h>
26#include <linux/acpi.h>
27#include <linux/platform_device.h>
28
29#include <linux/gpio.h>
30
31static DEFINE_SPINLOCK(gpio_lock);
32
33#define CGEN (0x00)
34#define CGIO (0x04)
35#define CGLV (0x08)
36
37#define RGEN (0x20)
38#define RGIO (0x24)
39#define RGLV (0x28)
40
41static unsigned short gpio_ba;
42
43static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num)
44{
45 u8 curr_dirs;
46 unsigned short offset, bit;
47
48 spin_lock(&gpio_lock);
49
50 offset = CGIO + gpio_num / 8;
51 bit = gpio_num % 8;
52
53 curr_dirs = inb(gpio_ba + offset);
54
55 if (!(curr_dirs & (1 << bit)))
56 outb(curr_dirs | (1 << bit), gpio_ba + offset);
57
58 spin_unlock(&gpio_lock);
59 return 0;
60}
61
62static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
63{
64 int res;
65 unsigned short offset, bit;
66
67 offset = CGLV + gpio_num / 8;
68 bit = gpio_num % 8;
69
70 res = !!(inb(gpio_ba + offset) & (1 << bit));
71 return res;
72}
73
74static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
75{
76 u8 curr_vals;
77 unsigned short offset, bit;
78
79 spin_lock(&gpio_lock);
80
81 offset = CGLV + gpio_num / 8;
82 bit = gpio_num % 8;
83
84 curr_vals = inb(gpio_ba + offset);
85
86 if (val)
87 outb(curr_vals | (1 << bit), gpio_ba + offset);
88 else
89 outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
90 spin_unlock(&gpio_lock);
91}
92
93static int sch_gpio_core_direction_out(struct gpio_chip *gc,
94 unsigned gpio_num, int val)
95{
96 u8 curr_dirs;
97 unsigned short offset, bit;
98
99 sch_gpio_core_set(gc, gpio_num, val);
100
101 spin_lock(&gpio_lock);
102
103 offset = CGIO + gpio_num / 8;
104 bit = gpio_num % 8;
105
106 curr_dirs = inb(gpio_ba + offset);
107 if (curr_dirs & (1 << bit))
108 outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
109
110 spin_unlock(&gpio_lock);
111 return 0;
112}
113
114static struct gpio_chip sch_gpio_core = {
115 .label = "sch_gpio_core",
116 .owner = THIS_MODULE,
117 .direction_input = sch_gpio_core_direction_in,
118 .get = sch_gpio_core_get,
119 .direction_output = sch_gpio_core_direction_out,
120 .set = sch_gpio_core_set,
121};
122
123static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
124 unsigned gpio_num)
125{
126 u8 curr_dirs;
127
128 spin_lock(&gpio_lock);
129
130 curr_dirs = inb(gpio_ba + RGIO);
131
132 if (!(curr_dirs & (1 << gpio_num)))
133 outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
134
135 spin_unlock(&gpio_lock);
136 return 0;
137}
138
139static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
140{
141 return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
142}
143
144static void sch_gpio_resume_set(struct gpio_chip *gc,
145 unsigned gpio_num, int val)
146{
147 u8 curr_vals;
148
149 spin_lock(&gpio_lock);
150
151 curr_vals = inb(gpio_ba + RGLV);
152
153 if (val)
154 outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
155 else
156 outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
157
158 spin_unlock(&gpio_lock);
159}
160
161static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
162 unsigned gpio_num, int val)
163{
164 u8 curr_dirs;
165
166 sch_gpio_resume_set(gc, gpio_num, val);
167
168 spin_lock(&gpio_lock);
169
170 curr_dirs = inb(gpio_ba + RGIO);
171 if (curr_dirs & (1 << gpio_num))
172 outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
173
174 spin_unlock(&gpio_lock);
175 return 0;
176}
177
178static struct gpio_chip sch_gpio_resume = {
179 .label = "sch_gpio_resume",
180 .owner = THIS_MODULE,
181 .direction_input = sch_gpio_resume_direction_in,
182 .get = sch_gpio_resume_get,
183 .direction_output = sch_gpio_resume_direction_out,
184 .set = sch_gpio_resume_set,
185};
186
187static int __devinit sch_gpio_probe(struct platform_device *pdev)
188{
189 struct resource *res;
190 int err;
191
192 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
193 if (!res)
194 return -EBUSY;
195
196 if (!request_region(res->start, resource_size(res), pdev->name))
197 return -EBUSY;
198
199 gpio_ba = res->start;
200
201 sch_gpio_core.base = 0;
202 sch_gpio_core.ngpio = 10;
203 sch_gpio_core.dev = &pdev->dev;
204
205 sch_gpio_resume.base = 10;
206 sch_gpio_resume.ngpio = 4;
207 sch_gpio_resume.dev = &pdev->dev;
208
209 err = gpiochip_add(&sch_gpio_core);
210 if (err < 0)
211 goto err_sch_gpio_core;
212
213 err = gpiochip_add(&sch_gpio_resume);
214 if (err < 0)
215 goto err_sch_gpio_resume;
216
217 /*
218 * GPIO[6:0] enabled by default
219 * GPIO7 is configured by the CMC as SLPIOVR
220 * Enable GPIO[9:8] core powered gpios explicitly
221 */
222 outb(0x3, gpio_ba + CGEN + 1);
223 /*
224 * SUS_GPIO[2:0] enabled by default
225 * Enable SUS_GPIO3 resume powered gpio explicitly
226 */
227 outb(0x8, gpio_ba + RGEN);
228
229 return 0;
230
231err_sch_gpio_resume:
232 err = gpiochip_remove(&sch_gpio_core);
233 if (err)
234 dev_err(&pdev->dev, "%s failed, %d\n",
235 "gpiochip_remove()", err);
236
237err_sch_gpio_core:
238 release_region(res->start, resource_size(res));
239 gpio_ba = 0;
240
241 return err;
242}
243
244static int __devexit sch_gpio_remove(struct platform_device *pdev)
245{
246 struct resource *res;
247 if (gpio_ba) {
248 int err;
249
250 err = gpiochip_remove(&sch_gpio_core);
251 if (err)
252 dev_err(&pdev->dev, "%s failed, %d\n",
253 "gpiochip_remove()", err);
254 err = gpiochip_remove(&sch_gpio_resume);
255 if (err)
256 dev_err(&pdev->dev, "%s failed, %d\n",
257 "gpiochip_remove()", err);
258
259 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
260
261 release_region(res->start, resource_size(res));
262 gpio_ba = 0;
263
264 return err;
265 }
266
267 return 0;
268}
269
270static struct platform_driver sch_gpio_driver = {
271 .driver = {
272 .name = "sch_gpio",
273 .owner = THIS_MODULE,
274 },
275 .probe = sch_gpio_probe,
276 .remove = __devexit_p(sch_gpio_remove),
277};
278
279static int __init sch_gpio_init(void)
280{
281 return platform_driver_register(&sch_gpio_driver);
282}
283
284static void __exit sch_gpio_exit(void)
285{
286 platform_driver_unregister(&sch_gpio_driver);
287}
288
289module_init(sch_gpio_init);
290module_exit(sch_gpio_exit);
291
292MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
293MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
294MODULE_LICENSE("GPL");
295MODULE_ALIAS("platform:sch_gpio");
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c
index b4468b616890..d09021f4a7d3 100644
--- a/drivers/gpio/wm831x-gpio.c
+++ b/drivers/gpio/wm831x-gpio.c
@@ -38,10 +38,14 @@ static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
38{ 38{
39 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 39 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
40 struct wm831x *wm831x = wm831x_gpio->wm831x; 40 struct wm831x *wm831x = wm831x_gpio->wm831x;
41 int val = WM831X_GPN_DIR;
42
43 if (wm831x->has_gpio_ena)
44 val |= WM831X_GPN_TRI;
41 45
42 return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 46 return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
43 WM831X_GPN_DIR | WM831X_GPN_TRI, 47 WM831X_GPN_DIR | WM831X_GPN_TRI |
44 WM831X_GPN_DIR); 48 WM831X_GPN_FN_MASK, val);
45} 49}
46 50
47static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset) 51static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -60,23 +64,36 @@ static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
60 return 0; 64 return 0;
61} 65}
62 66
63static int wm831x_gpio_direction_out(struct gpio_chip *chip, 67static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
64 unsigned offset, int value)
65{ 68{
66 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 69 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
67 struct wm831x *wm831x = wm831x_gpio->wm831x; 70 struct wm831x *wm831x = wm831x_gpio->wm831x;
68 71
69 return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset, 72 wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
70 WM831X_GPN_DIR | WM831X_GPN_TRI, 0); 73 value << offset);
71} 74}
72 75
73static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 76static int wm831x_gpio_direction_out(struct gpio_chip *chip,
77 unsigned offset, int value)
74{ 78{
75 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 79 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
76 struct wm831x *wm831x = wm831x_gpio->wm831x; 80 struct wm831x *wm831x = wm831x_gpio->wm831x;
81 int val = 0;
82 int ret;
77 83
78 wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset, 84 if (wm831x->has_gpio_ena)
79 value << offset); 85 val |= WM831X_GPN_TRI;
86
87 ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
88 WM831X_GPN_DIR | WM831X_GPN_TRI |
89 WM831X_GPN_FN_MASK, val);
90 if (ret < 0)
91 return ret;
92
93 /* Can only set GPIO state once it's in output mode */
94 wm831x_gpio_set(chip, offset, value);
95
96 return 0;
80} 97}
81 98
82static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 99static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -95,7 +112,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
95{ 112{
96 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); 113 struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
97 struct wm831x *wm831x = wm831x_gpio->wm831x; 114 struct wm831x *wm831x = wm831x_gpio->wm831x;
98 int i; 115 int i, tristated;
99 116
100 for (i = 0; i < chip->ngpio; i++) { 117 for (i = 0; i < chip->ngpio; i++) {
101 int gpio = i + chip->base; 118 int gpio = i + chip->base;
@@ -162,15 +179,19 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
162 break; 179 break;
163 } 180 }
164 181
182 tristated = reg & WM831X_GPN_TRI;
183 if (wm831x->has_gpio_ena)
184 tristated = !tristated;
185
165 seq_printf(s, " %s %s %s %s%s\n" 186 seq_printf(s, " %s %s %s %s%s\n"
166 " %s%s (0x%4x)\n", 187 " %s%s (0x%4x)\n",
167 reg & WM831X_GPN_DIR ? "in" : "out", 188 reg & WM831X_GPN_DIR ? "in" : "out",
168 wm831x_gpio_get(chip, i) ? "high" : "low", 189 wm831x_gpio_get(chip, i) ? "high" : "low",
169 pull, 190 pull,
170 powerdomain, 191 powerdomain,
171 reg & WM831X_GPN_POL ? " inverted" : "", 192 reg & WM831X_GPN_POL ? "" : " inverted",
172 reg & WM831X_GPN_OD ? "open-drain" : "CMOS", 193 reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
173 reg & WM831X_GPN_TRI ? " tristated" : "", 194 tristated ? " tristated" : "",
174 reg); 195 reg);
175 } 196 }
176} 197}
diff --git a/drivers/gpio/wm8350-gpiolib.c b/drivers/gpio/wm8350-gpiolib.c
new file mode 100644
index 000000000000..511840d1c7ba
--- /dev/null
+++ b/drivers/gpio/wm8350-gpiolib.c
@@ -0,0 +1,181 @@
1/*
2 * wm835x-gpiolib.c -- gpiolib support for Wolfson WM835x PMICs
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/gpio.h>
18#include <linux/mfd/core.h>
19#include <linux/platform_device.h>
20#include <linux/seq_file.h>
21
22#include <linux/mfd/wm8350/core.h>
23#include <linux/mfd/wm8350/gpio.h>
24
25struct wm8350_gpio_data {
26 struct wm8350 *wm8350;
27 struct gpio_chip gpio_chip;
28};
29
30static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
31{
32 return container_of(chip, struct wm8350_gpio_data, gpio_chip);
33}
34
35static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
36{
37 struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
38 struct wm8350 *wm8350 = wm8350_gpio->wm8350;
39
40 return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
41 1 << offset);
42}
43
44static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
45{
46 struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
47 struct wm8350 *wm8350 = wm8350_gpio->wm8350;
48 int ret;
49
50 ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
51 if (ret < 0)
52 return ret;
53
54 if (ret & (1 << offset))
55 return 1;
56 else
57 return 0;
58}
59
60static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
61{
62 struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
63 struct wm8350 *wm8350 = wm8350_gpio->wm8350;
64
65 if (value)
66 wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
67 else
68 wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
69}
70
71static int wm8350_gpio_direction_out(struct gpio_chip *chip,
72 unsigned offset, int value)
73{
74 struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
75 struct wm8350 *wm8350 = wm8350_gpio->wm8350;
76 int ret;
77
78 ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
79 1 << offset);
80 if (ret < 0)
81 return ret;
82
83 /* Don't have an atomic direction/value setup */
84 wm8350_gpio_set(chip, offset, value);
85
86 return 0;
87}
88
89static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
90{
91 struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
92 struct wm8350 *wm8350 = wm8350_gpio->wm8350;
93
94 if (!wm8350->irq_base)
95 return -EINVAL;
96
97 return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
98}
99
100static struct gpio_chip template_chip = {
101 .label = "wm8350",
102 .owner = THIS_MODULE,
103 .direction_input = wm8350_gpio_direction_in,
104 .get = wm8350_gpio_get,
105 .direction_output = wm8350_gpio_direction_out,
106 .set = wm8350_gpio_set,
107 .to_irq = wm8350_gpio_to_irq,
108 .can_sleep = 1,
109};
110
111static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
112{
113 struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
114 struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
115 struct wm8350_gpio_data *wm8350_gpio;
116 int ret;
117
118 wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
119 if (wm8350_gpio == NULL)
120 return -ENOMEM;
121
122 wm8350_gpio->wm8350 = wm8350;
123 wm8350_gpio->gpio_chip = template_chip;
124 wm8350_gpio->gpio_chip.ngpio = 13;
125 wm8350_gpio->gpio_chip.dev = &pdev->dev;
126 if (pdata && pdata->gpio_base)
127 wm8350_gpio->gpio_chip.base = pdata->gpio_base;
128 else
129 wm8350_gpio->gpio_chip.base = -1;
130
131 ret = gpiochip_add(&wm8350_gpio->gpio_chip);
132 if (ret < 0) {
133 dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
134 ret);
135 goto err;
136 }
137
138 platform_set_drvdata(pdev, wm8350_gpio);
139
140 return ret;
141
142err:
143 kfree(wm8350_gpio);
144 return ret;
145}
146
147static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
148{
149 struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
150 int ret;
151
152 ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
153 if (ret == 0)
154 kfree(wm8350_gpio);
155
156 return ret;
157}
158
159static struct platform_driver wm8350_gpio_driver = {
160 .driver.name = "wm8350-gpio",
161 .driver.owner = THIS_MODULE,
162 .probe = wm8350_gpio_probe,
163 .remove = __devexit_p(wm8350_gpio_remove),
164};
165
166static int __init wm8350_gpio_init(void)
167{
168 return platform_driver_register(&wm8350_gpio_driver);
169}
170subsys_initcall(wm8350_gpio_init);
171
172static void __exit wm8350_gpio_exit(void)
173{
174 platform_driver_unregister(&wm8350_gpio_driver);
175}
176module_exit(wm8350_gpio_exit);
177
178MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
179MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
180MODULE_LICENSE("GPL");
181MODULE_ALIAS("platform:wm8350-gpio");
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c
new file mode 100644
index 000000000000..de28b4a470ea
--- /dev/null
+++ b/drivers/gpio/wm8994-gpio.c
@@ -0,0 +1,204 @@
1/*
2 * wm8994-gpio.c -- gpiolib support for Wolfson WM8994
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/gpio.h>
18#include <linux/mfd/core.h>
19#include <linux/platform_device.h>
20#include <linux/seq_file.h>
21
22#include <linux/mfd/wm8994/core.h>
23#include <linux/mfd/wm8994/pdata.h>
24#include <linux/mfd/wm8994/gpio.h>
25#include <linux/mfd/wm8994/registers.h>
26
27struct wm8994_gpio {
28 struct wm8994 *wm8994;
29 struct gpio_chip gpio_chip;
30};
31
32static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
33{
34 return container_of(chip, struct wm8994_gpio, gpio_chip);
35}
36
37static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
38{
39 struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
40 struct wm8994 *wm8994 = wm8994_gpio->wm8994;
41
42 return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
43 WM8994_GPN_DIR, WM8994_GPN_DIR);
44}
45
46static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
47{
48 struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
49 struct wm8994 *wm8994 = wm8994_gpio->wm8994;
50 int ret;
51
52 ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
53 if (ret < 0)
54 return ret;
55
56 if (ret & WM8994_GPN_LVL)
57 return 1;
58 else
59 return 0;
60}
61
62static int wm8994_gpio_direction_out(struct gpio_chip *chip,
63 unsigned offset, int value)
64{
65 struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
66 struct wm8994 *wm8994 = wm8994_gpio->wm8994;
67
68 return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
69 WM8994_GPN_DIR, 0);
70}
71
72static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
73{
74 struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
75 struct wm8994 *wm8994 = wm8994_gpio->wm8994;
76
77 if (value)
78 value = WM8994_GPN_LVL;
79
80 wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
81}
82
83#ifdef CONFIG_DEBUG_FS
84static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
85{
86 struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
87 struct wm8994 *wm8994 = wm8994_gpio->wm8994;
88 int i;
89
90 for (i = 0; i < chip->ngpio; i++) {
91 int gpio = i + chip->base;
92 int reg;
93 const char *label;
94
95 /* We report the GPIO even if it's not requested since
96 * we're also reporting things like alternate
97 * functions which apply even when the GPIO is not in
98 * use as a GPIO.
99 */
100 label = gpiochip_is_requested(chip, i);
101 if (!label)
102 label = "Unrequested";
103
104 seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
105
106 reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
107 if (reg < 0) {
108 dev_err(wm8994->dev,
109 "GPIO control %d read failed: %d\n",
110 gpio, reg);
111 seq_printf(s, "\n");
112 continue;
113 }
114
115 /* No decode yet; note that GPIO2 is special */
116 seq_printf(s, "(%x)\n", reg);
117 }
118}
119#else
120#define wm8994_gpio_dbg_show NULL
121#endif
122
123static struct gpio_chip template_chip = {
124 .label = "wm8994",
125 .owner = THIS_MODULE,
126 .direction_input = wm8994_gpio_direction_in,
127 .get = wm8994_gpio_get,
128 .direction_output = wm8994_gpio_direction_out,
129 .set = wm8994_gpio_set,
130 .dbg_show = wm8994_gpio_dbg_show,
131 .can_sleep = 1,
132};
133
134static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
135{
136 struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
137 struct wm8994_pdata *pdata = wm8994->dev->platform_data;
138 struct wm8994_gpio *wm8994_gpio;
139 int ret;
140
141 wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
142 if (wm8994_gpio == NULL)
143 return -ENOMEM;
144
145 wm8994_gpio->wm8994 = wm8994;
146 wm8994_gpio->gpio_chip = template_chip;
147 wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
148 wm8994_gpio->gpio_chip.dev = &pdev->dev;
149 if (pdata && pdata->gpio_base)
150 wm8994_gpio->gpio_chip.base = pdata->gpio_base;
151 else
152 wm8994_gpio->gpio_chip.base = -1;
153
154 ret = gpiochip_add(&wm8994_gpio->gpio_chip);
155 if (ret < 0) {
156 dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
157 ret);
158 goto err;
159 }
160
161 platform_set_drvdata(pdev, wm8994_gpio);
162
163 return ret;
164
165err:
166 kfree(wm8994_gpio);
167 return ret;
168}
169
170static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
171{
172 struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
173 int ret;
174
175 ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
176 if (ret == 0)
177 kfree(wm8994_gpio);
178
179 return ret;
180}
181
182static struct platform_driver wm8994_gpio_driver = {
183 .driver.name = "wm8994-gpio",
184 .driver.owner = THIS_MODULE,
185 .probe = wm8994_gpio_probe,
186 .remove = __devexit_p(wm8994_gpio_remove),
187};
188
189static int __init wm8994_gpio_init(void)
190{
191 return platform_driver_register(&wm8994_gpio_driver);
192}
193subsys_initcall(wm8994_gpio_init);
194
195static void __exit wm8994_gpio_exit(void)
196{
197 platform_driver_unregister(&wm8994_gpio_driver);
198}
199module_exit(wm8994_gpio_exit);
200
201MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
202MODULE_DESCRIPTION("GPIO interface for WM8994");
203MODULE_LICENSE("GPL");
204MODULE_ALIAS("platform:wm8994-gpio");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4cc3807bd31c..4cd1ff77ceda 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -106,6 +106,8 @@ config I2C_I801
106config I2C_ISCH 106config I2C_ISCH
107 tristate "Intel SCH SMBus 1.0" 107 tristate "Intel SCH SMBus 1.0"
108 depends on PCI 108 depends on PCI
109 select MFD_CORE
110 select LPC_SCH
109 help 111 help
110 Say Y here if you want to use SMBus controller on the Intel SCH 112 Say Y here if you want to use SMBus controller on the Intel SCH
111 based systems. 113 based systems.
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index 69c22f79f231..ddc258edb34f 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -27,7 +27,7 @@
27*/ 27*/
28 28
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/pci.h> 30#include <linux/platform_device.h>
31#include <linux/kernel.h> 31#include <linux/kernel.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/stddef.h> 33#include <linux/stddef.h>
@@ -46,12 +46,6 @@
46#define SMBHSTDAT1 (7 + sch_smba) 46#define SMBHSTDAT1 (7 + sch_smba)
47#define SMBBLKDAT (0x20 + sch_smba) 47#define SMBBLKDAT (0x20 + sch_smba)
48 48
49/* count for request_region */
50#define SMBIOSIZE 64
51
52/* PCI Address Constants */
53#define SMBBA_SCH 0x40
54
55/* Other settings */ 49/* Other settings */
56#define MAX_TIMEOUT 500 50#define MAX_TIMEOUT 500
57 51
@@ -63,7 +57,6 @@
63#define SCH_BLOCK_DATA 0x05 57#define SCH_BLOCK_DATA 0x05
64 58
65static unsigned short sch_smba; 59static unsigned short sch_smba;
66static struct pci_driver sch_driver;
67static struct i2c_adapter sch_adapter; 60static struct i2c_adapter sch_adapter;
68 61
69/* 62/*
@@ -256,37 +249,23 @@ static struct i2c_adapter sch_adapter = {
256 .algo = &smbus_algorithm, 249 .algo = &smbus_algorithm,
257}; 250};
258 251
259static const struct pci_device_id sch_ids[] = { 252static int __devinit smbus_sch_probe(struct platform_device *dev)
260 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
261 { 0, }
262};
263
264MODULE_DEVICE_TABLE(pci, sch_ids);
265
266static int __devinit sch_probe(struct pci_dev *dev,
267 const struct pci_device_id *id)
268{ 253{
254 struct resource *res;
269 int retval; 255 int retval;
270 unsigned int smba;
271 256
272 pci_read_config_dword(dev, SMBBA_SCH, &smba); 257 res = platform_get_resource(dev, IORESOURCE_IO, 0);
273 if (!(smba & (1 << 31))) { 258 if (!res)
274 dev_err(&dev->dev, "SMBus I/O space disabled!\n"); 259 return -EBUSY;
275 return -ENODEV;
276 }
277 260
278 sch_smba = (unsigned short)smba; 261 if (!request_region(res->start, resource_size(res), dev->name)) {
279 if (sch_smba == 0) {
280 dev_err(&dev->dev, "SMBus base address uninitialized!\n");
281 return -ENODEV;
282 }
283 if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name))
284 return -ENODEV;
285 if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
286 dev_err(&dev->dev, "SMBus region 0x%x already in use!\n", 262 dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
287 sch_smba); 263 sch_smba);
288 return -EBUSY; 264 return -EBUSY;
289 } 265 }
266
267 sch_smba = res->start;
268
290 dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba); 269 dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
291 270
292 /* set up the sysfs linkage to our parent device */ 271 /* set up the sysfs linkage to our parent device */
@@ -298,37 +277,43 @@ static int __devinit sch_probe(struct pci_dev *dev,
298 retval = i2c_add_adapter(&sch_adapter); 277 retval = i2c_add_adapter(&sch_adapter);
299 if (retval) { 278 if (retval) {
300 dev_err(&dev->dev, "Couldn't register adapter!\n"); 279 dev_err(&dev->dev, "Couldn't register adapter!\n");
301 release_region(sch_smba, SMBIOSIZE); 280 release_region(res->start, resource_size(res));
302 sch_smba = 0; 281 sch_smba = 0;
303 } 282 }
304 283
305 return retval; 284 return retval;
306} 285}
307 286
308static void __devexit sch_remove(struct pci_dev *dev) 287static int __devexit smbus_sch_remove(struct platform_device *pdev)
309{ 288{
289 struct resource *res;
310 if (sch_smba) { 290 if (sch_smba) {
311 i2c_del_adapter(&sch_adapter); 291 i2c_del_adapter(&sch_adapter);
312 release_region(sch_smba, SMBIOSIZE); 292 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
293 release_region(res->start, resource_size(res));
313 sch_smba = 0; 294 sch_smba = 0;
314 } 295 }
296
297 return 0;
315} 298}
316 299
317static struct pci_driver sch_driver = { 300static struct platform_driver smbus_sch_driver = {
318 .name = "isch_smbus", 301 .driver = {
319 .id_table = sch_ids, 302 .name = "isch_smbus",
320 .probe = sch_probe, 303 .owner = THIS_MODULE,
321 .remove = __devexit_p(sch_remove), 304 },
305 .probe = smbus_sch_probe,
306 .remove = __devexit_p(smbus_sch_remove),
322}; 307};
323 308
324static int __init i2c_sch_init(void) 309static int __init i2c_sch_init(void)
325{ 310{
326 return pci_register_driver(&sch_driver); 311 return platform_driver_register(&smbus_sch_driver);
327} 312}
328 313
329static void __exit i2c_sch_exit(void) 314static void __exit i2c_sch_exit(void)
330{ 315{
331 pci_unregister_driver(&sch_driver); 316 platform_driver_unregister(&smbus_sch_driver);
332} 317}
333 318
334MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>"); 319MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
@@ -337,3 +322,4 @@ MODULE_LICENSE("GPL");
337 322
338module_init(i2c_sch_init); 323module_init(i2c_sch_init);
339module_exit(i2c_sch_exit); 324module_exit(i2c_sch_exit);
325MODULE_ALIAS("platform:isch_smbus");
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
new file mode 100644
index 000000000000..69a48e8701b9
--- /dev/null
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -0,0 +1,155 @@
1/*
2 * 88pm860x_onkey.c - Marvell 88PM860x ONKEY driver
3 *
4 * Copyright (C) 2009-2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file "COPYING" in the main directory of this
9 * archive for more details.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/i2c.h>
25#include <linux/input.h>
26#include <linux/interrupt.h>
27#include <linux/mfd/88pm860x.h>
28
29#define PM8607_WAKEUP 0x0b
30
31#define LONG_ONKEY_EN (1 << 1)
32#define ONKEY_STATUS (1 << 0)
33
34struct pm860x_onkey_info {
35 struct input_dev *idev;
36 struct pm860x_chip *chip;
37 struct i2c_client *i2c;
38 struct device *dev;
39 int irq;
40};
41
42/* 88PM860x gives us an interrupt when ONKEY is held */
43static irqreturn_t pm860x_onkey_handler(int irq, void *data)
44{
45 struct pm860x_onkey_info *info = data;
46 int ret;
47
48 ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
49 ret &= ONKEY_STATUS;
50 input_report_key(info->idev, KEY_POWER, ret);
51 input_sync(info->idev);
52
53 /* Enable 8-second long onkey detection */
54 pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
55 return IRQ_HANDLED;
56}
57
58static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
59{
60 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
61 struct pm860x_onkey_info *info;
62 int irq, ret;
63
64 irq = platform_get_irq(pdev, 0);
65 if (irq < 0) {
66 dev_err(&pdev->dev, "No IRQ resource!\n");
67 return -EINVAL;
68 }
69
70 info = kzalloc(sizeof(struct pm860x_onkey_info), GFP_KERNEL);
71 if (!info)
72 return -ENOMEM;
73 info->chip = chip;
74 info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
75 info->dev = &pdev->dev;
76 info->irq = irq + chip->irq_base;
77
78 info->idev = input_allocate_device();
79 if (!info->idev) {
80 dev_err(chip->dev, "Failed to allocate input dev\n");
81 ret = -ENOMEM;
82 goto out;
83 }
84
85 info->idev->name = "88pm860x_on";
86 info->idev->phys = "88pm860x_on/input0";
87 info->idev->id.bustype = BUS_I2C;
88 info->idev->dev.parent = &pdev->dev;
89 info->irq = irq;
90 info->idev->evbit[0] = BIT_MASK(EV_KEY);
91 info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
92
93 ret = input_register_device(info->idev);
94 if (ret) {
95 dev_err(chip->dev, "Can't register input device: %d\n", ret);
96 goto out_reg;
97 }
98
99 ret = request_threaded_irq(info->irq, NULL, pm860x_onkey_handler,
100 IRQF_ONESHOT, "onkey", info);
101 if (ret < 0) {
102 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
103 info->irq, ret);
104 goto out_irq;
105 }
106
107 platform_set_drvdata(pdev, info);
108 return 0;
109
110out_irq:
111 input_unregister_device(info->idev);
112 kfree(info);
113 return ret;
114
115out_reg:
116 input_free_device(info->idev);
117out:
118 kfree(info);
119 return ret;
120}
121
122static int __devexit pm860x_onkey_remove(struct platform_device *pdev)
123{
124 struct pm860x_onkey_info *info = platform_get_drvdata(pdev);
125
126 free_irq(info->irq, info);
127 input_unregister_device(info->idev);
128 kfree(info);
129 return 0;
130}
131
132static struct platform_driver pm860x_onkey_driver = {
133 .driver = {
134 .name = "88pm860x-onkey",
135 .owner = THIS_MODULE,
136 },
137 .probe = pm860x_onkey_probe,
138 .remove = __devexit_p(pm860x_onkey_remove),
139};
140
141static int __init pm860x_onkey_init(void)
142{
143 return platform_driver_register(&pm860x_onkey_driver);
144}
145module_init(pm860x_onkey_init);
146
147static void __exit pm860x_onkey_exit(void)
148{
149 platform_driver_unregister(&pm860x_onkey_driver);
150}
151module_exit(pm860x_onkey_exit);
152
153MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver");
154MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
155MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 16ec5233441c..7097bfe581d7 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -12,6 +12,16 @@ menuconfig INPUT_MISC
12 12
13if INPUT_MISC 13if INPUT_MISC
14 14
15config INPUT_88PM860X_ONKEY
16 tristate "88PM860x ONKEY support"
17 depends on MFD_88PM860X
18 help
19 Support the ONKEY of Marvell 88PM860x PMICs as an input device
20 reporting power button status.
21
22 To compile this driver as a module, choose M here: the module
23 will be called 88pm860x_onkey.
24
15config INPUT_PCSPKR 25config INPUT_PCSPKR
16 tristate "PC Speaker support" 26 tristate "PC Speaker support"
17 depends on PCSPKR_PLATFORM 27 depends on PCSPKR_PLATFORM
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a8b84854fb7b..b611615e24ad 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,6 +4,7 @@
4 4
5# Each configuration option enables a list of files. 5# Each configuration option enables a list of files.
6 6
7obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o
7obj-$(CONFIG_INPUT_APANEL) += apanel.o 8obj-$(CONFIG_INPUT_APANEL) += apanel.o
8obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o 9obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o
9obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o 10obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
new file mode 100644
index 000000000000..286bb490a9f2
--- /dev/null
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -0,0 +1,236 @@
1/*
2 * Touchscreen driver for Marvell 88PM860x
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/i2c.h>
15#include <linux/input.h>
16#include <linux/mfd/88pm860x.h>
17
18#define MEAS_LEN (8)
19#define ACCURATE_BIT (12)
20
21/* touch register */
22#define MEAS_EN3 (0x52)
23
24#define MEAS_TSIX_1 (0x8D)
25#define MEAS_TSIX_2 (0x8E)
26#define MEAS_TSIY_1 (0x8F)
27#define MEAS_TSIY_2 (0x90)
28#define MEAS_TSIZ1_1 (0x91)
29#define MEAS_TSIZ1_2 (0x92)
30#define MEAS_TSIZ2_1 (0x93)
31#define MEAS_TSIZ2_2 (0x94)
32
33/* bit definitions of touch */
34#define MEAS_PD_EN (1 << 3)
35#define MEAS_TSIX_EN (1 << 4)
36#define MEAS_TSIY_EN (1 << 5)
37#define MEAS_TSIZ1_EN (1 << 6)
38#define MEAS_TSIZ2_EN (1 << 7)
39
40struct pm860x_touch {
41 struct input_dev *idev;
42 struct i2c_client *i2c;
43 struct pm860x_chip *chip;
44 int irq;
45 int res_x; /* resistor of Xplate */
46};
47
48static irqreturn_t pm860x_touch_handler(int irq, void *data)
49{
50 struct pm860x_touch *touch = data;
51 struct pm860x_chip *chip = touch->chip;
52 unsigned char buf[MEAS_LEN];
53 int x, y, pen_down;
54 int z1, z2, rt = 0;
55 int ret;
56
57 ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
58 if (ret < 0)
59 goto out;
60
61 pen_down = buf[1] & (1 << 6);
62 x = ((buf[0] & 0xFF) << 4) | (buf[1] & 0x0F);
63 y = ((buf[2] & 0xFF) << 4) | (buf[3] & 0x0F);
64 z1 = ((buf[4] & 0xFF) << 4) | (buf[5] & 0x0F);
65 z2 = ((buf[6] & 0xFF) << 4) | (buf[7] & 0x0F);
66
67 if (pen_down) {
68 if ((x != 0) && (z1 != 0) && (touch->res_x != 0)) {
69 rt = z2 / z1 - 1;
70 rt = (rt * touch->res_x * x) >> ACCURATE_BIT;
71 dev_dbg(chip->dev, "z1:%d, z2:%d, rt:%d\n",
72 z1, z2, rt);
73 }
74 input_report_abs(touch->idev, ABS_X, x);
75 input_report_abs(touch->idev, ABS_Y, y);
76 input_report_abs(touch->idev, ABS_PRESSURE, rt);
77 input_report_key(touch->idev, BTN_TOUCH, 1);
78 dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
79 } else {
80 input_report_abs(touch->idev, ABS_PRESSURE, 0);
81 input_report_key(touch->idev, BTN_TOUCH, 0);
82 dev_dbg(chip->dev, "pen release\n");
83 }
84 input_sync(touch->idev);
85
86out:
87 return IRQ_HANDLED;
88}
89
90static int pm860x_touch_open(struct input_dev *dev)
91{
92 struct pm860x_touch *touch = input_get_drvdata(dev);
93 int data, ret;
94
95 data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
96 | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
97 ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
98 if (ret < 0)
99 goto out;
100 return 0;
101out:
102 return ret;
103}
104
105static void pm860x_touch_close(struct input_dev *dev)
106{
107 struct pm860x_touch *touch = input_get_drvdata(dev);
108 int data;
109
110 data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
111 | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
112 pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
113}
114
115static int __devinit pm860x_touch_probe(struct platform_device *pdev)
116{
117 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
118 struct pm860x_platform_data *pm860x_pdata = \
119 pdev->dev.parent->platform_data;
120 struct pm860x_touch_pdata *pdata = NULL;
121 struct pm860x_touch *touch;
122 int irq, ret;
123
124 irq = platform_get_irq(pdev, 0);
125 if (irq < 0) {
126 dev_err(&pdev->dev, "No IRQ resource!\n");
127 return -EINVAL;
128 }
129
130 if (!pm860x_pdata) {
131 dev_err(&pdev->dev, "platform data is missing\n");
132 return -EINVAL;
133 }
134
135 pdata = pm860x_pdata->touch;
136 if (!pdata) {
137 dev_err(&pdev->dev, "touchscreen data is missing\n");
138 return -EINVAL;
139 }
140
141 touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
142 if (touch == NULL)
143 return -ENOMEM;
144 dev_set_drvdata(&pdev->dev, touch);
145
146 touch->idev = input_allocate_device();
147 if (touch->idev == NULL) {
148 dev_err(&pdev->dev, "Failed to allocate input device!\n");
149 ret = -ENOMEM;
150 goto out;
151 }
152
153 touch->idev->name = "88pm860x-touch";
154 touch->idev->phys = "88pm860x/input0";
155 touch->idev->id.bustype = BUS_I2C;
156 touch->idev->dev.parent = &pdev->dev;
157 touch->idev->open = pm860x_touch_open;
158 touch->idev->close = pm860x_touch_close;
159 touch->chip = chip;
160 touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
161 touch->irq = irq + chip->irq_base;
162 touch->res_x = pdata->res_x;
163 input_set_drvdata(touch->idev, touch);
164
165 ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
166 IRQF_ONESHOT, "touch", touch);
167 if (ret < 0)
168 goto out_irq;
169
170 __set_bit(EV_ABS, touch->idev->evbit);
171 __set_bit(ABS_X, touch->idev->absbit);
172 __set_bit(ABS_Y, touch->idev->absbit);
173 __set_bit(ABS_PRESSURE, touch->idev->absbit);
174 __set_bit(EV_SYN, touch->idev->evbit);
175 __set_bit(EV_KEY, touch->idev->evbit);
176 __set_bit(BTN_TOUCH, touch->idev->keybit);
177
178 input_set_abs_params(touch->idev, ABS_X, 0, 1 << ACCURATE_BIT, 0, 0);
179 input_set_abs_params(touch->idev, ABS_Y, 0, 1 << ACCURATE_BIT, 0, 0);
180 input_set_abs_params(touch->idev, ABS_PRESSURE, 0, 1 << ACCURATE_BIT,
181 0, 0);
182
183 ret = input_register_device(touch->idev);
184 if (ret < 0) {
185 dev_err(chip->dev, "Failed to register touch!\n");
186 goto out_rg;
187 }
188
189 platform_set_drvdata(pdev, touch);
190 return 0;
191out_rg:
192 free_irq(touch->irq, touch);
193out_irq:
194 input_free_device(touch->idev);
195out:
196 kfree(touch);
197 return ret;
198}
199
200static int __devexit pm860x_touch_remove(struct platform_device *pdev)
201{
202 struct pm860x_touch *touch = platform_get_drvdata(pdev);
203
204 input_unregister_device(touch->idev);
205 free_irq(touch->irq, touch);
206 platform_set_drvdata(pdev, NULL);
207 kfree(touch);
208 return 0;
209}
210
211static struct platform_driver pm860x_touch_driver = {
212 .driver = {
213 .name = "88pm860x-touch",
214 .owner = THIS_MODULE,
215 },
216 .probe = pm860x_touch_probe,
217 .remove = __devexit_p(pm860x_touch_remove),
218};
219
220static int __init pm860x_touch_init(void)
221{
222 return platform_driver_register(&pm860x_touch_driver);
223}
224module_init(pm860x_touch_init);
225
226static void __exit pm860x_touch_exit(void)
227{
228 platform_driver_unregister(&pm860x_touch_driver);
229}
230module_exit(pm860x_touch_exit);
231
232MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x");
233MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
234MODULE_LICENSE("GPL");
235MODULE_ALIAS("platform:88pm860x-touch");
236
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6457e060ae49..7208654a94ae 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,6 +11,18 @@ menuconfig INPUT_TOUCHSCREEN
11 11
12if INPUT_TOUCHSCREEN 12if INPUT_TOUCHSCREEN
13 13
14config TOUCHSCREEN_88PM860X
15 tristate "Marvell 88PM860x touchscreen"
16 depends on MFD_88PM860X
17 help
18 Say Y here if you have a 88PM860x PMIC and want to enable
19 support for the built-in touchscreen.
20
21 If unsure, say N.
22
23 To compile this driver as a module, choose M here: the
24 module will be called 88pm860x-ts.
25
14config TOUCHSCREEN_ADS7846 26config TOUCHSCREEN_ADS7846
15 tristate "ADS7846/TSC2046 and ADS7843 based touchscreens" 27 tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"
16 depends on SPI_MASTER 28 depends on SPI_MASTER
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index d61a3b4def9a..7fef7d5cca23 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -6,6 +6,7 @@
6 6
7wm97xx-ts-y := wm97xx-core.o 7wm97xx-ts-y := wm97xx-core.o
8 8
9obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o
9obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o 10obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o
10obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o 11obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o
11obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o 12obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 8a0e1ec95e4a..e0b64312e66a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -17,6 +17,13 @@ config LEDS_CLASS
17 17
18comment "LED drivers" 18comment "LED drivers"
19 19
20config LEDS_88PM860X
21 tristate "LED Support for Marvell 88PM860x PMIC"
22 depends on LEDS_CLASS && MFD_88PM860X
23 help
24 This option enables support for on-chip LED drivers found on Marvell
25 Semiconductor 88PM8606 PMIC.
26
20config LEDS_ATMEL_PWM 27config LEDS_ATMEL_PWM
21 tristate "LED Support using Atmel PWM outputs" 28 tristate "LED Support using Atmel PWM outputs"
22 depends on LEDS_CLASS && ATMEL_PWM 29 depends on LEDS_CLASS && ATMEL_PWM
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 9e63869d7c0d..d76fb32b77c0 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_LEDS_CLASS) += led-class.o
5obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o 5obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
6 6
7# LED Platform Drivers 7# LED Platform Drivers
8obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o
8obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o 9obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
9obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o 10obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
10obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o 11obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
new file mode 100644
index 000000000000..d196073a6aeb
--- /dev/null
+++ b/drivers/leds/leds-88pm860x.c
@@ -0,0 +1,325 @@
1/*
2 * LED driver for Marvell 88PM860x
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/i2c.h>
17#include <linux/leds.h>
18#include <linux/workqueue.h>
19#include <linux/mfd/88pm860x.h>
20
21#define LED_PWM_SHIFT (3)
22#define LED_PWM_MASK (0x1F)
23#define LED_CURRENT_MASK (0x07 << 5)
24
25#define LED_BLINK_ON_MASK (0x07)
26#define LED_BLINK_PERIOD_MASK (0x0F << 3)
27#define LED_BLINK_MASK (0x7F)
28
29#define LED_BLINK_ON(x) ((x & 0x7) * 66 + 66)
30#define LED_BLINK_PERIOD(x) ((x & 0xF) * 530 + 930)
31#define LED_BLINK_ON_MIN LED_BLINK_ON(0)
32#define LED_BLINK_ON_MAX LED_BLINK_ON(0x7)
33#define LED_BLINK_PERIOD_MIN LED_BLINK_PERIOD(0)
34#define LED_BLINK_PERIOD_MAX LED_BLINK_PERIOD(0xE)
35#define LED_TO_ON(x) ((x - 66) / 66)
36#define LED_TO_PERIOD(x) ((x - 930) / 530)
37
38#define LED1_BLINK_EN (1 << 1)
39#define LED2_BLINK_EN (1 << 2)
40
41enum {
42 SET_BRIGHTNESS,
43 SET_BLINK,
44};
45
46struct pm860x_led {
47 struct led_classdev cdev;
48 struct i2c_client *i2c;
49 struct work_struct work;
50 struct pm860x_chip *chip;
51 struct mutex lock;
52 char name[MFD_NAME_SIZE];
53
54 int port;
55 int iset;
56 int command;
57 int offset;
58 unsigned char brightness;
59 unsigned char current_brightness;
60
61 int blink_data;
62 int blink_time;
63 int blink_on;
64 int blink_off;
65};
66
67/* return offset of color register */
68static inline int __led_off(int port)
69{
70 int ret = -EINVAL;
71
72 switch (port) {
73 case PM8606_LED1_RED:
74 case PM8606_LED1_GREEN:
75 case PM8606_LED1_BLUE:
76 ret = port - PM8606_LED1_RED + PM8606_RGB1B;
77 break;
78 case PM8606_LED2_RED:
79 case PM8606_LED2_GREEN:
80 case PM8606_LED2_BLUE:
81 ret = port - PM8606_LED2_RED + PM8606_RGB2B;
82 break;
83 }
84 return ret;
85}
86
87/* return offset of blink register */
88static inline int __blink_off(int port)
89{
90 int ret = -EINVAL;
91
92 switch (port) {
93 case PM8606_LED1_RED:
94 case PM8606_LED1_GREEN:
95 case PM8606_LED1_BLUE:
96 ret = PM8606_RGB1A;
97 case PM8606_LED2_RED:
98 case PM8606_LED2_GREEN:
99 case PM8606_LED2_BLUE:
100 ret = PM8606_RGB2A;
101 }
102 return ret;
103}
104
105static inline int __blink_ctl_mask(int port)
106{
107 int ret = -EINVAL;
108
109 switch (port) {
110 case PM8606_LED1_RED:
111 case PM8606_LED1_GREEN:
112 case PM8606_LED1_BLUE:
113 ret = LED1_BLINK_EN;
114 break;
115 case PM8606_LED2_RED:
116 case PM8606_LED2_GREEN:
117 case PM8606_LED2_BLUE:
118 ret = LED2_BLINK_EN;
119 break;
120 }
121 return ret;
122}
123
124static int __led_set(struct pm860x_led *led, int command)
125{
126 struct pm860x_chip *chip = led->chip;
127 int mask, ret;
128
129 mutex_lock(&led->lock);
130 switch (command) {
131 case SET_BRIGHTNESS:
132 if ((led->current_brightness == 0) && led->brightness) {
133 if (led->iset) {
134 ret = pm860x_set_bits(led->i2c, led->offset,
135 LED_CURRENT_MASK, led->iset);
136 if (ret < 0)
137 goto out;
138 }
139 } else if (led->brightness == 0) {
140 ret = pm860x_set_bits(led->i2c, led->offset,
141 LED_CURRENT_MASK, 0);
142 if (ret < 0)
143 goto out;
144 }
145 ret = pm860x_set_bits(led->i2c, led->offset, LED_PWM_MASK,
146 led->brightness);
147 if (ret < 0)
148 goto out;
149 led->current_brightness = led->brightness;
150 dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
151 led->offset, led->brightness);
152 break;
153 case SET_BLINK:
154 ret = pm860x_set_bits(led->i2c, led->offset,
155 LED_BLINK_MASK, led->blink_data);
156 if (ret < 0)
157 goto out;
158
159 mask = __blink_ctl_mask(led->port);
160 ret = pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
161 if (ret < 0)
162 goto out;
163 dev_dbg(chip->dev, "LED blink delay on:%dms, delay off:%dms\n",
164 led->blink_on, led->blink_off);
165 break;
166 }
167out:
168 mutex_unlock(&led->lock);
169 return 0;
170}
171
172static void pm860x_led_work(struct work_struct *work)
173{
174 struct pm860x_led *led;
175
176 led = container_of(work, struct pm860x_led, work);
177 __led_set(led, led->command);
178}
179
180static void pm860x_led_set(struct led_classdev *cdev,
181 enum led_brightness value)
182{
183 struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev);
184
185 data->offset = __led_off(data->port);
186 data->brightness = value >> 3;
187 data->command = SET_BRIGHTNESS;
188 schedule_work(&data->work);
189}
190
191static int pm860x_led_blink(struct led_classdev *cdev,
192 unsigned long *delay_on,
193 unsigned long *delay_off)
194{
195 struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev);
196 int period, on;
197
198 on = *delay_on;
199 if ((on < LED_BLINK_ON_MIN) || (on > LED_BLINK_ON_MAX))
200 return -EINVAL;
201
202 on = LED_TO_ON(on);
203 on = LED_BLINK_ON(on);
204
205 period = on + *delay_off;
206 if ((period < LED_BLINK_PERIOD_MIN) || (period > LED_BLINK_PERIOD_MAX))
207 return -EINVAL;
208 period = LED_TO_PERIOD(period);
209 period = LED_BLINK_PERIOD(period);
210
211 data->offset = __blink_off(data->port);
212 data->blink_on = on;
213 data->blink_off = period - data->blink_on;
214 data->blink_data = (period << 3) | data->blink_on;
215 data->command = SET_BLINK;
216 schedule_work(&data->work);
217
218 return 0;
219}
220
221static int __check_device(struct pm860x_led_pdata *pdata, char *name)
222{
223 struct pm860x_led_pdata *p = pdata;
224 int ret = -EINVAL;
225
226 while (p && p->id) {
227 if ((p->id != PM8606_ID_LED) || (p->flags < 0))
228 break;
229
230 if (!strncmp(name, pm860x_led_name[p->flags],
231 MFD_NAME_SIZE)) {
232 ret = (int)p->flags;
233 break;
234 }
235 p++;
236 }
237 return ret;
238}
239
240static int pm860x_led_probe(struct platform_device *pdev)
241{
242 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
243 struct pm860x_platform_data *pm860x_pdata;
244 struct pm860x_led_pdata *pdata;
245 struct pm860x_led *data;
246 struct resource *res;
247 int ret;
248
249 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
250 if (res == NULL) {
251 dev_err(&pdev->dev, "No I/O resource!\n");
252 return -EINVAL;
253 }
254
255 if (pdev->dev.parent->platform_data) {
256 pm860x_pdata = pdev->dev.parent->platform_data;
257 pdata = pm860x_pdata->led;
258 } else
259 pdata = NULL;
260
261 data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
262 if (data == NULL)
263 return -ENOMEM;
264 strncpy(data->name, res->name, MFD_NAME_SIZE);
265 dev_set_drvdata(&pdev->dev, data);
266 data->chip = chip;
267 data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
268 data->iset = pdata->iset;
269 data->port = __check_device(pdata, data->name);
270 if (data->port < 0)
271 return -EINVAL;
272
273 data->current_brightness = 0;
274 data->cdev.name = data->name;
275 data->cdev.brightness_set = pm860x_led_set;
276 data->cdev.blink_set = pm860x_led_blink;
277 mutex_init(&data->lock);
278 INIT_WORK(&data->work, pm860x_led_work);
279
280 ret = led_classdev_register(chip->dev, &data->cdev);
281 if (ret < 0) {
282 dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
283 goto out;
284 }
285 return 0;
286out:
287 kfree(data);
288 return ret;
289}
290
291static int pm860x_led_remove(struct platform_device *pdev)
292{
293 struct pm860x_led *data = platform_get_drvdata(pdev);
294
295 led_classdev_unregister(&data->cdev);
296 kfree(data);
297
298 return 0;
299}
300
301static struct platform_driver pm860x_led_driver = {
302 .driver = {
303 .name = "88pm860x-led",
304 .owner = THIS_MODULE,
305 },
306 .probe = pm860x_led_probe,
307 .remove = pm860x_led_remove,
308};
309
310static int __devinit pm860x_led_init(void)
311{
312 return platform_driver_register(&pm860x_led_driver);
313}
314module_init(pm860x_led_init);
315
316static void __devexit pm860x_led_exit(void)
317{
318 platform_driver_unregister(&pm860x_led_driver);
319}
320module_exit(pm860x_led_exit);
321
322MODULE_DESCRIPTION("LED driver for Marvell PM860x");
323MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
324MODULE_LICENSE("GPL");
325MODULE_ALIAS("platform:88pm860x-led");
diff --git a/drivers/mfd/88pm8607.c b/drivers/mfd/88pm8607.c
deleted file mode 100644
index 7e3f65907993..000000000000
--- a/drivers/mfd/88pm8607.c
+++ /dev/null
@@ -1,302 +0,0 @@
1/*
2 * Base driver for Marvell 88PM8607
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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/interrupt.h>
15#include <linux/platform_device.h>
16#include <linux/i2c.h>
17#include <linux/mfd/core.h>
18#include <linux/mfd/88pm8607.h>
19
20
21#define PM8607_REG_RESOURCE(_start, _end) \
22{ \
23 .start = PM8607_##_start, \
24 .end = PM8607_##_end, \
25 .flags = IORESOURCE_IO, \
26}
27
28static struct resource pm8607_regulator_resources[] = {
29 PM8607_REG_RESOURCE(BUCK1, BUCK1),
30 PM8607_REG_RESOURCE(BUCK2, BUCK2),
31 PM8607_REG_RESOURCE(BUCK3, BUCK3),
32 PM8607_REG_RESOURCE(LDO1, LDO1),
33 PM8607_REG_RESOURCE(LDO2, LDO2),
34 PM8607_REG_RESOURCE(LDO3, LDO3),
35 PM8607_REG_RESOURCE(LDO4, LDO4),
36 PM8607_REG_RESOURCE(LDO5, LDO5),
37 PM8607_REG_RESOURCE(LDO6, LDO6),
38 PM8607_REG_RESOURCE(LDO7, LDO7),
39 PM8607_REG_RESOURCE(LDO8, LDO8),
40 PM8607_REG_RESOURCE(LDO9, LDO9),
41 PM8607_REG_RESOURCE(LDO10, LDO10),
42 PM8607_REG_RESOURCE(LDO12, LDO12),
43 PM8607_REG_RESOURCE(LDO14, LDO14),
44};
45
46#define PM8607_REG_DEVS(_name, _id) \
47{ \
48 .name = "88pm8607-" #_name, \
49 .num_resources = 1, \
50 .resources = &pm8607_regulator_resources[PM8607_ID_##_id], \
51}
52
53static struct mfd_cell pm8607_devs[] = {
54 PM8607_REG_DEVS(buck1, BUCK1),
55 PM8607_REG_DEVS(buck2, BUCK2),
56 PM8607_REG_DEVS(buck3, BUCK3),
57 PM8607_REG_DEVS(ldo1, LDO1),
58 PM8607_REG_DEVS(ldo2, LDO2),
59 PM8607_REG_DEVS(ldo3, LDO3),
60 PM8607_REG_DEVS(ldo4, LDO4),
61 PM8607_REG_DEVS(ldo5, LDO5),
62 PM8607_REG_DEVS(ldo6, LDO6),
63 PM8607_REG_DEVS(ldo7, LDO7),
64 PM8607_REG_DEVS(ldo8, LDO8),
65 PM8607_REG_DEVS(ldo9, LDO9),
66 PM8607_REG_DEVS(ldo10, LDO10),
67 PM8607_REG_DEVS(ldo12, LDO12),
68 PM8607_REG_DEVS(ldo14, LDO14),
69};
70
71static inline int pm8607_read_device(struct pm8607_chip *chip,
72 int reg, int bytes, void *dest)
73{
74 struct i2c_client *i2c = chip->client;
75 unsigned char data;
76 int ret;
77
78 data = (unsigned char)reg;
79 ret = i2c_master_send(i2c, &data, 1);
80 if (ret < 0)
81 return ret;
82
83 ret = i2c_master_recv(i2c, dest, bytes);
84 if (ret < 0)
85 return ret;
86 return 0;
87}
88
89static inline int pm8607_write_device(struct pm8607_chip *chip,
90 int reg, int bytes, void *src)
91{
92 struct i2c_client *i2c = chip->client;
93 unsigned char buf[bytes + 1];
94 int ret;
95
96 buf[0] = (unsigned char)reg;
97 memcpy(&buf[1], src, bytes);
98
99 ret = i2c_master_send(i2c, buf, bytes + 1);
100 if (ret < 0)
101 return ret;
102 return 0;
103}
104
105int pm8607_reg_read(struct pm8607_chip *chip, int reg)
106{
107 unsigned char data;
108 int ret;
109
110 mutex_lock(&chip->io_lock);
111 ret = chip->read(chip, reg, 1, &data);
112 mutex_unlock(&chip->io_lock);
113
114 if (ret < 0)
115 return ret;
116 else
117 return (int)data;
118}
119EXPORT_SYMBOL(pm8607_reg_read);
120
121int pm8607_reg_write(struct pm8607_chip *chip, int reg,
122 unsigned char data)
123{
124 int ret;
125
126 mutex_lock(&chip->io_lock);
127 ret = chip->write(chip, reg, 1, &data);
128 mutex_unlock(&chip->io_lock);
129
130 return ret;
131}
132EXPORT_SYMBOL(pm8607_reg_write);
133
134int pm8607_bulk_read(struct pm8607_chip *chip, int reg,
135 int count, unsigned char *buf)
136{
137 int ret;
138
139 mutex_lock(&chip->io_lock);
140 ret = chip->read(chip, reg, count, buf);
141 mutex_unlock(&chip->io_lock);
142
143 return ret;
144}
145EXPORT_SYMBOL(pm8607_bulk_read);
146
147int pm8607_bulk_write(struct pm8607_chip *chip, int reg,
148 int count, unsigned char *buf)
149{
150 int ret;
151
152 mutex_lock(&chip->io_lock);
153 ret = chip->write(chip, reg, count, buf);
154 mutex_unlock(&chip->io_lock);
155
156 return ret;
157}
158EXPORT_SYMBOL(pm8607_bulk_write);
159
160int pm8607_set_bits(struct pm8607_chip *chip, int reg,
161 unsigned char mask, unsigned char data)
162{
163 unsigned char value;
164 int ret;
165
166 mutex_lock(&chip->io_lock);
167 ret = chip->read(chip, reg, 1, &value);
168 if (ret < 0)
169 goto out;
170 value &= ~mask;
171 value |= data;
172 ret = chip->write(chip, reg, 1, &value);
173out:
174 mutex_unlock(&chip->io_lock);
175 return ret;
176}
177EXPORT_SYMBOL(pm8607_set_bits);
178
179
180static const struct i2c_device_id pm8607_id_table[] = {
181 { "88PM8607", 0 },
182 {}
183};
184MODULE_DEVICE_TABLE(i2c, pm8607_id_table);
185
186
187static int __devinit pm8607_probe(struct i2c_client *client,
188 const struct i2c_device_id *id)
189{
190 struct pm8607_platform_data *pdata = client->dev.platform_data;
191 struct pm8607_chip *chip;
192 int i, count;
193 int ret;
194
195 chip = kzalloc(sizeof(struct pm8607_chip), GFP_KERNEL);
196 if (chip == NULL)
197 return -ENOMEM;
198
199 chip->client = client;
200 chip->dev = &client->dev;
201 chip->read = pm8607_read_device;
202 chip->write = pm8607_write_device;
203 i2c_set_clientdata(client, chip);
204
205 mutex_init(&chip->io_lock);
206 dev_set_drvdata(chip->dev, chip);
207
208 ret = pm8607_reg_read(chip, PM8607_CHIP_ID);
209 if (ret < 0) {
210 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
211 goto out;
212 }
213 if ((ret & CHIP_ID_MASK) == CHIP_ID)
214 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
215 ret);
216 else {
217 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
218 "Chip ID: %02x\n", ret);
219 goto out;
220 }
221 chip->chip_id = ret;
222
223 ret = pm8607_reg_read(chip, PM8607_BUCK3);
224 if (ret < 0) {
225 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
226 goto out;
227 }
228 if (ret & PM8607_BUCK3_DOUBLE)
229 chip->buck3_double = 1;
230
231 ret = pm8607_reg_read(chip, PM8607_MISC1);
232 if (ret < 0) {
233 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
234 goto out;
235 }
236 if (pdata->i2c_port == PI2C_PORT)
237 ret |= PM8607_MISC1_PI2C;
238 else
239 ret &= ~PM8607_MISC1_PI2C;
240 ret = pm8607_reg_write(chip, PM8607_MISC1, ret);
241 if (ret < 0) {
242 dev_err(chip->dev, "Failed to write MISC1 register: %d\n", ret);
243 goto out;
244 }
245
246
247 count = ARRAY_SIZE(pm8607_devs);
248 for (i = 0; i < count; i++) {
249 ret = mfd_add_devices(chip->dev, i, &pm8607_devs[i],
250 1, NULL, 0);
251 if (ret != 0) {
252 dev_err(chip->dev, "Failed to add subdevs\n");
253 goto out;
254 }
255 }
256
257 return 0;
258
259out:
260 i2c_set_clientdata(client, NULL);
261 kfree(chip);
262 return ret;
263}
264
265static int __devexit pm8607_remove(struct i2c_client *client)
266{
267 struct pm8607_chip *chip = i2c_get_clientdata(client);
268
269 mfd_remove_devices(chip->dev);
270 kfree(chip);
271 return 0;
272}
273
274static struct i2c_driver pm8607_driver = {
275 .driver = {
276 .name = "88PM8607",
277 .owner = THIS_MODULE,
278 },
279 .probe = pm8607_probe,
280 .remove = __devexit_p(pm8607_remove),
281 .id_table = pm8607_id_table,
282};
283
284static int __init pm8607_init(void)
285{
286 int ret;
287 ret = i2c_add_driver(&pm8607_driver);
288 if (ret != 0)
289 pr_err("Failed to register 88PM8607 I2C driver: %d\n", ret);
290 return ret;
291}
292subsys_initcall(pm8607_init);
293
294static void __exit pm8607_exit(void)
295{
296 i2c_del_driver(&pm8607_driver);
297}
298module_exit(pm8607_exit);
299
300MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM8607");
301MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
302MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
new file mode 100644
index 000000000000..6a14d2b1ccf0
--- /dev/null
+++ b/drivers/mfd/88pm860x-core.c
@@ -0,0 +1,740 @@
1/*
2 * Base driver for Marvell 88PM8607
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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/i2c.h>
15#include <linux/irq.h>
16#include <linux/interrupt.h>
17#include <linux/platform_device.h>
18#include <linux/mfd/core.h>
19#include <linux/mfd/88pm860x.h>
20
21#define INT_STATUS_NUM 3
22
23char pm860x_backlight_name[][MFD_NAME_SIZE] = {
24 "backlight-0",
25 "backlight-1",
26 "backlight-2",
27};
28EXPORT_SYMBOL(pm860x_backlight_name);
29
30char pm860x_led_name[][MFD_NAME_SIZE] = {
31 "led0-red",
32 "led0-green",
33 "led0-blue",
34 "led1-red",
35 "led1-green",
36 "led1-blue",
37};
38EXPORT_SYMBOL(pm860x_led_name);
39
40#define PM8606_BACKLIGHT_RESOURCE(_i, _x) \
41{ \
42 .name = pm860x_backlight_name[_i], \
43 .start = PM8606_##_x, \
44 .end = PM8606_##_x, \
45 .flags = IORESOURCE_IO, \
46}
47
48static struct resource backlight_resources[] = {
49 PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT1, WLED1A),
50 PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT2, WLED2A),
51 PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT3, WLED3A),
52};
53
54#define PM8606_BACKLIGHT_DEVS(_i) \
55{ \
56 .name = "88pm860x-backlight", \
57 .num_resources = 1, \
58 .resources = &backlight_resources[_i], \
59 .id = _i, \
60}
61
62static struct mfd_cell backlight_devs[] = {
63 PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT1),
64 PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT2),
65 PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT3),
66};
67
68#define PM8606_LED_RESOURCE(_i, _x) \
69{ \
70 .name = pm860x_led_name[_i], \
71 .start = PM8606_##_x, \
72 .end = PM8606_##_x, \
73 .flags = IORESOURCE_IO, \
74}
75
76static struct resource led_resources[] = {
77 PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB2B),
78 PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB2C),
79 PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB2D),
80 PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB1B),
81 PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB1C),
82 PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB1D),
83};
84
85#define PM8606_LED_DEVS(_i) \
86{ \
87 .name = "88pm860x-led", \
88 .num_resources = 1, \
89 .resources = &led_resources[_i], \
90 .id = _i, \
91}
92
93static struct mfd_cell led_devs[] = {
94 PM8606_LED_DEVS(PM8606_LED1_RED),
95 PM8606_LED_DEVS(PM8606_LED1_GREEN),
96 PM8606_LED_DEVS(PM8606_LED1_BLUE),
97 PM8606_LED_DEVS(PM8606_LED2_RED),
98 PM8606_LED_DEVS(PM8606_LED2_GREEN),
99 PM8606_LED_DEVS(PM8606_LED2_BLUE),
100};
101
102static struct resource touch_resources[] = {
103 {
104 .start = PM8607_IRQ_PEN,
105 .end = PM8607_IRQ_PEN,
106 .flags = IORESOURCE_IRQ,
107 },
108};
109
110static struct mfd_cell touch_devs[] = {
111 {
112 .name = "88pm860x-touch",
113 .num_resources = 1,
114 .resources = &touch_resources[0],
115 },
116};
117
118#define PM8607_REG_RESOURCE(_start, _end) \
119{ \
120 .start = PM8607_##_start, \
121 .end = PM8607_##_end, \
122 .flags = IORESOURCE_IO, \
123}
124
125static struct resource power_supply_resources[] = {
126 {
127 .name = "88pm860x-power",
128 .start = PM8607_IRQ_CHG,
129 .end = PM8607_IRQ_CHG,
130 .flags = IORESOURCE_IRQ,
131 },
132};
133
134static struct mfd_cell power_devs[] = {
135 {
136 .name = "88pm860x-power",
137 .num_resources = 1,
138 .resources = &power_supply_resources[0],
139 .id = -1,
140 },
141};
142
143static struct resource onkey_resources[] = {
144 {
145 .name = "88pm860x-onkey",
146 .start = PM8607_IRQ_ONKEY,
147 .end = PM8607_IRQ_ONKEY,
148 .flags = IORESOURCE_IRQ,
149 },
150};
151
152static struct mfd_cell onkey_devs[] = {
153 {
154 .name = "88pm860x-onkey",
155 .num_resources = 1,
156 .resources = &onkey_resources[0],
157 .id = -1,
158 },
159};
160
161static struct resource regulator_resources[] = {
162 PM8607_REG_RESOURCE(BUCK1, BUCK1),
163 PM8607_REG_RESOURCE(BUCK2, BUCK2),
164 PM8607_REG_RESOURCE(BUCK3, BUCK3),
165 PM8607_REG_RESOURCE(LDO1, LDO1),
166 PM8607_REG_RESOURCE(LDO2, LDO2),
167 PM8607_REG_RESOURCE(LDO3, LDO3),
168 PM8607_REG_RESOURCE(LDO4, LDO4),
169 PM8607_REG_RESOURCE(LDO5, LDO5),
170 PM8607_REG_RESOURCE(LDO6, LDO6),
171 PM8607_REG_RESOURCE(LDO7, LDO7),
172 PM8607_REG_RESOURCE(LDO8, LDO8),
173 PM8607_REG_RESOURCE(LDO9, LDO9),
174 PM8607_REG_RESOURCE(LDO10, LDO10),
175 PM8607_REG_RESOURCE(LDO12, LDO12),
176 PM8607_REG_RESOURCE(LDO14, LDO14),
177};
178
179#define PM8607_REG_DEVS(_name, _id) \
180{ \
181 .name = "88pm8607-" #_name, \
182 .num_resources = 1, \
183 .resources = &regulator_resources[PM8607_ID_##_id], \
184 .id = PM8607_ID_##_id, \
185}
186
187static struct mfd_cell regulator_devs[] = {
188 PM8607_REG_DEVS(buck1, BUCK1),
189 PM8607_REG_DEVS(buck2, BUCK2),
190 PM8607_REG_DEVS(buck3, BUCK3),
191 PM8607_REG_DEVS(ldo1, LDO1),
192 PM8607_REG_DEVS(ldo2, LDO2),
193 PM8607_REG_DEVS(ldo3, LDO3),
194 PM8607_REG_DEVS(ldo4, LDO4),
195 PM8607_REG_DEVS(ldo5, LDO5),
196 PM8607_REG_DEVS(ldo6, LDO6),
197 PM8607_REG_DEVS(ldo7, LDO7),
198 PM8607_REG_DEVS(ldo8, LDO8),
199 PM8607_REG_DEVS(ldo9, LDO9),
200 PM8607_REG_DEVS(ldo10, LDO10),
201 PM8607_REG_DEVS(ldo12, LDO12),
202 PM8607_REG_DEVS(ldo14, LDO14),
203};
204
205struct pm860x_irq_data {
206 int reg;
207 int mask_reg;
208 int enable; /* enable or not */
209 int offs; /* bit offset in mask register */
210};
211
212static struct pm860x_irq_data pm860x_irqs[] = {
213 [PM8607_IRQ_ONKEY] = {
214 .reg = PM8607_INT_STATUS1,
215 .mask_reg = PM8607_INT_MASK_1,
216 .offs = 1 << 0,
217 },
218 [PM8607_IRQ_EXTON] = {
219 .reg = PM8607_INT_STATUS1,
220 .mask_reg = PM8607_INT_MASK_1,
221 .offs = 1 << 1,
222 },
223 [PM8607_IRQ_CHG] = {
224 .reg = PM8607_INT_STATUS1,
225 .mask_reg = PM8607_INT_MASK_1,
226 .offs = 1 << 2,
227 },
228 [PM8607_IRQ_BAT] = {
229 .reg = PM8607_INT_STATUS1,
230 .mask_reg = PM8607_INT_MASK_1,
231 .offs = 1 << 3,
232 },
233 [PM8607_IRQ_RTC] = {
234 .reg = PM8607_INT_STATUS1,
235 .mask_reg = PM8607_INT_MASK_1,
236 .offs = 1 << 4,
237 },
238 [PM8607_IRQ_CC] = {
239 .reg = PM8607_INT_STATUS1,
240 .mask_reg = PM8607_INT_MASK_1,
241 .offs = 1 << 5,
242 },
243 [PM8607_IRQ_VBAT] = {
244 .reg = PM8607_INT_STATUS2,
245 .mask_reg = PM8607_INT_MASK_2,
246 .offs = 1 << 0,
247 },
248 [PM8607_IRQ_VCHG] = {
249 .reg = PM8607_INT_STATUS2,
250 .mask_reg = PM8607_INT_MASK_2,
251 .offs = 1 << 1,
252 },
253 [PM8607_IRQ_VSYS] = {
254 .reg = PM8607_INT_STATUS2,
255 .mask_reg = PM8607_INT_MASK_2,
256 .offs = 1 << 2,
257 },
258 [PM8607_IRQ_TINT] = {
259 .reg = PM8607_INT_STATUS2,
260 .mask_reg = PM8607_INT_MASK_2,
261 .offs = 1 << 3,
262 },
263 [PM8607_IRQ_GPADC0] = {
264 .reg = PM8607_INT_STATUS2,
265 .mask_reg = PM8607_INT_MASK_2,
266 .offs = 1 << 4,
267 },
268 [PM8607_IRQ_GPADC1] = {
269 .reg = PM8607_INT_STATUS2,
270 .mask_reg = PM8607_INT_MASK_2,
271 .offs = 1 << 5,
272 },
273 [PM8607_IRQ_GPADC2] = {
274 .reg = PM8607_INT_STATUS2,
275 .mask_reg = PM8607_INT_MASK_2,
276 .offs = 1 << 6,
277 },
278 [PM8607_IRQ_GPADC3] = {
279 .reg = PM8607_INT_STATUS2,
280 .mask_reg = PM8607_INT_MASK_2,
281 .offs = 1 << 7,
282 },
283 [PM8607_IRQ_AUDIO_SHORT] = {
284 .reg = PM8607_INT_STATUS3,
285 .mask_reg = PM8607_INT_MASK_3,
286 .offs = 1 << 0,
287 },
288 [PM8607_IRQ_PEN] = {
289 .reg = PM8607_INT_STATUS3,
290 .mask_reg = PM8607_INT_MASK_3,
291 .offs = 1 << 1,
292 },
293 [PM8607_IRQ_HEADSET] = {
294 .reg = PM8607_INT_STATUS3,
295 .mask_reg = PM8607_INT_MASK_3,
296 .offs = 1 << 2,
297 },
298 [PM8607_IRQ_HOOK] = {
299 .reg = PM8607_INT_STATUS3,
300 .mask_reg = PM8607_INT_MASK_3,
301 .offs = 1 << 3,
302 },
303 [PM8607_IRQ_MICIN] = {
304 .reg = PM8607_INT_STATUS3,
305 .mask_reg = PM8607_INT_MASK_3,
306 .offs = 1 << 4,
307 },
308 [PM8607_IRQ_CHG_FAIL] = {
309 .reg = PM8607_INT_STATUS3,
310 .mask_reg = PM8607_INT_MASK_3,
311 .offs = 1 << 5,
312 },
313 [PM8607_IRQ_CHG_DONE] = {
314 .reg = PM8607_INT_STATUS3,
315 .mask_reg = PM8607_INT_MASK_3,
316 .offs = 1 << 6,
317 },
318 [PM8607_IRQ_CHG_FAULT] = {
319 .reg = PM8607_INT_STATUS3,
320 .mask_reg = PM8607_INT_MASK_3,
321 .offs = 1 << 7,
322 },
323};
324
325static inline struct pm860x_irq_data *irq_to_pm860x(struct pm860x_chip *chip,
326 int irq)
327{
328 return &pm860x_irqs[irq - chip->irq_base];
329}
330
331static irqreturn_t pm860x_irq(int irq, void *data)
332{
333 struct pm860x_chip *chip = data;
334 struct pm860x_irq_data *irq_data;
335 struct i2c_client *i2c;
336 int read_reg = -1, value = 0;
337 int i;
338
339 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
340 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
341 irq_data = &pm860x_irqs[i];
342 if (read_reg != irq_data->reg) {
343 read_reg = irq_data->reg;
344 value = pm860x_reg_read(i2c, irq_data->reg);
345 }
346 if (value & irq_data->enable)
347 handle_nested_irq(chip->irq_base + i);
348 }
349 return IRQ_HANDLED;
350}
351
352static void pm860x_irq_lock(unsigned int irq)
353{
354 struct pm860x_chip *chip = get_irq_chip_data(irq);
355
356 mutex_lock(&chip->irq_lock);
357}
358
359static void pm860x_irq_sync_unlock(unsigned int irq)
360{
361 struct pm860x_chip *chip = get_irq_chip_data(irq);
362 struct pm860x_irq_data *irq_data;
363 struct i2c_client *i2c;
364 static unsigned char cached[3] = {0x0, 0x0, 0x0};
365 unsigned char mask[3];
366 int i;
367
368 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
369 /* Load cached value. In initial, all IRQs are masked */
370 for (i = 0; i < 3; i++)
371 mask[i] = cached[i];
372 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
373 irq_data = &pm860x_irqs[i];
374 switch (irq_data->mask_reg) {
375 case PM8607_INT_MASK_1:
376 mask[0] &= ~irq_data->offs;
377 mask[0] |= irq_data->enable;
378 break;
379 case PM8607_INT_MASK_2:
380 mask[1] &= ~irq_data->offs;
381 mask[1] |= irq_data->enable;
382 break;
383 case PM8607_INT_MASK_3:
384 mask[2] &= ~irq_data->offs;
385 mask[2] |= irq_data->enable;
386 break;
387 default:
388 dev_err(chip->dev, "wrong IRQ\n");
389 break;
390 }
391 }
392 /* update mask into registers */
393 for (i = 0; i < 3; i++) {
394 if (mask[i] != cached[i]) {
395 cached[i] = mask[i];
396 pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]);
397 }
398 }
399
400 mutex_unlock(&chip->irq_lock);
401}
402
403static void pm860x_irq_enable(unsigned int irq)
404{
405 struct pm860x_chip *chip = get_irq_chip_data(irq);
406 pm860x_irqs[irq - chip->irq_base].enable
407 = pm860x_irqs[irq - chip->irq_base].offs;
408}
409
410static void pm860x_irq_disable(unsigned int irq)
411{
412 struct pm860x_chip *chip = get_irq_chip_data(irq);
413 pm860x_irqs[irq - chip->irq_base].enable = 0;
414}
415
416static struct irq_chip pm860x_irq_chip = {
417 .name = "88pm860x",
418 .bus_lock = pm860x_irq_lock,
419 .bus_sync_unlock = pm860x_irq_sync_unlock,
420 .enable = pm860x_irq_enable,
421 .disable = pm860x_irq_disable,
422};
423
424static int __devinit device_gpadc_init(struct pm860x_chip *chip,
425 struct pm860x_platform_data *pdata)
426{
427 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
428 : chip->companion;
429 int use_gpadc = 0, data, ret;
430
431 /* initialize GPADC without activating it */
432
433 if (pdata && pdata->touch) {
434 /* set GPADC MISC1 register */
435 data = 0;
436 data |= (pdata->touch->gpadc_prebias << 1)
437 & PM8607_GPADC_PREBIAS_MASK;
438 data |= (pdata->touch->slot_cycle << 3)
439 & PM8607_GPADC_SLOT_CYCLE_MASK;
440 data |= (pdata->touch->off_scale << 5)
441 & PM8607_GPADC_OFF_SCALE_MASK;
442 data |= (pdata->touch->sw_cal << 7)
443 & PM8607_GPADC_SW_CAL_MASK;
444 if (data) {
445 ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
446 if (ret < 0)
447 goto out;
448 }
449 /* set tsi prebias time */
450 if (pdata->touch->tsi_prebias) {
451 data = pdata->touch->tsi_prebias;
452 ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
453 if (ret < 0)
454 goto out;
455 }
456 /* set prebias & prechg time of pen detect */
457 data = 0;
458 data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
459 data |= (pdata->touch->pen_prechg << 5)
460 & PM8607_PD_PRECHG_MASK;
461 if (data) {
462 ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
463 if (ret < 0)
464 goto out;
465 }
466
467 use_gpadc = 1;
468 }
469
470 /* turn on GPADC */
471 if (use_gpadc) {
472 ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
473 PM8607_GPADC_EN, PM8607_GPADC_EN);
474 }
475out:
476 return ret;
477}
478
479static int __devinit device_irq_init(struct pm860x_chip *chip,
480 struct pm860x_platform_data *pdata)
481{
482 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
483 : chip->companion;
484 unsigned char status_buf[INT_STATUS_NUM];
485 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
486 struct irq_desc *desc;
487 int i, data, mask, ret = -EINVAL;
488 int __irq;
489
490 if (!pdata || !pdata->irq_base) {
491 dev_warn(chip->dev, "No interrupt support on IRQ base\n");
492 return -EINVAL;
493 }
494
495 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
496 | PM8607_B0_MISC1_INT_MASK;
497 data = 0;
498 chip->irq_mode = 0;
499 if (pdata && pdata->irq_mode) {
500 /*
501 * irq_mode defines the way of clearing interrupt. If it's 1,
502 * clear IRQ by write. Otherwise, clear it by read.
503 * This control bit is valid from 88PM8607 B0 steping.
504 */
505 data |= PM8607_B0_MISC1_INT_CLEAR;
506 chip->irq_mode = 1;
507 }
508 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data);
509 if (ret < 0)
510 goto out;
511
512 /* mask all IRQs */
513 memset(status_buf, 0, INT_STATUS_NUM);
514 ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1,
515 INT_STATUS_NUM, status_buf);
516 if (ret < 0)
517 goto out;
518
519 if (chip->irq_mode) {
520 /* clear interrupt status by write */
521 memset(status_buf, 0xFF, INT_STATUS_NUM);
522 ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1,
523 INT_STATUS_NUM, status_buf);
524 } else {
525 /* clear interrupt status by read */
526 ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1,
527 INT_STATUS_NUM, status_buf);
528 }
529 if (ret < 0)
530 goto out;
531
532 mutex_init(&chip->irq_lock);
533 chip->irq_base = pdata->irq_base;
534 chip->core_irq = i2c->irq;
535 if (!chip->core_irq)
536 goto out;
537
538 desc = irq_to_desc(chip->core_irq);
539
540 /* register IRQ by genirq */
541 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
542 __irq = i + chip->irq_base;
543 set_irq_chip_data(__irq, chip);
544 set_irq_chip_and_handler(__irq, &pm860x_irq_chip,
545 handle_edge_irq);
546 set_irq_nested_thread(__irq, 1);
547#ifdef CONFIG_ARM
548 set_irq_flags(__irq, IRQF_VALID);
549#else
550 set_irq_noprobe(__irq);
551#endif
552 }
553
554 ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
555 "88pm860x", chip);
556 if (ret) {
557 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
558 chip->core_irq = 0;
559 }
560
561 return 0;
562out:
563 chip->core_irq = 0;
564 return ret;
565}
566
567static void __devexit device_irq_exit(struct pm860x_chip *chip)
568{
569 if (chip->core_irq)
570 free_irq(chip->core_irq, chip);
571}
572
573static void __devinit device_8606_init(struct pm860x_chip *chip,
574 struct i2c_client *i2c,
575 struct pm860x_platform_data *pdata)
576{
577 int ret;
578
579 if (pdata && pdata->backlight) {
580 ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
581 ARRAY_SIZE(backlight_devs),
582 &backlight_resources[0], 0);
583 if (ret < 0) {
584 dev_err(chip->dev, "Failed to add backlight "
585 "subdev\n");
586 goto out_dev;
587 }
588 }
589
590 if (pdata && pdata->led) {
591 ret = mfd_add_devices(chip->dev, 0, &led_devs[0],
592 ARRAY_SIZE(led_devs),
593 &led_resources[0], 0);
594 if (ret < 0) {
595 dev_err(chip->dev, "Failed to add led "
596 "subdev\n");
597 goto out_dev;
598 }
599 }
600 return;
601out_dev:
602 mfd_remove_devices(chip->dev);
603 device_irq_exit(chip);
604}
605
606static void __devinit device_8607_init(struct pm860x_chip *chip,
607 struct i2c_client *i2c,
608 struct pm860x_platform_data *pdata)
609{
610 int data, ret;
611
612 ret = pm860x_reg_read(i2c, PM8607_CHIP_ID);
613 if (ret < 0) {
614 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
615 goto out;
616 }
617 if ((ret & PM8607_VERSION_MASK) == PM8607_VERSION)
618 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
619 ret);
620 else {
621 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
622 "Chip ID: %02x\n", ret);
623 goto out;
624 }
625
626 ret = pm860x_reg_read(i2c, PM8607_BUCK3);
627 if (ret < 0) {
628 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
629 goto out;
630 }
631 if (ret & PM8607_BUCK3_DOUBLE)
632 chip->buck3_double = 1;
633
634 ret = pm860x_reg_read(i2c, PM8607_B0_MISC1);
635 if (ret < 0) {
636 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
637 goto out;
638 }
639
640 if (pdata && (pdata->i2c_port == PI2C_PORT))
641 data = PM8607_B0_MISC1_PI2C;
642 else
643 data = 0;
644 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data);
645 if (ret < 0) {
646 dev_err(chip->dev, "Failed to access MISC1:%d\n", ret);
647 goto out;
648 }
649
650 ret = device_gpadc_init(chip, pdata);
651 if (ret < 0)
652 goto out;
653
654 ret = device_irq_init(chip, pdata);
655 if (ret < 0)
656 goto out;
657
658 ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
659 ARRAY_SIZE(regulator_devs),
660 &regulator_resources[0], 0);
661 if (ret < 0) {
662 dev_err(chip->dev, "Failed to add regulator subdev\n");
663 goto out_dev;
664 }
665
666 if (pdata && pdata->touch) {
667 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
668 ARRAY_SIZE(touch_devs),
669 &touch_resources[0], 0);
670 if (ret < 0) {
671 dev_err(chip->dev, "Failed to add touch "
672 "subdev\n");
673 goto out_dev;
674 }
675 }
676
677 if (pdata && pdata->power) {
678 ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
679 ARRAY_SIZE(power_devs),
680 &power_supply_resources[0], 0);
681 if (ret < 0) {
682 dev_err(chip->dev, "Failed to add power supply "
683 "subdev\n");
684 goto out_dev;
685 }
686 }
687
688 ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
689 ARRAY_SIZE(onkey_devs),
690 &onkey_resources[0], 0);
691 if (ret < 0) {
692 dev_err(chip->dev, "Failed to add onkey subdev\n");
693 goto out_dev;
694 }
695
696 return;
697out_dev:
698 mfd_remove_devices(chip->dev);
699 device_irq_exit(chip);
700out:
701 return;
702}
703
704int pm860x_device_init(struct pm860x_chip *chip,
705 struct pm860x_platform_data *pdata)
706{
707 chip->core_irq = 0;
708
709 switch (chip->id) {
710 case CHIP_PM8606:
711 device_8606_init(chip, chip->client, pdata);
712 break;
713 case CHIP_PM8607:
714 device_8607_init(chip, chip->client, pdata);
715 break;
716 }
717
718 if (chip->companion) {
719 switch (chip->id) {
720 case CHIP_PM8607:
721 device_8606_init(chip, chip->companion, pdata);
722 break;
723 case CHIP_PM8606:
724 device_8607_init(chip, chip->companion, pdata);
725 break;
726 }
727 }
728
729 return 0;
730}
731
732void pm860x_device_exit(struct pm860x_chip *chip)
733{
734 device_irq_exit(chip);
735 mfd_remove_devices(chip->dev);
736}
737
738MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
739MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
740MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
new file mode 100644
index 000000000000..c37e12bf3004
--- /dev/null
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -0,0 +1,236 @@
1/*
2 * I2C driver for Marvell 88PM860x
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/i2c.h>
15#include <linux/mfd/88pm860x.h>
16
17static inline int pm860x_read_device(struct i2c_client *i2c,
18 int reg, int bytes, void *dest)
19{
20 unsigned char data;
21 int ret;
22
23 data = (unsigned char)reg;
24 ret = i2c_master_send(i2c, &data, 1);
25 if (ret < 0)
26 return ret;
27
28 ret = i2c_master_recv(i2c, dest, bytes);
29 if (ret < 0)
30 return ret;
31 return 0;
32}
33
34static inline int pm860x_write_device(struct i2c_client *i2c,
35 int reg, int bytes, void *src)
36{
37 unsigned char buf[bytes + 1];
38 int ret;
39
40 buf[0] = (unsigned char)reg;
41 memcpy(&buf[1], src, bytes);
42
43 ret = i2c_master_send(i2c, buf, bytes + 1);
44 if (ret < 0)
45 return ret;
46 return 0;
47}
48
49int pm860x_reg_read(struct i2c_client *i2c, int reg)
50{
51 struct pm860x_chip *chip = i2c_get_clientdata(i2c);
52 unsigned char data;
53 int ret;
54
55 mutex_lock(&chip->io_lock);
56 ret = pm860x_read_device(i2c, reg, 1, &data);
57 mutex_unlock(&chip->io_lock);
58
59 if (ret < 0)
60 return ret;
61 else
62 return (int)data;
63}
64EXPORT_SYMBOL(pm860x_reg_read);
65
66int pm860x_reg_write(struct i2c_client *i2c, int reg,
67 unsigned char data)
68{
69 struct pm860x_chip *chip = i2c_get_clientdata(i2c);
70 int ret;
71
72 mutex_lock(&chip->io_lock);
73 ret = pm860x_write_device(i2c, reg, 1, &data);
74 mutex_unlock(&chip->io_lock);
75
76 return ret;
77}
78EXPORT_SYMBOL(pm860x_reg_write);
79
80int pm860x_bulk_read(struct i2c_client *i2c, int reg,
81 int count, unsigned char *buf)
82{
83 struct pm860x_chip *chip = i2c_get_clientdata(i2c);
84 int ret;
85
86 mutex_lock(&chip->io_lock);
87 ret = pm860x_read_device(i2c, reg, count, buf);
88 mutex_unlock(&chip->io_lock);
89
90 return ret;
91}
92EXPORT_SYMBOL(pm860x_bulk_read);
93
94int pm860x_bulk_write(struct i2c_client *i2c, int reg,
95 int count, unsigned char *buf)
96{
97 struct pm860x_chip *chip = i2c_get_clientdata(i2c);
98 int ret;
99
100 mutex_lock(&chip->io_lock);
101 ret = pm860x_write_device(i2c, reg, count, buf);
102 mutex_unlock(&chip->io_lock);
103
104 return ret;
105}
106EXPORT_SYMBOL(pm860x_bulk_write);
107
108int pm860x_set_bits(struct i2c_client *i2c, int reg,
109 unsigned char mask, unsigned char data)
110{
111 struct pm860x_chip *chip = i2c_get_clientdata(i2c);
112 unsigned char value;
113 int ret;
114
115 mutex_lock(&chip->io_lock);
116 ret = pm860x_read_device(i2c, reg, 1, &value);
117 if (ret < 0)
118 goto out;
119 value &= ~mask;
120 value |= data;
121 ret = pm860x_write_device(i2c, reg, 1, &value);
122out:
123 mutex_unlock(&chip->io_lock);
124 return ret;
125}
126EXPORT_SYMBOL(pm860x_set_bits);
127
128
129static const struct i2c_device_id pm860x_id_table[] = {
130 { "88PM860x", 0 },
131 {}
132};
133MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
134
135static int verify_addr(struct i2c_client *i2c)
136{
137 unsigned short addr_8607[] = {0x30, 0x34};
138 unsigned short addr_8606[] = {0x10, 0x11};
139 int size, i;
140
141 if (i2c == NULL)
142 return 0;
143 size = ARRAY_SIZE(addr_8606);
144 for (i = 0; i < size; i++) {
145 if (i2c->addr == *(addr_8606 + i))
146 return CHIP_PM8606;
147 }
148 size = ARRAY_SIZE(addr_8607);
149 for (i = 0; i < size; i++) {
150 if (i2c->addr == *(addr_8607 + i))
151 return CHIP_PM8607;
152 }
153 return 0;
154}
155
156static int __devinit pm860x_probe(struct i2c_client *client,
157 const struct i2c_device_id *id)
158{
159 struct pm860x_platform_data *pdata = client->dev.platform_data;
160 struct pm860x_chip *chip;
161
162 if (!pdata) {
163 pr_info("No platform data in %s!\n", __func__);
164 return -EINVAL;
165 }
166
167 chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
168 if (chip == NULL)
169 return -ENOMEM;
170
171 chip->id = verify_addr(client);
172 chip->client = client;
173 i2c_set_clientdata(client, chip);
174 chip->dev = &client->dev;
175 mutex_init(&chip->io_lock);
176 dev_set_drvdata(chip->dev, chip);
177
178 /*
179 * Both client and companion client shares same platform driver.
180 * Driver distinguishes them by pdata->companion_addr.
181 * pdata->companion_addr is only assigned if companion chip exists.
182 * At the same time, the companion_addr shouldn't equal to client
183 * address.
184 */
185 if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
186 chip->companion_addr = pdata->companion_addr;
187 chip->companion = i2c_new_dummy(chip->client->adapter,
188 chip->companion_addr);
189 i2c_set_clientdata(chip->companion, chip);
190 }
191
192 pm860x_device_init(chip, pdata);
193 return 0;
194}
195
196static int __devexit pm860x_remove(struct i2c_client *client)
197{
198 struct pm860x_chip *chip = i2c_get_clientdata(client);
199
200 pm860x_device_exit(chip);
201 i2c_unregister_device(chip->companion);
202 i2c_set_clientdata(chip->companion, NULL);
203 i2c_set_clientdata(chip->client, NULL);
204 kfree(chip);
205 return 0;
206}
207
208static struct i2c_driver pm860x_driver = {
209 .driver = {
210 .name = "88PM860x",
211 .owner = THIS_MODULE,
212 },
213 .probe = pm860x_probe,
214 .remove = __devexit_p(pm860x_remove),
215 .id_table = pm860x_id_table,
216};
217
218static int __init pm860x_i2c_init(void)
219{
220 int ret;
221 ret = i2c_add_driver(&pm860x_driver);
222 if (ret != 0)
223 pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
224 return ret;
225}
226subsys_initcall(pm860x_i2c_init);
227
228static void __exit pm860x_i2c_exit(void)
229{
230 i2c_del_driver(&pm860x_driver);
231}
232module_exit(pm860x_i2c_exit);
233
234MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x");
235MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
236MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b670d10d5c92..951fa9b93fbe 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -9,6 +9,16 @@ config MFD_CORE
9 tristate 9 tristate
10 default n 10 default n
11 11
12config MFD_88PM860X
13 bool "Support Marvell 88PM8606/88PM8607"
14 depends on I2C=y
15 select MFD_CORE
16 help
17 This supports for Marvell 88PM8606/88PM8607 Power Management IC.
18 This includes the I2C driver and the core APIs _only_, you have to
19 select individual components like voltage regulators, RTC and
20 battery-charger under the corresponding menus.
21
12config MFD_SM501 22config MFD_SM501
13 tristate "Support for Silicon Motion SM501" 23 tristate "Support for Silicon Motion SM501"
14 ---help--- 24 ---help---
@@ -37,7 +47,7 @@ config MFD_ASIC3
37 47
38config MFD_SH_MOBILE_SDHI 48config MFD_SH_MOBILE_SDHI
39 bool "Support for SuperH Mobile SDHI" 49 bool "Support for SuperH Mobile SDHI"
40 depends on SUPERH 50 depends on SUPERH || ARCH_SHMOBILE
41 select MFD_CORE 51 select MFD_CORE
42 ---help--- 52 ---help---
43 This driver supports the SDHI hardware block found in many 53 This driver supports the SDHI hardware block found in many
@@ -68,6 +78,15 @@ config HTC_PASIC3
68 HTC Magician devices, respectively. Actual functionality is 78 HTC Magician devices, respectively. Actual functionality is
69 handled by the leds-pasic3 and ds1wm drivers. 79 handled by the leds-pasic3 and ds1wm drivers.
70 80
81config HTC_I2CPLD
82 bool "HTC I2C PLD chip support"
83 depends on I2C=y && GPIOLIB
84 help
85 If you say yes here you get support for the supposed CPLD
86 found on omap850 HTC devices like the HTC Wizard and HTC Herald.
87 This device provides input and output GPIOs through an I2C
88 interface to one or more sub-chips.
89
71config UCB1400_CORE 90config UCB1400_CORE
72 tristate "Philips UCB1400 Core driver" 91 tristate "Philips UCB1400 Core driver"
73 depends on AC97_BUS 92 depends on AC97_BUS
@@ -184,6 +203,16 @@ config PMIC_ADP5520
184 individual components like LCD backlight, LEDs, GPIOs and Kepad 203 individual components like LCD backlight, LEDs, GPIOs and Kepad
185 under the corresponding menus. 204 under the corresponding menus.
186 205
206config MFD_MAX8925
207 bool "Maxim Semiconductor MAX8925 PMIC Support"
208 depends on I2C=y
209 select MFD_CORE
210 help
211 Say yes here to support for Maxim Semiconductor MAX8925. This is
212 a Power Management IC. This driver provies common support for
213 accessing the device, additional drivers must be enabled in order
214 to use the functionality of the device.
215
187config MFD_WM8400 216config MFD_WM8400
188 tristate "Support Wolfson Microelectronics WM8400" 217 tristate "Support Wolfson Microelectronics WM8400"
189 select MFD_CORE 218 select MFD_CORE
@@ -205,7 +234,7 @@ config MFD_WM831X
205 functionality of the device. 234 functionality of the device.
206 235
207config MFD_WM8350 236config MFD_WM8350
208 tristate 237 bool
209 238
210config MFD_WM8350_CONFIG_MODE_0 239config MFD_WM8350_CONFIG_MODE_0
211 bool 240 bool
@@ -256,9 +285,9 @@ config MFD_WM8352_CONFIG_MODE_3
256 depends on MFD_WM8350 285 depends on MFD_WM8350
257 286
258config MFD_WM8350_I2C 287config MFD_WM8350_I2C
259 tristate "Support Wolfson Microelectronics WM8350 with I2C" 288 bool "Support Wolfson Microelectronics WM8350 with I2C"
260 select MFD_WM8350 289 select MFD_WM8350
261 depends on I2C 290 depends on I2C=y
262 help 291 help
263 The WM8350 is an integrated audio and power management 292 The WM8350 is an integrated audio and power management
264 subsystem with watchdog and RTC functionality for embedded 293 subsystem with watchdog and RTC functionality for embedded
@@ -266,6 +295,18 @@ config MFD_WM8350_I2C
266 I2C as the control interface. Additional options must be 295 I2C as the control interface. Additional options must be
267 selected to enable support for the functionality of the chip. 296 selected to enable support for the functionality of the chip.
268 297
298config MFD_WM8994
299 tristate "Support Wolfson Microelectronics WM8994"
300 select MFD_CORE
301 depends on I2C
302 help
303 The WM8994 is a highly integrated hi-fi CODEC designed for
304 smartphone applicatiosn. As well as audio functionality it
305 has on board GPIO and regulator functionality which is
306 supported via the relevant subsystems. This driver provides
307 core support for the WM8994, in order to use the actual
308 functionaltiy of the device other drivers must be enabled.
309
269config MFD_PCF50633 310config MFD_PCF50633
270 tristate "Support for NXP PCF50633" 311 tristate "Support for NXP PCF50633"
271 depends on I2C 312 depends on I2C
@@ -300,8 +341,8 @@ config PCF50633_GPIO
300 the PCF50633 chip. 341 the PCF50633 chip.
301 342
302config AB3100_CORE 343config AB3100_CORE
303 tristate "ST-Ericsson AB3100 Mixed Signal Circuit core functions" 344 bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
304 depends on I2C 345 depends on I2C=y
305 default y if ARCH_U300 346 default y if ARCH_U300
306 help 347 help
307 Select this to enable the AB3100 Mixed Signal IC core 348 Select this to enable the AB3100 Mixed Signal IC core
@@ -329,16 +370,6 @@ config EZX_PCAP
329 This enables the PCAP ASIC present on EZX Phones. This is 370 This enables the PCAP ASIC present on EZX Phones. This is
330 needed for MMC, TouchScreen, Sound, USB, etc.. 371 needed for MMC, TouchScreen, Sound, USB, etc..
331 372
332config MFD_88PM8607
333 bool "Support Marvell 88PM8607"
334 depends on I2C=y
335 select MFD_CORE
336 help
337 This supports for Marvell 88PM8607 Power Management IC. This includes
338 the I2C driver and the core APIs _only_, you have to select
339 individual components like voltage regulators, RTC and
340 battery-charger under the corresponding menus.
341
342config AB4500_CORE 373config AB4500_CORE
343 tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip" 374 tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip"
344 depends on SPI 375 depends on SPI
@@ -358,6 +389,15 @@ config MFD_TIMBERDALE
358 389
359 The timberdale FPGA can be found on the Intel Atom development board 390 The timberdale FPGA can be found on the Intel Atom development board
360 for in-vehicle infontainment, called Russellville. 391 for in-vehicle infontainment, called Russellville.
392
393config LPC_SCH
394 tristate "Intel SCH LPC"
395 depends on PCI
396 select MFD_CORE
397 help
398 LPC bridge function of the Intel SCH provides support for
399 System Management Bus and General Purpose I/O.
400
361endmenu 401endmenu
362 402
363menu "Multimedia Capabilities Port drivers" 403menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 78295d6a75f7..22715add99a7 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -2,12 +2,15 @@
2# Makefile for multifunction miscellaneous devices 2# Makefile for multifunction miscellaneous devices
3# 3#
4 4
588pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o
6obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o
5obj-$(CONFIG_MFD_SM501) += sm501.o 7obj-$(CONFIG_MFD_SM501) += sm501.o
6obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o 8obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
7obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o 9obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o
8 10
9obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o 11obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
10obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o 12obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
13obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
11 14
12obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o 15obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
13 16
@@ -22,6 +25,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
22wm8350-objs += wm8350-irq.o 25wm8350-objs += wm8350-irq.o
23obj-$(CONFIG_MFD_WM8350) += wm8350.o 26obj-$(CONFIG_MFD_WM8350) += wm8350.o
24obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o 27obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
28obj-$(CONFIG_MFD_WM8994) += wm8994-core.o
25 29
26obj-$(CONFIG_TPS65010) += tps65010.o 30obj-$(CONFIG_TPS65010) += tps65010.o
27obj-$(CONFIG_MENELAUS) += menelaus.o 31obj-$(CONFIG_MENELAUS) += menelaus.o
@@ -47,6 +51,8 @@ endif
47obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o 51obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
48 52
49obj-$(CONFIG_PMIC_DA903X) += da903x.o 53obj-$(CONFIG_PMIC_DA903X) += da903x.o
54max8925-objs := max8925-core.o max8925-i2c.o
55obj-$(CONFIG_MFD_MAX8925) += max8925.o
50 56
51obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o 57obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o
52obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o 58obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
@@ -55,5 +61,5 @@ obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
55obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o 61obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
56obj-$(CONFIG_AB4500_CORE) += ab4500-core.o 62obj-$(CONFIG_AB4500_CORE) += ab4500-core.o
57obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o 63obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
58obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o
59obj-$(CONFIG_PMIC_ADP5520) += adp5520.o 64obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
65obj-$(CONFIG_LPC_SCH) += lpc_sch.o \ No newline at end of file
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index fd42a80e7bf9..a2ce3b6af4a2 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2007-2009 ST-Ericsson 2 * Copyright (C) 2007-2010 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2 3 * License terms: GNU General Public License (GPL) version 2
4 * Low-level core for exclusive access to the AB3100 IC on the I2C bus 4 * Low-level core for exclusive access to the AB3100 IC on the I2C bus
5 * and some basic chip-configuration. 5 * and some basic chip-configuration.
@@ -14,6 +14,7 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/random.h>
17#include <linux/debugfs.h> 18#include <linux/debugfs.h>
18#include <linux/seq_file.h> 19#include <linux/seq_file.h>
19#include <linux/uaccess.h> 20#include <linux/uaccess.h>
@@ -365,18 +366,23 @@ int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100,
365} 366}
366EXPORT_SYMBOL(ab3100_event_registers_startup_state_get); 367EXPORT_SYMBOL(ab3100_event_registers_startup_state_get);
367 368
368/* Interrupt handling worker */ 369/*
369static void ab3100_work(struct work_struct *work) 370 * This is a threaded interrupt handler so we can make some
371 * I2C calls etc.
372 */
373static irqreturn_t ab3100_irq_handler(int irq, void *data)
370{ 374{
371 struct ab3100 *ab3100 = container_of(work, struct ab3100, work); 375 struct ab3100 *ab3100 = data;
372 u8 event_regs[3]; 376 u8 event_regs[3];
373 u32 fatevent; 377 u32 fatevent;
374 int err; 378 int err;
375 379
380 add_interrupt_randomness(irq);
381
376 err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1, 382 err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
377 event_regs, 3); 383 event_regs, 3);
378 if (err) 384 if (err)
379 goto err_event_wq; 385 goto err_event;
380 386
381 fatevent = (event_regs[0] << 16) | 387 fatevent = (event_regs[0] << 16) |
382 (event_regs[1] << 8) | 388 (event_regs[1] << 8) |
@@ -398,29 +404,11 @@ static void ab3100_work(struct work_struct *work)
398 dev_dbg(ab3100->dev, 404 dev_dbg(ab3100->dev,
399 "IRQ Event: 0x%08x\n", fatevent); 405 "IRQ Event: 0x%08x\n", fatevent);
400 406
401 /* By now the IRQ should be acked and deasserted so enable it again */ 407 return IRQ_HANDLED;
402 enable_irq(ab3100->i2c_client->irq);
403 return;
404 408
405 err_event_wq: 409 err_event:
406 dev_dbg(ab3100->dev, 410 dev_dbg(ab3100->dev,
407 "error in event workqueue\n"); 411 "error reading event status\n");
408 /* Enable the IRQ anyway, what choice do we have? */
409 enable_irq(ab3100->i2c_client->irq);
410 return;
411}
412
413static irqreturn_t ab3100_irq_handler(int irq, void *data)
414{
415 struct ab3100 *ab3100 = data;
416 /*
417 * Disable the IRQ and dispatch a worker to handle the
418 * event. Since the chip resides on I2C this is slow
419 * stuff and we will re-enable the interrupts once th
420 * worker has finished.
421 */
422 disable_irq_nosync(irq);
423 schedule_work(&ab3100->work);
424 return IRQ_HANDLED; 412 return IRQ_HANDLED;
425} 413}
426 414
@@ -735,10 +723,7 @@ static struct platform_device ab3100_##devname##_device = { \
735 .id = -1, \ 723 .id = -1, \
736} 724}
737 725
738/* 726/* This lists all the subdevices */
739 * This lists all the subdevices and corresponding register
740 * ranges.
741 */
742AB3100_DEVICE(dac, "ab3100-dac"); 727AB3100_DEVICE(dac, "ab3100-dac");
743AB3100_DEVICE(leds, "ab3100-leds"); 728AB3100_DEVICE(leds, "ab3100-leds");
744AB3100_DEVICE(power, "ab3100-power"); 729AB3100_DEVICE(power, "ab3100-power");
@@ -904,12 +889,11 @@ static int __init ab3100_probe(struct i2c_client *client,
904 if (err) 889 if (err)
905 goto exit_no_setup; 890 goto exit_no_setup;
906 891
907 INIT_WORK(&ab3100->work, ab3100_work); 892 err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler,
908 893 IRQF_ONESHOT, "ab3100-core", ab3100);
909 /* This real unpredictable IRQ is of course sampled for entropy */ 894 /* This real unpredictable IRQ is of course sampled for entropy */
910 err = request_irq(client->irq, ab3100_irq_handler, 895 rand_initialize_irq(client->irq);
911 IRQF_DISABLED | IRQF_SAMPLE_RANDOM, 896
912 "AB3100 IRQ", ab3100);
913 if (err) 897 if (err)
914 goto exit_no_irq; 898 goto exit_no_irq;
915 899
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c
index 0499b2031a2c..b603469dff69 100644
--- a/drivers/mfd/ab3100-otp.c
+++ b/drivers/mfd/ab3100-otp.c
@@ -13,6 +13,7 @@
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/mfd/ab3100.h> 14#include <linux/mfd/ab3100.h>
15#include <linux/debugfs.h> 15#include <linux/debugfs.h>
16#include <linux/seq_file.h>
16 17
17/* The OTP registers */ 18/* The OTP registers */
18#define AB3100_OTP0 0xb0 19#define AB3100_OTP0 0xb0
@@ -95,11 +96,10 @@ static int __init ab3100_otp_read(struct ab3100_otp *otp)
95 * This is a simple debugfs human-readable file that dumps out 96 * This is a simple debugfs human-readable file that dumps out
96 * the contents of the OTP. 97 * the contents of the OTP.
97 */ 98 */
98#ifdef CONFIG_DEBUGFS 99#ifdef CONFIG_DEBUG_FS
99static int show_otp(struct seq_file *s, void *v) 100static int ab3100_show_otp(struct seq_file *s, void *v)
100{ 101{
101 struct ab3100_otp *otp = s->private; 102 struct ab3100_otp *otp = s->private;
102 int err;
103 103
104 seq_printf(s, "OTP is %s\n", otp->locked ? "LOCKED" : "UNLOCKED"); 104 seq_printf(s, "OTP is %s\n", otp->locked ? "LOCKED" : "UNLOCKED");
105 seq_printf(s, "OTP clock switch startup is %uHz\n", otp->freq); 105 seq_printf(s, "OTP clock switch startup is %uHz\n", otp->freq);
@@ -113,7 +113,7 @@ static int show_otp(struct seq_file *s, void *v)
113 113
114static int ab3100_otp_open(struct inode *inode, struct file *file) 114static int ab3100_otp_open(struct inode *inode, struct file *file)
115{ 115{
116 return single_open(file, ab3100_otp_show, inode->i_private); 116 return single_open(file, ab3100_show_otp, inode->i_private);
117} 117}
118 118
119static const struct file_operations ab3100_otp_operations = { 119static const struct file_operations ab3100_otp_operations = {
@@ -131,13 +131,14 @@ static int __init ab3100_otp_init_debugfs(struct device *dev,
131 &ab3100_otp_operations); 131 &ab3100_otp_operations);
132 if (!otp->debugfs) { 132 if (!otp->debugfs) {
133 dev_err(dev, "AB3100 debugfs OTP file registration failed!\n"); 133 dev_err(dev, "AB3100 debugfs OTP file registration failed!\n");
134 return err; 134 return -ENOENT;
135 } 135 }
136 return 0;
136} 137}
137 138
138static void __exit ab3100_otp_exit_debugfs(struct ab3100_otp *otp) 139static void __exit ab3100_otp_exit_debugfs(struct ab3100_otp *otp)
139{ 140{
140 debugfs_remove_file(otp->debugfs); 141 debugfs_remove(otp->debugfs);
141} 142}
142#else 143#else
143/* Compile this out if debugfs not selected */ 144/* Compile this out if debugfs not selected */
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
new file mode 100644
index 000000000000..37b9fdab4f36
--- /dev/null
+++ b/drivers/mfd/htc-i2cpld.c
@@ -0,0 +1,710 @@
1/*
2 * htc-i2cpld.c
3 * Chip driver for an unknown CPLD chip found on omap850 HTC devices like
4 * the HTC Wizard and HTC Herald.
5 * The cpld is located on the i2c bus and acts as an input/output GPIO
6 * extender.
7 *
8 * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
9 *
10 * Based on work done in the linwizard project
11 * Copyright (C) 2008-2009 Angelo Arrifano <miknix@gmail.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <linux/module.h>
31#include <linux/interrupt.h>
32#include <linux/platform_device.h>
33#include <linux/i2c.h>
34#include <linux/irq.h>
35#include <linux/spinlock.h>
36#include <linux/htcpld.h>
37#include <linux/gpio.h>
38
39struct htcpld_chip {
40 spinlock_t lock;
41
42 /* chip info */
43 u8 reset;
44 u8 addr;
45 struct device *dev;
46 struct i2c_client *client;
47
48 /* Output details */
49 u8 cache_out;
50 struct gpio_chip chip_out;
51
52 /* Input details */
53 u8 cache_in;
54 struct gpio_chip chip_in;
55
56 u16 irqs_enabled;
57 uint irq_start;
58 int nirqs;
59
60 /*
61 * Work structure to allow for setting values outside of any
62 * possible interrupt context
63 */
64 struct work_struct set_val_work;
65};
66
67struct htcpld_data {
68 /* irq info */
69 u16 irqs_enabled;
70 uint irq_start;
71 int nirqs;
72 uint chained_irq;
73 unsigned int int_reset_gpio_hi;
74 unsigned int int_reset_gpio_lo;
75
76 /* htcpld info */
77 struct htcpld_chip *chip;
78 unsigned int nchips;
79};
80
81/* There does not appear to be a way to proactively mask interrupts
82 * on the htcpld chip itself. So, we simply ignore interrupts that
83 * aren't desired. */
84static void htcpld_mask(unsigned int irq)
85{
86 struct htcpld_chip *chip = get_irq_chip_data(irq);
87 chip->irqs_enabled &= ~(1 << (irq - chip->irq_start));
88 pr_debug("HTCPLD mask %d %04x\n", irq, chip->irqs_enabled);
89}
90static void htcpld_unmask(unsigned int irq)
91{
92 struct htcpld_chip *chip = get_irq_chip_data(irq);
93 chip->irqs_enabled |= 1 << (irq - chip->irq_start);
94 pr_debug("HTCPLD unmask %d %04x\n", irq, chip->irqs_enabled);
95}
96
97static int htcpld_set_type(unsigned int irq, unsigned int flags)
98{
99 struct irq_desc *d = irq_to_desc(irq);
100
101 if (!d) {
102 pr_err("HTCPLD invalid IRQ: %d\n", irq);
103 return -EINVAL;
104 }
105
106 if (flags & ~IRQ_TYPE_SENSE_MASK)
107 return -EINVAL;
108
109 /* We only allow edge triggering */
110 if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
111 return -EINVAL;
112
113 d->status &= ~IRQ_TYPE_SENSE_MASK;
114 d->status |= flags;
115
116 return 0;
117}
118
119static struct irq_chip htcpld_muxed_chip = {
120 .name = "htcpld",
121 .mask = htcpld_mask,
122 .unmask = htcpld_unmask,
123 .set_type = htcpld_set_type,
124};
125
126/* To properly dispatch IRQ events, we need to read from the
127 * chip. This is an I2C action that could possibly sleep
128 * (which is bad in interrupt context) -- so we use a threaded
129 * interrupt handler to get around that.
130 */
131static irqreturn_t htcpld_handler(int irq, void *dev)
132{
133 struct htcpld_data *htcpld = dev;
134 unsigned int i;
135 unsigned long flags;
136 int irqpin;
137 struct irq_desc *desc;
138
139 if (!htcpld) {
140 pr_debug("htcpld is null in ISR\n");
141 return IRQ_HANDLED;
142 }
143
144 /*
145 * For each chip, do a read of the chip and trigger any interrupts
146 * desired. The interrupts will be triggered from LSB to MSB (i.e.
147 * bit 0 first, then bit 1, etc.)
148 *
149 * For chips that have no interrupt range specified, just skip 'em.
150 */
151 for (i = 0; i < htcpld->nchips; i++) {
152 struct htcpld_chip *chip = &htcpld->chip[i];
153 struct i2c_client *client;
154 int val;
155 unsigned long uval, old_val;
156
157 if (!chip) {
158 pr_debug("chip %d is null in ISR\n", i);
159 continue;
160 }
161
162 if (chip->nirqs == 0)
163 continue;
164
165 client = chip->client;
166 if (!client) {
167 pr_debug("client %d is null in ISR\n", i);
168 continue;
169 }
170
171 /* Scan the chip */
172 val = i2c_smbus_read_byte_data(client, chip->cache_out);
173 if (val < 0) {
174 /* Throw a warning and skip this chip */
175 dev_warn(chip->dev, "Unable to read from chip: %d\n",
176 val);
177 continue;
178 }
179
180 uval = (unsigned long)val;
181
182 spin_lock_irqsave(&chip->lock, flags);
183
184 /* Save away the old value so we can compare it */
185 old_val = chip->cache_in;
186
187 /* Write the new value */
188 chip->cache_in = uval;
189
190 spin_unlock_irqrestore(&chip->lock, flags);
191
192 /*
193 * For each bit in the data (starting at bit 0), trigger
194 * associated interrupts.
195 */
196 for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
197 unsigned oldb, newb;
198 int flags;
199
200 irq = chip->irq_start + irqpin;
201 desc = irq_to_desc(irq);
202 flags = desc->status;
203
204 /* Run the IRQ handler, but only if the bit value
205 * changed, and the proper flags are set */
206 oldb = (old_val >> irqpin) & 1;
207 newb = (uval >> irqpin) & 1;
208
209 if ((!oldb && newb && (flags & IRQ_TYPE_EDGE_RISING)) ||
210 (oldb && !newb &&
211 (flags & IRQ_TYPE_EDGE_FALLING))) {
212 pr_debug("fire IRQ %d\n", irqpin);
213 desc->handle_irq(irq, desc);
214 }
215 }
216 }
217
218 /*
219 * In order to continue receiving interrupts, the int_reset_gpio must
220 * be asserted.
221 */
222 if (htcpld->int_reset_gpio_hi)
223 gpio_set_value(htcpld->int_reset_gpio_hi, 1);
224 if (htcpld->int_reset_gpio_lo)
225 gpio_set_value(htcpld->int_reset_gpio_lo, 0);
226
227 return IRQ_HANDLED;
228}
229
230/*
231 * The GPIO set routines can be called from interrupt context, especially if,
232 * for example they're attached to the led-gpio framework and a trigger is
233 * enabled. As such, we declared work above in the htcpld_chip structure,
234 * and that work is scheduled in the set routine. The kernel can then run
235 * the I2C functions, which will sleep, in process context.
236 */
237void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
238{
239 struct i2c_client *client;
240 struct htcpld_chip *chip_data;
241 unsigned long flags;
242
243 chip_data = container_of(chip, struct htcpld_chip, chip_out);
244 if (!chip_data)
245 return;
246
247 client = chip_data->client;
248 if (client == NULL)
249 return;
250
251 spin_lock_irqsave(&chip_data->lock, flags);
252 if (val)
253 chip_data->cache_out |= (1 << offset);
254 else
255 chip_data->cache_out &= ~(1 << offset);
256 spin_unlock_irqrestore(&chip_data->lock, flags);
257
258 schedule_work(&(chip_data->set_val_work));
259}
260
261void htcpld_chip_set_ni(struct work_struct *work)
262{
263 struct htcpld_chip *chip_data;
264 struct i2c_client *client;
265
266 chip_data = container_of(work, struct htcpld_chip, set_val_work);
267 client = chip_data->client;
268 i2c_smbus_read_byte_data(client, chip_data->cache_out);
269}
270
271int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
272{
273 struct htcpld_chip *chip_data;
274 int val = 0;
275 int is_input = 0;
276
277 /* Try out first */
278 chip_data = container_of(chip, struct htcpld_chip, chip_out);
279 if (!chip_data) {
280 /* Try in */
281 is_input = 1;
282 chip_data = container_of(chip, struct htcpld_chip, chip_in);
283 if (!chip_data)
284 return -EINVAL;
285 }
286
287 /* Determine if this is an input or output GPIO */
288 if (!is_input)
289 /* Use the output cache */
290 val = (chip_data->cache_out >> offset) & 1;
291 else
292 /* Use the input cache */
293 val = (chip_data->cache_in >> offset) & 1;
294
295 if (val)
296 return 1;
297 else
298 return 0;
299}
300
301static int htcpld_direction_output(struct gpio_chip *chip,
302 unsigned offset, int value)
303{
304 htcpld_chip_set(chip, offset, value);
305 return 0;
306}
307
308static int htcpld_direction_input(struct gpio_chip *chip,
309 unsigned offset)
310{
311 /*
312 * No-op: this function can only be called on the input chip.
313 * We do however make sure the offset is within range.
314 */
315 return (offset < chip->ngpio) ? 0 : -EINVAL;
316}
317
318int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
319{
320 struct htcpld_chip *chip_data;
321
322 chip_data = container_of(chip, struct htcpld_chip, chip_in);
323
324 if (offset < chip_data->nirqs)
325 return chip_data->irq_start + offset;
326 else
327 return -EINVAL;
328}
329
330void htcpld_chip_reset(struct i2c_client *client)
331{
332 struct htcpld_chip *chip_data = i2c_get_clientdata(client);
333 if (!chip_data)
334 return;
335
336 i2c_smbus_read_byte_data(
337 client, (chip_data->cache_out = chip_data->reset));
338}
339
340static int __devinit htcpld_setup_chip_irq(
341 struct platform_device *pdev,
342 int chip_index)
343{
344 struct htcpld_data *htcpld;
345 struct device *dev = &pdev->dev;
346 struct htcpld_core_platform_data *pdata;
347 struct htcpld_chip *chip;
348 struct htcpld_chip_platform_data *plat_chip_data;
349 unsigned int irq, irq_end;
350 int ret = 0;
351
352 /* Get the platform and driver data */
353 pdata = dev->platform_data;
354 htcpld = platform_get_drvdata(pdev);
355 chip = &htcpld->chip[chip_index];
356 plat_chip_data = &pdata->chip[chip_index];
357
358 /* Setup irq handlers */
359 irq_end = chip->irq_start + chip->nirqs;
360 for (irq = chip->irq_start; irq < irq_end; irq++) {
361 set_irq_chip(irq, &htcpld_muxed_chip);
362 set_irq_chip_data(irq, chip);
363 set_irq_handler(irq, handle_simple_irq);
364#ifdef CONFIG_ARM
365 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
366#else
367 set_irq_probe(irq);
368#endif
369 }
370
371 return ret;
372}
373
374static int __devinit htcpld_register_chip_i2c(
375 struct platform_device *pdev,
376 int chip_index)
377{
378 struct htcpld_data *htcpld;
379 struct device *dev = &pdev->dev;
380 struct htcpld_core_platform_data *pdata;
381 struct htcpld_chip *chip;
382 struct htcpld_chip_platform_data *plat_chip_data;
383 struct i2c_adapter *adapter;
384 struct i2c_client *client;
385 struct i2c_board_info info;
386
387 /* Get the platform and driver data */
388 pdata = dev->platform_data;
389 htcpld = platform_get_drvdata(pdev);
390 chip = &htcpld->chip[chip_index];
391 plat_chip_data = &pdata->chip[chip_index];
392
393 adapter = i2c_get_adapter(pdata->i2c_adapter_id);
394 if (adapter == NULL) {
395 /* Eek, no such I2C adapter! Bail out. */
396 dev_warn(dev, "Chip at i2c address 0x%x: Invalid i2c adapter %d\n",
397 plat_chip_data->addr, pdata->i2c_adapter_id);
398 return -ENODEV;
399 }
400
401 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
402 dev_warn(dev, "i2c adapter %d non-functional\n",
403 pdata->i2c_adapter_id);
404 return -EINVAL;
405 }
406
407 memset(&info, 0, sizeof(struct i2c_board_info));
408 info.addr = plat_chip_data->addr;
409 strlcpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
410 info.platform_data = chip;
411
412 /* Add the I2C device. This calls the probe() function. */
413 client = i2c_new_device(adapter, &info);
414 if (!client) {
415 /* I2C device registration failed, contineu with the next */
416 dev_warn(dev, "Unable to add I2C device for 0x%x\n",
417 plat_chip_data->addr);
418 return -ENODEV;
419 }
420
421 i2c_set_clientdata(client, chip);
422 snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%d", client->addr);
423 chip->client = client;
424
425 /* Reset the chip */
426 htcpld_chip_reset(client);
427 chip->cache_in = i2c_smbus_read_byte_data(client, chip->cache_out);
428
429 return 0;
430}
431
432static void __devinit htcpld_unregister_chip_i2c(
433 struct platform_device *pdev,
434 int chip_index)
435{
436 struct htcpld_data *htcpld;
437 struct htcpld_chip *chip;
438
439 /* Get the platform and driver data */
440 htcpld = platform_get_drvdata(pdev);
441 chip = &htcpld->chip[chip_index];
442
443 if (chip->client)
444 i2c_unregister_device(chip->client);
445}
446
447static int __devinit htcpld_register_chip_gpio(
448 struct platform_device *pdev,
449 int chip_index)
450{
451 struct htcpld_data *htcpld;
452 struct device *dev = &pdev->dev;
453 struct htcpld_core_platform_data *pdata;
454 struct htcpld_chip *chip;
455 struct htcpld_chip_platform_data *plat_chip_data;
456 struct gpio_chip *gpio_chip;
457 int ret = 0;
458
459 /* Get the platform and driver data */
460 pdata = dev->platform_data;
461 htcpld = platform_get_drvdata(pdev);
462 chip = &htcpld->chip[chip_index];
463 plat_chip_data = &pdata->chip[chip_index];
464
465 /* Setup the GPIO chips */
466 gpio_chip = &(chip->chip_out);
467 gpio_chip->label = "htcpld-out";
468 gpio_chip->dev = dev;
469 gpio_chip->owner = THIS_MODULE;
470 gpio_chip->get = htcpld_chip_get;
471 gpio_chip->set = htcpld_chip_set;
472 gpio_chip->direction_input = NULL;
473 gpio_chip->direction_output = htcpld_direction_output;
474 gpio_chip->base = plat_chip_data->gpio_out_base;
475 gpio_chip->ngpio = plat_chip_data->num_gpios;
476
477 gpio_chip = &(chip->chip_in);
478 gpio_chip->label = "htcpld-in";
479 gpio_chip->dev = dev;
480 gpio_chip->owner = THIS_MODULE;
481 gpio_chip->get = htcpld_chip_get;
482 gpio_chip->set = NULL;
483 gpio_chip->direction_input = htcpld_direction_input;
484 gpio_chip->direction_output = NULL;
485 gpio_chip->to_irq = htcpld_chip_to_irq;
486 gpio_chip->base = plat_chip_data->gpio_in_base;
487 gpio_chip->ngpio = plat_chip_data->num_gpios;
488
489 /* Add the GPIO chips */
490 ret = gpiochip_add(&(chip->chip_out));
491 if (ret) {
492 dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n",
493 plat_chip_data->addr, ret);
494 return ret;
495 }
496
497 ret = gpiochip_add(&(chip->chip_in));
498 if (ret) {
499 int error;
500
501 dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
502 plat_chip_data->addr, ret);
503
504 error = gpiochip_remove(&(chip->chip_out));
505 if (error)
506 dev_warn(dev, "Error while trying to unregister gpio chip: %d\n", error);
507
508 return ret;
509 }
510
511 return 0;
512}
513
514static int __devinit htcpld_setup_chips(struct platform_device *pdev)
515{
516 struct htcpld_data *htcpld;
517 struct device *dev = &pdev->dev;
518 struct htcpld_core_platform_data *pdata;
519 int i;
520
521 /* Get the platform and driver data */
522 pdata = dev->platform_data;
523 htcpld = platform_get_drvdata(pdev);
524
525 /* Setup each chip's output GPIOs */
526 htcpld->nchips = pdata->num_chip;
527 htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips,
528 GFP_KERNEL);
529 if (!htcpld->chip) {
530 dev_warn(dev, "Unable to allocate memory for chips\n");
531 return -ENOMEM;
532 }
533
534 /* Add the chips as best we can */
535 for (i = 0; i < htcpld->nchips; i++) {
536 int ret;
537
538 /* Setup the HTCPLD chips */
539 htcpld->chip[i].reset = pdata->chip[i].reset;
540 htcpld->chip[i].cache_out = pdata->chip[i].reset;
541 htcpld->chip[i].cache_in = 0;
542 htcpld->chip[i].dev = dev;
543 htcpld->chip[i].irq_start = pdata->chip[i].irq_base;
544 htcpld->chip[i].nirqs = pdata->chip[i].num_irqs;
545
546 INIT_WORK(&(htcpld->chip[i].set_val_work), &htcpld_chip_set_ni);
547 spin_lock_init(&(htcpld->chip[i].lock));
548
549 /* Setup the interrupts for the chip */
550 if (htcpld->chained_irq) {
551 ret = htcpld_setup_chip_irq(pdev, i);
552 if (ret)
553 continue;
554 }
555
556 /* Register the chip with I2C */
557 ret = htcpld_register_chip_i2c(pdev, i);
558 if (ret)
559 continue;
560
561
562 /* Register the chips with the GPIO subsystem */
563 ret = htcpld_register_chip_gpio(pdev, i);
564 if (ret) {
565 /* Unregister the chip from i2c and continue */
566 htcpld_unregister_chip_i2c(pdev, i);
567 continue;
568 }
569
570 dev_info(dev, "Registered chip at 0x%x\n", pdata->chip[i].addr);
571 }
572
573 return 0;
574}
575
576static int __devinit htcpld_core_probe(struct platform_device *pdev)
577{
578 struct htcpld_data *htcpld;
579 struct device *dev = &pdev->dev;
580 struct htcpld_core_platform_data *pdata;
581 struct resource *res;
582 int ret = 0;
583
584 if (!dev)
585 return -ENODEV;
586
587 pdata = dev->platform_data;
588 if (!pdata) {
589 dev_warn(dev, "Platform data not found for htcpld core!\n");
590 return -ENXIO;
591 }
592
593 htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL);
594 if (!htcpld)
595 return -ENOMEM;
596
597 /* Find chained irq */
598 ret = -EINVAL;
599 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
600 if (res) {
601 int flags;
602 htcpld->chained_irq = res->start;
603
604 /* Setup the chained interrupt handler */
605 flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
606 ret = request_threaded_irq(htcpld->chained_irq,
607 NULL, htcpld_handler,
608 flags, pdev->name, htcpld);
609 if (ret) {
610 dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
611 goto fail;
612 } else
613 device_init_wakeup(dev, 0);
614 }
615
616 /* Set the driver data */
617 platform_set_drvdata(pdev, htcpld);
618
619 /* Setup the htcpld chips */
620 ret = htcpld_setup_chips(pdev);
621 if (ret)
622 goto fail;
623
624 /* Request the GPIO(s) for the int reset and set them up */
625 if (pdata->int_reset_gpio_hi) {
626 ret = gpio_request(pdata->int_reset_gpio_hi, "htcpld-core");
627 if (ret) {
628 /*
629 * If it failed, that sucks, but we can probably
630 * continue on without it.
631 */
632 dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
633 htcpld->int_reset_gpio_hi = 0;
634 } else {
635 htcpld->int_reset_gpio_hi = pdata->int_reset_gpio_hi;
636 gpio_set_value(htcpld->int_reset_gpio_hi, 1);
637 }
638 }
639
640 if (pdata->int_reset_gpio_lo) {
641 ret = gpio_request(pdata->int_reset_gpio_lo, "htcpld-core");
642 if (ret) {
643 /*
644 * If it failed, that sucks, but we can probably
645 * continue on without it.
646 */
647 dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
648 htcpld->int_reset_gpio_lo = 0;
649 } else {
650 htcpld->int_reset_gpio_lo = pdata->int_reset_gpio_lo;
651 gpio_set_value(htcpld->int_reset_gpio_lo, 0);
652 }
653 }
654
655 dev_info(dev, "Initialized successfully\n");
656 return 0;
657
658fail:
659 kfree(htcpld);
660 return ret;
661}
662
663/* The I2C Driver -- used internally */
664static const struct i2c_device_id htcpld_chip_id[] = {
665 { "htcpld-chip", 0 },
666 { }
667};
668MODULE_DEVICE_TABLE(i2c, htcpld_chip_id);
669
670
671static struct i2c_driver htcpld_chip_driver = {
672 .driver = {
673 .name = "htcpld-chip",
674 },
675 .id_table = htcpld_chip_id,
676};
677
678/* The Core Driver */
679static struct platform_driver htcpld_core_driver = {
680 .driver = {
681 .name = "i2c-htcpld",
682 },
683};
684
685static int __init htcpld_core_init(void)
686{
687 int ret;
688
689 /* Register the I2C Chip driver */
690 ret = i2c_add_driver(&htcpld_chip_driver);
691 if (ret)
692 return ret;
693
694 /* Probe for our chips */
695 return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
696}
697
698static void __exit htcpld_core_exit(void)
699{
700 i2c_del_driver(&htcpld_chip_driver);
701 platform_driver_unregister(&htcpld_core_driver);
702}
703
704module_init(htcpld_core_init);
705module_exit(htcpld_core_exit);
706
707MODULE_AUTHOR("Cory Maccarrone <darkstar6262@gmail.com>");
708MODULE_DESCRIPTION("I2C HTC PLD Driver");
709MODULE_LICENSE("GPL");
710
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
new file mode 100644
index 000000000000..51b2f6065a0b
--- /dev/null
+++ b/drivers/mfd/lpc_sch.c
@@ -0,0 +1,133 @@
1/*
2 * lpc_sch.c - LPC interface for Intel Poulsbo SCH
3 *
4 * LPC bridge function of the Intel SCH contains many other
5 * functional units, such as Interrupt controllers, Timers,
6 * Power Management, System Management, GPIO, RTC, and LPC
7 * Configuration Registers.
8 *
9 * Copyright (c) 2010 CompuLab Ltd
10 * Author: Denis Turischev <denis@compulab.co.il>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/init.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/errno.h>
30#include <linux/acpi.h>
31#include <linux/pci.h>
32#include <linux/mfd/core.h>
33
34#define SMBASE 0x40
35#define SMBUS_IO_SIZE 64
36
37#define GPIOBASE 0x44
38#define GPIO_IO_SIZE 64
39
40static struct resource smbus_sch_resource = {
41 .flags = IORESOURCE_IO,
42};
43
44
45static struct resource gpio_sch_resource = {
46 .flags = IORESOURCE_IO,
47};
48
49static struct mfd_cell lpc_sch_cells[] = {
50 {
51 .name = "isch_smbus",
52 .num_resources = 1,
53 .resources = &smbus_sch_resource,
54 },
55 {
56 .name = "sch_gpio",
57 .num_resources = 1,
58 .resources = &gpio_sch_resource,
59 },
60};
61
62static struct pci_device_id lpc_sch_ids[] = {
63 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
64 { 0, }
65};
66MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
67
68static int __devinit lpc_sch_probe(struct pci_dev *dev,
69 const struct pci_device_id *id)
70{
71 unsigned int base_addr_cfg;
72 unsigned short base_addr;
73
74 pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
75 if (!(base_addr_cfg & (1 << 31))) {
76 dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n");
77 return -ENODEV;
78 }
79 base_addr = (unsigned short)base_addr_cfg;
80 if (base_addr == 0) {
81 dev_err(&dev->dev, "I/O space for SMBus uninitialized\n");
82 return -ENODEV;
83 }
84
85 smbus_sch_resource.start = base_addr;
86 smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
87
88 pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
89 if (!(base_addr_cfg & (1 << 31))) {
90 dev_err(&dev->dev, "Decode of the GPIO I/O range disabled\n");
91 return -ENODEV;
92 }
93 base_addr = (unsigned short)base_addr_cfg;
94 if (base_addr == 0) {
95 dev_err(&dev->dev, "I/O space for GPIO uninitialized\n");
96 return -ENODEV;
97 }
98
99 gpio_sch_resource.start = base_addr;
100 gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
101
102 return mfd_add_devices(&dev->dev, -1,
103 lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
104}
105
106static void __devexit lpc_sch_remove(struct pci_dev *dev)
107{
108 mfd_remove_devices(&dev->dev);
109}
110
111static struct pci_driver lpc_sch_driver = {
112 .name = "lpc_sch",
113 .id_table = lpc_sch_ids,
114 .probe = lpc_sch_probe,
115 .remove = __devexit_p(lpc_sch_remove),
116};
117
118static int __init lpc_sch_init(void)
119{
120 return pci_register_driver(&lpc_sch_driver);
121}
122
123static void __exit lpc_sch_exit(void)
124{
125 pci_unregister_driver(&lpc_sch_driver);
126}
127
128module_init(lpc_sch_init);
129module_exit(lpc_sch_exit);
130
131MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
132MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH");
133MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
new file mode 100644
index 000000000000..85d63c04749b
--- /dev/null
+++ b/drivers/mfd/max8925-core.c
@@ -0,0 +1,656 @@
1/*
2 * Base driver for Maxim MAX8925
3 *
4 * Copyright (C) 2009-2010 Marvell International Ltd.
5 * 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/i2c.h>
15#include <linux/irq.h>
16#include <linux/interrupt.h>
17#include <linux/platform_device.h>
18#include <linux/mfd/core.h>
19#include <linux/mfd/max8925.h>
20
21static struct resource backlight_resources[] = {
22 {
23 .name = "max8925-backlight",
24 .start = MAX8925_WLED_MODE_CNTL,
25 .end = MAX8925_WLED_CNTL,
26 .flags = IORESOURCE_IO,
27 },
28};
29
30static struct mfd_cell backlight_devs[] = {
31 {
32 .name = "max8925-backlight",
33 .num_resources = 1,
34 .resources = &backlight_resources[0],
35 .id = -1,
36 },
37};
38
39static struct resource touch_resources[] = {
40 {
41 .name = "max8925-tsc",
42 .start = MAX8925_TSC_IRQ,
43 .end = MAX8925_ADC_RES_END,
44 .flags = IORESOURCE_IO,
45 },
46};
47
48static struct mfd_cell touch_devs[] = {
49 {
50 .name = "max8925-touch",
51 .num_resources = 1,
52 .resources = &touch_resources[0],
53 .id = -1,
54 },
55};
56
57static struct resource power_supply_resources[] = {
58 {
59 .name = "max8925-power",
60 .start = MAX8925_CHG_IRQ1,
61 .end = MAX8925_CHG_IRQ1_MASK,
62 .flags = IORESOURCE_IO,
63 },
64};
65
66static struct mfd_cell power_devs[] = {
67 {
68 .name = "max8925-power",
69 .num_resources = 1,
70 .resources = &power_supply_resources[0],
71 .id = -1,
72 },
73};
74
75static struct resource rtc_resources[] = {
76 {
77 .name = "max8925-rtc",
78 .start = MAX8925_RTC_IRQ,
79 .end = MAX8925_RTC_IRQ_MASK,
80 .flags = IORESOURCE_IO,
81 },
82};
83
84static struct mfd_cell rtc_devs[] = {
85 {
86 .name = "max8925-rtc",
87 .num_resources = 1,
88 .resources = &rtc_resources[0],
89 .id = -1,
90 },
91};
92
93#define MAX8925_REG_RESOURCE(_start, _end) \
94{ \
95 .start = MAX8925_##_start, \
96 .end = MAX8925_##_end, \
97 .flags = IORESOURCE_IO, \
98}
99
100static struct resource regulator_resources[] = {
101 MAX8925_REG_RESOURCE(SDCTL1, SDCTL1),
102 MAX8925_REG_RESOURCE(SDCTL2, SDCTL2),
103 MAX8925_REG_RESOURCE(SDCTL3, SDCTL3),
104 MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1),
105 MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2),
106 MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3),
107 MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4),
108 MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5),
109 MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6),
110 MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7),
111 MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8),
112 MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9),
113 MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10),
114 MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11),
115 MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12),
116 MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13),
117 MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14),
118 MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15),
119 MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16),
120 MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17),
121 MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18),
122 MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19),
123 MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20),
124};
125
126#define MAX8925_REG_DEVS(_id) \
127{ \
128 .name = "max8925-regulator", \
129 .num_resources = 1, \
130 .resources = &regulator_resources[MAX8925_ID_##_id], \
131 .id = MAX8925_ID_##_id, \
132}
133
134static struct mfd_cell regulator_devs[] = {
135 MAX8925_REG_DEVS(SD1),
136 MAX8925_REG_DEVS(SD2),
137 MAX8925_REG_DEVS(SD3),
138 MAX8925_REG_DEVS(LDO1),
139 MAX8925_REG_DEVS(LDO2),
140 MAX8925_REG_DEVS(LDO3),
141 MAX8925_REG_DEVS(LDO4),
142 MAX8925_REG_DEVS(LDO5),
143 MAX8925_REG_DEVS(LDO6),
144 MAX8925_REG_DEVS(LDO7),
145 MAX8925_REG_DEVS(LDO8),
146 MAX8925_REG_DEVS(LDO9),
147 MAX8925_REG_DEVS(LDO10),
148 MAX8925_REG_DEVS(LDO11),
149 MAX8925_REG_DEVS(LDO12),
150 MAX8925_REG_DEVS(LDO13),
151 MAX8925_REG_DEVS(LDO14),
152 MAX8925_REG_DEVS(LDO15),
153 MAX8925_REG_DEVS(LDO16),
154 MAX8925_REG_DEVS(LDO17),
155 MAX8925_REG_DEVS(LDO18),
156 MAX8925_REG_DEVS(LDO19),
157 MAX8925_REG_DEVS(LDO20),
158};
159
160enum {
161 FLAGS_ADC = 1, /* register in ADC component */
162 FLAGS_RTC, /* register in RTC component */
163};
164
165struct max8925_irq_data {
166 int reg;
167 int mask_reg;
168 int enable; /* enable or not */
169 int offs; /* bit offset in mask register */
170 int flags;
171 int tsc_irq;
172};
173
174static struct max8925_irq_data max8925_irqs[] = {
175 [MAX8925_IRQ_VCHG_DC_OVP] = {
176 .reg = MAX8925_CHG_IRQ1,
177 .mask_reg = MAX8925_CHG_IRQ1_MASK,
178 .offs = 1 << 0,
179 },
180 [MAX8925_IRQ_VCHG_DC_F] = {
181 .reg = MAX8925_CHG_IRQ1,
182 .mask_reg = MAX8925_CHG_IRQ1_MASK,
183 .offs = 1 << 1,
184 },
185 [MAX8925_IRQ_VCHG_DC_R] = {
186 .reg = MAX8925_CHG_IRQ1,
187 .mask_reg = MAX8925_CHG_IRQ1_MASK,
188 .offs = 1 << 2,
189 },
190 [MAX8925_IRQ_VCHG_USB_OVP] = {
191 .reg = MAX8925_CHG_IRQ1,
192 .mask_reg = MAX8925_CHG_IRQ1_MASK,
193 .offs = 1 << 3,
194 },
195 [MAX8925_IRQ_VCHG_USB_F] = {
196 .reg = MAX8925_CHG_IRQ1,
197 .mask_reg = MAX8925_CHG_IRQ1_MASK,
198 .offs = 1 << 4,
199 },
200 [MAX8925_IRQ_VCHG_USB_R] = {
201 .reg = MAX8925_CHG_IRQ1,
202 .mask_reg = MAX8925_CHG_IRQ1_MASK,
203 .offs = 1 << 5,
204 },
205 [MAX8925_IRQ_VCHG_THM_OK_R] = {
206 .reg = MAX8925_CHG_IRQ2,
207 .mask_reg = MAX8925_CHG_IRQ2_MASK,
208 .offs = 1 << 0,
209 },
210 [MAX8925_IRQ_VCHG_THM_OK_F] = {
211 .reg = MAX8925_CHG_IRQ2,
212 .mask_reg = MAX8925_CHG_IRQ2_MASK,
213 .offs = 1 << 1,
214 },
215 [MAX8925_IRQ_VCHG_SYSLOW_F] = {
216 .reg = MAX8925_CHG_IRQ2,
217 .mask_reg = MAX8925_CHG_IRQ2_MASK,
218 .offs = 1 << 2,
219 },
220 [MAX8925_IRQ_VCHG_SYSLOW_R] = {
221 .reg = MAX8925_CHG_IRQ2,
222 .mask_reg = MAX8925_CHG_IRQ2_MASK,
223 .offs = 1 << 3,
224 },
225 [MAX8925_IRQ_VCHG_RST] = {
226 .reg = MAX8925_CHG_IRQ2,
227 .mask_reg = MAX8925_CHG_IRQ2_MASK,
228 .offs = 1 << 4,
229 },
230 [MAX8925_IRQ_VCHG_DONE] = {
231 .reg = MAX8925_CHG_IRQ2,
232 .mask_reg = MAX8925_CHG_IRQ2_MASK,
233 .offs = 1 << 5,
234 },
235 [MAX8925_IRQ_VCHG_TOPOFF] = {
236 .reg = MAX8925_CHG_IRQ2,
237 .mask_reg = MAX8925_CHG_IRQ2_MASK,
238 .offs = 1 << 6,
239 },
240 [MAX8925_IRQ_VCHG_TMR_FAULT] = {
241 .reg = MAX8925_CHG_IRQ2,
242 .mask_reg = MAX8925_CHG_IRQ2_MASK,
243 .offs = 1 << 7,
244 },
245 [MAX8925_IRQ_GPM_RSTIN] = {
246 .reg = MAX8925_ON_OFF_IRQ1,
247 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
248 .offs = 1 << 0,
249 },
250 [MAX8925_IRQ_GPM_MPL] = {
251 .reg = MAX8925_ON_OFF_IRQ1,
252 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
253 .offs = 1 << 1,
254 },
255 [MAX8925_IRQ_GPM_SW_3SEC] = {
256 .reg = MAX8925_ON_OFF_IRQ1,
257 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
258 .offs = 1 << 2,
259 },
260 [MAX8925_IRQ_GPM_EXTON_F] = {
261 .reg = MAX8925_ON_OFF_IRQ1,
262 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
263 .offs = 1 << 3,
264 },
265 [MAX8925_IRQ_GPM_EXTON_R] = {
266 .reg = MAX8925_ON_OFF_IRQ1,
267 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
268 .offs = 1 << 4,
269 },
270 [MAX8925_IRQ_GPM_SW_1SEC] = {
271 .reg = MAX8925_ON_OFF_IRQ1,
272 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
273 .offs = 1 << 5,
274 },
275 [MAX8925_IRQ_GPM_SW_F] = {
276 .reg = MAX8925_ON_OFF_IRQ1,
277 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
278 .offs = 1 << 6,
279 },
280 [MAX8925_IRQ_GPM_SW_R] = {
281 .reg = MAX8925_ON_OFF_IRQ1,
282 .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
283 .offs = 1 << 7,
284 },
285 [MAX8925_IRQ_GPM_SYSCKEN_F] = {
286 .reg = MAX8925_ON_OFF_IRQ2,
287 .mask_reg = MAX8925_ON_OFF_IRQ2_MASK,
288 .offs = 1 << 0,
289 },
290 [MAX8925_IRQ_GPM_SYSCKEN_R] = {
291 .reg = MAX8925_ON_OFF_IRQ2,
292 .mask_reg = MAX8925_ON_OFF_IRQ2_MASK,
293 .offs = 1 << 1,
294 },
295 [MAX8925_IRQ_RTC_ALARM1] = {
296 .reg = MAX8925_RTC_IRQ,
297 .mask_reg = MAX8925_RTC_IRQ_MASK,
298 .offs = 1 << 2,
299 .flags = FLAGS_RTC,
300 },
301 [MAX8925_IRQ_RTC_ALARM0] = {
302 .reg = MAX8925_RTC_IRQ,
303 .mask_reg = MAX8925_RTC_IRQ_MASK,
304 .offs = 1 << 3,
305 .flags = FLAGS_RTC,
306 },
307 [MAX8925_IRQ_TSC_STICK] = {
308 .reg = MAX8925_TSC_IRQ,
309 .mask_reg = MAX8925_TSC_IRQ_MASK,
310 .offs = 1 << 0,
311 .flags = FLAGS_ADC,
312 .tsc_irq = 1,
313 },
314 [MAX8925_IRQ_TSC_NSTICK] = {
315 .reg = MAX8925_TSC_IRQ,
316 .mask_reg = MAX8925_TSC_IRQ_MASK,
317 .offs = 1 << 1,
318 .flags = FLAGS_ADC,
319 .tsc_irq = 1,
320 },
321};
322
323static inline struct max8925_irq_data *irq_to_max8925(struct max8925_chip *chip,
324 int irq)
325{
326 return &max8925_irqs[irq - chip->irq_base];
327}
328
329static irqreturn_t max8925_irq(int irq, void *data)
330{
331 struct max8925_chip *chip = data;
332 struct max8925_irq_data *irq_data;
333 struct i2c_client *i2c;
334 int read_reg = -1, value = 0;
335 int i;
336
337 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
338 irq_data = &max8925_irqs[i];
339 /* TSC IRQ should be serviced in max8925_tsc_irq() */
340 if (irq_data->tsc_irq)
341 continue;
342 if (irq_data->flags == FLAGS_RTC)
343 i2c = chip->rtc;
344 else if (irq_data->flags == FLAGS_ADC)
345 i2c = chip->adc;
346 else
347 i2c = chip->i2c;
348 if (read_reg != irq_data->reg) {
349 read_reg = irq_data->reg;
350 value = max8925_reg_read(i2c, irq_data->reg);
351 }
352 if (value & irq_data->enable)
353 handle_nested_irq(chip->irq_base + i);
354 }
355 return IRQ_HANDLED;
356}
357
358static irqreturn_t max8925_tsc_irq(int irq, void *data)
359{
360 struct max8925_chip *chip = data;
361 struct max8925_irq_data *irq_data;
362 struct i2c_client *i2c;
363 int read_reg = -1, value = 0;
364 int i;
365
366 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
367 irq_data = &max8925_irqs[i];
368 /* non TSC IRQ should be serviced in max8925_irq() */
369 if (!irq_data->tsc_irq)
370 continue;
371 if (irq_data->flags == FLAGS_RTC)
372 i2c = chip->rtc;
373 else if (irq_data->flags == FLAGS_ADC)
374 i2c = chip->adc;
375 else
376 i2c = chip->i2c;
377 if (read_reg != irq_data->reg) {
378 read_reg = irq_data->reg;
379 value = max8925_reg_read(i2c, irq_data->reg);
380 }
381 if (value & irq_data->enable)
382 handle_nested_irq(chip->irq_base + i);
383 }
384 return IRQ_HANDLED;
385}
386
387static void max8925_irq_lock(unsigned int irq)
388{
389 struct max8925_chip *chip = get_irq_chip_data(irq);
390
391 mutex_lock(&chip->irq_lock);
392}
393
394static void max8925_irq_sync_unlock(unsigned int irq)
395{
396 struct max8925_chip *chip = get_irq_chip_data(irq);
397 struct max8925_irq_data *irq_data;
398 static unsigned char cache_chg[2] = {0xff, 0xff};
399 static unsigned char cache_on[2] = {0xff, 0xff};
400 static unsigned char cache_rtc = 0xff, cache_tsc = 0xff;
401 unsigned char irq_chg[2], irq_on[2];
402 unsigned char irq_rtc, irq_tsc;
403 int i;
404
405 /* Load cached value. In initial, all IRQs are masked */
406 irq_chg[0] = cache_chg[0];
407 irq_chg[1] = cache_chg[1];
408 irq_on[0] = cache_on[0];
409 irq_on[1] = cache_on[1];
410 irq_rtc = cache_rtc;
411 irq_tsc = cache_tsc;
412 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
413 irq_data = &max8925_irqs[i];
414 switch (irq_data->mask_reg) {
415 case MAX8925_CHG_IRQ1_MASK:
416 irq_chg[0] &= irq_data->enable;
417 break;
418 case MAX8925_CHG_IRQ2_MASK:
419 irq_chg[1] &= irq_data->enable;
420 break;
421 case MAX8925_ON_OFF_IRQ1_MASK:
422 irq_on[0] &= irq_data->enable;
423 break;
424 case MAX8925_ON_OFF_IRQ2_MASK:
425 irq_on[1] &= irq_data->enable;
426 break;
427 case MAX8925_RTC_IRQ_MASK:
428 irq_rtc &= irq_data->enable;
429 break;
430 case MAX8925_TSC_IRQ_MASK:
431 irq_tsc &= irq_data->enable;
432 break;
433 default:
434 dev_err(chip->dev, "wrong IRQ\n");
435 break;
436 }
437 }
438 /* update mask into registers */
439 if (cache_chg[0] != irq_chg[0]) {
440 cache_chg[0] = irq_chg[0];
441 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK,
442 irq_chg[0]);
443 }
444 if (cache_chg[1] != irq_chg[1]) {
445 cache_chg[1] = irq_chg[1];
446 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK,
447 irq_chg[1]);
448 }
449 if (cache_on[0] != irq_on[0]) {
450 cache_on[0] = irq_on[0];
451 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK,
452 irq_on[0]);
453 }
454 if (cache_on[1] != irq_on[1]) {
455 cache_on[1] = irq_on[1];
456 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK,
457 irq_on[1]);
458 }
459 if (cache_rtc != irq_rtc) {
460 cache_rtc = irq_rtc;
461 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, irq_rtc);
462 }
463 if (cache_tsc != irq_tsc) {
464 cache_tsc = irq_tsc;
465 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, irq_tsc);
466 }
467
468 mutex_unlock(&chip->irq_lock);
469}
470
471static void max8925_irq_enable(unsigned int irq)
472{
473 struct max8925_chip *chip = get_irq_chip_data(irq);
474 max8925_irqs[irq - chip->irq_base].enable
475 = max8925_irqs[irq - chip->irq_base].offs;
476}
477
478static void max8925_irq_disable(unsigned int irq)
479{
480 struct max8925_chip *chip = get_irq_chip_data(irq);
481 max8925_irqs[irq - chip->irq_base].enable = 0;
482}
483
484static struct irq_chip max8925_irq_chip = {
485 .name = "max8925",
486 .bus_lock = max8925_irq_lock,
487 .bus_sync_unlock = max8925_irq_sync_unlock,
488 .enable = max8925_irq_enable,
489 .disable = max8925_irq_disable,
490};
491
492static int max8925_irq_init(struct max8925_chip *chip, int irq,
493 struct max8925_platform_data *pdata)
494{
495 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
496 struct irq_desc *desc;
497 int i, ret;
498 int __irq;
499
500 if (!pdata || !pdata->irq_base) {
501 dev_warn(chip->dev, "No interrupt support on IRQ base\n");
502 return -EINVAL;
503 }
504 /* clear all interrupts */
505 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1);
506 max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2);
507 max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ1);
508 max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2);
509 max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ);
510 max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
511 /* mask all interrupts */
512 max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0);
513 max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0);
514 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff);
515 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 0xff);
516 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff);
517 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff);
518 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
519 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0xff);
520
521 mutex_init(&chip->irq_lock);
522 chip->core_irq = irq;
523 chip->irq_base = pdata->irq_base;
524 desc = irq_to_desc(chip->core_irq);
525
526 /* register with genirq */
527 for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
528 __irq = i + chip->irq_base;
529 set_irq_chip_data(__irq, chip);
530 set_irq_chip_and_handler(__irq, &max8925_irq_chip,
531 handle_edge_irq);
532 set_irq_nested_thread(__irq, 1);
533#ifdef CONFIG_ARM
534 set_irq_flags(__irq, IRQF_VALID);
535#else
536 set_irq_noprobe(__irq);
537#endif
538 }
539 if (!irq) {
540 dev_warn(chip->dev, "No interrupt support on core IRQ\n");
541 goto tsc_irq;
542 }
543
544 ret = request_threaded_irq(irq, NULL, max8925_irq, flags,
545 "max8925", chip);
546 if (ret) {
547 dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
548 chip->core_irq = 0;
549 }
550tsc_irq:
551 if (!pdata->tsc_irq) {
552 dev_warn(chip->dev, "No interrupt support on TSC IRQ\n");
553 return 0;
554 }
555 chip->tsc_irq = pdata->tsc_irq;
556
557 ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
558 flags, "max8925-tsc", chip);
559 if (ret) {
560 dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret);
561 chip->tsc_irq = 0;
562 }
563 return 0;
564}
565
566int __devinit max8925_device_init(struct max8925_chip *chip,
567 struct max8925_platform_data *pdata)
568{
569 int ret;
570
571 max8925_irq_init(chip, chip->i2c->irq, pdata);
572
573 if (pdata && (pdata->power || pdata->touch)) {
574 /* enable ADC to control internal reference */
575 max8925_set_bits(chip->i2c, MAX8925_RESET_CNFG, 1, 1);
576 /* enable internal reference for ADC */
577 max8925_set_bits(chip->adc, MAX8925_TSC_CNFG1, 3, 2);
578 /* check for internal reference IRQ */
579 do {
580 ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
581 } while (ret & MAX8925_NREF_OK);
582 /* enaable ADC scheduler, interval is 1 second */
583 max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2);
584 }
585
586 /* enable Momentary Power Loss */
587 max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4);
588
589 ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
590 ARRAY_SIZE(rtc_devs),
591 &rtc_resources[0], 0);
592 if (ret < 0) {
593 dev_err(chip->dev, "Failed to add rtc subdev\n");
594 goto out;
595 }
596 if (pdata && pdata->regulator[0]) {
597 ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
598 ARRAY_SIZE(regulator_devs),
599 &regulator_resources[0], 0);
600 if (ret < 0) {
601 dev_err(chip->dev, "Failed to add regulator subdev\n");
602 goto out_dev;
603 }
604 }
605
606 if (pdata && pdata->backlight) {
607 ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
608 ARRAY_SIZE(backlight_devs),
609 &backlight_resources[0], 0);
610 if (ret < 0) {
611 dev_err(chip->dev, "Failed to add backlight subdev\n");
612 goto out_dev;
613 }
614 }
615
616 if (pdata && pdata->power) {
617 ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
618 ARRAY_SIZE(power_devs),
619 &power_supply_resources[0], 0);
620 if (ret < 0) {
621 dev_err(chip->dev, "Failed to add power supply "
622 "subdev\n");
623 goto out_dev;
624 }
625 }
626
627 if (pdata && pdata->touch) {
628 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
629 ARRAY_SIZE(touch_devs),
630 &touch_resources[0], 0);
631 if (ret < 0) {
632 dev_err(chip->dev, "Failed to add touch subdev\n");
633 goto out_dev;
634 }
635 }
636
637 return 0;
638out_dev:
639 mfd_remove_devices(chip->dev);
640out:
641 return ret;
642}
643
644void __devexit max8925_device_exit(struct max8925_chip *chip)
645{
646 if (chip->core_irq)
647 free_irq(chip->core_irq, chip);
648 if (chip->tsc_irq)
649 free_irq(chip->tsc_irq, chip);
650 mfd_remove_devices(chip->dev);
651}
652
653
654MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925");
655MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com");
656MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
new file mode 100644
index 000000000000..c0b883c14f41
--- /dev/null
+++ b/drivers/mfd/max8925-i2c.c
@@ -0,0 +1,211 @@
1/*
2 * I2C driver for Maxim MAX8925
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/i2c.h>
15#include <linux/mfd/max8925.h>
16
17#define RTC_I2C_ADDR 0x68
18#define ADC_I2C_ADDR 0x47
19
20static inline int max8925_read_device(struct i2c_client *i2c,
21 int reg, int bytes, void *dest)
22{
23 int ret;
24
25 if (bytes > 1)
26 ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
27 else {
28 ret = i2c_smbus_read_byte_data(i2c, reg);
29 if (ret < 0)
30 return ret;
31 *(unsigned char *)dest = (unsigned char)ret;
32 }
33 return ret;
34}
35
36static inline int max8925_write_device(struct i2c_client *i2c,
37 int reg, int bytes, void *src)
38{
39 unsigned char buf[bytes + 1];
40 int ret;
41
42 buf[0] = (unsigned char)reg;
43 memcpy(&buf[1], src, bytes);
44
45 ret = i2c_master_send(i2c, buf, bytes + 1);
46 if (ret < 0)
47 return ret;
48 return 0;
49}
50
51int max8925_reg_read(struct i2c_client *i2c, int reg)
52{
53 struct max8925_chip *chip = i2c_get_clientdata(i2c);
54 unsigned char data = 0;
55 int ret;
56
57 mutex_lock(&chip->io_lock);
58 ret = max8925_read_device(i2c, reg, 1, &data);
59 mutex_unlock(&chip->io_lock);
60
61 if (ret < 0)
62 return ret;
63 else
64 return (int)data;
65}
66EXPORT_SYMBOL(max8925_reg_read);
67
68int max8925_reg_write(struct i2c_client *i2c, int reg,
69 unsigned char data)
70{
71 struct max8925_chip *chip = i2c_get_clientdata(i2c);
72 int ret;
73
74 mutex_lock(&chip->io_lock);
75 ret = max8925_write_device(i2c, reg, 1, &data);
76 mutex_unlock(&chip->io_lock);
77
78 return ret;
79}
80EXPORT_SYMBOL(max8925_reg_write);
81
82int max8925_bulk_read(struct i2c_client *i2c, int reg,
83 int count, unsigned char *buf)
84{
85 struct max8925_chip *chip = i2c_get_clientdata(i2c);
86 int ret;
87
88 mutex_lock(&chip->io_lock);
89 ret = max8925_read_device(i2c, reg, count, buf);
90 mutex_unlock(&chip->io_lock);
91
92 return ret;
93}
94EXPORT_SYMBOL(max8925_bulk_read);
95
96int max8925_bulk_write(struct i2c_client *i2c, int reg,
97 int count, unsigned char *buf)
98{
99 struct max8925_chip *chip = i2c_get_clientdata(i2c);
100 int ret;
101
102 mutex_lock(&chip->io_lock);
103 ret = max8925_write_device(i2c, reg, count, buf);
104 mutex_unlock(&chip->io_lock);
105
106 return ret;
107}
108EXPORT_SYMBOL(max8925_bulk_write);
109
110int max8925_set_bits(struct i2c_client *i2c, int reg,
111 unsigned char mask, unsigned char data)
112{
113 struct max8925_chip *chip = i2c_get_clientdata(i2c);
114 unsigned char value;
115 int ret;
116
117 mutex_lock(&chip->io_lock);
118 ret = max8925_read_device(i2c, reg, 1, &value);
119 if (ret < 0)
120 goto out;
121 value &= ~mask;
122 value |= data;
123 ret = max8925_write_device(i2c, reg, 1, &value);
124out:
125 mutex_unlock(&chip->io_lock);
126 return ret;
127}
128EXPORT_SYMBOL(max8925_set_bits);
129
130
131static const struct i2c_device_id max8925_id_table[] = {
132 { "max8925", 0 },
133 { },
134};
135MODULE_DEVICE_TABLE(i2c, max8925_id_table);
136
137static int __devinit max8925_probe(struct i2c_client *client,
138 const struct i2c_device_id *id)
139{
140 struct max8925_platform_data *pdata = client->dev.platform_data;
141 static struct max8925_chip *chip;
142
143 if (!pdata) {
144 pr_info("%s: platform data is missing\n", __func__);
145 return -EINVAL;
146 }
147
148 chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
149 if (chip == NULL)
150 return -ENOMEM;
151 chip->i2c = client;
152 chip->dev = &client->dev;
153 i2c_set_clientdata(client, chip);
154 dev_set_drvdata(chip->dev, chip);
155 mutex_init(&chip->io_lock);
156
157 chip->rtc = i2c_new_dummy(chip->i2c->adapter, RTC_I2C_ADDR);
158 i2c_set_clientdata(chip->rtc, chip);
159
160 chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
161 i2c_set_clientdata(chip->adc, chip);
162
163 max8925_device_init(chip, pdata);
164
165 return 0;
166}
167
168static int __devexit max8925_remove(struct i2c_client *client)
169{
170 struct max8925_chip *chip = i2c_get_clientdata(client);
171
172 max8925_device_exit(chip);
173 i2c_unregister_device(chip->adc);
174 i2c_unregister_device(chip->rtc);
175 i2c_set_clientdata(chip->adc, NULL);
176 i2c_set_clientdata(chip->rtc, NULL);
177 i2c_set_clientdata(chip->i2c, NULL);
178 kfree(chip);
179 return 0;
180}
181
182static struct i2c_driver max8925_driver = {
183 .driver = {
184 .name = "max8925",
185 .owner = THIS_MODULE,
186 },
187 .probe = max8925_probe,
188 .remove = __devexit_p(max8925_remove),
189 .id_table = max8925_id_table,
190};
191
192static int __init max8925_i2c_init(void)
193{
194 int ret;
195
196 ret = i2c_add_driver(&max8925_driver);
197 if (ret != 0)
198 pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
199 return ret;
200}
201subsys_initcall(max8925_i2c_init);
202
203static void __exit max8925_i2c_exit(void)
204{
205 i2c_del_driver(&max8925_driver);
206}
207module_exit(max8925_i2c_exit);
208
209MODULE_DESCRIPTION("I2C Driver for Maxim 8925");
210MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
211MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index ae15e495e20e..aa17f4bddc56 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/acpi.h>
16#include <linux/mfd/core.h> 17#include <linux/mfd/core.h>
17 18
18static int mfd_add_device(struct device *parent, int id, 19static int mfd_add_device(struct device *parent, int id,
@@ -62,6 +63,10 @@ static int mfd_add_device(struct device *parent, int id,
62 res[r].start = cell->resources[r].start; 63 res[r].start = cell->resources[r].start;
63 res[r].end = cell->resources[r].end; 64 res[r].end = cell->resources[r].end;
64 } 65 }
66
67 ret = acpi_check_resource_conflict(res);
68 if (ret)
69 goto fail_res;
65 } 70 }
66 71
67 platform_device_add_resources(pdev, res, cell->num_resources); 72 platform_device_add_resources(pdev, res, cell->num_resources);
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
index 03efae8041ab..468fd366d4da 100644
--- a/drivers/mfd/sh_mobile_sdhi.c
+++ b/drivers/mfd/sh_mobile_sdhi.c
@@ -21,7 +21,7 @@
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24#include <linux/mmc/host.h>
25#include <linux/mfd/core.h> 25#include <linux/mfd/core.h>
26#include <linux/mfd/tmio.h> 26#include <linux/mfd/tmio.h>
27#include <linux/mfd/sh_mobile_sdhi.h> 27#include <linux/mfd/sh_mobile_sdhi.h>
@@ -95,9 +95,9 @@ static int __init sh_mobile_sdhi_probe(struct platform_device *pdev)
95 95
96 clk_enable(priv->clk); 96 clk_enable(priv->clk);
97 97
98 /* FIXME: silly const unsigned int hclk */ 98 priv->mmc_data.hclk = clk_get_rate(priv->clk);
99 *(unsigned int *)&priv->mmc_data.hclk = clk_get_rate(priv->clk);
100 priv->mmc_data.set_pwr = sh_mobile_sdhi_set_pwr; 99 priv->mmc_data.set_pwr = sh_mobile_sdhi_set_pwr;
100 priv->mmc_data.capabilities = MMC_CAP_MMC_HIGHSPEED;
101 101
102 memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc)); 102 memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
103 priv->cell_mmc.driver_data = &priv->mmc_data; 103 priv->cell_mmc.driver_data = &priv->mmc_data;
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 0cc5eeff5ee8..dc9ea95c0561 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1430,7 +1430,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
1430 } 1430 }
1431 1431
1432 sm->regs_claim = request_mem_region(sm->io_res->start, 1432 sm->regs_claim = request_mem_region(sm->io_res->start,
1433 0x100, "sm501"); 1433 resource_size(sm->io_res), "sm501");
1434 1434
1435 if (sm->regs_claim == NULL) { 1435 if (sm->regs_claim == NULL) {
1436 dev_err(&dev->dev, "cannot claim registers\n"); 1436 dev_err(&dev->dev, "cannot claim registers\n");
@@ -1440,8 +1440,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
1440 1440
1441 platform_set_drvdata(dev, sm); 1441 platform_set_drvdata(dev, sm);
1442 1442
1443 sm->regs = ioremap(sm->io_res->start, 1443 sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
1444 (sm->io_res->end - sm->io_res->start) - 1);
1445 1444
1446 if (sm->regs == NULL) { 1445 if (sm->regs == NULL) {
1447 dev_err(&dev->dev, "cannot remap registers\n"); 1446 dev_err(&dev->dev, "cannot remap registers\n");
@@ -1645,7 +1644,7 @@ static int __devinit sm501_pci_probe(struct pci_dev *dev,
1645 sm->mem_res = &dev->resource[0]; 1644 sm->mem_res = &dev->resource[0];
1646 1645
1647 sm->regs_claim = request_mem_region(sm->io_res->start, 1646 sm->regs_claim = request_mem_region(sm->io_res->start,
1648 0x100, "sm501"); 1647 resource_size(sm->io_res), "sm501");
1649 if (sm->regs_claim == NULL) { 1648 if (sm->regs_claim == NULL) {
1650 dev_err(&dev->dev, "cannot claim registers\n"); 1649 dev_err(&dev->dev, "cannot claim registers\n");
1651 err= -EBUSY; 1650 err= -EBUSY;
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index bcf4687d4af5..26d9176fca91 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -360,7 +360,7 @@ static int t7l66xb_probe(struct platform_device *dev)
360 if (ret) 360 if (ret)
361 goto err_request_scr; 361 goto err_request_scr;
362 362
363 t7l66xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1); 363 t7l66xb->scr = ioremap(rscr->start, resource_size(rscr));
364 if (!t7l66xb->scr) { 364 if (!t7l66xb->scr) {
365 ret = -ENOMEM; 365 ret = -ENOMEM;
366 goto err_ioremap; 366 goto err_ioremap;
@@ -403,12 +403,12 @@ static int t7l66xb_probe(struct platform_device *dev)
403err_ioremap: 403err_ioremap:
404 release_resource(&t7l66xb->rscr); 404 release_resource(&t7l66xb->rscr);
405err_request_scr: 405err_request_scr:
406 kfree(t7l66xb);
407 clk_put(t7l66xb->clk48m); 406 clk_put(t7l66xb->clk48m);
408err_clk48m_get: 407err_clk48m_get:
409 clk_put(t7l66xb->clk32k); 408 clk_put(t7l66xb->clk32k);
410err_clk32k_get: 409err_clk32k_get:
411err_noirq: 410err_noirq:
411 kfree(t7l66xb);
412 return ret; 412 return ret;
413} 413}
414 414
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 4bc5a08a2b09..c59e5c5737d0 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -647,7 +647,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
647 if (ret) 647 if (ret)
648 goto err_request_scr; 648 goto err_request_scr;
649 649
650 tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1); 650 tc6393xb->scr = ioremap(rscr->start, resource_size(rscr));
651 if (!tc6393xb->scr) { 651 if (!tc6393xb->scr) {
652 ret = -ENOMEM; 652 ret = -ENOMEM;
653 goto err_ioremap; 653 goto err_ioremap;
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 19a930d06241..562cd4935e17 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -58,13 +58,6 @@
58 58
59#define DRIVER_NAME "twl" 59#define DRIVER_NAME "twl"
60 60
61#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
62 defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
63#define twl_has_bci() true
64#else
65#define twl_has_bci() false
66#endif
67
68#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE) 61#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
69#define twl_has_keypad() true 62#define twl_has_keypad() true
70#else 63#else
@@ -130,7 +123,7 @@
130#define TWL_NUM_SLAVES 4 123#define TWL_NUM_SLAVES 4
131 124
132#if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \ 125#if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \
133 || defined(CONFIG_INPUT_TWL4030_PWBUTTON_MODULE) 126 || defined(CONFIG_INPUT_TWL4030_PWRBUTTON_MODULE)
134#define twl_has_pwrbutton() true 127#define twl_has_pwrbutton() true
135#else 128#else
136#define twl_has_pwrbutton() false 129#define twl_has_pwrbutton() false
@@ -205,6 +198,7 @@
205/* subchip/slave 3 0x4B - AUDIO */ 198/* subchip/slave 3 0x4B - AUDIO */
206#define TWL6030_BASEADD_AUDIO 0x0000 199#define TWL6030_BASEADD_AUDIO 0x0000
207#define TWL6030_BASEADD_RSV 0x0000 200#define TWL6030_BASEADD_RSV 0x0000
201#define TWL6030_BASEADD_ZERO 0x0000
208 202
209/* Few power values */ 203/* Few power values */
210#define R_CFG_BOOT 0x05 204#define R_CFG_BOOT 0x05
@@ -320,9 +314,11 @@ static struct twl_mapping twl6030_map[] = {
320 { SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER }, 314 { SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER },
321 { SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE }, 315 { SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE },
322 { SUB_CHIP_ID1, TWL6030_BASEADD_PWM }, 316 { SUB_CHIP_ID1, TWL6030_BASEADD_PWM },
323 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, 317 { SUB_CHIP_ID0, TWL6030_BASEADD_ZERO },
324 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, 318 { SUB_CHIP_ID1, TWL6030_BASEADD_ZERO },
325 319
320 { SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
321 { SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
326 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, 322 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
327 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, 323 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
328 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, 324 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
@@ -588,18 +584,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
588 struct device *child; 584 struct device *child;
589 unsigned sub_chip_id; 585 unsigned sub_chip_id;
590 586
591 if (twl_has_bci() && pdata->bci &&
592 !(features & (TPS_SUBSET | TWL5031))) {
593 child = add_child(3, "twl4030_bci",
594 pdata->bci, sizeof(*pdata->bci),
595 false,
596 /* irq0 = CHG_PRES, irq1 = BCI */
597 pdata->irq_base + BCI_PRES_INTR_OFFSET,
598 pdata->irq_base + BCI_INTR_OFFSET);
599 if (IS_ERR(child))
600 return PTR_ERR(child);
601 }
602
603 if (twl_has_gpio() && pdata->gpio) { 587 if (twl_has_gpio() && pdata->gpio) {
604 child = add_child(SUB_CHIP_ID1, "twl4030_gpio", 588 child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
605 pdata->gpio, sizeof(*pdata->gpio), 589 pdata->gpio, sizeof(*pdata->gpio),
@@ -977,6 +961,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
977 int status; 961 int status;
978 unsigned i; 962 unsigned i;
979 struct twl4030_platform_data *pdata = client->dev.platform_data; 963 struct twl4030_platform_data *pdata = client->dev.platform_data;
964 u8 temp;
980 965
981 if (!pdata) { 966 if (!pdata) {
982 dev_dbg(&client->dev, "no platform data?\n"); 967 dev_dbg(&client->dev, "no platform data?\n");
@@ -1044,6 +1029,18 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
1044 goto fail; 1029 goto fail;
1045 } 1030 }
1046 1031
1032 /* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
1033 * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
1034 * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
1035 */
1036
1037 if (twl_class_is_4030()) {
1038 twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1);
1039 temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
1040 I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
1041 twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
1042 }
1043
1047 status = add_children(pdata, id->driver_data); 1044 status = add_children(pdata, id->driver_data);
1048fail: 1045fail:
1049 if (status < 0) 1046 if (status < 0)
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 0815292fdafc..7efa8789a3a2 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -405,7 +405,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
405 405
406 if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { 406 if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
407 remap &= ~SLEEP_STATE_MASK; 407 remap &= ~SLEEP_STATE_MASK;
408 remap |= rconfig->remap_off << SLEEP_STATE_SHIFT; 408 remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
409 } 409 }
410 410
411 err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 411 err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
@@ -461,6 +461,56 @@ out:
461 return err; 461 return err;
462} 462}
463 463
464int twl4030_remove_script(u8 flags)
465{
466 int err = 0;
467
468 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1,
469 R_PROTECT_KEY);
470 if (err) {
471 pr_err("twl4030: unable to unlock PROTECT_KEY\n");
472 return err;
473 }
474
475 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2,
476 R_PROTECT_KEY);
477 if (err) {
478 pr_err("twl4030: unable to unlock PROTECT_KEY\n");
479 return err;
480 }
481
482 if (flags & TWL4030_WRST_SCRIPT) {
483 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
484 R_SEQ_ADD_WARM);
485 if (err)
486 return err;
487 }
488 if (flags & TWL4030_WAKEUP12_SCRIPT) {
489 if (err)
490 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
491 R_SEQ_ADD_S2A12);
492 return err;
493 }
494 if (flags & TWL4030_WAKEUP3_SCRIPT) {
495 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
496 R_SEQ_ADD_S2A3);
497 if (err)
498 return err;
499 }
500 if (flags & TWL4030_SLEEP_SCRIPT) {
501 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
502 R_SEQ_ADD_A2S);
503 if (err)
504 return err;
505 }
506
507 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY);
508 if (err)
509 pr_err("TWL4030 Unable to relock registers\n");
510
511 return err;
512}
513
464void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) 514void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
465{ 515{
466 int err = 0; 516 int err = 0;
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 252b74188ec2..b281217334eb 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -27,6 +27,7 @@
27#include <linux/mutex.h> 27#include <linux/mutex.h>
28#include <linux/mfd/ucb1x00.h> 28#include <linux/mfd/ucb1x00.h>
29#include <linux/gpio.h> 29#include <linux/gpio.h>
30#include <linux/semaphore.h>
30 31
31#include <mach/dma.h> 32#include <mach/dma.h>
32#include <mach/hardware.h> 33#include <mach/hardware.h>
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 4b2021af1d96..07101e9e1cba 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -321,7 +321,6 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits);
321 */ 321 */
322int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) 322int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
323{ 323{
324 int tries = 10;
325 int ret, src; 324 int ret, src;
326 325
327 mutex_lock(&wm831x->auxadc_lock); 326 mutex_lock(&wm831x->auxadc_lock);
@@ -349,13 +348,14 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
349 goto disable; 348 goto disable;
350 } 349 }
351 350
352 do { 351 /* Ignore the result to allow us to soldier on without IRQ hookup */
353 msleep(1); 352 wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5));
354 353
355 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL); 354 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
356 if (ret < 0) 355 if (ret < 0) {
357 ret = WM831X_AUX_CVT_ENA; 356 dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret);
358 } while ((ret & WM831X_AUX_CVT_ENA) && --tries); 357 goto disable;
358 }
359 359
360 if (ret & WM831X_AUX_CVT_ENA) { 360 if (ret & WM831X_AUX_CVT_ENA) {
361 dev_err(wm831x->dev, "Timed out reading AUXADC\n"); 361 dev_err(wm831x->dev, "Timed out reading AUXADC\n");
@@ -390,6 +390,15 @@ out:
390} 390}
391EXPORT_SYMBOL_GPL(wm831x_auxadc_read); 391EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
392 392
393static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
394{
395 struct wm831x *wm831x = irq_data;
396
397 complete(&wm831x->auxadc_done);
398
399 return IRQ_HANDLED;
400}
401
393/** 402/**
394 * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC 403 * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
395 * 404 *
@@ -1411,6 +1420,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1411 mutex_init(&wm831x->io_lock); 1420 mutex_init(&wm831x->io_lock);
1412 mutex_init(&wm831x->key_lock); 1421 mutex_init(&wm831x->key_lock);
1413 mutex_init(&wm831x->auxadc_lock); 1422 mutex_init(&wm831x->auxadc_lock);
1423 init_completion(&wm831x->auxadc_done);
1414 dev_set_drvdata(wm831x->dev, wm831x); 1424 dev_set_drvdata(wm831x->dev, wm831x);
1415 1425
1416 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); 1426 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
@@ -1449,18 +1459,33 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1449 case WM8310: 1459 case WM8310:
1450 parent = WM8310; 1460 parent = WM8310;
1451 wm831x->num_gpio = 16; 1461 wm831x->num_gpio = 16;
1462 if (rev > 0) {
1463 wm831x->has_gpio_ena = 1;
1464 wm831x->has_cs_sts = 1;
1465 }
1466
1452 dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev); 1467 dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
1453 break; 1468 break;
1454 1469
1455 case WM8311: 1470 case WM8311:
1456 parent = WM8311; 1471 parent = WM8311;
1457 wm831x->num_gpio = 16; 1472 wm831x->num_gpio = 16;
1473 if (rev > 0) {
1474 wm831x->has_gpio_ena = 1;
1475 wm831x->has_cs_sts = 1;
1476 }
1477
1458 dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev); 1478 dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
1459 break; 1479 break;
1460 1480
1461 case WM8312: 1481 case WM8312:
1462 parent = WM8312; 1482 parent = WM8312;
1463 wm831x->num_gpio = 16; 1483 wm831x->num_gpio = 16;
1484 if (rev > 0) {
1485 wm831x->has_gpio_ena = 1;
1486 wm831x->has_cs_sts = 1;
1487 }
1488
1464 dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev); 1489 dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
1465 break; 1490 break;
1466 1491
@@ -1508,6 +1533,16 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1508 if (ret != 0) 1533 if (ret != 0)
1509 goto err; 1534 goto err;
1510 1535
1536 if (wm831x->irq_base) {
1537 ret = request_threaded_irq(wm831x->irq_base +
1538 WM831X_IRQ_AUXADC_DATA,
1539 NULL, wm831x_auxadc_irq, 0,
1540 "auxadc", wm831x);
1541 if (ret < 0)
1542 dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
1543 ret);
1544 }
1545
1511 /* The core device is up, instantiate the subdevices. */ 1546 /* The core device is up, instantiate the subdevices. */
1512 switch (parent) { 1547 switch (parent) {
1513 case WM8310: 1548 case WM8310:
@@ -1578,6 +1613,8 @@ static void wm831x_device_exit(struct wm831x *wm831x)
1578{ 1613{
1579 wm831x_otp_exit(wm831x); 1614 wm831x_otp_exit(wm831x);
1580 mfd_remove_devices(wm831x->dev); 1615 mfd_remove_devices(wm831x->dev);
1616 if (wm831x->irq_base)
1617 free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
1581 wm831x_irq_exit(wm831x); 1618 wm831x_irq_exit(wm831x);
1582 kfree(wm831x); 1619 kfree(wm831x);
1583} 1620}
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 9a970bd68775..bd75807d5302 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
339int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) 339int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
340{ 340{
341 u16 reg, result = 0; 341 u16 reg, result = 0;
342 int tries = 5;
343 342
344 if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) 343 if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
345 return -EINVAL; 344 return -EINVAL;
@@ -363,12 +362,13 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
363 reg |= 1 << channel | WM8350_AUXADC_POLL; 362 reg |= 1 << channel | WM8350_AUXADC_POLL;
364 wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); 363 wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
365 364
366 do { 365 /* We ignore the result of the completion and just check for a
367 schedule_timeout_interruptible(1); 366 * conversion result, allowing us to soldier on if the IRQ
368 reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); 367 * infrastructure is not set up for the chip. */
369 } while ((reg & WM8350_AUXADC_POLL) && --tries); 368 wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5));
370 369
371 if (!tries) 370 reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
371 if (reg & WM8350_AUXADC_POLL)
372 dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); 372 dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
373 else 373 else
374 result = wm8350_reg_read(wm8350, 374 result = wm8350_reg_read(wm8350,
@@ -385,6 +385,15 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
385} 385}
386EXPORT_SYMBOL_GPL(wm8350_read_auxadc); 386EXPORT_SYMBOL_GPL(wm8350_read_auxadc);
387 387
388static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data)
389{
390 struct wm8350 *wm8350 = irq_data;
391
392 complete(&wm8350->auxadc_done);
393
394 return IRQ_HANDLED;
395}
396
388/* 397/*
389 * Cache is always host endian. 398 * Cache is always host endian.
390 */ 399 */
@@ -682,11 +691,22 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
682 } 691 }
683 692
684 mutex_init(&wm8350->auxadc_mutex); 693 mutex_init(&wm8350->auxadc_mutex);
694 init_completion(&wm8350->auxadc_done);
685 695
686 ret = wm8350_irq_init(wm8350, irq, pdata); 696 ret = wm8350_irq_init(wm8350, irq, pdata);
687 if (ret < 0) 697 if (ret < 0)
688 goto err; 698 goto err;
689 699
700 if (wm8350->irq_base) {
701 ret = request_threaded_irq(wm8350->irq_base +
702 WM8350_IRQ_AUXADC_DATARDY,
703 NULL, wm8350_auxadc_irq, 0,
704 "auxadc", wm8350);
705 if (ret < 0)
706 dev_warn(wm8350->dev,
707 "Failed to request AUXADC IRQ: %d\n", ret);
708 }
709
690 if (pdata && pdata->init) { 710 if (pdata && pdata->init) {
691 ret = pdata->init(wm8350); 711 ret = pdata->init(wm8350);
692 if (ret != 0) { 712 if (ret != 0) {
@@ -736,6 +756,9 @@ void wm8350_device_exit(struct wm8350 *wm8350)
736 platform_device_unregister(wm8350->gpio.pdev); 756 platform_device_unregister(wm8350->gpio.pdev);
737 platform_device_unregister(wm8350->codec.pdev); 757 platform_device_unregister(wm8350->codec.pdev);
738 758
759 if (wm8350->irq_base)
760 free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);
761
739 wm8350_irq_exit(wm8350); 762 wm8350_irq_exit(wm8350);
740 763
741 kfree(wm8350->reg_cache); 764 kfree(wm8350->reg_cache);
diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c
index 9025f29e2707..f56c9adf9493 100644
--- a/drivers/mfd/wm8350-irq.c
+++ b/drivers/mfd/wm8350-irq.c
@@ -18,7 +18,7 @@
18#include <linux/bug.h> 18#include <linux/bug.h>
19#include <linux/device.h> 19#include <linux/device.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/workqueue.h> 21#include <linux/irq.h>
22 22
23#include <linux/mfd/wm8350/core.h> 23#include <linux/mfd/wm8350/core.h>
24#include <linux/mfd/wm8350/audio.h> 24#include <linux/mfd/wm8350/audio.h>
@@ -29,8 +29,6 @@
29#include <linux/mfd/wm8350/supply.h> 29#include <linux/mfd/wm8350/supply.h>
30#include <linux/mfd/wm8350/wdt.h> 30#include <linux/mfd/wm8350/wdt.h>
31 31
32#define WM8350_NUM_IRQ_REGS 7
33
34#define WM8350_INT_OFFSET_1 0 32#define WM8350_INT_OFFSET_1 0
35#define WM8350_INT_OFFSET_2 1 33#define WM8350_INT_OFFSET_2 1
36#define WM8350_POWER_UP_INT_OFFSET 2 34#define WM8350_POWER_UP_INT_OFFSET 2
@@ -366,19 +364,10 @@ static struct wm8350_irq_data wm8350_irqs[] = {
366 }, 364 },
367}; 365};
368 366
369static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) 367static inline struct wm8350_irq_data *irq_to_wm8350_irq(struct wm8350 *wm8350,
368 int irq)
370{ 369{
371 mutex_lock(&wm8350->irq_mutex); 370 return &wm8350_irqs[irq - wm8350->irq_base];
372
373 if (wm8350->irq[irq].handler)
374 wm8350->irq[irq].handler(irq, wm8350->irq[irq].data);
375 else {
376 dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n",
377 irq);
378 wm8350_mask_irq(wm8350, irq);
379 }
380
381 mutex_unlock(&wm8350->irq_mutex);
382} 371}
383 372
384/* 373/*
@@ -386,7 +375,9 @@ static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq)
386 * interrupts are clear on read the IRQ line will be reasserted and 375 * interrupts are clear on read the IRQ line will be reasserted and
387 * the physical IRQ will be handled again if another interrupt is 376 * the physical IRQ will be handled again if another interrupt is
388 * asserted while we run - in the normal course of events this is a 377 * asserted while we run - in the normal course of events this is a
389 * rare occurrence so we save I2C/SPI reads. 378 * rare occurrence so we save I2C/SPI reads. We're also assuming that
379 * it's rare to get lots of interrupts firing simultaneously so try to
380 * minimise I/O.
390 */ 381 */
391static irqreturn_t wm8350_irq(int irq, void *irq_data) 382static irqreturn_t wm8350_irq(int irq, void *irq_data)
392{ 383{
@@ -397,7 +388,6 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data)
397 struct wm8350_irq_data *data; 388 struct wm8350_irq_data *data;
398 int i; 389 int i;
399 390
400 /* TODO: Use block reads to improve performance? */
401 level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS) 391 level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS)
402 & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK); 392 & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK);
403 393
@@ -416,93 +406,101 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data)
416 sub_reg[data->reg] = 406 sub_reg[data->reg] =
417 wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 + 407 wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 +
418 data->reg); 408 data->reg);
419 sub_reg[data->reg] &= 409 sub_reg[data->reg] &= ~wm8350->irq_masks[data->reg];
420 ~wm8350_reg_read(wm8350,
421 WM8350_INT_STATUS_1_MASK +
422 data->reg);
423 read_done[data->reg] = 1; 410 read_done[data->reg] = 1;
424 } 411 }
425 412
426 if (sub_reg[data->reg] & data->mask) 413 if (sub_reg[data->reg] & data->mask)
427 wm8350_irq_call_handler(wm8350, i); 414 handle_nested_irq(wm8350->irq_base + i);
428 } 415 }
429 416
430 return IRQ_HANDLED; 417 return IRQ_HANDLED;
431} 418}
432 419
433int wm8350_register_irq(struct wm8350 *wm8350, int irq, 420static void wm8350_irq_lock(unsigned int irq)
434 irq_handler_t handler, unsigned long flags,
435 const char *name, void *data)
436{ 421{
437 if (irq < 0 || irq >= WM8350_NUM_IRQ || !handler) 422 struct wm8350 *wm8350 = get_irq_chip_data(irq);
438 return -EINVAL;
439
440 if (wm8350->irq[irq].handler)
441 return -EBUSY;
442
443 mutex_lock(&wm8350->irq_mutex);
444 wm8350->irq[irq].handler = handler;
445 wm8350->irq[irq].data = data;
446 mutex_unlock(&wm8350->irq_mutex);
447
448 wm8350_unmask_irq(wm8350, irq);
449 423
450 return 0; 424 mutex_lock(&wm8350->irq_lock);
451} 425}
452EXPORT_SYMBOL_GPL(wm8350_register_irq);
453 426
454int wm8350_free_irq(struct wm8350 *wm8350, int irq) 427static void wm8350_irq_sync_unlock(unsigned int irq)
455{ 428{
456 if (irq < 0 || irq >= WM8350_NUM_IRQ) 429 struct wm8350 *wm8350 = get_irq_chip_data(irq);
457 return -EINVAL; 430 int i;
458 431
459 wm8350_mask_irq(wm8350, irq); 432 for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
433 /* If there's been a change in the mask write it back
434 * to the hardware. */
435 if (wm8350->irq_masks[i] !=
436 wm8350->reg_cache[WM8350_INT_STATUS_1_MASK + i])
437 WARN_ON(wm8350_reg_write(wm8350,
438 WM8350_INT_STATUS_1_MASK + i,
439 wm8350->irq_masks[i]));
440 }
460 441
461 mutex_lock(&wm8350->irq_mutex); 442 mutex_unlock(&wm8350->irq_lock);
462 wm8350->irq[irq].handler = NULL;
463 mutex_unlock(&wm8350->irq_mutex);
464 return 0;
465} 443}
466EXPORT_SYMBOL_GPL(wm8350_free_irq);
467 444
468int wm8350_mask_irq(struct wm8350 *wm8350, int irq) 445static void wm8350_irq_enable(unsigned int irq)
469{ 446{
470 return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK + 447 struct wm8350 *wm8350 = get_irq_chip_data(irq);
471 wm8350_irqs[irq].reg, 448 struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
472 wm8350_irqs[irq].mask); 449
450 wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask;
473} 451}
474EXPORT_SYMBOL_GPL(wm8350_mask_irq);
475 452
476int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) 453static void wm8350_irq_disable(unsigned int irq)
477{ 454{
478 return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK + 455 struct wm8350 *wm8350 = get_irq_chip_data(irq);
479 wm8350_irqs[irq].reg, 456 struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
480 wm8350_irqs[irq].mask); 457
458 wm8350->irq_masks[irq_data->reg] |= irq_data->mask;
481} 459}
482EXPORT_SYMBOL_GPL(wm8350_unmask_irq); 460
461static struct irq_chip wm8350_irq_chip = {
462 .name = "wm8350",
463 .bus_lock = wm8350_irq_lock,
464 .bus_sync_unlock = wm8350_irq_sync_unlock,
465 .disable = wm8350_irq_disable,
466 .enable = wm8350_irq_enable,
467};
483 468
484int wm8350_irq_init(struct wm8350 *wm8350, int irq, 469int wm8350_irq_init(struct wm8350 *wm8350, int irq,
485 struct wm8350_platform_data *pdata) 470 struct wm8350_platform_data *pdata)
486{ 471{
487 int ret; 472 int ret, cur_irq, i;
488 int flags = IRQF_ONESHOT; 473 int flags = IRQF_ONESHOT;
489 474
490 if (!irq) { 475 if (!irq) {
491 dev_err(wm8350->dev, "No IRQ configured\n"); 476 dev_warn(wm8350->dev, "No interrupt support, no core IRQ\n");
492 return -EINVAL; 477 return 0;
478 }
479
480 if (!pdata || !pdata->irq_base) {
481 dev_warn(wm8350->dev, "No interrupt support, no IRQ base\n");
482 return 0;
493 } 483 }
494 484
485 /* Mask top level interrupts */
495 wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF); 486 wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
496 wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF);
497 wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF);
498 wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF);
499 wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF);
500 wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF);
501 487
502 mutex_init(&wm8350->irq_mutex); 488 /* Mask all individual interrupts by default and cache the
489 * masks. We read the masks back since there are unwritable
490 * bits in the mask registers. */
491 for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
492 wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK + i,
493 0xFFFF);
494 wm8350->irq_masks[i] =
495 wm8350_reg_read(wm8350,
496 WM8350_INT_STATUS_1_MASK + i);
497 }
498
499 mutex_init(&wm8350->irq_lock);
503 wm8350->chip_irq = irq; 500 wm8350->chip_irq = irq;
501 wm8350->irq_base = pdata->irq_base;
504 502
505 if (pdata && pdata->irq_high) { 503 if (pdata->irq_high) {
506 flags |= IRQF_TRIGGER_HIGH; 504 flags |= IRQF_TRIGGER_HIGH;
507 505
508 wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, 506 wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
@@ -514,11 +512,32 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
514 WM8350_IRQ_POL); 512 WM8350_IRQ_POL);
515 } 513 }
516 514
515 /* Register with genirq */
516 for (cur_irq = wm8350->irq_base;
517 cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base;
518 cur_irq++) {
519 set_irq_chip_data(cur_irq, wm8350);
520 set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip,
521 handle_edge_irq);
522 set_irq_nested_thread(cur_irq, 1);
523
524 /* ARM needs us to explicitly flag the IRQ as valid
525 * and will set them noprobe when we do so. */
526#ifdef CONFIG_ARM
527 set_irq_flags(cur_irq, IRQF_VALID);
528#else
529 set_irq_noprobe(cur_irq);
530#endif
531 }
532
517 ret = request_threaded_irq(irq, NULL, wm8350_irq, flags, 533 ret = request_threaded_irq(irq, NULL, wm8350_irq, flags,
518 "wm8350", wm8350); 534 "wm8350", wm8350);
519 if (ret != 0) 535 if (ret != 0)
520 dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret); 536 dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret);
521 537
538 /* Allow interrupts to fire */
539 wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0);
540
522 return ret; 541 return ret;
523} 542}
524 543
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
new file mode 100644
index 000000000000..844e1c1b7d90
--- /dev/null
+++ b/drivers/mfd/wm8994-core.c
@@ -0,0 +1,537 @@
1/*
2 * wm8994-core.c -- Device access for Wolfson WM8994
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/i2c.h>
18#include <linux/delay.h>
19#include <linux/mfd/core.h>
20#include <linux/regulator/consumer.h>
21#include <linux/regulator/machine.h>
22
23#include <linux/mfd/wm8994/core.h>
24#include <linux/mfd/wm8994/pdata.h>
25#include <linux/mfd/wm8994/registers.h>
26
27static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
28 int bytes, void *dest)
29{
30 int ret, i;
31 u16 *buf = dest;
32
33 BUG_ON(bytes % 2);
34 BUG_ON(bytes <= 0);
35
36 ret = wm8994->read_dev(wm8994, reg, bytes, dest);
37 if (ret < 0)
38 return ret;
39
40 for (i = 0; i < bytes / 2; i++) {
41 buf[i] = be16_to_cpu(buf[i]);
42
43 dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
44 buf[i], reg + i, reg + i);
45 }
46
47 return 0;
48}
49
50/**
51 * wm8994_reg_read: Read a single WM8994 register.
52 *
53 * @wm8994: Device to read from.
54 * @reg: Register to read.
55 */
56int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
57{
58 unsigned short val;
59 int ret;
60
61 mutex_lock(&wm8994->io_lock);
62
63 ret = wm8994_read(wm8994, reg, 2, &val);
64
65 mutex_unlock(&wm8994->io_lock);
66
67 if (ret < 0)
68 return ret;
69 else
70 return val;
71}
72EXPORT_SYMBOL_GPL(wm8994_reg_read);
73
74/**
75 * wm8994_bulk_read: Read multiple WM8994 registers
76 *
77 * @wm8994: Device to read from
78 * @reg: First register
79 * @count: Number of registers
80 * @buf: Buffer to fill.
81 */
82int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
83 int count, u16 *buf)
84{
85 int ret;
86
87 mutex_lock(&wm8994->io_lock);
88
89 ret = wm8994_read(wm8994, reg, count * 2, buf);
90
91 mutex_unlock(&wm8994->io_lock);
92
93 return ret;
94}
95EXPORT_SYMBOL_GPL(wm8994_bulk_read);
96
97static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
98 int bytes, void *src)
99{
100 u16 *buf = src;
101 int i;
102
103 BUG_ON(bytes % 2);
104 BUG_ON(bytes <= 0);
105
106 for (i = 0; i < bytes / 2; i++) {
107 dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
108 buf[i], reg + i, reg + i);
109
110 buf[i] = cpu_to_be16(buf[i]);
111 }
112
113 return wm8994->write_dev(wm8994, reg, bytes, src);
114}
115
116/**
117 * wm8994_reg_write: Write a single WM8994 register.
118 *
119 * @wm8994: Device to write to.
120 * @reg: Register to write to.
121 * @val: Value to write.
122 */
123int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
124 unsigned short val)
125{
126 int ret;
127
128 mutex_lock(&wm8994->io_lock);
129
130 ret = wm8994_write(wm8994, reg, 2, &val);
131
132 mutex_unlock(&wm8994->io_lock);
133
134 return ret;
135}
136EXPORT_SYMBOL_GPL(wm8994_reg_write);
137
138/**
139 * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
140 *
141 * @wm8994: Device to write to.
142 * @reg: Register to write to.
143 * @mask: Mask of bits to set.
144 * @val: Value to set (unshifted)
145 */
146int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
147 unsigned short mask, unsigned short val)
148{
149 int ret;
150 u16 r;
151
152 mutex_lock(&wm8994->io_lock);
153
154 ret = wm8994_read(wm8994, reg, 2, &r);
155 if (ret < 0)
156 goto out;
157
158 r &= ~mask;
159 r |= val;
160
161 ret = wm8994_write(wm8994, reg, 2, &r);
162
163out:
164 mutex_unlock(&wm8994->io_lock);
165
166 return ret;
167}
168EXPORT_SYMBOL_GPL(wm8994_set_bits);
169
170static struct mfd_cell wm8994_regulator_devs[] = {
171 { .name = "wm8994-ldo", .id = 1 },
172 { .name = "wm8994-ldo", .id = 2 },
173};
174
175static struct mfd_cell wm8994_devs[] = {
176 { .name = "wm8994-codec" },
177 { .name = "wm8994-gpio" },
178};
179
180/*
181 * Supplies for the main bulk of CODEC; the LDO supplies are ignored
182 * and should be handled via the standard regulator API supply
183 * management.
184 */
185static const char *wm8994_main_supplies[] = {
186 "DBVDD",
187 "DCVDD",
188 "AVDD1",
189 "AVDD2",
190 "CPVDD",
191 "SPKVDD1",
192 "SPKVDD2",
193};
194
195#ifdef CONFIG_PM
196static int wm8994_device_suspend(struct device *dev)
197{
198 struct wm8994 *wm8994 = dev_get_drvdata(dev);
199 int ret;
200
201 /* GPIO configuration state is saved here since we may be configuring
202 * the GPIO alternate functions even if we're not using the gpiolib
203 * driver for them.
204 */
205 ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
206 &wm8994->gpio_regs);
207 if (ret < 0)
208 dev_err(dev, "Failed to save GPIO registers: %d\n", ret);
209
210 /* For similar reasons we also stash the regulator states */
211 ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
212 &wm8994->ldo_regs);
213 if (ret < 0)
214 dev_err(dev, "Failed to save LDO registers: %d\n", ret);
215
216 ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
217 wm8994->supplies);
218 if (ret != 0) {
219 dev_err(dev, "Failed to disable supplies: %d\n", ret);
220 return ret;
221 }
222
223 return 0;
224}
225
226static int wm8994_device_resume(struct device *dev)
227{
228 struct wm8994 *wm8994 = dev_get_drvdata(dev);
229 int ret;
230
231 ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
232 wm8994->supplies);
233 if (ret != 0) {
234 dev_err(dev, "Failed to enable supplies: %d\n", ret);
235 return ret;
236 }
237
238 ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
239 &wm8994->ldo_regs);
240 if (ret < 0)
241 dev_err(dev, "Failed to restore LDO registers: %d\n", ret);
242
243 ret = wm8994_write(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
244 &wm8994->gpio_regs);
245 if (ret < 0)
246 dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
247
248 return 0;
249}
250#endif
251
252#ifdef CONFIG_REGULATOR
253static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
254{
255 struct wm8994_ldo_pdata *ldo_pdata;
256
257 if (!pdata)
258 return 0;
259
260 ldo_pdata = &pdata->ldo[ldo];
261
262 if (!ldo_pdata->init_data)
263 return 0;
264
265 return ldo_pdata->init_data->num_consumer_supplies != 0;
266}
267#else
268static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
269{
270 return 0;
271}
272#endif
273
274/*
275 * Instantiate the generic non-control parts of the device.
276 */
277static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
278{
279 struct wm8994_pdata *pdata = wm8994->dev->platform_data;
280 int ret, i;
281
282 mutex_init(&wm8994->io_lock);
283 dev_set_drvdata(wm8994->dev, wm8994);
284
285 /* Add the on-chip regulators first for bootstrapping */
286 ret = mfd_add_devices(wm8994->dev, -1,
287 wm8994_regulator_devs,
288 ARRAY_SIZE(wm8994_regulator_devs),
289 NULL, 0);
290 if (ret != 0) {
291 dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
292 goto err;
293 }
294
295 wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
296 ARRAY_SIZE(wm8994_main_supplies),
297 GFP_KERNEL);
298 if (!wm8994->supplies)
299 goto err;
300
301 for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
302 wm8994->supplies[i].supply = wm8994_main_supplies[i];
303
304 ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies),
305 wm8994->supplies);
306 if (ret != 0) {
307 dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
308 goto err_supplies;
309 }
310
311 ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
312 wm8994->supplies);
313 if (ret != 0) {
314 dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
315 goto err_get;
316 }
317
318 ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET);
319 if (ret < 0) {
320 dev_err(wm8994->dev, "Failed to read ID register\n");
321 goto err_enable;
322 }
323 if (ret != 0x8994) {
324 dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n",
325 ret);
326 ret = -EINVAL;
327 goto err_enable;
328 }
329
330 ret = wm8994_reg_read(wm8994, WM8994_CHIP_REVISION);
331 if (ret < 0) {
332 dev_err(wm8994->dev, "Failed to read revision register: %d\n",
333 ret);
334 goto err_enable;
335 }
336
337 switch (ret) {
338 case 0:
339 case 1:
340 dev_warn(wm8994->dev, "revision %c not fully supported\n",
341 'A' + ret);
342 break;
343 default:
344 dev_info(wm8994->dev, "revision %c\n", 'A' + ret);
345 break;
346 }
347
348
349 if (pdata) {
350 wm8994->gpio_base = pdata->gpio_base;
351
352 /* GPIO configuration is only applied if it's non-zero */
353 for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
354 if (pdata->gpio_defaults[i]) {
355 wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
356 0xffff,
357 pdata->gpio_defaults[i]);
358 }
359 }
360 }
361
362 /* In some system designs where the regulators are not in use,
363 * we can achieve a small reduction in leakage currents by
364 * floating LDO outputs. This bit makes no difference if the
365 * LDOs are enabled, it only affects cases where the LDOs were
366 * in operation and are then disabled.
367 */
368 for (i = 0; i < WM8994_NUM_LDO_REGS; i++) {
369 if (wm8994_ldo_in_use(pdata, i))
370 wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
371 WM8994_LDO1_DISCH, WM8994_LDO1_DISCH);
372 else
373 wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
374 WM8994_LDO1_DISCH, 0);
375 }
376
377 ret = mfd_add_devices(wm8994->dev, -1,
378 wm8994_devs, ARRAY_SIZE(wm8994_devs),
379 NULL, 0);
380 if (ret != 0) {
381 dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
382 goto err_enable;
383 }
384
385 return 0;
386
387err_enable:
388 regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
389 wm8994->supplies);
390err_get:
391 regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
392err_supplies:
393 kfree(wm8994->supplies);
394err:
395 mfd_remove_devices(wm8994->dev);
396 kfree(wm8994);
397 return ret;
398}
399
400static void wm8994_device_exit(struct wm8994 *wm8994)
401{
402 mfd_remove_devices(wm8994->dev);
403 regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
404 wm8994->supplies);
405 regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
406 kfree(wm8994->supplies);
407 kfree(wm8994);
408}
409
410static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg,
411 int bytes, void *dest)
412{
413 struct i2c_client *i2c = wm8994->control_data;
414 int ret;
415 u16 r = cpu_to_be16(reg);
416
417 ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
418 if (ret < 0)
419 return ret;
420 if (ret != 2)
421 return -EIO;
422
423 ret = i2c_master_recv(i2c, dest, bytes);
424 if (ret < 0)
425 return ret;
426 if (ret != bytes)
427 return -EIO;
428 return 0;
429}
430
431/* Currently we allocate the write buffer on the stack; this is OK for
432 * small writes - if we need to do large writes this will need to be
433 * revised.
434 */
435static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
436 int bytes, void *src)
437{
438 struct i2c_client *i2c = wm8994->control_data;
439 unsigned char msg[bytes + 2];
440 int ret;
441
442 reg = cpu_to_be16(reg);
443 memcpy(&msg[0], &reg, 2);
444 memcpy(&msg[2], src, bytes);
445
446 ret = i2c_master_send(i2c, msg, bytes + 2);
447 if (ret < 0)
448 return ret;
449 if (ret < bytes + 2)
450 return -EIO;
451
452 return 0;
453}
454
455static int wm8994_i2c_probe(struct i2c_client *i2c,
456 const struct i2c_device_id *id)
457{
458 struct wm8994 *wm8994;
459
460 wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
461 if (wm8994 == NULL) {
462 kfree(i2c);
463 return -ENOMEM;
464 }
465
466 i2c_set_clientdata(i2c, wm8994);
467 wm8994->dev = &i2c->dev;
468 wm8994->control_data = i2c;
469 wm8994->read_dev = wm8994_i2c_read_device;
470 wm8994->write_dev = wm8994_i2c_write_device;
471
472 return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
473}
474
475static int wm8994_i2c_remove(struct i2c_client *i2c)
476{
477 struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
478
479 wm8994_device_exit(wm8994);
480
481 return 0;
482}
483
484#ifdef CONFIG_PM
485static int wm8994_i2c_suspend(struct i2c_client *i2c, pm_message_t state)
486{
487 return wm8994_device_suspend(&i2c->dev);
488}
489
490static int wm8994_i2c_resume(struct i2c_client *i2c)
491{
492 return wm8994_device_resume(&i2c->dev);
493}
494#else
495#define wm8994_i2c_suspend NULL
496#define wm8994_i2c_resume NULL
497#endif
498
499static const struct i2c_device_id wm8994_i2c_id[] = {
500 { "wm8994", 0 },
501 { }
502};
503MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
504
505static struct i2c_driver wm8994_i2c_driver = {
506 .driver = {
507 .name = "wm8994",
508 .owner = THIS_MODULE,
509 },
510 .probe = wm8994_i2c_probe,
511 .remove = wm8994_i2c_remove,
512 .suspend = wm8994_i2c_suspend,
513 .resume = wm8994_i2c_resume,
514 .id_table = wm8994_i2c_id,
515};
516
517static int __init wm8994_i2c_init(void)
518{
519 int ret;
520
521 ret = i2c_add_driver(&wm8994_i2c_driver);
522 if (ret != 0)
523 pr_err("Failed to register wm8994 I2C driver: %d\n", ret);
524
525 return ret;
526}
527module_init(wm8994_i2c_init);
528
529static void __exit wm8994_i2c_exit(void)
530{
531 i2c_del_driver(&wm8994_i2c_driver);
532}
533module_exit(wm8994_i2c_exit);
534
535MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");
536MODULE_LICENSE("GPL");
537MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7b431bbab7f1..2e13b94769fd 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -365,7 +365,7 @@ config MMC_SDRICOH_CS
365 365
366config MMC_TMIO 366config MMC_TMIO
367 tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" 367 tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
368 depends on MFD_TMIO || MFD_ASIC3 || SUPERH 368 depends on MFD_TMIO || MFD_ASIC3 || MFD_SH_MOBILE_SDHI
369 help 369 help
370 This provides support for the SD/MMC cell found in TC6393XB, 370 This provides support for the SD/MMC cell found in TC6393XB,
371 T7L66XB and also HTC ASIC3 371 T7L66XB and also HTC ASIC3
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index e22c3fa3516a..b2b577f6afd4 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -323,7 +323,7 @@ static irqreturn_t tmio_mmc_irq(int irq, void *devid)
323 if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { 323 if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
324 ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT | 324 ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
325 TMIO_STAT_CARD_REMOVE); 325 TMIO_STAT_CARD_REMOVE);
326 mmc_detect_change(host->mmc, 0); 326 mmc_detect_change(host->mmc, msecs_to_jiffies(100));
327 } 327 }
328 328
329 /* CRC and other errors */ 329 /* CRC and other errors */
@@ -550,6 +550,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
550 550
551 mmc->ops = &tmio_mmc_ops; 551 mmc->ops = &tmio_mmc_ops;
552 mmc->caps = MMC_CAP_4_BIT_DATA; 552 mmc->caps = MMC_CAP_4_BIT_DATA;
553 mmc->caps |= pdata->capabilities;
553 mmc->f_max = pdata->hclk; 554 mmc->f_max = pdata->hclk;
554 mmc->f_min = mmc->f_max / 512; 555 mmc->f_min = mmc->f_max / 512;
555 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; 556 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
@@ -568,14 +569,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
568 if (ret >= 0) 569 if (ret >= 0)
569 host->irq = ret; 570 host->irq = ret;
570 else 571 else
571 goto unmap_ctl; 572 goto cell_disable;
572 573
573 disable_mmc_irqs(host, TMIO_MASK_ALL); 574 disable_mmc_irqs(host, TMIO_MASK_ALL);
574 575
575 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | 576 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
576 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); 577 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
577 if (ret) 578 if (ret)
578 goto unmap_ctl; 579 goto cell_disable;
579 580
580 mmc_add_host(mmc); 581 mmc_add_host(mmc);
581 582
@@ -587,6 +588,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
587 588
588 return 0; 589 return 0;
589 590
591cell_disable:
592 if (cell->disable)
593 cell->disable(dev);
590unmap_ctl: 594unmap_ctl:
591 iounmap(host->ctl); 595 iounmap(host->ctl);
592host_free: 596host_free:
@@ -597,6 +601,7 @@ out:
597 601
598static int __devexit tmio_mmc_remove(struct platform_device *dev) 602static int __devexit tmio_mmc_remove(struct platform_device *dev)
599{ 603{
604 struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
600 struct mmc_host *mmc = platform_get_drvdata(dev); 605 struct mmc_host *mmc = platform_get_drvdata(dev);
601 606
602 platform_set_drvdata(dev, NULL); 607 platform_set_drvdata(dev, NULL);
@@ -605,6 +610,8 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev)
605 struct tmio_mmc_host *host = mmc_priv(mmc); 610 struct tmio_mmc_host *host = mmc_priv(mmc);
606 mmc_remove_host(mmc); 611 mmc_remove_host(mmc);
607 free_irq(host->irq, host); 612 free_irq(host->irq, host);
613 if (cell->disable)
614 cell->disable(dev);
608 iounmap(host->ctl); 615 iounmap(host->ctl);
609 mmc_free_host(mmc); 616 mmc_free_host(mmc);
610 } 617 }
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 692dc23363b9..dafecfbcd91a 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -55,10 +55,8 @@
55/* Define some IRQ masks */ 55/* Define some IRQ masks */
56/* This is the mask used at reset by the chip */ 56/* This is the mask used at reset by the chip */
57#define TMIO_MASK_ALL 0x837f031d 57#define TMIO_MASK_ALL 0x837f031d
58#define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND | \ 58#define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
59 TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT) 59#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
60#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND | \
61 TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
62#define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \ 60#define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
63 TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT) 61 TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
64#define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD) 62#define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index bf1467213954..faaa9b4d0d07 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -29,6 +29,13 @@ config APM_POWER
29 Say Y here to enable support APM status emulation using 29 Say Y here to enable support APM status emulation using
30 battery class devices. 30 battery class devices.
31 31
32config MAX8925_POWER
33 tristate "MAX8925 battery charger support"
34 depends on MFD_MAX8925
35 help
36 Say Y here to enable support for the battery charger in the Maxim
37 MAX8925 PMIC.
38
32config WM831X_BACKUP 39config WM831X_BACKUP
33 tristate "WM831X backup battery charger support" 40 tristate "WM831X backup battery charger support"
34 depends on MFD_WM831X 41 depends on MFD_WM831X
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 573597c683b4..a2ba7c85c97a 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
16 16
17obj-$(CONFIG_PDA_POWER) += pda_power.o 17obj-$(CONFIG_PDA_POWER) += pda_power.o
18obj-$(CONFIG_APM_POWER) += apm_power.o 18obj-$(CONFIG_APM_POWER) += apm_power.o
19obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
19obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o 20obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
20obj-$(CONFIG_WM831X_POWER) += wm831x_power.o 21obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
21obj-$(CONFIG_WM8350_POWER) += wm8350_power.o 22obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
new file mode 100644
index 000000000000..a1b4410544d7
--- /dev/null
+++ b/drivers/power/max8925_power.c
@@ -0,0 +1,534 @@
1/*
2 * Battery driver for Maxim MAX8925
3 *
4 * Copyright (c) 2009-2010 Marvell International Ltd.
5 * 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/module.h>
13#include <linux/err.h>
14#include <linux/i2c.h>
15#include <linux/interrupt.h>
16#include <linux/platform_device.h>
17#include <linux/power_supply.h>
18#include <linux/mfd/max8925.h>
19
20/* registers in GPM */
21#define MAX8925_OUT5VEN 0x54
22#define MAX8925_OUT3VEN 0x58
23#define MAX8925_CHG_CNTL1 0x7c
24
25/* bits definition */
26#define MAX8925_CHG_STAT_VSYSLOW (1 << 0)
27#define MAX8925_CHG_STAT_MODE_MASK (3 << 2)
28#define MAX8925_CHG_STAT_EN_MASK (1 << 4)
29#define MAX8925_CHG_MBDET (1 << 1)
30#define MAX8925_CHG_AC_RANGE_MASK (3 << 6)
31
32/* registers in ADC */
33#define MAX8925_ADC_RES_CNFG1 0x06
34#define MAX8925_ADC_AVG_CNFG1 0x07
35#define MAX8925_ADC_ACQ_CNFG1 0x08
36#define MAX8925_ADC_ACQ_CNFG2 0x09
37/* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */
38#define MAX8925_ADC_AUX2 0x62
39#define MAX8925_ADC_VCHG 0x64
40#define MAX8925_ADC_VBBATT 0x66
41#define MAX8925_ADC_VMBATT 0x68
42#define MAX8925_ADC_ISNS 0x6a
43#define MAX8925_ADC_THM 0x6c
44#define MAX8925_ADC_TDIE 0x6e
45#define MAX8925_CMD_AUX2 0xc8
46#define MAX8925_CMD_VCHG 0xd0
47#define MAX8925_CMD_VBBATT 0xd8
48#define MAX8925_CMD_VMBATT 0xe0
49#define MAX8925_CMD_ISNS 0xe8
50#define MAX8925_CMD_THM 0xf0
51#define MAX8925_CMD_TDIE 0xf8
52
53enum {
54 MEASURE_AUX2,
55 MEASURE_VCHG,
56 MEASURE_VBBATT,
57 MEASURE_VMBATT,
58 MEASURE_ISNS,
59 MEASURE_THM,
60 MEASURE_TDIE,
61 MEASURE_MAX,
62};
63
64struct max8925_power_info {
65 struct max8925_chip *chip;
66 struct i2c_client *gpm;
67 struct i2c_client *adc;
68
69 struct power_supply ac;
70 struct power_supply usb;
71 struct power_supply battery;
72 int irq_base;
73 unsigned ac_online:1;
74 unsigned usb_online:1;
75 unsigned bat_online:1;
76 unsigned chg_mode:2;
77 unsigned batt_detect:1; /* detecing MB by ID pin */
78 unsigned topoff_threshold:2;
79 unsigned fast_charge:3;
80
81 int (*set_charger) (int);
82};
83
84static int __set_charger(struct max8925_power_info *info, int enable)
85{
86 struct max8925_chip *chip = info->chip;
87 if (enable) {
88 /* enable charger in platform */
89 if (info->set_charger)
90 info->set_charger(1);
91 /* enable charger */
92 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0);
93 } else {
94 /* disable charge */
95 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
96 if (info->set_charger)
97 info->set_charger(0);
98 }
99 dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger"
100 : "Disable charger");
101 return 0;
102}
103
104static irqreturn_t max8925_charger_handler(int irq, void *data)
105{
106 struct max8925_power_info *info = (struct max8925_power_info *)data;
107 struct max8925_chip *chip = info->chip;
108
109 switch (irq - chip->irq_base) {
110 case MAX8925_IRQ_VCHG_DC_R:
111 info->ac_online = 1;
112 __set_charger(info, 1);
113 dev_dbg(chip->dev, "Adapter inserted\n");
114 break;
115 case MAX8925_IRQ_VCHG_DC_F:
116 info->ac_online = 0;
117 __set_charger(info, 0);
118 dev_dbg(chip->dev, "Adapter is removal\n");
119 break;
120 case MAX8925_IRQ_VCHG_USB_R:
121 info->usb_online = 1;
122 __set_charger(info, 1);
123 dev_dbg(chip->dev, "USB inserted\n");
124 break;
125 case MAX8925_IRQ_VCHG_USB_F:
126 info->usb_online = 0;
127 __set_charger(info, 0);
128 dev_dbg(chip->dev, "USB is removal\n");
129 break;
130 case MAX8925_IRQ_VCHG_THM_OK_F:
131 /* Battery is not ready yet */
132 dev_dbg(chip->dev, "Battery temperature is out of range\n");
133 case MAX8925_IRQ_VCHG_DC_OVP:
134 dev_dbg(chip->dev, "Error detection\n");
135 __set_charger(info, 0);
136 break;
137 case MAX8925_IRQ_VCHG_THM_OK_R:
138 /* Battery is ready now */
139 dev_dbg(chip->dev, "Battery temperature is in range\n");
140 break;
141 case MAX8925_IRQ_VCHG_SYSLOW_R:
142 /* VSYS is low */
143 dev_info(chip->dev, "Sys power is too low\n");
144 break;
145 case MAX8925_IRQ_VCHG_SYSLOW_F:
146 dev_dbg(chip->dev, "Sys power is above low threshold\n");
147 break;
148 case MAX8925_IRQ_VCHG_DONE:
149 __set_charger(info, 0);
150 dev_dbg(chip->dev, "Charging is done\n");
151 break;
152 case MAX8925_IRQ_VCHG_TOPOFF:
153 dev_dbg(chip->dev, "Charging in top-off mode\n");
154 break;
155 case MAX8925_IRQ_VCHG_TMR_FAULT:
156 __set_charger(info, 0);
157 dev_dbg(chip->dev, "Safe timer is expired\n");
158 break;
159 case MAX8925_IRQ_VCHG_RST:
160 __set_charger(info, 0);
161 dev_dbg(chip->dev, "Charger is reset\n");
162 break;
163 }
164 return IRQ_HANDLED;
165}
166
167static int start_measure(struct max8925_power_info *info, int type)
168{
169 unsigned char buf[2] = {0, 0};
170 int meas_reg = 0, ret;
171
172 switch (type) {
173 case MEASURE_VCHG:
174 meas_reg = MAX8925_ADC_VCHG;
175 break;
176 case MEASURE_VBBATT:
177 meas_reg = MAX8925_ADC_VBBATT;
178 break;
179 case MEASURE_VMBATT:
180 meas_reg = MAX8925_ADC_VMBATT;
181 break;
182 case MEASURE_ISNS:
183 meas_reg = MAX8925_ADC_ISNS;
184 break;
185 default:
186 return -EINVAL;
187 }
188
189 max8925_bulk_read(info->adc, meas_reg, 2, buf);
190 ret = (buf[0] << 4) | (buf[1] >> 4);
191
192 return ret;
193}
194
195static int max8925_ac_get_prop(struct power_supply *psy,
196 enum power_supply_property psp,
197 union power_supply_propval *val)
198{
199 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
200 int ret = 0;
201
202 switch (psp) {
203 case POWER_SUPPLY_PROP_ONLINE:
204 val->intval = info->ac_online;
205 break;
206 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
207 if (info->ac_online) {
208 ret = start_measure(info, MEASURE_VCHG);
209 if (ret >= 0) {
210 val->intval = ret << 1; /* unit is mV */
211 goto out;
212 }
213 }
214 ret = -ENODATA;
215 break;
216 default:
217 ret = -ENODEV;
218 break;
219 }
220out:
221 return ret;
222}
223
224static enum power_supply_property max8925_ac_props[] = {
225 POWER_SUPPLY_PROP_ONLINE,
226 POWER_SUPPLY_PROP_VOLTAGE_NOW,
227};
228
229static int max8925_usb_get_prop(struct power_supply *psy,
230 enum power_supply_property psp,
231 union power_supply_propval *val)
232{
233 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
234 int ret = 0;
235
236 switch (psp) {
237 case POWER_SUPPLY_PROP_ONLINE:
238 val->intval = info->usb_online;
239 break;
240 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
241 if (info->usb_online) {
242 ret = start_measure(info, MEASURE_VCHG);
243 if (ret >= 0) {
244 val->intval = ret << 1; /* unit is mV */
245 goto out;
246 }
247 }
248 ret = -ENODATA;
249 break;
250 default:
251 ret = -ENODEV;
252 break;
253 }
254out:
255 return ret;
256}
257
258static enum power_supply_property max8925_usb_props[] = {
259 POWER_SUPPLY_PROP_ONLINE,
260 POWER_SUPPLY_PROP_VOLTAGE_NOW,
261};
262
263static int max8925_bat_get_prop(struct power_supply *psy,
264 enum power_supply_property psp,
265 union power_supply_propval *val)
266{
267 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
268 long long int tmp = 0;
269 int ret = 0;
270
271 switch (psp) {
272 case POWER_SUPPLY_PROP_ONLINE:
273 val->intval = info->bat_online;
274 break;
275 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
276 if (info->bat_online) {
277 ret = start_measure(info, MEASURE_VMBATT);
278 if (ret >= 0) {
279 val->intval = ret << 1; /* unit is mV */
280 ret = 0;
281 break;
282 }
283 }
284 ret = -ENODATA;
285 break;
286 case POWER_SUPPLY_PROP_CURRENT_NOW:
287 if (info->bat_online) {
288 ret = start_measure(info, MEASURE_ISNS);
289 if (ret >= 0) {
290 tmp = (long long int)ret * 6250 / 4096 - 3125;
291 ret = (int)tmp;
292 val->intval = 0;
293 if (ret > 0)
294 val->intval = ret; /* unit is mA */
295 ret = 0;
296 break;
297 }
298 }
299 ret = -ENODATA;
300 break;
301 case POWER_SUPPLY_PROP_CHARGE_TYPE:
302 if (!info->bat_online) {
303 ret = -ENODATA;
304 break;
305 }
306 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
307 ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2;
308 switch (ret) {
309 case 1:
310 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
311 break;
312 case 0:
313 case 2:
314 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
315 break;
316 case 3:
317 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
318 break;
319 }
320 ret = 0;
321 break;
322 case POWER_SUPPLY_PROP_STATUS:
323 if (!info->bat_online) {
324 ret = -ENODATA;
325 break;
326 }
327 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
328 if (info->usb_online || info->ac_online) {
329 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
330 if (ret & MAX8925_CHG_STAT_EN_MASK)
331 val->intval = POWER_SUPPLY_STATUS_CHARGING;
332 } else
333 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
334 ret = 0;
335 break;
336 default:
337 ret = -ENODEV;
338 break;
339 }
340 return ret;
341}
342
343static enum power_supply_property max8925_battery_props[] = {
344 POWER_SUPPLY_PROP_ONLINE,
345 POWER_SUPPLY_PROP_VOLTAGE_NOW,
346 POWER_SUPPLY_PROP_CURRENT_NOW,
347 POWER_SUPPLY_PROP_CHARGE_TYPE,
348 POWER_SUPPLY_PROP_STATUS,
349};
350
351#define REQUEST_IRQ(_irq, _name) \
352do { \
353 ret = request_threaded_irq(chip->irq_base + _irq, NULL, \
354 max8925_charger_handler, \
355 IRQF_ONESHOT, _name, info); \
356 if (ret) \
357 dev_err(chip->dev, "Failed to request IRQ #%d: %d\n", \
358 _irq, ret); \
359} while (0)
360
361static __devinit int max8925_init_charger(struct max8925_chip *chip,
362 struct max8925_power_info *info)
363{
364 int ret;
365
366 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
367 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
368 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
369 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp");
370 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove");
371 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert");
372 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
373 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
374 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
375 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
376 REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
377 REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done");
378 REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
379 REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
380
381 info->ac_online = 0;
382 info->usb_online = 0;
383 info->bat_online = 0;
384 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
385 if (ret >= 0) {
386 /*
387 * If battery detection is enabled, ID pin of battery is
388 * connected to MBDET pin of MAX8925. It could be used to
389 * detect battery presence.
390 * Otherwise, we have to assume that battery is always on.
391 */
392 if (info->batt_detect)
393 info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1;
394 else
395 info->bat_online = 1;
396 if (ret & MAX8925_CHG_AC_RANGE_MASK)
397 info->ac_online = 1;
398 else
399 info->ac_online = 0;
400 }
401 /* disable charge */
402 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
403 /* set charging current in charge topoff mode */
404 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5,
405 info->topoff_threshold << 5);
406 /* set charing current in fast charge mode */
407 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge);
408
409 return 0;
410}
411
412static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
413{
414 struct max8925_chip *chip = info->chip;
415 int irq;
416
417 irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP;
418 for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++)
419 free_irq(irq, info);
420
421 return 0;
422}
423
424static __devinit int max8925_power_probe(struct platform_device *pdev)
425{
426 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
427 struct max8925_platform_data *max8925_pdata;
428 struct max8925_power_pdata *pdata = NULL;
429 struct max8925_power_info *info;
430 int ret;
431
432 if (pdev->dev.parent->platform_data) {
433 max8925_pdata = pdev->dev.parent->platform_data;
434 pdata = max8925_pdata->power;
435 }
436
437 if (!pdata) {
438 dev_err(&pdev->dev, "platform data isn't assigned to "
439 "power supply\n");
440 return -EINVAL;
441 }
442
443 info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
444 if (!info)
445 return -ENOMEM;
446 info->chip = chip;
447 info->gpm = chip->i2c;
448 info->adc = chip->adc;
449
450 info->ac.name = "max8925-ac";
451 info->ac.type = POWER_SUPPLY_TYPE_MAINS;
452 info->ac.properties = max8925_ac_props;
453 info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
454 info->ac.get_property = max8925_ac_get_prop;
455 ret = power_supply_register(&pdev->dev, &info->ac);
456 if (ret)
457 goto out;
458 info->ac.dev->parent = &pdev->dev;
459
460 info->usb.name = "max8925-usb";
461 info->usb.type = POWER_SUPPLY_TYPE_USB;
462 info->usb.properties = max8925_usb_props;
463 info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
464 info->usb.get_property = max8925_usb_get_prop;
465 ret = power_supply_register(&pdev->dev, &info->usb);
466 if (ret)
467 goto out_usb;
468 info->usb.dev->parent = &pdev->dev;
469
470 info->battery.name = "max8925-battery";
471 info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
472 info->battery.properties = max8925_battery_props;
473 info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
474 info->battery.get_property = max8925_bat_get_prop;
475 ret = power_supply_register(&pdev->dev, &info->battery);
476 if (ret)
477 goto out_battery;
478 info->battery.dev->parent = &pdev->dev;
479
480 info->batt_detect = pdata->batt_detect;
481 info->topoff_threshold = pdata->topoff_threshold;
482 info->fast_charge = pdata->fast_charge;
483 info->set_charger = pdata->set_charger;
484 dev_set_drvdata(&pdev->dev, info);
485 platform_set_drvdata(pdev, info);
486
487 max8925_init_charger(chip, info);
488 return 0;
489out_battery:
490 power_supply_unregister(&info->battery);
491out_usb:
492 power_supply_unregister(&info->ac);
493out:
494 kfree(info);
495 return ret;
496}
497
498static __devexit int max8925_power_remove(struct platform_device *pdev)
499{
500 struct max8925_power_info *info = platform_get_drvdata(pdev);
501
502 if (info) {
503 power_supply_unregister(&info->ac);
504 power_supply_unregister(&info->usb);
505 power_supply_unregister(&info->battery);
506 max8925_deinit_charger(info);
507 kfree(info);
508 }
509 return 0;
510}
511
512static struct platform_driver max8925_power_driver = {
513 .probe = max8925_power_probe,
514 .remove = __devexit_p(max8925_power_remove),
515 .driver = {
516 .name = "max8925-power",
517 },
518};
519
520static int __init max8925_power_init(void)
521{
522 return platform_driver_register(&max8925_power_driver);
523}
524module_init(max8925_power_init);
525
526static void __exit max8925_power_exit(void)
527{
528 platform_driver_unregister(&max8925_power_driver);
529}
530module_exit(max8925_power_exit);
531
532MODULE_LICENSE("GPL");
533MODULE_DESCRIPTION("Power supply driver for MAX8925");
534MODULE_ALIAS("platform:max8925-power");
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index ad4f071e1287..0693902d6151 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -190,7 +190,7 @@ static irqreturn_t wm8350_charger_handler(int irq, void *data)
190 struct wm8350_power *power = &wm8350->power; 190 struct wm8350_power *power = &wm8350->power;
191 struct wm8350_charger_policy *policy = power->policy; 191 struct wm8350_charger_policy *policy = power->policy;
192 192
193 switch (irq) { 193 switch (irq - wm8350->irq_base) {
194 case WM8350_IRQ_CHG_BAT_FAIL: 194 case WM8350_IRQ_CHG_BAT_FAIL:
195 dev_err(wm8350->dev, "battery failed\n"); 195 dev_err(wm8350->dev, "battery failed\n");
196 break; 196 break;
@@ -428,18 +428,18 @@ static void wm8350_init_charger(struct wm8350 *wm8350)
428 428
429static void free_charger_irq(struct wm8350 *wm8350) 429static void free_charger_irq(struct wm8350 *wm8350)
430{ 430{
431 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); 431 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
432 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); 432 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
433 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); 433 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
434 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); 434 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
435 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); 435 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
436 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); 436 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
437 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); 437 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
438 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); 438 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
439 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); 439 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
440 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB); 440 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
441 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); 441 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
442 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); 442 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
443} 443}
444 444
445static __devinit int wm8350_power_probe(struct platform_device *pdev) 445static __devinit int wm8350_power_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 04719551381b..5fb83e2ced25 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -11,15 +11,17 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/err.h> 13#include <linux/err.h>
14#include <linux/i2c.h>
14#include <linux/platform_device.h> 15#include <linux/platform_device.h>
15#include <linux/regulator/driver.h> 16#include <linux/regulator/driver.h>
16#include <linux/regulator/machine.h> 17#include <linux/regulator/machine.h>
17#include <linux/mfd/88pm8607.h> 18#include <linux/mfd/88pm860x.h>
18 19
19struct pm8607_regulator_info { 20struct pm8607_regulator_info {
20 struct regulator_desc desc; 21 struct regulator_desc desc;
21 struct pm8607_chip *chip; 22 struct pm860x_chip *chip;
22 struct regulator_dev *regulator; 23 struct regulator_dev *regulator;
24 struct i2c_client *i2c;
23 25
24 int min_uV; 26 int min_uV;
25 int max_uV; 27 int max_uV;
@@ -46,7 +48,6 @@ static inline int check_range(struct pm8607_regulator_info *info,
46static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) 48static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
47{ 49{
48 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 50 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
49 uint8_t chip_id = info->chip->chip_id;
50 int ret = -EINVAL; 51 int ret = -EINVAL;
51 52
52 switch (info->desc.id) { 53 switch (info->desc.id) {
@@ -88,79 +89,29 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
88 case PM8607_ID_LDO2: 89 case PM8607_ID_LDO2:
89 case PM8607_ID_LDO3: 90 case PM8607_ID_LDO3:
90 case PM8607_ID_LDO9: 91 case PM8607_ID_LDO9:
91 switch (chip_id) { 92 ret = (index < 3) ? (index * 50000 + 1800000) :
92 case PM8607_CHIP_A0: 93 ((index < 7) ? (index * 50000 + 2550000) :
93 case PM8607_CHIP_A1: 94 3300000);
94 ret = (index < 3) ? (index * 50000 + 1800000) :
95 ((index < 8) ? (index * 50000 + 2550000) :
96 -EINVAL);
97 break;
98 case PM8607_CHIP_B0:
99 ret = (index < 3) ? (index * 50000 + 1800000) :
100 ((index < 7) ? (index * 50000 + 2550000) :
101 3300000);
102 break;
103 }
104 break; 95 break;
105 case PM8607_ID_LDO4: 96 case PM8607_ID_LDO4:
106 switch (chip_id) { 97 ret = (index < 3) ? (index * 50000 + 1800000) :
107 case PM8607_CHIP_A0: 98 ((index < 6) ? (index * 50000 + 2550000) :
108 case PM8607_CHIP_A1: 99 ((index == 6) ? 2900000 : 3300000));
109 ret = (index < 3) ? (index * 50000 + 1800000) :
110 ((index < 8) ? (index * 50000 + 2550000) :
111 -EINVAL);
112 break;
113 case PM8607_CHIP_B0:
114 ret = (index < 3) ? (index * 50000 + 1800000) :
115 ((index < 6) ? (index * 50000 + 2550000) :
116 ((index == 6) ? 2900000 : 3300000));
117 break;
118 }
119 break; 100 break;
120 case PM8607_ID_LDO6: 101 case PM8607_ID_LDO6:
121 switch (chip_id) { 102 ret = (index < 2) ? (index * 50000 + 1800000) :
122 case PM8607_CHIP_A0: 103 ((index < 7) ? (index * 50000 + 2500000) :
123 case PM8607_CHIP_A1: 104 3300000);
124 ret = (index < 3) ? (index * 50000 + 1800000) :
125 ((index < 8) ? (index * 50000 + 2450000) :
126 -EINVAL);
127 break;
128 case PM8607_CHIP_B0:
129 ret = (index < 2) ? (index * 50000 + 1800000) :
130 ((index < 7) ? (index * 50000 + 2500000) :
131 3300000);
132 break;
133 }
134 break; 105 break;
135 case PM8607_ID_LDO10: 106 case PM8607_ID_LDO10:
136 switch (chip_id) { 107 ret = (index < 3) ? (index * 50000 + 1800000) :
137 case PM8607_CHIP_A0: 108 ((index < 7) ? (index * 50000 + 2550000) :
138 case PM8607_CHIP_A1: 109 ((index == 7) ? 3300000 : 1200000));
139 ret = (index < 3) ? (index * 50000 + 1800000) :
140 ((index < 8) ? (index * 50000 + 2550000) :
141 1200000);
142 break;
143 case PM8607_CHIP_B0:
144 ret = (index < 3) ? (index * 50000 + 1800000) :
145 ((index < 7) ? (index * 50000 + 2550000) :
146 ((index == 7) ? 3300000 : 1200000));
147 break;
148 }
149 break; 110 break;
150 case PM8607_ID_LDO14: 111 case PM8607_ID_LDO14:
151 switch (chip_id) { 112 ret = (index < 2) ? (index * 50000 + 1800000) :
152 case PM8607_CHIP_A0: 113 ((index < 7) ? (index * 50000 + 2600000) :
153 case PM8607_CHIP_A1: 114 3300000);
154 ret = (index < 3) ? (index * 50000 + 1800000) :
155 ((index < 8) ? (index * 50000 + 2550000) :
156 -EINVAL);
157 break;
158 case PM8607_CHIP_B0:
159 ret = (index < 2) ? (index * 50000 + 1800000) :
160 ((index < 7) ? (index * 50000 + 2600000) :
161 3300000);
162 break;
163 }
164 break; 115 break;
165 } 116 }
166 return ret; 117 return ret;
@@ -169,7 +120,6 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
169static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) 120static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
170{ 121{
171 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 122 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
172 uint8_t chip_id = info->chip->chip_id;
173 int val = -ENOENT; 123 int val = -ENOENT;
174 int ret; 124 int ret;
175 125
@@ -254,161 +204,77 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
254 case PM8607_ID_LDO2: 204 case PM8607_ID_LDO2:
255 case PM8607_ID_LDO3: 205 case PM8607_ID_LDO3:
256 case PM8607_ID_LDO9: 206 case PM8607_ID_LDO9:
257 switch (chip_id) { 207 if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
258 case PM8607_CHIP_A0: 208 if (min_uV <= 1800000)
259 case PM8607_CHIP_A1: 209 val = 0;
260 if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */ 210 else if (min_uV <= 1900000)
261 if (min_uV <= 1800000) 211 val = (min_uV - 1750001) / 50000;
262 val = 0; 212 else
263 else if (min_uV <= 1900000) 213 val = 3; /* 2700mV */
264 val = (min_uV - 1750001) / 50000; 214 } else { /* 2700mV ~ 2850mV / 50mV */
265 else 215 if (min_uV <= 2850000) {
266 val = 3; /* 2700mV */ 216 val = (min_uV - 2650001) / 50000;
267 else { /* 2700mV ~ 2900mV / 50mV */ 217 val += 3;
268 if (min_uV <= 2900000) { 218 } else if (min_uV <= 3300000)
269 val = (min_uV - 2650001) / 50000; 219 val = 7;
270 val += 3; 220 else
271 } else 221 val = -EINVAL;
272 val = -EINVAL;
273 }
274 break;
275 case PM8607_CHIP_B0:
276 if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
277 if (min_uV <= 1800000)
278 val = 0;
279 else if (min_uV <= 1900000)
280 val = (min_uV - 1750001) / 50000;
281 else
282 val = 3; /* 2700mV */
283 } else { /* 2700mV ~ 2850mV / 50mV */
284 if (min_uV <= 2850000) {
285 val = (min_uV - 2650001) / 50000;
286 val += 3;
287 } else if (min_uV <= 3300000)
288 val = 7;
289 else
290 val = -EINVAL;
291 }
292 break;
293 } 222 }
294 break; 223 break;
295 case PM8607_ID_LDO4: 224 case PM8607_ID_LDO4:
296 switch (chip_id) { 225 if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
297 case PM8607_CHIP_A0: 226 if (min_uV <= 1800000)
298 case PM8607_CHIP_A1: 227 val = 0;
299 if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */ 228 else if (min_uV <= 1900000)
300 if (min_uV <= 1800000) 229 val = (min_uV - 1750001) / 50000;
301 val = 0; 230 else
302 else if (min_uV <= 1900000) 231 val = 3; /* 2700mV */
303 val = (min_uV - 1750001) / 50000; 232 } else { /* 2700mV ~ 2800mV / 50mV */
304 else 233 if (min_uV <= 2850000) {
305 val = 3; /* 2700mV */ 234 val = (min_uV - 2650001) / 50000;
306 else { /* 2700mV ~ 2900mV / 50mV */ 235 val += 3;
307 if (min_uV <= 2900000) { 236 } else if (min_uV <= 2900000)
308 val = (min_uV - 2650001) / 50000; 237 val = 6;
309 val += 3; 238 else if (min_uV <= 3300000)
310 } else 239 val = 7;
311 val = -EINVAL; 240 else
312 } 241 val = -EINVAL;
313 break;
314 case PM8607_CHIP_B0:
315 if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
316 if (min_uV <= 1800000)
317 val = 0;
318 else if (min_uV <= 1900000)
319 val = (min_uV - 1750001) / 50000;
320 else
321 val = 3; /* 2700mV */
322 } else { /* 2700mV ~ 2800mV / 50mV */
323 if (min_uV <= 2850000) {
324 val = (min_uV - 2650001) / 50000;
325 val += 3;
326 } else if (min_uV <= 2900000)
327 val = 6;
328 else if (min_uV <= 3300000)
329 val = 7;
330 else
331 val = -EINVAL;
332 }
333 break;
334 } 242 }
335 break; 243 break;
336 case PM8607_ID_LDO6: 244 case PM8607_ID_LDO6:
337 switch (chip_id) { 245 if (min_uV < 2600000) { /* 1800mV ~ 1850mV / 50mV */
338 case PM8607_CHIP_A0: 246 if (min_uV <= 1800000)
339 case PM8607_CHIP_A1: 247 val = 0;
340 if (min_uV < 2600000) { /* 1800mV ~ 1900mV / 50mV */ 248 else if (min_uV <= 1850000)
341 if (min_uV <= 1800000) 249 val = (min_uV - 1750001) / 50000;
342 val = 0; 250 else
343 else if (min_uV <= 1900000) 251 val = 2; /* 2600mV */
344 val = (min_uV - 1750001) / 50000; 252 } else { /* 2600mV ~ 2800mV / 50mV */
345 else 253 if (min_uV <= 2800000) {
346 val = 3; /* 2600mV */ 254 val = (min_uV - 2550001) / 50000;
347 } else { /* 2600mV ~ 2800mV / 50mV */ 255 val += 2;
348 if (min_uV <= 2800000) { 256 } else if (min_uV <= 3300000)
349 val = (min_uV - 2550001) / 50000; 257 val = 7;
350 val += 3; 258 else
351 } else 259 val = -EINVAL;
352 val = -EINVAL;
353 }
354 break;
355 case PM8607_CHIP_B0:
356 if (min_uV < 2600000) { /* 1800mV ~ 1850mV / 50mV */
357 if (min_uV <= 1800000)
358 val = 0;
359 else if (min_uV <= 1850000)
360 val = (min_uV - 1750001) / 50000;
361 else
362 val = 2; /* 2600mV */
363 } else { /* 2600mV ~ 2800mV / 50mV */
364 if (min_uV <= 2800000) {
365 val = (min_uV - 2550001) / 50000;
366 val += 2;
367 } else if (min_uV <= 3300000)
368 val = 7;
369 else
370 val = -EINVAL;
371 }
372 break;
373 } 260 }
374 break; 261 break;
375 case PM8607_ID_LDO14: 262 case PM8607_ID_LDO14:
376 switch (chip_id) { 263 if (min_uV < 2700000) { /* 1800mV ~ 1850mV / 50mV */
377 case PM8607_CHIP_A0: 264 if (min_uV <= 1800000)
378 case PM8607_CHIP_A1: 265 val = 0;
379 if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ 266 else if (min_uV <= 1850000)
380 if (min_uV <= 1800000) 267 val = (min_uV - 1750001) / 50000;
381 val = 0; 268 else
382 else if (min_uV <= 1900000) 269 val = 2; /* 2700mV */
383 val = (min_uV - 1750001) / 50000; 270 } else { /* 2700mV ~ 2900mV / 50mV */
384 else 271 if (min_uV <= 2900000) {
385 val = 3; /* 2700mV */ 272 val = (min_uV - 2650001) / 50000;
386 } else { /* 2700mV ~ 2900mV / 50mV */ 273 val += 2;
387 if (min_uV <= 2900000) { 274 } else if (min_uV <= 3300000)
388 val = (min_uV - 2650001) / 50000; 275 val = 7;
389 val += 3; 276 else
390 } else 277 val = -EINVAL;
391 val = -EINVAL;
392 }
393 break;
394 case PM8607_CHIP_B0:
395 if (min_uV < 2700000) { /* 1800mV ~ 1850mV / 50mV */
396 if (min_uV <= 1800000)
397 val = 0;
398 else if (min_uV <= 1850000)
399 val = (min_uV - 1750001) / 50000;
400 else
401 val = 2; /* 2700mV */
402 } else { /* 2700mV ~ 2900mV / 50mV */
403 if (min_uV <= 2900000) {
404 val = (min_uV - 2650001) / 50000;
405 val += 2;
406 } else if (min_uV <= 3300000)
407 val = 7;
408 else
409 val = -EINVAL;
410 }
411 break;
412 } 278 }
413 break; 279 break;
414 } 280 }
@@ -428,7 +294,6 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
428 int min_uV, int max_uV) 294 int min_uV, int max_uV)
429{ 295{
430 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 296 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
431 struct pm8607_chip *chip = info->chip;
432 uint8_t val, mask; 297 uint8_t val, mask;
433 int ret; 298 int ret;
434 299
@@ -443,13 +308,13 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
443 val = (uint8_t)(ret << info->vol_shift); 308 val = (uint8_t)(ret << info->vol_shift);
444 mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; 309 mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
445 310
446 ret = pm8607_set_bits(chip, info->vol_reg, mask, val); 311 ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val);
447 if (ret) 312 if (ret)
448 return ret; 313 return ret;
449 switch (info->desc.id) { 314 switch (info->desc.id) {
450 case PM8607_ID_BUCK1: 315 case PM8607_ID_BUCK1:
451 case PM8607_ID_BUCK3: 316 case PM8607_ID_BUCK3:
452 ret = pm8607_set_bits(chip, info->update_reg, 317 ret = pm860x_set_bits(info->i2c, info->update_reg,
453 1 << info->update_bit, 318 1 << info->update_bit,
454 1 << info->update_bit); 319 1 << info->update_bit);
455 break; 320 break;
@@ -460,11 +325,10 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
460static int pm8607_get_voltage(struct regulator_dev *rdev) 325static int pm8607_get_voltage(struct regulator_dev *rdev)
461{ 326{
462 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 327 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
463 struct pm8607_chip *chip = info->chip;
464 uint8_t val, mask; 328 uint8_t val, mask;
465 int ret; 329 int ret;
466 330
467 ret = pm8607_reg_read(chip, info->vol_reg); 331 ret = pm860x_reg_read(info->i2c, info->vol_reg);
468 if (ret < 0) 332 if (ret < 0)
469 return ret; 333 return ret;
470 334
@@ -477,9 +341,8 @@ static int pm8607_get_voltage(struct regulator_dev *rdev)
477static int pm8607_enable(struct regulator_dev *rdev) 341static int pm8607_enable(struct regulator_dev *rdev)
478{ 342{
479 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 343 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
480 struct pm8607_chip *chip = info->chip;
481 344
482 return pm8607_set_bits(chip, info->enable_reg, 345 return pm860x_set_bits(info->i2c, info->enable_reg,
483 1 << info->enable_bit, 346 1 << info->enable_bit,
484 1 << info->enable_bit); 347 1 << info->enable_bit);
485} 348}
@@ -487,19 +350,17 @@ static int pm8607_enable(struct regulator_dev *rdev)
487static int pm8607_disable(struct regulator_dev *rdev) 350static int pm8607_disable(struct regulator_dev *rdev)
488{ 351{
489 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 352 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
490 struct pm8607_chip *chip = info->chip;
491 353
492 return pm8607_set_bits(chip, info->enable_reg, 354 return pm860x_set_bits(info->i2c, info->enable_reg,
493 1 << info->enable_bit, 0); 355 1 << info->enable_bit, 0);
494} 356}
495 357
496static int pm8607_is_enabled(struct regulator_dev *rdev) 358static int pm8607_is_enabled(struct regulator_dev *rdev)
497{ 359{
498 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 360 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
499 struct pm8607_chip *chip = info->chip;
500 int ret; 361 int ret;
501 362
502 ret = pm8607_reg_read(chip, info->enable_reg); 363 ret = pm860x_reg_read(info->i2c, info->enable_reg);
503 if (ret < 0) 364 if (ret < 0)
504 return ret; 365 return ret;
505 366
@@ -589,8 +450,8 @@ static inline struct pm8607_regulator_info *find_regulator_info(int id)
589 450
590static int __devinit pm8607_regulator_probe(struct platform_device *pdev) 451static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
591{ 452{
592 struct pm8607_chip *chip = dev_get_drvdata(pdev->dev.parent); 453 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
593 struct pm8607_platform_data *pdata = chip->dev->platform_data; 454 struct pm860x_platform_data *pdata = chip->dev->platform_data;
594 struct pm8607_regulator_info *info = NULL; 455 struct pm8607_regulator_info *info = NULL;
595 456
596 info = find_regulator_info(pdev->id); 457 info = find_regulator_info(pdev->id);
@@ -599,6 +460,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
599 return -EINVAL; 460 return -EINVAL;
600 } 461 }
601 462
463 info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
602 info->chip = chip; 464 info->chip = chip;
603 465
604 info->regulator = regulator_register(&info->desc, &pdev->dev, 466 info->regulator = regulator_register(&info->desc, &pdev->dev,
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 834b48441829..04f2e085116a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -94,6 +94,12 @@ config REGULATOR_MAX8660
94 This driver controls a Maxim 8660/8661 voltage output 94 This driver controls a Maxim 8660/8661 voltage output
95 regulator via I2C bus. 95 regulator via I2C bus.
96 96
97config REGULATOR_MAX8925
98 tristate "Maxim MAX8925 Power Management IC"
99 depends on MFD_MAX8925
100 help
101 Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC.
102
97config REGULATOR_TWL4030 103config REGULATOR_TWL4030
98 bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" 104 bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
99 depends on TWL4030_CORE 105 depends on TWL4030_CORE
@@ -191,7 +197,7 @@ config REGULATOR_TPS6507X
191 197
192config REGULATOR_88PM8607 198config REGULATOR_88PM8607
193 bool "Marvell 88PM8607 Power regulators" 199 bool "Marvell 88PM8607 Power regulators"
194 depends on MFD_88PM8607=y 200 depends on MFD_88PM860X=y
195 help 201 help
196 This driver supports 88PM8607 voltage regulator chips. 202 This driver supports 88PM8607 voltage regulator chips.
197 203
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index e845b66ad59c..4e7feece22d5 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
15obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o 15obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
16obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o 16obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
17obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o 17obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
18obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
18obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o 19obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
19obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o 20obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
20obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o 21obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
new file mode 100644
index 000000000000..67873f08ed40
--- /dev/null
+++ b/drivers/regulator/max8925-regulator.c
@@ -0,0 +1,306 @@
1/*
2 * Regulators driver for Maxim max8925
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/err.h>
14#include <linux/i2c.h>
15#include <linux/platform_device.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h>
18#include <linux/mfd/max8925.h>
19
20#define SD1_DVM_VMIN 850000
21#define SD1_DVM_VMAX 1000000
22#define SD1_DVM_STEP 50000
23#define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */
24#define SD1_DVM_EN 6 /* SDV1 bit 6 */
25
26struct max8925_regulator_info {
27 struct regulator_desc desc;
28 struct regulator_dev *regulator;
29 struct i2c_client *i2c;
30 struct max8925_chip *chip;
31
32 int min_uV;
33 int max_uV;
34 int step_uV;
35 int vol_reg;
36 int vol_shift;
37 int vol_nbits;
38 int enable_bit;
39 int enable_reg;
40};
41
42static inline int check_range(struct max8925_regulator_info *info,
43 int min_uV, int max_uV)
44{
45 if (min_uV < info->min_uV || min_uV > info->max_uV)
46 return -EINVAL;
47
48 return 0;
49}
50
51static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index)
52{
53 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
54 return info->min_uV + index * info->step_uV;
55}
56
57static int max8925_set_voltage(struct regulator_dev *rdev,
58 int min_uV, int max_uV)
59{
60 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
61 unsigned char data, mask;
62
63 if (check_range(info, min_uV, max_uV)) {
64 dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n",
65 min_uV, max_uV);
66 return -EINVAL;
67 }
68 data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
69 data <<= info->vol_shift;
70 mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
71
72 return max8925_set_bits(info->i2c, info->vol_reg, mask, data);
73}
74
75static int max8925_get_voltage(struct regulator_dev *rdev)
76{
77 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
78 unsigned char data, mask;
79 int ret;
80
81 ret = max8925_reg_read(info->i2c, info->vol_reg);
82 if (ret < 0)
83 return ret;
84 mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
85 data = (ret & mask) >> info->vol_shift;
86
87 return max8925_list_voltage(rdev, data);
88}
89
90static int max8925_enable(struct regulator_dev *rdev)
91{
92 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
93
94 return max8925_set_bits(info->i2c, info->enable_reg,
95 1 << info->enable_bit,
96 1 << info->enable_bit);
97}
98
99static int max8925_disable(struct regulator_dev *rdev)
100{
101 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
102
103 return max8925_set_bits(info->i2c, info->enable_reg,
104 1 << info->enable_bit, 0);
105}
106
107static int max8925_is_enabled(struct regulator_dev *rdev)
108{
109 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
110 int ret;
111
112 ret = max8925_reg_read(info->i2c, info->vol_reg);
113 if (ret < 0)
114 return ret;
115
116 return ret & (1 << info->enable_bit);
117}
118
119static int max8925_set_dvm_voltage(struct regulator_dev *rdev, int uV)
120{
121 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
122 unsigned char data, mask;
123
124 if (uV < SD1_DVM_VMIN || uV > SD1_DVM_VMAX)
125 return -EINVAL;
126
127 data = (uV - SD1_DVM_VMIN + SD1_DVM_STEP - 1) / SD1_DVM_STEP;
128 data <<= SD1_DVM_SHIFT;
129 mask = 3 << SD1_DVM_SHIFT;
130
131 return max8925_set_bits(info->i2c, info->enable_reg, mask, data);
132}
133
134static int max8925_set_dvm_enable(struct regulator_dev *rdev)
135{
136 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
137
138 return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN,
139 1 << SD1_DVM_EN);
140}
141
142static int max8925_set_dvm_disable(struct regulator_dev *rdev)
143{
144 struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
145
146 return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN, 0);
147}
148
149static struct regulator_ops max8925_regulator_sdv_ops = {
150 .set_voltage = max8925_set_voltage,
151 .get_voltage = max8925_get_voltage,
152 .enable = max8925_enable,
153 .disable = max8925_disable,
154 .is_enabled = max8925_is_enabled,
155 .set_suspend_voltage = max8925_set_dvm_voltage,
156 .set_suspend_enable = max8925_set_dvm_enable,
157 .set_suspend_disable = max8925_set_dvm_disable,
158};
159
160static struct regulator_ops max8925_regulator_ldo_ops = {
161 .set_voltage = max8925_set_voltage,
162 .get_voltage = max8925_get_voltage,
163 .enable = max8925_enable,
164 .disable = max8925_disable,
165 .is_enabled = max8925_is_enabled,
166};
167
168#define MAX8925_SDV(_id, min, max, step) \
169{ \
170 .desc = { \
171 .name = "SDV" #_id, \
172 .ops = &max8925_regulator_sdv_ops, \
173 .type = REGULATOR_VOLTAGE, \
174 .id = MAX8925_ID_SD##_id, \
175 .owner = THIS_MODULE, \
176 }, \
177 .min_uV = min * 1000, \
178 .max_uV = max * 1000, \
179 .step_uV = step * 1000, \
180 .vol_reg = MAX8925_SDV##_id, \
181 .vol_shift = 0, \
182 .vol_nbits = 6, \
183 .enable_reg = MAX8925_SDCTL##_id, \
184 .enable_bit = 0, \
185}
186
187#define MAX8925_LDO(_id, min, max, step) \
188{ \
189 .desc = { \
190 .name = "LDO" #_id, \
191 .ops = &max8925_regulator_ldo_ops, \
192 .type = REGULATOR_VOLTAGE, \
193 .id = MAX8925_ID_LDO##_id, \
194 .owner = THIS_MODULE, \
195 }, \
196 .min_uV = min * 1000, \
197 .max_uV = max * 1000, \
198 .step_uV = step * 1000, \
199 .vol_reg = MAX8925_LDOVOUT##_id, \
200 .vol_shift = 0, \
201 .vol_nbits = 6, \
202 .enable_reg = MAX8925_LDOCTL##_id, \
203 .enable_bit = 0, \
204}
205
206static struct max8925_regulator_info max8925_regulator_info[] = {
207 MAX8925_SDV(1, 637.5, 1425, 12.5),
208 MAX8925_SDV(2, 650, 2225, 25),
209 MAX8925_SDV(3, 750, 3900, 50),
210
211 MAX8925_LDO(1, 750, 3900, 50),
212 MAX8925_LDO(2, 650, 2250, 25),
213 MAX8925_LDO(3, 650, 2250, 25),
214 MAX8925_LDO(4, 750, 3900, 50),
215 MAX8925_LDO(5, 750, 3900, 50),
216 MAX8925_LDO(6, 750, 3900, 50),
217 MAX8925_LDO(7, 750, 3900, 50),
218 MAX8925_LDO(8, 750, 3900, 50),
219 MAX8925_LDO(9, 750, 3900, 50),
220 MAX8925_LDO(10, 750, 3900, 50),
221 MAX8925_LDO(11, 750, 3900, 50),
222 MAX8925_LDO(12, 750, 3900, 50),
223 MAX8925_LDO(13, 750, 3900, 50),
224 MAX8925_LDO(14, 750, 3900, 50),
225 MAX8925_LDO(15, 750, 3900, 50),
226 MAX8925_LDO(16, 750, 3900, 50),
227 MAX8925_LDO(17, 650, 2250, 25),
228 MAX8925_LDO(18, 650, 2250, 25),
229 MAX8925_LDO(19, 750, 3900, 50),
230 MAX8925_LDO(20, 750, 3900, 50),
231};
232
233static inline struct max8925_regulator_info *find_regulator_info(int id)
234{
235 struct max8925_regulator_info *ri;
236 int i;
237
238 for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
239 ri = &max8925_regulator_info[i];
240 if (ri->desc.id == id)
241 return ri;
242 }
243 return NULL;
244}
245
246static int __devinit max8925_regulator_probe(struct platform_device *pdev)
247{
248 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
249 struct max8925_platform_data *pdata = chip->dev->platform_data;
250 struct max8925_regulator_info *ri = NULL;
251 struct regulator_dev *rdev;
252
253 ri = find_regulator_info(pdev->id);
254 if (ri == NULL) {
255 dev_err(&pdev->dev, "invalid regulator ID specified\n");
256 return -EINVAL;
257 }
258 ri->i2c = chip->i2c;
259 ri->chip = chip;
260
261 rdev = regulator_register(&ri->desc, &pdev->dev,
262 pdata->regulator[pdev->id], ri);
263 if (IS_ERR(rdev)) {
264 dev_err(&pdev->dev, "failed to register regulator %s\n",
265 ri->desc.name);
266 return PTR_ERR(rdev);
267 }
268
269 platform_set_drvdata(pdev, rdev);
270 return 0;
271}
272
273static int __devexit max8925_regulator_remove(struct platform_device *pdev)
274{
275 struct regulator_dev *rdev = platform_get_drvdata(pdev);
276
277 regulator_unregister(rdev);
278 return 0;
279}
280
281static struct platform_driver max8925_regulator_driver = {
282 .driver = {
283 .name = "max8925-regulator",
284 .owner = THIS_MODULE,
285 },
286 .probe = max8925_regulator_probe,
287 .remove = __devexit_p(max8925_regulator_remove),
288};
289
290static int __init max8925_regulator_init(void)
291{
292 return platform_driver_register(&max8925_regulator_driver);
293}
294subsys_initcall(max8925_regulator_init);
295
296static void __exit max8925_regulator_exit(void)
297{
298 platform_driver_unregister(&max8925_regulator_driver);
299}
300module_exit(max8925_regulator_exit);
301
302MODULE_LICENSE("GPL");
303MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
304MODULE_DESCRIPTION("Regulator Driver for Maxim 8925 PMIC");
305MODULE_ALIAS("platform:max8925-regulator");
306
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 94227dd6ba7b..723cd1fb4867 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1453,7 +1453,7 @@ static int wm8350_regulator_remove(struct platform_device *pdev)
1453 struct regulator_dev *rdev = platform_get_drvdata(pdev); 1453 struct regulator_dev *rdev = platform_get_drvdata(pdev);
1454 struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1454 struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
1455 1455
1456 wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq); 1456 wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
1457 1457
1458 regulator_unregister(rdev); 1458 regulator_unregister(rdev);
1459 1459
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2bb8a8b7ffaf..6a1303759432 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -175,6 +175,16 @@ config RTC_DRV_MAX6900
175 This driver can also be built as a module. If so, the module 175 This driver can also be built as a module. If so, the module
176 will be called rtc-max6900. 176 will be called rtc-max6900.
177 177
178config RTC_DRV_MAX8925
179 tristate "Maxim MAX8925"
180 depends on MFD_MAX8925
181 help
182 If you say yes here you will get support for the
183 RTC of Maxim MAX8925 PMIC.
184
185 This driver can also be built as a module. If so, the module
186 will be called rtc-max8925.
187
178config RTC_DRV_RS5C372 188config RTC_DRV_RS5C372
179 tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" 189 tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
180 help 190 help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index b7148afb8f55..44ef194a9573 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
52obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o 52obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
53obj-$(CONFIG_RTC_MXC) += rtc-mxc.o 53obj-$(CONFIG_RTC_MXC) += rtc-mxc.o
54obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o 54obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
55obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
55obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o 56obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
56obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o 57obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o
57obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o 58obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c
new file mode 100644
index 000000000000..acdbb1760187
--- /dev/null
+++ b/drivers/rtc/rtc-max8925.c
@@ -0,0 +1,314 @@
1/*
2 * RTC driver for Maxim MAX8925
3 *
4 * Copyright (C) 2009-2010 Marvell International Ltd.
5 * 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/module.h>
13#include <linux/i2c.h>
14#include <linux/rtc.h>
15#include <linux/platform_device.h>
16#include <linux/mfd/max8925.h>
17
18enum {
19 RTC_SEC = 0,
20 RTC_MIN,
21 RTC_HOUR,
22 RTC_WEEKDAY,
23 RTC_DATE,
24 RTC_MONTH,
25 RTC_YEAR1,
26 RTC_YEAR2,
27};
28
29#define MAX8925_RTC_SEC 0x00
30#define MAX8925_RTC_MIN 0x01
31#define MAX8925_RTC_HOUR 0x02
32#define MAX8925_RTC_WEEKDAY 0x03
33#define MAX8925_RTC_DATE 0x04
34#define MAX8925_RTC_MONTH 0x05
35#define MAX8925_RTC_YEAR1 0x06
36#define MAX8925_RTC_YEAR2 0x07
37#define MAX8925_ALARM0_SEC 0x08
38#define MAX8925_ALARM0_MIN 0x09
39#define MAX8925_ALARM0_HOUR 0x0a
40#define MAX8925_ALARM0_WEEKDAY 0x0b
41#define MAX8925_ALARM0_DATE 0x0c
42#define MAX8925_ALARM0_MON 0x0d
43#define MAX8925_ALARM0_YEAR1 0x0e
44#define MAX8925_ALARM0_YEAR2 0x0f
45#define MAX8925_ALARM1_SEC 0x10
46#define MAX8925_ALARM1_MIN 0x11
47#define MAX8925_ALARM1_HOUR 0x12
48#define MAX8925_ALARM1_WEEKDAY 0x13
49#define MAX8925_ALARM1_DATE 0x14
50#define MAX8925_ALARM1_MON 0x15
51#define MAX8925_ALARM1_YEAR1 0x16
52#define MAX8925_ALARM1_YEAR2 0x17
53#define MAX8925_RTC_CNTL 0x1b
54#define MAX8925_RTC_STATUS 0x20
55
56#define TIME_NUM 8
57#define ALARM_1SEC (1 << 7)
58#define HOUR_12 (1 << 7)
59#define HOUR_AM_PM (1 << 5)
60#define ALARM0_IRQ (1 << 3)
61#define ALARM1_IRQ (1 << 2)
62#define ALARM0_STATUS (1 << 2)
63#define ALARM1_STATUS (1 << 1)
64
65
66struct max8925_rtc_info {
67 struct rtc_device *rtc_dev;
68 struct max8925_chip *chip;
69 struct i2c_client *rtc;
70 struct device *dev;
71};
72
73static irqreturn_t rtc_update_handler(int irq, void *data)
74{
75 struct max8925_rtc_info *info = (struct max8925_rtc_info *)data;
76
77 /* disable ALARM0 except for 1SEC alarm */
78 max8925_set_bits(info->rtc, MAX8925_ALARM0_CNTL, 0x7f, 0);
79 rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
80 return IRQ_HANDLED;
81}
82
83static int tm_calc(struct rtc_time *tm, unsigned char *buf, int len)
84{
85 if (len < TIME_NUM)
86 return -EINVAL;
87 tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000
88 + (buf[RTC_YEAR2] & 0xf) * 100
89 + (buf[RTC_YEAR1] >> 4) * 10
90 + (buf[RTC_YEAR1] & 0xf);
91 tm->tm_year -= 1900;
92 tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10
93 + (buf[RTC_MONTH] & 0x0f);
94 tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10
95 + (buf[RTC_DATE] & 0x0f);
96 tm->tm_wday = buf[RTC_WEEKDAY] & 0x07;
97 if (buf[RTC_HOUR] & HOUR_12) {
98 tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10
99 + (buf[RTC_HOUR] & 0x0f);
100 if (buf[RTC_HOUR] & HOUR_AM_PM)
101 tm->tm_hour += 12;
102 } else
103 tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10
104 + (buf[RTC_HOUR] & 0x0f);
105 tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10
106 + (buf[RTC_MIN] & 0x0f);
107 tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10
108 + (buf[RTC_SEC] & 0x0f);
109 return 0;
110}
111
112static int data_calc(unsigned char *buf, struct rtc_time *tm, int len)
113{
114 unsigned char high, low;
115
116 if (len < TIME_NUM)
117 return -EINVAL;
118
119 high = (tm->tm_year + 1900) / 1000;
120 low = (tm->tm_year + 1900) / 100;
121 low = low - high * 10;
122 buf[RTC_YEAR2] = (high << 4) + low;
123 high = (tm->tm_year + 1900) / 10;
124 low = tm->tm_year + 1900;
125 low = low - high * 10;
126 high = high - (high / 10) * 10;
127 buf[RTC_YEAR1] = (high << 4) + low;
128 high = tm->tm_mon / 10;
129 low = tm->tm_mon;
130 low = low - high * 10;
131 buf[RTC_MONTH] = (high << 4) + low;
132 high = tm->tm_mday / 10;
133 low = tm->tm_mday;
134 low = low - high * 10;
135 buf[RTC_DATE] = (high << 4) + low;
136 buf[RTC_WEEKDAY] = tm->tm_wday;
137 high = tm->tm_hour / 10;
138 low = tm->tm_hour;
139 low = low - high * 10;
140 buf[RTC_HOUR] = (high << 4) + low;
141 high = tm->tm_min / 10;
142 low = tm->tm_min;
143 low = low - high * 10;
144 buf[RTC_MIN] = (high << 4) + low;
145 high = tm->tm_sec / 10;
146 low = tm->tm_sec;
147 low = low - high * 10;
148 buf[RTC_SEC] = (high << 4) + low;
149 return 0;
150}
151
152static int max8925_rtc_read_time(struct device *dev, struct rtc_time *tm)
153{
154 struct max8925_rtc_info *info = dev_get_drvdata(dev);
155 unsigned char buf[TIME_NUM];
156 int ret;
157
158 ret = max8925_bulk_read(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf);
159 if (ret < 0)
160 goto out;
161 ret = tm_calc(tm, buf, TIME_NUM);
162out:
163 return ret;
164}
165
166static int max8925_rtc_set_time(struct device *dev, struct rtc_time *tm)
167{
168 struct max8925_rtc_info *info = dev_get_drvdata(dev);
169 unsigned char buf[TIME_NUM];
170 int ret;
171
172 ret = data_calc(buf, tm, TIME_NUM);
173 if (ret < 0)
174 goto out;
175 ret = max8925_bulk_write(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf);
176out:
177 return ret;
178}
179
180static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
181{
182 struct max8925_rtc_info *info = dev_get_drvdata(dev);
183 unsigned char buf[TIME_NUM];
184 int ret;
185
186 ret = max8925_bulk_read(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf);
187 if (ret < 0)
188 goto out;
189 ret = tm_calc(&alrm->time, buf, TIME_NUM);
190 if (ret < 0)
191 goto out;
192 ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK);
193 if (ret < 0)
194 goto out;
195 if ((ret & ALARM0_IRQ) == 0)
196 alrm->enabled = 1;
197 else
198 alrm->enabled = 0;
199 ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS);
200 if (ret < 0)
201 goto out;
202 if (ret & ALARM0_STATUS)
203 alrm->pending = 1;
204 else
205 alrm->pending = 0;
206out:
207 return ret;
208}
209
210static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
211{
212 struct max8925_rtc_info *info = dev_get_drvdata(dev);
213 unsigned char buf[TIME_NUM];
214 int ret;
215
216 ret = data_calc(buf, &alrm->time, TIME_NUM);
217 if (ret < 0)
218 goto out;
219 ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf);
220 if (ret < 0)
221 goto out;
222 /* only enable alarm on year/month/day/hour/min/sec */
223 ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77);
224 if (ret < 0)
225 goto out;
226out:
227 return ret;
228}
229
230static const struct rtc_class_ops max8925_rtc_ops = {
231 .read_time = max8925_rtc_read_time,
232 .set_time = max8925_rtc_set_time,
233 .read_alarm = max8925_rtc_read_alarm,
234 .set_alarm = max8925_rtc_set_alarm,
235};
236
237static int __devinit max8925_rtc_probe(struct platform_device *pdev)
238{
239 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
240 struct max8925_rtc_info *info;
241 int irq, ret;
242
243 info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL);
244 if (!info)
245 return -ENOMEM;
246 info->chip = chip;
247 info->rtc = chip->rtc;
248 info->dev = &pdev->dev;
249 irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0;
250
251 ret = request_threaded_irq(irq, NULL, rtc_update_handler,
252 IRQF_ONESHOT, "rtc-alarm0", info);
253 if (ret < 0) {
254 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
255 irq, ret);
256 goto out_irq;
257 }
258
259 info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
260 &max8925_rtc_ops, THIS_MODULE);
261 ret = PTR_ERR(info->rtc_dev);
262 if (IS_ERR(info->rtc_dev)) {
263 dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
264 goto out_rtc;
265 }
266
267 dev_set_drvdata(&pdev->dev, info);
268 platform_set_drvdata(pdev, info);
269
270 return 0;
271out_rtc:
272 free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
273out_irq:
274 kfree(info);
275 return ret;
276}
277
278static int __devexit max8925_rtc_remove(struct platform_device *pdev)
279{
280 struct max8925_rtc_info *info = platform_get_drvdata(pdev);
281
282 if (info) {
283 free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
284 rtc_device_unregister(info->rtc_dev);
285 kfree(info);
286 }
287 return 0;
288}
289
290static struct platform_driver max8925_rtc_driver = {
291 .driver = {
292 .name = "max8925-rtc",
293 .owner = THIS_MODULE,
294 },
295 .probe = max8925_rtc_probe,
296 .remove = __devexit_p(max8925_rtc_remove),
297};
298
299static int __init max8925_rtc_init(void)
300{
301 return platform_driver_register(&max8925_rtc_driver);
302}
303module_init(max8925_rtc_init);
304
305static void __exit max8925_rtc_exit(void)
306{
307 platform_driver_unregister(&max8925_rtc_driver);
308}
309module_exit(max8925_rtc_exit);
310
311MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
312MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
313MODULE_LICENSE("GPL");
314
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index f1e440521c54..3d0dc76b38af 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -307,11 +307,18 @@ static int wm8350_rtc_update_irq_enable(struct device *dev,
307{ 307{
308 struct wm8350 *wm8350 = dev_get_drvdata(dev); 308 struct wm8350 *wm8350 = dev_get_drvdata(dev);
309 309
310 /* Suppress duplicate changes since genirq nests enable and
311 * disable calls. */
312 if (enabled == wm8350->rtc.update_enabled)
313 return 0;
314
310 if (enabled) 315 if (enabled)
311 wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); 316 wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
312 else 317 else
313 wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); 318 wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
314 319
320 wm8350->rtc.update_enabled = enabled;
321
315 return 0; 322 return 0;
316} 323}
317 324
@@ -478,8 +485,8 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev)
478 struct wm8350 *wm8350 = platform_get_drvdata(pdev); 485 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
479 struct wm8350_rtc *wm_rtc = &wm8350->rtc; 486 struct wm8350_rtc *wm_rtc = &wm8350->rtc;
480 487
481 wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); 488 wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350);
482 wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); 489 wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350);
483 490
484 rtc_device_unregister(wm_rtc->rtc); 491 rtc_device_unregister(wm_rtc->rtc);
485 492
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
new file mode 100644
index 000000000000..b8f705cca438
--- /dev/null
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -0,0 +1,304 @@
1/*
2 * Backlight driver for Marvell Semiconductor 88PM8606
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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/init.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/fb.h>
16#include <linux/i2c.h>
17#include <linux/backlight.h>
18#include <linux/mfd/88pm860x.h>
19
20#define MAX_BRIGHTNESS (0xFF)
21#define MIN_BRIGHTNESS (0)
22
23#define CURRENT_MASK (0x1F << 1)
24
25struct pm860x_backlight_data {
26 struct pm860x_chip *chip;
27 struct i2c_client *i2c;
28 int current_brightness;
29 int port;
30 int pwm;
31 int iset;
32};
33
34static inline int wled_a(int port)
35{
36 int ret;
37
38 ret = ((port - PM8606_BACKLIGHT1) << 1) + 2;
39 return ret;
40}
41
42static inline int wled_b(int port)
43{
44 int ret;
45
46 ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
47 return ret;
48}
49
50/* WLED2 & WLED3 share the same IDC */
51static inline int wled_idc(int port)
52{
53 int ret;
54
55 switch (port) {
56 case PM8606_BACKLIGHT1:
57 case PM8606_BACKLIGHT2:
58 ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
59 break;
60 case PM8606_BACKLIGHT3:
61 default:
62 ret = ((port - PM8606_BACKLIGHT2) << 1) + 3;
63 break;
64 }
65 return ret;
66}
67
68static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
69{
70 struct pm860x_backlight_data *data = bl_get_data(bl);
71 struct pm860x_chip *chip = data->chip;
72 unsigned char value;
73 int ret;
74
75 if (brightness > MAX_BRIGHTNESS)
76 value = MAX_BRIGHTNESS;
77 else
78 value = brightness;
79
80 ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
81 if (ret < 0)
82 goto out;
83
84 if ((data->current_brightness == 0) && brightness) {
85 if (data->iset) {
86 ret = pm860x_set_bits(data->i2c, wled_idc(data->port),
87 CURRENT_MASK, data->iset);
88 if (ret < 0)
89 goto out;
90 }
91 if (data->pwm) {
92 ret = pm860x_set_bits(data->i2c, PM8606_PWM,
93 PM8606_PWM_FREQ_MASK, data->pwm);
94 if (ret < 0)
95 goto out;
96 }
97 if (brightness == MAX_BRIGHTNESS) {
98 /* set WLED_ON bit as 100% */
99 ret = pm860x_set_bits(data->i2c, wled_b(data->port),
100 PM8606_WLED_ON, PM8606_WLED_ON);
101 }
102 } else {
103 if (brightness == MAX_BRIGHTNESS) {
104 /* set WLED_ON bit as 100% */
105 ret = pm860x_set_bits(data->i2c, wled_b(data->port),
106 PM8606_WLED_ON, PM8606_WLED_ON);
107 } else {
108 /* clear WLED_ON bit since it's not 100% */
109 ret = pm860x_set_bits(data->i2c, wled_b(data->port),
110 PM8606_WLED_ON, 0);
111 }
112 }
113 if (ret < 0)
114 goto out;
115
116 dev_dbg(chip->dev, "set brightness %d\n", value);
117 data->current_brightness = value;
118 return 0;
119out:
120 dev_dbg(chip->dev, "set brightness %d failure with return "
121 "value:%d\n", value, ret);
122 return ret;
123}
124
125static int pm860x_backlight_update_status(struct backlight_device *bl)
126{
127 int brightness = bl->props.brightness;
128
129 if (bl->props.power != FB_BLANK_UNBLANK)
130 brightness = 0;
131
132 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
133 brightness = 0;
134
135 if (bl->props.state & BL_CORE_SUSPENDED)
136 brightness = 0;
137
138 return pm860x_backlight_set(bl, brightness);
139}
140
141static int pm860x_backlight_get_brightness(struct backlight_device *bl)
142{
143 struct pm860x_backlight_data *data = bl_get_data(bl);
144 struct pm860x_chip *chip = data->chip;
145 int ret;
146
147 ret = pm860x_reg_read(data->i2c, wled_a(data->port));
148 if (ret < 0)
149 goto out;
150 data->current_brightness = ret;
151 dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
152 return data->current_brightness;
153out:
154 return -EINVAL;
155}
156
157static struct backlight_ops pm860x_backlight_ops = {
158 .options = BL_CORE_SUSPENDRESUME,
159 .update_status = pm860x_backlight_update_status,
160 .get_brightness = pm860x_backlight_get_brightness,
161};
162
163static int __check_device(struct pm860x_backlight_pdata *pdata, char *name)
164{
165 struct pm860x_backlight_pdata *p = pdata;
166 int ret = -EINVAL;
167
168 while (p && p->id) {
169 if ((p->id != PM8606_ID_BACKLIGHT) || (p->flags < 0))
170 break;
171
172 if (!strncmp(name, pm860x_backlight_name[p->flags],
173 MFD_NAME_SIZE)) {
174 ret = (int)p->flags;
175 break;
176 }
177 p++;
178 }
179 return ret;
180}
181
182static int pm860x_backlight_probe(struct platform_device *pdev)
183{
184 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
185 struct pm860x_platform_data *pm860x_pdata;
186 struct pm860x_backlight_pdata *pdata = NULL;
187 struct pm860x_backlight_data *data;
188 struct backlight_device *bl;
189 struct resource *res;
190 unsigned char value;
191 char name[MFD_NAME_SIZE];
192 int ret;
193
194 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
195 if (res == NULL) {
196 dev_err(&pdev->dev, "No I/O resource!\n");
197 return -EINVAL;
198 }
199
200 if (pdev->dev.parent->platform_data) {
201 pm860x_pdata = pdev->dev.parent->platform_data;
202 pdata = pm860x_pdata->backlight;
203 }
204 if (pdata == NULL) {
205 dev_err(&pdev->dev, "platform data isn't assigned to "
206 "backlight\n");
207 return -EINVAL;
208 }
209
210 data = kzalloc(sizeof(struct pm860x_backlight_data), GFP_KERNEL);
211 if (data == NULL)
212 return -ENOMEM;
213 strncpy(name, res->name, MFD_NAME_SIZE);
214 data->chip = chip;
215 data->i2c = (chip->id == CHIP_PM8606) ? chip->client \
216 : chip->companion;
217 data->current_brightness = MAX_BRIGHTNESS;
218 data->pwm = pdata->pwm;
219 data->iset = pdata->iset;
220 data->port = __check_device(pdata, name);
221 if (data->port < 0) {
222 dev_err(&pdev->dev, "wrong platform data is assigned");
223 return -EINVAL;
224 }
225
226 bl = backlight_device_register(name, &pdev->dev, data,
227 &pm860x_backlight_ops);
228 if (IS_ERR(bl)) {
229 dev_err(&pdev->dev, "failed to register backlight\n");
230 kfree(data);
231 return PTR_ERR(bl);
232 }
233 bl->props.max_brightness = MAX_BRIGHTNESS;
234 bl->props.brightness = MAX_BRIGHTNESS;
235
236 platform_set_drvdata(pdev, bl);
237
238 /* Enable reference VSYS */
239 ret = pm860x_reg_read(data->i2c, PM8606_VSYS);
240 if (ret < 0)
241 goto out;
242 if ((ret & PM8606_VSYS_EN) == 0) {
243 value = ret | PM8606_VSYS_EN;
244 ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value);
245 if (ret < 0)
246 goto out;
247 }
248 /* Enable reference OSC */
249 ret = pm860x_reg_read(data->i2c, PM8606_MISC);
250 if (ret < 0)
251 goto out;
252 if ((ret & PM8606_MISC_OSC_EN) == 0) {
253 value = ret | PM8606_MISC_OSC_EN;
254 ret = pm860x_reg_write(data->i2c, PM8606_MISC, value);
255 if (ret < 0)
256 goto out;
257 }
258 /* read current backlight */
259 ret = pm860x_backlight_get_brightness(bl);
260 if (ret < 0)
261 goto out;
262
263 backlight_update_status(bl);
264 return 0;
265out:
266 kfree(data);
267 return ret;
268}
269
270static int pm860x_backlight_remove(struct platform_device *pdev)
271{
272 struct backlight_device *bl = platform_get_drvdata(pdev);
273 struct pm860x_backlight_data *data = bl_get_data(bl);
274
275 backlight_device_unregister(bl);
276 kfree(data);
277 return 0;
278}
279
280static struct platform_driver pm860x_backlight_driver = {
281 .driver = {
282 .name = "88pm860x-backlight",
283 .owner = THIS_MODULE,
284 },
285 .probe = pm860x_backlight_probe,
286 .remove = pm860x_backlight_remove,
287};
288
289static int __init pm860x_backlight_init(void)
290{
291 return platform_driver_register(&pm860x_backlight_driver);
292}
293module_init(pm860x_backlight_init);
294
295static void __exit pm860x_backlight_exit(void)
296{
297 platform_driver_unregister(&pm860x_backlight_driver);
298}
299module_exit(pm860x_backlight_exit);
300
301MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606");
302MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
303MODULE_LICENSE("GPL");
304MODULE_ALIAS("platform:88pm860x-backlight");
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 09bfa9662e4d..0c77fc610212 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -212,6 +212,13 @@ config BACKLIGHT_DA903X
212 If you have a LCD backlight connected to the WLED output of DA9030 212 If you have a LCD backlight connected to the WLED output of DA9030
213 or DA9034 WLED output, say Y here to enable this driver. 213 or DA9034 WLED output, say Y here to enable this driver.
214 214
215config BACKLIGHT_MAX8925
216 tristate "Backlight driver for MAX8925"
217 depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925
218 help
219 If you have a LCD backlight connected to the WLED output of MAX8925
220 WLED output, say Y here to enable this driver.
221
215config BACKLIGHT_MBP_NVIDIA 222config BACKLIGHT_MBP_NVIDIA
216 tristate "MacBook Pro Nvidia Backlight Driver" 223 tristate "MacBook Pro Nvidia Backlight Driver"
217 depends on BACKLIGHT_CLASS_DEVICE && X86 224 depends on BACKLIGHT_CLASS_DEVICE && X86
@@ -262,3 +269,9 @@ config BACKLIGHT_ADP5520
262 To compile this driver as a module, choose M here: the module will 269 To compile this driver as a module, choose M here: the module will
263 be called adp5520_bl. 270 be called adp5520_bl.
264 271
272config BACKLIGHT_88PM860X
273 tristate "Backlight Driver for 88PM8606 using WLED"
274 depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X
275 help
276 Say Y to enable the backlight driver for Marvell 88PM8606.
277
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 9a405548874c..6c704d41462d 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -22,10 +22,12 @@ obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
22obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o 22obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
23obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o 23obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
24obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o 24obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
25obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
25obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o 26obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
26obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o 27obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
27obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o 28obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
28obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o 29obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
29obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o 30obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
30obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o 31obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
32obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
31 33
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
new file mode 100644
index 000000000000..c267069a52a3
--- /dev/null
+++ b/drivers/video/backlight/max8925_bl.c
@@ -0,0 +1,200 @@
1/*
2 * Backlight driver for Maxim MAX8925
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * 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/init.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/fb.h>
16#include <linux/i2c.h>
17#include <linux/backlight.h>
18#include <linux/mfd/max8925.h>
19
20#define MAX_BRIGHTNESS (0xff)
21#define MIN_BRIGHTNESS (0)
22
23#define LWX_FREQ(x) (((x - 601) / 100) & 0x7)
24
25struct max8925_backlight_data {
26 struct max8925_chip *chip;
27
28 int current_brightness;
29};
30
31static int max8925_backlight_set(struct backlight_device *bl, int brightness)
32{
33 struct max8925_backlight_data *data = bl_get_data(bl);
34 struct max8925_chip *chip = data->chip;
35 unsigned char value;
36 int ret;
37
38 if (brightness > MAX_BRIGHTNESS)
39 value = MAX_BRIGHTNESS;
40 else
41 value = brightness;
42
43 ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value);
44 if (ret < 0)
45 goto out;
46
47 if (!data->current_brightness && brightness)
48 /* enable WLED output */
49 ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1);
50 else if (!brightness)
51 /* disable WLED output */
52 ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0);
53 if (ret < 0)
54 goto out;
55 dev_dbg(chip->dev, "set brightness %d\n", value);
56 data->current_brightness = value;
57 return 0;
58out:
59 dev_dbg(chip->dev, "set brightness %d failure with return value:%d\n",
60 value, ret);
61 return ret;
62}
63
64static int max8925_backlight_update_status(struct backlight_device *bl)
65{
66 int brightness = bl->props.brightness;
67
68 if (bl->props.power != FB_BLANK_UNBLANK)
69 brightness = 0;
70
71 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
72 brightness = 0;
73
74 if (bl->props.state & BL_CORE_SUSPENDED)
75 brightness = 0;
76
77 return max8925_backlight_set(bl, brightness);
78}
79
80static int max8925_backlight_get_brightness(struct backlight_device *bl)
81{
82 struct max8925_backlight_data *data = bl_get_data(bl);
83 struct max8925_chip *chip = data->chip;
84 int ret;
85
86 ret = max8925_reg_read(chip->i2c, MAX8925_WLED_CNTL);
87 if (ret < 0)
88 return -EINVAL;
89 data->current_brightness = ret;
90 dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
91 return ret;
92}
93
94static struct backlight_ops max8925_backlight_ops = {
95 .options = BL_CORE_SUSPENDRESUME,
96 .update_status = max8925_backlight_update_status,
97 .get_brightness = max8925_backlight_get_brightness,
98};
99
100static int __devinit max8925_backlight_probe(struct platform_device *pdev)
101{
102 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
103 struct max8925_platform_data *max8925_pdata;
104 struct max8925_backlight_pdata *pdata = NULL;
105 struct max8925_backlight_data *data;
106 struct backlight_device *bl;
107 struct resource *res;
108 char name[MAX8925_NAME_SIZE];
109 unsigned char value;
110 int ret;
111
112 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
113 if (res == NULL) {
114 dev_err(&pdev->dev, "No I/O resource!\n");
115 return -EINVAL;
116 }
117
118 if (pdev->dev.parent->platform_data) {
119 max8925_pdata = pdev->dev.parent->platform_data;
120 pdata = max8925_pdata->backlight;
121 }
122
123 if (!pdata) {
124 dev_err(&pdev->dev, "platform data isn't assigned to "
125 "backlight\n");
126 return -EINVAL;
127 }
128
129 data = kzalloc(sizeof(struct max8925_backlight_data), GFP_KERNEL);
130 if (data == NULL)
131 return -ENOMEM;
132 strncpy(name, res->name, MAX8925_NAME_SIZE);
133 data->chip = chip;
134 data->current_brightness = 0;
135
136 bl = backlight_device_register(name, &pdev->dev, data,
137 &max8925_backlight_ops);
138 if (IS_ERR(bl)) {
139 dev_err(&pdev->dev, "failed to register backlight\n");
140 kfree(data);
141 return PTR_ERR(bl);
142 }
143 bl->props.max_brightness = MAX_BRIGHTNESS;
144 bl->props.brightness = MAX_BRIGHTNESS;
145
146 platform_set_drvdata(pdev, bl);
147
148 value = 0;
149 if (pdata->lxw_scl)
150 value |= (1 << 7);
151 if (pdata->lxw_freq)
152 value |= (LWX_FREQ(pdata->lxw_freq) << 4);
153 if (pdata->dual_string)
154 value |= (1 << 1);
155 ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value);
156 if (ret < 0)
157 goto out;
158
159 backlight_update_status(bl);
160 return 0;
161out:
162 kfree(data);
163 return ret;
164}
165
166static int __devexit max8925_backlight_remove(struct platform_device *pdev)
167{
168 struct backlight_device *bl = platform_get_drvdata(pdev);
169 struct max8925_backlight_data *data = bl_get_data(bl);
170
171 backlight_device_unregister(bl);
172 kfree(data);
173 return 0;
174}
175
176static struct platform_driver max8925_backlight_driver = {
177 .driver = {
178 .name = "max8925-backlight",
179 .owner = THIS_MODULE,
180 },
181 .probe = max8925_backlight_probe,
182 .remove = __devexit_p(max8925_backlight_remove),
183};
184
185static int __init max8925_backlight_init(void)
186{
187 return platform_driver_register(&max8925_backlight_driver);
188}
189module_init(max8925_backlight_init);
190
191static void __exit max8925_backlight_exit(void)
192{
193 platform_driver_unregister(&max8925_backlight_driver);
194};
195module_exit(max8925_backlight_exit);
196
197MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925");
198MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
199MODULE_LICENSE("GPL");
200MODULE_ALIAS("platform:max8925-backlight");