diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-12 13:01:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-12 13:01:06 -0400 |
commit | e83ddb335468cdd9ea6e9767eb30b64d8ff176ce (patch) | |
tree | af7ca0b5be74b713970149efaebe682596523252 /drivers | |
parent | 14a4fa20a10d76eb98b7feb25be60735217929ba (diff) | |
parent | d0a11693967295772d2a7c22b6b37eb20684e709 (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: (40 commits)
mfd: Fix incorrect kfree(i2c) in wm8994-core i2c_driver probe
mfd: Fix incorrect kfree(i2c) in wm831x-core i2c_driver probe
mfd: Fix incorrect kfree(i2c) in tps6507x i2c_driver probe
mfd: Add TPS6586x driver
mfd: Use macros instead of some constant magic numbers for menelaus
mfd: Fix menelaus mmc slot 2 misconfiguration
mfd: Missing slab.h includes
mfd: Fix wrong wm8350-core kfree in error path
mfd: Fix wm8994_device_init() return value
mfd: Avoid calling platform_device_put() twice in ucb1400 probe error path
mfd: Annotate tc6387xb probe/remove routines with __devinit/__devexit
mfd: Fix tc6387xb resource reclaim
mfd: Fix wrong goto labels for tc6393xb error handling
mfd: Get rid of now unused mc13783 private header
hwmon: Don't access struct mc13783 directly from mc13783-adc
mfd: New mc13783 function exposing flags
mfd: Check jz4740-adc kmalloc() result
mfd: Fix jz4740-adc resource reclaim in probe error path
mfd: Add WM8321 support
mfd: Add stmpe auto sleep feature
...
Diffstat (limited to 'drivers')
37 files changed, 3647 insertions, 119 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f623953b579..510aa205454 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -206,6 +206,13 @@ config GPIO_SX150X | |||
206 | 8 bits: sx1508q | 206 | 8 bits: sx1508q |
207 | 16 bits: sx1509q | 207 | 16 bits: sx1509q |
208 | 208 | ||
209 | config GPIO_STMPE | ||
210 | bool "STMPE GPIOs" | ||
211 | depends on MFD_STMPE | ||
212 | help | ||
213 | This enables support for the GPIOs found on the STMPE I/O | ||
214 | Expanders. | ||
215 | |||
209 | config GPIO_TC35892 | 216 | config GPIO_TC35892 |
210 | bool "TC35892 GPIOs" | 217 | bool "TC35892 GPIOs" |
211 | depends on MFD_TC35892 | 218 | depends on MFD_TC35892 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a69e0609ff7..fc6019d9372 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | |||
20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
22 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 22 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
23 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o | ||
23 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o | 24 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o |
24 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o | 25 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o |
25 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 26 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c new file mode 100644 index 00000000000..4e1f1b9d5e6 --- /dev/null +++ b/drivers/gpio/stmpe-gpio.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | |||
17 | /* | ||
18 | * These registers are modified under the irq bus lock and cached to avoid | ||
19 | * unnecessary writes in bus_sync_unlock. | ||
20 | */ | ||
21 | enum { REG_RE, REG_FE, REG_IE }; | ||
22 | |||
23 | #define CACHE_NR_REGS 3 | ||
24 | #define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8) | ||
25 | |||
26 | struct stmpe_gpio { | ||
27 | struct gpio_chip chip; | ||
28 | struct stmpe *stmpe; | ||
29 | struct device *dev; | ||
30 | struct mutex irq_lock; | ||
31 | |||
32 | int irq_base; | ||
33 | |||
34 | /* Caches of interrupt control registers for bus_lock */ | ||
35 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
36 | u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
37 | }; | ||
38 | |||
39 | static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip) | ||
40 | { | ||
41 | return container_of(chip, struct stmpe_gpio, chip); | ||
42 | } | ||
43 | |||
44 | static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
45 | { | ||
46 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
47 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
48 | u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8); | ||
49 | u8 mask = 1 << (offset % 8); | ||
50 | int ret; | ||
51 | |||
52 | ret = stmpe_reg_read(stmpe, reg); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | return ret & mask; | ||
57 | } | ||
58 | |||
59 | static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
60 | { | ||
61 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
62 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
63 | int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB; | ||
64 | u8 reg = stmpe->regs[which] - (offset / 8); | ||
65 | u8 mask = 1 << (offset % 8); | ||
66 | |||
67 | stmpe_reg_write(stmpe, reg, mask); | ||
68 | } | ||
69 | |||
70 | static int stmpe_gpio_direction_output(struct gpio_chip *chip, | ||
71 | unsigned offset, int val) | ||
72 | { | ||
73 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
74 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
75 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
76 | u8 mask = 1 << (offset % 8); | ||
77 | |||
78 | stmpe_gpio_set(chip, offset, val); | ||
79 | |||
80 | return stmpe_set_bits(stmpe, reg, mask, mask); | ||
81 | } | ||
82 | |||
83 | static int stmpe_gpio_direction_input(struct gpio_chip *chip, | ||
84 | unsigned offset) | ||
85 | { | ||
86 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
87 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
88 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
89 | u8 mask = 1 << (offset % 8); | ||
90 | |||
91 | return stmpe_set_bits(stmpe, reg, mask, 0); | ||
92 | } | ||
93 | |||
94 | static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
95 | { | ||
96 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
97 | |||
98 | return stmpe_gpio->irq_base + offset; | ||
99 | } | ||
100 | |||
101 | static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
102 | { | ||
103 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
104 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
105 | |||
106 | return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); | ||
107 | } | ||
108 | |||
109 | static struct gpio_chip template_chip = { | ||
110 | .label = "stmpe", | ||
111 | .owner = THIS_MODULE, | ||
112 | .direction_input = stmpe_gpio_direction_input, | ||
113 | .get = stmpe_gpio_get, | ||
114 | .direction_output = stmpe_gpio_direction_output, | ||
115 | .set = stmpe_gpio_set, | ||
116 | .to_irq = stmpe_gpio_to_irq, | ||
117 | .request = stmpe_gpio_request, | ||
118 | .can_sleep = 1, | ||
119 | }; | ||
120 | |||
121 | static int stmpe_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
122 | { | ||
123 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
124 | int offset = irq - stmpe_gpio->irq_base; | ||
125 | int regoffset = offset / 8; | ||
126 | int mask = 1 << (offset % 8); | ||
127 | |||
128 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | ||
129 | return -EINVAL; | ||
130 | |||
131 | if (type == IRQ_TYPE_EDGE_RISING) | ||
132 | stmpe_gpio->regs[REG_RE][regoffset] |= mask; | ||
133 | else | ||
134 | stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; | ||
135 | |||
136 | if (type == IRQ_TYPE_EDGE_FALLING) | ||
137 | stmpe_gpio->regs[REG_FE][regoffset] |= mask; | ||
138 | else | ||
139 | stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void stmpe_gpio_irq_lock(unsigned int irq) | ||
145 | { | ||
146 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
147 | |||
148 | mutex_lock(&stmpe_gpio->irq_lock); | ||
149 | } | ||
150 | |||
151 | static void stmpe_gpio_irq_sync_unlock(unsigned int irq) | ||
152 | { | ||
153 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
154 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
155 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
156 | static const u8 regmap[] = { | ||
157 | [REG_RE] = STMPE_IDX_GPRER_LSB, | ||
158 | [REG_FE] = STMPE_IDX_GPFER_LSB, | ||
159 | [REG_IE] = STMPE_IDX_IEGPIOR_LSB, | ||
160 | }; | ||
161 | int i, j; | ||
162 | |||
163 | for (i = 0; i < CACHE_NR_REGS; i++) { | ||
164 | for (j = 0; j < num_banks; j++) { | ||
165 | u8 old = stmpe_gpio->oldregs[i][j]; | ||
166 | u8 new = stmpe_gpio->regs[i][j]; | ||
167 | |||
168 | if (new == old) | ||
169 | continue; | ||
170 | |||
171 | stmpe_gpio->oldregs[i][j] = new; | ||
172 | stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | mutex_unlock(&stmpe_gpio->irq_lock); | ||
177 | } | ||
178 | |||
179 | static void stmpe_gpio_irq_mask(unsigned int irq) | ||
180 | { | ||
181 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
182 | int offset = irq - stmpe_gpio->irq_base; | ||
183 | int regoffset = offset / 8; | ||
184 | int mask = 1 << (offset % 8); | ||
185 | |||
186 | stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; | ||
187 | } | ||
188 | |||
189 | static void stmpe_gpio_irq_unmask(unsigned int irq) | ||
190 | { | ||
191 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
192 | int offset = irq - stmpe_gpio->irq_base; | ||
193 | int regoffset = offset / 8; | ||
194 | int mask = 1 << (offset % 8); | ||
195 | |||
196 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; | ||
197 | } | ||
198 | |||
199 | static struct irq_chip stmpe_gpio_irq_chip = { | ||
200 | .name = "stmpe-gpio", | ||
201 | .bus_lock = stmpe_gpio_irq_lock, | ||
202 | .bus_sync_unlock = stmpe_gpio_irq_sync_unlock, | ||
203 | .mask = stmpe_gpio_irq_mask, | ||
204 | .unmask = stmpe_gpio_irq_unmask, | ||
205 | .set_type = stmpe_gpio_irq_set_type, | ||
206 | }; | ||
207 | |||
208 | static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | ||
209 | { | ||
210 | struct stmpe_gpio *stmpe_gpio = dev; | ||
211 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
212 | u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; | ||
213 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
214 | u8 status[num_banks]; | ||
215 | int ret; | ||
216 | int i; | ||
217 | |||
218 | ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status); | ||
219 | if (ret < 0) | ||
220 | return IRQ_NONE; | ||
221 | |||
222 | for (i = 0; i < num_banks; i++) { | ||
223 | int bank = num_banks - i - 1; | ||
224 | unsigned int enabled = stmpe_gpio->regs[REG_IE][bank]; | ||
225 | unsigned int stat = status[i]; | ||
226 | |||
227 | stat &= enabled; | ||
228 | if (!stat) | ||
229 | continue; | ||
230 | |||
231 | while (stat) { | ||
232 | int bit = __ffs(stat); | ||
233 | int line = bank * 8 + bit; | ||
234 | |||
235 | handle_nested_irq(stmpe_gpio->irq_base + line); | ||
236 | stat &= ~(1 << bit); | ||
237 | } | ||
238 | |||
239 | stmpe_reg_write(stmpe, statmsbreg + i, status[i]); | ||
240 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i, | ||
241 | status[i]); | ||
242 | } | ||
243 | |||
244 | return IRQ_HANDLED; | ||
245 | } | ||
246 | |||
247 | static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) | ||
248 | { | ||
249 | int base = stmpe_gpio->irq_base; | ||
250 | int irq; | ||
251 | |||
252 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
253 | set_irq_chip_data(irq, stmpe_gpio); | ||
254 | set_irq_chip_and_handler(irq, &stmpe_gpio_irq_chip, | ||
255 | handle_simple_irq); | ||
256 | set_irq_nested_thread(irq, 1); | ||
257 | #ifdef CONFIG_ARM | ||
258 | set_irq_flags(irq, IRQF_VALID); | ||
259 | #else | ||
260 | set_irq_noprobe(irq); | ||
261 | #endif | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) | ||
268 | { | ||
269 | int base = stmpe_gpio->irq_base; | ||
270 | int irq; | ||
271 | |||
272 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
273 | #ifdef CONFIG_ARM | ||
274 | set_irq_flags(irq, 0); | ||
275 | #endif | ||
276 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
277 | set_irq_chip_data(irq, NULL); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | ||
282 | { | ||
283 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
284 | struct stmpe_gpio_platform_data *pdata; | ||
285 | struct stmpe_gpio *stmpe_gpio; | ||
286 | int ret; | ||
287 | int irq; | ||
288 | |||
289 | pdata = stmpe->pdata->gpio; | ||
290 | if (!pdata) | ||
291 | return -ENODEV; | ||
292 | |||
293 | irq = platform_get_irq(pdev, 0); | ||
294 | if (irq < 0) | ||
295 | return irq; | ||
296 | |||
297 | stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); | ||
298 | if (!stmpe_gpio) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | mutex_init(&stmpe_gpio->irq_lock); | ||
302 | |||
303 | stmpe_gpio->dev = &pdev->dev; | ||
304 | stmpe_gpio->stmpe = stmpe; | ||
305 | |||
306 | stmpe_gpio->chip = template_chip; | ||
307 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; | ||
308 | stmpe_gpio->chip.dev = &pdev->dev; | ||
309 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; | ||
310 | |||
311 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | ||
312 | |||
313 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
314 | if (ret) | ||
315 | return ret; | ||
316 | |||
317 | ret = stmpe_gpio_irq_init(stmpe_gpio); | ||
318 | if (ret) | ||
319 | goto out_free; | ||
320 | |||
321 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, | ||
322 | "stmpe-gpio", stmpe_gpio); | ||
323 | if (ret) { | ||
324 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
325 | goto out_removeirq; | ||
326 | } | ||
327 | |||
328 | ret = gpiochip_add(&stmpe_gpio->chip); | ||
329 | if (ret) { | ||
330 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
331 | goto out_freeirq; | ||
332 | } | ||
333 | |||
334 | if (pdata && pdata->setup) | ||
335 | pdata->setup(stmpe, stmpe_gpio->chip.base); | ||
336 | |||
337 | platform_set_drvdata(pdev, stmpe_gpio); | ||
338 | |||
339 | return 0; | ||
340 | |||
341 | out_freeirq: | ||
342 | free_irq(irq, stmpe_gpio); | ||
343 | out_removeirq: | ||
344 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
345 | out_free: | ||
346 | kfree(stmpe_gpio); | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int __devexit stmpe_gpio_remove(struct platform_device *pdev) | ||
351 | { | ||
352 | struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); | ||
353 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
354 | struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio; | ||
355 | int irq = platform_get_irq(pdev, 0); | ||
356 | int ret; | ||
357 | |||
358 | if (pdata && pdata->remove) | ||
359 | pdata->remove(stmpe, stmpe_gpio->chip.base); | ||
360 | |||
361 | ret = gpiochip_remove(&stmpe_gpio->chip); | ||
362 | if (ret < 0) { | ||
363 | dev_err(stmpe_gpio->dev, | ||
364 | "unable to remove gpiochip: %d\n", ret); | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | ||
369 | |||
370 | free_irq(irq, stmpe_gpio); | ||
371 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
372 | platform_set_drvdata(pdev, NULL); | ||
373 | kfree(stmpe_gpio); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static struct platform_driver stmpe_gpio_driver = { | ||
379 | .driver.name = "stmpe-gpio", | ||
380 | .driver.owner = THIS_MODULE, | ||
381 | .probe = stmpe_gpio_probe, | ||
382 | .remove = __devexit_p(stmpe_gpio_remove), | ||
383 | }; | ||
384 | |||
385 | static int __init stmpe_gpio_init(void) | ||
386 | { | ||
387 | return platform_driver_register(&stmpe_gpio_driver); | ||
388 | } | ||
389 | subsys_initcall(stmpe_gpio_init); | ||
390 | |||
391 | static void __exit stmpe_gpio_exit(void) | ||
392 | { | ||
393 | platform_driver_unregister(&stmpe_gpio_driver); | ||
394 | } | ||
395 | module_exit(stmpe_gpio_exit); | ||
396 | |||
397 | MODULE_LICENSE("GPL v2"); | ||
398 | MODULE_DESCRIPTION("STMPExxxx GPIO driver"); | ||
399 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c index 1fa449a1a4c..309644cf4d9 100644 --- a/drivers/gpio/wm831x-gpio.c +++ b/drivers/gpio/wm831x-gpio.c | |||
@@ -108,6 +108,37 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; | 108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, | ||
112 | unsigned debounce) | ||
113 | { | ||
114 | struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); | ||
115 | struct wm831x *wm831x = wm831x_gpio->wm831x; | ||
116 | int reg = WM831X_GPIO1_CONTROL + offset; | ||
117 | int ret, fn; | ||
118 | |||
119 | ret = wm831x_reg_read(wm831x, reg); | ||
120 | if (ret < 0) | ||
121 | return ret; | ||
122 | |||
123 | switch (ret & WM831X_GPN_FN_MASK) { | ||
124 | case 0: | ||
125 | case 1: | ||
126 | break; | ||
127 | default: | ||
128 | /* Not in GPIO mode */ | ||
129 | return -EBUSY; | ||
130 | } | ||
131 | |||
132 | if (debounce >= 32 && debounce <= 64) | ||
133 | fn = 0; | ||
134 | else if (debounce >= 4000 && debounce <= 8000) | ||
135 | fn = 1; | ||
136 | else | ||
137 | return -EINVAL; | ||
138 | |||
139 | return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); | ||
140 | } | ||
141 | |||
111 | #ifdef CONFIG_DEBUG_FS | 142 | #ifdef CONFIG_DEBUG_FS |
112 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 143 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
113 | { | 144 | { |
@@ -208,6 +239,7 @@ static struct gpio_chip template_chip = { | |||
208 | .direction_output = wm831x_gpio_direction_out, | 239 | .direction_output = wm831x_gpio_direction_out, |
209 | .set = wm831x_gpio_set, | 240 | .set = wm831x_gpio_set, |
210 | .to_irq = wm831x_gpio_to_irq, | 241 | .to_irq = wm831x_gpio_to_irq, |
242 | .set_debounce = wm831x_gpio_set_debounce, | ||
211 | .dbg_show = wm831x_gpio_dbg_show, | 243 | .dbg_show = wm831x_gpio_dbg_show, |
212 | .can_sleep = 1, | 244 | .can_sleep = 1, |
213 | }; | 245 | }; |
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c index ce3c7bc8181..d5226c9e120 100644 --- a/drivers/hwmon/mc13783-adc.c +++ b/drivers/hwmon/mc13783-adc.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/mfd/mc13783-private.h> | 21 | #include <linux/mfd/mc13783.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/hwmon-sysfs.h> | 23 | #include <linux/hwmon-sysfs.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
@@ -144,6 +144,14 @@ static const struct attribute_group mc13783_group_ts = { | |||
144 | .attrs = mc13783_attr_ts, | 144 | .attrs = mc13783_attr_ts, |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static int mc13783_adc_use_touchscreen(struct platform_device *pdev) | ||
148 | { | ||
149 | struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); | ||
150 | unsigned flags = mc13783_get_flags(priv->mc13783); | ||
151 | |||
152 | return flags & MC13783_USE_TOUCHSCREEN; | ||
153 | } | ||
154 | |||
147 | static int __init mc13783_adc_probe(struct platform_device *pdev) | 155 | static int __init mc13783_adc_probe(struct platform_device *pdev) |
148 | { | 156 | { |
149 | struct mc13783_adc_priv *priv; | 157 | struct mc13783_adc_priv *priv; |
@@ -162,10 +170,11 @@ static int __init mc13783_adc_probe(struct platform_device *pdev) | |||
162 | if (ret) | 170 | if (ret) |
163 | goto out_err_create1; | 171 | goto out_err_create1; |
164 | 172 | ||
165 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 173 | if (!mc13783_adc_use_touchscreen(pdev)) { |
166 | ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); | 174 | ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); |
167 | if (ret) | 175 | if (ret) |
168 | goto out_err_create2; | 176 | goto out_err_create2; |
177 | } | ||
169 | 178 | ||
170 | priv->hwmon_dev = hwmon_device_register(&pdev->dev); | 179 | priv->hwmon_dev = hwmon_device_register(&pdev->dev); |
171 | if (IS_ERR(priv->hwmon_dev)) { | 180 | if (IS_ERR(priv->hwmon_dev)) { |
@@ -180,7 +189,7 @@ static int __init mc13783_adc_probe(struct platform_device *pdev) | |||
180 | 189 | ||
181 | out_err_register: | 190 | out_err_register: |
182 | 191 | ||
183 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 192 | if (!mc13783_adc_use_touchscreen(pdev)) |
184 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); | 193 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); |
185 | out_err_create2: | 194 | out_err_create2: |
186 | 195 | ||
@@ -199,7 +208,7 @@ static int __devexit mc13783_adc_remove(struct platform_device *pdev) | |||
199 | 208 | ||
200 | hwmon_device_unregister(priv->hwmon_dev); | 209 | hwmon_device_unregister(priv->hwmon_dev); |
201 | 210 | ||
202 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 211 | if (!mc13783_adc_use_touchscreen(pdev)) |
203 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); | 212 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); |
204 | 213 | ||
205 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); | 214 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b171f63fe4d..9cc488d2149 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -395,6 +395,16 @@ config KEYBOARD_SH_KEYSC | |||
395 | To compile this driver as a module, choose M here: the | 395 | To compile this driver as a module, choose M here: the |
396 | module will be called sh_keysc. | 396 | module will be called sh_keysc. |
397 | 397 | ||
398 | config KEYBOARD_STMPE | ||
399 | tristate "STMPE keypad support" | ||
400 | depends on MFD_STMPE | ||
401 | help | ||
402 | Say Y here if you want to use the keypad controller on STMPE I/O | ||
403 | expanders. | ||
404 | |||
405 | To compile this driver as a module, choose M here: the module will be | ||
406 | called stmpe-keypad. | ||
407 | |||
398 | config KEYBOARD_DAVINCI | 408 | config KEYBOARD_DAVINCI |
399 | tristate "TI DaVinci Key Scan" | 409 | tristate "TI DaVinci Key Scan" |
400 | depends on ARCH_DAVINCI_DM365 | 410 | depends on ARCH_DAVINCI_DM365 |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 1a66d5f1ca8..504b591be0c 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -35,6 +35,7 @@ obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | |||
35 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | 35 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o |
36 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o | 36 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o |
37 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 37 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
38 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o | ||
38 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 39 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
39 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 40 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
40 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 41 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c new file mode 100644 index 00000000000..ab7610ca10e --- /dev/null +++ b/drivers/input/keyboard/stmpe-keypad.c | |||
@@ -0,0 +1,386 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/input.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/input/matrix_keypad.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | |||
17 | /* These are at the same addresses in all STMPE variants */ | ||
18 | #define STMPE_KPC_COL 0x60 | ||
19 | #define STMPE_KPC_ROW_MSB 0x61 | ||
20 | #define STMPE_KPC_ROW_LSB 0x62 | ||
21 | #define STMPE_KPC_CTRL_MSB 0x63 | ||
22 | #define STMPE_KPC_CTRL_LSB 0x64 | ||
23 | #define STMPE_KPC_COMBI_KEY_0 0x65 | ||
24 | #define STMPE_KPC_COMBI_KEY_1 0x66 | ||
25 | #define STMPE_KPC_COMBI_KEY_2 0x67 | ||
26 | #define STMPE_KPC_DATA_BYTE0 0x68 | ||
27 | #define STMPE_KPC_DATA_BYTE1 0x69 | ||
28 | #define STMPE_KPC_DATA_BYTE2 0x6a | ||
29 | #define STMPE_KPC_DATA_BYTE3 0x6b | ||
30 | #define STMPE_KPC_DATA_BYTE4 0x6c | ||
31 | |||
32 | #define STMPE_KPC_CTRL_LSB_SCAN (0x1 << 0) | ||
33 | #define STMPE_KPC_CTRL_LSB_DEBOUNCE (0x7f << 1) | ||
34 | #define STMPE_KPC_CTRL_MSB_SCAN_COUNT (0xf << 4) | ||
35 | |||
36 | #define STMPE_KPC_ROW_MSB_ROWS 0xff | ||
37 | |||
38 | #define STMPE_KPC_DATA_UP (0x1 << 7) | ||
39 | #define STMPE_KPC_DATA_ROW (0xf << 3) | ||
40 | #define STMPE_KPC_DATA_COL (0x7 << 0) | ||
41 | #define STMPE_KPC_DATA_NOKEY_MASK 0x78 | ||
42 | |||
43 | #define STMPE_KEYPAD_MAX_DEBOUNCE 127 | ||
44 | #define STMPE_KEYPAD_MAX_SCAN_COUNT 15 | ||
45 | |||
46 | #define STMPE_KEYPAD_MAX_ROWS 8 | ||
47 | #define STMPE_KEYPAD_MAX_COLS 8 | ||
48 | #define STMPE_KEYPAD_ROW_SHIFT 3 | ||
49 | #define STMPE_KEYPAD_KEYMAP_SIZE \ | ||
50 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) | ||
51 | |||
52 | /** | ||
53 | * struct stmpe_keypad_variant - model-specific attributes | ||
54 | * @auto_increment: whether the KPC_DATA_BYTE register address | ||
55 | * auto-increments on multiple read | ||
56 | * @num_data: number of data bytes | ||
57 | * @num_normal_data: number of normal keys' data bytes | ||
58 | * @max_cols: maximum number of columns supported | ||
59 | * @max_rows: maximum number of rows supported | ||
60 | * @col_gpios: bitmask of gpios which can be used for columns | ||
61 | * @row_gpios: bitmask of gpios which can be used for rows | ||
62 | */ | ||
63 | struct stmpe_keypad_variant { | ||
64 | bool auto_increment; | ||
65 | int num_data; | ||
66 | int num_normal_data; | ||
67 | int max_cols; | ||
68 | int max_rows; | ||
69 | unsigned int col_gpios; | ||
70 | unsigned int row_gpios; | ||
71 | }; | ||
72 | |||
73 | static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | ||
74 | [STMPE1601] = { | ||
75 | .auto_increment = true, | ||
76 | .num_data = 5, | ||
77 | .num_normal_data = 3, | ||
78 | .max_cols = 8, | ||
79 | .max_rows = 8, | ||
80 | .col_gpios = 0x000ff, /* GPIO 0 - 7 */ | ||
81 | .row_gpios = 0x0ff00, /* GPIO 8 - 15 */ | ||
82 | }, | ||
83 | [STMPE2401] = { | ||
84 | .auto_increment = false, | ||
85 | .num_data = 3, | ||
86 | .num_normal_data = 2, | ||
87 | .max_cols = 8, | ||
88 | .max_rows = 12, | ||
89 | .col_gpios = 0x0000ff, /* GPIO 0 - 7*/ | ||
90 | .row_gpios = 0x1fef00, /* GPIO 8-14, 16-20 */ | ||
91 | }, | ||
92 | [STMPE2403] = { | ||
93 | .auto_increment = true, | ||
94 | .num_data = 5, | ||
95 | .num_normal_data = 3, | ||
96 | .max_cols = 8, | ||
97 | .max_rows = 12, | ||
98 | .col_gpios = 0x0000ff, /* GPIO 0 - 7*/ | ||
99 | .row_gpios = 0x1fef00, /* GPIO 8-14, 16-20 */ | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | struct stmpe_keypad { | ||
104 | struct stmpe *stmpe; | ||
105 | struct input_dev *input; | ||
106 | const struct stmpe_keypad_variant *variant; | ||
107 | const struct stmpe_keypad_platform_data *plat; | ||
108 | |||
109 | unsigned int rows; | ||
110 | unsigned int cols; | ||
111 | |||
112 | unsigned short keymap[STMPE_KEYPAD_KEYMAP_SIZE]; | ||
113 | }; | ||
114 | |||
115 | static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data) | ||
116 | { | ||
117 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
118 | struct stmpe *stmpe = keypad->stmpe; | ||
119 | int ret; | ||
120 | int i; | ||
121 | |||
122 | if (variant->auto_increment) | ||
123 | return stmpe_block_read(stmpe, STMPE_KPC_DATA_BYTE0, | ||
124 | variant->num_data, data); | ||
125 | |||
126 | for (i = 0; i < variant->num_data; i++) { | ||
127 | ret = stmpe_reg_read(stmpe, STMPE_KPC_DATA_BYTE0 + i); | ||
128 | if (ret < 0) | ||
129 | return ret; | ||
130 | |||
131 | data[i] = ret; | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static irqreturn_t stmpe_keypad_irq(int irq, void *dev) | ||
138 | { | ||
139 | struct stmpe_keypad *keypad = dev; | ||
140 | struct input_dev *input = keypad->input; | ||
141 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
142 | u8 fifo[variant->num_data]; | ||
143 | int ret; | ||
144 | int i; | ||
145 | |||
146 | ret = stmpe_keypad_read_data(keypad, fifo); | ||
147 | if (ret < 0) | ||
148 | return IRQ_NONE; | ||
149 | |||
150 | for (i = 0; i < variant->num_normal_data; i++) { | ||
151 | u8 data = fifo[i]; | ||
152 | int row = (data & STMPE_KPC_DATA_ROW) >> 3; | ||
153 | int col = data & STMPE_KPC_DATA_COL; | ||
154 | int code = MATRIX_SCAN_CODE(row, col, STMPE_KEYPAD_ROW_SHIFT); | ||
155 | bool up = data & STMPE_KPC_DATA_UP; | ||
156 | |||
157 | if ((data & STMPE_KPC_DATA_NOKEY_MASK) | ||
158 | == STMPE_KPC_DATA_NOKEY_MASK) | ||
159 | continue; | ||
160 | |||
161 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
162 | input_report_key(input, keypad->keymap[code], !up); | ||
163 | input_sync(input); | ||
164 | } | ||
165 | |||
166 | return IRQ_HANDLED; | ||
167 | } | ||
168 | |||
169 | static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) | ||
170 | { | ||
171 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
172 | unsigned int col_gpios = variant->col_gpios; | ||
173 | unsigned int row_gpios = variant->row_gpios; | ||
174 | struct stmpe *stmpe = keypad->stmpe; | ||
175 | unsigned int pins = 0; | ||
176 | int i; | ||
177 | |||
178 | /* | ||
179 | * Figure out which pins need to be set to the keypad alternate | ||
180 | * function. | ||
181 | * | ||
182 | * {cols,rows}_gpios are bitmasks of which pins on the chip can be used | ||
183 | * for the keypad. | ||
184 | * | ||
185 | * keypad->{cols,rows} are a bitmask of which pins (of the ones useable | ||
186 | * for the keypad) are used on the board. | ||
187 | */ | ||
188 | |||
189 | for (i = 0; i < variant->max_cols; i++) { | ||
190 | int num = __ffs(col_gpios); | ||
191 | |||
192 | if (keypad->cols & (1 << i)) | ||
193 | pins |= 1 << num; | ||
194 | |||
195 | col_gpios &= ~(1 << num); | ||
196 | } | ||
197 | |||
198 | for (i = 0; i < variant->max_rows; i++) { | ||
199 | int num = __ffs(row_gpios); | ||
200 | |||
201 | if (keypad->rows & (1 << i)) | ||
202 | pins |= 1 << num; | ||
203 | |||
204 | row_gpios &= ~(1 << num); | ||
205 | } | ||
206 | |||
207 | return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD); | ||
208 | } | ||
209 | |||
210 | static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad) | ||
211 | { | ||
212 | const struct stmpe_keypad_platform_data *plat = keypad->plat; | ||
213 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
214 | struct stmpe *stmpe = keypad->stmpe; | ||
215 | int ret; | ||
216 | |||
217 | if (plat->debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE) | ||
218 | return -EINVAL; | ||
219 | |||
220 | if (plat->scan_count > STMPE_KEYPAD_MAX_SCAN_COUNT) | ||
221 | return -EINVAL; | ||
222 | |||
223 | ret = stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD); | ||
224 | if (ret < 0) | ||
225 | return ret; | ||
226 | |||
227 | ret = stmpe_keypad_altfunc_init(keypad); | ||
228 | if (ret < 0) | ||
229 | return ret; | ||
230 | |||
231 | ret = stmpe_reg_write(stmpe, STMPE_KPC_COL, keypad->cols); | ||
232 | if (ret < 0) | ||
233 | return ret; | ||
234 | |||
235 | ret = stmpe_reg_write(stmpe, STMPE_KPC_ROW_LSB, keypad->rows); | ||
236 | if (ret < 0) | ||
237 | return ret; | ||
238 | |||
239 | if (variant->max_rows > 8) { | ||
240 | ret = stmpe_set_bits(stmpe, STMPE_KPC_ROW_MSB, | ||
241 | STMPE_KPC_ROW_MSB_ROWS, | ||
242 | keypad->rows >> 8); | ||
243 | if (ret < 0) | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | ret = stmpe_set_bits(stmpe, STMPE_KPC_CTRL_MSB, | ||
248 | STMPE_KPC_CTRL_MSB_SCAN_COUNT, | ||
249 | plat->scan_count << 4); | ||
250 | if (ret < 0) | ||
251 | return ret; | ||
252 | |||
253 | return stmpe_set_bits(stmpe, STMPE_KPC_CTRL_LSB, | ||
254 | STMPE_KPC_CTRL_LSB_SCAN | | ||
255 | STMPE_KPC_CTRL_LSB_DEBOUNCE, | ||
256 | STMPE_KPC_CTRL_LSB_SCAN | | ||
257 | (plat->debounce_ms << 1)); | ||
258 | } | ||
259 | |||
260 | static int __devinit stmpe_keypad_probe(struct platform_device *pdev) | ||
261 | { | ||
262 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
263 | struct stmpe_keypad_platform_data *plat; | ||
264 | struct stmpe_keypad *keypad; | ||
265 | struct input_dev *input; | ||
266 | int ret; | ||
267 | int irq; | ||
268 | int i; | ||
269 | |||
270 | plat = stmpe->pdata->keypad; | ||
271 | if (!plat) | ||
272 | return -ENODEV; | ||
273 | |||
274 | irq = platform_get_irq(pdev, 0); | ||
275 | if (irq < 0) | ||
276 | return irq; | ||
277 | |||
278 | keypad = kzalloc(sizeof(struct stmpe_keypad), GFP_KERNEL); | ||
279 | if (!keypad) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | input = input_allocate_device(); | ||
283 | if (!input) { | ||
284 | ret = -ENOMEM; | ||
285 | goto out_freekeypad; | ||
286 | } | ||
287 | |||
288 | input->name = "STMPE keypad"; | ||
289 | input->id.bustype = BUS_I2C; | ||
290 | input->dev.parent = &pdev->dev; | ||
291 | |||
292 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
293 | |||
294 | __set_bit(EV_KEY, input->evbit); | ||
295 | if (!plat->no_autorepeat) | ||
296 | __set_bit(EV_REP, input->evbit); | ||
297 | |||
298 | input->keycode = keypad->keymap; | ||
299 | input->keycodesize = sizeof(keypad->keymap[0]); | ||
300 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
301 | |||
302 | matrix_keypad_build_keymap(plat->keymap_data, STMPE_KEYPAD_ROW_SHIFT, | ||
303 | input->keycode, input->keybit); | ||
304 | |||
305 | for (i = 0; i < plat->keymap_data->keymap_size; i++) { | ||
306 | unsigned int key = plat->keymap_data->keymap[i]; | ||
307 | |||
308 | keypad->cols |= 1 << KEY_COL(key); | ||
309 | keypad->rows |= 1 << KEY_ROW(key); | ||
310 | } | ||
311 | |||
312 | keypad->stmpe = stmpe; | ||
313 | keypad->plat = plat; | ||
314 | keypad->input = input; | ||
315 | keypad->variant = &stmpe_keypad_variants[stmpe->partnum]; | ||
316 | |||
317 | ret = stmpe_keypad_chip_init(keypad); | ||
318 | if (ret < 0) | ||
319 | goto out_freeinput; | ||
320 | |||
321 | ret = input_register_device(input); | ||
322 | if (ret) { | ||
323 | dev_err(&pdev->dev, | ||
324 | "unable to register input device: %d\n", ret); | ||
325 | goto out_freeinput; | ||
326 | } | ||
327 | |||
328 | ret = request_threaded_irq(irq, NULL, stmpe_keypad_irq, IRQF_ONESHOT, | ||
329 | "stmpe-keypad", keypad); | ||
330 | if (ret) { | ||
331 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
332 | goto out_unregisterinput; | ||
333 | } | ||
334 | |||
335 | platform_set_drvdata(pdev, keypad); | ||
336 | |||
337 | return 0; | ||
338 | |||
339 | out_unregisterinput: | ||
340 | input_unregister_device(input); | ||
341 | input = NULL; | ||
342 | out_freeinput: | ||
343 | input_free_device(input); | ||
344 | out_freekeypad: | ||
345 | kfree(keypad); | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit stmpe_keypad_remove(struct platform_device *pdev) | ||
350 | { | ||
351 | struct stmpe_keypad *keypad = platform_get_drvdata(pdev); | ||
352 | struct stmpe *stmpe = keypad->stmpe; | ||
353 | int irq = platform_get_irq(pdev, 0); | ||
354 | |||
355 | stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD); | ||
356 | |||
357 | free_irq(irq, keypad); | ||
358 | input_unregister_device(keypad->input); | ||
359 | platform_set_drvdata(pdev, NULL); | ||
360 | kfree(keypad); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static struct platform_driver stmpe_keypad_driver = { | ||
366 | .driver.name = "stmpe-keypad", | ||
367 | .driver.owner = THIS_MODULE, | ||
368 | .probe = stmpe_keypad_probe, | ||
369 | .remove = __devexit_p(stmpe_keypad_remove), | ||
370 | }; | ||
371 | |||
372 | static int __init stmpe_keypad_init(void) | ||
373 | { | ||
374 | return platform_driver_register(&stmpe_keypad_driver); | ||
375 | } | ||
376 | module_init(stmpe_keypad_init); | ||
377 | |||
378 | static void __exit stmpe_keypad_exit(void) | ||
379 | { | ||
380 | platform_driver_unregister(&stmpe_keypad_driver); | ||
381 | } | ||
382 | module_exit(stmpe_keypad_exit); | ||
383 | |||
384 | MODULE_LICENSE("GPL v2"); | ||
385 | MODULE_DESCRIPTION("STMPExxxx keypad driver"); | ||
386 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 61f35184f76..0069d9703fd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -628,4 +628,14 @@ config TOUCHSCREEN_TPS6507X | |||
628 | To compile this driver as a module, choose M here: the | 628 | To compile this driver as a module, choose M here: the |
629 | module will be called tps6507x_ts. | 629 | module will be called tps6507x_ts. |
630 | 630 | ||
631 | config TOUCHSCREEN_STMPE | ||
632 | tristate "STMicroelectronics STMPE touchscreens" | ||
633 | depends on MFD_STMPE | ||
634 | help | ||
635 | Say Y here if you want support for STMicroelectronics | ||
636 | STMPE touchscreen controllers. | ||
637 | |||
638 | To compile this driver as a module, choose M here: the | ||
639 | module will be called stmpe-ts. | ||
640 | |||
631 | endif | 641 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index bd6f30b4ff7..28217e1dcaf 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | |||
36 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 36 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
37 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o | 37 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o |
38 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 38 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
39 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | ||
39 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 40 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
40 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 41 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
41 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 42 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c new file mode 100644 index 00000000000..656148ec002 --- /dev/null +++ b/drivers/input/touchscreen/stmpe-ts.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* STMicroelectronics STMPE811 Touchscreen Driver | ||
2 | * | ||
3 | * (C) 2010 Luotao Fu <l.fu@pengutronix.de> | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #include <linux/mfd/stmpe.h> | ||
27 | |||
28 | /* Register layouts and functionalities are identical on all stmpexxx variants | ||
29 | * with touchscreen controller | ||
30 | */ | ||
31 | #define STMPE_REG_INT_STA 0x0B | ||
32 | #define STMPE_REG_ADC_CTRL1 0x20 | ||
33 | #define STMPE_REG_ADC_CTRL2 0x21 | ||
34 | #define STMPE_REG_TSC_CTRL 0x40 | ||
35 | #define STMPE_REG_TSC_CFG 0x41 | ||
36 | #define STMPE_REG_FIFO_TH 0x4A | ||
37 | #define STMPE_REG_FIFO_STA 0x4B | ||
38 | #define STMPE_REG_FIFO_SIZE 0x4C | ||
39 | #define STMPE_REG_TSC_DATA_XYZ 0x52 | ||
40 | #define STMPE_REG_TSC_FRACTION_Z 0x56 | ||
41 | #define STMPE_REG_TSC_I_DRIVE 0x58 | ||
42 | |||
43 | #define OP_MOD_XYZ 0 | ||
44 | |||
45 | #define STMPE_TSC_CTRL_TSC_EN (1<<0) | ||
46 | |||
47 | #define STMPE_FIFO_STA_RESET (1<<0) | ||
48 | |||
49 | #define STMPE_IRQ_TOUCH_DET 0 | ||
50 | |||
51 | #define SAMPLE_TIME(x) ((x & 0xf) << 4) | ||
52 | #define MOD_12B(x) ((x & 0x1) << 3) | ||
53 | #define REF_SEL(x) ((x & 0x1) << 1) | ||
54 | #define ADC_FREQ(x) (x & 0x3) | ||
55 | #define AVE_CTRL(x) ((x & 0x3) << 6) | ||
56 | #define DET_DELAY(x) ((x & 0x7) << 3) | ||
57 | #define SETTLING(x) (x & 0x7) | ||
58 | #define FRACTION_Z(x) (x & 0x7) | ||
59 | #define I_DRIVE(x) (x & 0x1) | ||
60 | #define OP_MODE(x) ((x & 0x7) << 1) | ||
61 | |||
62 | #define STMPE_TS_NAME "stmpe-ts" | ||
63 | #define XY_MASK 0xfff | ||
64 | |||
65 | struct stmpe_touch { | ||
66 | struct stmpe *stmpe; | ||
67 | struct input_dev *idev; | ||
68 | struct delayed_work work; | ||
69 | struct device *dev; | ||
70 | u8 sample_time; | ||
71 | u8 mod_12b; | ||
72 | u8 ref_sel; | ||
73 | u8 adc_freq; | ||
74 | u8 ave_ctrl; | ||
75 | u8 touch_det_delay; | ||
76 | u8 settling; | ||
77 | u8 fraction_z; | ||
78 | u8 i_drive; | ||
79 | }; | ||
80 | |||
81 | static int __stmpe_reset_fifo(struct stmpe *stmpe) | ||
82 | { | ||
83 | int ret; | ||
84 | |||
85 | ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, | ||
86 | STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET); | ||
87 | if (ret) | ||
88 | return ret; | ||
89 | |||
90 | return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, | ||
91 | STMPE_FIFO_STA_RESET, 0); | ||
92 | } | ||
93 | |||
94 | static void stmpe_work(struct work_struct *work) | ||
95 | { | ||
96 | int int_sta; | ||
97 | u32 timeout = 40; | ||
98 | |||
99 | struct stmpe_touch *ts = | ||
100 | container_of(work, struct stmpe_touch, work.work); | ||
101 | |||
102 | int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); | ||
103 | |||
104 | /* | ||
105 | * touch_det sometimes get desasserted or just get stuck. This appears | ||
106 | * to be a silicon bug, We still have to clearify this with the | ||
107 | * manufacture. As a workaround We release the key anyway if the | ||
108 | * touch_det keeps coming in after 4ms, while the FIFO contains no value | ||
109 | * during the whole time. | ||
110 | */ | ||
111 | while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) { | ||
112 | timeout--; | ||
113 | int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); | ||
114 | udelay(100); | ||
115 | } | ||
116 | |||
117 | /* reset the FIFO before we report release event */ | ||
118 | __stmpe_reset_fifo(ts->stmpe); | ||
119 | |||
120 | input_report_abs(ts->idev, ABS_PRESSURE, 0); | ||
121 | input_sync(ts->idev); | ||
122 | } | ||
123 | |||
124 | static irqreturn_t stmpe_ts_handler(int irq, void *data) | ||
125 | { | ||
126 | u8 data_set[4]; | ||
127 | int x, y, z; | ||
128 | struct stmpe_touch *ts = data; | ||
129 | |||
130 | /* | ||
131 | * Cancel scheduled polling for release if we have new value | ||
132 | * available. Wait if the polling is already running. | ||
133 | */ | ||
134 | cancel_delayed_work_sync(&ts->work); | ||
135 | |||
136 | /* | ||
137 | * The FIFO sometimes just crashes and stops generating interrupts. This | ||
138 | * appears to be a silicon bug. We still have to clearify this with | ||
139 | * the manufacture. As a workaround we disable the TSC while we are | ||
140 | * collecting data and flush the FIFO after reading | ||
141 | */ | ||
142 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
143 | STMPE_TSC_CTRL_TSC_EN, 0); | ||
144 | |||
145 | stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set); | ||
146 | |||
147 | x = (data_set[0] << 4) | (data_set[1] >> 4); | ||
148 | y = ((data_set[1] & 0xf) << 8) | data_set[2]; | ||
149 | z = data_set[3]; | ||
150 | |||
151 | input_report_abs(ts->idev, ABS_X, x); | ||
152 | input_report_abs(ts->idev, ABS_Y, y); | ||
153 | input_report_abs(ts->idev, ABS_PRESSURE, z); | ||
154 | input_sync(ts->idev); | ||
155 | |||
156 | /* flush the FIFO after we have read out our values. */ | ||
157 | __stmpe_reset_fifo(ts->stmpe); | ||
158 | |||
159 | /* reenable the tsc */ | ||
160 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
161 | STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); | ||
162 | |||
163 | /* start polling for touch_det to detect release */ | ||
164 | schedule_delayed_work(&ts->work, HZ / 50); | ||
165 | |||
166 | return IRQ_HANDLED; | ||
167 | } | ||
168 | |||
169 | static int __devinit stmpe_init_hw(struct stmpe_touch *ts) | ||
170 | { | ||
171 | int ret; | ||
172 | u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; | ||
173 | struct stmpe *stmpe = ts->stmpe; | ||
174 | struct device *dev = ts->dev; | ||
175 | |||
176 | ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC); | ||
177 | if (ret) { | ||
178 | dev_err(dev, "Could not enable clock for ADC and TS\n"); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) | | ||
183 | REF_SEL(ts->ref_sel); | ||
184 | adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff); | ||
185 | |||
186 | ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1, | ||
187 | adc_ctrl1_mask, adc_ctrl1); | ||
188 | if (ret) { | ||
189 | dev_err(dev, "Could not setup ADC\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2, | ||
194 | ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq)); | ||
195 | if (ret) { | ||
196 | dev_err(dev, "Could not setup ADC\n"); | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) | | ||
201 | SETTLING(ts->settling); | ||
202 | tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff); | ||
203 | |||
204 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg); | ||
205 | if (ret) { | ||
206 | dev_err(dev, "Could not config touch\n"); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z, | ||
211 | FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z)); | ||
212 | if (ret) { | ||
213 | dev_err(dev, "Could not config touch\n"); | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE, | ||
218 | I_DRIVE(0xff), I_DRIVE(ts->i_drive)); | ||
219 | if (ret) { | ||
220 | dev_err(dev, "Could not config touch\n"); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | /* set FIFO to 1 for single point reading */ | ||
225 | ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1); | ||
226 | if (ret) { | ||
227 | dev_err(dev, "Could not set FIFO\n"); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL, | ||
232 | OP_MODE(0xff), OP_MODE(OP_MOD_XYZ)); | ||
233 | if (ret) { | ||
234 | dev_err(dev, "Could not set mode\n"); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int stmpe_ts_open(struct input_dev *dev) | ||
242 | { | ||
243 | struct stmpe_touch *ts = input_get_drvdata(dev); | ||
244 | int ret = 0; | ||
245 | |||
246 | ret = __stmpe_reset_fifo(ts->stmpe); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
251 | STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); | ||
252 | } | ||
253 | |||
254 | static void stmpe_ts_close(struct input_dev *dev) | ||
255 | { | ||
256 | struct stmpe_touch *ts = input_get_drvdata(dev); | ||
257 | |||
258 | cancel_delayed_work_sync(&ts->work); | ||
259 | |||
260 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
261 | STMPE_TSC_CTRL_TSC_EN, 0); | ||
262 | } | ||
263 | |||
264 | static int __devinit stmpe_input_probe(struct platform_device *pdev) | ||
265 | { | ||
266 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
267 | struct stmpe_platform_data *pdata = stmpe->pdata; | ||
268 | struct stmpe_touch *ts; | ||
269 | struct input_dev *idev; | ||
270 | struct stmpe_ts_platform_data *ts_pdata = NULL; | ||
271 | int ret = 0; | ||
272 | int ts_irq; | ||
273 | |||
274 | ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
275 | if (ts_irq < 0) | ||
276 | return ts_irq; | ||
277 | |||
278 | ts = kzalloc(sizeof(*ts), GFP_KERNEL); | ||
279 | if (!ts) | ||
280 | goto err_out; | ||
281 | |||
282 | idev = input_allocate_device(); | ||
283 | if (!idev) | ||
284 | goto err_free_ts; | ||
285 | |||
286 | platform_set_drvdata(pdev, ts); | ||
287 | ts->stmpe = stmpe; | ||
288 | ts->idev = idev; | ||
289 | ts->dev = &pdev->dev; | ||
290 | |||
291 | if (pdata) | ||
292 | ts_pdata = pdata->ts; | ||
293 | |||
294 | if (ts_pdata) { | ||
295 | ts->sample_time = ts_pdata->sample_time; | ||
296 | ts->mod_12b = ts_pdata->mod_12b; | ||
297 | ts->ref_sel = ts_pdata->ref_sel; | ||
298 | ts->adc_freq = ts_pdata->adc_freq; | ||
299 | ts->ave_ctrl = ts_pdata->ave_ctrl; | ||
300 | ts->touch_det_delay = ts_pdata->touch_det_delay; | ||
301 | ts->settling = ts_pdata->settling; | ||
302 | ts->fraction_z = ts_pdata->fraction_z; | ||
303 | ts->i_drive = ts_pdata->i_drive; | ||
304 | } | ||
305 | |||
306 | INIT_DELAYED_WORK(&ts->work, stmpe_work); | ||
307 | |||
308 | ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler, | ||
309 | IRQF_ONESHOT, STMPE_TS_NAME, ts); | ||
310 | if (ret) { | ||
311 | dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq); | ||
312 | goto err_free_input; | ||
313 | } | ||
314 | |||
315 | ret = stmpe_init_hw(ts); | ||
316 | if (ret) | ||
317 | goto err_free_irq; | ||
318 | |||
319 | idev->name = STMPE_TS_NAME; | ||
320 | idev->id.bustype = BUS_I2C; | ||
321 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
322 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
323 | |||
324 | idev->open = stmpe_ts_open; | ||
325 | idev->close = stmpe_ts_close; | ||
326 | |||
327 | input_set_drvdata(idev, ts); | ||
328 | |||
329 | input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0); | ||
330 | input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); | ||
331 | input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); | ||
332 | |||
333 | ret = input_register_device(idev); | ||
334 | if (ret) { | ||
335 | dev_err(&pdev->dev, "Could not register input device\n"); | ||
336 | goto err_free_irq; | ||
337 | } | ||
338 | |||
339 | return ret; | ||
340 | |||
341 | err_free_irq: | ||
342 | free_irq(ts_irq, ts); | ||
343 | err_free_input: | ||
344 | input_free_device(idev); | ||
345 | platform_set_drvdata(pdev, NULL); | ||
346 | err_free_ts: | ||
347 | kfree(ts); | ||
348 | err_out: | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static int __devexit stmpe_ts_remove(struct platform_device *pdev) | ||
353 | { | ||
354 | struct stmpe_touch *ts = platform_get_drvdata(pdev); | ||
355 | unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
356 | |||
357 | stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN); | ||
358 | |||
359 | free_irq(ts_irq, ts); | ||
360 | |||
361 | platform_set_drvdata(pdev, NULL); | ||
362 | |||
363 | input_unregister_device(ts->idev); | ||
364 | input_free_device(ts->idev); | ||
365 | |||
366 | kfree(ts); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static struct platform_driver stmpe_ts_driver = { | ||
372 | .driver = { | ||
373 | .name = STMPE_TS_NAME, | ||
374 | .owner = THIS_MODULE, | ||
375 | }, | ||
376 | .probe = stmpe_input_probe, | ||
377 | .remove = __devexit_p(stmpe_ts_remove), | ||
378 | }; | ||
379 | |||
380 | static int __init stmpe_ts_init(void) | ||
381 | { | ||
382 | return platform_driver_register(&stmpe_ts_driver); | ||
383 | } | ||
384 | |||
385 | module_init(stmpe_ts_init); | ||
386 | |||
387 | static void __exit stmpe_ts_exit(void) | ||
388 | { | ||
389 | platform_driver_unregister(&stmpe_ts_driver); | ||
390 | } | ||
391 | |||
392 | module_exit(stmpe_ts_exit); | ||
393 | |||
394 | MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); | ||
395 | MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); | ||
396 | MODULE_LICENSE("GPL"); | ||
397 | MODULE_ALIAS("platform:" STMPE_TS_NAME); | ||
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 2c65a2c5729..07933f3f7e4 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -74,12 +74,12 @@ static struct mfd_cell backlight_devs[] = { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | static struct resource led_resources[] = { | 76 | static struct resource led_resources[] = { |
77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB2B), | 77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B), |
78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB2C), | 78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C), |
79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB2D), | 79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D), |
80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB1B), | 80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B), |
81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB1C), | 81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C), |
82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB1D), | 82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D), |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define PM8606_LED_DEVS(_i) \ | 85 | #define PM8606_LED_DEVS(_i) \ |
@@ -428,52 +428,44 @@ static int __devinit device_gpadc_init(struct pm860x_chip *chip, | |||
428 | { | 428 | { |
429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | 429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ |
430 | : chip->companion; | 430 | : chip->companion; |
431 | int use_gpadc = 0, data, ret; | 431 | int data; |
432 | int ret; | ||
432 | 433 | ||
433 | /* initialize GPADC without activating it */ | 434 | /* initialize GPADC without activating it */ |
434 | 435 | ||
435 | if (pdata && pdata->touch) { | 436 | if (!pdata || !pdata->touch) |
436 | /* set GPADC MISC1 register */ | 437 | return -EINVAL; |
437 | data = 0; | ||
438 | data |= (pdata->touch->gpadc_prebias << 1) | ||
439 | & PM8607_GPADC_PREBIAS_MASK; | ||
440 | data |= (pdata->touch->slot_cycle << 3) | ||
441 | & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
442 | data |= (pdata->touch->off_scale << 5) | ||
443 | & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) | ||
445 | & PM8607_GPADC_SW_CAL_MASK; | ||
446 | if (data) { | ||
447 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
448 | if (ret < 0) | ||
449 | goto out; | ||
450 | } | ||
451 | /* set tsi prebias time */ | ||
452 | if (pdata->touch->tsi_prebias) { | ||
453 | data = pdata->touch->tsi_prebias; | ||
454 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); | ||
455 | if (ret < 0) | ||
456 | goto out; | ||
457 | } | ||
458 | /* set prebias & prechg time of pen detect */ | ||
459 | data = 0; | ||
460 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
461 | data |= (pdata->touch->pen_prechg << 5) | ||
462 | & PM8607_PD_PRECHG_MASK; | ||
463 | if (data) { | ||
464 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
465 | if (ret < 0) | ||
466 | goto out; | ||
467 | } | ||
468 | 438 | ||
469 | use_gpadc = 1; | 439 | /* set GPADC MISC1 register */ |
440 | data = 0; | ||
441 | data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; | ||
442 | data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
443 | data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; | ||
445 | if (data) { | ||
446 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
447 | if (ret < 0) | ||
448 | goto out; | ||
470 | } | 449 | } |
471 | 450 | /* set tsi prebias time */ | |
472 | /* turn on GPADC */ | 451 | if (pdata->touch->tsi_prebias) { |
473 | if (use_gpadc) { | 452 | data = pdata->touch->tsi_prebias; |
474 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | 453 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); |
475 | PM8607_GPADC_EN, PM8607_GPADC_EN); | 454 | if (ret < 0) |
455 | goto out; | ||
476 | } | 456 | } |
457 | /* set prebias & prechg time of pen detect */ | ||
458 | data = 0; | ||
459 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
460 | data |= (pdata->touch->pen_prechg << 5) & 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 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | ||
468 | PM8607_GPADC_EN, PM8607_GPADC_EN); | ||
477 | out: | 469 | out: |
478 | return ret; | 470 | return ret; |
479 | } | 471 | } |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9da0e504bbe..d75909e7cf2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -7,7 +7,16 @@ menuconfig MFD_SUPPORT | |||
7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | default y | 8 | default y |
9 | help | 9 | help |
10 | Configure MFD device drivers. | 10 | Multifunction devices embed several functions (e.g. GPIOs, |
11 | touchscreens, keyboards, current regulators, power management chips, | ||
12 | etc...) in one single integrated circuit. They usually talk to the | ||
13 | main CPU through one or more IRQ lines and low speed data busses (SPI, | ||
14 | I2C, etc..). They appear as one single device to the main system | ||
15 | through the data bus and the MFD framework allows for sub devices | ||
16 | (a.k.a. functions) to appear as discrete platform devices. | ||
17 | MFDs are typically found on embedded platforms. | ||
18 | |||
19 | This option alone does not add any kernel code. | ||
11 | 20 | ||
12 | if MFD_SUPPORT | 21 | if MFD_SUPPORT |
13 | 22 | ||
@@ -177,6 +186,38 @@ config TWL4030_CODEC | |||
177 | select MFD_CORE | 186 | select MFD_CORE |
178 | default n | 187 | default n |
179 | 188 | ||
189 | config TWL6030_PWM | ||
190 | tristate "TWL6030 PWM (Pulse Width Modulator) Support" | ||
191 | depends on TWL4030_CORE | ||
192 | select HAVE_PWM | ||
193 | default n | ||
194 | help | ||
195 | Say yes here if you want support for TWL6030 PWM. | ||
196 | This is used to control charging LED brightness. | ||
197 | |||
198 | config MFD_STMPE | ||
199 | bool "Support STMicroelectronics STMPE" | ||
200 | depends on I2C=y && GENERIC_HARDIRQS | ||
201 | select MFD_CORE | ||
202 | help | ||
203 | Support for the STMPE family of I/O Expanders from | ||
204 | STMicroelectronics. | ||
205 | |||
206 | Currently supported devices are: | ||
207 | |||
208 | STMPE811: GPIO, Touchscreen | ||
209 | STMPE1601: GPIO, Keypad | ||
210 | STMPE2401: GPIO, Keypad | ||
211 | STMPE2403: GPIO, Keypad | ||
212 | |||
213 | This driver provides common support for accessing the device, | ||
214 | additional drivers must be enabled in order to use the functionality | ||
215 | of the device. Currently available sub drivers are: | ||
216 | |||
217 | GPIO: stmpe-gpio | ||
218 | Keypad: stmpe-keypad | ||
219 | Touchscreen: stmpe-ts | ||
220 | |||
180 | config MFD_TC35892 | 221 | config MFD_TC35892 |
181 | bool "Support Toshiba TC35892" | 222 | bool "Support Toshiba TC35892" |
182 | depends on I2C=y && GENERIC_HARDIRQS | 223 | depends on I2C=y && GENERIC_HARDIRQS |
@@ -482,6 +523,28 @@ config MFD_JANZ_CMODIO | |||
482 | host many different types of MODULbus daughterboards, including | 523 | host many different types of MODULbus daughterboards, including |
483 | CAN and GPIO controllers. | 524 | CAN and GPIO controllers. |
484 | 525 | ||
526 | config MFD_JZ4740_ADC | ||
527 | tristate "Support for the JZ4740 SoC ADC core" | ||
528 | select MFD_CORE | ||
529 | depends on MACH_JZ4740 | ||
530 | help | ||
531 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. | ||
532 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. | ||
533 | |||
534 | config MFD_TPS6586X | ||
535 | tristate "TPS6586x Power Management chips" | ||
536 | depends on I2C && GPIOLIB | ||
537 | select MFD_CORE | ||
538 | help | ||
539 | If you say yes here you get support for the TPS6586X series of | ||
540 | Power Management chips. | ||
541 | This driver provides common support for accessing the device, | ||
542 | additional drivers must be enabled in order to use the | ||
543 | functionality of the device. | ||
544 | |||
545 | This driver can also be built as a module. If so, the module | ||
546 | will be called tps6586x. | ||
547 | |||
485 | endif # MFD_SUPPORT | 548 | endif # MFD_SUPPORT |
486 | 549 | ||
487 | menu "Multimedia Capabilities Port drivers" | 550 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index fb503e77dc6..1e48d7e3e88 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o | |||
15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o | 15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o |
16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o | 16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o |
17 | 17 | ||
18 | obj-$(CONFIG_MFD_STMPE) += stmpe.o | ||
18 | obj-$(CONFIG_MFD_TC35892) += tc35892.o | 19 | obj-$(CONFIG_MFD_TC35892) += tc35892.o |
19 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o | 20 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o |
20 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o | 21 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o |
@@ -36,6 +37,7 @@ obj-$(CONFIG_MENELAUS) += menelaus.o | |||
36 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o | 37 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o |
37 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | 38 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o |
38 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | 39 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o |
40 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | ||
39 | 41 | ||
40 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o | 42 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o |
41 | 43 | ||
@@ -71,3 +73,5 @@ obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | |||
71 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o | 73 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o |
72 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o | 74 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o |
73 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o | 75 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o |
76 | obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o | ||
77 | obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o | ||
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index 63d2b727ddb..8440010eb2b 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c | |||
@@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
199 | 199 | ||
200 | err = ab3100_otp_read(otp); | 200 | err = ab3100_otp_read(otp); |
201 | if (err) | 201 | if (err) |
202 | return err; | 202 | goto err_otp_read; |
203 | 203 | ||
204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); | 204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); |
205 | 205 | ||
@@ -208,21 +208,21 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
208 | err = device_create_file(&pdev->dev, | 208 | err = device_create_file(&pdev->dev, |
209 | &ab3100_otp_attrs[i]); | 209 | &ab3100_otp_attrs[i]); |
210 | if (err) | 210 | if (err) |
211 | goto out_no_sysfs; | 211 | goto err_create_file; |
212 | } | 212 | } |
213 | 213 | ||
214 | /* debugfs entries */ | 214 | /* debugfs entries */ |
215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); | 215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); |
216 | if (err) | 216 | if (err) |
217 | goto out_no_debugfs; | 217 | goto err_init_debugfs; |
218 | 218 | ||
219 | return 0; | 219 | return 0; |
220 | 220 | ||
221 | out_no_sysfs: | 221 | err_init_debugfs: |
222 | for (i = 0; i < ARRAY_SIZE(ab3100_otp_attrs); i++) | 222 | err_create_file: |
223 | device_remove_file(&pdev->dev, | 223 | while (--i >= 0) |
224 | &ab3100_otp_attrs[i]); | 224 | device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); |
225 | out_no_debugfs: | 225 | err_otp_read: |
226 | kfree(otp); | 226 | kfree(otp); |
227 | return err; | 227 | return err; |
228 | } | 228 | } |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index f54ab62e7bc..8a98739e6d9 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c | |||
@@ -589,16 +589,16 @@ static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | |||
589 | } | 589 | } |
590 | 590 | ||
591 | /* | 591 | /* |
592 | * The exported register access functionality. | 592 | * The register access functionality. |
593 | */ | 593 | */ |
594 | int ab3550_get_chip_id(struct device *dev) | 594 | static int ab3550_get_chip_id(struct device *dev) |
595 | { | 595 | { |
596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); | 596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); |
597 | return (int)ab->chip_id; | 597 | return (int)ab->chip_id; |
598 | } | 598 | } |
599 | 599 | ||
600 | int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | 600 | static int ab3550_mask_and_set_register_interruptible(struct device *dev, |
601 | u8 reg, u8 bitmask, u8 bitvalues) | 601 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) |
602 | { | 602 | { |
603 | struct ab3550 *ab; | 603 | struct ab3550 *ab; |
604 | struct platform_device *pdev = to_platform_device(dev); | 604 | struct platform_device *pdev = to_platform_device(dev); |
@@ -612,15 +612,15 @@ int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | |||
612 | bitmask, bitvalues); | 612 | bitmask, bitvalues); |
613 | } | 613 | } |
614 | 614 | ||
615 | int ab3550_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | 615 | static int ab3550_set_register_interruptible(struct device *dev, u8 bank, |
616 | u8 value) | 616 | u8 reg, u8 value) |
617 | { | 617 | { |
618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | 618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, |
619 | value); | 619 | value); |
620 | } | 620 | } |
621 | 621 | ||
622 | int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | 622 | static int ab3550_get_register_interruptible(struct device *dev, u8 bank, |
623 | u8 *value) | 623 | u8 reg, u8 *value) |
624 | { | 624 | { |
625 | struct ab3550 *ab; | 625 | struct ab3550 *ab; |
626 | struct platform_device *pdev = to_platform_device(dev); | 626 | struct platform_device *pdev = to_platform_device(dev); |
@@ -633,7 +633,7 @@ int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | |||
633 | return get_register_interruptible(ab, bank, reg, value); | 633 | return get_register_interruptible(ab, bank, reg, value); |
634 | } | 634 | } |
635 | 635 | ||
636 | int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | 636 | static int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, |
637 | u8 first_reg, u8 *regvals, u8 numregs) | 637 | u8 first_reg, u8 *regvals, u8 numregs) |
638 | { | 638 | { |
639 | struct ab3550 *ab; | 639 | struct ab3550 *ab; |
@@ -649,7 +649,8 @@ int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | |||
649 | numregs); | 649 | numregs); |
650 | } | 650 | } |
651 | 651 | ||
652 | int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | 652 | static int ab3550_event_registers_startup_state_get(struct device *dev, |
653 | u8 *event) | ||
653 | { | 654 | { |
654 | struct ab3550 *ab; | 655 | struct ab3550 *ab; |
655 | 656 | ||
@@ -661,7 +662,7 @@ int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | |||
661 | return 0; | 662 | return 0; |
662 | } | 663 | } |
663 | 664 | ||
664 | int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) | 665 | static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) |
665 | { | 666 | { |
666 | struct ab3550 *ab; | 667 | struct ab3550 *ab; |
667 | struct ab3550_platform_data *plf_data; | 668 | struct ab3550_platform_data *plf_data; |
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c index b81d4f768ef..e1c8b62b086 100644 --- a/drivers/mfd/ab8500-spi.c +++ b/drivers/mfd/ab8500-spi.c | |||
@@ -68,7 +68,12 @@ static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr) | |||
68 | 68 | ||
69 | ret = spi_sync(spi, &msg); | 69 | ret = spi_sync(spi, &msg); |
70 | if (!ret) | 70 | if (!ret) |
71 | ret = ab8500->rx_buf[0]; | 71 | /* |
72 | * Only the 8 lowermost bytes are | ||
73 | * defined with value, the rest may | ||
74 | * vary depending on chip/board noise. | ||
75 | */ | ||
76 | ret = ab8500->rx_buf[0] & 0xFFU; | ||
72 | 77 | ||
73 | return ret; | 78 | return ret; |
74 | } | 79 | } |
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 3b3b97ec32a..f12720dbe12 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c | |||
@@ -36,7 +36,7 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops) | |||
36 | struct abx500_device_entry *dev_entry; | 36 | struct abx500_device_entry *dev_entry; |
37 | 37 | ||
38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); | 38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); |
39 | if (IS_ERR(dev_entry)) { | 39 | if (!dev_entry) { |
40 | dev_err(dev, "register_ops kzalloc failed"); | 40 | dev_err(dev, "register_ops kzalloc failed"); |
41 | return -ENOMEM; | 41 | return -ENOMEM; |
42 | } | 42 | } |
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 3e75f02e477..33c923d215c 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c | |||
@@ -94,7 +94,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
95 | if (!res) { | 95 | if (!res) { |
96 | dev_err(&pdev->dev, "no DMA resource\n"); | 96 | dev_err(&pdev->dev, "no DMA resource\n"); |
97 | return -ENXIO; | 97 | ret = -ENXIO; |
98 | goto fail4; | ||
98 | } | 99 | } |
99 | 100 | ||
100 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; | 101 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; |
@@ -104,7 +105,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
104 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 105 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
105 | if (!res) { | 106 | if (!res) { |
106 | dev_err(&pdev->dev, "no DMA resource\n"); | 107 | dev_err(&pdev->dev, "no DMA resource\n"); |
107 | return -ENXIO; | 108 | ret = -ENXIO; |
109 | goto fail4; | ||
108 | } | 110 | } |
109 | 111 | ||
110 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; | 112 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; |
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 9ed630799ac..36a166bcdb0 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/mfd/core.h> | 22 | #include <linux/mfd/core.h> |
22 | 23 | ||
23 | #include <linux/mfd/janz.h> | 24 | #include <linux/mfd/janz.h> |
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c new file mode 100644 index 00000000000..3ad492cb6c4 --- /dev/null +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -0,0 +1,394 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 SoC ADC driver | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | * This driver synchronizes access to the JZ4740 ADC core between the | ||
15 | * JZ4740 battery and hwmon drivers. | ||
16 | */ | ||
17 | |||
18 | #include <linux/err.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | |||
27 | #include <linux/clk.h> | ||
28 | #include <linux/mfd/core.h> | ||
29 | |||
30 | #include <linux/jz4740-adc.h> | ||
31 | |||
32 | |||
33 | #define JZ_REG_ADC_ENABLE 0x00 | ||
34 | #define JZ_REG_ADC_CFG 0x04 | ||
35 | #define JZ_REG_ADC_CTRL 0x08 | ||
36 | #define JZ_REG_ADC_STATUS 0x0c | ||
37 | |||
38 | #define JZ_REG_ADC_TOUCHSCREEN_BASE 0x10 | ||
39 | #define JZ_REG_ADC_BATTERY_BASE 0x1c | ||
40 | #define JZ_REG_ADC_HWMON_BASE 0x20 | ||
41 | |||
42 | #define JZ_ADC_ENABLE_TOUCH BIT(2) | ||
43 | #define JZ_ADC_ENABLE_BATTERY BIT(1) | ||
44 | #define JZ_ADC_ENABLE_ADCIN BIT(0) | ||
45 | |||
46 | enum { | ||
47 | JZ_ADC_IRQ_ADCIN = 0, | ||
48 | JZ_ADC_IRQ_BATTERY, | ||
49 | JZ_ADC_IRQ_TOUCH, | ||
50 | JZ_ADC_IRQ_PENUP, | ||
51 | JZ_ADC_IRQ_PENDOWN, | ||
52 | }; | ||
53 | |||
54 | struct jz4740_adc { | ||
55 | struct resource *mem; | ||
56 | void __iomem *base; | ||
57 | |||
58 | int irq; | ||
59 | int irq_base; | ||
60 | |||
61 | struct clk *clk; | ||
62 | atomic_t clk_ref; | ||
63 | |||
64 | spinlock_t lock; | ||
65 | }; | ||
66 | |||
67 | static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq, | ||
68 | bool masked) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | uint8_t val; | ||
72 | |||
73 | irq -= adc->irq_base; | ||
74 | |||
75 | spin_lock_irqsave(&adc->lock, flags); | ||
76 | |||
77 | val = readb(adc->base + JZ_REG_ADC_CTRL); | ||
78 | if (masked) | ||
79 | val |= BIT(irq); | ||
80 | else | ||
81 | val &= ~BIT(irq); | ||
82 | writeb(val, adc->base + JZ_REG_ADC_CTRL); | ||
83 | |||
84 | spin_unlock_irqrestore(&adc->lock, flags); | ||
85 | } | ||
86 | |||
87 | static void jz4740_adc_irq_mask(unsigned int irq) | ||
88 | { | ||
89 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
90 | jz4740_adc_irq_set_masked(adc, irq, true); | ||
91 | } | ||
92 | |||
93 | static void jz4740_adc_irq_unmask(unsigned int irq) | ||
94 | { | ||
95 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
96 | jz4740_adc_irq_set_masked(adc, irq, false); | ||
97 | } | ||
98 | |||
99 | static void jz4740_adc_irq_ack(unsigned int irq) | ||
100 | { | ||
101 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
102 | |||
103 | irq -= adc->irq_base; | ||
104 | writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS); | ||
105 | } | ||
106 | |||
107 | static struct irq_chip jz4740_adc_irq_chip = { | ||
108 | .name = "jz4740-adc", | ||
109 | .mask = jz4740_adc_irq_mask, | ||
110 | .unmask = jz4740_adc_irq_unmask, | ||
111 | .ack = jz4740_adc_irq_ack, | ||
112 | }; | ||
113 | |||
114 | static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
115 | { | ||
116 | struct jz4740_adc *adc = get_irq_desc_data(desc); | ||
117 | uint8_t status; | ||
118 | unsigned int i; | ||
119 | |||
120 | status = readb(adc->base + JZ_REG_ADC_STATUS); | ||
121 | |||
122 | for (i = 0; i < 5; ++i) { | ||
123 | if (status & BIT(i)) | ||
124 | generic_handle_irq(adc->irq_base + i); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | |||
129 | /* Refcounting for the ADC clock is done in here instead of in the clock | ||
130 | * framework, because it is the only clock which is shared between multiple | ||
131 | * devices and thus is the only clock which needs refcounting */ | ||
132 | static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc) | ||
133 | { | ||
134 | if (atomic_inc_return(&adc->clk_ref) == 1) | ||
135 | clk_enable(adc->clk); | ||
136 | } | ||
137 | |||
138 | static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc) | ||
139 | { | ||
140 | if (atomic_dec_return(&adc->clk_ref) == 0) | ||
141 | clk_disable(adc->clk); | ||
142 | } | ||
143 | |||
144 | static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine, | ||
145 | bool enabled) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | uint8_t val; | ||
149 | |||
150 | spin_lock_irqsave(&adc->lock, flags); | ||
151 | |||
152 | val = readb(adc->base + JZ_REG_ADC_ENABLE); | ||
153 | if (enabled) | ||
154 | val |= BIT(engine); | ||
155 | else | ||
156 | val &= BIT(engine); | ||
157 | writeb(val, adc->base + JZ_REG_ADC_ENABLE); | ||
158 | |||
159 | spin_unlock_irqrestore(&adc->lock, flags); | ||
160 | } | ||
161 | |||
162 | static int jz4740_adc_cell_enable(struct platform_device *pdev) | ||
163 | { | ||
164 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
165 | |||
166 | jz4740_adc_clk_enable(adc); | ||
167 | jz4740_adc_set_enabled(adc, pdev->id, true); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int jz4740_adc_cell_disable(struct platform_device *pdev) | ||
173 | { | ||
174 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
175 | |||
176 | jz4740_adc_set_enabled(adc, pdev->id, false); | ||
177 | jz4740_adc_clk_disable(adc); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int jz4740_adc_set_config(struct device *dev, uint32_t mask, uint32_t val) | ||
183 | { | ||
184 | struct jz4740_adc *adc = dev_get_drvdata(dev); | ||
185 | unsigned long flags; | ||
186 | uint32_t cfg; | ||
187 | |||
188 | if (!adc) | ||
189 | return -ENODEV; | ||
190 | |||
191 | spin_lock_irqsave(&adc->lock, flags); | ||
192 | |||
193 | cfg = readl(adc->base + JZ_REG_ADC_CFG); | ||
194 | |||
195 | cfg &= ~mask; | ||
196 | cfg |= val; | ||
197 | |||
198 | writel(cfg, adc->base + JZ_REG_ADC_CFG); | ||
199 | |||
200 | spin_unlock_irqrestore(&adc->lock, flags); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(jz4740_adc_set_config); | ||
205 | |||
206 | static struct resource jz4740_hwmon_resources[] = { | ||
207 | { | ||
208 | .start = JZ_ADC_IRQ_ADCIN, | ||
209 | .flags = IORESOURCE_IRQ, | ||
210 | }, | ||
211 | { | ||
212 | .start = JZ_REG_ADC_HWMON_BASE, | ||
213 | .end = JZ_REG_ADC_HWMON_BASE + 3, | ||
214 | .flags = IORESOURCE_MEM, | ||
215 | }, | ||
216 | }; | ||
217 | |||
218 | static struct resource jz4740_battery_resources[] = { | ||
219 | { | ||
220 | .start = JZ_ADC_IRQ_BATTERY, | ||
221 | .flags = IORESOURCE_IRQ, | ||
222 | }, | ||
223 | { | ||
224 | .start = JZ_REG_ADC_BATTERY_BASE, | ||
225 | .end = JZ_REG_ADC_BATTERY_BASE + 3, | ||
226 | .flags = IORESOURCE_MEM, | ||
227 | }, | ||
228 | }; | ||
229 | |||
230 | const struct mfd_cell jz4740_adc_cells[] = { | ||
231 | { | ||
232 | .id = 0, | ||
233 | .name = "jz4740-hwmon", | ||
234 | .num_resources = ARRAY_SIZE(jz4740_hwmon_resources), | ||
235 | .resources = jz4740_hwmon_resources, | ||
236 | .platform_data = (void *)&jz4740_adc_cells[0], | ||
237 | .data_size = sizeof(struct mfd_cell), | ||
238 | |||
239 | .enable = jz4740_adc_cell_enable, | ||
240 | .disable = jz4740_adc_cell_disable, | ||
241 | }, | ||
242 | { | ||
243 | .id = 1, | ||
244 | .name = "jz4740-battery", | ||
245 | .num_resources = ARRAY_SIZE(jz4740_battery_resources), | ||
246 | .resources = jz4740_battery_resources, | ||
247 | .platform_data = (void *)&jz4740_adc_cells[1], | ||
248 | .data_size = sizeof(struct mfd_cell), | ||
249 | |||
250 | .enable = jz4740_adc_cell_enable, | ||
251 | .disable = jz4740_adc_cell_disable, | ||
252 | }, | ||
253 | }; | ||
254 | |||
255 | static int __devinit jz4740_adc_probe(struct platform_device *pdev) | ||
256 | { | ||
257 | int ret; | ||
258 | struct jz4740_adc *adc; | ||
259 | struct resource *mem_base; | ||
260 | int irq; | ||
261 | |||
262 | adc = kmalloc(sizeof(*adc), GFP_KERNEL); | ||
263 | if (!adc) { | ||
264 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | adc->irq = platform_get_irq(pdev, 0); | ||
269 | if (adc->irq < 0) { | ||
270 | ret = adc->irq; | ||
271 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); | ||
272 | goto err_free; | ||
273 | } | ||
274 | |||
275 | adc->irq_base = platform_get_irq(pdev, 1); | ||
276 | if (adc->irq_base < 0) { | ||
277 | ret = adc->irq_base; | ||
278 | dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret); | ||
279 | goto err_free; | ||
280 | } | ||
281 | |||
282 | mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
283 | if (!mem_base) { | ||
284 | ret = -ENOENT; | ||
285 | dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); | ||
286 | goto err_free; | ||
287 | } | ||
288 | |||
289 | /* Only request the shared registers for the MFD driver */ | ||
290 | adc->mem = request_mem_region(mem_base->start, JZ_REG_ADC_STATUS, | ||
291 | pdev->name); | ||
292 | if (!adc->mem) { | ||
293 | ret = -EBUSY; | ||
294 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
295 | goto err_free; | ||
296 | } | ||
297 | |||
298 | adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem)); | ||
299 | if (!adc->base) { | ||
300 | ret = -EBUSY; | ||
301 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
302 | goto err_release_mem_region; | ||
303 | } | ||
304 | |||
305 | adc->clk = clk_get(&pdev->dev, "adc"); | ||
306 | if (IS_ERR(adc->clk)) { | ||
307 | ret = PTR_ERR(adc->clk); | ||
308 | dev_err(&pdev->dev, "Failed to get clock: %d\n", ret); | ||
309 | goto err_iounmap; | ||
310 | } | ||
311 | |||
312 | spin_lock_init(&adc->lock); | ||
313 | atomic_set(&adc->clk_ref, 0); | ||
314 | |||
315 | platform_set_drvdata(pdev, adc); | ||
316 | |||
317 | for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) { | ||
318 | set_irq_chip_data(irq, adc); | ||
319 | set_irq_chip_and_handler(irq, &jz4740_adc_irq_chip, | ||
320 | handle_level_irq); | ||
321 | } | ||
322 | |||
323 | set_irq_data(adc->irq, adc); | ||
324 | set_irq_chained_handler(adc->irq, jz4740_adc_irq_demux); | ||
325 | |||
326 | writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); | ||
327 | writeb(0xff, adc->base + JZ_REG_ADC_CTRL); | ||
328 | |||
329 | ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, | ||
330 | ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base); | ||
331 | if (ret < 0) | ||
332 | goto err_clk_put; | ||
333 | |||
334 | return 0; | ||
335 | |||
336 | err_clk_put: | ||
337 | clk_put(adc->clk); | ||
338 | err_iounmap: | ||
339 | platform_set_drvdata(pdev, NULL); | ||
340 | iounmap(adc->base); | ||
341 | err_release_mem_region: | ||
342 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
343 | err_free: | ||
344 | kfree(adc); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit jz4740_adc_remove(struct platform_device *pdev) | ||
350 | { | ||
351 | struct jz4740_adc *adc = platform_get_drvdata(pdev); | ||
352 | |||
353 | mfd_remove_devices(&pdev->dev); | ||
354 | |||
355 | set_irq_data(adc->irq, NULL); | ||
356 | set_irq_chained_handler(adc->irq, NULL); | ||
357 | |||
358 | iounmap(adc->base); | ||
359 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
360 | |||
361 | clk_put(adc->clk); | ||
362 | |||
363 | platform_set_drvdata(pdev, NULL); | ||
364 | |||
365 | kfree(adc); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | struct platform_driver jz4740_adc_driver = { | ||
371 | .probe = jz4740_adc_probe, | ||
372 | .remove = __devexit_p(jz4740_adc_remove), | ||
373 | .driver = { | ||
374 | .name = "jz4740-adc", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | }; | ||
378 | |||
379 | static int __init jz4740_adc_init(void) | ||
380 | { | ||
381 | return platform_driver_register(&jz4740_adc_driver); | ||
382 | } | ||
383 | module_init(jz4740_adc_init); | ||
384 | |||
385 | static void __exit jz4740_adc_exit(void) | ||
386 | { | ||
387 | platform_driver_unregister(&jz4740_adc_driver); | ||
388 | } | ||
389 | module_exit(jz4740_adc_exit); | ||
390 | |||
391 | MODULE_DESCRIPTION("JZ4740 SoC ADC driver"); | ||
392 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_ALIAS("platform:jz4740-adc"); | ||
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index f621bcea3d0..04028a9ee08 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -90,6 +90,24 @@ static struct mfd_cell rtc_devs[] = { | |||
90 | }, | 90 | }, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static struct resource onkey_resources[] = { | ||
94 | { | ||
95 | .name = "max8925-onkey", | ||
96 | .start = MAX8925_IRQ_GPM_SW_3SEC, | ||
97 | .end = MAX8925_IRQ_GPM_SW_3SEC, | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static struct mfd_cell onkey_devs[] = { | ||
103 | { | ||
104 | .name = "max8925-onkey", | ||
105 | .num_resources = 1, | ||
106 | .resources = &onkey_resources[0], | ||
107 | .id = -1, | ||
108 | }, | ||
109 | }; | ||
110 | |||
93 | #define MAX8925_REG_RESOURCE(_start, _end) \ | 111 | #define MAX8925_REG_RESOURCE(_start, _end) \ |
94 | { \ | 112 | { \ |
95 | .start = MAX8925_##_start, \ | 113 | .start = MAX8925_##_start, \ |
@@ -596,6 +614,15 @@ int __devinit max8925_device_init(struct max8925_chip *chip, | |||
596 | dev_err(chip->dev, "Failed to add rtc subdev\n"); | 614 | dev_err(chip->dev, "Failed to add rtc subdev\n"); |
597 | goto out; | 615 | goto out; |
598 | } | 616 | } |
617 | |||
618 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
619 | ARRAY_SIZE(onkey_devs), | ||
620 | &onkey_resources[0], 0); | ||
621 | if (ret < 0) { | ||
622 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
623 | goto out_dev; | ||
624 | } | ||
625 | |||
599 | if (pdata && pdata->regulator[0]) { | 626 | if (pdata && pdata->regulator[0]) { |
600 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], | 627 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], |
601 | ARRAY_SIZE(regulator_devs), | 628 | ARRAY_SIZE(regulator_devs), |
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index fecf38a4f02..6df34989c1f 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
@@ -11,9 +11,31 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/interrupt.h> | ||
14 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
15 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
16 | #include <linux/mfd/mc13783-private.h> | 19 | #include <linux/mfd/mc13783.h> |
20 | |||
21 | struct mc13783 { | ||
22 | struct spi_device *spidev; | ||
23 | struct mutex lock; | ||
24 | int irq; | ||
25 | int flags; | ||
26 | |||
27 | irq_handler_t irqhandler[MC13783_NUM_IRQ]; | ||
28 | void *irqdata[MC13783_NUM_IRQ]; | ||
29 | |||
30 | /* XXX these should go as platformdata to the regulator subdevice */ | ||
31 | struct mc13783_regulator_init_data *regulators; | ||
32 | int num_regulators; | ||
33 | }; | ||
34 | |||
35 | #define MC13783_REG_REVISION 7 | ||
36 | #define MC13783_REG_ADC_0 43 | ||
37 | #define MC13783_REG_ADC_1 44 | ||
38 | #define MC13783_REG_ADC_2 45 | ||
17 | 39 | ||
18 | #define MC13783_IRQSTAT0 0 | 40 | #define MC13783_IRQSTAT0 0 |
19 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) | 41 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) |
@@ -226,6 +248,12 @@ int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | |||
226 | } | 248 | } |
227 | EXPORT_SYMBOL(mc13783_reg_rmw); | 249 | EXPORT_SYMBOL(mc13783_reg_rmw); |
228 | 250 | ||
251 | int mc13783_get_flags(struct mc13783 *mc13783) | ||
252 | { | ||
253 | return mc13783->flags; | ||
254 | } | ||
255 | EXPORT_SYMBOL(mc13783_get_flags); | ||
256 | |||
229 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) | 257 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) |
230 | { | 258 | { |
231 | int ret; | 259 | int ret; |
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index a3fb4bcb988..4ba85bbdb4c 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c | |||
@@ -128,6 +128,39 @@ | |||
128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ | 128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ |
129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ | 129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ |
130 | 130 | ||
131 | /* VCORE_CTRL1 register */ | ||
132 | #define VCORE_CTRL1_BYP_COMP (1 << 5) | ||
133 | #define VCORE_CTRL1_HW_NSW (1 << 7) | ||
134 | |||
135 | /* GPIO_CTRL register */ | ||
136 | #define GPIO_CTRL_SLOTSELEN (1 << 5) | ||
137 | #define GPIO_CTRL_SLPCTLEN (1 << 6) | ||
138 | #define GPIO1_DIR_INPUT (1 << 0) | ||
139 | #define GPIO2_DIR_INPUT (1 << 1) | ||
140 | #define GPIO3_DIR_INPUT (1 << 2) | ||
141 | |||
142 | /* MCT_CTRL1 register */ | ||
143 | #define MCT_CTRL1_S1_CMD_OD (1 << 2) | ||
144 | #define MCT_CTRL1_S2_CMD_OD (1 << 3) | ||
145 | |||
146 | /* MCT_CTRL2 register */ | ||
147 | #define MCT_CTRL2_VS2_SEL_D0 (1 << 0) | ||
148 | #define MCT_CTRL2_VS2_SEL_D1 (1 << 1) | ||
149 | #define MCT_CTRL2_S1CD_BUFEN (1 << 4) | ||
150 | #define MCT_CTRL2_S2CD_BUFEN (1 << 5) | ||
151 | #define MCT_CTRL2_S1CD_DBEN (1 << 6) | ||
152 | #define MCT_CTRL2_S2CD_BEN (1 << 7) | ||
153 | |||
154 | /* MCT_CTRL3 register */ | ||
155 | #define MCT_CTRL3_SLOT1_EN (1 << 0) | ||
156 | #define MCT_CTRL3_SLOT2_EN (1 << 1) | ||
157 | #define MCT_CTRL3_S1_AUTO_EN (1 << 2) | ||
158 | #define MCT_CTRL3_S2_AUTO_EN (1 << 3) | ||
159 | |||
160 | /* MCT_PIN_ST register */ | ||
161 | #define MCT_PIN_ST_S1_CD_ST (1 << 0) | ||
162 | #define MCT_PIN_ST_S2_CD_ST (1 << 1) | ||
163 | |||
131 | static void menelaus_work(struct work_struct *_menelaus); | 164 | static void menelaus_work(struct work_struct *_menelaus); |
132 | 165 | ||
133 | struct menelaus_chip { | 166 | struct menelaus_chip { |
@@ -249,10 +282,10 @@ static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw) | |||
249 | return; | 282 | return; |
250 | 283 | ||
251 | if (!(reg & 0x1)) | 284 | if (!(reg & 0x1)) |
252 | card_mask |= (1 << 0); | 285 | card_mask |= MCT_PIN_ST_S1_CD_ST; |
253 | 286 | ||
254 | if (!(reg & 0x2)) | 287 | if (!(reg & 0x2)) |
255 | card_mask |= (1 << 1); | 288 | card_mask |= MCT_PIN_ST_S2_CD_ST; |
256 | 289 | ||
257 | if (menelaus_hw->mmc_callback) | 290 | if (menelaus_hw->mmc_callback) |
258 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, | 291 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, |
@@ -277,14 +310,14 @@ int menelaus_set_mmc_opendrain(int slot, int enable) | |||
277 | val = ret; | 310 | val = ret; |
278 | if (slot == 1) { | 311 | if (slot == 1) { |
279 | if (enable) | 312 | if (enable) |
280 | val |= 1 << 2; | 313 | val |= MCT_CTRL1_S1_CMD_OD; |
281 | else | 314 | else |
282 | val &= ~(1 << 2); | 315 | val &= ~MCT_CTRL1_S1_CMD_OD; |
283 | } else { | 316 | } else { |
284 | if (enable) | 317 | if (enable) |
285 | val |= 1 << 3; | 318 | val |= MCT_CTRL1_S2_CMD_OD; |
286 | else | 319 | else |
287 | val &= ~(1 << 3); | 320 | val &= ~MCT_CTRL1_S2_CMD_OD; |
288 | } | 321 | } |
289 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); | 322 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); |
290 | mutex_unlock(&the_menelaus->lock); | 323 | mutex_unlock(&the_menelaus->lock); |
@@ -301,11 +334,11 @@ int menelaus_set_slot_sel(int enable) | |||
301 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 334 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
302 | if (ret < 0) | 335 | if (ret < 0) |
303 | goto out; | 336 | goto out; |
304 | ret |= 0x02; | 337 | ret |= GPIO2_DIR_INPUT; |
305 | if (enable) | 338 | if (enable) |
306 | ret |= 1 << 5; | 339 | ret |= GPIO_CTRL_SLOTSELEN; |
307 | else | 340 | else |
308 | ret &= ~(1 << 5); | 341 | ret &= ~GPIO_CTRL_SLOTSELEN; |
309 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); | 342 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); |
310 | out: | 343 | out: |
311 | mutex_unlock(&the_menelaus->lock); | 344 | mutex_unlock(&the_menelaus->lock); |
@@ -330,14 +363,14 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
330 | val = ret; | 363 | val = ret; |
331 | if (slot == 1) { | 364 | if (slot == 1) { |
332 | if (cd_en) | 365 | if (cd_en) |
333 | val |= (1 << 4) | (1 << 6); | 366 | val |= MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN; |
334 | else | 367 | else |
335 | val &= ~((1 << 4) | (1 << 6)); | 368 | val &= ~(MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN); |
336 | } else { | 369 | } else { |
337 | if (cd_en) | 370 | if (cd_en) |
338 | val |= (1 << 5) | (1 << 7); | 371 | val |= MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN; |
339 | else | 372 | else |
340 | val &= ~((1 << 5) | (1 << 7)); | 373 | val &= ~(MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN); |
341 | } | 374 | } |
342 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); | 375 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); |
343 | if (ret < 0) | 376 | if (ret < 0) |
@@ -349,25 +382,25 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
349 | val = ret; | 382 | val = ret; |
350 | if (slot == 1) { | 383 | if (slot == 1) { |
351 | if (enable) | 384 | if (enable) |
352 | val |= 1 << 0; | 385 | val |= MCT_CTRL3_SLOT1_EN; |
353 | else | 386 | else |
354 | val &= ~(1 << 0); | 387 | val &= ~MCT_CTRL3_SLOT1_EN; |
355 | } else { | 388 | } else { |
356 | int b; | 389 | int b; |
357 | 390 | ||
358 | if (enable) | 391 | if (enable) |
359 | ret |= 1 << 1; | 392 | val |= MCT_CTRL3_SLOT2_EN; |
360 | else | 393 | else |
361 | ret &= ~(1 << 1); | 394 | val &= ~MCT_CTRL3_SLOT2_EN; |
362 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); | 395 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); |
363 | b &= ~0x03; | 396 | b &= ~(MCT_CTRL2_VS2_SEL_D0 | MCT_CTRL2_VS2_SEL_D1); |
364 | b |= power; | 397 | b |= power; |
365 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); | 398 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); |
366 | if (ret < 0) | 399 | if (ret < 0) |
367 | goto out; | 400 | goto out; |
368 | } | 401 | } |
369 | /* Disable autonomous shutdown */ | 402 | /* Disable autonomous shutdown */ |
370 | val &= ~(0x03 << 2); | 403 | val &= ~(MCT_CTRL3_S1_AUTO_EN | MCT_CTRL3_S2_AUTO_EN); |
371 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); | 404 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); |
372 | out: | 405 | out: |
373 | mutex_unlock(&the_menelaus->lock); | 406 | mutex_unlock(&the_menelaus->lock); |
@@ -552,7 +585,7 @@ int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV) | |||
552 | if (!the_menelaus->vcore_hw_mode) { | 585 | if (!the_menelaus->vcore_hw_mode) { |
553 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); | 586 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); |
554 | /* HW mode, turn OFF byte comparator */ | 587 | /* HW mode, turn OFF byte comparator */ |
555 | val |= ((1 << 7) | (1 << 5)); | 588 | val |= (VCORE_CTRL1_HW_NSW | VCORE_CTRL1_BYP_COMP); |
556 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); | 589 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); |
557 | the_menelaus->vcore_hw_mode = 1; | 590 | the_menelaus->vcore_hw_mode = 1; |
558 | } | 591 | } |
@@ -749,7 +782,7 @@ int menelaus_set_regulator_sleep(int enable, u32 val) | |||
749 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 782 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
750 | if (ret < 0) | 783 | if (ret < 0) |
751 | goto out; | 784 | goto out; |
752 | t = ((1 << 6) | 0x04); | 785 | t = (GPIO_CTRL_SLPCTLEN | GPIO3_DIR_INPUT); |
753 | if (enable) | 786 | if (enable) |
754 | ret |= t; | 787 | ret |= t; |
755 | else | 788 | else |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 7dd76bceaae..1823a57b7d8 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -70,7 +70,9 @@ static int mfd_add_device(struct device *parent, int id, | |||
70 | goto fail_res; | 70 | goto fail_res; |
71 | } | 71 | } |
72 | 72 | ||
73 | platform_device_add_resources(pdev, res, cell->num_resources); | 73 | ret = platform_device_add_resources(pdev, res, cell->num_resources); |
74 | if (ret) | ||
75 | goto fail_res; | ||
74 | 76 | ||
75 | ret = platform_device_add(pdev); | 77 | ret = platform_device_add(pdev); |
76 | if (ret) | 78 | if (ret) |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c new file mode 100644 index 00000000000..0754c5e9199 --- /dev/null +++ b/drivers/mfd/stmpe.c | |||
@@ -0,0 +1,985 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mfd/core.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | #include "stmpe.h" | ||
17 | |||
18 | static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
19 | { | ||
20 | return stmpe->variant->enable(stmpe, blocks, true); | ||
21 | } | ||
22 | |||
23 | static int __stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
24 | { | ||
25 | return stmpe->variant->enable(stmpe, blocks, false); | ||
26 | } | ||
27 | |||
28 | static int __stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
29 | { | ||
30 | int ret; | ||
31 | |||
32 | ret = i2c_smbus_read_byte_data(stmpe->i2c, reg); | ||
33 | if (ret < 0) | ||
34 | dev_err(stmpe->dev, "failed to read reg %#x: %d\n", | ||
35 | reg, ret); | ||
36 | |||
37 | dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret); | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
43 | { | ||
44 | int ret; | ||
45 | |||
46 | dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val); | ||
47 | |||
48 | ret = i2c_smbus_write_byte_data(stmpe->i2c, reg, val); | ||
49 | if (ret < 0) | ||
50 | dev_err(stmpe->dev, "failed to write reg %#x: %d\n", | ||
51 | reg, ret); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | static int __stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
57 | { | ||
58 | int ret; | ||
59 | |||
60 | ret = __stmpe_reg_read(stmpe, reg); | ||
61 | if (ret < 0) | ||
62 | return ret; | ||
63 | |||
64 | ret &= ~mask; | ||
65 | ret |= val; | ||
66 | |||
67 | return __stmpe_reg_write(stmpe, reg, ret); | ||
68 | } | ||
69 | |||
70 | static int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, | ||
71 | u8 *values) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = i2c_smbus_read_i2c_block_data(stmpe->i2c, reg, length, values); | ||
76 | if (ret < 0) | ||
77 | dev_err(stmpe->dev, "failed to read regs %#x: %d\n", | ||
78 | reg, ret); | ||
79 | |||
80 | dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret); | ||
81 | stmpe_dump_bytes("stmpe rd: ", values, length); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
87 | const u8 *values) | ||
88 | { | ||
89 | int ret; | ||
90 | |||
91 | dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length); | ||
92 | stmpe_dump_bytes("stmpe wr: ", values, length); | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(stmpe->i2c, reg, length, | ||
95 | values); | ||
96 | if (ret < 0) | ||
97 | dev_err(stmpe->dev, "failed to write regs %#x: %d\n", | ||
98 | reg, ret); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * stmpe_enable - enable blocks on an STMPE device | ||
105 | * @stmpe: Device to work on | ||
106 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
107 | */ | ||
108 | int stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
109 | { | ||
110 | int ret; | ||
111 | |||
112 | mutex_lock(&stmpe->lock); | ||
113 | ret = __stmpe_enable(stmpe, blocks); | ||
114 | mutex_unlock(&stmpe->lock); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | EXPORT_SYMBOL_GPL(stmpe_enable); | ||
119 | |||
120 | /** | ||
121 | * stmpe_disable - disable blocks on an STMPE device | ||
122 | * @stmpe: Device to work on | ||
123 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
124 | */ | ||
125 | int stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | mutex_lock(&stmpe->lock); | ||
130 | ret = __stmpe_disable(stmpe, blocks); | ||
131 | mutex_unlock(&stmpe->lock); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(stmpe_disable); | ||
136 | |||
137 | /** | ||
138 | * stmpe_reg_read() - read a single STMPE register | ||
139 | * @stmpe: Device to read from | ||
140 | * @reg: Register to read | ||
141 | */ | ||
142 | int stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | mutex_lock(&stmpe->lock); | ||
147 | ret = __stmpe_reg_read(stmpe, reg); | ||
148 | mutex_unlock(&stmpe->lock); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | EXPORT_SYMBOL_GPL(stmpe_reg_read); | ||
153 | |||
154 | /** | ||
155 | * stmpe_reg_write() - write a single STMPE register | ||
156 | * @stmpe: Device to write to | ||
157 | * @reg: Register to write | ||
158 | * @val: Value to write | ||
159 | */ | ||
160 | int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | mutex_lock(&stmpe->lock); | ||
165 | ret = __stmpe_reg_write(stmpe, reg, val); | ||
166 | mutex_unlock(&stmpe->lock); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(stmpe_reg_write); | ||
171 | |||
172 | /** | ||
173 | * stmpe_set_bits() - set the value of a bitfield in a STMPE register | ||
174 | * @stmpe: Device to write to | ||
175 | * @reg: Register to write | ||
176 | * @mask: Mask of bits to set | ||
177 | * @val: Value to set | ||
178 | */ | ||
179 | int stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
180 | { | ||
181 | int ret; | ||
182 | |||
183 | mutex_lock(&stmpe->lock); | ||
184 | ret = __stmpe_set_bits(stmpe, reg, mask, val); | ||
185 | mutex_unlock(&stmpe->lock); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(stmpe_set_bits); | ||
190 | |||
191 | /** | ||
192 | * stmpe_block_read() - read multiple STMPE registers | ||
193 | * @stmpe: Device to read from | ||
194 | * @reg: First register | ||
195 | * @length: Number of registers | ||
196 | * @values: Buffer to write to | ||
197 | */ | ||
198 | int stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values) | ||
199 | { | ||
200 | int ret; | ||
201 | |||
202 | mutex_lock(&stmpe->lock); | ||
203 | ret = __stmpe_block_read(stmpe, reg, length, values); | ||
204 | mutex_unlock(&stmpe->lock); | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(stmpe_block_read); | ||
209 | |||
210 | /** | ||
211 | * stmpe_block_write() - write multiple STMPE registers | ||
212 | * @stmpe: Device to write to | ||
213 | * @reg: First register | ||
214 | * @length: Number of registers | ||
215 | * @values: Values to write | ||
216 | */ | ||
217 | int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
218 | const u8 *values) | ||
219 | { | ||
220 | int ret; | ||
221 | |||
222 | mutex_lock(&stmpe->lock); | ||
223 | ret = __stmpe_block_write(stmpe, reg, length, values); | ||
224 | mutex_unlock(&stmpe->lock); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(stmpe_block_write); | ||
229 | |||
230 | /** | ||
231 | * stmpe_set_altfunc: set the alternate function for STMPE pins | ||
232 | * @stmpe: Device to configure | ||
233 | * @pins: Bitmask of pins to affect | ||
234 | * @block: block to enable alternate functions for | ||
235 | * | ||
236 | * @pins is assumed to have a bit set for each of the bits whose alternate | ||
237 | * function is to be changed, numbered according to the GPIOXY numbers. | ||
238 | * | ||
239 | * If the GPIO module is not enabled, this function automatically enables it in | ||
240 | * order to perform the change. | ||
241 | */ | ||
242 | int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block) | ||
243 | { | ||
244 | struct stmpe_variant_info *variant = stmpe->variant; | ||
245 | u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; | ||
246 | int af_bits = variant->af_bits; | ||
247 | int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); | ||
248 | int afperreg = 8 / af_bits; | ||
249 | int mask = (1 << af_bits) - 1; | ||
250 | u8 regs[numregs]; | ||
251 | int af; | ||
252 | int ret; | ||
253 | |||
254 | mutex_lock(&stmpe->lock); | ||
255 | |||
256 | ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
257 | if (ret < 0) | ||
258 | goto out; | ||
259 | |||
260 | ret = __stmpe_block_read(stmpe, regaddr, numregs, regs); | ||
261 | if (ret < 0) | ||
262 | goto out; | ||
263 | |||
264 | af = variant->get_altfunc(stmpe, block); | ||
265 | |||
266 | while (pins) { | ||
267 | int pin = __ffs(pins); | ||
268 | int regoffset = numregs - (pin / afperreg) - 1; | ||
269 | int pos = (pin % afperreg) * (8 / afperreg); | ||
270 | |||
271 | regs[regoffset] &= ~(mask << pos); | ||
272 | regs[regoffset] |= af << pos; | ||
273 | |||
274 | pins &= ~(1 << pin); | ||
275 | } | ||
276 | |||
277 | ret = __stmpe_block_write(stmpe, regaddr, numregs, regs); | ||
278 | |||
279 | out: | ||
280 | mutex_unlock(&stmpe->lock); | ||
281 | return ret; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(stmpe_set_altfunc); | ||
284 | |||
285 | /* | ||
286 | * GPIO (all variants) | ||
287 | */ | ||
288 | |||
289 | static struct resource stmpe_gpio_resources[] = { | ||
290 | /* Start and end filled dynamically */ | ||
291 | { | ||
292 | .flags = IORESOURCE_IRQ, | ||
293 | }, | ||
294 | }; | ||
295 | |||
296 | static struct mfd_cell stmpe_gpio_cell = { | ||
297 | .name = "stmpe-gpio", | ||
298 | .resources = stmpe_gpio_resources, | ||
299 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), | ||
300 | }; | ||
301 | |||
302 | /* | ||
303 | * Keypad (1601, 2401, 2403) | ||
304 | */ | ||
305 | |||
306 | static struct resource stmpe_keypad_resources[] = { | ||
307 | { | ||
308 | .name = "KEYPAD", | ||
309 | .start = 0, | ||
310 | .end = 0, | ||
311 | .flags = IORESOURCE_IRQ, | ||
312 | }, | ||
313 | { | ||
314 | .name = "KEYPAD_OVER", | ||
315 | .start = 1, | ||
316 | .end = 1, | ||
317 | .flags = IORESOURCE_IRQ, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static struct mfd_cell stmpe_keypad_cell = { | ||
322 | .name = "stmpe-keypad", | ||
323 | .resources = stmpe_keypad_resources, | ||
324 | .num_resources = ARRAY_SIZE(stmpe_keypad_resources), | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | * Touchscreen (STMPE811) | ||
329 | */ | ||
330 | |||
331 | static struct resource stmpe_ts_resources[] = { | ||
332 | { | ||
333 | .name = "TOUCH_DET", | ||
334 | .start = 0, | ||
335 | .end = 0, | ||
336 | .flags = IORESOURCE_IRQ, | ||
337 | }, | ||
338 | { | ||
339 | .name = "FIFO_TH", | ||
340 | .start = 1, | ||
341 | .end = 1, | ||
342 | .flags = IORESOURCE_IRQ, | ||
343 | }, | ||
344 | }; | ||
345 | |||
346 | static struct mfd_cell stmpe_ts_cell = { | ||
347 | .name = "stmpe-ts", | ||
348 | .resources = stmpe_ts_resources, | ||
349 | .num_resources = ARRAY_SIZE(stmpe_ts_resources), | ||
350 | }; | ||
351 | |||
352 | /* | ||
353 | * STMPE811 | ||
354 | */ | ||
355 | |||
356 | static const u8 stmpe811_regs[] = { | ||
357 | [STMPE_IDX_CHIP_ID] = STMPE811_REG_CHIP_ID, | ||
358 | [STMPE_IDX_ICR_LSB] = STMPE811_REG_INT_CTRL, | ||
359 | [STMPE_IDX_IER_LSB] = STMPE811_REG_INT_EN, | ||
360 | [STMPE_IDX_ISR_MSB] = STMPE811_REG_INT_STA, | ||
361 | [STMPE_IDX_GPMR_LSB] = STMPE811_REG_GPIO_MP_STA, | ||
362 | [STMPE_IDX_GPSR_LSB] = STMPE811_REG_GPIO_SET_PIN, | ||
363 | [STMPE_IDX_GPCR_LSB] = STMPE811_REG_GPIO_CLR_PIN, | ||
364 | [STMPE_IDX_GPDR_LSB] = STMPE811_REG_GPIO_DIR, | ||
365 | [STMPE_IDX_GPRER_LSB] = STMPE811_REG_GPIO_RE, | ||
366 | [STMPE_IDX_GPFER_LSB] = STMPE811_REG_GPIO_FE, | ||
367 | [STMPE_IDX_GPAFR_U_MSB] = STMPE811_REG_GPIO_AF, | ||
368 | [STMPE_IDX_IEGPIOR_LSB] = STMPE811_REG_GPIO_INT_EN, | ||
369 | [STMPE_IDX_ISGPIOR_MSB] = STMPE811_REG_GPIO_INT_STA, | ||
370 | [STMPE_IDX_GPEDR_MSB] = STMPE811_REG_GPIO_ED, | ||
371 | }; | ||
372 | |||
373 | static struct stmpe_variant_block stmpe811_blocks[] = { | ||
374 | { | ||
375 | .cell = &stmpe_gpio_cell, | ||
376 | .irq = STMPE811_IRQ_GPIOC, | ||
377 | .block = STMPE_BLOCK_GPIO, | ||
378 | }, | ||
379 | { | ||
380 | .cell = &stmpe_ts_cell, | ||
381 | .irq = STMPE811_IRQ_TOUCH_DET, | ||
382 | .block = STMPE_BLOCK_TOUCHSCREEN, | ||
383 | }, | ||
384 | }; | ||
385 | |||
386 | static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, | ||
387 | bool enable) | ||
388 | { | ||
389 | unsigned int mask = 0; | ||
390 | |||
391 | if (blocks & STMPE_BLOCK_GPIO) | ||
392 | mask |= STMPE811_SYS_CTRL2_GPIO_OFF; | ||
393 | |||
394 | if (blocks & STMPE_BLOCK_ADC) | ||
395 | mask |= STMPE811_SYS_CTRL2_ADC_OFF; | ||
396 | |||
397 | if (blocks & STMPE_BLOCK_TOUCHSCREEN) | ||
398 | mask |= STMPE811_SYS_CTRL2_TSC_OFF; | ||
399 | |||
400 | return __stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask, | ||
401 | enable ? 0 : mask); | ||
402 | } | ||
403 | |||
404 | static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
405 | { | ||
406 | /* 0 for touchscreen, 1 for GPIO */ | ||
407 | return block != STMPE_BLOCK_TOUCHSCREEN; | ||
408 | } | ||
409 | |||
410 | static struct stmpe_variant_info stmpe811 = { | ||
411 | .name = "stmpe811", | ||
412 | .id_val = 0x0811, | ||
413 | .id_mask = 0xffff, | ||
414 | .num_gpios = 8, | ||
415 | .af_bits = 1, | ||
416 | .regs = stmpe811_regs, | ||
417 | .blocks = stmpe811_blocks, | ||
418 | .num_blocks = ARRAY_SIZE(stmpe811_blocks), | ||
419 | .num_irqs = STMPE811_NR_INTERNAL_IRQS, | ||
420 | .enable = stmpe811_enable, | ||
421 | .get_altfunc = stmpe811_get_altfunc, | ||
422 | }; | ||
423 | |||
424 | /* | ||
425 | * STMPE1601 | ||
426 | */ | ||
427 | |||
428 | static const u8 stmpe1601_regs[] = { | ||
429 | [STMPE_IDX_CHIP_ID] = STMPE1601_REG_CHIP_ID, | ||
430 | [STMPE_IDX_ICR_LSB] = STMPE1601_REG_ICR_LSB, | ||
431 | [STMPE_IDX_IER_LSB] = STMPE1601_REG_IER_LSB, | ||
432 | [STMPE_IDX_ISR_MSB] = STMPE1601_REG_ISR_MSB, | ||
433 | [STMPE_IDX_GPMR_LSB] = STMPE1601_REG_GPIO_MP_LSB, | ||
434 | [STMPE_IDX_GPSR_LSB] = STMPE1601_REG_GPIO_SET_LSB, | ||
435 | [STMPE_IDX_GPCR_LSB] = STMPE1601_REG_GPIO_CLR_LSB, | ||
436 | [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, | ||
437 | [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, | ||
438 | [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, | ||
439 | [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, | ||
440 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, | ||
441 | [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, | ||
442 | [STMPE_IDX_GPEDR_MSB] = STMPE1601_REG_GPIO_ED_MSB, | ||
443 | }; | ||
444 | |||
445 | static struct stmpe_variant_block stmpe1601_blocks[] = { | ||
446 | { | ||
447 | .cell = &stmpe_gpio_cell, | ||
448 | .irq = STMPE24XX_IRQ_GPIOC, | ||
449 | .block = STMPE_BLOCK_GPIO, | ||
450 | }, | ||
451 | { | ||
452 | .cell = &stmpe_keypad_cell, | ||
453 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
454 | .block = STMPE_BLOCK_KEYPAD, | ||
455 | }, | ||
456 | }; | ||
457 | |||
458 | /* supported autosleep timeout delay (in msecs) */ | ||
459 | static const int stmpe_autosleep_delay[] = { | ||
460 | 4, 16, 32, 64, 128, 256, 512, 1024, | ||
461 | }; | ||
462 | |||
463 | static int stmpe_round_timeout(int timeout) | ||
464 | { | ||
465 | int i; | ||
466 | |||
467 | for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) { | ||
468 | if (stmpe_autosleep_delay[i] >= timeout) | ||
469 | return i; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * requests for delays longer than supported should not return the | ||
474 | * longest supported delay | ||
475 | */ | ||
476 | return -EINVAL; | ||
477 | } | ||
478 | |||
479 | static int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | if (!stmpe->variant->enable_autosleep) | ||
484 | return -ENOSYS; | ||
485 | |||
486 | mutex_lock(&stmpe->lock); | ||
487 | ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout); | ||
488 | mutex_unlock(&stmpe->lock); | ||
489 | |||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * Both stmpe 1601/2403 support same layout for autosleep | ||
495 | */ | ||
496 | static int stmpe1601_autosleep(struct stmpe *stmpe, | ||
497 | int autosleep_timeout) | ||
498 | { | ||
499 | int ret, timeout; | ||
500 | |||
501 | /* choose the best available timeout */ | ||
502 | timeout = stmpe_round_timeout(autosleep_timeout); | ||
503 | if (timeout < 0) { | ||
504 | dev_err(stmpe->dev, "invalid timeout\n"); | ||
505 | return timeout; | ||
506 | } | ||
507 | |||
508 | ret = __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
509 | STMPE1601_AUTOSLEEP_TIMEOUT_MASK, | ||
510 | timeout); | ||
511 | if (ret < 0) | ||
512 | return ret; | ||
513 | |||
514 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
515 | STPME1601_AUTOSLEEP_ENABLE, | ||
516 | STPME1601_AUTOSLEEP_ENABLE); | ||
517 | } | ||
518 | |||
519 | static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks, | ||
520 | bool enable) | ||
521 | { | ||
522 | unsigned int mask = 0; | ||
523 | |||
524 | if (blocks & STMPE_BLOCK_GPIO) | ||
525 | mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO; | ||
526 | |||
527 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
528 | mask |= STMPE1601_SYS_CTRL_ENABLE_KPC; | ||
529 | |||
530 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask, | ||
531 | enable ? mask : 0); | ||
532 | } | ||
533 | |||
534 | static int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
535 | { | ||
536 | switch (block) { | ||
537 | case STMPE_BLOCK_PWM: | ||
538 | return 2; | ||
539 | |||
540 | case STMPE_BLOCK_KEYPAD: | ||
541 | return 1; | ||
542 | |||
543 | case STMPE_BLOCK_GPIO: | ||
544 | default: | ||
545 | return 0; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static struct stmpe_variant_info stmpe1601 = { | ||
550 | .name = "stmpe1601", | ||
551 | .id_val = 0x0210, | ||
552 | .id_mask = 0xfff0, /* at least 0x0210 and 0x0212 */ | ||
553 | .num_gpios = 16, | ||
554 | .af_bits = 2, | ||
555 | .regs = stmpe1601_regs, | ||
556 | .blocks = stmpe1601_blocks, | ||
557 | .num_blocks = ARRAY_SIZE(stmpe1601_blocks), | ||
558 | .num_irqs = STMPE1601_NR_INTERNAL_IRQS, | ||
559 | .enable = stmpe1601_enable, | ||
560 | .get_altfunc = stmpe1601_get_altfunc, | ||
561 | .enable_autosleep = stmpe1601_autosleep, | ||
562 | }; | ||
563 | |||
564 | /* | ||
565 | * STMPE24XX | ||
566 | */ | ||
567 | |||
568 | static const u8 stmpe24xx_regs[] = { | ||
569 | [STMPE_IDX_CHIP_ID] = STMPE24XX_REG_CHIP_ID, | ||
570 | [STMPE_IDX_ICR_LSB] = STMPE24XX_REG_ICR_LSB, | ||
571 | [STMPE_IDX_IER_LSB] = STMPE24XX_REG_IER_LSB, | ||
572 | [STMPE_IDX_ISR_MSB] = STMPE24XX_REG_ISR_MSB, | ||
573 | [STMPE_IDX_GPMR_LSB] = STMPE24XX_REG_GPMR_LSB, | ||
574 | [STMPE_IDX_GPSR_LSB] = STMPE24XX_REG_GPSR_LSB, | ||
575 | [STMPE_IDX_GPCR_LSB] = STMPE24XX_REG_GPCR_LSB, | ||
576 | [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, | ||
577 | [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, | ||
578 | [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, | ||
579 | [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, | ||
580 | [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, | ||
581 | [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, | ||
582 | [STMPE_IDX_GPEDR_MSB] = STMPE24XX_REG_GPEDR_MSB, | ||
583 | }; | ||
584 | |||
585 | static struct stmpe_variant_block stmpe24xx_blocks[] = { | ||
586 | { | ||
587 | .cell = &stmpe_gpio_cell, | ||
588 | .irq = STMPE24XX_IRQ_GPIOC, | ||
589 | .block = STMPE_BLOCK_GPIO, | ||
590 | }, | ||
591 | { | ||
592 | .cell = &stmpe_keypad_cell, | ||
593 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
594 | .block = STMPE_BLOCK_KEYPAD, | ||
595 | }, | ||
596 | }; | ||
597 | |||
598 | static int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks, | ||
599 | bool enable) | ||
600 | { | ||
601 | unsigned int mask = 0; | ||
602 | |||
603 | if (blocks & STMPE_BLOCK_GPIO) | ||
604 | mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO; | ||
605 | |||
606 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
607 | mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC; | ||
608 | |||
609 | return __stmpe_set_bits(stmpe, STMPE24XX_REG_SYS_CTRL, mask, | ||
610 | enable ? mask : 0); | ||
611 | } | ||
612 | |||
613 | static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
614 | { | ||
615 | switch (block) { | ||
616 | case STMPE_BLOCK_ROTATOR: | ||
617 | return 2; | ||
618 | |||
619 | case STMPE_BLOCK_KEYPAD: | ||
620 | return 1; | ||
621 | |||
622 | case STMPE_BLOCK_GPIO: | ||
623 | default: | ||
624 | return 0; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | static struct stmpe_variant_info stmpe2401 = { | ||
629 | .name = "stmpe2401", | ||
630 | .id_val = 0x0101, | ||
631 | .id_mask = 0xffff, | ||
632 | .num_gpios = 24, | ||
633 | .af_bits = 2, | ||
634 | .regs = stmpe24xx_regs, | ||
635 | .blocks = stmpe24xx_blocks, | ||
636 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
637 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
638 | .enable = stmpe24xx_enable, | ||
639 | .get_altfunc = stmpe24xx_get_altfunc, | ||
640 | }; | ||
641 | |||
642 | static struct stmpe_variant_info stmpe2403 = { | ||
643 | .name = "stmpe2403", | ||
644 | .id_val = 0x0120, | ||
645 | .id_mask = 0xffff, | ||
646 | .num_gpios = 24, | ||
647 | .af_bits = 2, | ||
648 | .regs = stmpe24xx_regs, | ||
649 | .blocks = stmpe24xx_blocks, | ||
650 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
651 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
652 | .enable = stmpe24xx_enable, | ||
653 | .get_altfunc = stmpe24xx_get_altfunc, | ||
654 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ | ||
655 | }; | ||
656 | |||
657 | static struct stmpe_variant_info *stmpe_variant_info[] = { | ||
658 | [STMPE811] = &stmpe811, | ||
659 | [STMPE1601] = &stmpe1601, | ||
660 | [STMPE2401] = &stmpe2401, | ||
661 | [STMPE2403] = &stmpe2403, | ||
662 | }; | ||
663 | |||
664 | static irqreturn_t stmpe_irq(int irq, void *data) | ||
665 | { | ||
666 | struct stmpe *stmpe = data; | ||
667 | struct stmpe_variant_info *variant = stmpe->variant; | ||
668 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
669 | u8 israddr = stmpe->regs[STMPE_IDX_ISR_MSB]; | ||
670 | u8 isr[num]; | ||
671 | int ret; | ||
672 | int i; | ||
673 | |||
674 | ret = stmpe_block_read(stmpe, israddr, num, isr); | ||
675 | if (ret < 0) | ||
676 | return IRQ_NONE; | ||
677 | |||
678 | for (i = 0; i < num; i++) { | ||
679 | int bank = num - i - 1; | ||
680 | u8 status = isr[i]; | ||
681 | u8 clear; | ||
682 | |||
683 | status &= stmpe->ier[bank]; | ||
684 | if (!status) | ||
685 | continue; | ||
686 | |||
687 | clear = status; | ||
688 | while (status) { | ||
689 | int bit = __ffs(status); | ||
690 | int line = bank * 8 + bit; | ||
691 | |||
692 | handle_nested_irq(stmpe->irq_base + line); | ||
693 | status &= ~(1 << bit); | ||
694 | } | ||
695 | |||
696 | stmpe_reg_write(stmpe, israddr + i, clear); | ||
697 | } | ||
698 | |||
699 | return IRQ_HANDLED; | ||
700 | } | ||
701 | |||
702 | static void stmpe_irq_lock(unsigned int irq) | ||
703 | { | ||
704 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
705 | |||
706 | mutex_lock(&stmpe->irq_lock); | ||
707 | } | ||
708 | |||
709 | static void stmpe_irq_sync_unlock(unsigned int irq) | ||
710 | { | ||
711 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
712 | struct stmpe_variant_info *variant = stmpe->variant; | ||
713 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
714 | int i; | ||
715 | |||
716 | for (i = 0; i < num; i++) { | ||
717 | u8 new = stmpe->ier[i]; | ||
718 | u8 old = stmpe->oldier[i]; | ||
719 | |||
720 | if (new == old) | ||
721 | continue; | ||
722 | |||
723 | stmpe->oldier[i] = new; | ||
724 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB] - i, new); | ||
725 | } | ||
726 | |||
727 | mutex_unlock(&stmpe->irq_lock); | ||
728 | } | ||
729 | |||
730 | static void stmpe_irq_mask(unsigned int irq) | ||
731 | { | ||
732 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
733 | int offset = irq - stmpe->irq_base; | ||
734 | int regoffset = offset / 8; | ||
735 | int mask = 1 << (offset % 8); | ||
736 | |||
737 | stmpe->ier[regoffset] &= ~mask; | ||
738 | } | ||
739 | |||
740 | static void stmpe_irq_unmask(unsigned int irq) | ||
741 | { | ||
742 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
743 | int offset = irq - stmpe->irq_base; | ||
744 | int regoffset = offset / 8; | ||
745 | int mask = 1 << (offset % 8); | ||
746 | |||
747 | stmpe->ier[regoffset] |= mask; | ||
748 | } | ||
749 | |||
750 | static struct irq_chip stmpe_irq_chip = { | ||
751 | .name = "stmpe", | ||
752 | .bus_lock = stmpe_irq_lock, | ||
753 | .bus_sync_unlock = stmpe_irq_sync_unlock, | ||
754 | .mask = stmpe_irq_mask, | ||
755 | .unmask = stmpe_irq_unmask, | ||
756 | }; | ||
757 | |||
758 | static int __devinit stmpe_irq_init(struct stmpe *stmpe) | ||
759 | { | ||
760 | int num_irqs = stmpe->variant->num_irqs; | ||
761 | int base = stmpe->irq_base; | ||
762 | int irq; | ||
763 | |||
764 | for (irq = base; irq < base + num_irqs; irq++) { | ||
765 | set_irq_chip_data(irq, stmpe); | ||
766 | set_irq_chip_and_handler(irq, &stmpe_irq_chip, | ||
767 | handle_edge_irq); | ||
768 | set_irq_nested_thread(irq, 1); | ||
769 | #ifdef CONFIG_ARM | ||
770 | set_irq_flags(irq, IRQF_VALID); | ||
771 | #else | ||
772 | set_irq_noprobe(irq); | ||
773 | #endif | ||
774 | } | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static void stmpe_irq_remove(struct stmpe *stmpe) | ||
780 | { | ||
781 | int num_irqs = stmpe->variant->num_irqs; | ||
782 | int base = stmpe->irq_base; | ||
783 | int irq; | ||
784 | |||
785 | for (irq = base; irq < base + num_irqs; irq++) { | ||
786 | #ifdef CONFIG_ARM | ||
787 | set_irq_flags(irq, 0); | ||
788 | #endif | ||
789 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
790 | set_irq_chip_data(irq, NULL); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | static int __devinit stmpe_chip_init(struct stmpe *stmpe) | ||
795 | { | ||
796 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; | ||
797 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; | ||
798 | struct stmpe_variant_info *variant = stmpe->variant; | ||
799 | u8 icr = STMPE_ICR_LSB_GIM; | ||
800 | unsigned int id; | ||
801 | u8 data[2]; | ||
802 | int ret; | ||
803 | |||
804 | ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID], | ||
805 | ARRAY_SIZE(data), data); | ||
806 | if (ret < 0) | ||
807 | return ret; | ||
808 | |||
809 | id = (data[0] << 8) | data[1]; | ||
810 | if ((id & variant->id_mask) != variant->id_val) { | ||
811 | dev_err(stmpe->dev, "unknown chip id: %#x\n", id); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id); | ||
816 | |||
817 | /* Disable all modules -- subdrivers should enable what they need. */ | ||
818 | ret = stmpe_disable(stmpe, ~0); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
822 | if (irq_trigger == IRQF_TRIGGER_FALLING || | ||
823 | irq_trigger == IRQF_TRIGGER_RISING) | ||
824 | icr |= STMPE_ICR_LSB_EDGE; | ||
825 | |||
826 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
827 | irq_trigger == IRQF_TRIGGER_HIGH) | ||
828 | icr |= STMPE_ICR_LSB_HIGH; | ||
829 | |||
830 | if (stmpe->pdata->irq_invert_polarity) | ||
831 | icr ^= STMPE_ICR_LSB_HIGH; | ||
832 | |||
833 | if (stmpe->pdata->autosleep) { | ||
834 | ret = stmpe_autosleep(stmpe, autosleep_timeout); | ||
835 | if (ret) | ||
836 | return ret; | ||
837 | } | ||
838 | |||
839 | return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); | ||
840 | } | ||
841 | |||
842 | static int __devinit stmpe_add_device(struct stmpe *stmpe, | ||
843 | struct mfd_cell *cell, int irq) | ||
844 | { | ||
845 | return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, | ||
846 | NULL, stmpe->irq_base + irq); | ||
847 | } | ||
848 | |||
849 | static int __devinit stmpe_devices_init(struct stmpe *stmpe) | ||
850 | { | ||
851 | struct stmpe_variant_info *variant = stmpe->variant; | ||
852 | unsigned int platform_blocks = stmpe->pdata->blocks; | ||
853 | int ret = -EINVAL; | ||
854 | int i; | ||
855 | |||
856 | for (i = 0; i < variant->num_blocks; i++) { | ||
857 | struct stmpe_variant_block *block = &variant->blocks[i]; | ||
858 | |||
859 | if (!(platform_blocks & block->block)) | ||
860 | continue; | ||
861 | |||
862 | platform_blocks &= ~block->block; | ||
863 | ret = stmpe_add_device(stmpe, block->cell, block->irq); | ||
864 | if (ret) | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | if (platform_blocks) | ||
869 | dev_warn(stmpe->dev, | ||
870 | "platform wants blocks (%#x) not present on variant", | ||
871 | platform_blocks); | ||
872 | |||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | static int __devinit stmpe_probe(struct i2c_client *i2c, | ||
877 | const struct i2c_device_id *id) | ||
878 | { | ||
879 | struct stmpe_platform_data *pdata = i2c->dev.platform_data; | ||
880 | struct stmpe *stmpe; | ||
881 | int ret; | ||
882 | |||
883 | if (!pdata) | ||
884 | return -EINVAL; | ||
885 | |||
886 | stmpe = kzalloc(sizeof(struct stmpe), GFP_KERNEL); | ||
887 | if (!stmpe) | ||
888 | return -ENOMEM; | ||
889 | |||
890 | mutex_init(&stmpe->irq_lock); | ||
891 | mutex_init(&stmpe->lock); | ||
892 | |||
893 | stmpe->dev = &i2c->dev; | ||
894 | stmpe->i2c = i2c; | ||
895 | |||
896 | stmpe->pdata = pdata; | ||
897 | stmpe->irq_base = pdata->irq_base; | ||
898 | |||
899 | stmpe->partnum = id->driver_data; | ||
900 | stmpe->variant = stmpe_variant_info[stmpe->partnum]; | ||
901 | stmpe->regs = stmpe->variant->regs; | ||
902 | stmpe->num_gpios = stmpe->variant->num_gpios; | ||
903 | |||
904 | i2c_set_clientdata(i2c, stmpe); | ||
905 | |||
906 | ret = stmpe_chip_init(stmpe); | ||
907 | if (ret) | ||
908 | goto out_free; | ||
909 | |||
910 | ret = stmpe_irq_init(stmpe); | ||
911 | if (ret) | ||
912 | goto out_free; | ||
913 | |||
914 | ret = request_threaded_irq(stmpe->i2c->irq, NULL, stmpe_irq, | ||
915 | pdata->irq_trigger | IRQF_ONESHOT, | ||
916 | "stmpe", stmpe); | ||
917 | if (ret) { | ||
918 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret); | ||
919 | goto out_removeirq; | ||
920 | } | ||
921 | |||
922 | ret = stmpe_devices_init(stmpe); | ||
923 | if (ret) { | ||
924 | dev_err(stmpe->dev, "failed to add children\n"); | ||
925 | goto out_removedevs; | ||
926 | } | ||
927 | |||
928 | return 0; | ||
929 | |||
930 | out_removedevs: | ||
931 | mfd_remove_devices(stmpe->dev); | ||
932 | free_irq(stmpe->i2c->irq, stmpe); | ||
933 | out_removeirq: | ||
934 | stmpe_irq_remove(stmpe); | ||
935 | out_free: | ||
936 | kfree(stmpe); | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int __devexit stmpe_remove(struct i2c_client *client) | ||
941 | { | ||
942 | struct stmpe *stmpe = i2c_get_clientdata(client); | ||
943 | |||
944 | mfd_remove_devices(stmpe->dev); | ||
945 | |||
946 | free_irq(stmpe->i2c->irq, stmpe); | ||
947 | stmpe_irq_remove(stmpe); | ||
948 | |||
949 | kfree(stmpe); | ||
950 | |||
951 | return 0; | ||
952 | } | ||
953 | |||
954 | static const struct i2c_device_id stmpe_id[] = { | ||
955 | { "stmpe811", STMPE811 }, | ||
956 | { "stmpe1601", STMPE1601 }, | ||
957 | { "stmpe2401", STMPE2401 }, | ||
958 | { "stmpe2403", STMPE2403 }, | ||
959 | { } | ||
960 | }; | ||
961 | MODULE_DEVICE_TABLE(i2c, stmpe_id); | ||
962 | |||
963 | static struct i2c_driver stmpe_driver = { | ||
964 | .driver.name = "stmpe", | ||
965 | .driver.owner = THIS_MODULE, | ||
966 | .probe = stmpe_probe, | ||
967 | .remove = __devexit_p(stmpe_remove), | ||
968 | .id_table = stmpe_id, | ||
969 | }; | ||
970 | |||
971 | static int __init stmpe_init(void) | ||
972 | { | ||
973 | return i2c_add_driver(&stmpe_driver); | ||
974 | } | ||
975 | subsys_initcall(stmpe_init); | ||
976 | |||
977 | static void __exit stmpe_exit(void) | ||
978 | { | ||
979 | i2c_del_driver(&stmpe_driver); | ||
980 | } | ||
981 | module_exit(stmpe_exit); | ||
982 | |||
983 | MODULE_LICENSE("GPL v2"); | ||
984 | MODULE_DESCRIPTION("STMPE MFD core driver"); | ||
985 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h new file mode 100644 index 00000000000..0dbdc4e8cd7 --- /dev/null +++ b/drivers/mfd/stmpe.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #ifndef __STMPE_H | ||
9 | #define __STMPE_H | ||
10 | |||
11 | #ifdef STMPE_DUMP_BYTES | ||
12 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
13 | size_t len) | ||
14 | { | ||
15 | print_hex_dump_bytes(str, DUMP_PREFIX_OFFSET, buf, len); | ||
16 | } | ||
17 | #else | ||
18 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
19 | size_t len) | ||
20 | { | ||
21 | } | ||
22 | #endif | ||
23 | |||
24 | /** | ||
25 | * struct stmpe_variant_block - information about block | ||
26 | * @cell: base mfd cell | ||
27 | * @irq: interrupt number to be added to each IORESOURCE_IRQ | ||
28 | * in the cell | ||
29 | * @block: block id; used for identification with platform data and for | ||
30 | * enable and altfunc callbacks | ||
31 | */ | ||
32 | struct stmpe_variant_block { | ||
33 | struct mfd_cell *cell; | ||
34 | int irq; | ||
35 | enum stmpe_block block; | ||
36 | }; | ||
37 | |||
38 | /** | ||
39 | * struct stmpe_variant_info - variant-specific information | ||
40 | * @name: part name | ||
41 | * @id_val: content of CHIPID register | ||
42 | * @id_mask: bits valid in CHIPID register for comparison with id_val | ||
43 | * @num_gpios: number of GPIOS | ||
44 | * @af_bits: number of bits used to specify the alternate function | ||
45 | * @blocks: list of blocks present on this device | ||
46 | * @num_blocks: number of blocks present on this device | ||
47 | * @num_irqs: number of internal IRQs available on this device | ||
48 | * @enable: callback to enable the specified blocks. | ||
49 | * Called with the I/O lock held. | ||
50 | * @get_altfunc: callback to get the alternate function number for the | ||
51 | * specific block | ||
52 | * @enable_autosleep: callback to configure autosleep with specified timeout | ||
53 | */ | ||
54 | struct stmpe_variant_info { | ||
55 | const char *name; | ||
56 | u16 id_val; | ||
57 | u16 id_mask; | ||
58 | int num_gpios; | ||
59 | int af_bits; | ||
60 | const u8 *regs; | ||
61 | struct stmpe_variant_block *blocks; | ||
62 | int num_blocks; | ||
63 | int num_irqs; | ||
64 | int (*enable)(struct stmpe *stmpe, unsigned int blocks, bool enable); | ||
65 | int (*get_altfunc)(struct stmpe *stmpe, enum stmpe_block block); | ||
66 | int (*enable_autosleep)(struct stmpe *stmpe, int autosleep_timeout); | ||
67 | }; | ||
68 | |||
69 | #define STMPE_ICR_LSB_HIGH (1 << 2) | ||
70 | #define STMPE_ICR_LSB_EDGE (1 << 1) | ||
71 | #define STMPE_ICR_LSB_GIM (1 << 0) | ||
72 | |||
73 | /* | ||
74 | * STMPE811 | ||
75 | */ | ||
76 | |||
77 | #define STMPE811_IRQ_TOUCH_DET 0 | ||
78 | #define STMPE811_IRQ_FIFO_TH 1 | ||
79 | #define STMPE811_IRQ_FIFO_OFLOW 2 | ||
80 | #define STMPE811_IRQ_FIFO_FULL 3 | ||
81 | #define STMPE811_IRQ_FIFO_EMPTY 4 | ||
82 | #define STMPE811_IRQ_TEMP_SENS 5 | ||
83 | #define STMPE811_IRQ_ADC 6 | ||
84 | #define STMPE811_IRQ_GPIOC 7 | ||
85 | #define STMPE811_NR_INTERNAL_IRQS 8 | ||
86 | |||
87 | #define STMPE811_REG_CHIP_ID 0x00 | ||
88 | #define STMPE811_REG_SYS_CTRL2 0x04 | ||
89 | #define STMPE811_REG_INT_CTRL 0x09 | ||
90 | #define STMPE811_REG_INT_EN 0x0A | ||
91 | #define STMPE811_REG_INT_STA 0x0B | ||
92 | #define STMPE811_REG_GPIO_INT_EN 0x0C | ||
93 | #define STMPE811_REG_GPIO_INT_STA 0x0D | ||
94 | #define STMPE811_REG_GPIO_SET_PIN 0x10 | ||
95 | #define STMPE811_REG_GPIO_CLR_PIN 0x11 | ||
96 | #define STMPE811_REG_GPIO_MP_STA 0x12 | ||
97 | #define STMPE811_REG_GPIO_DIR 0x13 | ||
98 | #define STMPE811_REG_GPIO_ED 0x14 | ||
99 | #define STMPE811_REG_GPIO_RE 0x15 | ||
100 | #define STMPE811_REG_GPIO_FE 0x16 | ||
101 | #define STMPE811_REG_GPIO_AF 0x17 | ||
102 | |||
103 | #define STMPE811_SYS_CTRL2_ADC_OFF (1 << 0) | ||
104 | #define STMPE811_SYS_CTRL2_TSC_OFF (1 << 1) | ||
105 | #define STMPE811_SYS_CTRL2_GPIO_OFF (1 << 2) | ||
106 | #define STMPE811_SYS_CTRL2_TS_OFF (1 << 3) | ||
107 | |||
108 | /* | ||
109 | * STMPE1601 | ||
110 | */ | ||
111 | |||
112 | #define STMPE1601_IRQ_GPIOC 8 | ||
113 | #define STMPE1601_IRQ_PWM3 7 | ||
114 | #define STMPE1601_IRQ_PWM2 6 | ||
115 | #define STMPE1601_IRQ_PWM1 5 | ||
116 | #define STMPE1601_IRQ_PWM0 4 | ||
117 | #define STMPE1601_IRQ_KEYPAD_OVER 2 | ||
118 | #define STMPE1601_IRQ_KEYPAD 1 | ||
119 | #define STMPE1601_IRQ_WAKEUP 0 | ||
120 | #define STMPE1601_NR_INTERNAL_IRQS 9 | ||
121 | |||
122 | #define STMPE1601_REG_SYS_CTRL 0x02 | ||
123 | #define STMPE1601_REG_SYS_CTRL2 0x03 | ||
124 | #define STMPE1601_REG_ICR_LSB 0x11 | ||
125 | #define STMPE1601_REG_IER_LSB 0x13 | ||
126 | #define STMPE1601_REG_ISR_MSB 0x14 | ||
127 | #define STMPE1601_REG_CHIP_ID 0x80 | ||
128 | #define STMPE1601_REG_INT_EN_GPIO_MASK_LSB 0x17 | ||
129 | #define STMPE1601_REG_INT_STA_GPIO_MSB 0x18 | ||
130 | #define STMPE1601_REG_GPIO_MP_LSB 0x87 | ||
131 | #define STMPE1601_REG_GPIO_SET_LSB 0x83 | ||
132 | #define STMPE1601_REG_GPIO_CLR_LSB 0x85 | ||
133 | #define STMPE1601_REG_GPIO_SET_DIR_LSB 0x89 | ||
134 | #define STMPE1601_REG_GPIO_ED_MSB 0x8A | ||
135 | #define STMPE1601_REG_GPIO_RE_LSB 0x8D | ||
136 | #define STMPE1601_REG_GPIO_FE_LSB 0x8F | ||
137 | #define STMPE1601_REG_GPIO_AF_U_MSB 0x92 | ||
138 | |||
139 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
140 | #define STMPE1601_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
141 | #define STMPE1601_SYSCON_ENABLE_SPWM (1 << 0) | ||
142 | |||
143 | /* The 1601/2403 share the same masks */ | ||
144 | #define STMPE1601_AUTOSLEEP_TIMEOUT_MASK (0x7) | ||
145 | #define STPME1601_AUTOSLEEP_ENABLE (1 << 3) | ||
146 | |||
147 | /* | ||
148 | * STMPE24xx | ||
149 | */ | ||
150 | |||
151 | #define STMPE24XX_IRQ_GPIOC 8 | ||
152 | #define STMPE24XX_IRQ_PWM2 7 | ||
153 | #define STMPE24XX_IRQ_PWM1 6 | ||
154 | #define STMPE24XX_IRQ_PWM0 5 | ||
155 | #define STMPE24XX_IRQ_ROT_OVER 4 | ||
156 | #define STMPE24XX_IRQ_ROT 3 | ||
157 | #define STMPE24XX_IRQ_KEYPAD_OVER 2 | ||
158 | #define STMPE24XX_IRQ_KEYPAD 1 | ||
159 | #define STMPE24XX_IRQ_WAKEUP 0 | ||
160 | #define STMPE24XX_NR_INTERNAL_IRQS 9 | ||
161 | |||
162 | #define STMPE24XX_REG_SYS_CTRL 0x02 | ||
163 | #define STMPE24XX_REG_ICR_LSB 0x11 | ||
164 | #define STMPE24XX_REG_IER_LSB 0x13 | ||
165 | #define STMPE24XX_REG_ISR_MSB 0x14 | ||
166 | #define STMPE24XX_REG_CHIP_ID 0x80 | ||
167 | #define STMPE24XX_REG_IEGPIOR_LSB 0x18 | ||
168 | #define STMPE24XX_REG_ISGPIOR_MSB 0x19 | ||
169 | #define STMPE24XX_REG_GPMR_LSB 0xA5 | ||
170 | #define STMPE24XX_REG_GPSR_LSB 0x85 | ||
171 | #define STMPE24XX_REG_GPCR_LSB 0x88 | ||
172 | #define STMPE24XX_REG_GPDR_LSB 0x8B | ||
173 | #define STMPE24XX_REG_GPEDR_MSB 0x8C | ||
174 | #define STMPE24XX_REG_GPRER_LSB 0x91 | ||
175 | #define STMPE24XX_REG_GPFER_LSB 0x94 | ||
176 | #define STMPE24XX_REG_GPAFR_U_MSB 0x9B | ||
177 | |||
178 | #define STMPE24XX_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
179 | #define STMPE24XX_SYSCON_ENABLE_PWM (1 << 2) | ||
180 | #define STMPE24XX_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
181 | #define STMPE24XX_SYSCON_ENABLE_ROT (1 << 0) | ||
182 | |||
183 | #endif | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 5041d33adf0..006c121f3f0 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -350,7 +350,6 @@ static int t7l66xb_probe(struct platform_device *dev) | |||
350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); | 350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); |
351 | if (IS_ERR(t7l66xb->clk48m)) { | 351 | if (IS_ERR(t7l66xb->clk48m)) { |
352 | ret = PTR_ERR(t7l66xb->clk48m); | 352 | ret = PTR_ERR(t7l66xb->clk48m); |
353 | clk_put(t7l66xb->clk32k); | ||
354 | goto err_clk48m_get; | 353 | goto err_clk48m_get; |
355 | } | 354 | } |
356 | 355 | ||
@@ -425,6 +424,8 @@ static int t7l66xb_remove(struct platform_device *dev) | |||
425 | ret = pdata->disable(dev); | 424 | ret = pdata->disable(dev); |
426 | clk_disable(t7l66xb->clk48m); | 425 | clk_disable(t7l66xb->clk48m); |
427 | clk_put(t7l66xb->clk48m); | 426 | clk_put(t7l66xb->clk48m); |
427 | clk_disable(t7l66xb->clk32k); | ||
428 | clk_put(t7l66xb->clk32k); | ||
428 | t7l66xb_detach_irq(dev); | 429 | t7l66xb_detach_irq(dev); |
429 | iounmap(t7l66xb->scr); | 430 | iounmap(t7l66xb->scr); |
430 | release_resource(&t7l66xb->rscr); | 431 | release_resource(&t7l66xb->rscr); |
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 517f9bcdeaa..6315f63f017 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
@@ -137,7 +137,7 @@ static struct mfd_cell tc6387xb_cells[] = { | |||
137 | }, | 137 | }, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static int tc6387xb_probe(struct platform_device *dev) | 140 | static int __devinit tc6387xb_probe(struct platform_device *dev) |
141 | { | 141 | { |
142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; | 142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; |
143 | struct resource *iomem, *rscr; | 143 | struct resource *iomem, *rscr; |
@@ -201,6 +201,7 @@ static int tc6387xb_probe(struct platform_device *dev) | |||
201 | if (!ret) | 201 | if (!ret) |
202 | return 0; | 202 | return 0; |
203 | 203 | ||
204 | iounmap(tc6387xb->scr); | ||
204 | err_ioremap: | 205 | err_ioremap: |
205 | release_resource(&tc6387xb->rscr); | 206 | release_resource(&tc6387xb->rscr); |
206 | err_resource: | 207 | err_resource: |
@@ -211,14 +212,17 @@ err_no_irq: | |||
211 | return ret; | 212 | return ret; |
212 | } | 213 | } |
213 | 214 | ||
214 | static int tc6387xb_remove(struct platform_device *dev) | 215 | static int __devexit tc6387xb_remove(struct platform_device *dev) |
215 | { | 216 | { |
216 | struct clk *clk32k = platform_get_drvdata(dev); | 217 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); |
217 | 218 | ||
218 | mfd_remove_devices(&dev->dev); | 219 | mfd_remove_devices(&dev->dev); |
219 | clk_disable(clk32k); | 220 | iounmap(tc6387xb->scr); |
220 | clk_put(clk32k); | 221 | release_resource(&tc6387xb->rscr); |
222 | clk_disable(tc6387xb->clk32k); | ||
223 | clk_put(tc6387xb->clk32k); | ||
221 | platform_set_drvdata(dev, NULL); | 224 | platform_set_drvdata(dev, NULL); |
225 | kfree(tc6387xb); | ||
222 | 226 | ||
223 | return 0; | 227 | return 0; |
224 | } | 228 | } |
@@ -229,7 +233,7 @@ static struct platform_driver tc6387xb_platform_driver = { | |||
229 | .name = "tc6387xb", | 233 | .name = "tc6387xb", |
230 | }, | 234 | }, |
231 | .probe = tc6387xb_probe, | 235 | .probe = tc6387xb_probe, |
232 | .remove = tc6387xb_remove, | 236 | .remove = __devexit_p(tc6387xb_remove), |
233 | .suspend = tc6387xb_suspend, | 237 | .suspend = tc6387xb_suspend, |
234 | .resume = tc6387xb_resume, | 238 | .resume = tc6387xb_resume, |
235 | }; | 239 | }; |
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index fcf9068810f..ef6c42c8917 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -732,9 +732,9 @@ err_gpio_add: | |||
732 | if (tc6393xb->gpio.base != -1) | 732 | if (tc6393xb->gpio.base != -1) |
733 | temp = gpiochip_remove(&tc6393xb->gpio); | 733 | temp = gpiochip_remove(&tc6393xb->gpio); |
734 | tcpd->disable(dev); | 734 | tcpd->disable(dev); |
735 | err_clk_enable: | ||
736 | clk_disable(tc6393xb->clk); | ||
737 | err_enable: | 735 | err_enable: |
736 | clk_disable(tc6393xb->clk); | ||
737 | err_clk_enable: | ||
738 | iounmap(tc6393xb->scr); | 738 | iounmap(tc6393xb->scr); |
739 | err_ioremap: | 739 | err_ioremap: |
740 | release_resource(&tc6393xb->rscr); | 740 | release_resource(&tc6393xb->rscr); |
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index d859dffed39..fc019764928 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c | |||
@@ -89,10 +89,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, | |||
89 | int ret = 0; | 89 | int ret = 0; |
90 | 90 | ||
91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); | 91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); |
92 | if (tps6507x == NULL) { | 92 | if (tps6507x == NULL) |
93 | kfree(i2c); | ||
94 | return -ENOMEM; | 93 | return -ENOMEM; |
95 | } | ||
96 | 94 | ||
97 | i2c_set_clientdata(i2c, tps6507x); | 95 | i2c_set_clientdata(i2c, tps6507x); |
98 | tps6507x->dev = &i2c->dev; | 96 | tps6507x->dev = &i2c->dev; |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c new file mode 100644 index 00000000000..4cde31e6a25 --- /dev/null +++ b/drivers/mfd/tps6586x.c | |||
@@ -0,0 +1,375 @@ | |||
1 | /* | ||
2 | * Core driver for TI TPS6586x PMIC family | ||
3 | * | ||
4 | * Copyright (c) 2010 CompuLab Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on da903x.c. | ||
8 | * Copyright (C) 2008 Compulab, Ltd. | ||
9 | * Mike Rapoport <mike@compulab.co.il> | ||
10 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
11 | * Eric Miao <eric.miao@marvell.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 version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/i2c.h> | ||
24 | |||
25 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/tps6586x.h> | ||
27 | |||
28 | /* GPIO control registers */ | ||
29 | #define TPS6586X_GPIOSET1 0x5d | ||
30 | #define TPS6586X_GPIOSET2 0x5e | ||
31 | |||
32 | /* device id */ | ||
33 | #define TPS6586X_VERSIONCRC 0xcd | ||
34 | #define TPS658621A_VERSIONCRC 0x15 | ||
35 | |||
36 | struct tps6586x { | ||
37 | struct mutex lock; | ||
38 | struct device *dev; | ||
39 | struct i2c_client *client; | ||
40 | |||
41 | struct gpio_chip gpio; | ||
42 | }; | ||
43 | |||
44 | static inline int __tps6586x_read(struct i2c_client *client, | ||
45 | int reg, uint8_t *val) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | ret = i2c_smbus_read_byte_data(client, reg); | ||
50 | if (ret < 0) { | ||
51 | dev_err(&client->dev, "failed reading at 0x%02x\n", reg); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | *val = (uint8_t)ret; | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static inline int __tps6586x_reads(struct i2c_client *client, int reg, | ||
61 | int len, uint8_t *val) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); | ||
66 | if (ret < 0) { | ||
67 | dev_err(&client->dev, "failed reading from 0x%02x\n", reg); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static inline int __tps6586x_write(struct i2c_client *client, | ||
75 | int reg, uint8_t val) | ||
76 | { | ||
77 | int ret; | ||
78 | |||
79 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
80 | if (ret < 0) { | ||
81 | dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", | ||
82 | val, reg); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static inline int __tps6586x_writes(struct i2c_client *client, int reg, | ||
90 | int len, uint8_t *val) | ||
91 | { | ||
92 | int ret; | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(client, reg, len, val); | ||
95 | if (ret < 0) { | ||
96 | dev_err(&client->dev, "failed writings to 0x%02x\n", reg); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int tps6586x_write(struct device *dev, int reg, uint8_t val) | ||
104 | { | ||
105 | return __tps6586x_write(to_i2c_client(dev), reg, val); | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(tps6586x_write); | ||
108 | |||
109 | int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) | ||
110 | { | ||
111 | return __tps6586x_writes(to_i2c_client(dev), reg, len, val); | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(tps6586x_writes); | ||
114 | |||
115 | int tps6586x_read(struct device *dev, int reg, uint8_t *val) | ||
116 | { | ||
117 | return __tps6586x_read(to_i2c_client(dev), reg, val); | ||
118 | } | ||
119 | EXPORT_SYMBOL_GPL(tps6586x_read); | ||
120 | |||
121 | int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) | ||
122 | { | ||
123 | return __tps6586x_reads(to_i2c_client(dev), reg, len, val); | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(tps6586x_reads); | ||
126 | |||
127 | int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
128 | { | ||
129 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
130 | uint8_t reg_val; | ||
131 | int ret = 0; | ||
132 | |||
133 | mutex_lock(&tps6586x->lock); | ||
134 | |||
135 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
136 | if (ret) | ||
137 | goto out; | ||
138 | |||
139 | if ((reg_val & bit_mask) == 0) { | ||
140 | reg_val |= bit_mask; | ||
141 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
142 | } | ||
143 | out: | ||
144 | mutex_unlock(&tps6586x->lock); | ||
145 | return ret; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(tps6586x_set_bits); | ||
148 | |||
149 | int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
150 | { | ||
151 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
152 | uint8_t reg_val; | ||
153 | int ret = 0; | ||
154 | |||
155 | mutex_lock(&tps6586x->lock); | ||
156 | |||
157 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
158 | if (ret) | ||
159 | goto out; | ||
160 | |||
161 | if (reg_val & bit_mask) { | ||
162 | reg_val &= ~bit_mask; | ||
163 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
164 | } | ||
165 | out: | ||
166 | mutex_unlock(&tps6586x->lock); | ||
167 | return ret; | ||
168 | } | ||
169 | EXPORT_SYMBOL_GPL(tps6586x_clr_bits); | ||
170 | |||
171 | int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) | ||
172 | { | ||
173 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
174 | uint8_t reg_val; | ||
175 | int ret = 0; | ||
176 | |||
177 | mutex_lock(&tps6586x->lock); | ||
178 | |||
179 | ret = __tps6586x_read(tps6586x->client, reg, ®_val); | ||
180 | if (ret) | ||
181 | goto out; | ||
182 | |||
183 | if ((reg_val & mask) != val) { | ||
184 | reg_val = (reg_val & ~mask) | val; | ||
185 | ret = __tps6586x_write(tps6586x->client, reg, reg_val); | ||
186 | } | ||
187 | out: | ||
188 | mutex_unlock(&tps6586x->lock); | ||
189 | return ret; | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(tps6586x_update); | ||
192 | |||
193 | static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
194 | { | ||
195 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
196 | uint8_t val; | ||
197 | int ret; | ||
198 | |||
199 | ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
203 | return !!(val & (1 << offset)); | ||
204 | } | ||
205 | |||
206 | |||
207 | static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, | ||
208 | int value) | ||
209 | { | ||
210 | struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); | ||
211 | |||
212 | __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, | ||
213 | value << offset); | ||
214 | } | ||
215 | |||
216 | static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, | ||
217 | int value) | ||
218 | { | ||
219 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
220 | uint8_t val, mask; | ||
221 | |||
222 | tps6586x_gpio_set(gc, offset, value); | ||
223 | |||
224 | val = 0x1 << (offset * 2); | ||
225 | mask = 0x3 << (offset * 2); | ||
226 | |||
227 | return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); | ||
228 | } | ||
229 | |||
230 | static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | if (!gpio_base) | ||
235 | return; | ||
236 | |||
237 | tps6586x->gpio.owner = THIS_MODULE; | ||
238 | tps6586x->gpio.label = tps6586x->client->name; | ||
239 | tps6586x->gpio.dev = tps6586x->dev; | ||
240 | tps6586x->gpio.base = gpio_base; | ||
241 | tps6586x->gpio.ngpio = 4; | ||
242 | tps6586x->gpio.can_sleep = 1; | ||
243 | |||
244 | /* FIXME: add handling of GPIOs as dedicated inputs */ | ||
245 | tps6586x->gpio.direction_output = tps6586x_gpio_output; | ||
246 | tps6586x->gpio.set = tps6586x_gpio_set; | ||
247 | tps6586x->gpio.get = tps6586x_gpio_get; | ||
248 | |||
249 | ret = gpiochip_add(&tps6586x->gpio); | ||
250 | if (ret) | ||
251 | dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret); | ||
252 | } | ||
253 | |||
254 | static int __remove_subdev(struct device *dev, void *unused) | ||
255 | { | ||
256 | platform_device_unregister(to_platform_device(dev)); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) | ||
261 | { | ||
262 | return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); | ||
263 | } | ||
264 | |||
265 | static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, | ||
266 | struct tps6586x_platform_data *pdata) | ||
267 | { | ||
268 | struct tps6586x_subdev_info *subdev; | ||
269 | struct platform_device *pdev; | ||
270 | int i, ret = 0; | ||
271 | |||
272 | for (i = 0; i < pdata->num_subdevs; i++) { | ||
273 | subdev = &pdata->subdevs[i]; | ||
274 | |||
275 | pdev = platform_device_alloc(subdev->name, subdev->id); | ||
276 | |||
277 | pdev->dev.parent = tps6586x->dev; | ||
278 | pdev->dev.platform_data = subdev->platform_data; | ||
279 | |||
280 | ret = platform_device_add(pdev); | ||
281 | if (ret) | ||
282 | goto failed; | ||
283 | } | ||
284 | return 0; | ||
285 | |||
286 | failed: | ||
287 | tps6586x_remove_subdevs(tps6586x); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | ||
292 | const struct i2c_device_id *id) | ||
293 | { | ||
294 | struct tps6586x_platform_data *pdata = client->dev.platform_data; | ||
295 | struct tps6586x *tps6586x; | ||
296 | int ret; | ||
297 | |||
298 | if (!pdata) { | ||
299 | dev_err(&client->dev, "tps6586x requires platform data\n"); | ||
300 | return -ENOTSUPP; | ||
301 | } | ||
302 | |||
303 | ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); | ||
304 | if (ret < 0) { | ||
305 | dev_err(&client->dev, "Chip ID read failed: %d\n", ret); | ||
306 | return -EIO; | ||
307 | } | ||
308 | |||
309 | if (ret != TPS658621A_VERSIONCRC) { | ||
310 | dev_err(&client->dev, "Unsupported chip ID: %x\n", ret); | ||
311 | return -ENODEV; | ||
312 | } | ||
313 | |||
314 | tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); | ||
315 | if (tps6586x == NULL) | ||
316 | return -ENOMEM; | ||
317 | |||
318 | tps6586x->client = client; | ||
319 | tps6586x->dev = &client->dev; | ||
320 | i2c_set_clientdata(client, tps6586x); | ||
321 | |||
322 | mutex_init(&tps6586x->lock); | ||
323 | |||
324 | ret = tps6586x_add_subdevs(tps6586x, pdata); | ||
325 | if (ret) { | ||
326 | dev_err(&client->dev, "add devices failed: %d\n", ret); | ||
327 | goto err_add_devs; | ||
328 | } | ||
329 | |||
330 | tps6586x_gpio_init(tps6586x, pdata->gpio_base); | ||
331 | |||
332 | return 0; | ||
333 | |||
334 | err_add_devs: | ||
335 | kfree(tps6586x); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int __devexit tps6586x_i2c_remove(struct i2c_client *client) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static const struct i2c_device_id tps6586x_id_table[] = { | ||
345 | { "tps6586x", 0 }, | ||
346 | { }, | ||
347 | }; | ||
348 | MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); | ||
349 | |||
350 | static struct i2c_driver tps6586x_driver = { | ||
351 | .driver = { | ||
352 | .name = "tps6586x", | ||
353 | .owner = THIS_MODULE, | ||
354 | }, | ||
355 | .probe = tps6586x_i2c_probe, | ||
356 | .remove = __devexit_p(tps6586x_i2c_remove), | ||
357 | .id_table = tps6586x_id_table, | ||
358 | }; | ||
359 | |||
360 | static int __init tps6586x_init(void) | ||
361 | { | ||
362 | return i2c_add_driver(&tps6586x_driver); | ||
363 | } | ||
364 | subsys_initcall(tps6586x_init); | ||
365 | |||
366 | static void __exit tps6586x_exit(void) | ||
367 | { | ||
368 | i2c_del_driver(&tps6586x_driver); | ||
369 | } | ||
370 | module_exit(tps6586x_exit); | ||
371 | |||
372 | MODULE_DESCRIPTION("TPS6586X core driver"); | ||
373 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
374 | MODULE_LICENSE("GPL"); | ||
375 | |||
diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c new file mode 100644 index 00000000000..5d25bdc7842 --- /dev/null +++ b/drivers/mfd/twl6030-pwm.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * twl6030_pwm.c | ||
3 | * Driver for PHOENIX (TWL6030) Pulse Width Modulator | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments | ||
6 | * Author: Hemanth V <hemanthv@ti.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 version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/i2c/twl.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #define LED_PWM_CTRL1 0xF4 | ||
27 | #define LED_PWM_CTRL2 0xF5 | ||
28 | |||
29 | /* Max value for CTRL1 register */ | ||
30 | #define PWM_CTRL1_MAX 255 | ||
31 | |||
32 | /* Pull down disable */ | ||
33 | #define PWM_CTRL2_DIS_PD (1 << 6) | ||
34 | |||
35 | /* Current control 2.5 milli Amps */ | ||
36 | #define PWM_CTRL2_CURR_02 (2 << 4) | ||
37 | |||
38 | /* LED supply source */ | ||
39 | #define PWM_CTRL2_SRC_VAC (1 << 2) | ||
40 | |||
41 | /* LED modes */ | ||
42 | #define PWM_CTRL2_MODE_HW (0 << 0) | ||
43 | #define PWM_CTRL2_MODE_SW (1 << 0) | ||
44 | #define PWM_CTRL2_MODE_DIS (2 << 0) | ||
45 | |||
46 | #define PWM_CTRL2_MODE_MASK 0x3 | ||
47 | |||
48 | struct pwm_device { | ||
49 | const char *label; | ||
50 | unsigned int pwm_id; | ||
51 | }; | ||
52 | |||
53 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | ||
54 | { | ||
55 | u8 duty_cycle; | ||
56 | int ret; | ||
57 | |||
58 | if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) | ||
59 | return -EINVAL; | ||
60 | |||
61 | duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns; | ||
62 | |||
63 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1); | ||
64 | |||
65 | if (ret < 0) { | ||
66 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
67 | pwm->label, ret); | ||
68 | return ret; | ||
69 | } | ||
70 | return 0; | ||
71 | } | ||
72 | EXPORT_SYMBOL(pwm_config); | ||
73 | |||
74 | int pwm_enable(struct pwm_device *pwm) | ||
75 | { | ||
76 | u8 val; | ||
77 | int ret; | ||
78 | |||
79 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
80 | if (ret < 0) { | ||
81 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | /* Change mode to software control */ | ||
86 | val &= ~PWM_CTRL2_MODE_MASK; | ||
87 | val |= PWM_CTRL2_MODE_SW; | ||
88 | |||
89 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
90 | if (ret < 0) { | ||
91 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
96 | return 0; | ||
97 | } | ||
98 | EXPORT_SYMBOL(pwm_enable); | ||
99 | |||
100 | void pwm_disable(struct pwm_device *pwm) | ||
101 | { | ||
102 | u8 val; | ||
103 | int ret; | ||
104 | |||
105 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
106 | if (ret < 0) { | ||
107 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
108 | pwm->label, ret); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | val &= ~PWM_CTRL2_MODE_MASK; | ||
113 | val |= PWM_CTRL2_MODE_HW; | ||
114 | |||
115 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
116 | if (ret < 0) { | ||
117 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
118 | pwm->label, ret); | ||
119 | return; | ||
120 | } | ||
121 | return; | ||
122 | } | ||
123 | EXPORT_SYMBOL(pwm_disable); | ||
124 | |||
125 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
126 | { | ||
127 | u8 val; | ||
128 | int ret; | ||
129 | struct pwm_device *pwm; | ||
130 | |||
131 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | ||
132 | if (pwm == NULL) { | ||
133 | pr_err("%s: failed to allocate memory\n", label); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | pwm->label = label; | ||
138 | pwm->pwm_id = pwm_id; | ||
139 | |||
140 | /* Configure PWM */ | ||
141 | val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC | | ||
142 | PWM_CTRL2_MODE_HW; | ||
143 | |||
144 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
145 | |||
146 | if (ret < 0) { | ||
147 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
148 | pwm->label, ret); | ||
149 | |||
150 | kfree(pwm); | ||
151 | return NULL; | ||
152 | } | ||
153 | |||
154 | return pwm; | ||
155 | } | ||
156 | EXPORT_SYMBOL(pwm_request); | ||
157 | |||
158 | void pwm_free(struct pwm_device *pwm) | ||
159 | { | ||
160 | pwm_disable(pwm); | ||
161 | kfree(pwm); | ||
162 | } | ||
163 | EXPORT_SYMBOL(pwm_free); | ||
diff --git a/drivers/mfd/ucb1400_core.c b/drivers/mfd/ucb1400_core.c index dbe280153f9..d73f84ba0f0 100644 --- a/drivers/mfd/ucb1400_core.c +++ b/drivers/mfd/ucb1400_core.c | |||
@@ -114,7 +114,7 @@ static int ucb1400_core_probe(struct device *dev) | |||
114 | err3: | 114 | err3: |
115 | platform_device_put(ucb->ucb1400_ts); | 115 | platform_device_put(ucb->ucb1400_ts); |
116 | err2: | 116 | err2: |
117 | platform_device_unregister(ucb->ucb1400_gpio); | 117 | platform_device_del(ucb->ucb1400_gpio); |
118 | err1: | 118 | err1: |
119 | platform_device_put(ucb->ucb1400_gpio); | 119 | platform_device_put(ucb->ucb1400_gpio); |
120 | err0: | 120 | err0: |
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 1a968f34d67..1e7aaaf6cc6 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -95,6 +95,7 @@ enum wm831x_parent { | |||
95 | WM8311 = 0x8311, | 95 | WM8311 = 0x8311, |
96 | WM8312 = 0x8312, | 96 | WM8312 = 0x8312, |
97 | WM8320 = 0x8320, | 97 | WM8320 = 0x8320, |
98 | WM8321 = 0x8321, | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) | 101 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) |
@@ -1533,6 +1534,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1533 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); | 1534 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); |
1534 | break; | 1535 | break; |
1535 | 1536 | ||
1537 | case WM8321: | ||
1538 | parent = WM8321; | ||
1539 | wm831x->num_gpio = 12; | ||
1540 | dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev); | ||
1541 | break; | ||
1542 | |||
1536 | default: | 1543 | default: |
1537 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); | 1544 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); |
1538 | ret = -EINVAL; | 1545 | ret = -EINVAL; |
@@ -1607,6 +1614,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1607 | NULL, 0); | 1614 | NULL, 0); |
1608 | break; | 1615 | break; |
1609 | 1616 | ||
1617 | case WM8321: | ||
1618 | ret = mfd_add_devices(wm831x->dev, -1, | ||
1619 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | ||
1620 | NULL, 0); | ||
1621 | break; | ||
1622 | |||
1610 | default: | 1623 | default: |
1611 | /* If this happens the bus probe function is buggy */ | 1624 | /* If this happens the bus probe function is buggy */ |
1612 | BUG(); | 1625 | BUG(); |
@@ -1744,10 +1757,8 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, | |||
1744 | struct wm831x *wm831x; | 1757 | struct wm831x *wm831x; |
1745 | 1758 | ||
1746 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | 1759 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); |
1747 | if (wm831x == NULL) { | 1760 | if (wm831x == NULL) |
1748 | kfree(i2c); | ||
1749 | return -ENOMEM; | 1761 | return -ENOMEM; |
1750 | } | ||
1751 | 1762 | ||
1752 | i2c_set_clientdata(i2c, wm831x); | 1763 | i2c_set_clientdata(i2c, wm831x); |
1753 | wm831x->dev = &i2c->dev; | 1764 | wm831x->dev = &i2c->dev; |
@@ -1779,6 +1790,7 @@ static const struct i2c_device_id wm831x_i2c_id[] = { | |||
1779 | { "wm8311", WM8311 }, | 1790 | { "wm8311", WM8311 }, |
1780 | { "wm8312", WM8312 }, | 1791 | { "wm8312", WM8312 }, |
1781 | { "wm8320", WM8320 }, | 1792 | { "wm8320", WM8320 }, |
1793 | { "wm8321", WM8321 }, | ||
1782 | { } | 1794 | { } |
1783 | }; | 1795 | }; |
1784 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | 1796 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); |
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index b5807484b4c..e81cc31e420 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -536,6 +536,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) | |||
536 | } | 536 | } |
537 | 537 | ||
538 | out: | 538 | out: |
539 | kfree(wm8350->reg_cache); | ||
539 | return ret; | 540 | return ret; |
540 | } | 541 | } |
541 | 542 | ||
@@ -700,7 +701,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
700 | 701 | ||
701 | ret = wm8350_irq_init(wm8350, irq, pdata); | 702 | ret = wm8350_irq_init(wm8350, irq, pdata); |
702 | if (ret < 0) | 703 | if (ret < 0) |
703 | goto err; | 704 | goto err_free; |
704 | 705 | ||
705 | if (wm8350->irq_base) { | 706 | if (wm8350->irq_base) { |
706 | ret = request_threaded_irq(wm8350->irq_base + | 707 | ret = request_threaded_irq(wm8350->irq_base + |
@@ -738,8 +739,9 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
738 | 739 | ||
739 | err_irq: | 740 | err_irq: |
740 | wm8350_irq_exit(wm8350); | 741 | wm8350_irq_exit(wm8350); |
741 | err: | 742 | err_free: |
742 | kfree(wm8350->reg_cache); | 743 | kfree(wm8350->reg_cache); |
744 | err: | ||
743 | return ret; | 745 | return ret; |
744 | } | 746 | } |
745 | EXPORT_SYMBOL_GPL(wm8350_device_init); | 747 | EXPORT_SYMBOL_GPL(wm8350_device_init); |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index ec71c936890..b3b2aaf89db 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -326,8 +326,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * | 326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * |
327 | ARRAY_SIZE(wm8994_main_supplies), | 327 | ARRAY_SIZE(wm8994_main_supplies), |
328 | GFP_KERNEL); | 328 | GFP_KERNEL); |
329 | if (!wm8994->supplies) | 329 | if (!wm8994->supplies) { |
330 | ret = -ENOMEM; | ||
330 | goto err; | 331 | goto err; |
332 | } | ||
331 | 333 | ||
332 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 334 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) |
333 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 335 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
@@ -495,10 +497,8 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
495 | struct wm8994 *wm8994; | 497 | struct wm8994 *wm8994; |
496 | 498 | ||
497 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); | 499 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); |
498 | if (wm8994 == NULL) { | 500 | if (wm8994 == NULL) |
499 | kfree(i2c); | ||
500 | return -ENOMEM; | 501 | return -ENOMEM; |
501 | } | ||
502 | 502 | ||
503 | i2c_set_clientdata(i2c, wm8994); | 503 | i2c_set_clientdata(i2c, wm8994); |
504 | wm8994->dev = &i2c->dev; | 504 | wm8994->dev = &i2c->dev; |