diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 18:54:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 18:54:04 -0400 |
commit | b779b332d0e1ef68f40867948ae5526a3e925163 (patch) | |
tree | d2fc8bb455d696fbdb288055ce0a4f0cfcee31fd /drivers | |
parent | a0cadc2777a71b1fde62e6417284b38e52128e88 (diff) | |
parent | 0f48285755991b73c14b6eeeee464590f490ac25 (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: (73 commits)
power: Revert "power_supply: Mark twl4030_charger as broken"
mfd: Fix a memory leak when unload mc13xxx-core module
mfd: Fix resource reclaim for max8998
mfd: Remove unneeded ret value checking for max8998 register updates
mfd: Add free max8998->ono irq in max8998_irq_exit()
mfd: Fix resource reclaim in pcf50633_remove()
omap4: pandaboard: fix up mmc card detect logic
mfd: Fix ezx_pcap_probe error path
mfd: Fix off-by-one value range checking for tps6507x
mfd: Remove __devinitdata from tc6393xb_mmc_resources
mfd: Add WM831x SPI support
mfd: Factor out WM831x I2C I/O from the core driver
mfd: Remove DEBUG defines from mc13xxx-core
mfd: Fix jz4740_adc_set_enabled
mfd: Add TPS658621C device ID
mfd: Fix twl-irq function declaration warnings
regulator: max8998 BUCK1/2 voltage change with use of GPIOs
mfd: Voltages and GPIOs platform_data definitions for max8998
regulator: max8998 BUCK1/2 internal voltages and indexes defined
mfd: Support for ICs compliant with max8998
...
Diffstat (limited to 'drivers')
57 files changed, 5071 insertions, 1844 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index dd9b4ba8d32d..3143ac795eb0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -116,6 +116,18 @@ config GPIO_SCH | |||
116 | This driver can also be built as a module. If so, the module | 116 | This driver can also be built as a module. If so, the module |
117 | will be called sch-gpio. | 117 | will be called sch-gpio. |
118 | 118 | ||
119 | config GPIO_VX855 | ||
120 | tristate "VIA VX855/VX875 GPIO" | ||
121 | depends on GPIOLIB | ||
122 | select MFD_CORE | ||
123 | select MFD_VX855 | ||
124 | help | ||
125 | Support access to the VX855/VX875 GPIO lines through the gpio library. | ||
126 | |||
127 | This driver provides common support for accessing the device, | ||
128 | additional drivers must be enabled in order to use the | ||
129 | functionality of the device. | ||
130 | |||
119 | comment "I2C GPIO expanders:" | 131 | comment "I2C GPIO expanders:" |
120 | 132 | ||
121 | config GPIO_MAX7300 | 133 | config GPIO_MAX7300 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index da2ecde5abdd..bdf3ddec0652 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -40,3 +40,4 @@ obj-$(CONFIG_GPIO_SCH) += sch_gpio.o | |||
40 | obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o | 40 | obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o |
41 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o | 41 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o |
42 | obj-$(CONFIG_GPIO_SX150X) += sx150x.o | 42 | obj-$(CONFIG_GPIO_SX150X) += sx150x.o |
43 | obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o | ||
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c index 4e1f1b9d5e67..7c9e6a052c45 100644 --- a/drivers/gpio/stmpe-gpio.c +++ b/drivers/gpio/stmpe-gpio.c | |||
@@ -30,6 +30,7 @@ struct stmpe_gpio { | |||
30 | struct mutex irq_lock; | 30 | struct mutex irq_lock; |
31 | 31 | ||
32 | int irq_base; | 32 | int irq_base; |
33 | unsigned norequest_mask; | ||
33 | 34 | ||
34 | /* Caches of interrupt control registers for bus_lock */ | 35 | /* Caches of interrupt control registers for bus_lock */ |
35 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | 36 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; |
@@ -103,6 +104,9 @@ static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) | |||
103 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | 104 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); |
104 | struct stmpe *stmpe = stmpe_gpio->stmpe; | 105 | struct stmpe *stmpe = stmpe_gpio->stmpe; |
105 | 106 | ||
107 | if (stmpe_gpio->norequest_mask & (1 << offset)) | ||
108 | return -EINVAL; | ||
109 | |||
106 | return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); | 110 | return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); |
107 | } | 111 | } |
108 | 112 | ||
@@ -287,8 +291,6 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
287 | int irq; | 291 | int irq; |
288 | 292 | ||
289 | pdata = stmpe->pdata->gpio; | 293 | pdata = stmpe->pdata->gpio; |
290 | if (!pdata) | ||
291 | return -ENODEV; | ||
292 | 294 | ||
293 | irq = platform_get_irq(pdev, 0); | 295 | irq = platform_get_irq(pdev, 0); |
294 | if (irq < 0) | 296 | if (irq < 0) |
@@ -302,6 +304,7 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
302 | 304 | ||
303 | stmpe_gpio->dev = &pdev->dev; | 305 | stmpe_gpio->dev = &pdev->dev; |
304 | stmpe_gpio->stmpe = stmpe; | 306 | stmpe_gpio->stmpe = stmpe; |
307 | stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0; | ||
305 | 308 | ||
306 | stmpe_gpio->chip = template_chip; | 309 | stmpe_gpio->chip = template_chip; |
307 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; | 310 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; |
@@ -312,11 +315,11 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
312 | 315 | ||
313 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | 316 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); |
314 | if (ret) | 317 | if (ret) |
315 | return ret; | 318 | goto out_free; |
316 | 319 | ||
317 | ret = stmpe_gpio_irq_init(stmpe_gpio); | 320 | ret = stmpe_gpio_irq_init(stmpe_gpio); |
318 | if (ret) | 321 | if (ret) |
319 | goto out_free; | 322 | goto out_disable; |
320 | 323 | ||
321 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, | 324 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, |
322 | "stmpe-gpio", stmpe_gpio); | 325 | "stmpe-gpio", stmpe_gpio); |
@@ -342,6 +345,8 @@ out_freeirq: | |||
342 | free_irq(irq, stmpe_gpio); | 345 | free_irq(irq, stmpe_gpio); |
343 | out_removeirq: | 346 | out_removeirq: |
344 | stmpe_gpio_irq_remove(stmpe_gpio); | 347 | stmpe_gpio_irq_remove(stmpe_gpio); |
348 | out_disable: | ||
349 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | ||
345 | out_free: | 350 | out_free: |
346 | kfree(stmpe_gpio); | 351 | kfree(stmpe_gpio); |
347 | return ret; | 352 | return ret; |
diff --git a/drivers/gpio/vx855_gpio.c b/drivers/gpio/vx855_gpio.c new file mode 100644 index 000000000000..8a98ee5d5f6c --- /dev/null +++ b/drivers/gpio/vx855_gpio.c | |||
@@ -0,0 +1,332 @@ | |||
1 | /* | ||
2 | * Linux GPIOlib driver for the VIA VX855 integrated southbridge GPIO | ||
3 | * | ||
4 | * Copyright (C) 2009 VIA Technologies, Inc. | ||
5 | * Copyright (C) 2010 One Laptop per Child | ||
6 | * Author: Harald Welte <HaraldWelte@viatech.com> | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License as | ||
11 | * published by the Free Software Foundation; either version 2 of | ||
12 | * the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
22 | * MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/gpio.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/io.h> | ||
33 | |||
34 | #define MODULE_NAME "vx855_gpio" | ||
35 | |||
36 | /* The VX855 south bridge has the following GPIO pins: | ||
37 | * GPI 0...13 General Purpose Input | ||
38 | * GPO 0...12 General Purpose Output | ||
39 | * GPIO 0...14 General Purpose I/O (Open-Drain) | ||
40 | */ | ||
41 | |||
42 | #define NR_VX855_GPI 14 | ||
43 | #define NR_VX855_GPO 13 | ||
44 | #define NR_VX855_GPIO 15 | ||
45 | |||
46 | #define NR_VX855_GPInO (NR_VX855_GPI + NR_VX855_GPO) | ||
47 | #define NR_VX855_GP (NR_VX855_GPI + NR_VX855_GPO + NR_VX855_GPIO) | ||
48 | |||
49 | struct vx855_gpio { | ||
50 | struct gpio_chip gpio; | ||
51 | spinlock_t lock; | ||
52 | u32 io_gpi; | ||
53 | u32 io_gpo; | ||
54 | bool gpi_reserved; | ||
55 | bool gpo_reserved; | ||
56 | }; | ||
57 | |||
58 | /* resolve a GPIx into the corresponding bit position */ | ||
59 | static inline u_int32_t gpi_i_bit(int i) | ||
60 | { | ||
61 | if (i < 10) | ||
62 | return 1 << i; | ||
63 | else | ||
64 | return 1 << (i + 14); | ||
65 | } | ||
66 | |||
67 | static inline u_int32_t gpo_o_bit(int i) | ||
68 | { | ||
69 | if (i < 11) | ||
70 | return 1 << i; | ||
71 | else | ||
72 | return 1 << (i + 14); | ||
73 | } | ||
74 | |||
75 | static inline u_int32_t gpio_i_bit(int i) | ||
76 | { | ||
77 | if (i < 14) | ||
78 | return 1 << (i + 10); | ||
79 | else | ||
80 | return 1 << (i + 14); | ||
81 | } | ||
82 | |||
83 | static inline u_int32_t gpio_o_bit(int i) | ||
84 | { | ||
85 | if (i < 14) | ||
86 | return 1 << (i + 11); | ||
87 | else | ||
88 | return 1 << (i + 13); | ||
89 | } | ||
90 | |||
91 | /* Mapping betwee numeric GPIO ID and the actual GPIO hardware numbering: | ||
92 | * 0..13 GPI 0..13 | ||
93 | * 14..26 GPO 0..12 | ||
94 | * 27..41 GPIO 0..14 | ||
95 | */ | ||
96 | |||
97 | static int vx855gpio_direction_input(struct gpio_chip *gpio, | ||
98 | unsigned int nr) | ||
99 | { | ||
100 | struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio); | ||
101 | unsigned long flags; | ||
102 | u_int32_t reg_out; | ||
103 | |||
104 | /* Real GPI bits are always in input direction */ | ||
105 | if (nr < NR_VX855_GPI) | ||
106 | return 0; | ||
107 | |||
108 | /* Real GPO bits cannot be put in output direction */ | ||
109 | if (nr < NR_VX855_GPInO) | ||
110 | return -EINVAL; | ||
111 | |||
112 | /* Open Drain GPIO have to be set to one */ | ||
113 | spin_lock_irqsave(&vg->lock, flags); | ||
114 | reg_out = inl(vg->io_gpo); | ||
115 | reg_out |= gpio_o_bit(nr - NR_VX855_GPInO); | ||
116 | outl(reg_out, vg->io_gpo); | ||
117 | spin_unlock_irqrestore(&vg->lock, flags); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int vx855gpio_get(struct gpio_chip *gpio, unsigned int nr) | ||
123 | { | ||
124 | struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio); | ||
125 | u_int32_t reg_in; | ||
126 | int ret = 0; | ||
127 | |||
128 | if (nr < NR_VX855_GPI) { | ||
129 | reg_in = inl(vg->io_gpi); | ||
130 | if (reg_in & gpi_i_bit(nr)) | ||
131 | ret = 1; | ||
132 | } else if (nr < NR_VX855_GPInO) { | ||
133 | /* GPO don't have an input bit, we need to read it | ||
134 | * back from the output register */ | ||
135 | reg_in = inl(vg->io_gpo); | ||
136 | if (reg_in & gpo_o_bit(nr - NR_VX855_GPI)) | ||
137 | ret = 1; | ||
138 | } else { | ||
139 | reg_in = inl(vg->io_gpi); | ||
140 | if (reg_in & gpio_i_bit(nr - NR_VX855_GPInO)) | ||
141 | ret = 1; | ||
142 | } | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static void vx855gpio_set(struct gpio_chip *gpio, unsigned int nr, | ||
148 | int val) | ||
149 | { | ||
150 | struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio); | ||
151 | unsigned long flags; | ||
152 | u_int32_t reg_out; | ||
153 | |||
154 | /* True GPI cannot be switched to output mode */ | ||
155 | if (nr < NR_VX855_GPI) | ||
156 | return; | ||
157 | |||
158 | spin_lock_irqsave(&vg->lock, flags); | ||
159 | reg_out = inl(vg->io_gpo); | ||
160 | if (nr < NR_VX855_GPInO) { | ||
161 | if (val) | ||
162 | reg_out |= gpo_o_bit(nr - NR_VX855_GPI); | ||
163 | else | ||
164 | reg_out &= ~gpo_o_bit(nr - NR_VX855_GPI); | ||
165 | } else { | ||
166 | if (val) | ||
167 | reg_out |= gpio_o_bit(nr - NR_VX855_GPInO); | ||
168 | else | ||
169 | reg_out &= ~gpio_o_bit(nr - NR_VX855_GPInO); | ||
170 | } | ||
171 | outl(reg_out, vg->io_gpo); | ||
172 | spin_unlock_irqrestore(&vg->lock, flags); | ||
173 | } | ||
174 | |||
175 | static int vx855gpio_direction_output(struct gpio_chip *gpio, | ||
176 | unsigned int nr, int val) | ||
177 | { | ||
178 | /* True GPI cannot be switched to output mode */ | ||
179 | if (nr < NR_VX855_GPI) | ||
180 | return -EINVAL; | ||
181 | |||
182 | /* True GPO don't need to be switched to output mode, | ||
183 | * and GPIO are open-drain, i.e. also need no switching, | ||
184 | * so all we do is set the level */ | ||
185 | vx855gpio_set(gpio, nr, val); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static const char *vx855gpio_names[NR_VX855_GP] = { | ||
191 | "VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4", | ||
192 | "VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9", | ||
193 | "VX855_GPI10", "VX855_GPI11", "VX855_GPI12", "VX855_GPI13", | ||
194 | "VX855_GPO0", "VX855_GPO1", "VX855_GPO2", "VX855_GPO3", "VX855_GPO4", | ||
195 | "VX855_GPO5", "VX855_GPO6", "VX855_GPO7", "VX855_GPO8", "VX855_GPO9", | ||
196 | "VX855_GPO10", "VX855_GPO11", "VX855_GPO12", | ||
197 | "VX855_GPIO0", "VX855_GPIO1", "VX855_GPIO2", "VX855_GPIO3", | ||
198 | "VX855_GPIO4", "VX855_GPIO5", "VX855_GPIO6", "VX855_GPIO7", | ||
199 | "VX855_GPIO8", "VX855_GPIO9", "VX855_GPIO10", "VX855_GPIO11", | ||
200 | "VX855_GPIO12", "VX855_GPIO13", "VX855_GPIO14" | ||
201 | }; | ||
202 | |||
203 | static void vx855gpio_gpio_setup(struct vx855_gpio *vg) | ||
204 | { | ||
205 | struct gpio_chip *c = &vg->gpio; | ||
206 | |||
207 | c->label = "VX855 South Bridge"; | ||
208 | c->owner = THIS_MODULE; | ||
209 | c->direction_input = vx855gpio_direction_input; | ||
210 | c->direction_output = vx855gpio_direction_output; | ||
211 | c->get = vx855gpio_get; | ||
212 | c->set = vx855gpio_set; | ||
213 | c->dbg_show = NULL; | ||
214 | c->base = 0; | ||
215 | c->ngpio = NR_VX855_GP; | ||
216 | c->can_sleep = 0; | ||
217 | c->names = vx855gpio_names; | ||
218 | } | ||
219 | |||
220 | /* This platform device is ordinarily registered by the vx855 mfd driver */ | ||
221 | static __devinit int vx855gpio_probe(struct platform_device *pdev) | ||
222 | { | ||
223 | struct resource *res_gpi; | ||
224 | struct resource *res_gpo; | ||
225 | struct vx855_gpio *vg; | ||
226 | int ret; | ||
227 | |||
228 | res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
229 | res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1); | ||
230 | if (!res_gpi || !res_gpo) | ||
231 | return -EBUSY; | ||
232 | |||
233 | vg = kzalloc(sizeof(*vg), GFP_KERNEL); | ||
234 | if (!vg) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | platform_set_drvdata(pdev, vg); | ||
238 | |||
239 | dev_info(&pdev->dev, "found VX855 GPIO controller\n"); | ||
240 | vg->io_gpi = res_gpi->start; | ||
241 | vg->io_gpo = res_gpo->start; | ||
242 | spin_lock_init(&vg->lock); | ||
243 | |||
244 | /* | ||
245 | * A single byte is used to control various GPIO ports on the VX855, | ||
246 | * and in the case of the OLPC XO-1.5, some of those ports are used | ||
247 | * for switches that are interpreted and exposed through ACPI. ACPI | ||
248 | * will have reserved the region, so our own reservation will not | ||
249 | * succeed. Ignore and continue. | ||
250 | */ | ||
251 | |||
252 | if (!request_region(res_gpi->start, resource_size(res_gpi), | ||
253 | MODULE_NAME "_gpi")) | ||
254 | dev_warn(&pdev->dev, | ||
255 | "GPI I/O resource busy, probably claimed by ACPI\n"); | ||
256 | else | ||
257 | vg->gpi_reserved = true; | ||
258 | |||
259 | if (!request_region(res_gpo->start, resource_size(res_gpo), | ||
260 | MODULE_NAME "_gpo")) | ||
261 | dev_warn(&pdev->dev, | ||
262 | "GPO I/O resource busy, probably claimed by ACPI\n"); | ||
263 | else | ||
264 | vg->gpo_reserved = true; | ||
265 | |||
266 | vx855gpio_gpio_setup(vg); | ||
267 | |||
268 | ret = gpiochip_add(&vg->gpio); | ||
269 | if (ret) { | ||
270 | dev_err(&pdev->dev, "failed to register GPIOs\n"); | ||
271 | goto out_release; | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | |||
276 | out_release: | ||
277 | if (vg->gpi_reserved) | ||
278 | release_region(res_gpi->start, resource_size(res_gpi)); | ||
279 | if (vg->gpo_reserved) | ||
280 | release_region(res_gpi->start, resource_size(res_gpo)); | ||
281 | platform_set_drvdata(pdev, NULL); | ||
282 | kfree(vg); | ||
283 | return ret; | ||
284 | } | ||
285 | |||
286 | static int __devexit vx855gpio_remove(struct platform_device *pdev) | ||
287 | { | ||
288 | struct vx855_gpio *vg = platform_get_drvdata(pdev); | ||
289 | struct resource *res; | ||
290 | |||
291 | if (gpiochip_remove(&vg->gpio)) | ||
292 | dev_err(&pdev->dev, "unable to remove gpio_chip?\n"); | ||
293 | |||
294 | if (vg->gpi_reserved) { | ||
295 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
296 | release_region(res->start, resource_size(res)); | ||
297 | } | ||
298 | if (vg->gpo_reserved) { | ||
299 | res = platform_get_resource(pdev, IORESOURCE_IO, 1); | ||
300 | release_region(res->start, resource_size(res)); | ||
301 | } | ||
302 | |||
303 | platform_set_drvdata(pdev, NULL); | ||
304 | kfree(vg); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static struct platform_driver vx855gpio_driver = { | ||
309 | .driver = { | ||
310 | .name = MODULE_NAME, | ||
311 | .owner = THIS_MODULE, | ||
312 | }, | ||
313 | .probe = vx855gpio_probe, | ||
314 | .remove = __devexit_p(vx855gpio_remove), | ||
315 | }; | ||
316 | |||
317 | static int vx855gpio_init(void) | ||
318 | { | ||
319 | return platform_driver_register(&vx855gpio_driver); | ||
320 | } | ||
321 | module_init(vx855gpio_init); | ||
322 | |||
323 | static void vx855gpio_exit(void) | ||
324 | { | ||
325 | platform_driver_unregister(&vx855gpio_driver); | ||
326 | } | ||
327 | module_exit(vx855gpio_exit); | ||
328 | |||
329 | MODULE_LICENSE("GPL"); | ||
330 | MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>"); | ||
331 | MODULE_DESCRIPTION("GPIO driver for the VIA VX855 chipset"); | ||
332 | MODULE_ALIAS("platform:vx855_gpio"); | ||
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c index 2ac9a16d3daa..618398e4ed8e 100644 --- a/drivers/gpio/wm8994-gpio.c +++ b/drivers/gpio/wm8994-gpio.c | |||
@@ -140,6 +140,7 @@ static struct gpio_chip template_chip = { | |||
140 | .get = wm8994_gpio_get, | 140 | .get = wm8994_gpio_get, |
141 | .direction_output = wm8994_gpio_direction_out, | 141 | .direction_output = wm8994_gpio_direction_out, |
142 | .set = wm8994_gpio_set, | 142 | .set = wm8994_gpio_set, |
143 | .to_irq = wm8994_gpio_to_irq, | ||
143 | .dbg_show = wm8994_gpio_dbg_show, | 144 | .dbg_show = wm8994_gpio_dbg_show, |
144 | .can_sleep = 1, | 145 | .can_sleep = 1, |
145 | }; | 146 | }; |
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index 80af44608018..7de0ded4ccc3 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c | |||
@@ -27,27 +27,37 @@ | |||
27 | #include <linux/mfd/max8925.h> | 27 | #include <linux/mfd/max8925.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | 29 | ||
30 | #define SW_INPUT (1 << 7) /* 0/1 -- up/down */ | ||
30 | #define HARDRESET_EN (1 << 7) | 31 | #define HARDRESET_EN (1 << 7) |
31 | #define PWREN_EN (1 << 7) | 32 | #define PWREN_EN (1 << 7) |
32 | 33 | ||
33 | struct max8925_onkey_info { | 34 | struct max8925_onkey_info { |
34 | struct input_dev *idev; | 35 | struct input_dev *idev; |
35 | struct i2c_client *i2c; | 36 | struct i2c_client *i2c; |
36 | int irq; | 37 | struct device *dev; |
38 | int irq[2]; | ||
37 | }; | 39 | }; |
38 | 40 | ||
39 | /* | 41 | /* |
40 | * MAX8925 gives us an interrupt when ONKEY is held for 3 seconds. | 42 | * MAX8925 gives us an interrupt when ONKEY is pressed or released. |
41 | * max8925_set_bits() operates I2C bus and may sleep. So implement | 43 | * max8925_set_bits() operates I2C bus and may sleep. So implement |
42 | * it in thread IRQ handler. | 44 | * it in thread IRQ handler. |
43 | */ | 45 | */ |
44 | static irqreturn_t max8925_onkey_handler(int irq, void *data) | 46 | static irqreturn_t max8925_onkey_handler(int irq, void *data) |
45 | { | 47 | { |
46 | struct max8925_onkey_info *info = data; | 48 | struct max8925_onkey_info *info = data; |
47 | 49 | int ret, event; | |
48 | input_report_key(info->idev, KEY_POWER, 1); | 50 | |
51 | ret = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS); | ||
52 | if (ret & SW_INPUT) | ||
53 | event = 1; | ||
54 | else | ||
55 | event = 0; | ||
56 | input_report_key(info->idev, KEY_POWER, event); | ||
49 | input_sync(info->idev); | 57 | input_sync(info->idev); |
50 | 58 | ||
59 | dev_dbg(info->dev, "onkey event:%d\n", event); | ||
60 | |||
51 | /* Enable hardreset to halt if system isn't shutdown on time */ | 61 | /* Enable hardreset to halt if system isn't shutdown on time */ |
52 | max8925_set_bits(info->i2c, MAX8925_SYSENSEL, | 62 | max8925_set_bits(info->i2c, MAX8925_SYSENSEL, |
53 | HARDRESET_EN, HARDRESET_EN); | 63 | HARDRESET_EN, HARDRESET_EN); |
@@ -59,14 +69,42 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev) | |||
59 | { | 69 | { |
60 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | 70 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); |
61 | struct max8925_onkey_info *info; | 71 | struct max8925_onkey_info *info; |
62 | int error; | 72 | int irq[2], error; |
73 | |||
74 | irq[0] = platform_get_irq(pdev, 0); | ||
75 | if (irq[0] < 0) { | ||
76 | dev_err(&pdev->dev, "No IRQ resource!\n"); | ||
77 | return -EINVAL; | ||
78 | } | ||
79 | irq[1] = platform_get_irq(pdev, 1); | ||
80 | if (irq[1] < 0) { | ||
81 | dev_err(&pdev->dev, "No IRQ resource!\n"); | ||
82 | return -EINVAL; | ||
83 | } | ||
63 | 84 | ||
64 | info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); | 85 | info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); |
65 | if (!info) | 86 | if (!info) |
66 | return -ENOMEM; | 87 | return -ENOMEM; |
67 | 88 | ||
68 | info->i2c = chip->i2c; | 89 | info->i2c = chip->i2c; |
69 | info->irq = chip->irq_base + MAX8925_IRQ_GPM_SW_3SEC; | 90 | info->dev = &pdev->dev; |
91 | irq[0] += chip->irq_base; | ||
92 | irq[1] += chip->irq_base; | ||
93 | |||
94 | error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, | ||
95 | IRQF_ONESHOT, "onkey-down", info); | ||
96 | if (error < 0) { | ||
97 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
98 | irq[0], error); | ||
99 | goto out; | ||
100 | } | ||
101 | error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler, | ||
102 | IRQF_ONESHOT, "onkey-up", info); | ||
103 | if (error < 0) { | ||
104 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
105 | irq[1], error); | ||
106 | goto out_irq; | ||
107 | } | ||
70 | 108 | ||
71 | info->idev = input_allocate_device(); | 109 | info->idev = input_allocate_device(); |
72 | if (!info->idev) { | 110 | if (!info->idev) { |
@@ -79,32 +117,29 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev) | |||
79 | info->idev->phys = "max8925_on/input0"; | 117 | info->idev->phys = "max8925_on/input0"; |
80 | info->idev->id.bustype = BUS_I2C; | 118 | info->idev->id.bustype = BUS_I2C; |
81 | info->idev->dev.parent = &pdev->dev; | 119 | info->idev->dev.parent = &pdev->dev; |
120 | info->irq[0] = irq[0]; | ||
121 | info->irq[1] = irq[1]; | ||
82 | info->idev->evbit[0] = BIT_MASK(EV_KEY); | 122 | info->idev->evbit[0] = BIT_MASK(EV_KEY); |
83 | info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | 123 | info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); |
84 | 124 | ||
85 | error = request_threaded_irq(info->irq, NULL, max8925_onkey_handler, | ||
86 | IRQF_ONESHOT, "onkey", info); | ||
87 | if (error < 0) { | ||
88 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
89 | info->irq, error); | ||
90 | goto out_irq; | ||
91 | } | ||
92 | 125 | ||
93 | error = input_register_device(info->idev); | 126 | error = input_register_device(info->idev); |
94 | if (error) { | 127 | if (error) { |
95 | dev_err(chip->dev, "Can't register input device: %d\n", error); | 128 | dev_err(chip->dev, "Can't register input device: %d\n", error); |
96 | goto out; | 129 | goto out_reg; |
97 | } | 130 | } |
98 | 131 | ||
99 | platform_set_drvdata(pdev, info); | 132 | platform_set_drvdata(pdev, info); |
100 | 133 | ||
101 | return 0; | 134 | return 0; |
102 | 135 | ||
103 | out: | 136 | out_reg: |
104 | free_irq(info->irq, info); | ||
105 | out_irq: | ||
106 | input_free_device(info->idev); | 137 | input_free_device(info->idev); |
107 | out_input: | 138 | out_input: |
139 | free_irq(info->irq[1], info); | ||
140 | out_irq: | ||
141 | free_irq(info->irq[0], info); | ||
142 | out: | ||
108 | kfree(info); | 143 | kfree(info); |
109 | return error; | 144 | return error; |
110 | } | 145 | } |
@@ -113,7 +148,8 @@ static int __devexit max8925_onkey_remove(struct platform_device *pdev) | |||
113 | { | 148 | { |
114 | struct max8925_onkey_info *info = platform_get_drvdata(pdev); | 149 | struct max8925_onkey_info *info = platform_get_drvdata(pdev); |
115 | 150 | ||
116 | free_irq(info->irq, info); | 151 | free_irq(info->irq[0], info); |
152 | free_irq(info->irq[1], info); | ||
117 | input_unregister_device(info->idev); | 153 | input_unregister_device(info->idev); |
118 | kfree(info); | 154 | kfree(info); |
119 | 155 | ||
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index b7677106cff8..e672b44ee172 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -24,26 +24,17 @@ | |||
24 | #define LED_CURRENT_MASK (0x07 << 5) | 24 | #define LED_CURRENT_MASK (0x07 << 5) |
25 | 25 | ||
26 | #define LED_BLINK_ON_MASK (0x07) | 26 | #define LED_BLINK_ON_MASK (0x07) |
27 | #define LED_BLINK_PERIOD_MASK (0x0F << 3) | ||
28 | #define LED_BLINK_MASK (0x7F) | 27 | #define LED_BLINK_MASK (0x7F) |
29 | 28 | ||
30 | #define LED_BLINK_ON(x) ((x & 0x7) * 66 + 66) | 29 | #define LED_BLINK_ON(x) ((x & 0x7) * 66 + 66) |
31 | #define LED_BLINK_PERIOD(x) ((x & 0xF) * 530 + 930) | ||
32 | #define LED_BLINK_ON_MIN LED_BLINK_ON(0) | 30 | #define LED_BLINK_ON_MIN LED_BLINK_ON(0) |
33 | #define LED_BLINK_ON_MAX LED_BLINK_ON(0x7) | 31 | #define LED_BLINK_ON_MAX LED_BLINK_ON(0x7) |
34 | #define LED_BLINK_PERIOD_MIN LED_BLINK_PERIOD(0) | 32 | #define LED_ON_CONTINUOUS (0x0F << 3) |
35 | #define LED_BLINK_PERIOD_MAX LED_BLINK_PERIOD(0xE) | ||
36 | #define LED_TO_ON(x) ((x - 66) / 66) | 33 | #define LED_TO_ON(x) ((x - 66) / 66) |
37 | #define LED_TO_PERIOD(x) ((x - 930) / 530) | ||
38 | 34 | ||
39 | #define LED1_BLINK_EN (1 << 1) | 35 | #define LED1_BLINK_EN (1 << 1) |
40 | #define LED2_BLINK_EN (1 << 2) | 36 | #define LED2_BLINK_EN (1 << 2) |
41 | 37 | ||
42 | enum { | ||
43 | SET_BRIGHTNESS, | ||
44 | SET_BLINK, | ||
45 | }; | ||
46 | |||
47 | struct pm860x_led { | 38 | struct pm860x_led { |
48 | struct led_classdev cdev; | 39 | struct led_classdev cdev; |
49 | struct i2c_client *i2c; | 40 | struct i2c_client *i2c; |
@@ -54,8 +45,6 @@ struct pm860x_led { | |||
54 | 45 | ||
55 | int port; | 46 | int port; |
56 | int iset; | 47 | int iset; |
57 | int command; | ||
58 | int offset; | ||
59 | unsigned char brightness; | 48 | unsigned char brightness; |
60 | unsigned char current_brightness; | 49 | unsigned char current_brightness; |
61 | 50 | ||
@@ -95,10 +84,12 @@ static inline int __blink_off(int port) | |||
95 | case PM8606_LED1_GREEN: | 84 | case PM8606_LED1_GREEN: |
96 | case PM8606_LED1_BLUE: | 85 | case PM8606_LED1_BLUE: |
97 | ret = PM8606_RGB1A; | 86 | ret = PM8606_RGB1A; |
87 | break; | ||
98 | case PM8606_LED2_RED: | 88 | case PM8606_LED2_RED: |
99 | case PM8606_LED2_GREEN: | 89 | case PM8606_LED2_GREEN: |
100 | case PM8606_LED2_BLUE: | 90 | case PM8606_LED2_BLUE: |
101 | ret = PM8606_RGB2A; | 91 | ret = PM8606_RGB2A; |
92 | break; | ||
102 | } | 93 | } |
103 | return ret; | 94 | return ret; |
104 | } | 95 | } |
@@ -122,60 +113,35 @@ static inline int __blink_ctl_mask(int port) | |||
122 | return ret; | 113 | return ret; |
123 | } | 114 | } |
124 | 115 | ||
125 | static int __led_set(struct pm860x_led *led, int command) | 116 | static void pm860x_led_work(struct work_struct *work) |
126 | { | 117 | { |
127 | struct pm860x_chip *chip = led->chip; | ||
128 | int mask, ret; | ||
129 | 118 | ||
119 | struct pm860x_led *led; | ||
120 | struct pm860x_chip *chip; | ||
121 | int mask; | ||
122 | |||
123 | led = container_of(work, struct pm860x_led, work); | ||
124 | chip = led->chip; | ||
130 | mutex_lock(&led->lock); | 125 | mutex_lock(&led->lock); |
131 | switch (command) { | 126 | if ((led->current_brightness == 0) && led->brightness) { |
132 | case SET_BRIGHTNESS: | 127 | if (led->iset) { |
133 | if ((led->current_brightness == 0) && led->brightness) { | 128 | pm860x_set_bits(led->i2c, __led_off(led->port), |
134 | if (led->iset) { | 129 | LED_CURRENT_MASK, led->iset); |
135 | ret = pm860x_set_bits(led->i2c, led->offset, | ||
136 | LED_CURRENT_MASK, led->iset); | ||
137 | if (ret < 0) | ||
138 | goto out; | ||
139 | } | ||
140 | } else if (led->brightness == 0) { | ||
141 | ret = pm860x_set_bits(led->i2c, led->offset, | ||
142 | LED_CURRENT_MASK, 0); | ||
143 | if (ret < 0) | ||
144 | goto out; | ||
145 | } | 130 | } |
146 | ret = pm860x_set_bits(led->i2c, led->offset, LED_PWM_MASK, | ||
147 | led->brightness); | ||
148 | if (ret < 0) | ||
149 | goto out; | ||
150 | led->current_brightness = led->brightness; | ||
151 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", | ||
152 | led->offset, led->brightness); | ||
153 | break; | ||
154 | case SET_BLINK: | ||
155 | ret = pm860x_set_bits(led->i2c, led->offset, | ||
156 | LED_BLINK_MASK, led->blink_data); | ||
157 | if (ret < 0) | ||
158 | goto out; | ||
159 | |||
160 | mask = __blink_ctl_mask(led->port); | 131 | mask = __blink_ctl_mask(led->port); |
161 | ret = pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); | 132 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); |
162 | if (ret < 0) | 133 | } else if (led->brightness == 0) { |
163 | goto out; | 134 | pm860x_set_bits(led->i2c, __led_off(led->port), |
164 | dev_dbg(chip->dev, "LED blink delay on:%dms, delay off:%dms\n", | 135 | LED_CURRENT_MASK, 0); |
165 | led->blink_on, led->blink_off); | 136 | mask = __blink_ctl_mask(led->port); |
166 | break; | 137 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); |
167 | } | 138 | } |
168 | out: | 139 | pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, |
140 | led->brightness); | ||
141 | led->current_brightness = led->brightness; | ||
142 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", | ||
143 | __led_off(led->port), led->brightness); | ||
169 | mutex_unlock(&led->lock); | 144 | mutex_unlock(&led->lock); |
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static void pm860x_led_work(struct work_struct *work) | ||
174 | { | ||
175 | struct pm860x_led *led; | ||
176 | |||
177 | led = container_of(work, struct pm860x_led, work); | ||
178 | __led_set(led, led->command); | ||
179 | } | 145 | } |
180 | 146 | ||
181 | static void pm860x_led_set(struct led_classdev *cdev, | 147 | static void pm860x_led_set(struct led_classdev *cdev, |
@@ -183,42 +149,10 @@ static void pm860x_led_set(struct led_classdev *cdev, | |||
183 | { | 149 | { |
184 | struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev); | 150 | struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev); |
185 | 151 | ||
186 | data->offset = __led_off(data->port); | ||
187 | data->brightness = value >> 3; | 152 | data->brightness = value >> 3; |
188 | data->command = SET_BRIGHTNESS; | ||
189 | schedule_work(&data->work); | 153 | schedule_work(&data->work); |
190 | } | 154 | } |
191 | 155 | ||
192 | static int pm860x_led_blink(struct led_classdev *cdev, | ||
193 | unsigned long *delay_on, | ||
194 | unsigned long *delay_off) | ||
195 | { | ||
196 | struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev); | ||
197 | int period, on; | ||
198 | |||
199 | on = *delay_on; | ||
200 | if ((on < LED_BLINK_ON_MIN) || (on > LED_BLINK_ON_MAX)) | ||
201 | return -EINVAL; | ||
202 | |||
203 | on = LED_TO_ON(on); | ||
204 | on = LED_BLINK_ON(on); | ||
205 | |||
206 | period = on + *delay_off; | ||
207 | if ((period < LED_BLINK_PERIOD_MIN) || (period > LED_BLINK_PERIOD_MAX)) | ||
208 | return -EINVAL; | ||
209 | period = LED_TO_PERIOD(period); | ||
210 | period = LED_BLINK_PERIOD(period); | ||
211 | |||
212 | data->offset = __blink_off(data->port); | ||
213 | data->blink_on = on; | ||
214 | data->blink_off = period - data->blink_on; | ||
215 | data->blink_data = (period << 3) | data->blink_on; | ||
216 | data->command = SET_BLINK; | ||
217 | schedule_work(&data->work); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int __check_device(struct pm860x_led_pdata *pdata, char *name) | 156 | static int __check_device(struct pm860x_led_pdata *pdata, char *name) |
223 | { | 157 | { |
224 | struct pm860x_led_pdata *p = pdata; | 158 | struct pm860x_led_pdata *p = pdata; |
@@ -257,7 +191,7 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
257 | pm860x_pdata = pdev->dev.parent->platform_data; | 191 | pm860x_pdata = pdev->dev.parent->platform_data; |
258 | pdata = pm860x_pdata->led; | 192 | pdata = pm860x_pdata->led; |
259 | } else { | 193 | } else { |
260 | dev_err(&pdev->dev, "missing platform data\n"); | 194 | dev_err(&pdev->dev, "No platform data!\n"); |
261 | return -EINVAL; | 195 | return -EINVAL; |
262 | } | 196 | } |
263 | 197 | ||
@@ -279,7 +213,6 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
279 | data->current_brightness = 0; | 213 | data->current_brightness = 0; |
280 | data->cdev.name = data->name; | 214 | data->cdev.name = data->name; |
281 | data->cdev.brightness_set = pm860x_led_set; | 215 | data->cdev.brightness_set = pm860x_led_set; |
282 | data->cdev.blink_set = pm860x_led_blink; | ||
283 | mutex_init(&data->lock); | 216 | mutex_init(&data->lock); |
284 | INIT_WORK(&data->work, pm860x_led_work); | 217 | INIT_WORK(&data->work, pm860x_led_work); |
285 | 218 | ||
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 07933f3f7e4c..20895e7a99c9 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -158,6 +158,43 @@ static struct mfd_cell onkey_devs[] = { | |||
158 | }, | 158 | }, |
159 | }; | 159 | }; |
160 | 160 | ||
161 | static struct resource codec_resources[] = { | ||
162 | { | ||
163 | /* Headset microphone insertion or removal */ | ||
164 | .name = "micin", | ||
165 | .start = PM8607_IRQ_MICIN, | ||
166 | .end = PM8607_IRQ_MICIN, | ||
167 | .flags = IORESOURCE_IRQ, | ||
168 | }, { | ||
169 | /* Hook-switch press or release */ | ||
170 | .name = "hook", | ||
171 | .start = PM8607_IRQ_HOOK, | ||
172 | .end = PM8607_IRQ_HOOK, | ||
173 | .flags = IORESOURCE_IRQ, | ||
174 | }, { | ||
175 | /* Headset insertion or removal */ | ||
176 | .name = "headset", | ||
177 | .start = PM8607_IRQ_HEADSET, | ||
178 | .end = PM8607_IRQ_HEADSET, | ||
179 | .flags = IORESOURCE_IRQ, | ||
180 | }, { | ||
181 | /* Audio short */ | ||
182 | .name = "audio-short", | ||
183 | .start = PM8607_IRQ_AUDIO_SHORT, | ||
184 | .end = PM8607_IRQ_AUDIO_SHORT, | ||
185 | .flags = IORESOURCE_IRQ, | ||
186 | }, | ||
187 | }; | ||
188 | |||
189 | static struct mfd_cell codec_devs[] = { | ||
190 | { | ||
191 | .name = "88pm860x-codec", | ||
192 | .num_resources = ARRAY_SIZE(codec_resources), | ||
193 | .resources = &codec_resources[0], | ||
194 | .id = -1, | ||
195 | }, | ||
196 | }; | ||
197 | |||
161 | static struct resource regulator_resources[] = { | 198 | static struct resource regulator_resources[] = { |
162 | PM8607_REG_RESOURCE(BUCK1, BUCK1), | 199 | PM8607_REG_RESOURCE(BUCK1, BUCK1), |
163 | PM8607_REG_RESOURCE(BUCK2, BUCK2), | 200 | PM8607_REG_RESOURCE(BUCK2, BUCK2), |
@@ -608,10 +645,13 @@ static void __devinit device_8607_init(struct pm860x_chip *chip, | |||
608 | dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); | 645 | dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); |
609 | goto out; | 646 | goto out; |
610 | } | 647 | } |
611 | if ((ret & PM8607_VERSION_MASK) == PM8607_VERSION) | 648 | switch (ret & PM8607_VERSION_MASK) { |
649 | case 0x40: | ||
650 | case 0x50: | ||
612 | dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", | 651 | dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", |
613 | ret); | 652 | ret); |
614 | else { | 653 | break; |
654 | default: | ||
615 | dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " | 655 | dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " |
616 | "Chip ID: %02x\n", ret); | 656 | "Chip ID: %02x\n", ret); |
617 | goto out; | 657 | goto out; |
@@ -687,6 +727,13 @@ static void __devinit device_8607_init(struct pm860x_chip *chip, | |||
687 | goto out_dev; | 727 | goto out_dev; |
688 | } | 728 | } |
689 | 729 | ||
730 | ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], | ||
731 | ARRAY_SIZE(codec_devs), | ||
732 | &codec_resources[0], 0); | ||
733 | if (ret < 0) { | ||
734 | dev_err(chip->dev, "Failed to add codec subdev\n"); | ||
735 | goto out_dev; | ||
736 | } | ||
690 | return; | 737 | return; |
691 | out_dev: | 738 | out_dev: |
692 | mfd_remove_devices(chip->dev); | 739 | mfd_remove_devices(chip->dev); |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index db51ea1c6082..3a1493b8b5e5 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -75,7 +75,7 @@ config MFD_DAVINCI_VOICECODEC | |||
75 | 75 | ||
76 | config MFD_DM355EVM_MSP | 76 | config MFD_DM355EVM_MSP |
77 | bool "DaVinci DM355 EVM microcontroller" | 77 | bool "DaVinci DM355 EVM microcontroller" |
78 | depends on I2C && MACH_DAVINCI_DM355_EVM | 78 | depends on I2C=y && MACH_DAVINCI_DM355_EVM |
79 | help | 79 | help |
80 | This driver supports the MSP430 microcontroller used on these | 80 | This driver supports the MSP430 microcontroller used on these |
81 | boards. MSP430 firmware manages resets and power sequencing, | 81 | boards. MSP430 firmware manages resets and power sequencing, |
@@ -294,14 +294,15 @@ config MFD_MAX8925 | |||
294 | to use the functionality of the device. | 294 | to use the functionality of the device. |
295 | 295 | ||
296 | config MFD_MAX8998 | 296 | config MFD_MAX8998 |
297 | bool "Maxim Semiconductor MAX8998 PMIC Support" | 297 | bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" |
298 | depends on I2C=y | 298 | depends on I2C=y && GENERIC_HARDIRQS |
299 | select MFD_CORE | 299 | select MFD_CORE |
300 | help | 300 | help |
301 | Say yes here to support for Maxim Semiconductor MAX8998. This is | 301 | Say yes here to support for Maxim Semiconductor MAX8998 and |
302 | a Power Management IC. This driver provies common support for | 302 | National Semiconductor LP3974. This is a Power Management IC. |
303 | accessing the device, additional drivers must be enabled in order | 303 | This driver provies common support for accessing the device, |
304 | to use the functionality of the device. | 304 | additional drivers must be enabled in order to use the functionality |
305 | of the device. | ||
305 | 306 | ||
306 | config MFD_WM8400 | 307 | config MFD_WM8400 |
307 | tristate "Support Wolfson Microelectronics WM8400" | 308 | tristate "Support Wolfson Microelectronics WM8400" |
@@ -314,14 +315,30 @@ config MFD_WM8400 | |||
314 | the functionality of the device. | 315 | the functionality of the device. |
315 | 316 | ||
316 | config MFD_WM831X | 317 | config MFD_WM831X |
317 | bool "Support Wolfson Microelectronics WM831x/2x PMICs" | 318 | bool |
319 | depends on GENERIC_HARDIRQS | ||
320 | |||
321 | config MFD_WM831X_I2C | ||
322 | bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C" | ||
318 | select MFD_CORE | 323 | select MFD_CORE |
324 | select MFD_WM831X | ||
319 | depends on I2C=y && GENERIC_HARDIRQS | 325 | depends on I2C=y && GENERIC_HARDIRQS |
320 | help | 326 | help |
321 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs. | 327 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs |
322 | This driver provides common support for accessing the device, | 328 | when controlled using I2C. This driver provides common support |
323 | additional drivers must be enabled in order to use the | 329 | for accessing the device, additional drivers must be enabled in |
324 | functionality of the device. | 330 | order to use the functionality of the device. |
331 | |||
332 | config MFD_WM831X_SPI | ||
333 | bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI" | ||
334 | select MFD_CORE | ||
335 | select MFD_WM831X | ||
336 | depends on SPI_MASTER && GENERIC_HARDIRQS | ||
337 | help | ||
338 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs | ||
339 | when controlled using SPI. This driver provides common support | ||
340 | for accessing the device, additional drivers must be enabled in | ||
341 | order to use the functionality of the device. | ||
325 | 342 | ||
326 | config MFD_WM8350 | 343 | config MFD_WM8350 |
327 | bool | 344 | bool |
@@ -408,11 +425,16 @@ config MFD_PCF50633 | |||
408 | so that function-specific drivers can bind to them. | 425 | so that function-specific drivers can bind to them. |
409 | 426 | ||
410 | config MFD_MC13783 | 427 | config MFD_MC13783 |
411 | tristate "Support Freescale MC13783" | 428 | tristate |
429 | |||
430 | config MFD_MC13XXX | ||
431 | tristate "Support Freescale MC13783 and MC13892" | ||
412 | depends on SPI_MASTER | 432 | depends on SPI_MASTER |
413 | select MFD_CORE | 433 | select MFD_CORE |
434 | select MFD_MC13783 | ||
414 | help | 435 | help |
415 | Support for the Freescale (Atlas) MC13783 PMIC and audio CODEC. | 436 | Support for the Freescale (Atlas) PMIC and audio CODECs |
437 | MC13783 and MC13892. | ||
416 | This driver provides common support for accessing the device, | 438 | This driver provides common support for accessing the device, |
417 | additional drivers must be enabled in order to use the | 439 | additional drivers must be enabled in order to use the |
418 | functionality of the device. | 440 | functionality of the device. |
@@ -433,7 +455,7 @@ config PCF50633_GPIO | |||
433 | 455 | ||
434 | config ABX500_CORE | 456 | config ABX500_CORE |
435 | bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" | 457 | bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" |
436 | default y if ARCH_U300 | 458 | default y if ARCH_U300 || ARCH_U8500 |
437 | help | 459 | help |
438 | Say yes here if you have the ABX500 Mixed Signal IC family | 460 | Say yes here if you have the ABX500 Mixed Signal IC family |
439 | chips. This core driver expose register access functions. | 461 | chips. This core driver expose register access functions. |
@@ -444,6 +466,7 @@ config ABX500_CORE | |||
444 | config AB3100_CORE | 466 | config AB3100_CORE |
445 | bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" | 467 | bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" |
446 | depends on I2C=y && ABX500_CORE | 468 | depends on I2C=y && ABX500_CORE |
469 | select MFD_CORE | ||
447 | default y if ARCH_U300 | 470 | default y if ARCH_U300 |
448 | help | 471 | help |
449 | Select this to enable the AB3100 Mixed Signal IC core | 472 | Select this to enable the AB3100 Mixed Signal IC core |
@@ -473,14 +496,33 @@ config EZX_PCAP | |||
473 | 496 | ||
474 | config AB8500_CORE | 497 | config AB8500_CORE |
475 | bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" | 498 | bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" |
476 | depends on SPI=y && GENERIC_HARDIRQS | 499 | depends on GENERIC_HARDIRQS && ABX500_CORE && SPI_MASTER && ARCH_U8500 |
477 | select MFD_CORE | 500 | select MFD_CORE |
478 | help | 501 | help |
479 | Select this option to enable access to AB8500 power management | 502 | Select this option to enable access to AB8500 power management |
480 | chip. This connects to U8500 on the SSP/SPI bus and exports | 503 | chip. This connects to U8500 either on the SSP/SPI bus |
481 | read/write functions for the devices to get access to this chip. | 504 | or the I2C bus via PRCMU. It also adds the irq_chip |
505 | parts for handling the Mixed Signal chip events. | ||
482 | This chip embeds various other multimedia funtionalities as well. | 506 | This chip embeds various other multimedia funtionalities as well. |
483 | 507 | ||
508 | config AB8500_I2C_CORE | ||
509 | bool "AB8500 register access via PRCMU I2C" | ||
510 | depends on AB8500_CORE && UX500_SOC_DB8500 | ||
511 | default y | ||
512 | help | ||
513 | This enables register access to the AB8500 chip via PRCMU I2C. | ||
514 | The AB8500 chip can be accessed via SPI or I2C. On DB8500 hardware | ||
515 | the I2C bus is connected to the Power Reset | ||
516 | and Mangagement Unit, PRCMU. | ||
517 | |||
518 | config AB8500_DEBUG | ||
519 | bool "Enable debug info via debugfs" | ||
520 | depends on AB8500_CORE && DEBUG_FS | ||
521 | default y if DEBUG_FS | ||
522 | help | ||
523 | Select this option if you want debug information using the debug | ||
524 | filesystem, debugfs. | ||
525 | |||
484 | config AB3550_CORE | 526 | config AB3550_CORE |
485 | bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions" | 527 | bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions" |
486 | select MFD_CORE | 528 | select MFD_CORE |
@@ -542,8 +584,8 @@ config MFD_JZ4740_ADC | |||
542 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. | 584 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. |
543 | 585 | ||
544 | config MFD_TPS6586X | 586 | config MFD_TPS6586X |
545 | tristate "TPS6586x Power Management chips" | 587 | bool "TPS6586x Power Management chips" |
546 | depends on I2C && GPIOLIB | 588 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS |
547 | select MFD_CORE | 589 | select MFD_CORE |
548 | help | 590 | help |
549 | If you say yes here you get support for the TPS6586X series of | 591 | If you say yes here you get support for the TPS6586X series of |
@@ -555,6 +597,15 @@ config MFD_TPS6586X | |||
555 | This driver can also be built as a module. If so, the module | 597 | This driver can also be built as a module. If so, the module |
556 | will be called tps6586x. | 598 | will be called tps6586x. |
557 | 599 | ||
600 | config MFD_VX855 | ||
601 | tristate "Support for VIA VX855/VX875 integrated south bridge" | ||
602 | depends on PCI | ||
603 | select MFD_CORE | ||
604 | help | ||
605 | Say yes here to enable support for various functions of the | ||
606 | VIA VX855/VX875 south bridge. You will need to enable the vx855_spi | ||
607 | and/or vx855_gpio drivers for this to do anything useful. | ||
608 | |||
558 | endif # MFD_SUPPORT | 609 | endif # MFD_SUPPORT |
559 | 610 | ||
560 | menu "Multimedia Capabilities Port drivers" | 611 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index feaeeaeeddb7..f54b3659abbb 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -24,6 +24,8 @@ obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o | |||
24 | obj-$(CONFIG_MFD_WM8400) += wm8400-core.o | 24 | obj-$(CONFIG_MFD_WM8400) += wm8400-core.o |
25 | wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o | 25 | wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o |
26 | obj-$(CONFIG_MFD_WM831X) += wm831x.o | 26 | obj-$(CONFIG_MFD_WM831X) += wm831x.o |
27 | obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o | ||
28 | obj-$(CONFIG_MFD_WM831X_SPI) += wm831x-spi.o | ||
27 | wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o | 29 | wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o |
28 | wm8350-objs += wm8350-irq.o | 30 | wm8350-objs += wm8350-irq.o |
29 | obj-$(CONFIG_MFD_WM8350) += wm8350.o | 31 | obj-$(CONFIG_MFD_WM8350) += wm8350.o |
@@ -39,7 +41,7 @@ obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | |||
39 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | 41 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o |
40 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | 42 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o |
41 | 43 | ||
42 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o | 44 | obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o |
43 | 45 | ||
44 | obj-$(CONFIG_MFD_CORE) += mfd-core.o | 46 | obj-$(CONFIG_MFD_CORE) += mfd-core.o |
45 | 47 | ||
@@ -58,7 +60,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o | |||
58 | obj-$(CONFIG_PMIC_DA903X) += da903x.o | 60 | obj-$(CONFIG_PMIC_DA903X) += da903x.o |
59 | max8925-objs := max8925-core.o max8925-i2c.o | 61 | max8925-objs := max8925-core.o max8925-i2c.o |
60 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 62 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
61 | obj-$(CONFIG_MFD_MAX8998) += max8998.o | 63 | obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o |
62 | 64 | ||
63 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o | 65 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o |
64 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o | 66 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o |
@@ -69,6 +71,8 @@ obj-$(CONFIG_AB3100_CORE) += ab3100-core.o | |||
69 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o | 71 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o |
70 | obj-$(CONFIG_AB3550_CORE) += ab3550-core.o | 72 | obj-$(CONFIG_AB3550_CORE) += ab3550-core.o |
71 | obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-spi.o | 73 | obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-spi.o |
74 | obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o | ||
75 | obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o | ||
72 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o | 76 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o |
73 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | 77 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o |
74 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o | 78 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o |
@@ -76,3 +80,4 @@ obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o | |||
76 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o | 80 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o |
77 | obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o | 81 | obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o |
78 | obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o | 82 | obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o |
83 | obj-$(CONFIG_MFD_VX855) += vx855.o | ||
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index b048ecc56db9..4193af5f2743 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/debugfs.h> | 19 | #include <linux/debugfs.h> |
20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/mfd/core.h> | ||
22 | #include <linux/mfd/abx500.h> | 23 | #include <linux/mfd/abx500.h> |
23 | 24 | ||
24 | /* These are the only registers inside AB3100 used in this main file */ | 25 | /* These are the only registers inside AB3100 used in this main file */ |
@@ -146,7 +147,7 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100, | |||
146 | } | 147 | } |
147 | 148 | ||
148 | static int ab3100_get_register_interruptible(struct ab3100 *ab3100, | 149 | static int ab3100_get_register_interruptible(struct ab3100 *ab3100, |
149 | u8 reg, u8 *regval) | 150 | u8 reg, u8 *regval) |
150 | { | 151 | { |
151 | int err; | 152 | int err; |
152 | 153 | ||
@@ -202,7 +203,7 @@ static int ab3100_get_register_interruptible(struct ab3100 *ab3100, | |||
202 | } | 203 | } |
203 | 204 | ||
204 | static int get_register_interruptible(struct device *dev, u8 bank, u8 reg, | 205 | static int get_register_interruptible(struct device *dev, u8 bank, u8 reg, |
205 | u8 *value) | 206 | u8 *value) |
206 | { | 207 | { |
207 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | 208 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); |
208 | 209 | ||
@@ -666,7 +667,7 @@ struct ab3100_init_setting { | |||
666 | u8 setting; | 667 | u8 setting; |
667 | }; | 668 | }; |
668 | 669 | ||
669 | static const struct ab3100_init_setting __initconst | 670 | static const struct ab3100_init_setting __devinitconst |
670 | ab3100_init_settings[] = { | 671 | ab3100_init_settings[] = { |
671 | { | 672 | { |
672 | .abreg = AB3100_MCA, | 673 | .abreg = AB3100_MCA, |
@@ -713,7 +714,7 @@ ab3100_init_settings[] = { | |||
713 | }, | 714 | }, |
714 | }; | 715 | }; |
715 | 716 | ||
716 | static int __init ab3100_setup(struct ab3100 *ab3100) | 717 | static int __devinit ab3100_setup(struct ab3100 *ab3100) |
717 | { | 718 | { |
718 | int err = 0; | 719 | int err = 0; |
719 | int i; | 720 | int i; |
@@ -743,52 +744,64 @@ static int __init ab3100_setup(struct ab3100 *ab3100) | |||
743 | return err; | 744 | return err; |
744 | } | 745 | } |
745 | 746 | ||
746 | /* | 747 | /* The subdevices of the AB3100 */ |
747 | * Here we define all the platform devices that appear | 748 | static struct mfd_cell ab3100_devs[] = { |
748 | * as children of the AB3100. These are regular platform | 749 | { |
749 | * devices with the IORESOURCE_IO .start and .end set | 750 | .name = "ab3100-dac", |
750 | * to correspond to the internal AB3100 register range | 751 | .id = -1, |
751 | * mapping to the corresponding subdevice. | 752 | }, |
752 | */ | 753 | { |
753 | 754 | .name = "ab3100-leds", | |
754 | #define AB3100_DEVICE(devname, devid) \ | 755 | .id = -1, |
755 | static struct platform_device ab3100_##devname##_device = { \ | 756 | }, |
756 | .name = devid, \ | 757 | { |
757 | .id = -1, \ | 758 | .name = "ab3100-power", |
758 | } | 759 | .id = -1, |
759 | 760 | }, | |
760 | /* This lists all the subdevices */ | 761 | { |
761 | AB3100_DEVICE(dac, "ab3100-dac"); | 762 | .name = "ab3100-regulators", |
762 | AB3100_DEVICE(leds, "ab3100-leds"); | 763 | .id = -1, |
763 | AB3100_DEVICE(power, "ab3100-power"); | 764 | }, |
764 | AB3100_DEVICE(regulators, "ab3100-regulators"); | 765 | { |
765 | AB3100_DEVICE(sim, "ab3100-sim"); | 766 | .name = "ab3100-sim", |
766 | AB3100_DEVICE(uart, "ab3100-uart"); | 767 | .id = -1, |
767 | AB3100_DEVICE(rtc, "ab3100-rtc"); | 768 | }, |
768 | AB3100_DEVICE(charger, "ab3100-charger"); | 769 | { |
769 | AB3100_DEVICE(boost, "ab3100-boost"); | 770 | .name = "ab3100-uart", |
770 | AB3100_DEVICE(adc, "ab3100-adc"); | 771 | .id = -1, |
771 | AB3100_DEVICE(fuelgauge, "ab3100-fuelgauge"); | 772 | }, |
772 | AB3100_DEVICE(vibrator, "ab3100-vibrator"); | 773 | { |
773 | AB3100_DEVICE(otp, "ab3100-otp"); | 774 | .name = "ab3100-rtc", |
774 | AB3100_DEVICE(codec, "ab3100-codec"); | 775 | .id = -1, |
775 | 776 | }, | |
776 | static struct platform_device * | 777 | { |
777 | ab3100_platform_devs[] = { | 778 | .name = "ab3100-charger", |
778 | &ab3100_dac_device, | 779 | .id = -1, |
779 | &ab3100_leds_device, | 780 | }, |
780 | &ab3100_power_device, | 781 | { |
781 | &ab3100_regulators_device, | 782 | .name = "ab3100-boost", |
782 | &ab3100_sim_device, | 783 | .id = -1, |
783 | &ab3100_uart_device, | 784 | }, |
784 | &ab3100_rtc_device, | 785 | { |
785 | &ab3100_charger_device, | 786 | .name = "ab3100-adc", |
786 | &ab3100_boost_device, | 787 | .id = -1, |
787 | &ab3100_adc_device, | 788 | }, |
788 | &ab3100_fuelgauge_device, | 789 | { |
789 | &ab3100_vibrator_device, | 790 | .name = "ab3100-fuelgauge", |
790 | &ab3100_otp_device, | 791 | .id = -1, |
791 | &ab3100_codec_device, | 792 | }, |
793 | { | ||
794 | .name = "ab3100-vibrator", | ||
795 | .id = -1, | ||
796 | }, | ||
797 | { | ||
798 | .name = "ab3100-otp", | ||
799 | .id = -1, | ||
800 | }, | ||
801 | { | ||
802 | .name = "ab3100-codec", | ||
803 | .id = -1, | ||
804 | }, | ||
792 | }; | 805 | }; |
793 | 806 | ||
794 | struct ab_family_id { | 807 | struct ab_family_id { |
@@ -796,7 +809,7 @@ struct ab_family_id { | |||
796 | char *name; | 809 | char *name; |
797 | }; | 810 | }; |
798 | 811 | ||
799 | static const struct ab_family_id ids[] __initdata = { | 812 | static const struct ab_family_id ids[] __devinitdata = { |
800 | /* AB3100 */ | 813 | /* AB3100 */ |
801 | { | 814 | { |
802 | .id = 0xc0, | 815 | .id = 0xc0, |
@@ -850,8 +863,8 @@ static const struct ab_family_id ids[] __initdata = { | |||
850 | }, | 863 | }, |
851 | }; | 864 | }; |
852 | 865 | ||
853 | static int __init ab3100_probe(struct i2c_client *client, | 866 | static int __devinit ab3100_probe(struct i2c_client *client, |
854 | const struct i2c_device_id *id) | 867 | const struct i2c_device_id *id) |
855 | { | 868 | { |
856 | struct ab3100 *ab3100; | 869 | struct ab3100 *ab3100; |
857 | struct ab3100_platform_data *ab3100_plf_data = | 870 | struct ab3100_platform_data *ab3100_plf_data = |
@@ -935,18 +948,14 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
935 | if (err) | 948 | if (err) |
936 | goto exit_no_ops; | 949 | goto exit_no_ops; |
937 | 950 | ||
938 | /* Set parent and a pointer back to the container in device data */ | 951 | /* Set up and register the platform devices. */ |
939 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) { | 952 | for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) { |
940 | ab3100_platform_devs[i]->dev.parent = | 953 | ab3100_devs[i].platform_data = ab3100_plf_data; |
941 | &client->dev; | 954 | ab3100_devs[i].data_size = sizeof(struct ab3100_platform_data); |
942 | ab3100_platform_devs[i]->dev.platform_data = | ||
943 | ab3100_plf_data; | ||
944 | platform_set_drvdata(ab3100_platform_devs[i], ab3100); | ||
945 | } | 955 | } |
946 | 956 | ||
947 | /* Register the platform devices */ | 957 | err = mfd_add_devices(&client->dev, 0, ab3100_devs, |
948 | platform_add_devices(ab3100_platform_devs, | 958 | ARRAY_SIZE(ab3100_devs), NULL, 0); |
949 | ARRAY_SIZE(ab3100_platform_devs)); | ||
950 | 959 | ||
951 | ab3100_setup_debugfs(ab3100); | 960 | ab3100_setup_debugfs(ab3100); |
952 | 961 | ||
@@ -962,14 +971,12 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
962 | return err; | 971 | return err; |
963 | } | 972 | } |
964 | 973 | ||
965 | static int __exit ab3100_remove(struct i2c_client *client) | 974 | static int __devexit ab3100_remove(struct i2c_client *client) |
966 | { | 975 | { |
967 | struct ab3100 *ab3100 = i2c_get_clientdata(client); | 976 | struct ab3100 *ab3100 = i2c_get_clientdata(client); |
968 | int i; | ||
969 | 977 | ||
970 | /* Unregister subdevices */ | 978 | /* Unregister subdevices */ |
971 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) | 979 | mfd_remove_devices(&client->dev); |
972 | platform_device_unregister(ab3100_platform_devs[i]); | ||
973 | 980 | ||
974 | ab3100_remove_debugfs(); | 981 | ab3100_remove_debugfs(); |
975 | i2c_unregister_device(ab3100->testreg_client); | 982 | i2c_unregister_device(ab3100->testreg_client); |
@@ -996,7 +1003,7 @@ static struct i2c_driver ab3100_driver = { | |||
996 | }, | 1003 | }, |
997 | .id_table = ab3100_id, | 1004 | .id_table = ab3100_id, |
998 | .probe = ab3100_probe, | 1005 | .probe = ab3100_probe, |
999 | .remove = __exit_p(ab3100_remove), | 1006 | .remove = __devexit_p(ab3100_remove), |
1000 | }; | 1007 | }; |
1001 | 1008 | ||
1002 | static int __init ab3100_i2c_init(void) | 1009 | static int __init ab3100_i2c_init(void) |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index b8c4b80e4c43..dbe1c93c1af3 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * License Terms: GNU General Public License v2 | 4 | * License Terms: GNU General Public License v2 |
5 | * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | 5 | * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> |
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> | 6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> |
7 | * Changes: Mattias Wallin <mattias.wallin@stericsson.com> | ||
7 | */ | 8 | */ |
8 | 9 | ||
9 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -15,6 +16,7 @@ | |||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
17 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
19 | #include <linux/mfd/abx500.h> | ||
18 | #include <linux/mfd/ab8500.h> | 20 | #include <linux/mfd/ab8500.h> |
19 | #include <linux/regulator/ab8500.h> | 21 | #include <linux/regulator/ab8500.h> |
20 | 22 | ||
@@ -22,71 +24,71 @@ | |||
22 | * Interrupt register offsets | 24 | * Interrupt register offsets |
23 | * Bank : 0x0E | 25 | * Bank : 0x0E |
24 | */ | 26 | */ |
25 | #define AB8500_IT_SOURCE1_REG 0x0E00 | 27 | #define AB8500_IT_SOURCE1_REG 0x00 |
26 | #define AB8500_IT_SOURCE2_REG 0x0E01 | 28 | #define AB8500_IT_SOURCE2_REG 0x01 |
27 | #define AB8500_IT_SOURCE3_REG 0x0E02 | 29 | #define AB8500_IT_SOURCE3_REG 0x02 |
28 | #define AB8500_IT_SOURCE4_REG 0x0E03 | 30 | #define AB8500_IT_SOURCE4_REG 0x03 |
29 | #define AB8500_IT_SOURCE5_REG 0x0E04 | 31 | #define AB8500_IT_SOURCE5_REG 0x04 |
30 | #define AB8500_IT_SOURCE6_REG 0x0E05 | 32 | #define AB8500_IT_SOURCE6_REG 0x05 |
31 | #define AB8500_IT_SOURCE7_REG 0x0E06 | 33 | #define AB8500_IT_SOURCE7_REG 0x06 |
32 | #define AB8500_IT_SOURCE8_REG 0x0E07 | 34 | #define AB8500_IT_SOURCE8_REG 0x07 |
33 | #define AB8500_IT_SOURCE19_REG 0x0E12 | 35 | #define AB8500_IT_SOURCE19_REG 0x12 |
34 | #define AB8500_IT_SOURCE20_REG 0x0E13 | 36 | #define AB8500_IT_SOURCE20_REG 0x13 |
35 | #define AB8500_IT_SOURCE21_REG 0x0E14 | 37 | #define AB8500_IT_SOURCE21_REG 0x14 |
36 | #define AB8500_IT_SOURCE22_REG 0x0E15 | 38 | #define AB8500_IT_SOURCE22_REG 0x15 |
37 | #define AB8500_IT_SOURCE23_REG 0x0E16 | 39 | #define AB8500_IT_SOURCE23_REG 0x16 |
38 | #define AB8500_IT_SOURCE24_REG 0x0E17 | 40 | #define AB8500_IT_SOURCE24_REG 0x17 |
39 | 41 | ||
40 | /* | 42 | /* |
41 | * latch registers | 43 | * latch registers |
42 | */ | 44 | */ |
43 | #define AB8500_IT_LATCH1_REG 0x0E20 | 45 | #define AB8500_IT_LATCH1_REG 0x20 |
44 | #define AB8500_IT_LATCH2_REG 0x0E21 | 46 | #define AB8500_IT_LATCH2_REG 0x21 |
45 | #define AB8500_IT_LATCH3_REG 0x0E22 | 47 | #define AB8500_IT_LATCH3_REG 0x22 |
46 | #define AB8500_IT_LATCH4_REG 0x0E23 | 48 | #define AB8500_IT_LATCH4_REG 0x23 |
47 | #define AB8500_IT_LATCH5_REG 0x0E24 | 49 | #define AB8500_IT_LATCH5_REG 0x24 |
48 | #define AB8500_IT_LATCH6_REG 0x0E25 | 50 | #define AB8500_IT_LATCH6_REG 0x25 |
49 | #define AB8500_IT_LATCH7_REG 0x0E26 | 51 | #define AB8500_IT_LATCH7_REG 0x26 |
50 | #define AB8500_IT_LATCH8_REG 0x0E27 | 52 | #define AB8500_IT_LATCH8_REG 0x27 |
51 | #define AB8500_IT_LATCH9_REG 0x0E28 | 53 | #define AB8500_IT_LATCH9_REG 0x28 |
52 | #define AB8500_IT_LATCH10_REG 0x0E29 | 54 | #define AB8500_IT_LATCH10_REG 0x29 |
53 | #define AB8500_IT_LATCH19_REG 0x0E32 | 55 | #define AB8500_IT_LATCH19_REG 0x32 |
54 | #define AB8500_IT_LATCH20_REG 0x0E33 | 56 | #define AB8500_IT_LATCH20_REG 0x33 |
55 | #define AB8500_IT_LATCH21_REG 0x0E34 | 57 | #define AB8500_IT_LATCH21_REG 0x34 |
56 | #define AB8500_IT_LATCH22_REG 0x0E35 | 58 | #define AB8500_IT_LATCH22_REG 0x35 |
57 | #define AB8500_IT_LATCH23_REG 0x0E36 | 59 | #define AB8500_IT_LATCH23_REG 0x36 |
58 | #define AB8500_IT_LATCH24_REG 0x0E37 | 60 | #define AB8500_IT_LATCH24_REG 0x37 |
59 | 61 | ||
60 | /* | 62 | /* |
61 | * mask registers | 63 | * mask registers |
62 | */ | 64 | */ |
63 | 65 | ||
64 | #define AB8500_IT_MASK1_REG 0x0E40 | 66 | #define AB8500_IT_MASK1_REG 0x40 |
65 | #define AB8500_IT_MASK2_REG 0x0E41 | 67 | #define AB8500_IT_MASK2_REG 0x41 |
66 | #define AB8500_IT_MASK3_REG 0x0E42 | 68 | #define AB8500_IT_MASK3_REG 0x42 |
67 | #define AB8500_IT_MASK4_REG 0x0E43 | 69 | #define AB8500_IT_MASK4_REG 0x43 |
68 | #define AB8500_IT_MASK5_REG 0x0E44 | 70 | #define AB8500_IT_MASK5_REG 0x44 |
69 | #define AB8500_IT_MASK6_REG 0x0E45 | 71 | #define AB8500_IT_MASK6_REG 0x45 |
70 | #define AB8500_IT_MASK7_REG 0x0E46 | 72 | #define AB8500_IT_MASK7_REG 0x46 |
71 | #define AB8500_IT_MASK8_REG 0x0E47 | 73 | #define AB8500_IT_MASK8_REG 0x47 |
72 | #define AB8500_IT_MASK9_REG 0x0E48 | 74 | #define AB8500_IT_MASK9_REG 0x48 |
73 | #define AB8500_IT_MASK10_REG 0x0E49 | 75 | #define AB8500_IT_MASK10_REG 0x49 |
74 | #define AB8500_IT_MASK11_REG 0x0E4A | 76 | #define AB8500_IT_MASK11_REG 0x4A |
75 | #define AB8500_IT_MASK12_REG 0x0E4B | 77 | #define AB8500_IT_MASK12_REG 0x4B |
76 | #define AB8500_IT_MASK13_REG 0x0E4C | 78 | #define AB8500_IT_MASK13_REG 0x4C |
77 | #define AB8500_IT_MASK14_REG 0x0E4D | 79 | #define AB8500_IT_MASK14_REG 0x4D |
78 | #define AB8500_IT_MASK15_REG 0x0E4E | 80 | #define AB8500_IT_MASK15_REG 0x4E |
79 | #define AB8500_IT_MASK16_REG 0x0E4F | 81 | #define AB8500_IT_MASK16_REG 0x4F |
80 | #define AB8500_IT_MASK17_REG 0x0E50 | 82 | #define AB8500_IT_MASK17_REG 0x50 |
81 | #define AB8500_IT_MASK18_REG 0x0E51 | 83 | #define AB8500_IT_MASK18_REG 0x51 |
82 | #define AB8500_IT_MASK19_REG 0x0E52 | 84 | #define AB8500_IT_MASK19_REG 0x52 |
83 | #define AB8500_IT_MASK20_REG 0x0E53 | 85 | #define AB8500_IT_MASK20_REG 0x53 |
84 | #define AB8500_IT_MASK21_REG 0x0E54 | 86 | #define AB8500_IT_MASK21_REG 0x54 |
85 | #define AB8500_IT_MASK22_REG 0x0E55 | 87 | #define AB8500_IT_MASK22_REG 0x55 |
86 | #define AB8500_IT_MASK23_REG 0x0E56 | 88 | #define AB8500_IT_MASK23_REG 0x56 |
87 | #define AB8500_IT_MASK24_REG 0x0E57 | 89 | #define AB8500_IT_MASK24_REG 0x57 |
88 | 90 | ||
89 | #define AB8500_REV_REG 0x1080 | 91 | #define AB8500_REV_REG 0x80 |
90 | 92 | ||
91 | /* | 93 | /* |
92 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt | 94 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt |
@@ -99,96 +101,132 @@ static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { | |||
99 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21, | 101 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21, |
100 | }; | 102 | }; |
101 | 103 | ||
102 | static int __ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data) | 104 | static int ab8500_get_chip_id(struct device *dev) |
105 | { | ||
106 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
107 | return (int)ab8500->chip_id; | ||
108 | } | ||
109 | |||
110 | static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, | ||
111 | u8 reg, u8 data) | ||
103 | { | 112 | { |
104 | int ret; | 113 | int ret; |
114 | /* | ||
115 | * Put the u8 bank and u8 register together into a an u16. | ||
116 | * The bank on higher 8 bits and register in lower 8 bits. | ||
117 | * */ | ||
118 | u16 addr = ((u16)bank) << 8 | reg; | ||
105 | 119 | ||
106 | dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); | 120 | dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); |
107 | 121 | ||
122 | ret = mutex_lock_interruptible(&ab8500->lock); | ||
123 | if (ret) | ||
124 | return ret; | ||
125 | |||
108 | ret = ab8500->write(ab8500, addr, data); | 126 | ret = ab8500->write(ab8500, addr, data); |
109 | if (ret < 0) | 127 | if (ret < 0) |
110 | dev_err(ab8500->dev, "failed to write reg %#x: %d\n", | 128 | dev_err(ab8500->dev, "failed to write reg %#x: %d\n", |
111 | addr, ret); | 129 | addr, ret); |
130 | mutex_unlock(&ab8500->lock); | ||
112 | 131 | ||
113 | return ret; | 132 | return ret; |
114 | } | 133 | } |
115 | 134 | ||
116 | /** | 135 | static int ab8500_set_register(struct device *dev, u8 bank, |
117 | * ab8500_write() - write an AB8500 register | 136 | u8 reg, u8 value) |
118 | * @ab8500: device to write to | ||
119 | * @addr: address of the register | ||
120 | * @data: value to write | ||
121 | */ | ||
122 | int ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data) | ||
123 | { | 137 | { |
124 | int ret; | 138 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); |
125 | 139 | ||
126 | mutex_lock(&ab8500->lock); | 140 | return set_register_interruptible(ab8500, bank, reg, value); |
127 | ret = __ab8500_write(ab8500, addr, data); | ||
128 | mutex_unlock(&ab8500->lock); | ||
129 | |||
130 | return ret; | ||
131 | } | 141 | } |
132 | EXPORT_SYMBOL_GPL(ab8500_write); | ||
133 | 142 | ||
134 | static int __ab8500_read(struct ab8500 *ab8500, u16 addr) | 143 | static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, |
144 | u8 reg, u8 *value) | ||
135 | { | 145 | { |
136 | int ret; | 146 | int ret; |
147 | /* put the u8 bank and u8 reg together into a an u16. | ||
148 | * bank on higher 8 bits and reg in lower */ | ||
149 | u16 addr = ((u16)bank) << 8 | reg; | ||
150 | |||
151 | ret = mutex_lock_interruptible(&ab8500->lock); | ||
152 | if (ret) | ||
153 | return ret; | ||
137 | 154 | ||
138 | ret = ab8500->read(ab8500, addr); | 155 | ret = ab8500->read(ab8500, addr); |
139 | if (ret < 0) | 156 | if (ret < 0) |
140 | dev_err(ab8500->dev, "failed to read reg %#x: %d\n", | 157 | dev_err(ab8500->dev, "failed to read reg %#x: %d\n", |
141 | addr, ret); | 158 | addr, ret); |
159 | else | ||
160 | *value = ret; | ||
142 | 161 | ||
162 | mutex_unlock(&ab8500->lock); | ||
143 | dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); | 163 | dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); |
144 | 164 | ||
145 | return ret; | 165 | return ret; |
146 | } | 166 | } |
147 | 167 | ||
148 | /** | 168 | static int ab8500_get_register(struct device *dev, u8 bank, |
149 | * ab8500_read() - read an AB8500 register | 169 | u8 reg, u8 *value) |
150 | * @ab8500: device to read from | ||
151 | * @addr: address of the register | ||
152 | */ | ||
153 | int ab8500_read(struct ab8500 *ab8500, u16 addr) | ||
154 | { | 170 | { |
155 | int ret; | 171 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); |
156 | |||
157 | mutex_lock(&ab8500->lock); | ||
158 | ret = __ab8500_read(ab8500, addr); | ||
159 | mutex_unlock(&ab8500->lock); | ||
160 | 172 | ||
161 | return ret; | 173 | return get_register_interruptible(ab8500, bank, reg, value); |
162 | } | 174 | } |
163 | EXPORT_SYMBOL_GPL(ab8500_read); | 175 | |
164 | 176 | static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, | |
165 | /** | 177 | u8 reg, u8 bitmask, u8 bitvalues) |
166 | * ab8500_set_bits() - set a bitfield in an AB8500 register | ||
167 | * @ab8500: device to read from | ||
168 | * @addr: address of the register | ||
169 | * @mask: mask of the bitfield to modify | ||
170 | * @data: value to set to the bitfield | ||
171 | */ | ||
172 | int ab8500_set_bits(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data) | ||
173 | { | 178 | { |
174 | int ret; | 179 | int ret; |
180 | u8 data; | ||
181 | /* put the u8 bank and u8 reg together into a an u16. | ||
182 | * bank on higher 8 bits and reg in lower */ | ||
183 | u16 addr = ((u16)bank) << 8 | reg; | ||
175 | 184 | ||
176 | mutex_lock(&ab8500->lock); | 185 | ret = mutex_lock_interruptible(&ab8500->lock); |
186 | if (ret) | ||
187 | return ret; | ||
177 | 188 | ||
178 | ret = __ab8500_read(ab8500, addr); | 189 | ret = ab8500->read(ab8500, addr); |
179 | if (ret < 0) | 190 | if (ret < 0) { |
191 | dev_err(ab8500->dev, "failed to read reg %#x: %d\n", | ||
192 | addr, ret); | ||
180 | goto out; | 193 | goto out; |
194 | } | ||
181 | 195 | ||
182 | ret &= ~mask; | 196 | data = (u8)ret; |
183 | ret |= data; | 197 | data = (~bitmask & data) | (bitmask & bitvalues); |
184 | 198 | ||
185 | ret = __ab8500_write(ab8500, addr, ret); | 199 | ret = ab8500->write(ab8500, addr, data); |
200 | if (ret < 0) | ||
201 | dev_err(ab8500->dev, "failed to write reg %#x: %d\n", | ||
202 | addr, ret); | ||
186 | 203 | ||
204 | dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data); | ||
187 | out: | 205 | out: |
188 | mutex_unlock(&ab8500->lock); | 206 | mutex_unlock(&ab8500->lock); |
189 | return ret; | 207 | return ret; |
190 | } | 208 | } |
191 | EXPORT_SYMBOL_GPL(ab8500_set_bits); | 209 | |
210 | static int ab8500_mask_and_set_register(struct device *dev, | ||
211 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) | ||
212 | { | ||
213 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
214 | |||
215 | return mask_and_set_register_interruptible(ab8500, bank, reg, | ||
216 | bitmask, bitvalues); | ||
217 | |||
218 | } | ||
219 | |||
220 | static struct abx500_ops ab8500_ops = { | ||
221 | .get_chip_id = ab8500_get_chip_id, | ||
222 | .get_register = ab8500_get_register, | ||
223 | .set_register = ab8500_set_register, | ||
224 | .get_register_page = NULL, | ||
225 | .set_register_page = NULL, | ||
226 | .mask_and_set_register = ab8500_mask_and_set_register, | ||
227 | .event_registers_startup_state_get = NULL, | ||
228 | .startup_irq_enabled = NULL, | ||
229 | }; | ||
192 | 230 | ||
193 | static void ab8500_irq_lock(unsigned int irq) | 231 | static void ab8500_irq_lock(unsigned int irq) |
194 | { | 232 | { |
@@ -213,7 +251,7 @@ static void ab8500_irq_sync_unlock(unsigned int irq) | |||
213 | ab8500->oldmask[i] = new; | 251 | ab8500->oldmask[i] = new; |
214 | 252 | ||
215 | reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; | 253 | reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; |
216 | ab8500_write(ab8500, reg, new); | 254 | set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); |
217 | } | 255 | } |
218 | 256 | ||
219 | mutex_unlock(&ab8500->irq_lock); | 257 | mutex_unlock(&ab8500->irq_lock); |
@@ -257,9 +295,11 @@ static irqreturn_t ab8500_irq(int irq, void *dev) | |||
257 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { | 295 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { |
258 | int regoffset = ab8500_irq_regoffset[i]; | 296 | int regoffset = ab8500_irq_regoffset[i]; |
259 | int status; | 297 | int status; |
298 | u8 value; | ||
260 | 299 | ||
261 | status = ab8500_read(ab8500, AB8500_IT_LATCH1_REG + regoffset); | 300 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, |
262 | if (status <= 0) | 301 | AB8500_IT_LATCH1_REG + regoffset, &value); |
302 | if (status < 0 || value == 0) | ||
263 | continue; | 303 | continue; |
264 | 304 | ||
265 | do { | 305 | do { |
@@ -267,8 +307,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev) | |||
267 | int line = i * 8 + bit; | 307 | int line = i * 8 + bit; |
268 | 308 | ||
269 | handle_nested_irq(ab8500->irq_base + line); | 309 | handle_nested_irq(ab8500->irq_base + line); |
270 | status &= ~(1 << bit); | 310 | value &= ~(1 << bit); |
271 | } while (status); | 311 | } while (value); |
272 | } | 312 | } |
273 | 313 | ||
274 | return IRQ_HANDLED; | 314 | return IRQ_HANDLED; |
@@ -354,6 +394,11 @@ static struct resource ab8500_poweronkey_db_resources[] = { | |||
354 | }; | 394 | }; |
355 | 395 | ||
356 | static struct mfd_cell ab8500_devs[] = { | 396 | static struct mfd_cell ab8500_devs[] = { |
397 | #ifdef CONFIG_DEBUG_FS | ||
398 | { | ||
399 | .name = "ab8500-debug", | ||
400 | }, | ||
401 | #endif | ||
357 | { | 402 | { |
358 | .name = "ab8500-gpadc", | 403 | .name = "ab8500-gpadc", |
359 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), | 404 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), |
@@ -364,10 +409,21 @@ static struct mfd_cell ab8500_devs[] = { | |||
364 | .num_resources = ARRAY_SIZE(ab8500_rtc_resources), | 409 | .num_resources = ARRAY_SIZE(ab8500_rtc_resources), |
365 | .resources = ab8500_rtc_resources, | 410 | .resources = ab8500_rtc_resources, |
366 | }, | 411 | }, |
412 | { | ||
413 | .name = "ab8500-pwm", | ||
414 | .id = 1, | ||
415 | }, | ||
416 | { | ||
417 | .name = "ab8500-pwm", | ||
418 | .id = 2, | ||
419 | }, | ||
420 | { | ||
421 | .name = "ab8500-pwm", | ||
422 | .id = 3, | ||
423 | }, | ||
367 | { .name = "ab8500-charger", }, | 424 | { .name = "ab8500-charger", }, |
368 | { .name = "ab8500-audio", }, | 425 | { .name = "ab8500-audio", }, |
369 | { .name = "ab8500-usb", }, | 426 | { .name = "ab8500-usb", }, |
370 | { .name = "ab8500-pwm", }, | ||
371 | { .name = "ab8500-regulator", }, | 427 | { .name = "ab8500-regulator", }, |
372 | { | 428 | { |
373 | .name = "ab8500-poweron-key", | 429 | .name = "ab8500-poweron-key", |
@@ -381,6 +437,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
381 | struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); | 437 | struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); |
382 | int ret; | 438 | int ret; |
383 | int i; | 439 | int i; |
440 | u8 value; | ||
384 | 441 | ||
385 | if (plat) | 442 | if (plat) |
386 | ab8500->irq_base = plat->irq_base; | 443 | ab8500->irq_base = plat->irq_base; |
@@ -388,7 +445,8 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
388 | mutex_init(&ab8500->lock); | 445 | mutex_init(&ab8500->lock); |
389 | mutex_init(&ab8500->irq_lock); | 446 | mutex_init(&ab8500->irq_lock); |
390 | 447 | ||
391 | ret = ab8500_read(ab8500, AB8500_REV_REG); | 448 | ret = get_register_interruptible(ab8500, AB8500_MISC, |
449 | AB8500_REV_REG, &value); | ||
392 | if (ret < 0) | 450 | if (ret < 0) |
393 | return ret; | 451 | return ret; |
394 | 452 | ||
@@ -397,28 +455,37 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
397 | * 0x10 - Cut 1.0 | 455 | * 0x10 - Cut 1.0 |
398 | * 0x11 - Cut 1.1 | 456 | * 0x11 - Cut 1.1 |
399 | */ | 457 | */ |
400 | if (ret == 0x0 || ret == 0x10 || ret == 0x11) { | 458 | if (value == 0x0 || value == 0x10 || value == 0x11) { |
401 | ab8500->revision = ret; | 459 | ab8500->revision = value; |
402 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", ret); | 460 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); |
403 | } else { | 461 | } else { |
404 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", ret); | 462 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); |
405 | return -EINVAL; | 463 | return -EINVAL; |
406 | } | 464 | } |
465 | ab8500->chip_id = value; | ||
407 | 466 | ||
408 | if (plat && plat->init) | 467 | if (plat && plat->init) |
409 | plat->init(ab8500); | 468 | plat->init(ab8500); |
410 | 469 | ||
411 | /* Clear and mask all interrupts */ | 470 | /* Clear and mask all interrupts */ |
412 | for (i = 0; i < 10; i++) { | 471 | for (i = 0; i < 10; i++) { |
413 | ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); | 472 | get_register_interruptible(ab8500, AB8500_INTERRUPT, |
414 | ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); | 473 | AB8500_IT_LATCH1_REG + i, &value); |
474 | set_register_interruptible(ab8500, AB8500_INTERRUPT, | ||
475 | AB8500_IT_MASK1_REG + i, 0xff); | ||
415 | } | 476 | } |
416 | 477 | ||
417 | for (i = 18; i < 24; i++) { | 478 | for (i = 18; i < 24; i++) { |
418 | ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); | 479 | get_register_interruptible(ab8500, AB8500_INTERRUPT, |
419 | ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); | 480 | AB8500_IT_LATCH1_REG + i, &value); |
481 | set_register_interruptible(ab8500, AB8500_INTERRUPT, | ||
482 | AB8500_IT_MASK1_REG + i, 0xff); | ||
420 | } | 483 | } |
421 | 484 | ||
485 | ret = abx500_register_ops(ab8500->dev, &ab8500_ops); | ||
486 | if (ret) | ||
487 | return ret; | ||
488 | |||
422 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) | 489 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) |
423 | ab8500->mask[i] = ab8500->oldmask[i] = 0xff; | 490 | ab8500->mask[i] = ab8500->oldmask[i] = 0xff; |
424 | 491 | ||
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c new file mode 100644 index 000000000000..8d1e05a39815 --- /dev/null +++ b/drivers/mfd/ab8500-debugfs.c | |||
@@ -0,0 +1,652 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson. | ||
5 | * License Terms: GNU General Public License v2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/seq_file.h> | ||
9 | #include <linux/uaccess.h> | ||
10 | #include <linux/fs.h> | ||
11 | #include <linux/debugfs.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <linux/mfd/abx500.h> | ||
15 | #include <linux/mfd/ab8500.h> | ||
16 | |||
17 | static u32 debug_bank; | ||
18 | static u32 debug_address; | ||
19 | |||
20 | /** | ||
21 | * struct ab8500_reg_range | ||
22 | * @first: the first address of the range | ||
23 | * @last: the last address of the range | ||
24 | * @perm: access permissions for the range | ||
25 | */ | ||
26 | struct ab8500_reg_range { | ||
27 | u8 first; | ||
28 | u8 last; | ||
29 | u8 perm; | ||
30 | }; | ||
31 | |||
32 | /** | ||
33 | * struct ab8500_i2c_ranges | ||
34 | * @num_ranges: the number of ranges in the list | ||
35 | * @bankid: bank identifier | ||
36 | * @range: the list of register ranges | ||
37 | */ | ||
38 | struct ab8500_i2c_ranges { | ||
39 | u8 num_ranges; | ||
40 | u8 bankid; | ||
41 | const struct ab8500_reg_range *range; | ||
42 | }; | ||
43 | |||
44 | #define AB8500_NAME_STRING "ab8500" | ||
45 | #define AB8500_NUM_BANKS 22 | ||
46 | |||
47 | #define AB8500_REV_REG 0x80 | ||
48 | |||
49 | static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { | ||
50 | [0x0] = { | ||
51 | .num_ranges = 0, | ||
52 | .range = 0, | ||
53 | }, | ||
54 | [AB8500_SYS_CTRL1_BLOCK] = { | ||
55 | .num_ranges = 3, | ||
56 | .range = (struct ab8500_reg_range[]) { | ||
57 | { | ||
58 | .first = 0x00, | ||
59 | .last = 0x02, | ||
60 | }, | ||
61 | { | ||
62 | .first = 0x42, | ||
63 | .last = 0x42, | ||
64 | }, | ||
65 | { | ||
66 | .first = 0x80, | ||
67 | .last = 0x81, | ||
68 | }, | ||
69 | }, | ||
70 | }, | ||
71 | [AB8500_SYS_CTRL2_BLOCK] = { | ||
72 | .num_ranges = 4, | ||
73 | .range = (struct ab8500_reg_range[]) { | ||
74 | { | ||
75 | .first = 0x00, | ||
76 | .last = 0x0D, | ||
77 | }, | ||
78 | { | ||
79 | .first = 0x0F, | ||
80 | .last = 0x17, | ||
81 | }, | ||
82 | { | ||
83 | .first = 0x30, | ||
84 | .last = 0x30, | ||
85 | }, | ||
86 | { | ||
87 | .first = 0x32, | ||
88 | .last = 0x33, | ||
89 | }, | ||
90 | }, | ||
91 | }, | ||
92 | [AB8500_REGU_CTRL1] = { | ||
93 | .num_ranges = 3, | ||
94 | .range = (struct ab8500_reg_range[]) { | ||
95 | { | ||
96 | .first = 0x00, | ||
97 | .last = 0x00, | ||
98 | }, | ||
99 | { | ||
100 | .first = 0x03, | ||
101 | .last = 0x10, | ||
102 | }, | ||
103 | { | ||
104 | .first = 0x80, | ||
105 | .last = 0x84, | ||
106 | }, | ||
107 | }, | ||
108 | }, | ||
109 | [AB8500_REGU_CTRL2] = { | ||
110 | .num_ranges = 5, | ||
111 | .range = (struct ab8500_reg_range[]) { | ||
112 | { | ||
113 | .first = 0x00, | ||
114 | .last = 0x15, | ||
115 | }, | ||
116 | { | ||
117 | .first = 0x17, | ||
118 | .last = 0x19, | ||
119 | }, | ||
120 | { | ||
121 | .first = 0x1B, | ||
122 | .last = 0x1D, | ||
123 | }, | ||
124 | { | ||
125 | .first = 0x1F, | ||
126 | .last = 0x22, | ||
127 | }, | ||
128 | { | ||
129 | .first = 0x40, | ||
130 | .last = 0x44, | ||
131 | }, | ||
132 | /* 0x80-0x8B is SIM registers and should | ||
133 | * not be accessed from here */ | ||
134 | }, | ||
135 | }, | ||
136 | [AB8500_USB] = { | ||
137 | .num_ranges = 2, | ||
138 | .range = (struct ab8500_reg_range[]) { | ||
139 | { | ||
140 | .first = 0x80, | ||
141 | .last = 0x83, | ||
142 | }, | ||
143 | { | ||
144 | .first = 0x87, | ||
145 | .last = 0x8A, | ||
146 | }, | ||
147 | }, | ||
148 | }, | ||
149 | [AB8500_TVOUT] = { | ||
150 | .num_ranges = 9, | ||
151 | .range = (struct ab8500_reg_range[]) { | ||
152 | { | ||
153 | .first = 0x00, | ||
154 | .last = 0x12, | ||
155 | }, | ||
156 | { | ||
157 | .first = 0x15, | ||
158 | .last = 0x17, | ||
159 | }, | ||
160 | { | ||
161 | .first = 0x19, | ||
162 | .last = 0x21, | ||
163 | }, | ||
164 | { | ||
165 | .first = 0x27, | ||
166 | .last = 0x2C, | ||
167 | }, | ||
168 | { | ||
169 | .first = 0x41, | ||
170 | .last = 0x41, | ||
171 | }, | ||
172 | { | ||
173 | .first = 0x45, | ||
174 | .last = 0x5B, | ||
175 | }, | ||
176 | { | ||
177 | .first = 0x5D, | ||
178 | .last = 0x5D, | ||
179 | }, | ||
180 | { | ||
181 | .first = 0x69, | ||
182 | .last = 0x69, | ||
183 | }, | ||
184 | { | ||
185 | .first = 0x80, | ||
186 | .last = 0x81, | ||
187 | }, | ||
188 | }, | ||
189 | }, | ||
190 | [AB8500_DBI] = { | ||
191 | .num_ranges = 0, | ||
192 | .range = 0, | ||
193 | }, | ||
194 | [AB8500_ECI_AV_ACC] = { | ||
195 | .num_ranges = 1, | ||
196 | .range = (struct ab8500_reg_range[]) { | ||
197 | { | ||
198 | .first = 0x80, | ||
199 | .last = 0x82, | ||
200 | }, | ||
201 | }, | ||
202 | }, | ||
203 | [0x9] = { | ||
204 | .num_ranges = 0, | ||
205 | .range = 0, | ||
206 | }, | ||
207 | [AB8500_GPADC] = { | ||
208 | .num_ranges = 1, | ||
209 | .range = (struct ab8500_reg_range[]) { | ||
210 | { | ||
211 | .first = 0x00, | ||
212 | .last = 0x08, | ||
213 | }, | ||
214 | }, | ||
215 | }, | ||
216 | [AB8500_CHARGER] = { | ||
217 | .num_ranges = 8, | ||
218 | .range = (struct ab8500_reg_range[]) { | ||
219 | { | ||
220 | .first = 0x00, | ||
221 | .last = 0x03, | ||
222 | }, | ||
223 | { | ||
224 | .first = 0x05, | ||
225 | .last = 0x05, | ||
226 | }, | ||
227 | { | ||
228 | .first = 0x40, | ||
229 | .last = 0x40, | ||
230 | }, | ||
231 | { | ||
232 | .first = 0x42, | ||
233 | .last = 0x42, | ||
234 | }, | ||
235 | { | ||
236 | .first = 0x44, | ||
237 | .last = 0x44, | ||
238 | }, | ||
239 | { | ||
240 | .first = 0x50, | ||
241 | .last = 0x55, | ||
242 | }, | ||
243 | { | ||
244 | .first = 0x80, | ||
245 | .last = 0x82, | ||
246 | }, | ||
247 | { | ||
248 | .first = 0xC0, | ||
249 | .last = 0xC2, | ||
250 | }, | ||
251 | }, | ||
252 | }, | ||
253 | [AB8500_GAS_GAUGE] = { | ||
254 | .num_ranges = 3, | ||
255 | .range = (struct ab8500_reg_range[]) { | ||
256 | { | ||
257 | .first = 0x00, | ||
258 | .last = 0x00, | ||
259 | }, | ||
260 | { | ||
261 | .first = 0x07, | ||
262 | .last = 0x0A, | ||
263 | }, | ||
264 | { | ||
265 | .first = 0x10, | ||
266 | .last = 0x14, | ||
267 | }, | ||
268 | }, | ||
269 | }, | ||
270 | [AB8500_AUDIO] = { | ||
271 | .num_ranges = 1, | ||
272 | .range = (struct ab8500_reg_range[]) { | ||
273 | { | ||
274 | .first = 0x00, | ||
275 | .last = 0x6F, | ||
276 | }, | ||
277 | }, | ||
278 | }, | ||
279 | [AB8500_INTERRUPT] = { | ||
280 | .num_ranges = 0, | ||
281 | .range = 0, | ||
282 | }, | ||
283 | [AB8500_RTC] = { | ||
284 | .num_ranges = 1, | ||
285 | .range = (struct ab8500_reg_range[]) { | ||
286 | { | ||
287 | .first = 0x00, | ||
288 | .last = 0x0F, | ||
289 | }, | ||
290 | }, | ||
291 | }, | ||
292 | [AB8500_MISC] = { | ||
293 | .num_ranges = 8, | ||
294 | .range = (struct ab8500_reg_range[]) { | ||
295 | { | ||
296 | .first = 0x00, | ||
297 | .last = 0x05, | ||
298 | }, | ||
299 | { | ||
300 | .first = 0x10, | ||
301 | .last = 0x15, | ||
302 | }, | ||
303 | { | ||
304 | .first = 0x20, | ||
305 | .last = 0x25, | ||
306 | }, | ||
307 | { | ||
308 | .first = 0x30, | ||
309 | .last = 0x35, | ||
310 | }, | ||
311 | { | ||
312 | .first = 0x40, | ||
313 | .last = 0x45, | ||
314 | }, | ||
315 | { | ||
316 | .first = 0x50, | ||
317 | .last = 0x50, | ||
318 | }, | ||
319 | { | ||
320 | .first = 0x60, | ||
321 | .last = 0x67, | ||
322 | }, | ||
323 | { | ||
324 | .first = 0x80, | ||
325 | .last = 0x80, | ||
326 | }, | ||
327 | }, | ||
328 | }, | ||
329 | [0x11] = { | ||
330 | .num_ranges = 0, | ||
331 | .range = 0, | ||
332 | }, | ||
333 | [0x12] = { | ||
334 | .num_ranges = 0, | ||
335 | .range = 0, | ||
336 | }, | ||
337 | [0x13] = { | ||
338 | .num_ranges = 0, | ||
339 | .range = 0, | ||
340 | }, | ||
341 | [0x14] = { | ||
342 | .num_ranges = 0, | ||
343 | .range = 0, | ||
344 | }, | ||
345 | [AB8500_OTP_EMUL] = { | ||
346 | .num_ranges = 1, | ||
347 | .range = (struct ab8500_reg_range[]) { | ||
348 | { | ||
349 | .first = 0x01, | ||
350 | .last = 0x0F, | ||
351 | }, | ||
352 | }, | ||
353 | }, | ||
354 | }; | ||
355 | |||
356 | static int ab8500_registers_print(struct seq_file *s, void *p) | ||
357 | { | ||
358 | struct device *dev = s->private; | ||
359 | unsigned int i; | ||
360 | u32 bank = debug_bank; | ||
361 | |||
362 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); | ||
363 | |||
364 | seq_printf(s, " bank %u:\n", bank); | ||
365 | for (i = 0; i < debug_ranges[bank].num_ranges; i++) { | ||
366 | u32 reg; | ||
367 | |||
368 | for (reg = debug_ranges[bank].range[i].first; | ||
369 | reg <= debug_ranges[bank].range[i].last; | ||
370 | reg++) { | ||
371 | u8 value; | ||
372 | int err; | ||
373 | |||
374 | err = abx500_get_register_interruptible(dev, | ||
375 | (u8)bank, (u8)reg, &value); | ||
376 | if (err < 0) { | ||
377 | dev_err(dev, "ab->read fail %d\n", err); | ||
378 | return err; | ||
379 | } | ||
380 | |||
381 | err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n", bank, | ||
382 | reg, value); | ||
383 | if (err < 0) { | ||
384 | dev_err(dev, "seq_printf overflow\n"); | ||
385 | /* Error is not returned here since | ||
386 | * the output is wanted in any case */ | ||
387 | return 0; | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int ab8500_registers_open(struct inode *inode, struct file *file) | ||
395 | { | ||
396 | return single_open(file, ab8500_registers_print, inode->i_private); | ||
397 | } | ||
398 | |||
399 | static const struct file_operations ab8500_registers_fops = { | ||
400 | .open = ab8500_registers_open, | ||
401 | .read = seq_read, | ||
402 | .llseek = seq_lseek, | ||
403 | .release = single_release, | ||
404 | .owner = THIS_MODULE, | ||
405 | }; | ||
406 | |||
407 | static int ab8500_bank_print(struct seq_file *s, void *p) | ||
408 | { | ||
409 | return seq_printf(s, "%d\n", debug_bank); | ||
410 | } | ||
411 | |||
412 | static int ab8500_bank_open(struct inode *inode, struct file *file) | ||
413 | { | ||
414 | return single_open(file, ab8500_bank_print, inode->i_private); | ||
415 | } | ||
416 | |||
417 | static ssize_t ab8500_bank_write(struct file *file, | ||
418 | const char __user *user_buf, | ||
419 | size_t count, loff_t *ppos) | ||
420 | { | ||
421 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
422 | char buf[32]; | ||
423 | int buf_size; | ||
424 | unsigned long user_bank; | ||
425 | int err; | ||
426 | |||
427 | /* Get userspace string and assure termination */ | ||
428 | buf_size = min(count, (sizeof(buf) - 1)); | ||
429 | if (copy_from_user(buf, user_buf, buf_size)) | ||
430 | return -EFAULT; | ||
431 | buf[buf_size] = 0; | ||
432 | |||
433 | err = strict_strtoul(buf, 0, &user_bank); | ||
434 | if (err) | ||
435 | return -EINVAL; | ||
436 | |||
437 | if (user_bank >= AB8500_NUM_BANKS) { | ||
438 | dev_err(dev, "debugfs error input > number of banks\n"); | ||
439 | return -EINVAL; | ||
440 | } | ||
441 | |||
442 | debug_bank = user_bank; | ||
443 | |||
444 | return buf_size; | ||
445 | } | ||
446 | |||
447 | static int ab8500_address_print(struct seq_file *s, void *p) | ||
448 | { | ||
449 | return seq_printf(s, "0x%02X\n", debug_address); | ||
450 | } | ||
451 | |||
452 | static int ab8500_address_open(struct inode *inode, struct file *file) | ||
453 | { | ||
454 | return single_open(file, ab8500_address_print, inode->i_private); | ||
455 | } | ||
456 | |||
457 | static ssize_t ab8500_address_write(struct file *file, | ||
458 | const char __user *user_buf, | ||
459 | size_t count, loff_t *ppos) | ||
460 | { | ||
461 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
462 | char buf[32]; | ||
463 | int buf_size; | ||
464 | unsigned long user_address; | ||
465 | int err; | ||
466 | |||
467 | /* Get userspace string and assure termination */ | ||
468 | buf_size = min(count, (sizeof(buf) - 1)); | ||
469 | if (copy_from_user(buf, user_buf, buf_size)) | ||
470 | return -EFAULT; | ||
471 | buf[buf_size] = 0; | ||
472 | |||
473 | err = strict_strtoul(buf, 0, &user_address); | ||
474 | if (err) | ||
475 | return -EINVAL; | ||
476 | if (user_address > 0xff) { | ||
477 | dev_err(dev, "debugfs error input > 0xff\n"); | ||
478 | return -EINVAL; | ||
479 | } | ||
480 | debug_address = user_address; | ||
481 | return buf_size; | ||
482 | } | ||
483 | |||
484 | static int ab8500_val_print(struct seq_file *s, void *p) | ||
485 | { | ||
486 | struct device *dev = s->private; | ||
487 | int ret; | ||
488 | u8 regvalue; | ||
489 | |||
490 | ret = abx500_get_register_interruptible(dev, | ||
491 | (u8)debug_bank, (u8)debug_address, ®value); | ||
492 | if (ret < 0) { | ||
493 | dev_err(dev, "abx500_get_reg fail %d, %d\n", | ||
494 | ret, __LINE__); | ||
495 | return -EINVAL; | ||
496 | } | ||
497 | seq_printf(s, "0x%02X\n", regvalue); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int ab8500_val_open(struct inode *inode, struct file *file) | ||
503 | { | ||
504 | return single_open(file, ab8500_val_print, inode->i_private); | ||
505 | } | ||
506 | |||
507 | static ssize_t ab8500_val_write(struct file *file, | ||
508 | const char __user *user_buf, | ||
509 | size_t count, loff_t *ppos) | ||
510 | { | ||
511 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
512 | char buf[32]; | ||
513 | int buf_size; | ||
514 | unsigned long user_val; | ||
515 | int err; | ||
516 | |||
517 | /* Get userspace string and assure termination */ | ||
518 | buf_size = min(count, (sizeof(buf)-1)); | ||
519 | if (copy_from_user(buf, user_buf, buf_size)) | ||
520 | return -EFAULT; | ||
521 | buf[buf_size] = 0; | ||
522 | |||
523 | err = strict_strtoul(buf, 0, &user_val); | ||
524 | if (err) | ||
525 | return -EINVAL; | ||
526 | if (user_val > 0xff) { | ||
527 | dev_err(dev, "debugfs error input > 0xff\n"); | ||
528 | return -EINVAL; | ||
529 | } | ||
530 | err = abx500_set_register_interruptible(dev, | ||
531 | (u8)debug_bank, debug_address, (u8)user_val); | ||
532 | if (err < 0) { | ||
533 | printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__); | ||
534 | return -EINVAL; | ||
535 | } | ||
536 | |||
537 | return buf_size; | ||
538 | } | ||
539 | |||
540 | static const struct file_operations ab8500_bank_fops = { | ||
541 | .open = ab8500_bank_open, | ||
542 | .write = ab8500_bank_write, | ||
543 | .read = seq_read, | ||
544 | .llseek = seq_lseek, | ||
545 | .release = single_release, | ||
546 | .owner = THIS_MODULE, | ||
547 | }; | ||
548 | |||
549 | static const struct file_operations ab8500_address_fops = { | ||
550 | .open = ab8500_address_open, | ||
551 | .write = ab8500_address_write, | ||
552 | .read = seq_read, | ||
553 | .llseek = seq_lseek, | ||
554 | .release = single_release, | ||
555 | .owner = THIS_MODULE, | ||
556 | }; | ||
557 | |||
558 | static const struct file_operations ab8500_val_fops = { | ||
559 | .open = ab8500_val_open, | ||
560 | .write = ab8500_val_write, | ||
561 | .read = seq_read, | ||
562 | .llseek = seq_lseek, | ||
563 | .release = single_release, | ||
564 | .owner = THIS_MODULE, | ||
565 | }; | ||
566 | |||
567 | static struct dentry *ab8500_dir; | ||
568 | static struct dentry *ab8500_reg_file; | ||
569 | static struct dentry *ab8500_bank_file; | ||
570 | static struct dentry *ab8500_address_file; | ||
571 | static struct dentry *ab8500_val_file; | ||
572 | |||
573 | static int __devinit ab8500_debug_probe(struct platform_device *plf) | ||
574 | { | ||
575 | debug_bank = AB8500_MISC; | ||
576 | debug_address = AB8500_REV_REG & 0x00FF; | ||
577 | |||
578 | ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); | ||
579 | if (!ab8500_dir) | ||
580 | goto exit_no_debugfs; | ||
581 | |||
582 | ab8500_reg_file = debugfs_create_file("all-bank-registers", | ||
583 | S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops); | ||
584 | if (!ab8500_reg_file) | ||
585 | goto exit_destroy_dir; | ||
586 | |||
587 | ab8500_bank_file = debugfs_create_file("register-bank", | ||
588 | (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops); | ||
589 | if (!ab8500_bank_file) | ||
590 | goto exit_destroy_reg; | ||
591 | |||
592 | ab8500_address_file = debugfs_create_file("register-address", | ||
593 | (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, | ||
594 | &ab8500_address_fops); | ||
595 | if (!ab8500_address_file) | ||
596 | goto exit_destroy_bank; | ||
597 | |||
598 | ab8500_val_file = debugfs_create_file("register-value", | ||
599 | (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops); | ||
600 | if (!ab8500_val_file) | ||
601 | goto exit_destroy_address; | ||
602 | |||
603 | return 0; | ||
604 | |||
605 | exit_destroy_address: | ||
606 | debugfs_remove(ab8500_address_file); | ||
607 | exit_destroy_bank: | ||
608 | debugfs_remove(ab8500_bank_file); | ||
609 | exit_destroy_reg: | ||
610 | debugfs_remove(ab8500_reg_file); | ||
611 | exit_destroy_dir: | ||
612 | debugfs_remove(ab8500_dir); | ||
613 | exit_no_debugfs: | ||
614 | dev_err(&plf->dev, "failed to create debugfs entries.\n"); | ||
615 | return -ENOMEM; | ||
616 | } | ||
617 | |||
618 | static int __devexit ab8500_debug_remove(struct platform_device *plf) | ||
619 | { | ||
620 | debugfs_remove(ab8500_val_file); | ||
621 | debugfs_remove(ab8500_address_file); | ||
622 | debugfs_remove(ab8500_bank_file); | ||
623 | debugfs_remove(ab8500_reg_file); | ||
624 | debugfs_remove(ab8500_dir); | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | static struct platform_driver ab8500_debug_driver = { | ||
630 | .driver = { | ||
631 | .name = "ab8500-debug", | ||
632 | .owner = THIS_MODULE, | ||
633 | }, | ||
634 | .probe = ab8500_debug_probe, | ||
635 | .remove = __devexit_p(ab8500_debug_remove) | ||
636 | }; | ||
637 | |||
638 | static int __init ab8500_debug_init(void) | ||
639 | { | ||
640 | return platform_driver_register(&ab8500_debug_driver); | ||
641 | } | ||
642 | |||
643 | static void __exit ab8500_debug_exit(void) | ||
644 | { | ||
645 | platform_driver_unregister(&ab8500_debug_driver); | ||
646 | } | ||
647 | subsys_initcall(ab8500_debug_init); | ||
648 | module_exit(ab8500_debug_exit); | ||
649 | |||
650 | MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com"); | ||
651 | MODULE_DESCRIPTION("AB8500 DEBUG"); | ||
652 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/ab8500-i2c.c b/drivers/mfd/ab8500-i2c.c new file mode 100644 index 000000000000..6820327adf4a --- /dev/null +++ b/drivers/mfd/ab8500-i2c.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson. | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * This file was based on drivers/mfd/ab8500-spi.c | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/mfd/ab8500.h> | ||
14 | |||
15 | #include <mach/prcmu.h> | ||
16 | |||
17 | static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) | ||
18 | { | ||
19 | int ret; | ||
20 | |||
21 | ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); | ||
22 | if (ret < 0) | ||
23 | dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); | ||
24 | return ret; | ||
25 | } | ||
26 | |||
27 | static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr) | ||
28 | { | ||
29 | int ret; | ||
30 | u8 data; | ||
31 | |||
32 | ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); | ||
33 | if (ret < 0) { | ||
34 | dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); | ||
35 | return ret; | ||
36 | } | ||
37 | return (int)data; | ||
38 | } | ||
39 | |||
40 | static int __devinit ab8500_i2c_probe(struct platform_device *plf) | ||
41 | { | ||
42 | struct ab8500 *ab8500; | ||
43 | struct resource *resource; | ||
44 | int ret; | ||
45 | |||
46 | ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL); | ||
47 | if (!ab8500) | ||
48 | return -ENOMEM; | ||
49 | |||
50 | ab8500->dev = &plf->dev; | ||
51 | |||
52 | resource = platform_get_resource(plf, IORESOURCE_IRQ, 0); | ||
53 | if (!resource) { | ||
54 | kfree(ab8500); | ||
55 | return -ENODEV; | ||
56 | } | ||
57 | |||
58 | ab8500->irq = resource->start; | ||
59 | |||
60 | ab8500->read = ab8500_i2c_read; | ||
61 | ab8500->write = ab8500_i2c_write; | ||
62 | |||
63 | platform_set_drvdata(plf, ab8500); | ||
64 | |||
65 | ret = ab8500_init(ab8500); | ||
66 | if (ret) | ||
67 | kfree(ab8500); | ||
68 | |||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static int __devexit ab8500_i2c_remove(struct platform_device *plf) | ||
73 | { | ||
74 | struct ab8500 *ab8500 = platform_get_drvdata(plf); | ||
75 | |||
76 | ab8500_exit(ab8500); | ||
77 | kfree(ab8500); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static struct platform_driver ab8500_i2c_driver = { | ||
83 | .driver = { | ||
84 | .name = "ab8500-i2c", | ||
85 | .owner = THIS_MODULE, | ||
86 | }, | ||
87 | .probe = ab8500_i2c_probe, | ||
88 | .remove = __devexit_p(ab8500_i2c_remove) | ||
89 | }; | ||
90 | |||
91 | static int __init ab8500_i2c_init(void) | ||
92 | { | ||
93 | return platform_driver_register(&ab8500_i2c_driver); | ||
94 | } | ||
95 | |||
96 | static void __exit ab8500_i2c_exit(void) | ||
97 | { | ||
98 | platform_driver_unregister(&ab8500_i2c_driver); | ||
99 | } | ||
100 | subsys_initcall(ab8500_i2c_init); | ||
101 | module_exit(ab8500_i2c_exit); | ||
102 | |||
103 | MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com"); | ||
104 | MODULE_DESCRIPTION("AB8500 Core access via PRCMU I2C"); | ||
105 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c index 01b6d584442c..b1653421edb5 100644 --- a/drivers/mfd/ab8500-spi.c +++ b/drivers/mfd/ab8500-spi.c | |||
@@ -119,7 +119,7 @@ static int __devexit ab8500_spi_remove(struct spi_device *spi) | |||
119 | 119 | ||
120 | static struct spi_driver ab8500_spi_driver = { | 120 | static struct spi_driver ab8500_spi_driver = { |
121 | .driver = { | 121 | .driver = { |
122 | .name = "ab8500", | 122 | .name = "ab8500-spi", |
123 | .owner = THIS_MODULE, | 123 | .owner = THIS_MODULE, |
124 | }, | 124 | }, |
125 | .probe = ab8500_spi_probe, | 125 | .probe = ab8500_spi_probe, |
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index c07aece900fb..2fadbaeb1cb1 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c | |||
@@ -470,13 +470,19 @@ static int __devinit da903x_add_subdevs(struct da903x_chip *chip, | |||
470 | subdev = &pdata->subdevs[i]; | 470 | subdev = &pdata->subdevs[i]; |
471 | 471 | ||
472 | pdev = platform_device_alloc(subdev->name, subdev->id); | 472 | pdev = platform_device_alloc(subdev->name, subdev->id); |
473 | if (!pdev) { | ||
474 | ret = -ENOMEM; | ||
475 | goto failed; | ||
476 | } | ||
473 | 477 | ||
474 | pdev->dev.parent = chip->dev; | 478 | pdev->dev.parent = chip->dev; |
475 | pdev->dev.platform_data = subdev->platform_data; | 479 | pdev->dev.platform_data = subdev->platform_data; |
476 | 480 | ||
477 | ret = platform_device_add(pdev); | 481 | ret = platform_device_add(pdev); |
478 | if (ret) | 482 | if (ret) { |
483 | platform_device_put(pdev); | ||
479 | goto failed; | 484 | goto failed; |
485 | } | ||
480 | } | 486 | } |
481 | return 0; | 487 | return 0; |
482 | 488 | ||
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 134c69aa4790..c2b698d69a93 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c | |||
@@ -384,12 +384,20 @@ static int __devinit pcap_add_subdev(struct pcap_chip *pcap, | |||
384 | struct pcap_subdev *subdev) | 384 | struct pcap_subdev *subdev) |
385 | { | 385 | { |
386 | struct platform_device *pdev; | 386 | struct platform_device *pdev; |
387 | int ret; | ||
387 | 388 | ||
388 | pdev = platform_device_alloc(subdev->name, subdev->id); | 389 | pdev = platform_device_alloc(subdev->name, subdev->id); |
390 | if (!pdev) | ||
391 | return -ENOMEM; | ||
392 | |||
389 | pdev->dev.parent = &pcap->spi->dev; | 393 | pdev->dev.parent = &pcap->spi->dev; |
390 | pdev->dev.platform_data = subdev->platform_data; | 394 | pdev->dev.platform_data = subdev->platform_data; |
391 | 395 | ||
392 | return platform_device_add(pdev); | 396 | ret = platform_device_add(pdev); |
397 | if (ret) | ||
398 | platform_device_put(pdev); | ||
399 | |||
400 | return ret; | ||
393 | } | 401 | } |
394 | 402 | ||
395 | static int __devexit ezx_pcap_remove(struct spi_device *spi) | 403 | static int __devexit ezx_pcap_remove(struct spi_device *spi) |
@@ -457,6 +465,7 @@ static int __devinit ezx_pcap_probe(struct spi_device *spi) | |||
457 | pcap->irq_base = pdata->irq_base; | 465 | pcap->irq_base = pdata->irq_base; |
458 | pcap->workqueue = create_singlethread_workqueue("pcapd"); | 466 | pcap->workqueue = create_singlethread_workqueue("pcapd"); |
459 | if (!pcap->workqueue) { | 467 | if (!pcap->workqueue) { |
468 | ret = -ENOMEM; | ||
460 | dev_err(&spi->dev, "cant create pcap thread\n"); | 469 | dev_err(&spi->dev, "cant create pcap thread\n"); |
461 | goto free_pcap; | 470 | goto free_pcap; |
462 | } | 471 | } |
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index f04300e05fd6..7bc752272dc1 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c | |||
@@ -138,13 +138,6 @@ static int __init pasic3_probe(struct platform_device *pdev) | |||
138 | irq = r->start; | 138 | irq = r->start; |
139 | } | 139 | } |
140 | 140 | ||
141 | r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
142 | if (r) { | ||
143 | ds1wm_resources[1].flags = IORESOURCE_IRQ | (r->flags & | ||
144 | (IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE)); | ||
145 | irq = r->start; | ||
146 | } | ||
147 | |||
148 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 141 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
149 | if (!r) | 142 | if (!r) |
150 | return -ENXIO; | 143 | return -ENXIO; |
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 3ad492cb6c41..9dd1b33f2275 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -153,7 +153,7 @@ static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine, | |||
153 | if (enabled) | 153 | if (enabled) |
154 | val |= BIT(engine); | 154 | val |= BIT(engine); |
155 | else | 155 | else |
156 | val &= BIT(engine); | 156 | val &= ~BIT(engine); |
157 | writeb(val, adc->base + JZ_REG_ADC_ENABLE); | 157 | writeb(val, adc->base + JZ_REG_ADC_ENABLE); |
158 | 158 | ||
159 | spin_unlock_irqrestore(&adc->lock, flags); | 159 | spin_unlock_irqrestore(&adc->lock, flags); |
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 428377a5a6f5..44695f5a1800 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -93,8 +93,13 @@ static struct mfd_cell rtc_devs[] = { | |||
93 | static struct resource onkey_resources[] = { | 93 | static struct resource onkey_resources[] = { |
94 | { | 94 | { |
95 | .name = "max8925-onkey", | 95 | .name = "max8925-onkey", |
96 | .start = MAX8925_IRQ_GPM_SW_3SEC, | 96 | .start = MAX8925_IRQ_GPM_SW_R, |
97 | .end = MAX8925_IRQ_GPM_SW_3SEC, | 97 | .end = MAX8925_IRQ_GPM_SW_R, |
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, { | ||
100 | .name = "max8925-onkey", | ||
101 | .start = MAX8925_IRQ_GPM_SW_F, | ||
102 | .end = MAX8925_IRQ_GPM_SW_F, | ||
98 | .flags = IORESOURCE_IRQ, | 103 | .flags = IORESOURCE_IRQ, |
99 | }, | 104 | }, |
100 | }; | 105 | }; |
@@ -102,7 +107,7 @@ static struct resource onkey_resources[] = { | |||
102 | static struct mfd_cell onkey_devs[] = { | 107 | static struct mfd_cell onkey_devs[] = { |
103 | { | 108 | { |
104 | .name = "max8925-onkey", | 109 | .name = "max8925-onkey", |
105 | .num_resources = 1, | 110 | .num_resources = 2, |
106 | .resources = &onkey_resources[0], | 111 | .resources = &onkey_resources[0], |
107 | .id = -1, | 112 | .id = -1, |
108 | }, | 113 | }, |
diff --git a/drivers/mfd/max8998-irq.c b/drivers/mfd/max8998-irq.c new file mode 100644 index 000000000000..45bfe77b639b --- /dev/null +++ b/drivers/mfd/max8998-irq.c | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * Interrupt controller support for MAX8998 | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <linux/mfd/max8998-private.h> | ||
18 | |||
19 | struct max8998_irq_data { | ||
20 | int reg; | ||
21 | int mask; | ||
22 | }; | ||
23 | |||
24 | static struct max8998_irq_data max8998_irqs[] = { | ||
25 | [MAX8998_IRQ_DCINF] = { | ||
26 | .reg = 1, | ||
27 | .mask = MAX8998_IRQ_DCINF_MASK, | ||
28 | }, | ||
29 | [MAX8998_IRQ_DCINR] = { | ||
30 | .reg = 1, | ||
31 | .mask = MAX8998_IRQ_DCINR_MASK, | ||
32 | }, | ||
33 | [MAX8998_IRQ_JIGF] = { | ||
34 | .reg = 1, | ||
35 | .mask = MAX8998_IRQ_JIGF_MASK, | ||
36 | }, | ||
37 | [MAX8998_IRQ_JIGR] = { | ||
38 | .reg = 1, | ||
39 | .mask = MAX8998_IRQ_JIGR_MASK, | ||
40 | }, | ||
41 | [MAX8998_IRQ_PWRONF] = { | ||
42 | .reg = 1, | ||
43 | .mask = MAX8998_IRQ_PWRONF_MASK, | ||
44 | }, | ||
45 | [MAX8998_IRQ_PWRONR] = { | ||
46 | .reg = 1, | ||
47 | .mask = MAX8998_IRQ_PWRONR_MASK, | ||
48 | }, | ||
49 | [MAX8998_IRQ_WTSREVNT] = { | ||
50 | .reg = 2, | ||
51 | .mask = MAX8998_IRQ_WTSREVNT_MASK, | ||
52 | }, | ||
53 | [MAX8998_IRQ_SMPLEVNT] = { | ||
54 | .reg = 2, | ||
55 | .mask = MAX8998_IRQ_SMPLEVNT_MASK, | ||
56 | }, | ||
57 | [MAX8998_IRQ_ALARM1] = { | ||
58 | .reg = 2, | ||
59 | .mask = MAX8998_IRQ_ALARM1_MASK, | ||
60 | }, | ||
61 | [MAX8998_IRQ_ALARM0] = { | ||
62 | .reg = 2, | ||
63 | .mask = MAX8998_IRQ_ALARM0_MASK, | ||
64 | }, | ||
65 | [MAX8998_IRQ_ONKEY1S] = { | ||
66 | .reg = 3, | ||
67 | .mask = MAX8998_IRQ_ONKEY1S_MASK, | ||
68 | }, | ||
69 | [MAX8998_IRQ_TOPOFFR] = { | ||
70 | .reg = 3, | ||
71 | .mask = MAX8998_IRQ_TOPOFFR_MASK, | ||
72 | }, | ||
73 | [MAX8998_IRQ_DCINOVPR] = { | ||
74 | .reg = 3, | ||
75 | .mask = MAX8998_IRQ_DCINOVPR_MASK, | ||
76 | }, | ||
77 | [MAX8998_IRQ_CHGRSTF] = { | ||
78 | .reg = 3, | ||
79 | .mask = MAX8998_IRQ_CHGRSTF_MASK, | ||
80 | }, | ||
81 | [MAX8998_IRQ_DONER] = { | ||
82 | .reg = 3, | ||
83 | .mask = MAX8998_IRQ_DONER_MASK, | ||
84 | }, | ||
85 | [MAX8998_IRQ_CHGFAULT] = { | ||
86 | .reg = 3, | ||
87 | .mask = MAX8998_IRQ_CHGFAULT_MASK, | ||
88 | }, | ||
89 | [MAX8998_IRQ_LOBAT1] = { | ||
90 | .reg = 4, | ||
91 | .mask = MAX8998_IRQ_LOBAT1_MASK, | ||
92 | }, | ||
93 | [MAX8998_IRQ_LOBAT2] = { | ||
94 | .reg = 4, | ||
95 | .mask = MAX8998_IRQ_LOBAT2_MASK, | ||
96 | }, | ||
97 | }; | ||
98 | |||
99 | static inline struct max8998_irq_data * | ||
100 | irq_to_max8998_irq(struct max8998_dev *max8998, int irq) | ||
101 | { | ||
102 | return &max8998_irqs[irq - max8998->irq_base]; | ||
103 | } | ||
104 | |||
105 | static void max8998_irq_lock(unsigned int irq) | ||
106 | { | ||
107 | struct max8998_dev *max8998 = get_irq_chip_data(irq); | ||
108 | |||
109 | mutex_lock(&max8998->irqlock); | ||
110 | } | ||
111 | |||
112 | static void max8998_irq_sync_unlock(unsigned int irq) | ||
113 | { | ||
114 | struct max8998_dev *max8998 = get_irq_chip_data(irq); | ||
115 | int i; | ||
116 | |||
117 | for (i = 0; i < ARRAY_SIZE(max8998->irq_masks_cur); i++) { | ||
118 | /* | ||
119 | * If there's been a change in the mask write it back | ||
120 | * to the hardware. | ||
121 | */ | ||
122 | if (max8998->irq_masks_cur[i] != max8998->irq_masks_cache[i]) { | ||
123 | max8998->irq_masks_cache[i] = max8998->irq_masks_cur[i]; | ||
124 | max8998_write_reg(max8998->i2c, MAX8998_REG_IRQM1 + i, | ||
125 | max8998->irq_masks_cur[i]); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | mutex_unlock(&max8998->irqlock); | ||
130 | } | ||
131 | |||
132 | static void max8998_irq_unmask(unsigned int irq) | ||
133 | { | ||
134 | struct max8998_dev *max8998 = get_irq_chip_data(irq); | ||
135 | struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, irq); | ||
136 | |||
137 | max8998->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; | ||
138 | } | ||
139 | |||
140 | static void max8998_irq_mask(unsigned int irq) | ||
141 | { | ||
142 | struct max8998_dev *max8998 = get_irq_chip_data(irq); | ||
143 | struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, irq); | ||
144 | |||
145 | max8998->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; | ||
146 | } | ||
147 | |||
148 | static struct irq_chip max8998_irq_chip = { | ||
149 | .name = "max8998", | ||
150 | .bus_lock = max8998_irq_lock, | ||
151 | .bus_sync_unlock = max8998_irq_sync_unlock, | ||
152 | .mask = max8998_irq_mask, | ||
153 | .unmask = max8998_irq_unmask, | ||
154 | }; | ||
155 | |||
156 | static irqreturn_t max8998_irq_thread(int irq, void *data) | ||
157 | { | ||
158 | struct max8998_dev *max8998 = data; | ||
159 | u8 irq_reg[MAX8998_NUM_IRQ_REGS]; | ||
160 | int ret; | ||
161 | int i; | ||
162 | |||
163 | ret = max8998_bulk_read(max8998->i2c, MAX8998_REG_IRQ1, | ||
164 | MAX8998_NUM_IRQ_REGS, irq_reg); | ||
165 | if (ret < 0) { | ||
166 | dev_err(max8998->dev, "Failed to read interrupt register: %d\n", | ||
167 | ret); | ||
168 | return IRQ_NONE; | ||
169 | } | ||
170 | |||
171 | /* Apply masking */ | ||
172 | for (i = 0; i < MAX8998_NUM_IRQ_REGS; i++) | ||
173 | irq_reg[i] &= ~max8998->irq_masks_cur[i]; | ||
174 | |||
175 | /* Report */ | ||
176 | for (i = 0; i < MAX8998_IRQ_NR; i++) { | ||
177 | if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) | ||
178 | handle_nested_irq(max8998->irq_base + i); | ||
179 | } | ||
180 | |||
181 | return IRQ_HANDLED; | ||
182 | } | ||
183 | |||
184 | int max8998_irq_init(struct max8998_dev *max8998) | ||
185 | { | ||
186 | int i; | ||
187 | int cur_irq; | ||
188 | int ret; | ||
189 | |||
190 | if (!max8998->irq) { | ||
191 | dev_warn(max8998->dev, | ||
192 | "No interrupt specified, no interrupts\n"); | ||
193 | max8998->irq_base = 0; | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | if (!max8998->irq_base) { | ||
198 | dev_err(max8998->dev, | ||
199 | "No interrupt base specified, no interrupts\n"); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | mutex_init(&max8998->irqlock); | ||
204 | |||
205 | /* Mask the individual interrupt sources */ | ||
206 | for (i = 0; i < MAX8998_NUM_IRQ_REGS; i++) { | ||
207 | max8998->irq_masks_cur[i] = 0xff; | ||
208 | max8998->irq_masks_cache[i] = 0xff; | ||
209 | max8998_write_reg(max8998->i2c, MAX8998_REG_IRQM1 + i, 0xff); | ||
210 | } | ||
211 | |||
212 | max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff); | ||
213 | max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff); | ||
214 | |||
215 | /* register with genirq */ | ||
216 | for (i = 0; i < MAX8998_IRQ_NR; i++) { | ||
217 | cur_irq = i + max8998->irq_base; | ||
218 | set_irq_chip_data(cur_irq, max8998); | ||
219 | set_irq_chip_and_handler(cur_irq, &max8998_irq_chip, | ||
220 | handle_edge_irq); | ||
221 | set_irq_nested_thread(cur_irq, 1); | ||
222 | #ifdef CONFIG_ARM | ||
223 | set_irq_flags(cur_irq, IRQF_VALID); | ||
224 | #else | ||
225 | set_irq_noprobe(cur_irq); | ||
226 | #endif | ||
227 | } | ||
228 | |||
229 | ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread, | ||
230 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
231 | "max8998-irq", max8998); | ||
232 | if (ret) { | ||
233 | dev_err(max8998->dev, "Failed to request IRQ %d: %d\n", | ||
234 | max8998->irq, ret); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | if (!max8998->ono) | ||
239 | return 0; | ||
240 | |||
241 | ret = request_threaded_irq(max8998->ono, NULL, max8998_irq_thread, | ||
242 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | | ||
243 | IRQF_ONESHOT, "max8998-ono", max8998); | ||
244 | if (ret) | ||
245 | dev_err(max8998->dev, "Failed to request IRQ %d: %d\n", | ||
246 | max8998->ono, ret); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | void max8998_irq_exit(struct max8998_dev *max8998) | ||
252 | { | ||
253 | if (max8998->ono) | ||
254 | free_irq(max8998->ono, max8998); | ||
255 | |||
256 | if (max8998->irq) | ||
257 | free_irq(max8998->irq, max8998); | ||
258 | } | ||
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 73e6f5c4efc9..bb9977bebe78 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * max8698.c - mfd core driver for the Maxim 8998 | 2 | * max8998.c - mfd core driver for the Maxim 8998 |
3 | * | 3 | * |
4 | * Copyright (C) 2009-2010 Samsung Electronics | 4 | * Copyright (C) 2009-2010 Samsung Electronics |
5 | * Kyungmin Park <kyungmin.park@samsung.com> | 5 | * Kyungmin Park <kyungmin.park@samsung.com> |
@@ -30,19 +30,23 @@ | |||
30 | #include <linux/mfd/max8998.h> | 30 | #include <linux/mfd/max8998.h> |
31 | #include <linux/mfd/max8998-private.h> | 31 | #include <linux/mfd/max8998-private.h> |
32 | 32 | ||
33 | #define RTC_I2C_ADDR (0x0c >> 1) | ||
34 | |||
33 | static struct mfd_cell max8998_devs[] = { | 35 | static struct mfd_cell max8998_devs[] = { |
34 | { | 36 | { |
35 | .name = "max8998-pmic", | 37 | .name = "max8998-pmic", |
36 | } | 38 | }, { |
39 | .name = "max8998-rtc", | ||
40 | }, | ||
37 | }; | 41 | }; |
38 | 42 | ||
39 | static int max8998_i2c_device_read(struct max8998_dev *max8998, u8 reg, u8 *dest) | 43 | int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) |
40 | { | 44 | { |
41 | struct i2c_client *client = max8998->i2c_client; | 45 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); |
42 | int ret; | 46 | int ret; |
43 | 47 | ||
44 | mutex_lock(&max8998->iolock); | 48 | mutex_lock(&max8998->iolock); |
45 | ret = i2c_smbus_read_byte_data(client, reg); | 49 | ret = i2c_smbus_read_byte_data(i2c, reg); |
46 | mutex_unlock(&max8998->iolock); | 50 | mutex_unlock(&max8998->iolock); |
47 | if (ret < 0) | 51 | if (ret < 0) |
48 | return ret; | 52 | return ret; |
@@ -51,40 +55,71 @@ static int max8998_i2c_device_read(struct max8998_dev *max8998, u8 reg, u8 *dest | |||
51 | *dest = ret; | 55 | *dest = ret; |
52 | return 0; | 56 | return 0; |
53 | } | 57 | } |
58 | EXPORT_SYMBOL(max8998_read_reg); | ||
54 | 59 | ||
55 | static int max8998_i2c_device_write(struct max8998_dev *max8998, u8 reg, u8 value) | 60 | int max8998_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf) |
56 | { | 61 | { |
57 | struct i2c_client *client = max8998->i2c_client; | 62 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); |
63 | int ret; | ||
64 | |||
65 | mutex_lock(&max8998->iolock); | ||
66 | ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf); | ||
67 | mutex_unlock(&max8998->iolock); | ||
68 | if (ret < 0) | ||
69 | return ret; | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | EXPORT_SYMBOL(max8998_bulk_read); | ||
74 | |||
75 | int max8998_write_reg(struct i2c_client *i2c, u8 reg, u8 value) | ||
76 | { | ||
77 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); | ||
58 | int ret; | 78 | int ret; |
59 | 79 | ||
60 | mutex_lock(&max8998->iolock); | 80 | mutex_lock(&max8998->iolock); |
61 | ret = i2c_smbus_write_byte_data(client, reg, value); | 81 | ret = i2c_smbus_write_byte_data(i2c, reg, value); |
62 | mutex_unlock(&max8998->iolock); | 82 | mutex_unlock(&max8998->iolock); |
63 | return ret; | 83 | return ret; |
64 | } | 84 | } |
85 | EXPORT_SYMBOL(max8998_write_reg); | ||
65 | 86 | ||
66 | static int max8998_i2c_device_update(struct max8998_dev *max8998, u8 reg, | 87 | int max8998_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf) |
67 | u8 val, u8 mask) | ||
68 | { | 88 | { |
69 | struct i2c_client *client = max8998->i2c_client; | 89 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); |
90 | int ret; | ||
91 | |||
92 | mutex_lock(&max8998->iolock); | ||
93 | ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf); | ||
94 | mutex_unlock(&max8998->iolock); | ||
95 | if (ret < 0) | ||
96 | return ret; | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | EXPORT_SYMBOL(max8998_bulk_write); | ||
101 | |||
102 | int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) | ||
103 | { | ||
104 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); | ||
70 | int ret; | 105 | int ret; |
71 | 106 | ||
72 | mutex_lock(&max8998->iolock); | 107 | mutex_lock(&max8998->iolock); |
73 | ret = i2c_smbus_read_byte_data(client, reg); | 108 | ret = i2c_smbus_read_byte_data(i2c, reg); |
74 | if (ret >= 0) { | 109 | if (ret >= 0) { |
75 | u8 old_val = ret & 0xff; | 110 | u8 old_val = ret & 0xff; |
76 | u8 new_val = (val & mask) | (old_val & (~mask)); | 111 | u8 new_val = (val & mask) | (old_val & (~mask)); |
77 | ret = i2c_smbus_write_byte_data(client, reg, new_val); | 112 | ret = i2c_smbus_write_byte_data(i2c, reg, new_val); |
78 | if (ret >= 0) | ||
79 | ret = 0; | ||
80 | } | 113 | } |
81 | mutex_unlock(&max8998->iolock); | 114 | mutex_unlock(&max8998->iolock); |
82 | return ret; | 115 | return ret; |
83 | } | 116 | } |
117 | EXPORT_SYMBOL(max8998_update_reg); | ||
84 | 118 | ||
85 | static int max8998_i2c_probe(struct i2c_client *i2c, | 119 | static int max8998_i2c_probe(struct i2c_client *i2c, |
86 | const struct i2c_device_id *id) | 120 | const struct i2c_device_id *id) |
87 | { | 121 | { |
122 | struct max8998_platform_data *pdata = i2c->dev.platform_data; | ||
88 | struct max8998_dev *max8998; | 123 | struct max8998_dev *max8998; |
89 | int ret = 0; | 124 | int ret = 0; |
90 | 125 | ||
@@ -94,12 +129,20 @@ static int max8998_i2c_probe(struct i2c_client *i2c, | |||
94 | 129 | ||
95 | i2c_set_clientdata(i2c, max8998); | 130 | i2c_set_clientdata(i2c, max8998); |
96 | max8998->dev = &i2c->dev; | 131 | max8998->dev = &i2c->dev; |
97 | max8998->i2c_client = i2c; | 132 | max8998->i2c = i2c; |
98 | max8998->dev_read = max8998_i2c_device_read; | 133 | max8998->irq = i2c->irq; |
99 | max8998->dev_write = max8998_i2c_device_write; | 134 | max8998->type = id->driver_data; |
100 | max8998->dev_update = max8998_i2c_device_update; | 135 | if (pdata) { |
136 | max8998->ono = pdata->ono; | ||
137 | max8998->irq_base = pdata->irq_base; | ||
138 | } | ||
101 | mutex_init(&max8998->iolock); | 139 | mutex_init(&max8998->iolock); |
102 | 140 | ||
141 | max8998->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); | ||
142 | i2c_set_clientdata(max8998->rtc, max8998); | ||
143 | |||
144 | max8998_irq_init(max8998); | ||
145 | |||
103 | ret = mfd_add_devices(max8998->dev, -1, | 146 | ret = mfd_add_devices(max8998->dev, -1, |
104 | max8998_devs, ARRAY_SIZE(max8998_devs), | 147 | max8998_devs, ARRAY_SIZE(max8998_devs), |
105 | NULL, 0); | 148 | NULL, 0); |
@@ -110,6 +153,8 @@ static int max8998_i2c_probe(struct i2c_client *i2c, | |||
110 | 153 | ||
111 | err: | 154 | err: |
112 | mfd_remove_devices(max8998->dev); | 155 | mfd_remove_devices(max8998->dev); |
156 | max8998_irq_exit(max8998); | ||
157 | i2c_unregister_device(max8998->rtc); | ||
113 | kfree(max8998); | 158 | kfree(max8998); |
114 | return ret; | 159 | return ret; |
115 | } | 160 | } |
@@ -119,14 +164,17 @@ static int max8998_i2c_remove(struct i2c_client *i2c) | |||
119 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); | 164 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); |
120 | 165 | ||
121 | mfd_remove_devices(max8998->dev); | 166 | mfd_remove_devices(max8998->dev); |
167 | max8998_irq_exit(max8998); | ||
168 | i2c_unregister_device(max8998->rtc); | ||
122 | kfree(max8998); | 169 | kfree(max8998); |
123 | 170 | ||
124 | return 0; | 171 | return 0; |
125 | } | 172 | } |
126 | 173 | ||
127 | static const struct i2c_device_id max8998_i2c_id[] = { | 174 | static const struct i2c_device_id max8998_i2c_id[] = { |
128 | { "max8998", 0 }, | 175 | { "max8998", TYPE_MAX8998 }, |
129 | { } | 176 | { "lp3974", TYPE_LP3974}, |
177 | { } | ||
130 | }; | 178 | }; |
131 | MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); | 179 | MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); |
132 | 180 | ||
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c deleted file mode 100644 index 6df34989c1f6..000000000000 --- a/drivers/mfd/mc13783-core.c +++ /dev/null | |||
@@ -1,752 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Pengutronix | ||
3 | * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> | ||
4 | * | ||
5 | * loosely based on an earlier driver that has | ||
6 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it under | ||
9 | * the terms of the GNU General Public License version 2 as published by the | ||
10 | * Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/spi/spi.h> | ||
18 | #include <linux/mfd/core.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 | ||
39 | |||
40 | #define MC13783_IRQSTAT0 0 | ||
41 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) | ||
42 | #define MC13783_IRQSTAT0_ADCBISDONEI (1 << 1) | ||
43 | #define MC13783_IRQSTAT0_TSI (1 << 2) | ||
44 | #define MC13783_IRQSTAT0_WHIGHI (1 << 3) | ||
45 | #define MC13783_IRQSTAT0_WLOWI (1 << 4) | ||
46 | #define MC13783_IRQSTAT0_CHGDETI (1 << 6) | ||
47 | #define MC13783_IRQSTAT0_CHGOVI (1 << 7) | ||
48 | #define MC13783_IRQSTAT0_CHGREVI (1 << 8) | ||
49 | #define MC13783_IRQSTAT0_CHGSHORTI (1 << 9) | ||
50 | #define MC13783_IRQSTAT0_CCCVI (1 << 10) | ||
51 | #define MC13783_IRQSTAT0_CHGCURRI (1 << 11) | ||
52 | #define MC13783_IRQSTAT0_BPONI (1 << 12) | ||
53 | #define MC13783_IRQSTAT0_LOBATLI (1 << 13) | ||
54 | #define MC13783_IRQSTAT0_LOBATHI (1 << 14) | ||
55 | #define MC13783_IRQSTAT0_UDPI (1 << 15) | ||
56 | #define MC13783_IRQSTAT0_USBI (1 << 16) | ||
57 | #define MC13783_IRQSTAT0_IDI (1 << 19) | ||
58 | #define MC13783_IRQSTAT0_SE1I (1 << 21) | ||
59 | #define MC13783_IRQSTAT0_CKDETI (1 << 22) | ||
60 | #define MC13783_IRQSTAT0_UDMI (1 << 23) | ||
61 | |||
62 | #define MC13783_IRQMASK0 1 | ||
63 | #define MC13783_IRQMASK0_ADCDONEM MC13783_IRQSTAT0_ADCDONEI | ||
64 | #define MC13783_IRQMASK0_ADCBISDONEM MC13783_IRQSTAT0_ADCBISDONEI | ||
65 | #define MC13783_IRQMASK0_TSM MC13783_IRQSTAT0_TSI | ||
66 | #define MC13783_IRQMASK0_WHIGHM MC13783_IRQSTAT0_WHIGHI | ||
67 | #define MC13783_IRQMASK0_WLOWM MC13783_IRQSTAT0_WLOWI | ||
68 | #define MC13783_IRQMASK0_CHGDETM MC13783_IRQSTAT0_CHGDETI | ||
69 | #define MC13783_IRQMASK0_CHGOVM MC13783_IRQSTAT0_CHGOVI | ||
70 | #define MC13783_IRQMASK0_CHGREVM MC13783_IRQSTAT0_CHGREVI | ||
71 | #define MC13783_IRQMASK0_CHGSHORTM MC13783_IRQSTAT0_CHGSHORTI | ||
72 | #define MC13783_IRQMASK0_CCCVM MC13783_IRQSTAT0_CCCVI | ||
73 | #define MC13783_IRQMASK0_CHGCURRM MC13783_IRQSTAT0_CHGCURRI | ||
74 | #define MC13783_IRQMASK0_BPONM MC13783_IRQSTAT0_BPONI | ||
75 | #define MC13783_IRQMASK0_LOBATLM MC13783_IRQSTAT0_LOBATLI | ||
76 | #define MC13783_IRQMASK0_LOBATHM MC13783_IRQSTAT0_LOBATHI | ||
77 | #define MC13783_IRQMASK0_UDPM MC13783_IRQSTAT0_UDPI | ||
78 | #define MC13783_IRQMASK0_USBM MC13783_IRQSTAT0_USBI | ||
79 | #define MC13783_IRQMASK0_IDM MC13783_IRQSTAT0_IDI | ||
80 | #define MC13783_IRQMASK0_SE1M MC13783_IRQSTAT0_SE1I | ||
81 | #define MC13783_IRQMASK0_CKDETM MC13783_IRQSTAT0_CKDETI | ||
82 | #define MC13783_IRQMASK0_UDMM MC13783_IRQSTAT0_UDMI | ||
83 | |||
84 | #define MC13783_IRQSTAT1 3 | ||
85 | #define MC13783_IRQSTAT1_1HZI (1 << 0) | ||
86 | #define MC13783_IRQSTAT1_TODAI (1 << 1) | ||
87 | #define MC13783_IRQSTAT1_ONOFD1I (1 << 3) | ||
88 | #define MC13783_IRQSTAT1_ONOFD2I (1 << 4) | ||
89 | #define MC13783_IRQSTAT1_ONOFD3I (1 << 5) | ||
90 | #define MC13783_IRQSTAT1_SYSRSTI (1 << 6) | ||
91 | #define MC13783_IRQSTAT1_RTCRSTI (1 << 7) | ||
92 | #define MC13783_IRQSTAT1_PCI (1 << 8) | ||
93 | #define MC13783_IRQSTAT1_WARMI (1 << 9) | ||
94 | #define MC13783_IRQSTAT1_MEMHLDI (1 << 10) | ||
95 | #define MC13783_IRQSTAT1_PWRRDYI (1 << 11) | ||
96 | #define MC13783_IRQSTAT1_THWARNLI (1 << 12) | ||
97 | #define MC13783_IRQSTAT1_THWARNHI (1 << 13) | ||
98 | #define MC13783_IRQSTAT1_CLKI (1 << 14) | ||
99 | #define MC13783_IRQSTAT1_SEMAFI (1 << 15) | ||
100 | #define MC13783_IRQSTAT1_MC2BI (1 << 17) | ||
101 | #define MC13783_IRQSTAT1_HSDETI (1 << 18) | ||
102 | #define MC13783_IRQSTAT1_HSLI (1 << 19) | ||
103 | #define MC13783_IRQSTAT1_ALSPTHI (1 << 20) | ||
104 | #define MC13783_IRQSTAT1_AHSSHORTI (1 << 21) | ||
105 | |||
106 | #define MC13783_IRQMASK1 4 | ||
107 | #define MC13783_IRQMASK1_1HZM MC13783_IRQSTAT1_1HZI | ||
108 | #define MC13783_IRQMASK1_TODAM MC13783_IRQSTAT1_TODAI | ||
109 | #define MC13783_IRQMASK1_ONOFD1M MC13783_IRQSTAT1_ONOFD1I | ||
110 | #define MC13783_IRQMASK1_ONOFD2M MC13783_IRQSTAT1_ONOFD2I | ||
111 | #define MC13783_IRQMASK1_ONOFD3M MC13783_IRQSTAT1_ONOFD3I | ||
112 | #define MC13783_IRQMASK1_SYSRSTM MC13783_IRQSTAT1_SYSRSTI | ||
113 | #define MC13783_IRQMASK1_RTCRSTM MC13783_IRQSTAT1_RTCRSTI | ||
114 | #define MC13783_IRQMASK1_PCM MC13783_IRQSTAT1_PCI | ||
115 | #define MC13783_IRQMASK1_WARMM MC13783_IRQSTAT1_WARMI | ||
116 | #define MC13783_IRQMASK1_MEMHLDM MC13783_IRQSTAT1_MEMHLDI | ||
117 | #define MC13783_IRQMASK1_PWRRDYM MC13783_IRQSTAT1_PWRRDYI | ||
118 | #define MC13783_IRQMASK1_THWARNLM MC13783_IRQSTAT1_THWARNLI | ||
119 | #define MC13783_IRQMASK1_THWARNHM MC13783_IRQSTAT1_THWARNHI | ||
120 | #define MC13783_IRQMASK1_CLKM MC13783_IRQSTAT1_CLKI | ||
121 | #define MC13783_IRQMASK1_SEMAFM MC13783_IRQSTAT1_SEMAFI | ||
122 | #define MC13783_IRQMASK1_MC2BM MC13783_IRQSTAT1_MC2BI | ||
123 | #define MC13783_IRQMASK1_HSDETM MC13783_IRQSTAT1_HSDETI | ||
124 | #define MC13783_IRQMASK1_HSLM MC13783_IRQSTAT1_HSLI | ||
125 | #define MC13783_IRQMASK1_ALSPTHM MC13783_IRQSTAT1_ALSPTHI | ||
126 | #define MC13783_IRQMASK1_AHSSHORTM MC13783_IRQSTAT1_AHSSHORTI | ||
127 | |||
128 | #define MC13783_ADC1 44 | ||
129 | #define MC13783_ADC1_ADEN (1 << 0) | ||
130 | #define MC13783_ADC1_RAND (1 << 1) | ||
131 | #define MC13783_ADC1_ADSEL (1 << 3) | ||
132 | #define MC13783_ADC1_ASC (1 << 20) | ||
133 | #define MC13783_ADC1_ADTRIGIGN (1 << 21) | ||
134 | |||
135 | #define MC13783_NUMREGS 0x3f | ||
136 | |||
137 | void mc13783_lock(struct mc13783 *mc13783) | ||
138 | { | ||
139 | if (!mutex_trylock(&mc13783->lock)) { | ||
140 | dev_dbg(&mc13783->spidev->dev, "wait for %s from %pf\n", | ||
141 | __func__, __builtin_return_address(0)); | ||
142 | |||
143 | mutex_lock(&mc13783->lock); | ||
144 | } | ||
145 | dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", | ||
146 | __func__, __builtin_return_address(0)); | ||
147 | } | ||
148 | EXPORT_SYMBOL(mc13783_lock); | ||
149 | |||
150 | void mc13783_unlock(struct mc13783 *mc13783) | ||
151 | { | ||
152 | dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", | ||
153 | __func__, __builtin_return_address(0)); | ||
154 | mutex_unlock(&mc13783->lock); | ||
155 | } | ||
156 | EXPORT_SYMBOL(mc13783_unlock); | ||
157 | |||
158 | #define MC13783_REGOFFSET_SHIFT 25 | ||
159 | int mc13783_reg_read(struct mc13783 *mc13783, unsigned int offset, u32 *val) | ||
160 | { | ||
161 | struct spi_transfer t; | ||
162 | struct spi_message m; | ||
163 | int ret; | ||
164 | |||
165 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
166 | |||
167 | if (offset > MC13783_NUMREGS) | ||
168 | return -EINVAL; | ||
169 | |||
170 | *val = offset << MC13783_REGOFFSET_SHIFT; | ||
171 | |||
172 | memset(&t, 0, sizeof(t)); | ||
173 | |||
174 | t.tx_buf = val; | ||
175 | t.rx_buf = val; | ||
176 | t.len = sizeof(u32); | ||
177 | |||
178 | spi_message_init(&m); | ||
179 | spi_message_add_tail(&t, &m); | ||
180 | |||
181 | ret = spi_sync(mc13783->spidev, &m); | ||
182 | |||
183 | /* error in message.status implies error return from spi_sync */ | ||
184 | BUG_ON(!ret && m.status); | ||
185 | |||
186 | if (ret) | ||
187 | return ret; | ||
188 | |||
189 | *val &= 0xffffff; | ||
190 | |||
191 | dev_vdbg(&mc13783->spidev->dev, "[0x%02x] -> 0x%06x\n", offset, *val); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | EXPORT_SYMBOL(mc13783_reg_read); | ||
196 | |||
197 | int mc13783_reg_write(struct mc13783 *mc13783, unsigned int offset, u32 val) | ||
198 | { | ||
199 | u32 buf; | ||
200 | struct spi_transfer t; | ||
201 | struct spi_message m; | ||
202 | int ret; | ||
203 | |||
204 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
205 | |||
206 | dev_vdbg(&mc13783->spidev->dev, "[0x%02x] <- 0x%06x\n", offset, val); | ||
207 | |||
208 | if (offset > MC13783_NUMREGS || val > 0xffffff) | ||
209 | return -EINVAL; | ||
210 | |||
211 | buf = 1 << 31 | offset << MC13783_REGOFFSET_SHIFT | val; | ||
212 | |||
213 | memset(&t, 0, sizeof(t)); | ||
214 | |||
215 | t.tx_buf = &buf; | ||
216 | t.rx_buf = &buf; | ||
217 | t.len = sizeof(u32); | ||
218 | |||
219 | spi_message_init(&m); | ||
220 | spi_message_add_tail(&t, &m); | ||
221 | |||
222 | ret = spi_sync(mc13783->spidev, &m); | ||
223 | |||
224 | BUG_ON(!ret && m.status); | ||
225 | |||
226 | if (ret) | ||
227 | return ret; | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | EXPORT_SYMBOL(mc13783_reg_write); | ||
232 | |||
233 | int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | ||
234 | u32 mask, u32 val) | ||
235 | { | ||
236 | int ret; | ||
237 | u32 valread; | ||
238 | |||
239 | BUG_ON(val & ~mask); | ||
240 | |||
241 | ret = mc13783_reg_read(mc13783, offset, &valread); | ||
242 | if (ret) | ||
243 | return ret; | ||
244 | |||
245 | valread = (valread & ~mask) | val; | ||
246 | |||
247 | return mc13783_reg_write(mc13783, offset, valread); | ||
248 | } | ||
249 | EXPORT_SYMBOL(mc13783_reg_rmw); | ||
250 | |||
251 | int mc13783_get_flags(struct mc13783 *mc13783) | ||
252 | { | ||
253 | return mc13783->flags; | ||
254 | } | ||
255 | EXPORT_SYMBOL(mc13783_get_flags); | ||
256 | |||
257 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) | ||
258 | { | ||
259 | int ret; | ||
260 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
261 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
262 | u32 mask; | ||
263 | |||
264 | if (irq < 0 || irq >= MC13783_NUM_IRQ) | ||
265 | return -EINVAL; | ||
266 | |||
267 | ret = mc13783_reg_read(mc13783, offmask, &mask); | ||
268 | if (ret) | ||
269 | return ret; | ||
270 | |||
271 | if (mask & irqbit) | ||
272 | /* already masked */ | ||
273 | return 0; | ||
274 | |||
275 | return mc13783_reg_write(mc13783, offmask, mask | irqbit); | ||
276 | } | ||
277 | EXPORT_SYMBOL(mc13783_irq_mask); | ||
278 | |||
279 | int mc13783_irq_unmask(struct mc13783 *mc13783, int irq) | ||
280 | { | ||
281 | int ret; | ||
282 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
283 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
284 | u32 mask; | ||
285 | |||
286 | if (irq < 0 || irq >= MC13783_NUM_IRQ) | ||
287 | return -EINVAL; | ||
288 | |||
289 | ret = mc13783_reg_read(mc13783, offmask, &mask); | ||
290 | if (ret) | ||
291 | return ret; | ||
292 | |||
293 | if (!(mask & irqbit)) | ||
294 | /* already unmasked */ | ||
295 | return 0; | ||
296 | |||
297 | return mc13783_reg_write(mc13783, offmask, mask & ~irqbit); | ||
298 | } | ||
299 | EXPORT_SYMBOL(mc13783_irq_unmask); | ||
300 | |||
301 | int mc13783_irq_status(struct mc13783 *mc13783, int irq, | ||
302 | int *enabled, int *pending) | ||
303 | { | ||
304 | int ret; | ||
305 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
306 | unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; | ||
307 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
308 | |||
309 | if (irq < 0 || irq >= MC13783_NUM_IRQ) | ||
310 | return -EINVAL; | ||
311 | |||
312 | if (enabled) { | ||
313 | u32 mask; | ||
314 | |||
315 | ret = mc13783_reg_read(mc13783, offmask, &mask); | ||
316 | if (ret) | ||
317 | return ret; | ||
318 | |||
319 | *enabled = mask & irqbit; | ||
320 | } | ||
321 | |||
322 | if (pending) { | ||
323 | u32 stat; | ||
324 | |||
325 | ret = mc13783_reg_read(mc13783, offstat, &stat); | ||
326 | if (ret) | ||
327 | return ret; | ||
328 | |||
329 | *pending = stat & irqbit; | ||
330 | } | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | EXPORT_SYMBOL(mc13783_irq_status); | ||
335 | |||
336 | int mc13783_irq_ack(struct mc13783 *mc13783, int irq) | ||
337 | { | ||
338 | unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; | ||
339 | unsigned int val = 1 << (irq < 24 ? irq : irq - 24); | ||
340 | |||
341 | BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ); | ||
342 | |||
343 | return mc13783_reg_write(mc13783, offstat, val); | ||
344 | } | ||
345 | EXPORT_SYMBOL(mc13783_irq_ack); | ||
346 | |||
347 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, | ||
348 | irq_handler_t handler, const char *name, void *dev) | ||
349 | { | ||
350 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
351 | BUG_ON(!handler); | ||
352 | |||
353 | if (irq < 0 || irq >= MC13783_NUM_IRQ) | ||
354 | return -EINVAL; | ||
355 | |||
356 | if (mc13783->irqhandler[irq]) | ||
357 | return -EBUSY; | ||
358 | |||
359 | mc13783->irqhandler[irq] = handler; | ||
360 | mc13783->irqdata[irq] = dev; | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | EXPORT_SYMBOL(mc13783_irq_request_nounmask); | ||
365 | |||
366 | int mc13783_irq_request(struct mc13783 *mc13783, int irq, | ||
367 | irq_handler_t handler, const char *name, void *dev) | ||
368 | { | ||
369 | int ret; | ||
370 | |||
371 | ret = mc13783_irq_request_nounmask(mc13783, irq, handler, name, dev); | ||
372 | if (ret) | ||
373 | return ret; | ||
374 | |||
375 | ret = mc13783_irq_unmask(mc13783, irq); | ||
376 | if (ret) { | ||
377 | mc13783->irqhandler[irq] = NULL; | ||
378 | mc13783->irqdata[irq] = NULL; | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | EXPORT_SYMBOL(mc13783_irq_request); | ||
385 | |||
386 | int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev) | ||
387 | { | ||
388 | int ret; | ||
389 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
390 | |||
391 | if (irq < 0 || irq >= MC13783_NUM_IRQ || !mc13783->irqhandler[irq] || | ||
392 | mc13783->irqdata[irq] != dev) | ||
393 | return -EINVAL; | ||
394 | |||
395 | ret = mc13783_irq_mask(mc13783, irq); | ||
396 | if (ret) | ||
397 | return ret; | ||
398 | |||
399 | mc13783->irqhandler[irq] = NULL; | ||
400 | mc13783->irqdata[irq] = NULL; | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | EXPORT_SYMBOL(mc13783_irq_free); | ||
405 | |||
406 | static inline irqreturn_t mc13783_irqhandler(struct mc13783 *mc13783, int irq) | ||
407 | { | ||
408 | return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]); | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * returns: number of handled irqs or negative error | ||
413 | * locking: holds mc13783->lock | ||
414 | */ | ||
415 | static int mc13783_irq_handle(struct mc13783 *mc13783, | ||
416 | unsigned int offstat, unsigned int offmask, int baseirq) | ||
417 | { | ||
418 | u32 stat, mask; | ||
419 | int ret = mc13783_reg_read(mc13783, offstat, &stat); | ||
420 | int num_handled = 0; | ||
421 | |||
422 | if (ret) | ||
423 | return ret; | ||
424 | |||
425 | ret = mc13783_reg_read(mc13783, offmask, &mask); | ||
426 | if (ret) | ||
427 | return ret; | ||
428 | |||
429 | while (stat & ~mask) { | ||
430 | int irq = __ffs(stat & ~mask); | ||
431 | |||
432 | stat &= ~(1 << irq); | ||
433 | |||
434 | if (likely(mc13783->irqhandler[baseirq + irq])) { | ||
435 | irqreturn_t handled; | ||
436 | |||
437 | handled = mc13783_irqhandler(mc13783, baseirq + irq); | ||
438 | if (handled == IRQ_HANDLED) | ||
439 | num_handled++; | ||
440 | } else { | ||
441 | dev_err(&mc13783->spidev->dev, | ||
442 | "BUG: irq %u but no handler\n", | ||
443 | baseirq + irq); | ||
444 | |||
445 | mask |= 1 << irq; | ||
446 | |||
447 | ret = mc13783_reg_write(mc13783, offmask, mask); | ||
448 | } | ||
449 | } | ||
450 | |||
451 | return num_handled; | ||
452 | } | ||
453 | |||
454 | static irqreturn_t mc13783_irq_thread(int irq, void *data) | ||
455 | { | ||
456 | struct mc13783 *mc13783 = data; | ||
457 | irqreturn_t ret; | ||
458 | int handled = 0; | ||
459 | |||
460 | mc13783_lock(mc13783); | ||
461 | |||
462 | ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT0, | ||
463 | MC13783_IRQMASK0, MC13783_IRQ_ADCDONE); | ||
464 | if (ret > 0) | ||
465 | handled = 1; | ||
466 | |||
467 | ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT1, | ||
468 | MC13783_IRQMASK1, MC13783_IRQ_1HZ); | ||
469 | if (ret > 0) | ||
470 | handled = 1; | ||
471 | |||
472 | mc13783_unlock(mc13783); | ||
473 | |||
474 | return IRQ_RETVAL(handled); | ||
475 | } | ||
476 | |||
477 | #define MC13783_ADC1_CHAN0_SHIFT 5 | ||
478 | #define MC13783_ADC1_CHAN1_SHIFT 8 | ||
479 | |||
480 | struct mc13783_adcdone_data { | ||
481 | struct mc13783 *mc13783; | ||
482 | struct completion done; | ||
483 | }; | ||
484 | |||
485 | static irqreturn_t mc13783_handler_adcdone(int irq, void *data) | ||
486 | { | ||
487 | struct mc13783_adcdone_data *adcdone_data = data; | ||
488 | |||
489 | mc13783_irq_ack(adcdone_data->mc13783, irq); | ||
490 | |||
491 | complete_all(&adcdone_data->done); | ||
492 | |||
493 | return IRQ_HANDLED; | ||
494 | } | ||
495 | |||
496 | #define MC13783_ADC_WORKING (1 << 16) | ||
497 | |||
498 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | ||
499 | unsigned int channel, unsigned int *sample) | ||
500 | { | ||
501 | u32 adc0, adc1, old_adc0; | ||
502 | int i, ret; | ||
503 | struct mc13783_adcdone_data adcdone_data = { | ||
504 | .mc13783 = mc13783, | ||
505 | }; | ||
506 | init_completion(&adcdone_data.done); | ||
507 | |||
508 | dev_dbg(&mc13783->spidev->dev, "%s\n", __func__); | ||
509 | |||
510 | mc13783_lock(mc13783); | ||
511 | |||
512 | if (mc13783->flags & MC13783_ADC_WORKING) { | ||
513 | ret = -EBUSY; | ||
514 | goto out; | ||
515 | } | ||
516 | |||
517 | mc13783->flags |= MC13783_ADC_WORKING; | ||
518 | |||
519 | mc13783_reg_read(mc13783, MC13783_ADC0, &old_adc0); | ||
520 | |||
521 | adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; | ||
522 | adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC; | ||
523 | |||
524 | if (channel > 7) | ||
525 | adc1 |= MC13783_ADC1_ADSEL; | ||
526 | |||
527 | switch (mode) { | ||
528 | case MC13783_ADC_MODE_TS: | ||
529 | adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_TSMOD0 | | ||
530 | MC13783_ADC0_TSMOD1; | ||
531 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | ||
532 | break; | ||
533 | |||
534 | case MC13783_ADC_MODE_SINGLE_CHAN: | ||
535 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; | ||
536 | adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; | ||
537 | adc1 |= MC13783_ADC1_RAND; | ||
538 | break; | ||
539 | |||
540 | case MC13783_ADC_MODE_MULT_CHAN: | ||
541 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; | ||
542 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | ||
543 | break; | ||
544 | |||
545 | default: | ||
546 | mc13783_unlock(mc13783); | ||
547 | return -EINVAL; | ||
548 | } | ||
549 | |||
550 | dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__); | ||
551 | mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE, | ||
552 | mc13783_handler_adcdone, __func__, &adcdone_data); | ||
553 | mc13783_irq_ack(mc13783, MC13783_IRQ_ADCDONE); | ||
554 | |||
555 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0); | ||
556 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1); | ||
557 | |||
558 | mc13783_unlock(mc13783); | ||
559 | |||
560 | ret = wait_for_completion_interruptible_timeout(&adcdone_data.done, HZ); | ||
561 | |||
562 | if (!ret) | ||
563 | ret = -ETIMEDOUT; | ||
564 | |||
565 | mc13783_lock(mc13783); | ||
566 | |||
567 | mc13783_irq_free(mc13783, MC13783_IRQ_ADCDONE, &adcdone_data); | ||
568 | |||
569 | if (ret > 0) | ||
570 | for (i = 0; i < 4; ++i) { | ||
571 | ret = mc13783_reg_read(mc13783, | ||
572 | MC13783_REG_ADC_2, &sample[i]); | ||
573 | if (ret) | ||
574 | break; | ||
575 | } | ||
576 | |||
577 | if (mode == MC13783_ADC_MODE_TS) | ||
578 | /* restore TSMOD */ | ||
579 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, old_adc0); | ||
580 | |||
581 | mc13783->flags &= ~MC13783_ADC_WORKING; | ||
582 | out: | ||
583 | mc13783_unlock(mc13783); | ||
584 | |||
585 | return ret; | ||
586 | } | ||
587 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); | ||
588 | |||
589 | static int mc13783_add_subdevice_pdata(struct mc13783 *mc13783, | ||
590 | const char *name, void *pdata, size_t pdata_size) | ||
591 | { | ||
592 | struct mfd_cell cell = { | ||
593 | .name = name, | ||
594 | .platform_data = pdata, | ||
595 | .data_size = pdata_size, | ||
596 | }; | ||
597 | |||
598 | return mfd_add_devices(&mc13783->spidev->dev, -1, &cell, 1, NULL, 0); | ||
599 | } | ||
600 | |||
601 | static int mc13783_add_subdevice(struct mc13783 *mc13783, const char *name) | ||
602 | { | ||
603 | return mc13783_add_subdevice_pdata(mc13783, name, NULL, 0); | ||
604 | } | ||
605 | |||
606 | static int mc13783_check_revision(struct mc13783 *mc13783) | ||
607 | { | ||
608 | u32 rev_id, rev1, rev2, finid, icid; | ||
609 | |||
610 | mc13783_reg_read(mc13783, MC13783_REG_REVISION, &rev_id); | ||
611 | |||
612 | rev1 = (rev_id & 0x018) >> 3; | ||
613 | rev2 = (rev_id & 0x007); | ||
614 | icid = (rev_id & 0x01C0) >> 6; | ||
615 | finid = (rev_id & 0x01E00) >> 9; | ||
616 | |||
617 | /* Ver 0.2 is actually 3.2a. Report as 3.2 */ | ||
618 | if ((rev1 == 0) && (rev2 == 2)) | ||
619 | rev1 = 3; | ||
620 | |||
621 | if (rev1 == 0 || icid != 2) { | ||
622 | dev_err(&mc13783->spidev->dev, "No MC13783 detected.\n"); | ||
623 | return -ENODEV; | ||
624 | } | ||
625 | |||
626 | dev_info(&mc13783->spidev->dev, | ||
627 | "MC13783 Rev %d.%d FinVer %x detected\n", | ||
628 | rev1, rev2, finid); | ||
629 | |||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | static int mc13783_probe(struct spi_device *spi) | ||
634 | { | ||
635 | struct mc13783 *mc13783; | ||
636 | struct mc13783_platform_data *pdata = dev_get_platdata(&spi->dev); | ||
637 | int ret; | ||
638 | |||
639 | mc13783 = kzalloc(sizeof(*mc13783), GFP_KERNEL); | ||
640 | if (!mc13783) | ||
641 | return -ENOMEM; | ||
642 | |||
643 | dev_set_drvdata(&spi->dev, mc13783); | ||
644 | spi->mode = SPI_MODE_0 | SPI_CS_HIGH; | ||
645 | spi->bits_per_word = 32; | ||
646 | spi_setup(spi); | ||
647 | |||
648 | mc13783->spidev = spi; | ||
649 | |||
650 | mutex_init(&mc13783->lock); | ||
651 | mc13783_lock(mc13783); | ||
652 | |||
653 | ret = mc13783_check_revision(mc13783); | ||
654 | if (ret) | ||
655 | goto err_revision; | ||
656 | |||
657 | /* mask all irqs */ | ||
658 | ret = mc13783_reg_write(mc13783, MC13783_IRQMASK0, 0x00ffffff); | ||
659 | if (ret) | ||
660 | goto err_mask; | ||
661 | |||
662 | ret = mc13783_reg_write(mc13783, MC13783_IRQMASK1, 0x00ffffff); | ||
663 | if (ret) | ||
664 | goto err_mask; | ||
665 | |||
666 | ret = request_threaded_irq(spi->irq, NULL, mc13783_irq_thread, | ||
667 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13783", mc13783); | ||
668 | |||
669 | if (ret) { | ||
670 | err_mask: | ||
671 | err_revision: | ||
672 | mutex_unlock(&mc13783->lock); | ||
673 | dev_set_drvdata(&spi->dev, NULL); | ||
674 | kfree(mc13783); | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | /* This should go away (BEGIN) */ | ||
679 | if (pdata) { | ||
680 | mc13783->flags = pdata->flags; | ||
681 | mc13783->regulators = pdata->regulators; | ||
682 | mc13783->num_regulators = pdata->num_regulators; | ||
683 | } | ||
684 | /* This should go away (END) */ | ||
685 | |||
686 | mc13783_unlock(mc13783); | ||
687 | |||
688 | if (pdata->flags & MC13783_USE_ADC) | ||
689 | mc13783_add_subdevice(mc13783, "mc13783-adc"); | ||
690 | |||
691 | if (pdata->flags & MC13783_USE_CODEC) | ||
692 | mc13783_add_subdevice(mc13783, "mc13783-codec"); | ||
693 | |||
694 | if (pdata->flags & MC13783_USE_REGULATOR) { | ||
695 | struct mc13783_regulator_platform_data regulator_pdata = { | ||
696 | .num_regulators = pdata->num_regulators, | ||
697 | .regulators = pdata->regulators, | ||
698 | }; | ||
699 | |||
700 | mc13783_add_subdevice_pdata(mc13783, "mc13783-regulator", | ||
701 | ®ulator_pdata, sizeof(regulator_pdata)); | ||
702 | } | ||
703 | |||
704 | if (pdata->flags & MC13783_USE_RTC) | ||
705 | mc13783_add_subdevice(mc13783, "mc13783-rtc"); | ||
706 | |||
707 | if (pdata->flags & MC13783_USE_TOUCHSCREEN) | ||
708 | mc13783_add_subdevice(mc13783, "mc13783-ts"); | ||
709 | |||
710 | if (pdata->flags & MC13783_USE_LED) | ||
711 | mc13783_add_subdevice_pdata(mc13783, "mc13783-led", | ||
712 | pdata->leds, sizeof(*pdata->leds)); | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static int __devexit mc13783_remove(struct spi_device *spi) | ||
718 | { | ||
719 | struct mc13783 *mc13783 = dev_get_drvdata(&spi->dev); | ||
720 | |||
721 | free_irq(mc13783->spidev->irq, mc13783); | ||
722 | |||
723 | mfd_remove_devices(&spi->dev); | ||
724 | |||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | static struct spi_driver mc13783_driver = { | ||
729 | .driver = { | ||
730 | .name = "mc13783", | ||
731 | .bus = &spi_bus_type, | ||
732 | .owner = THIS_MODULE, | ||
733 | }, | ||
734 | .probe = mc13783_probe, | ||
735 | .remove = __devexit_p(mc13783_remove), | ||
736 | }; | ||
737 | |||
738 | static int __init mc13783_init(void) | ||
739 | { | ||
740 | return spi_register_driver(&mc13783_driver); | ||
741 | } | ||
742 | subsys_initcall(mc13783_init); | ||
743 | |||
744 | static void __exit mc13783_exit(void) | ||
745 | { | ||
746 | spi_unregister_driver(&mc13783_driver); | ||
747 | } | ||
748 | module_exit(mc13783_exit); | ||
749 | |||
750 | MODULE_DESCRIPTION("Core driver for Freescale MC13783 PMIC"); | ||
751 | MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); | ||
752 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c new file mode 100644 index 000000000000..a2ac2ed6d64c --- /dev/null +++ b/drivers/mfd/mc13xxx-core.c | |||
@@ -0,0 +1,840 @@ | |||
1 | /* | ||
2 | * Copyright 2009-2010 Pengutronix | ||
3 | * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> | ||
4 | * | ||
5 | * loosely based on an earlier driver that has | ||
6 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it under | ||
9 | * the terms of the GNU General Public License version 2 as published by the | ||
10 | * Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/mutex.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | #include <linux/mfd/core.h> | ||
20 | #include <linux/mfd/mc13xxx.h> | ||
21 | |||
22 | struct mc13xxx { | ||
23 | struct spi_device *spidev; | ||
24 | struct mutex lock; | ||
25 | int irq; | ||
26 | |||
27 | irq_handler_t irqhandler[MC13XXX_NUM_IRQ]; | ||
28 | void *irqdata[MC13XXX_NUM_IRQ]; | ||
29 | }; | ||
30 | |||
31 | struct mc13783 { | ||
32 | struct mc13xxx mc13xxx; | ||
33 | |||
34 | int adcflags; | ||
35 | }; | ||
36 | |||
37 | struct mc13xxx *mc13783_to_mc13xxx(struct mc13783 *mc13783) | ||
38 | { | ||
39 | return &mc13783->mc13xxx; | ||
40 | } | ||
41 | EXPORT_SYMBOL(mc13783_to_mc13xxx); | ||
42 | |||
43 | #define MC13XXX_IRQSTAT0 0 | ||
44 | #define MC13XXX_IRQSTAT0_ADCDONEI (1 << 0) | ||
45 | #define MC13XXX_IRQSTAT0_ADCBISDONEI (1 << 1) | ||
46 | #define MC13XXX_IRQSTAT0_TSI (1 << 2) | ||
47 | #define MC13783_IRQSTAT0_WHIGHI (1 << 3) | ||
48 | #define MC13783_IRQSTAT0_WLOWI (1 << 4) | ||
49 | #define MC13XXX_IRQSTAT0_CHGDETI (1 << 6) | ||
50 | #define MC13783_IRQSTAT0_CHGOVI (1 << 7) | ||
51 | #define MC13XXX_IRQSTAT0_CHGREVI (1 << 8) | ||
52 | #define MC13XXX_IRQSTAT0_CHGSHORTI (1 << 9) | ||
53 | #define MC13XXX_IRQSTAT0_CCCVI (1 << 10) | ||
54 | #define MC13XXX_IRQSTAT0_CHGCURRI (1 << 11) | ||
55 | #define MC13XXX_IRQSTAT0_BPONI (1 << 12) | ||
56 | #define MC13XXX_IRQSTAT0_LOBATLI (1 << 13) | ||
57 | #define MC13XXX_IRQSTAT0_LOBATHI (1 << 14) | ||
58 | #define MC13783_IRQSTAT0_UDPI (1 << 15) | ||
59 | #define MC13783_IRQSTAT0_USBI (1 << 16) | ||
60 | #define MC13783_IRQSTAT0_IDI (1 << 19) | ||
61 | #define MC13783_IRQSTAT0_SE1I (1 << 21) | ||
62 | #define MC13783_IRQSTAT0_CKDETI (1 << 22) | ||
63 | #define MC13783_IRQSTAT0_UDMI (1 << 23) | ||
64 | |||
65 | #define MC13XXX_IRQMASK0 1 | ||
66 | #define MC13XXX_IRQMASK0_ADCDONEM MC13XXX_IRQSTAT0_ADCDONEI | ||
67 | #define MC13XXX_IRQMASK0_ADCBISDONEM MC13XXX_IRQSTAT0_ADCBISDONEI | ||
68 | #define MC13XXX_IRQMASK0_TSM MC13XXX_IRQSTAT0_TSI | ||
69 | #define MC13783_IRQMASK0_WHIGHM MC13783_IRQSTAT0_WHIGHI | ||
70 | #define MC13783_IRQMASK0_WLOWM MC13783_IRQSTAT0_WLOWI | ||
71 | #define MC13XXX_IRQMASK0_CHGDETM MC13XXX_IRQSTAT0_CHGDETI | ||
72 | #define MC13783_IRQMASK0_CHGOVM MC13783_IRQSTAT0_CHGOVI | ||
73 | #define MC13XXX_IRQMASK0_CHGREVM MC13XXX_IRQSTAT0_CHGREVI | ||
74 | #define MC13XXX_IRQMASK0_CHGSHORTM MC13XXX_IRQSTAT0_CHGSHORTI | ||
75 | #define MC13XXX_IRQMASK0_CCCVM MC13XXX_IRQSTAT0_CCCVI | ||
76 | #define MC13XXX_IRQMASK0_CHGCURRM MC13XXX_IRQSTAT0_CHGCURRI | ||
77 | #define MC13XXX_IRQMASK0_BPONM MC13XXX_IRQSTAT0_BPONI | ||
78 | #define MC13XXX_IRQMASK0_LOBATLM MC13XXX_IRQSTAT0_LOBATLI | ||
79 | #define MC13XXX_IRQMASK0_LOBATHM MC13XXX_IRQSTAT0_LOBATHI | ||
80 | #define MC13783_IRQMASK0_UDPM MC13783_IRQSTAT0_UDPI | ||
81 | #define MC13783_IRQMASK0_USBM MC13783_IRQSTAT0_USBI | ||
82 | #define MC13783_IRQMASK0_IDM MC13783_IRQSTAT0_IDI | ||
83 | #define MC13783_IRQMASK0_SE1M MC13783_IRQSTAT0_SE1I | ||
84 | #define MC13783_IRQMASK0_CKDETM MC13783_IRQSTAT0_CKDETI | ||
85 | #define MC13783_IRQMASK0_UDMM MC13783_IRQSTAT0_UDMI | ||
86 | |||
87 | #define MC13XXX_IRQSTAT1 3 | ||
88 | #define MC13XXX_IRQSTAT1_1HZI (1 << 0) | ||
89 | #define MC13XXX_IRQSTAT1_TODAI (1 << 1) | ||
90 | #define MC13783_IRQSTAT1_ONOFD1I (1 << 3) | ||
91 | #define MC13783_IRQSTAT1_ONOFD2I (1 << 4) | ||
92 | #define MC13783_IRQSTAT1_ONOFD3I (1 << 5) | ||
93 | #define MC13XXX_IRQSTAT1_SYSRSTI (1 << 6) | ||
94 | #define MC13XXX_IRQSTAT1_RTCRSTI (1 << 7) | ||
95 | #define MC13XXX_IRQSTAT1_PCI (1 << 8) | ||
96 | #define MC13XXX_IRQSTAT1_WARMI (1 << 9) | ||
97 | #define MC13XXX_IRQSTAT1_MEMHLDI (1 << 10) | ||
98 | #define MC13783_IRQSTAT1_PWRRDYI (1 << 11) | ||
99 | #define MC13XXX_IRQSTAT1_THWARNLI (1 << 12) | ||
100 | #define MC13XXX_IRQSTAT1_THWARNHI (1 << 13) | ||
101 | #define MC13XXX_IRQSTAT1_CLKI (1 << 14) | ||
102 | #define MC13783_IRQSTAT1_SEMAFI (1 << 15) | ||
103 | #define MC13783_IRQSTAT1_MC2BI (1 << 17) | ||
104 | #define MC13783_IRQSTAT1_HSDETI (1 << 18) | ||
105 | #define MC13783_IRQSTAT1_HSLI (1 << 19) | ||
106 | #define MC13783_IRQSTAT1_ALSPTHI (1 << 20) | ||
107 | #define MC13783_IRQSTAT1_AHSSHORTI (1 << 21) | ||
108 | |||
109 | #define MC13XXX_IRQMASK1 4 | ||
110 | #define MC13XXX_IRQMASK1_1HZM MC13XXX_IRQSTAT1_1HZI | ||
111 | #define MC13XXX_IRQMASK1_TODAM MC13XXX_IRQSTAT1_TODAI | ||
112 | #define MC13783_IRQMASK1_ONOFD1M MC13783_IRQSTAT1_ONOFD1I | ||
113 | #define MC13783_IRQMASK1_ONOFD2M MC13783_IRQSTAT1_ONOFD2I | ||
114 | #define MC13783_IRQMASK1_ONOFD3M MC13783_IRQSTAT1_ONOFD3I | ||
115 | #define MC13XXX_IRQMASK1_SYSRSTM MC13XXX_IRQSTAT1_SYSRSTI | ||
116 | #define MC13XXX_IRQMASK1_RTCRSTM MC13XXX_IRQSTAT1_RTCRSTI | ||
117 | #define MC13XXX_IRQMASK1_PCM MC13XXX_IRQSTAT1_PCI | ||
118 | #define MC13XXX_IRQMASK1_WARMM MC13XXX_IRQSTAT1_WARMI | ||
119 | #define MC13XXX_IRQMASK1_MEMHLDM MC13XXX_IRQSTAT1_MEMHLDI | ||
120 | #define MC13783_IRQMASK1_PWRRDYM MC13783_IRQSTAT1_PWRRDYI | ||
121 | #define MC13XXX_IRQMASK1_THWARNLM MC13XXX_IRQSTAT1_THWARNLI | ||
122 | #define MC13XXX_IRQMASK1_THWARNHM MC13XXX_IRQSTAT1_THWARNHI | ||
123 | #define MC13XXX_IRQMASK1_CLKM MC13XXX_IRQSTAT1_CLKI | ||
124 | #define MC13783_IRQMASK1_SEMAFM MC13783_IRQSTAT1_SEMAFI | ||
125 | #define MC13783_IRQMASK1_MC2BM MC13783_IRQSTAT1_MC2BI | ||
126 | #define MC13783_IRQMASK1_HSDETM MC13783_IRQSTAT1_HSDETI | ||
127 | #define MC13783_IRQMASK1_HSLM MC13783_IRQSTAT1_HSLI | ||
128 | #define MC13783_IRQMASK1_ALSPTHM MC13783_IRQSTAT1_ALSPTHI | ||
129 | #define MC13783_IRQMASK1_AHSSHORTM MC13783_IRQSTAT1_AHSSHORTI | ||
130 | |||
131 | #define MC13XXX_REVISION 7 | ||
132 | #define MC13XXX_REVISION_REVMETAL (0x07 << 0) | ||
133 | #define MC13XXX_REVISION_REVFULL (0x03 << 3) | ||
134 | #define MC13XXX_REVISION_ICID (0x07 << 6) | ||
135 | #define MC13XXX_REVISION_FIN (0x03 << 9) | ||
136 | #define MC13XXX_REVISION_FAB (0x03 << 11) | ||
137 | #define MC13XXX_REVISION_ICIDCODE (0x3f << 13) | ||
138 | |||
139 | #define MC13783_ADC1 44 | ||
140 | #define MC13783_ADC1_ADEN (1 << 0) | ||
141 | #define MC13783_ADC1_RAND (1 << 1) | ||
142 | #define MC13783_ADC1_ADSEL (1 << 3) | ||
143 | #define MC13783_ADC1_ASC (1 << 20) | ||
144 | #define MC13783_ADC1_ADTRIGIGN (1 << 21) | ||
145 | |||
146 | #define MC13783_ADC2 45 | ||
147 | |||
148 | #define MC13XXX_NUMREGS 0x3f | ||
149 | |||
150 | void mc13xxx_lock(struct mc13xxx *mc13xxx) | ||
151 | { | ||
152 | if (!mutex_trylock(&mc13xxx->lock)) { | ||
153 | dev_dbg(&mc13xxx->spidev->dev, "wait for %s from %pf\n", | ||
154 | __func__, __builtin_return_address(0)); | ||
155 | |||
156 | mutex_lock(&mc13xxx->lock); | ||
157 | } | ||
158 | dev_dbg(&mc13xxx->spidev->dev, "%s from %pf\n", | ||
159 | __func__, __builtin_return_address(0)); | ||
160 | } | ||
161 | EXPORT_SYMBOL(mc13xxx_lock); | ||
162 | |||
163 | void mc13xxx_unlock(struct mc13xxx *mc13xxx) | ||
164 | { | ||
165 | dev_dbg(&mc13xxx->spidev->dev, "%s from %pf\n", | ||
166 | __func__, __builtin_return_address(0)); | ||
167 | mutex_unlock(&mc13xxx->lock); | ||
168 | } | ||
169 | EXPORT_SYMBOL(mc13xxx_unlock); | ||
170 | |||
171 | #define MC13XXX_REGOFFSET_SHIFT 25 | ||
172 | int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val) | ||
173 | { | ||
174 | struct spi_transfer t; | ||
175 | struct spi_message m; | ||
176 | int ret; | ||
177 | |||
178 | BUG_ON(!mutex_is_locked(&mc13xxx->lock)); | ||
179 | |||
180 | if (offset > MC13XXX_NUMREGS) | ||
181 | return -EINVAL; | ||
182 | |||
183 | *val = offset << MC13XXX_REGOFFSET_SHIFT; | ||
184 | |||
185 | memset(&t, 0, sizeof(t)); | ||
186 | |||
187 | t.tx_buf = val; | ||
188 | t.rx_buf = val; | ||
189 | t.len = sizeof(u32); | ||
190 | |||
191 | spi_message_init(&m); | ||
192 | spi_message_add_tail(&t, &m); | ||
193 | |||
194 | ret = spi_sync(mc13xxx->spidev, &m); | ||
195 | |||
196 | /* error in message.status implies error return from spi_sync */ | ||
197 | BUG_ON(!ret && m.status); | ||
198 | |||
199 | if (ret) | ||
200 | return ret; | ||
201 | |||
202 | *val &= 0xffffff; | ||
203 | |||
204 | dev_vdbg(&mc13xxx->spidev->dev, "[0x%02x] -> 0x%06x\n", offset, *val); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | EXPORT_SYMBOL(mc13xxx_reg_read); | ||
209 | |||
210 | int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val) | ||
211 | { | ||
212 | u32 buf; | ||
213 | struct spi_transfer t; | ||
214 | struct spi_message m; | ||
215 | int ret; | ||
216 | |||
217 | BUG_ON(!mutex_is_locked(&mc13xxx->lock)); | ||
218 | |||
219 | dev_vdbg(&mc13xxx->spidev->dev, "[0x%02x] <- 0x%06x\n", offset, val); | ||
220 | |||
221 | if (offset > MC13XXX_NUMREGS || val > 0xffffff) | ||
222 | return -EINVAL; | ||
223 | |||
224 | buf = 1 << 31 | offset << MC13XXX_REGOFFSET_SHIFT | val; | ||
225 | |||
226 | memset(&t, 0, sizeof(t)); | ||
227 | |||
228 | t.tx_buf = &buf; | ||
229 | t.rx_buf = &buf; | ||
230 | t.len = sizeof(u32); | ||
231 | |||
232 | spi_message_init(&m); | ||
233 | spi_message_add_tail(&t, &m); | ||
234 | |||
235 | ret = spi_sync(mc13xxx->spidev, &m); | ||
236 | |||
237 | BUG_ON(!ret && m.status); | ||
238 | |||
239 | if (ret) | ||
240 | return ret; | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | EXPORT_SYMBOL(mc13xxx_reg_write); | ||
245 | |||
246 | int mc13xxx_reg_rmw(struct mc13xxx *mc13xxx, unsigned int offset, | ||
247 | u32 mask, u32 val) | ||
248 | { | ||
249 | int ret; | ||
250 | u32 valread; | ||
251 | |||
252 | BUG_ON(val & ~mask); | ||
253 | |||
254 | ret = mc13xxx_reg_read(mc13xxx, offset, &valread); | ||
255 | if (ret) | ||
256 | return ret; | ||
257 | |||
258 | valread = (valread & ~mask) | val; | ||
259 | |||
260 | return mc13xxx_reg_write(mc13xxx, offset, valread); | ||
261 | } | ||
262 | EXPORT_SYMBOL(mc13xxx_reg_rmw); | ||
263 | |||
264 | int mc13xxx_irq_mask(struct mc13xxx *mc13xxx, int irq) | ||
265 | { | ||
266 | int ret; | ||
267 | unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1; | ||
268 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
269 | u32 mask; | ||
270 | |||
271 | if (irq < 0 || irq >= MC13XXX_NUM_IRQ) | ||
272 | return -EINVAL; | ||
273 | |||
274 | ret = mc13xxx_reg_read(mc13xxx, offmask, &mask); | ||
275 | if (ret) | ||
276 | return ret; | ||
277 | |||
278 | if (mask & irqbit) | ||
279 | /* already masked */ | ||
280 | return 0; | ||
281 | |||
282 | return mc13xxx_reg_write(mc13xxx, offmask, mask | irqbit); | ||
283 | } | ||
284 | EXPORT_SYMBOL(mc13xxx_irq_mask); | ||
285 | |||
286 | int mc13xxx_irq_unmask(struct mc13xxx *mc13xxx, int irq) | ||
287 | { | ||
288 | int ret; | ||
289 | unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1; | ||
290 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
291 | u32 mask; | ||
292 | |||
293 | if (irq < 0 || irq >= MC13XXX_NUM_IRQ) | ||
294 | return -EINVAL; | ||
295 | |||
296 | ret = mc13xxx_reg_read(mc13xxx, offmask, &mask); | ||
297 | if (ret) | ||
298 | return ret; | ||
299 | |||
300 | if (!(mask & irqbit)) | ||
301 | /* already unmasked */ | ||
302 | return 0; | ||
303 | |||
304 | return mc13xxx_reg_write(mc13xxx, offmask, mask & ~irqbit); | ||
305 | } | ||
306 | EXPORT_SYMBOL(mc13xxx_irq_unmask); | ||
307 | |||
308 | int mc13xxx_irq_status(struct mc13xxx *mc13xxx, int irq, | ||
309 | int *enabled, int *pending) | ||
310 | { | ||
311 | int ret; | ||
312 | unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1; | ||
313 | unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1; | ||
314 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
315 | |||
316 | if (irq < 0 || irq >= MC13XXX_NUM_IRQ) | ||
317 | return -EINVAL; | ||
318 | |||
319 | if (enabled) { | ||
320 | u32 mask; | ||
321 | |||
322 | ret = mc13xxx_reg_read(mc13xxx, offmask, &mask); | ||
323 | if (ret) | ||
324 | return ret; | ||
325 | |||
326 | *enabled = mask & irqbit; | ||
327 | } | ||
328 | |||
329 | if (pending) { | ||
330 | u32 stat; | ||
331 | |||
332 | ret = mc13xxx_reg_read(mc13xxx, offstat, &stat); | ||
333 | if (ret) | ||
334 | return ret; | ||
335 | |||
336 | *pending = stat & irqbit; | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | EXPORT_SYMBOL(mc13xxx_irq_status); | ||
342 | |||
343 | int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq) | ||
344 | { | ||
345 | unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1; | ||
346 | unsigned int val = 1 << (irq < 24 ? irq : irq - 24); | ||
347 | |||
348 | BUG_ON(irq < 0 || irq >= MC13XXX_NUM_IRQ); | ||
349 | |||
350 | return mc13xxx_reg_write(mc13xxx, offstat, val); | ||
351 | } | ||
352 | EXPORT_SYMBOL(mc13xxx_irq_ack); | ||
353 | |||
354 | int mc13xxx_irq_request_nounmask(struct mc13xxx *mc13xxx, int irq, | ||
355 | irq_handler_t handler, const char *name, void *dev) | ||
356 | { | ||
357 | BUG_ON(!mutex_is_locked(&mc13xxx->lock)); | ||
358 | BUG_ON(!handler); | ||
359 | |||
360 | if (irq < 0 || irq >= MC13XXX_NUM_IRQ) | ||
361 | return -EINVAL; | ||
362 | |||
363 | if (mc13xxx->irqhandler[irq]) | ||
364 | return -EBUSY; | ||
365 | |||
366 | mc13xxx->irqhandler[irq] = handler; | ||
367 | mc13xxx->irqdata[irq] = dev; | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | EXPORT_SYMBOL(mc13xxx_irq_request_nounmask); | ||
372 | |||
373 | int mc13xxx_irq_request(struct mc13xxx *mc13xxx, int irq, | ||
374 | irq_handler_t handler, const char *name, void *dev) | ||
375 | { | ||
376 | int ret; | ||
377 | |||
378 | ret = mc13xxx_irq_request_nounmask(mc13xxx, irq, handler, name, dev); | ||
379 | if (ret) | ||
380 | return ret; | ||
381 | |||
382 | ret = mc13xxx_irq_unmask(mc13xxx, irq); | ||
383 | if (ret) { | ||
384 | mc13xxx->irqhandler[irq] = NULL; | ||
385 | mc13xxx->irqdata[irq] = NULL; | ||
386 | return ret; | ||
387 | } | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | EXPORT_SYMBOL(mc13xxx_irq_request); | ||
392 | |||
393 | int mc13xxx_irq_free(struct mc13xxx *mc13xxx, int irq, void *dev) | ||
394 | { | ||
395 | int ret; | ||
396 | BUG_ON(!mutex_is_locked(&mc13xxx->lock)); | ||
397 | |||
398 | if (irq < 0 || irq >= MC13XXX_NUM_IRQ || !mc13xxx->irqhandler[irq] || | ||
399 | mc13xxx->irqdata[irq] != dev) | ||
400 | return -EINVAL; | ||
401 | |||
402 | ret = mc13xxx_irq_mask(mc13xxx, irq); | ||
403 | if (ret) | ||
404 | return ret; | ||
405 | |||
406 | mc13xxx->irqhandler[irq] = NULL; | ||
407 | mc13xxx->irqdata[irq] = NULL; | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | EXPORT_SYMBOL(mc13xxx_irq_free); | ||
412 | |||
413 | static inline irqreturn_t mc13xxx_irqhandler(struct mc13xxx *mc13xxx, int irq) | ||
414 | { | ||
415 | return mc13xxx->irqhandler[irq](irq, mc13xxx->irqdata[irq]); | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * returns: number of handled irqs or negative error | ||
420 | * locking: holds mc13xxx->lock | ||
421 | */ | ||
422 | static int mc13xxx_irq_handle(struct mc13xxx *mc13xxx, | ||
423 | unsigned int offstat, unsigned int offmask, int baseirq) | ||
424 | { | ||
425 | u32 stat, mask; | ||
426 | int ret = mc13xxx_reg_read(mc13xxx, offstat, &stat); | ||
427 | int num_handled = 0; | ||
428 | |||
429 | if (ret) | ||
430 | return ret; | ||
431 | |||
432 | ret = mc13xxx_reg_read(mc13xxx, offmask, &mask); | ||
433 | if (ret) | ||
434 | return ret; | ||
435 | |||
436 | while (stat & ~mask) { | ||
437 | int irq = __ffs(stat & ~mask); | ||
438 | |||
439 | stat &= ~(1 << irq); | ||
440 | |||
441 | if (likely(mc13xxx->irqhandler[baseirq + irq])) { | ||
442 | irqreturn_t handled; | ||
443 | |||
444 | handled = mc13xxx_irqhandler(mc13xxx, baseirq + irq); | ||
445 | if (handled == IRQ_HANDLED) | ||
446 | num_handled++; | ||
447 | } else { | ||
448 | dev_err(&mc13xxx->spidev->dev, | ||
449 | "BUG: irq %u but no handler\n", | ||
450 | baseirq + irq); | ||
451 | |||
452 | mask |= 1 << irq; | ||
453 | |||
454 | ret = mc13xxx_reg_write(mc13xxx, offmask, mask); | ||
455 | } | ||
456 | } | ||
457 | |||
458 | return num_handled; | ||
459 | } | ||
460 | |||
461 | static irqreturn_t mc13xxx_irq_thread(int irq, void *data) | ||
462 | { | ||
463 | struct mc13xxx *mc13xxx = data; | ||
464 | irqreturn_t ret; | ||
465 | int handled = 0; | ||
466 | |||
467 | mc13xxx_lock(mc13xxx); | ||
468 | |||
469 | ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT0, | ||
470 | MC13XXX_IRQMASK0, 0); | ||
471 | if (ret > 0) | ||
472 | handled = 1; | ||
473 | |||
474 | ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT1, | ||
475 | MC13XXX_IRQMASK1, 24); | ||
476 | if (ret > 0) | ||
477 | handled = 1; | ||
478 | |||
479 | mc13xxx_unlock(mc13xxx); | ||
480 | |||
481 | return IRQ_RETVAL(handled); | ||
482 | } | ||
483 | |||
484 | enum mc13xxx_id { | ||
485 | MC13XXX_ID_MC13783, | ||
486 | MC13XXX_ID_MC13892, | ||
487 | MC13XXX_ID_INVALID, | ||
488 | }; | ||
489 | |||
490 | const char *mc13xxx_chipname[] = { | ||
491 | [MC13XXX_ID_MC13783] = "mc13783", | ||
492 | [MC13XXX_ID_MC13892] = "mc13892", | ||
493 | }; | ||
494 | |||
495 | #define maskval(reg, mask) (((reg) & (mask)) >> __ffs(mask)) | ||
496 | static int mc13xxx_identify(struct mc13xxx *mc13xxx, enum mc13xxx_id *id) | ||
497 | { | ||
498 | u32 icid; | ||
499 | u32 revision; | ||
500 | const char *name; | ||
501 | int ret; | ||
502 | |||
503 | ret = mc13xxx_reg_read(mc13xxx, 46, &icid); | ||
504 | if (ret) | ||
505 | return ret; | ||
506 | |||
507 | icid = (icid >> 6) & 0x7; | ||
508 | |||
509 | switch (icid) { | ||
510 | case 2: | ||
511 | *id = MC13XXX_ID_MC13783; | ||
512 | name = "mc13783"; | ||
513 | break; | ||
514 | case 7: | ||
515 | *id = MC13XXX_ID_MC13892; | ||
516 | name = "mc13892"; | ||
517 | break; | ||
518 | default: | ||
519 | *id = MC13XXX_ID_INVALID; | ||
520 | break; | ||
521 | } | ||
522 | |||
523 | if (*id == MC13XXX_ID_MC13783 || *id == MC13XXX_ID_MC13892) { | ||
524 | ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision); | ||
525 | if (ret) | ||
526 | return ret; | ||
527 | |||
528 | dev_info(&mc13xxx->spidev->dev, "%s: rev: %d.%d, " | ||
529 | "fin: %d, fab: %d, icid: %d/%d\n", | ||
530 | mc13xxx_chipname[*id], | ||
531 | maskval(revision, MC13XXX_REVISION_REVFULL), | ||
532 | maskval(revision, MC13XXX_REVISION_REVMETAL), | ||
533 | maskval(revision, MC13XXX_REVISION_FIN), | ||
534 | maskval(revision, MC13XXX_REVISION_FAB), | ||
535 | maskval(revision, MC13XXX_REVISION_ICID), | ||
536 | maskval(revision, MC13XXX_REVISION_ICIDCODE)); | ||
537 | } | ||
538 | |||
539 | if (*id != MC13XXX_ID_INVALID) { | ||
540 | const struct spi_device_id *devid = | ||
541 | spi_get_device_id(mc13xxx->spidev); | ||
542 | if (!devid || devid->driver_data != *id) | ||
543 | dev_warn(&mc13xxx->spidev->dev, "device id doesn't " | ||
544 | "match auto detection!\n"); | ||
545 | } | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx) | ||
551 | { | ||
552 | const struct spi_device_id *devid = | ||
553 | spi_get_device_id(mc13xxx->spidev); | ||
554 | |||
555 | if (!devid) | ||
556 | return NULL; | ||
557 | |||
558 | return mc13xxx_chipname[devid->driver_data]; | ||
559 | } | ||
560 | |||
561 | #include <linux/mfd/mc13783.h> | ||
562 | |||
563 | int mc13xxx_get_flags(struct mc13xxx *mc13xxx) | ||
564 | { | ||
565 | struct mc13xxx_platform_data *pdata = | ||
566 | dev_get_platdata(&mc13xxx->spidev->dev); | ||
567 | |||
568 | return pdata->flags; | ||
569 | } | ||
570 | EXPORT_SYMBOL(mc13xxx_get_flags); | ||
571 | |||
572 | #define MC13783_ADC1_CHAN0_SHIFT 5 | ||
573 | #define MC13783_ADC1_CHAN1_SHIFT 8 | ||
574 | |||
575 | struct mc13xxx_adcdone_data { | ||
576 | struct mc13xxx *mc13xxx; | ||
577 | struct completion done; | ||
578 | }; | ||
579 | |||
580 | static irqreturn_t mc13783_handler_adcdone(int irq, void *data) | ||
581 | { | ||
582 | struct mc13xxx_adcdone_data *adcdone_data = data; | ||
583 | |||
584 | mc13xxx_irq_ack(adcdone_data->mc13xxx, irq); | ||
585 | |||
586 | complete_all(&adcdone_data->done); | ||
587 | |||
588 | return IRQ_HANDLED; | ||
589 | } | ||
590 | |||
591 | #define MC13783_ADC_WORKING (1 << 0) | ||
592 | |||
593 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | ||
594 | unsigned int channel, unsigned int *sample) | ||
595 | { | ||
596 | struct mc13xxx *mc13xxx = &mc13783->mc13xxx; | ||
597 | u32 adc0, adc1, old_adc0; | ||
598 | int i, ret; | ||
599 | struct mc13xxx_adcdone_data adcdone_data = { | ||
600 | .mc13xxx = mc13xxx, | ||
601 | }; | ||
602 | init_completion(&adcdone_data.done); | ||
603 | |||
604 | dev_dbg(&mc13xxx->spidev->dev, "%s\n", __func__); | ||
605 | |||
606 | mc13xxx_lock(mc13xxx); | ||
607 | |||
608 | if (mc13783->adcflags & MC13783_ADC_WORKING) { | ||
609 | ret = -EBUSY; | ||
610 | goto out; | ||
611 | } | ||
612 | |||
613 | mc13783->adcflags |= MC13783_ADC_WORKING; | ||
614 | |||
615 | mc13xxx_reg_read(mc13xxx, MC13783_ADC0, &old_adc0); | ||
616 | |||
617 | adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; | ||
618 | adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC; | ||
619 | |||
620 | if (channel > 7) | ||
621 | adc1 |= MC13783_ADC1_ADSEL; | ||
622 | |||
623 | switch (mode) { | ||
624 | case MC13783_ADC_MODE_TS: | ||
625 | adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_TSMOD0 | | ||
626 | MC13783_ADC0_TSMOD1; | ||
627 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | ||
628 | break; | ||
629 | |||
630 | case MC13783_ADC_MODE_SINGLE_CHAN: | ||
631 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; | ||
632 | adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; | ||
633 | adc1 |= MC13783_ADC1_RAND; | ||
634 | break; | ||
635 | |||
636 | case MC13783_ADC_MODE_MULT_CHAN: | ||
637 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; | ||
638 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | ||
639 | break; | ||
640 | |||
641 | default: | ||
642 | mc13783_unlock(mc13783); | ||
643 | return -EINVAL; | ||
644 | } | ||
645 | |||
646 | dev_dbg(&mc13783->mc13xxx.spidev->dev, "%s: request irq\n", __func__); | ||
647 | mc13xxx_irq_request(mc13xxx, MC13783_IRQ_ADCDONE, | ||
648 | mc13783_handler_adcdone, __func__, &adcdone_data); | ||
649 | mc13xxx_irq_ack(mc13xxx, MC13783_IRQ_ADCDONE); | ||
650 | |||
651 | mc13xxx_reg_write(mc13xxx, MC13783_ADC0, adc0); | ||
652 | mc13xxx_reg_write(mc13xxx, MC13783_ADC1, adc1); | ||
653 | |||
654 | mc13xxx_unlock(mc13xxx); | ||
655 | |||
656 | ret = wait_for_completion_interruptible_timeout(&adcdone_data.done, HZ); | ||
657 | |||
658 | if (!ret) | ||
659 | ret = -ETIMEDOUT; | ||
660 | |||
661 | mc13xxx_lock(mc13xxx); | ||
662 | |||
663 | mc13xxx_irq_free(mc13xxx, MC13783_IRQ_ADCDONE, &adcdone_data); | ||
664 | |||
665 | if (ret > 0) | ||
666 | for (i = 0; i < 4; ++i) { | ||
667 | ret = mc13xxx_reg_read(mc13xxx, | ||
668 | MC13783_ADC2, &sample[i]); | ||
669 | if (ret) | ||
670 | break; | ||
671 | } | ||
672 | |||
673 | if (mode == MC13783_ADC_MODE_TS) | ||
674 | /* restore TSMOD */ | ||
675 | mc13xxx_reg_write(mc13xxx, MC13783_ADC0, old_adc0); | ||
676 | |||
677 | mc13783->adcflags &= ~MC13783_ADC_WORKING; | ||
678 | out: | ||
679 | mc13xxx_unlock(mc13xxx); | ||
680 | |||
681 | return ret; | ||
682 | } | ||
683 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); | ||
684 | |||
685 | static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, | ||
686 | const char *format, void *pdata, size_t pdata_size) | ||
687 | { | ||
688 | char buf[30]; | ||
689 | const char *name = mc13xxx_get_chipname(mc13xxx); | ||
690 | |||
691 | struct mfd_cell cell = { | ||
692 | .platform_data = pdata, | ||
693 | .data_size = pdata_size, | ||
694 | }; | ||
695 | |||
696 | /* there is no asnprintf in the kernel :-( */ | ||
697 | if (snprintf(buf, sizeof(buf), format, name) > sizeof(buf)) | ||
698 | return -E2BIG; | ||
699 | |||
700 | cell.name = kmemdup(buf, strlen(buf) + 1, GFP_KERNEL); | ||
701 | if (!cell.name) | ||
702 | return -ENOMEM; | ||
703 | |||
704 | return mfd_add_devices(&mc13xxx->spidev->dev, -1, &cell, 1, NULL, 0); | ||
705 | } | ||
706 | |||
707 | static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) | ||
708 | { | ||
709 | return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0); | ||
710 | } | ||
711 | |||
712 | static int mc13xxx_probe(struct spi_device *spi) | ||
713 | { | ||
714 | struct mc13xxx *mc13xxx; | ||
715 | struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev); | ||
716 | enum mc13xxx_id id; | ||
717 | int ret; | ||
718 | |||
719 | mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); | ||
720 | if (!mc13xxx) | ||
721 | return -ENOMEM; | ||
722 | |||
723 | dev_set_drvdata(&spi->dev, mc13xxx); | ||
724 | spi->mode = SPI_MODE_0 | SPI_CS_HIGH; | ||
725 | spi->bits_per_word = 32; | ||
726 | spi_setup(spi); | ||
727 | |||
728 | mc13xxx->spidev = spi; | ||
729 | |||
730 | mutex_init(&mc13xxx->lock); | ||
731 | mc13xxx_lock(mc13xxx); | ||
732 | |||
733 | ret = mc13xxx_identify(mc13xxx, &id); | ||
734 | if (ret || id == MC13XXX_ID_INVALID) | ||
735 | goto err_revision; | ||
736 | |||
737 | /* mask all irqs */ | ||
738 | ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff); | ||
739 | if (ret) | ||
740 | goto err_mask; | ||
741 | |||
742 | ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK1, 0x00ffffff); | ||
743 | if (ret) | ||
744 | goto err_mask; | ||
745 | |||
746 | ret = request_threaded_irq(spi->irq, NULL, mc13xxx_irq_thread, | ||
747 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx); | ||
748 | |||
749 | if (ret) { | ||
750 | err_mask: | ||
751 | err_revision: | ||
752 | mutex_unlock(&mc13xxx->lock); | ||
753 | dev_set_drvdata(&spi->dev, NULL); | ||
754 | kfree(mc13xxx); | ||
755 | return ret; | ||
756 | } | ||
757 | |||
758 | mc13xxx_unlock(mc13xxx); | ||
759 | |||
760 | if (pdata->flags & MC13XXX_USE_ADC) | ||
761 | mc13xxx_add_subdevice(mc13xxx, "%s-adc"); | ||
762 | |||
763 | if (pdata->flags & MC13XXX_USE_CODEC) | ||
764 | mc13xxx_add_subdevice(mc13xxx, "%s-codec"); | ||
765 | |||
766 | if (pdata->flags & MC13XXX_USE_REGULATOR) { | ||
767 | struct mc13xxx_regulator_platform_data regulator_pdata = { | ||
768 | .num_regulators = pdata->num_regulators, | ||
769 | .regulators = pdata->regulators, | ||
770 | }; | ||
771 | |||
772 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", | ||
773 | ®ulator_pdata, sizeof(regulator_pdata)); | ||
774 | } | ||
775 | |||
776 | if (pdata->flags & MC13XXX_USE_RTC) | ||
777 | mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); | ||
778 | |||
779 | if (pdata->flags & MC13XXX_USE_TOUCHSCREEN) | ||
780 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); | ||
781 | |||
782 | if (pdata->flags & MC13XXX_USE_LED) { | ||
783 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", | ||
784 | pdata->leds, sizeof(*pdata->leds)); | ||
785 | } | ||
786 | |||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | static int __devexit mc13xxx_remove(struct spi_device *spi) | ||
791 | { | ||
792 | struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev); | ||
793 | |||
794 | free_irq(mc13xxx->spidev->irq, mc13xxx); | ||
795 | |||
796 | mfd_remove_devices(&spi->dev); | ||
797 | |||
798 | kfree(mc13xxx); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static const struct spi_device_id mc13xxx_device_id[] = { | ||
804 | { | ||
805 | .name = "mc13783", | ||
806 | .driver_data = MC13XXX_ID_MC13783, | ||
807 | }, { | ||
808 | .name = "mc13892", | ||
809 | .driver_data = MC13XXX_ID_MC13892, | ||
810 | }, { | ||
811 | /* sentinel */ | ||
812 | } | ||
813 | }; | ||
814 | |||
815 | static struct spi_driver mc13xxx_driver = { | ||
816 | .id_table = mc13xxx_device_id, | ||
817 | .driver = { | ||
818 | .name = "mc13xxx", | ||
819 | .bus = &spi_bus_type, | ||
820 | .owner = THIS_MODULE, | ||
821 | }, | ||
822 | .probe = mc13xxx_probe, | ||
823 | .remove = __devexit_p(mc13xxx_remove), | ||
824 | }; | ||
825 | |||
826 | static int __init mc13xxx_init(void) | ||
827 | { | ||
828 | return spi_register_driver(&mc13xxx_driver); | ||
829 | } | ||
830 | subsys_initcall(mc13xxx_init); | ||
831 | |||
832 | static void __exit mc13xxx_exit(void) | ||
833 | { | ||
834 | spi_unregister_driver(&mc13xxx_driver); | ||
835 | } | ||
836 | module_exit(mc13xxx_exit); | ||
837 | |||
838 | MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC"); | ||
839 | MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); | ||
840 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 1823a57b7d8f..ec99f681e773 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -38,10 +38,12 @@ static int mfd_add_device(struct device *parent, int id, | |||
38 | pdev->dev.parent = parent; | 38 | pdev->dev.parent = parent; |
39 | platform_set_drvdata(pdev, cell->driver_data); | 39 | platform_set_drvdata(pdev, cell->driver_data); |
40 | 40 | ||
41 | ret = platform_device_add_data(pdev, | 41 | if (cell->data_size) { |
42 | cell->platform_data, cell->data_size); | 42 | ret = platform_device_add_data(pdev, |
43 | if (ret) | 43 | cell->platform_data, cell->data_size); |
44 | goto fail_res; | 44 | if (ret) |
45 | goto fail_res; | ||
46 | } | ||
45 | 47 | ||
46 | for (r = 0; r < cell->num_resources; r++) { | 48 | for (r = 0; r < cell->num_resources; r++) { |
47 | res[r].name = cell->resources[r].name; | 49 | res[r].name = cell->resources[r].name; |
@@ -65,9 +67,11 @@ static int mfd_add_device(struct device *parent, int id, | |||
65 | res[r].end = cell->resources[r].end; | 67 | res[r].end = cell->resources[r].end; |
66 | } | 68 | } |
67 | 69 | ||
68 | ret = acpi_check_resource_conflict(res); | 70 | if (!cell->ignore_resource_conflicts) { |
69 | if (ret) | 71 | ret = acpi_check_resource_conflict(res); |
70 | goto fail_res; | 72 | if (ret) |
73 | goto fail_res; | ||
74 | } | ||
71 | } | 75 | } |
72 | 76 | ||
73 | ret = platform_device_add_resources(pdev, res, cell->num_resources); | 77 | ret = platform_device_add_resources(pdev, res, cell->num_resources); |
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 23e585527285..501ce13b693e 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -25,13 +25,6 @@ | |||
25 | 25 | ||
26 | #include <linux/mfd/pcf50633/core.h> | 26 | #include <linux/mfd/pcf50633/core.h> |
27 | 27 | ||
28 | int pcf50633_irq_init(struct pcf50633 *pcf, int irq); | ||
29 | void pcf50633_irq_free(struct pcf50633 *pcf); | ||
30 | #ifdef CONFIG_PM | ||
31 | int pcf50633_irq_suspend(struct pcf50633 *pcf); | ||
32 | int pcf50633_irq_resume(struct pcf50633 *pcf); | ||
33 | #endif | ||
34 | |||
35 | static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data) | 28 | static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data) |
36 | { | 29 | { |
37 | int ret; | 30 | int ret; |
@@ -346,12 +339,14 @@ static int __devexit pcf50633_remove(struct i2c_client *client) | |||
346 | struct pcf50633 *pcf = i2c_get_clientdata(client); | 339 | struct pcf50633 *pcf = i2c_get_clientdata(client); |
347 | int i; | 340 | int i; |
348 | 341 | ||
342 | sysfs_remove_group(&client->dev.kobj, &pcf_attr_group); | ||
349 | pcf50633_irq_free(pcf); | 343 | pcf50633_irq_free(pcf); |
350 | 344 | ||
351 | platform_device_unregister(pcf->input_pdev); | 345 | platform_device_unregister(pcf->input_pdev); |
352 | platform_device_unregister(pcf->rtc_pdev); | 346 | platform_device_unregister(pcf->rtc_pdev); |
353 | platform_device_unregister(pcf->mbc_pdev); | 347 | platform_device_unregister(pcf->mbc_pdev); |
354 | platform_device_unregister(pcf->adc_pdev); | 348 | platform_device_unregister(pcf->adc_pdev); |
349 | platform_device_unregister(pcf->bl_pdev); | ||
355 | 350 | ||
356 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) | 351 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) |
357 | platform_device_unregister(pcf->regulator_pdev[i]); | 352 | platform_device_unregister(pcf->regulator_pdev[i]); |
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c index 49b4d069cbf9..f1714f93af9d 100644 --- a/drivers/mfd/sh_mobile_sdhi.c +++ b/drivers/mfd/sh_mobile_sdhi.c | |||
@@ -65,6 +65,17 @@ static void sh_mobile_sdhi_set_pwr(struct platform_device *tmio, int state) | |||
65 | p->set_pwr(pdev, state); | 65 | p->set_pwr(pdev, state); |
66 | } | 66 | } |
67 | 67 | ||
68 | static int sh_mobile_sdhi_get_cd(struct platform_device *tmio) | ||
69 | { | ||
70 | struct platform_device *pdev = to_platform_device(tmio->dev.parent); | ||
71 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; | ||
72 | |||
73 | if (p && p->get_cd) | ||
74 | return p->get_cd(pdev); | ||
75 | else | ||
76 | return -ENOSYS; | ||
77 | } | ||
78 | |||
68 | static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | 79 | static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) |
69 | { | 80 | { |
70 | struct sh_mobile_sdhi *priv; | 81 | struct sh_mobile_sdhi *priv; |
@@ -106,12 +117,20 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
106 | 117 | ||
107 | mmc_data->hclk = clk_get_rate(priv->clk); | 118 | mmc_data->hclk = clk_get_rate(priv->clk); |
108 | mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; | 119 | mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; |
120 | mmc_data->get_cd = sh_mobile_sdhi_get_cd; | ||
109 | mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; | 121 | mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; |
110 | if (p) { | 122 | if (p) { |
111 | mmc_data->flags = p->tmio_flags; | 123 | mmc_data->flags = p->tmio_flags; |
112 | mmc_data->ocr_mask = p->tmio_ocr_mask; | 124 | mmc_data->ocr_mask = p->tmio_ocr_mask; |
125 | mmc_data->capabilities |= p->tmio_caps; | ||
113 | } | 126 | } |
114 | 127 | ||
128 | /* | ||
129 | * All SDHI blocks support 2-byte and larger block sizes in 4-bit | ||
130 | * bus width mode. | ||
131 | */ | ||
132 | mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES; | ||
133 | |||
115 | if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { | 134 | if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { |
116 | priv->param_tx.slave_id = p->dma_slave_tx; | 135 | priv->param_tx.slave_id = p->dma_slave_tx; |
117 | priv->param_rx.slave_id = p->dma_slave_rx; | 136 | priv->param_rx.slave_id = p->dma_slave_rx; |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 0754c5e91995..b11487f1e1cb 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c | |||
@@ -873,6 +873,28 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe) | |||
873 | return ret; | 873 | return ret; |
874 | } | 874 | } |
875 | 875 | ||
876 | #ifdef CONFIG_PM | ||
877 | static int stmpe_suspend(struct device *dev) | ||
878 | { | ||
879 | struct i2c_client *i2c = to_i2c_client(dev); | ||
880 | |||
881 | if (device_may_wakeup(&i2c->dev)) | ||
882 | enable_irq_wake(i2c->irq); | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | static int stmpe_resume(struct device *dev) | ||
888 | { | ||
889 | struct i2c_client *i2c = to_i2c_client(dev); | ||
890 | |||
891 | if (device_may_wakeup(&i2c->dev)) | ||
892 | disable_irq_wake(i2c->irq); | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | #endif | ||
897 | |||
876 | static int __devinit stmpe_probe(struct i2c_client *i2c, | 898 | static int __devinit stmpe_probe(struct i2c_client *i2c, |
877 | const struct i2c_device_id *id) | 899 | const struct i2c_device_id *id) |
878 | { | 900 | { |
@@ -960,9 +982,19 @@ static const struct i2c_device_id stmpe_id[] = { | |||
960 | }; | 982 | }; |
961 | MODULE_DEVICE_TABLE(i2c, stmpe_id); | 983 | MODULE_DEVICE_TABLE(i2c, stmpe_id); |
962 | 984 | ||
985 | #ifdef CONFIG_PM | ||
986 | static const struct dev_pm_ops stmpe_dev_pm_ops = { | ||
987 | .suspend = stmpe_suspend, | ||
988 | .resume = stmpe_resume, | ||
989 | }; | ||
990 | #endif | ||
991 | |||
963 | static struct i2c_driver stmpe_driver = { | 992 | static struct i2c_driver stmpe_driver = { |
964 | .driver.name = "stmpe", | 993 | .driver.name = "stmpe", |
965 | .driver.owner = THIS_MODULE, | 994 | .driver.owner = THIS_MODULE, |
995 | #ifdef CONFIG_PM | ||
996 | .driver.pm = &stmpe_dev_pm_ops, | ||
997 | #endif | ||
966 | .probe = stmpe_probe, | 998 | .probe = stmpe_probe, |
967 | .remove = __devexit_p(stmpe_remove), | 999 | .remove = __devexit_p(stmpe_remove), |
968 | .id_table = stmpe_id, | 1000 | .id_table = stmpe_id, |
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index ef6c42c8917a..1ea80d8ad915 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -155,7 +155,7 @@ static struct resource __devinitdata tc6393xb_nand_resources[] = { | |||
155 | }, | 155 | }, |
156 | }; | 156 | }; |
157 | 157 | ||
158 | static struct resource __devinitdata tc6393xb_mmc_resources[] = { | 158 | static struct resource tc6393xb_mmc_resources[] = { |
159 | { | 159 | { |
160 | .start = 0x800, | 160 | .start = 0x800, |
161 | .end = 0x9ff, | 161 | .end = 0x9ff, |
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index ac5995026c88..727f62c15a60 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c | |||
@@ -43,6 +43,8 @@ | |||
43 | 43 | ||
44 | #include <linux/timb_dma.h> | 44 | #include <linux/timb_dma.h> |
45 | 45 | ||
46 | #include <linux/ks8842.h> | ||
47 | |||
46 | #include "timberdale.h" | 48 | #include "timberdale.h" |
47 | 49 | ||
48 | #define DRIVER_NAME "timberdale" | 50 | #define DRIVER_NAME "timberdale" |
@@ -161,6 +163,12 @@ static const __devinitconst struct resource timberdale_spi_resources[] = { | |||
161 | }, | 163 | }, |
162 | }; | 164 | }; |
163 | 165 | ||
166 | static __devinitdata struct ks8842_platform_data | ||
167 | timberdale_ks8842_platform_data = { | ||
168 | .rx_dma_channel = DMA_ETH_RX, | ||
169 | .tx_dma_channel = DMA_ETH_TX | ||
170 | }; | ||
171 | |||
164 | static const __devinitconst struct resource timberdale_eth_resources[] = { | 172 | static const __devinitconst struct resource timberdale_eth_resources[] = { |
165 | { | 173 | { |
166 | .start = ETHOFFSET, | 174 | .start = ETHOFFSET, |
@@ -389,6 +397,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { | |||
389 | .name = "ks8842", | 397 | .name = "ks8842", |
390 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 398 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
391 | .resources = timberdale_eth_resources, | 399 | .resources = timberdale_eth_resources, |
400 | .platform_data = &timberdale_ks8842_platform_data, | ||
401 | .data_size = sizeof(timberdale_ks8842_platform_data) | ||
392 | }, | 402 | }, |
393 | }; | 403 | }; |
394 | 404 | ||
@@ -447,6 +457,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
447 | .name = "ks8842", | 457 | .name = "ks8842", |
448 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 458 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
449 | .resources = timberdale_eth_resources, | 459 | .resources = timberdale_eth_resources, |
460 | .platform_data = &timberdale_ks8842_platform_data, | ||
461 | .data_size = sizeof(timberdale_ks8842_platform_data) | ||
450 | }, | 462 | }, |
451 | }; | 463 | }; |
452 | 464 | ||
@@ -538,6 +550,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | |||
538 | .name = "ks8842", | 550 | .name = "ks8842", |
539 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 551 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
540 | .resources = timberdale_eth_resources, | 552 | .resources = timberdale_eth_resources, |
553 | .platform_data = &timberdale_ks8842_platform_data, | ||
554 | .data_size = sizeof(timberdale_ks8842_platform_data) | ||
541 | }, | 555 | }, |
542 | }; | 556 | }; |
543 | 557 | ||
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index fc0197649281..33ba7723c967 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c | |||
@@ -68,7 +68,7 @@ static int tps6507x_i2c_write_device(struct tps6507x_dev *tps6507x, char reg, | |||
68 | u8 msg[TPS6507X_MAX_REGISTER + 1]; | 68 | u8 msg[TPS6507X_MAX_REGISTER + 1]; |
69 | int ret; | 69 | int ret; |
70 | 70 | ||
71 | if (bytes > (TPS6507X_MAX_REGISTER + 1)) | 71 | if (bytes > TPS6507X_MAX_REGISTER) |
72 | return -EINVAL; | 72 | return -EINVAL; |
73 | 73 | ||
74 | msg[0] = reg; | 74 | msg[0] = reg; |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 4cde31e6a252..b4931ab34929 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c | |||
@@ -15,6 +15,8 @@ | |||
15 | * published by the Free Software Foundation. | 15 | * published by the Free Software Foundation. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/irq.h> | ||
18 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 21 | #include <linux/module.h> |
20 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
@@ -29,9 +31,64 @@ | |||
29 | #define TPS6586X_GPIOSET1 0x5d | 31 | #define TPS6586X_GPIOSET1 0x5d |
30 | #define TPS6586X_GPIOSET2 0x5e | 32 | #define TPS6586X_GPIOSET2 0x5e |
31 | 33 | ||
34 | /* interrupt control registers */ | ||
35 | #define TPS6586X_INT_ACK1 0xb5 | ||
36 | #define TPS6586X_INT_ACK2 0xb6 | ||
37 | #define TPS6586X_INT_ACK3 0xb7 | ||
38 | #define TPS6586X_INT_ACK4 0xb8 | ||
39 | |||
40 | /* interrupt mask registers */ | ||
41 | #define TPS6586X_INT_MASK1 0xb0 | ||
42 | #define TPS6586X_INT_MASK2 0xb1 | ||
43 | #define TPS6586X_INT_MASK3 0xb2 | ||
44 | #define TPS6586X_INT_MASK4 0xb3 | ||
45 | #define TPS6586X_INT_MASK5 0xb4 | ||
46 | |||
32 | /* device id */ | 47 | /* device id */ |
33 | #define TPS6586X_VERSIONCRC 0xcd | 48 | #define TPS6586X_VERSIONCRC 0xcd |
34 | #define TPS658621A_VERSIONCRC 0x15 | 49 | #define TPS658621A_VERSIONCRC 0x15 |
50 | #define TPS658621C_VERSIONCRC 0x2c | ||
51 | |||
52 | struct tps6586x_irq_data { | ||
53 | u8 mask_reg; | ||
54 | u8 mask_mask; | ||
55 | }; | ||
56 | |||
57 | #define TPS6586X_IRQ(_reg, _mask) \ | ||
58 | { \ | ||
59 | .mask_reg = (_reg) - TPS6586X_INT_MASK1, \ | ||
60 | .mask_mask = (_mask), \ | ||
61 | } | ||
62 | |||
63 | static const struct tps6586x_irq_data tps6586x_irqs[] = { | ||
64 | [TPS6586X_INT_PLDO_0] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 0), | ||
65 | [TPS6586X_INT_PLDO_1] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 1), | ||
66 | [TPS6586X_INT_PLDO_2] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 2), | ||
67 | [TPS6586X_INT_PLDO_3] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 3), | ||
68 | [TPS6586X_INT_PLDO_4] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 4), | ||
69 | [TPS6586X_INT_PLDO_5] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 5), | ||
70 | [TPS6586X_INT_PLDO_6] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 6), | ||
71 | [TPS6586X_INT_PLDO_7] = TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 7), | ||
72 | [TPS6586X_INT_COMP_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 0), | ||
73 | [TPS6586X_INT_ADC] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 1), | ||
74 | [TPS6586X_INT_PLDO_8] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 2), | ||
75 | [TPS6586X_INT_PLDO_9] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 3), | ||
76 | [TPS6586X_INT_PSM_0] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 4), | ||
77 | [TPS6586X_INT_PSM_1] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 5), | ||
78 | [TPS6586X_INT_PSM_2] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 6), | ||
79 | [TPS6586X_INT_PSM_3] = TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 7), | ||
80 | [TPS6586X_INT_RTC_ALM1] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 4), | ||
81 | [TPS6586X_INT_ACUSB_OVP] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 0x03), | ||
82 | [TPS6586X_INT_USB_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 2), | ||
83 | [TPS6586X_INT_AC_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 3), | ||
84 | [TPS6586X_INT_BAT_DET] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 1 << 0), | ||
85 | [TPS6586X_INT_CHG_STAT] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 0xfc), | ||
86 | [TPS6586X_INT_CHG_TEMP] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 0x06), | ||
87 | [TPS6586X_INT_PP] = TPS6586X_IRQ(TPS6586X_INT_MASK3, 0xf0), | ||
88 | [TPS6586X_INT_RESUME] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 5), | ||
89 | [TPS6586X_INT_LOW_SYS] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 6), | ||
90 | [TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1), | ||
91 | }; | ||
35 | 92 | ||
36 | struct tps6586x { | 93 | struct tps6586x { |
37 | struct mutex lock; | 94 | struct mutex lock; |
@@ -39,6 +96,12 @@ struct tps6586x { | |||
39 | struct i2c_client *client; | 96 | struct i2c_client *client; |
40 | 97 | ||
41 | struct gpio_chip gpio; | 98 | struct gpio_chip gpio; |
99 | struct irq_chip irq_chip; | ||
100 | struct mutex irq_lock; | ||
101 | int irq_base; | ||
102 | u32 irq_en; | ||
103 | u8 mask_cache[5]; | ||
104 | u8 mask_reg[5]; | ||
42 | }; | 105 | }; |
43 | 106 | ||
44 | static inline int __tps6586x_read(struct i2c_client *client, | 107 | static inline int __tps6586x_read(struct i2c_client *client, |
@@ -262,6 +325,129 @@ static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) | |||
262 | return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); | 325 | return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); |
263 | } | 326 | } |
264 | 327 | ||
328 | static void tps6586x_irq_lock(unsigned int irq) | ||
329 | { | ||
330 | struct tps6586x *tps6586x = get_irq_chip_data(irq); | ||
331 | |||
332 | mutex_lock(&tps6586x->irq_lock); | ||
333 | } | ||
334 | |||
335 | static void tps6586x_irq_enable(unsigned int irq) | ||
336 | { | ||
337 | struct tps6586x *tps6586x = get_irq_chip_data(irq); | ||
338 | unsigned int __irq = irq - tps6586x->irq_base; | ||
339 | const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; | ||
340 | |||
341 | tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask; | ||
342 | tps6586x->irq_en |= (1 << __irq); | ||
343 | } | ||
344 | |||
345 | static void tps6586x_irq_disable(unsigned int irq) | ||
346 | { | ||
347 | struct tps6586x *tps6586x = get_irq_chip_data(irq); | ||
348 | |||
349 | unsigned int __irq = irq - tps6586x->irq_base; | ||
350 | const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; | ||
351 | |||
352 | tps6586x->mask_reg[data->mask_reg] |= data->mask_mask; | ||
353 | tps6586x->irq_en &= ~(1 << __irq); | ||
354 | } | ||
355 | |||
356 | static void tps6586x_irq_sync_unlock(unsigned int irq) | ||
357 | { | ||
358 | struct tps6586x *tps6586x = get_irq_chip_data(irq); | ||
359 | int i; | ||
360 | |||
361 | for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) { | ||
362 | if (tps6586x->mask_reg[i] != tps6586x->mask_cache[i]) { | ||
363 | if (!WARN_ON(tps6586x_write(tps6586x->dev, | ||
364 | TPS6586X_INT_MASK1 + i, | ||
365 | tps6586x->mask_reg[i]))) | ||
366 | tps6586x->mask_cache[i] = tps6586x->mask_reg[i]; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | mutex_unlock(&tps6586x->irq_lock); | ||
371 | } | ||
372 | |||
373 | static irqreturn_t tps6586x_irq(int irq, void *data) | ||
374 | { | ||
375 | struct tps6586x *tps6586x = data; | ||
376 | u32 acks; | ||
377 | int ret = 0; | ||
378 | |||
379 | ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, | ||
380 | sizeof(acks), (uint8_t *)&acks); | ||
381 | |||
382 | if (ret < 0) { | ||
383 | dev_err(tps6586x->dev, "failed to read interrupt status\n"); | ||
384 | return IRQ_NONE; | ||
385 | } | ||
386 | |||
387 | acks = le32_to_cpu(acks); | ||
388 | |||
389 | while (acks) { | ||
390 | int i = __ffs(acks); | ||
391 | |||
392 | if (tps6586x->irq_en & (1 << i)) | ||
393 | handle_nested_irq(tps6586x->irq_base + i); | ||
394 | |||
395 | acks &= ~(1 << i); | ||
396 | } | ||
397 | |||
398 | return IRQ_HANDLED; | ||
399 | } | ||
400 | |||
401 | static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq, | ||
402 | int irq_base) | ||
403 | { | ||
404 | int i, ret; | ||
405 | u8 tmp[4]; | ||
406 | |||
407 | if (!irq_base) { | ||
408 | dev_warn(tps6586x->dev, "No interrupt support on IRQ base\n"); | ||
409 | return -EINVAL; | ||
410 | } | ||
411 | |||
412 | mutex_init(&tps6586x->irq_lock); | ||
413 | for (i = 0; i < 5; i++) { | ||
414 | tps6586x->mask_cache[i] = 0xff; | ||
415 | tps6586x->mask_reg[i] = 0xff; | ||
416 | tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff); | ||
417 | } | ||
418 | |||
419 | tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, sizeof(tmp), tmp); | ||
420 | |||
421 | tps6586x->irq_base = irq_base; | ||
422 | |||
423 | tps6586x->irq_chip.name = "tps6586x"; | ||
424 | tps6586x->irq_chip.enable = tps6586x_irq_enable; | ||
425 | tps6586x->irq_chip.disable = tps6586x_irq_disable; | ||
426 | tps6586x->irq_chip.bus_lock = tps6586x_irq_lock; | ||
427 | tps6586x->irq_chip.bus_sync_unlock = tps6586x_irq_sync_unlock; | ||
428 | |||
429 | for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) { | ||
430 | int __irq = i + tps6586x->irq_base; | ||
431 | set_irq_chip_data(__irq, tps6586x); | ||
432 | set_irq_chip_and_handler(__irq, &tps6586x->irq_chip, | ||
433 | handle_simple_irq); | ||
434 | set_irq_nested_thread(__irq, 1); | ||
435 | #ifdef CONFIG_ARM | ||
436 | set_irq_flags(__irq, IRQF_VALID); | ||
437 | #endif | ||
438 | } | ||
439 | |||
440 | ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT, | ||
441 | "tps6586x", tps6586x); | ||
442 | |||
443 | if (!ret) { | ||
444 | device_init_wakeup(tps6586x->dev, 1); | ||
445 | enable_irq_wake(irq); | ||
446 | } | ||
447 | |||
448 | return ret; | ||
449 | } | ||
450 | |||
265 | static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, | 451 | static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, |
266 | struct tps6586x_platform_data *pdata) | 452 | struct tps6586x_platform_data *pdata) |
267 | { | 453 | { |
@@ -273,13 +459,19 @@ static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, | |||
273 | subdev = &pdata->subdevs[i]; | 459 | subdev = &pdata->subdevs[i]; |
274 | 460 | ||
275 | pdev = platform_device_alloc(subdev->name, subdev->id); | 461 | pdev = platform_device_alloc(subdev->name, subdev->id); |
462 | if (!pdev) { | ||
463 | ret = -ENOMEM; | ||
464 | goto failed; | ||
465 | } | ||
276 | 466 | ||
277 | pdev->dev.parent = tps6586x->dev; | 467 | pdev->dev.parent = tps6586x->dev; |
278 | pdev->dev.platform_data = subdev->platform_data; | 468 | pdev->dev.platform_data = subdev->platform_data; |
279 | 469 | ||
280 | ret = platform_device_add(pdev); | 470 | ret = platform_device_add(pdev); |
281 | if (ret) | 471 | if (ret) { |
472 | platform_device_put(pdev); | ||
282 | goto failed; | 473 | goto failed; |
474 | } | ||
283 | } | 475 | } |
284 | return 0; | 476 | return 0; |
285 | 477 | ||
@@ -306,7 +498,8 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | |||
306 | return -EIO; | 498 | return -EIO; |
307 | } | 499 | } |
308 | 500 | ||
309 | if (ret != TPS658621A_VERSIONCRC) { | 501 | if ((ret != TPS658621A_VERSIONCRC) && |
502 | (ret != TPS658621C_VERSIONCRC)) { | ||
310 | dev_err(&client->dev, "Unsupported chip ID: %x\n", ret); | 503 | dev_err(&client->dev, "Unsupported chip ID: %x\n", ret); |
311 | return -ENODEV; | 504 | return -ENODEV; |
312 | } | 505 | } |
@@ -321,6 +514,15 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | |||
321 | 514 | ||
322 | mutex_init(&tps6586x->lock); | 515 | mutex_init(&tps6586x->lock); |
323 | 516 | ||
517 | if (client->irq) { | ||
518 | ret = tps6586x_irq_init(tps6586x, client->irq, | ||
519 | pdata->irq_base); | ||
520 | if (ret) { | ||
521 | dev_err(&client->dev, "IRQ init failed: %d\n", ret); | ||
522 | goto err_irq_init; | ||
523 | } | ||
524 | } | ||
525 | |||
324 | ret = tps6586x_add_subdevs(tps6586x, pdata); | 526 | ret = tps6586x_add_subdevs(tps6586x, pdata); |
325 | if (ret) { | 527 | if (ret) { |
326 | dev_err(&client->dev, "add devices failed: %d\n", ret); | 528 | dev_err(&client->dev, "add devices failed: %d\n", ret); |
@@ -332,12 +534,31 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | |||
332 | return 0; | 534 | return 0; |
333 | 535 | ||
334 | err_add_devs: | 536 | err_add_devs: |
537 | if (client->irq) | ||
538 | free_irq(client->irq, tps6586x); | ||
539 | err_irq_init: | ||
335 | kfree(tps6586x); | 540 | kfree(tps6586x); |
336 | return ret; | 541 | return ret; |
337 | } | 542 | } |
338 | 543 | ||
339 | static int __devexit tps6586x_i2c_remove(struct i2c_client *client) | 544 | static int __devexit tps6586x_i2c_remove(struct i2c_client *client) |
340 | { | 545 | { |
546 | struct tps6586x *tps6586x = i2c_get_clientdata(client); | ||
547 | struct tps6586x_platform_data *pdata = client->dev.platform_data; | ||
548 | int ret; | ||
549 | |||
550 | if (client->irq) | ||
551 | free_irq(client->irq, tps6586x); | ||
552 | |||
553 | if (pdata->gpio_base) { | ||
554 | ret = gpiochip_remove(&tps6586x->gpio); | ||
555 | if (ret) | ||
556 | dev_err(&client->dev, "Can't remove gpio chip: %d\n", | ||
557 | ret); | ||
558 | } | ||
559 | |||
560 | tps6586x_remove_subdevs(tps6586x); | ||
561 | kfree(tps6586x); | ||
341 | return 0; | 562 | return 0; |
342 | } | 563 | } |
343 | 564 | ||
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 5d0fb60a4c14..35275ba7096f 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -115,6 +115,12 @@ | |||
115 | #define twl_has_codec() false | 115 | #define twl_has_codec() false |
116 | #endif | 116 | #endif |
117 | 117 | ||
118 | #if defined(CONFIG_CHARGER_TWL4030) || defined(CONFIG_CHARGER_TWL4030_MODULE) | ||
119 | #define twl_has_bci() true | ||
120 | #else | ||
121 | #define twl_has_bci() false | ||
122 | #endif | ||
123 | |||
118 | /* Triton Core internal information (BEGIN) */ | 124 | /* Triton Core internal information (BEGIN) */ |
119 | 125 | ||
120 | /* Last - for index max*/ | 126 | /* Last - for index max*/ |
@@ -202,12 +208,6 @@ | |||
202 | 208 | ||
203 | /* Few power values */ | 209 | /* Few power values */ |
204 | #define R_CFG_BOOT 0x05 | 210 | #define R_CFG_BOOT 0x05 |
205 | #define R_PROTECT_KEY 0x0E | ||
206 | |||
207 | /* access control values for R_PROTECT_KEY */ | ||
208 | #define KEY_UNLOCK1 0xce | ||
209 | #define KEY_UNLOCK2 0xec | ||
210 | #define KEY_LOCK 0x00 | ||
211 | 211 | ||
212 | /* some fields in R_CFG_BOOT */ | 212 | /* some fields in R_CFG_BOOT */ |
213 | #define HFCLK_FREQ_19p2_MHZ (1 << 0) | 213 | #define HFCLK_FREQ_19p2_MHZ (1 << 0) |
@@ -255,7 +255,7 @@ struct twl_mapping { | |||
255 | unsigned char sid; /* Slave ID */ | 255 | unsigned char sid; /* Slave ID */ |
256 | unsigned char base; /* base address */ | 256 | unsigned char base; /* base address */ |
257 | }; | 257 | }; |
258 | struct twl_mapping *twl_map; | 258 | static struct twl_mapping *twl_map; |
259 | 259 | ||
260 | static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | 260 | static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { |
261 | /* | 261 | /* |
@@ -832,6 +832,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
832 | return PTR_ERR(child); | 832 | return PTR_ERR(child); |
833 | } | 833 | } |
834 | 834 | ||
835 | if (twl_has_bci() && pdata->bci && | ||
836 | !(features & (TPS_SUBSET | TWL5031))) { | ||
837 | child = add_child(3, "twl4030_bci", | ||
838 | pdata->bci, sizeof(*pdata->bci), false, | ||
839 | /* irq0 = CHG_PRES, irq1 = BCI */ | ||
840 | pdata->irq_base + BCI_PRES_INTR_OFFSET, | ||
841 | pdata->irq_base + BCI_INTR_OFFSET); | ||
842 | if (IS_ERR(child)) | ||
843 | return PTR_ERR(child); | ||
844 | } | ||
845 | |||
835 | return 0; | 846 | return 0; |
836 | } | 847 | } |
837 | 848 | ||
@@ -846,8 +857,8 @@ static inline int __init protect_pm_master(void) | |||
846 | { | 857 | { |
847 | int e = 0; | 858 | int e = 0; |
848 | 859 | ||
849 | e = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_LOCK, | 860 | e = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, |
850 | R_PROTECT_KEY); | 861 | TWL4030_PM_MASTER_PROTECT_KEY); |
851 | return e; | 862 | return e; |
852 | } | 863 | } |
853 | 864 | ||
@@ -855,10 +866,13 @@ static inline int __init unprotect_pm_master(void) | |||
855 | { | 866 | { |
856 | int e = 0; | 867 | int e = 0; |
857 | 868 | ||
858 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK1, | 869 | e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
859 | R_PROTECT_KEY); | 870 | TWL4030_PM_MASTER_KEY_CFG1, |
860 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, KEY_UNLOCK2, | 871 | TWL4030_PM_MASTER_PROTECT_KEY); |
861 | R_PROTECT_KEY); | 872 | e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
873 | TWL4030_PM_MASTER_KEY_CFG2, | ||
874 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
875 | |||
862 | return e; | 876 | return e; |
863 | } | 877 | } |
864 | 878 | ||
diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h new file mode 100644 index 000000000000..8c50a556e986 --- /dev/null +++ b/drivers/mfd/twl-core.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __TWL_CORE_H__ | ||
2 | #define __TWL_CORE_H__ | ||
3 | |||
4 | extern int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | ||
5 | extern int twl6030_exit_irq(void); | ||
6 | extern int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | ||
7 | extern int twl4030_exit_irq(void); | ||
8 | extern int twl4030_init_chip_irq(const char *chip); | ||
9 | |||
10 | #endif /* __TWL_CORE_H__ */ | ||
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index b9fda7018cef..5d3a1478004b 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include <linux/i2c/twl.h> | 36 | #include <linux/i2c/twl.h> |
37 | 37 | ||
38 | #include "twl-core.h" | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * TWL4030 IRQ handling has two stages in hardware, and thus in software. | 41 | * TWL4030 IRQ handling has two stages in hardware, and thus in software. |
@@ -144,6 +145,7 @@ static const struct sih sih_modules_twl4030[6] = { | |||
144 | .name = "bci", | 145 | .name = "bci", |
145 | .module = TWL4030_MODULE_INTERRUPTS, | 146 | .module = TWL4030_MODULE_INTERRUPTS, |
146 | .control_offset = TWL4030_INTERRUPTS_BCISIHCTRL, | 147 | .control_offset = TWL4030_INTERRUPTS_BCISIHCTRL, |
148 | .set_cor = true, | ||
147 | .bits = 12, | 149 | .bits = 12, |
148 | .bytes_ixr = 2, | 150 | .bytes_ixr = 2, |
149 | .edr_offset = TWL4030_INTERRUPTS_BCIEDR1, | 151 | .edr_offset = TWL4030_INTERRUPTS_BCIEDR1, |
@@ -408,7 +410,7 @@ static int twl4030_init_sih_modules(unsigned line) | |||
408 | * set Clear-On-Read (COR) bit. | 410 | * set Clear-On-Read (COR) bit. |
409 | * | 411 | * |
410 | * NOTE that sometimes COR polarity is documented as being | 412 | * NOTE that sometimes COR polarity is documented as being |
411 | * inverted: for MADC and BCI, COR=1 means "clear on write". | 413 | * inverted: for MADC, COR=1 means "clear on write". |
412 | * And for PWR_INT it's not documented... | 414 | * And for PWR_INT it's not documented... |
413 | */ | 415 | */ |
414 | if (sih->set_cor) { | 416 | if (sih->set_cor) { |
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 7efa8789a3a2..16422de0823a 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c | |||
@@ -63,10 +63,6 @@ static u8 twl4030_start_script_address = 0x2b; | |||
63 | #define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59) | 63 | #define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59) |
64 | #define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a) | 64 | #define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a) |
65 | 65 | ||
66 | #define R_PROTECT_KEY 0x0E | ||
67 | #define R_KEY_1 0xC0 | ||
68 | #define R_KEY_2 0x0C | ||
69 | |||
70 | /* resource configuration registers | 66 | /* resource configuration registers |
71 | <RESOURCE>_DEV_GRP at address 'n+0' | 67 | <RESOURCE>_DEV_GRP at address 'n+0' |
72 | <RESOURCE>_TYPE at address 'n+1' | 68 | <RESOURCE>_TYPE at address 'n+1' |
@@ -465,15 +461,17 @@ int twl4030_remove_script(u8 flags) | |||
465 | { | 461 | { |
466 | int err = 0; | 462 | int err = 0; |
467 | 463 | ||
468 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1, | 464 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
469 | R_PROTECT_KEY); | 465 | TWL4030_PM_MASTER_KEY_CFG1, |
466 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
470 | if (err) { | 467 | if (err) { |
471 | pr_err("twl4030: unable to unlock PROTECT_KEY\n"); | 468 | pr_err("twl4030: unable to unlock PROTECT_KEY\n"); |
472 | return err; | 469 | return err; |
473 | } | 470 | } |
474 | 471 | ||
475 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2, | 472 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
476 | R_PROTECT_KEY); | 473 | TWL4030_PM_MASTER_KEY_CFG2, |
474 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
477 | if (err) { | 475 | if (err) { |
478 | pr_err("twl4030: unable to unlock PROTECT_KEY\n"); | 476 | pr_err("twl4030: unable to unlock PROTECT_KEY\n"); |
479 | return err; | 477 | return err; |
@@ -504,7 +502,8 @@ int twl4030_remove_script(u8 flags) | |||
504 | return err; | 502 | return err; |
505 | } | 503 | } |
506 | 504 | ||
507 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY); | 505 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, |
506 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
508 | if (err) | 507 | if (err) |
509 | pr_err("TWL4030 Unable to relock registers\n"); | 508 | pr_err("TWL4030 Unable to relock registers\n"); |
510 | 509 | ||
@@ -518,13 +517,15 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | |||
518 | struct twl4030_resconfig *resconfig; | 517 | struct twl4030_resconfig *resconfig; |
519 | u8 address = twl4030_start_script_address; | 518 | u8 address = twl4030_start_script_address; |
520 | 519 | ||
521 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1, | 520 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
522 | R_PROTECT_KEY); | 521 | TWL4030_PM_MASTER_KEY_CFG1, |
522 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
523 | if (err) | 523 | if (err) |
524 | goto unlock; | 524 | goto unlock; |
525 | 525 | ||
526 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2, | 526 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
527 | R_PROTECT_KEY); | 527 | TWL4030_PM_MASTER_KEY_CFG2, |
528 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
528 | if (err) | 529 | if (err) |
529 | goto unlock; | 530 | goto unlock; |
530 | 531 | ||
@@ -546,7 +547,8 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | |||
546 | } | 547 | } |
547 | } | 548 | } |
548 | 549 | ||
549 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY); | 550 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, |
551 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
550 | if (err) | 552 | if (err) |
551 | pr_err("TWL4030 Unable to relock registers\n"); | 553 | pr_err("TWL4030 Unable to relock registers\n"); |
552 | return; | 554 | return; |
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index 10bf228ad626..aaedb11d9d2c 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c | |||
@@ -36,6 +36,9 @@ | |||
36 | #include <linux/irq.h> | 36 | #include <linux/irq.h> |
37 | #include <linux/kthread.h> | 37 | #include <linux/kthread.h> |
38 | #include <linux/i2c/twl.h> | 38 | #include <linux/i2c/twl.h> |
39 | #include <linux/platform_device.h> | ||
40 | |||
41 | #include "twl-core.h" | ||
39 | 42 | ||
40 | /* | 43 | /* |
41 | * TWL6030 (unlike its predecessors, which had two level interrupt handling) | 44 | * TWL6030 (unlike its predecessors, which had two level interrupt handling) |
@@ -223,6 +226,78 @@ int twl6030_interrupt_mask(u8 bit_mask, u8 offset) | |||
223 | } | 226 | } |
224 | EXPORT_SYMBOL(twl6030_interrupt_mask); | 227 | EXPORT_SYMBOL(twl6030_interrupt_mask); |
225 | 228 | ||
229 | int twl6030_mmc_card_detect_config(void) | ||
230 | { | ||
231 | int ret; | ||
232 | u8 reg_val = 0; | ||
233 | |||
234 | /* Unmasking the Card detect Interrupt line for MMC1 from Phoenix */ | ||
235 | twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK, | ||
236 | REG_INT_MSK_LINE_B); | ||
237 | twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK, | ||
238 | REG_INT_MSK_STS_B); | ||
239 | /* | ||
240 | * Intially Configuring MMC_CTRL for receving interrupts & | ||
241 | * Card status on TWL6030 for MMC1 | ||
242 | */ | ||
243 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, ®_val, TWL6030_MMCCTRL); | ||
244 | if (ret < 0) { | ||
245 | pr_err("twl6030: Failed to read MMCCTRL, error %d\n", ret); | ||
246 | return ret; | ||
247 | } | ||
248 | reg_val &= ~VMMC_AUTO_OFF; | ||
249 | reg_val |= SW_FC; | ||
250 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_MMCCTRL); | ||
251 | if (ret < 0) { | ||
252 | pr_err("twl6030: Failed to write MMCCTRL, error %d\n", ret); | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | /* Configuring PullUp-PullDown register */ | ||
257 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, ®_val, | ||
258 | TWL6030_CFG_INPUT_PUPD3); | ||
259 | if (ret < 0) { | ||
260 | pr_err("twl6030: Failed to read CFG_INPUT_PUPD3, error %d\n", | ||
261 | ret); | ||
262 | return ret; | ||
263 | } | ||
264 | reg_val &= ~(MMC_PU | MMC_PD); | ||
265 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, | ||
266 | TWL6030_CFG_INPUT_PUPD3); | ||
267 | if (ret < 0) { | ||
268 | pr_err("twl6030: Failed to write CFG_INPUT_PUPD3, error %d\n", | ||
269 | ret); | ||
270 | return ret; | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
274 | EXPORT_SYMBOL(twl6030_mmc_card_detect_config); | ||
275 | |||
276 | int twl6030_mmc_card_detect(struct device *dev, int slot) | ||
277 | { | ||
278 | int ret = -EIO; | ||
279 | u8 read_reg = 0; | ||
280 | struct platform_device *pdev = to_platform_device(dev); | ||
281 | |||
282 | if (pdev->id) { | ||
283 | /* TWL6030 provide's Card detect support for | ||
284 | * only MMC1 controller. | ||
285 | */ | ||
286 | pr_err("Unkown MMC controller %d in %s\n", pdev->id, __func__); | ||
287 | return ret; | ||
288 | } | ||
289 | /* | ||
290 | * BIT0 of MMC_CTRL on TWL6030 provides card status for MMC1 | ||
291 | * 0 - Card not present ,1 - Card present | ||
292 | */ | ||
293 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &read_reg, | ||
294 | TWL6030_MMCCTRL); | ||
295 | if (ret >= 0) | ||
296 | ret = read_reg & STS_MMC; | ||
297 | return ret; | ||
298 | } | ||
299 | EXPORT_SYMBOL(twl6030_mmc_card_detect); | ||
300 | |||
226 | int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | 301 | int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) |
227 | { | 302 | { |
228 | 303 | ||
diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c new file mode 100644 index 000000000000..ebb059765edd --- /dev/null +++ b/drivers/mfd/vx855.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * Linux multi-function-device driver (MFD) for the integrated peripherals | ||
3 | * of the VIA VX855 chipset | ||
4 | * | ||
5 | * Copyright (C) 2009 VIA Technologies, Inc. | ||
6 | * Copyright (C) 2010 One Laptop per Child | ||
7 | * Author: Harald Welte <HaraldWelte@viatech.com> | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of | ||
13 | * the License, or (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
23 | * MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/mfd/core.h> | ||
33 | |||
34 | /* offset into pci config space indicating the 16bit register containing | ||
35 | * the power management IO space base */ | ||
36 | #define VX855_CFG_PMIO_OFFSET 0x88 | ||
37 | |||
38 | /* ACPI I/O Space registers */ | ||
39 | #define VX855_PMIO_ACPI 0x00 | ||
40 | #define VX855_PMIO_ACPI_LEN 0x0b | ||
41 | |||
42 | /* Processor Power Management */ | ||
43 | #define VX855_PMIO_PPM 0x10 | ||
44 | #define VX855_PMIO_PPM_LEN 0x08 | ||
45 | |||
46 | /* General Purpose Power Management */ | ||
47 | #define VX855_PMIO_GPPM 0x20 | ||
48 | #define VX855_PMIO_R_GPI 0x48 | ||
49 | #define VX855_PMIO_R_GPO 0x4c | ||
50 | #define VX855_PMIO_GPPM_LEN 0x33 | ||
51 | |||
52 | #define VSPIC_MMIO_SIZE 0x1000 | ||
53 | |||
54 | static struct resource vx855_gpio_resources[] = { | ||
55 | { | ||
56 | .flags = IORESOURCE_IO, | ||
57 | }, | ||
58 | { | ||
59 | .flags = IORESOURCE_IO, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | static struct mfd_cell vx855_cells[] = { | ||
64 | { | ||
65 | .name = "vx855_gpio", | ||
66 | .num_resources = ARRAY_SIZE(vx855_gpio_resources), | ||
67 | .resources = vx855_gpio_resources, | ||
68 | |||
69 | /* we must ignore resource conflicts, for reasons outlined in | ||
70 | * the vx855_gpio driver */ | ||
71 | .ignore_resource_conflicts = true, | ||
72 | }, | ||
73 | }; | ||
74 | |||
75 | static __devinit int vx855_probe(struct pci_dev *pdev, | ||
76 | const struct pci_device_id *id) | ||
77 | { | ||
78 | int ret; | ||
79 | u16 gpio_io_offset; | ||
80 | |||
81 | ret = pci_enable_device(pdev); | ||
82 | if (ret) | ||
83 | return -ENODEV; | ||
84 | |||
85 | pci_read_config_word(pdev, VX855_CFG_PMIO_OFFSET, &gpio_io_offset); | ||
86 | if (!gpio_io_offset) { | ||
87 | dev_warn(&pdev->dev, | ||
88 | "BIOS did not assign PMIO base offset?!?\n"); | ||
89 | ret = -ENODEV; | ||
90 | goto out; | ||
91 | } | ||
92 | |||
93 | /* mask out the lowest seven bits, as they are always zero, but | ||
94 | * hardware returns them as 0x01 */ | ||
95 | gpio_io_offset &= 0xff80; | ||
96 | |||
97 | /* As the region identified here includes many non-GPIO things, we | ||
98 | * only work with the specific registers that concern us. */ | ||
99 | vx855_gpio_resources[0].start = gpio_io_offset + VX855_PMIO_R_GPI; | ||
100 | vx855_gpio_resources[0].end = vx855_gpio_resources[0].start + 3; | ||
101 | vx855_gpio_resources[1].start = gpio_io_offset + VX855_PMIO_R_GPO; | ||
102 | vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3; | ||
103 | |||
104 | ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells), | ||
105 | NULL, 0); | ||
106 | |||
107 | /* we always return -ENODEV here in order to enable other | ||
108 | * drivers like old, not-yet-platform_device ported i2c-viapro */ | ||
109 | return -ENODEV; | ||
110 | out: | ||
111 | pci_disable_device(pdev); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | static void vx855_remove(struct pci_dev *pdev) | ||
116 | { | ||
117 | mfd_remove_devices(&pdev->dev); | ||
118 | pci_disable_device(pdev); | ||
119 | } | ||
120 | |||
121 | static struct pci_device_id vx855_pci_tbl[] = { | ||
122 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) }, | ||
123 | { 0, } | ||
124 | }; | ||
125 | |||
126 | static struct pci_driver vx855_pci_driver = { | ||
127 | .name = "vx855", | ||
128 | .id_table = vx855_pci_tbl, | ||
129 | .probe = vx855_probe, | ||
130 | .remove = __devexit_p(vx855_remove), | ||
131 | }; | ||
132 | |||
133 | static int vx855_init(void) | ||
134 | { | ||
135 | return pci_register_driver(&vx855_pci_driver); | ||
136 | } | ||
137 | module_init(vx855_init); | ||
138 | |||
139 | static void vx855_exit(void) | ||
140 | { | ||
141 | pci_unregister_driver(&vx855_pci_driver); | ||
142 | } | ||
143 | module_exit(vx855_exit); | ||
144 | |||
145 | MODULE_LICENSE("GPL"); | ||
146 | MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>"); | ||
147 | MODULE_DESCRIPTION("Driver for the VIA VX855 chipset"); | ||
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 1e7aaaf6cc6f..7d2563fc15c6 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/i2c.h> | ||
18 | #include <linux/bcd.h> | 17 | #include <linux/bcd.h> |
19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
20 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
@@ -90,14 +89,6 @@ int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = { | |||
90 | }; | 89 | }; |
91 | EXPORT_SYMBOL_GPL(wm831x_isinkv_values); | 90 | EXPORT_SYMBOL_GPL(wm831x_isinkv_values); |
92 | 91 | ||
93 | enum wm831x_parent { | ||
94 | WM8310 = 0x8310, | ||
95 | WM8311 = 0x8311, | ||
96 | WM8312 = 0x8312, | ||
97 | WM8320 = 0x8320, | ||
98 | WM8321 = 0x8321, | ||
99 | }; | ||
100 | |||
101 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) | 92 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) |
102 | { | 93 | { |
103 | if (!wm831x->locked) | 94 | if (!wm831x->locked) |
@@ -1446,7 +1437,7 @@ static struct mfd_cell backlight_devs[] = { | |||
1446 | /* | 1437 | /* |
1447 | * Instantiate the generic non-control parts of the device. | 1438 | * Instantiate the generic non-control parts of the device. |
1448 | */ | 1439 | */ |
1449 | static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | 1440 | int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) |
1450 | { | 1441 | { |
1451 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; | 1442 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; |
1452 | int rev; | 1443 | int rev; |
@@ -1540,6 +1531,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1540 | dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev); | 1531 | dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev); |
1541 | break; | 1532 | break; |
1542 | 1533 | ||
1534 | case WM8325: | ||
1535 | parent = WM8325; | ||
1536 | wm831x->num_gpio = 12; | ||
1537 | dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev); | ||
1538 | break; | ||
1539 | |||
1543 | default: | 1540 | default: |
1544 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); | 1541 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); |
1545 | ret = -EINVAL; | 1542 | ret = -EINVAL; |
@@ -1620,6 +1617,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1620 | NULL, 0); | 1617 | NULL, 0); |
1621 | break; | 1618 | break; |
1622 | 1619 | ||
1620 | case WM8325: | ||
1621 | ret = mfd_add_devices(wm831x->dev, -1, | ||
1622 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | ||
1623 | NULL, 0); | ||
1624 | break; | ||
1625 | |||
1623 | default: | 1626 | default: |
1624 | /* If this happens the bus probe function is buggy */ | 1627 | /* If this happens the bus probe function is buggy */ |
1625 | BUG(); | 1628 | BUG(); |
@@ -1660,7 +1663,7 @@ err: | |||
1660 | return ret; | 1663 | return ret; |
1661 | } | 1664 | } |
1662 | 1665 | ||
1663 | static void wm831x_device_exit(struct wm831x *wm831x) | 1666 | void wm831x_device_exit(struct wm831x *wm831x) |
1664 | { | 1667 | { |
1665 | wm831x_otp_exit(wm831x); | 1668 | wm831x_otp_exit(wm831x); |
1666 | mfd_remove_devices(wm831x->dev); | 1669 | mfd_remove_devices(wm831x->dev); |
@@ -1670,7 +1673,7 @@ static void wm831x_device_exit(struct wm831x *wm831x) | |||
1670 | kfree(wm831x); | 1673 | kfree(wm831x); |
1671 | } | 1674 | } |
1672 | 1675 | ||
1673 | static int wm831x_device_suspend(struct wm831x *wm831x) | 1676 | int wm831x_device_suspend(struct wm831x *wm831x) |
1674 | { | 1677 | { |
1675 | int reg, mask; | 1678 | int reg, mask; |
1676 | 1679 | ||
@@ -1706,125 +1709,6 @@ static int wm831x_device_suspend(struct wm831x *wm831x) | |||
1706 | return 0; | 1709 | return 0; |
1707 | } | 1710 | } |
1708 | 1711 | ||
1709 | static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, | 1712 | MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC"); |
1710 | int bytes, void *dest) | ||
1711 | { | ||
1712 | struct i2c_client *i2c = wm831x->control_data; | ||
1713 | int ret; | ||
1714 | u16 r = cpu_to_be16(reg); | ||
1715 | |||
1716 | ret = i2c_master_send(i2c, (unsigned char *)&r, 2); | ||
1717 | if (ret < 0) | ||
1718 | return ret; | ||
1719 | if (ret != 2) | ||
1720 | return -EIO; | ||
1721 | |||
1722 | ret = i2c_master_recv(i2c, dest, bytes); | ||
1723 | if (ret < 0) | ||
1724 | return ret; | ||
1725 | if (ret != bytes) | ||
1726 | return -EIO; | ||
1727 | return 0; | ||
1728 | } | ||
1729 | |||
1730 | /* Currently we allocate the write buffer on the stack; this is OK for | ||
1731 | * small writes - if we need to do large writes this will need to be | ||
1732 | * revised. | ||
1733 | */ | ||
1734 | static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg, | ||
1735 | int bytes, void *src) | ||
1736 | { | ||
1737 | struct i2c_client *i2c = wm831x->control_data; | ||
1738 | unsigned char msg[bytes + 2]; | ||
1739 | int ret; | ||
1740 | |||
1741 | reg = cpu_to_be16(reg); | ||
1742 | memcpy(&msg[0], ®, 2); | ||
1743 | memcpy(&msg[2], src, bytes); | ||
1744 | |||
1745 | ret = i2c_master_send(i2c, msg, bytes + 2); | ||
1746 | if (ret < 0) | ||
1747 | return ret; | ||
1748 | if (ret < bytes + 2) | ||
1749 | return -EIO; | ||
1750 | |||
1751 | return 0; | ||
1752 | } | ||
1753 | |||
1754 | static int wm831x_i2c_probe(struct i2c_client *i2c, | ||
1755 | const struct i2c_device_id *id) | ||
1756 | { | ||
1757 | struct wm831x *wm831x; | ||
1758 | |||
1759 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | ||
1760 | if (wm831x == NULL) | ||
1761 | return -ENOMEM; | ||
1762 | |||
1763 | i2c_set_clientdata(i2c, wm831x); | ||
1764 | wm831x->dev = &i2c->dev; | ||
1765 | wm831x->control_data = i2c; | ||
1766 | wm831x->read_dev = wm831x_i2c_read_device; | ||
1767 | wm831x->write_dev = wm831x_i2c_write_device; | ||
1768 | |||
1769 | return wm831x_device_init(wm831x, id->driver_data, i2c->irq); | ||
1770 | } | ||
1771 | |||
1772 | static int wm831x_i2c_remove(struct i2c_client *i2c) | ||
1773 | { | ||
1774 | struct wm831x *wm831x = i2c_get_clientdata(i2c); | ||
1775 | |||
1776 | wm831x_device_exit(wm831x); | ||
1777 | |||
1778 | return 0; | ||
1779 | } | ||
1780 | |||
1781 | static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg) | ||
1782 | { | ||
1783 | struct wm831x *wm831x = i2c_get_clientdata(i2c); | ||
1784 | |||
1785 | return wm831x_device_suspend(wm831x); | ||
1786 | } | ||
1787 | |||
1788 | static const struct i2c_device_id wm831x_i2c_id[] = { | ||
1789 | { "wm8310", WM8310 }, | ||
1790 | { "wm8311", WM8311 }, | ||
1791 | { "wm8312", WM8312 }, | ||
1792 | { "wm8320", WM8320 }, | ||
1793 | { "wm8321", WM8321 }, | ||
1794 | { } | ||
1795 | }; | ||
1796 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | ||
1797 | |||
1798 | |||
1799 | static struct i2c_driver wm831x_i2c_driver = { | ||
1800 | .driver = { | ||
1801 | .name = "wm831x", | ||
1802 | .owner = THIS_MODULE, | ||
1803 | }, | ||
1804 | .probe = wm831x_i2c_probe, | ||
1805 | .remove = wm831x_i2c_remove, | ||
1806 | .suspend = wm831x_i2c_suspend, | ||
1807 | .id_table = wm831x_i2c_id, | ||
1808 | }; | ||
1809 | |||
1810 | static int __init wm831x_i2c_init(void) | ||
1811 | { | ||
1812 | int ret; | ||
1813 | |||
1814 | ret = i2c_add_driver(&wm831x_i2c_driver); | ||
1815 | if (ret != 0) | ||
1816 | pr_err("Failed to register wm831x I2C driver: %d\n", ret); | ||
1817 | |||
1818 | return ret; | ||
1819 | } | ||
1820 | subsys_initcall(wm831x_i2c_init); | ||
1821 | |||
1822 | static void __exit wm831x_i2c_exit(void) | ||
1823 | { | ||
1824 | i2c_del_driver(&wm831x_i2c_driver); | ||
1825 | } | ||
1826 | module_exit(wm831x_i2c_exit); | ||
1827 | |||
1828 | MODULE_DESCRIPTION("I2C support for the WM831X AudioPlus PMIC"); | ||
1829 | MODULE_LICENSE("GPL"); | 1713 | MODULE_LICENSE("GPL"); |
1830 | MODULE_AUTHOR("Mark Brown"); | 1714 | MODULE_AUTHOR("Mark Brown"); |
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c new file mode 100644 index 000000000000..156b19859e81 --- /dev/null +++ b/drivers/mfd/wm831x-i2c.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * wm831x-i2c.c -- I2C access for Wolfson WM831x PMICs | ||
3 | * | ||
4 | * Copyright 2009,2010 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/mfd/core.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <linux/mfd/wm831x/core.h> | ||
23 | #include <linux/mfd/wm831x/pdata.h> | ||
24 | |||
25 | static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, | ||
26 | int bytes, void *dest) | ||
27 | { | ||
28 | struct i2c_client *i2c = wm831x->control_data; | ||
29 | int ret; | ||
30 | u16 r = cpu_to_be16(reg); | ||
31 | |||
32 | ret = i2c_master_send(i2c, (unsigned char *)&r, 2); | ||
33 | if (ret < 0) | ||
34 | return ret; | ||
35 | if (ret != 2) | ||
36 | return -EIO; | ||
37 | |||
38 | ret = i2c_master_recv(i2c, dest, bytes); | ||
39 | if (ret < 0) | ||
40 | return ret; | ||
41 | if (ret != bytes) | ||
42 | return -EIO; | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | /* Currently we allocate the write buffer on the stack; this is OK for | ||
47 | * small writes - if we need to do large writes this will need to be | ||
48 | * revised. | ||
49 | */ | ||
50 | static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg, | ||
51 | int bytes, void *src) | ||
52 | { | ||
53 | struct i2c_client *i2c = wm831x->control_data; | ||
54 | unsigned char msg[bytes + 2]; | ||
55 | int ret; | ||
56 | |||
57 | reg = cpu_to_be16(reg); | ||
58 | memcpy(&msg[0], ®, 2); | ||
59 | memcpy(&msg[2], src, bytes); | ||
60 | |||
61 | ret = i2c_master_send(i2c, msg, bytes + 2); | ||
62 | if (ret < 0) | ||
63 | return ret; | ||
64 | if (ret < bytes + 2) | ||
65 | return -EIO; | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int wm831x_i2c_probe(struct i2c_client *i2c, | ||
71 | const struct i2c_device_id *id) | ||
72 | { | ||
73 | struct wm831x *wm831x; | ||
74 | |||
75 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | ||
76 | if (wm831x == NULL) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | i2c_set_clientdata(i2c, wm831x); | ||
80 | wm831x->dev = &i2c->dev; | ||
81 | wm831x->control_data = i2c; | ||
82 | wm831x->read_dev = wm831x_i2c_read_device; | ||
83 | wm831x->write_dev = wm831x_i2c_write_device; | ||
84 | |||
85 | return wm831x_device_init(wm831x, id->driver_data, i2c->irq); | ||
86 | } | ||
87 | |||
88 | static int wm831x_i2c_remove(struct i2c_client *i2c) | ||
89 | { | ||
90 | struct wm831x *wm831x = i2c_get_clientdata(i2c); | ||
91 | |||
92 | wm831x_device_exit(wm831x); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg) | ||
98 | { | ||
99 | struct wm831x *wm831x = i2c_get_clientdata(i2c); | ||
100 | |||
101 | return wm831x_device_suspend(wm831x); | ||
102 | } | ||
103 | |||
104 | static const struct i2c_device_id wm831x_i2c_id[] = { | ||
105 | { "wm8310", WM8310 }, | ||
106 | { "wm8311", WM8311 }, | ||
107 | { "wm8312", WM8312 }, | ||
108 | { "wm8320", WM8320 }, | ||
109 | { "wm8321", WM8321 }, | ||
110 | { "wm8325", WM8325 }, | ||
111 | { } | ||
112 | }; | ||
113 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | ||
114 | |||
115 | |||
116 | static struct i2c_driver wm831x_i2c_driver = { | ||
117 | .driver = { | ||
118 | .name = "wm831x", | ||
119 | .owner = THIS_MODULE, | ||
120 | }, | ||
121 | .probe = wm831x_i2c_probe, | ||
122 | .remove = wm831x_i2c_remove, | ||
123 | .suspend = wm831x_i2c_suspend, | ||
124 | .id_table = wm831x_i2c_id, | ||
125 | }; | ||
126 | |||
127 | static int __init wm831x_i2c_init(void) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | ret = i2c_add_driver(&wm831x_i2c_driver); | ||
132 | if (ret != 0) | ||
133 | pr_err("Failed to register wm831x I2C driver: %d\n", ret); | ||
134 | |||
135 | return ret; | ||
136 | } | ||
137 | subsys_initcall(wm831x_i2c_init); | ||
138 | |||
139 | static void __exit wm831x_i2c_exit(void) | ||
140 | { | ||
141 | i2c_del_driver(&wm831x_i2c_driver); | ||
142 | } | ||
143 | module_exit(wm831x_i2c_exit); | ||
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c new file mode 100644 index 000000000000..2789b151b0f9 --- /dev/null +++ b/drivers/mfd/wm831x-spi.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * wm831x-spi.c -- SPI access for Wolfson WM831x PMICs | ||
3 | * | ||
4 | * Copyright 2009,2010 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/spi/spi.h> | ||
18 | |||
19 | #include <linux/mfd/wm831x/core.h> | ||
20 | |||
21 | static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg, | ||
22 | int bytes, void *dest) | ||
23 | { | ||
24 | u16 tx_val; | ||
25 | u16 *d = dest; | ||
26 | int r, ret; | ||
27 | |||
28 | /* Go register at a time */ | ||
29 | for (r = reg; r < reg + (bytes / 2); r++) { | ||
30 | tx_val = r | 0x8000; | ||
31 | |||
32 | ret = spi_write_then_read(wm831x->control_data, | ||
33 | (u8 *)&tx_val, 2, (u8 *)d, 2); | ||
34 | if (ret != 0) | ||
35 | return ret; | ||
36 | |||
37 | *d = be16_to_cpu(*d); | ||
38 | |||
39 | d++; | ||
40 | } | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg, | ||
46 | int bytes, void *src) | ||
47 | { | ||
48 | struct spi_device *spi = wm831x->control_data; | ||
49 | u16 *s = src; | ||
50 | u16 data[2]; | ||
51 | int ret, r; | ||
52 | |||
53 | /* Go register at a time */ | ||
54 | for (r = reg; r < reg + (bytes / 2); r++) { | ||
55 | data[0] = r; | ||
56 | data[1] = *s++; | ||
57 | |||
58 | ret = spi_write(spi, (char *)&data, sizeof(data)); | ||
59 | if (ret != 0) | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int __devinit wm831x_spi_probe(struct spi_device *spi) | ||
67 | { | ||
68 | struct wm831x *wm831x; | ||
69 | enum wm831x_parent type; | ||
70 | |||
71 | /* Currently SPI support for ID tables is unmerged, we're faking it */ | ||
72 | if (strcmp(spi->modalias, "wm8310") == 0) | ||
73 | type = WM8310; | ||
74 | else if (strcmp(spi->modalias, "wm8311") == 0) | ||
75 | type = WM8311; | ||
76 | else if (strcmp(spi->modalias, "wm8312") == 0) | ||
77 | type = WM8312; | ||
78 | else if (strcmp(spi->modalias, "wm8320") == 0) | ||
79 | type = WM8320; | ||
80 | else if (strcmp(spi->modalias, "wm8321") == 0) | ||
81 | type = WM8321; | ||
82 | else if (strcmp(spi->modalias, "wm8325") == 0) | ||
83 | type = WM8325; | ||
84 | else { | ||
85 | dev_err(&spi->dev, "Unknown device type\n"); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | ||
90 | if (wm831x == NULL) | ||
91 | return -ENOMEM; | ||
92 | |||
93 | spi->bits_per_word = 16; | ||
94 | spi->mode = SPI_MODE_0; | ||
95 | |||
96 | dev_set_drvdata(&spi->dev, wm831x); | ||
97 | wm831x->dev = &spi->dev; | ||
98 | wm831x->control_data = spi; | ||
99 | wm831x->read_dev = wm831x_spi_read_device; | ||
100 | wm831x->write_dev = wm831x_spi_write_device; | ||
101 | |||
102 | return wm831x_device_init(wm831x, type, spi->irq); | ||
103 | } | ||
104 | |||
105 | static int __devexit wm831x_spi_remove(struct spi_device *spi) | ||
106 | { | ||
107 | struct wm831x *wm831x = dev_get_drvdata(&spi->dev); | ||
108 | |||
109 | wm831x_device_exit(wm831x); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m) | ||
115 | { | ||
116 | struct wm831x *wm831x = dev_get_drvdata(&spi->dev); | ||
117 | |||
118 | return wm831x_device_suspend(wm831x); | ||
119 | } | ||
120 | |||
121 | static struct spi_driver wm8310_spi_driver = { | ||
122 | .driver = { | ||
123 | .name = "wm8310", | ||
124 | .bus = &spi_bus_type, | ||
125 | .owner = THIS_MODULE, | ||
126 | }, | ||
127 | .probe = wm831x_spi_probe, | ||
128 | .remove = __devexit_p(wm831x_spi_remove), | ||
129 | .suspend = wm831x_spi_suspend, | ||
130 | }; | ||
131 | |||
132 | static struct spi_driver wm8311_spi_driver = { | ||
133 | .driver = { | ||
134 | .name = "wm8311", | ||
135 | .bus = &spi_bus_type, | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | .probe = wm831x_spi_probe, | ||
139 | .remove = __devexit_p(wm831x_spi_remove), | ||
140 | .suspend = wm831x_spi_suspend, | ||
141 | }; | ||
142 | |||
143 | static struct spi_driver wm8312_spi_driver = { | ||
144 | .driver = { | ||
145 | .name = "wm8312", | ||
146 | .bus = &spi_bus_type, | ||
147 | .owner = THIS_MODULE, | ||
148 | }, | ||
149 | .probe = wm831x_spi_probe, | ||
150 | .remove = __devexit_p(wm831x_spi_remove), | ||
151 | .suspend = wm831x_spi_suspend, | ||
152 | }; | ||
153 | |||
154 | static struct spi_driver wm8320_spi_driver = { | ||
155 | .driver = { | ||
156 | .name = "wm8320", | ||
157 | .bus = &spi_bus_type, | ||
158 | .owner = THIS_MODULE, | ||
159 | }, | ||
160 | .probe = wm831x_spi_probe, | ||
161 | .remove = __devexit_p(wm831x_spi_remove), | ||
162 | .suspend = wm831x_spi_suspend, | ||
163 | }; | ||
164 | |||
165 | static struct spi_driver wm8321_spi_driver = { | ||
166 | .driver = { | ||
167 | .name = "wm8321", | ||
168 | .bus = &spi_bus_type, | ||
169 | .owner = THIS_MODULE, | ||
170 | }, | ||
171 | .probe = wm831x_spi_probe, | ||
172 | .remove = __devexit_p(wm831x_spi_remove), | ||
173 | .suspend = wm831x_spi_suspend, | ||
174 | }; | ||
175 | |||
176 | static struct spi_driver wm8325_spi_driver = { | ||
177 | .driver = { | ||
178 | .name = "wm8325", | ||
179 | .bus = &spi_bus_type, | ||
180 | .owner = THIS_MODULE, | ||
181 | }, | ||
182 | .probe = wm831x_spi_probe, | ||
183 | .remove = __devexit_p(wm831x_spi_remove), | ||
184 | .suspend = wm831x_spi_suspend, | ||
185 | }; | ||
186 | |||
187 | static int __init wm831x_spi_init(void) | ||
188 | { | ||
189 | int ret; | ||
190 | |||
191 | ret = spi_register_driver(&wm8310_spi_driver); | ||
192 | if (ret != 0) | ||
193 | pr_err("Failed to register WM8310 SPI driver: %d\n", ret); | ||
194 | |||
195 | ret = spi_register_driver(&wm8311_spi_driver); | ||
196 | if (ret != 0) | ||
197 | pr_err("Failed to register WM8311 SPI driver: %d\n", ret); | ||
198 | |||
199 | ret = spi_register_driver(&wm8312_spi_driver); | ||
200 | if (ret != 0) | ||
201 | pr_err("Failed to register WM8312 SPI driver: %d\n", ret); | ||
202 | |||
203 | ret = spi_register_driver(&wm8320_spi_driver); | ||
204 | if (ret != 0) | ||
205 | pr_err("Failed to register WM8320 SPI driver: %d\n", ret); | ||
206 | |||
207 | ret = spi_register_driver(&wm8321_spi_driver); | ||
208 | if (ret != 0) | ||
209 | pr_err("Failed to register WM8321 SPI driver: %d\n", ret); | ||
210 | |||
211 | ret = spi_register_driver(&wm8325_spi_driver); | ||
212 | if (ret != 0) | ||
213 | pr_err("Failed to register WM8325 SPI driver: %d\n", ret); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | subsys_initcall(wm831x_spi_init); | ||
218 | |||
219 | static void __exit wm831x_spi_exit(void) | ||
220 | { | ||
221 | spi_unregister_driver(&wm8325_spi_driver); | ||
222 | spi_unregister_driver(&wm8321_spi_driver); | ||
223 | spi_unregister_driver(&wm8320_spi_driver); | ||
224 | spi_unregister_driver(&wm8312_spi_driver); | ||
225 | spi_unregister_driver(&wm8311_spi_driver); | ||
226 | spi_unregister_driver(&wm8310_spi_driver); | ||
227 | } | ||
228 | module_exit(wm831x_spi_exit); | ||
229 | |||
230 | MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs"); | ||
231 | MODULE_LICENSE("GPL"); | ||
232 | MODULE_AUTHOR("Mark Brown"); | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 39a2173b4e6c..4d073f1e4502 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -62,6 +62,15 @@ config ATMEL_PWM | |||
62 | purposes including software controlled power-efficient backlights | 62 | purposes including software controlled power-efficient backlights |
63 | on LCD displays, motor control, and waveform generation. | 63 | on LCD displays, motor control, and waveform generation. |
64 | 64 | ||
65 | config AB8500_PWM | ||
66 | bool "AB8500 PWM support" | ||
67 | depends on AB8500_CORE | ||
68 | select HAVE_PWM | ||
69 | help | ||
70 | This driver exports functions to enable/disble/config/free Pulse | ||
71 | Width Modulation in the Analog Baseband Chip AB8500. | ||
72 | It is used by led and backlight driver to control the intensity. | ||
73 | |||
65 | config ATMEL_TCLIB | 74 | config ATMEL_TCLIB |
66 | bool "Atmel AT32/AT91 Timer/Counter Library" | 75 | bool "Atmel AT32/AT91 Timer/Counter Library" |
67 | depends on (AVR32 || ARCH_AT91) | 76 | depends on (AVR32 || ARCH_AT91) |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 47af4cd08f01..98009cc20cb9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -41,3 +41,4 @@ obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o | |||
41 | obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o | 41 | obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o |
42 | obj-$(CONFIG_PCH_PHUB) += pch_phub.o | 42 | obj-$(CONFIG_PCH_PHUB) += pch_phub.o |
43 | obj-y += ti-st/ | 43 | obj-y += ti-st/ |
44 | obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o | ||
diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c new file mode 100644 index 000000000000..54e3d05b63cc --- /dev/null +++ b/drivers/misc/ab8500-pwm.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Arun R Murthy <arun.murthy@stericsson.com> | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | */ | ||
7 | #include <linux/err.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/pwm.h> | ||
11 | #include <linux/mfd/ab8500.h> | ||
12 | #include <linux/mfd/abx500.h> | ||
13 | |||
14 | /* | ||
15 | * PWM Out generators | ||
16 | * Bank: 0x10 | ||
17 | */ | ||
18 | #define AB8500_PWM_OUT_CTRL1_REG 0x60 | ||
19 | #define AB8500_PWM_OUT_CTRL2_REG 0x61 | ||
20 | #define AB8500_PWM_OUT_CTRL7_REG 0x66 | ||
21 | |||
22 | /* backlight driver constants */ | ||
23 | #define ENABLE_PWM 1 | ||
24 | #define DISABLE_PWM 0 | ||
25 | |||
26 | struct pwm_device { | ||
27 | struct device *dev; | ||
28 | struct list_head node; | ||
29 | const char *label; | ||
30 | unsigned int pwm_id; | ||
31 | }; | ||
32 | |||
33 | static LIST_HEAD(pwm_list); | ||
34 | |||
35 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | ||
36 | { | ||
37 | int ret = 0; | ||
38 | unsigned int higher_val, lower_val; | ||
39 | u8 reg; | ||
40 | |||
41 | /* | ||
42 | * get the first 8 bits that are be written to | ||
43 | * AB8500_PWM_OUT_CTRL1_REG[0:7] | ||
44 | */ | ||
45 | lower_val = duty_ns & 0x00FF; | ||
46 | /* | ||
47 | * get bits [9:10] that are to be written to | ||
48 | * AB8500_PWM_OUT_CTRL2_REG[0:1] | ||
49 | */ | ||
50 | higher_val = ((duty_ns & 0x0300) >> 8); | ||
51 | |||
52 | reg = AB8500_PWM_OUT_CTRL1_REG + ((pwm->pwm_id - 1) * 2); | ||
53 | |||
54 | ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC, | ||
55 | reg, (u8)lower_val); | ||
56 | if (ret < 0) | ||
57 | return ret; | ||
58 | ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC, | ||
59 | (reg + 1), (u8)higher_val); | ||
60 | |||
61 | return ret; | ||
62 | } | ||
63 | EXPORT_SYMBOL(pwm_config); | ||
64 | |||
65 | int pwm_enable(struct pwm_device *pwm) | ||
66 | { | ||
67 | int ret; | ||
68 | |||
69 | ret = abx500_mask_and_set_register_interruptible(pwm->dev, | ||
70 | AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, | ||
71 | 1 << (pwm->pwm_id-1), ENABLE_PWM); | ||
72 | if (ret < 0) | ||
73 | dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n", | ||
74 | pwm->label, ret); | ||
75 | return ret; | ||
76 | } | ||
77 | EXPORT_SYMBOL(pwm_enable); | ||
78 | |||
79 | void pwm_disable(struct pwm_device *pwm) | ||
80 | { | ||
81 | int ret; | ||
82 | |||
83 | ret = abx500_mask_and_set_register_interruptible(pwm->dev, | ||
84 | AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, | ||
85 | 1 << (pwm->pwm_id-1), DISABLE_PWM); | ||
86 | if (ret < 0) | ||
87 | dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n", | ||
88 | pwm->label, ret); | ||
89 | return; | ||
90 | } | ||
91 | EXPORT_SYMBOL(pwm_disable); | ||
92 | |||
93 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
94 | { | ||
95 | struct pwm_device *pwm; | ||
96 | |||
97 | list_for_each_entry(pwm, &pwm_list, node) { | ||
98 | if (pwm->pwm_id == pwm_id) { | ||
99 | pwm->label = label; | ||
100 | pwm->pwm_id = pwm_id; | ||
101 | return pwm; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | return ERR_PTR(-ENOENT); | ||
106 | } | ||
107 | EXPORT_SYMBOL(pwm_request); | ||
108 | |||
109 | void pwm_free(struct pwm_device *pwm) | ||
110 | { | ||
111 | pwm_disable(pwm); | ||
112 | } | ||
113 | EXPORT_SYMBOL(pwm_free); | ||
114 | |||
115 | static int __devinit ab8500_pwm_probe(struct platform_device *pdev) | ||
116 | { | ||
117 | struct pwm_device *pwm; | ||
118 | /* | ||
119 | * Nothing to be done in probe, this is required to get the | ||
120 | * device which is required for ab8500 read and write | ||
121 | */ | ||
122 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | ||
123 | if (pwm == NULL) { | ||
124 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | pwm->dev = &pdev->dev; | ||
128 | pwm->pwm_id = pdev->id; | ||
129 | list_add_tail(&pwm->node, &pwm_list); | ||
130 | platform_set_drvdata(pdev, pwm); | ||
131 | dev_dbg(pwm->dev, "pwm probe successful\n"); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int __devexit ab8500_pwm_remove(struct platform_device *pdev) | ||
136 | { | ||
137 | struct pwm_device *pwm = platform_get_drvdata(pdev); | ||
138 | list_del(&pwm->node); | ||
139 | dev_dbg(&pdev->dev, "pwm driver removed\n"); | ||
140 | kfree(pwm); | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static struct platform_driver ab8500_pwm_driver = { | ||
145 | .driver = { | ||
146 | .name = "ab8500-pwm", | ||
147 | .owner = THIS_MODULE, | ||
148 | }, | ||
149 | .probe = ab8500_pwm_probe, | ||
150 | .remove = __devexit_p(ab8500_pwm_remove), | ||
151 | }; | ||
152 | |||
153 | static int __init ab8500_pwm_init(void) | ||
154 | { | ||
155 | return platform_driver_register(&ab8500_pwm_driver); | ||
156 | } | ||
157 | |||
158 | static void __exit ab8500_pwm_exit(void) | ||
159 | { | ||
160 | platform_driver_unregister(&ab8500_pwm_driver); | ||
161 | } | ||
162 | |||
163 | subsys_initcall(ab8500_pwm_init); | ||
164 | module_exit(ab8500_pwm_exit); | ||
165 | MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>"); | ||
166 | MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver"); | ||
167 | MODULE_ALIAS("AB8500 PWM driver"); | ||
168 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index e865032a52eb..82a1079bbdc7 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -483,8 +483,6 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) | |||
483 | int ret; | 483 | int ret; |
484 | 484 | ||
485 | if (gpio_is_valid(pdata->slots[0].switch_pin)) { | 485 | if (gpio_is_valid(pdata->slots[0].switch_pin)) { |
486 | pdata->suspend = omap_hsmmc_suspend_cdirq; | ||
487 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
488 | if (pdata->slots[0].cover) | 486 | if (pdata->slots[0].cover) |
489 | pdata->slots[0].get_cover_state = | 487 | pdata->slots[0].get_cover_state = |
490 | omap_hsmmc_get_cover_state; | 488 | omap_hsmmc_get_cover_state; |
@@ -2218,6 +2216,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2218 | "Unable to grab MMC CD IRQ\n"); | 2216 | "Unable to grab MMC CD IRQ\n"); |
2219 | goto err_irq_cd; | 2217 | goto err_irq_cd; |
2220 | } | 2218 | } |
2219 | pdata->suspend = omap_hsmmc_suspend_cdirq; | ||
2220 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
2221 | } | 2221 | } |
2222 | 2222 | ||
2223 | omap_hsmmc_disable_irq(host); | 2223 | omap_hsmmc_disable_irq(host); |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 0f06b8002814..ddd09840520b 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -710,9 +710,21 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
710 | host->bus_width = ios->bus_width; | 710 | host->bus_width = ios->bus_width; |
711 | } | 711 | } |
712 | 712 | ||
713 | static int sh_mmcif_get_cd(struct mmc_host *mmc) | ||
714 | { | ||
715 | struct sh_mmcif_host *host = mmc_priv(mmc); | ||
716 | struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; | ||
717 | |||
718 | if (!p->get_cd) | ||
719 | return -ENOSYS; | ||
720 | else | ||
721 | return p->get_cd(host->pd); | ||
722 | } | ||
723 | |||
713 | static struct mmc_host_ops sh_mmcif_ops = { | 724 | static struct mmc_host_ops sh_mmcif_ops = { |
714 | .request = sh_mmcif_request, | 725 | .request = sh_mmcif_request, |
715 | .set_ios = sh_mmcif_set_ios, | 726 | .set_ios = sh_mmcif_set_ios, |
727 | .get_cd = sh_mmcif_get_cd, | ||
716 | }; | 728 | }; |
717 | 729 | ||
718 | static void sh_mmcif_detect(struct mmc_host *mmc) | 730 | static void sh_mmcif_detect(struct mmc_host *mmc) |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 69d98e3bf6ab..e7765a89593e 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
@@ -658,14 +658,21 @@ static void tmio_mmc_release_dma(struct tmio_mmc_host *host) | |||
658 | static int tmio_mmc_start_data(struct tmio_mmc_host *host, | 658 | static int tmio_mmc_start_data(struct tmio_mmc_host *host, |
659 | struct mmc_data *data) | 659 | struct mmc_data *data) |
660 | { | 660 | { |
661 | struct mfd_cell *cell = host->pdev->dev.platform_data; | ||
662 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
663 | |||
661 | pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n", | 664 | pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n", |
662 | data->blksz, data->blocks); | 665 | data->blksz, data->blocks); |
663 | 666 | ||
664 | /* Hardware cannot perform 1 and 2 byte requests in 4 bit mode */ | 667 | /* Some hardware cannot perform 2 byte requests in 4 bit mode */ |
665 | if (data->blksz < 4 && host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) { | 668 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) { |
666 | pr_err("%s: %d byte block unsupported in 4 bit mode\n", | 669 | int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES; |
667 | mmc_hostname(host->mmc), data->blksz); | 670 | |
668 | return -EINVAL; | 671 | if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) { |
672 | pr_err("%s: %d byte block unsupported in 4 bit mode\n", | ||
673 | mmc_hostname(host->mmc), data->blksz); | ||
674 | return -EINVAL; | ||
675 | } | ||
669 | } | 676 | } |
670 | 677 | ||
671 | tmio_mmc_init_sg(host, data); | 678 | tmio_mmc_init_sg(host, data); |
@@ -756,10 +763,23 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) | |||
756 | (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1; | 763 | (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1; |
757 | } | 764 | } |
758 | 765 | ||
766 | static int tmio_mmc_get_cd(struct mmc_host *mmc) | ||
767 | { | ||
768 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
769 | struct mfd_cell *cell = host->pdev->dev.platform_data; | ||
770 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
771 | |||
772 | if (!pdata->get_cd) | ||
773 | return -ENOSYS; | ||
774 | else | ||
775 | return pdata->get_cd(host->pdev); | ||
776 | } | ||
777 | |||
759 | static const struct mmc_host_ops tmio_mmc_ops = { | 778 | static const struct mmc_host_ops tmio_mmc_ops = { |
760 | .request = tmio_mmc_request, | 779 | .request = tmio_mmc_request, |
761 | .set_ios = tmio_mmc_set_ios, | 780 | .set_ios = tmio_mmc_set_ios, |
762 | .get_ro = tmio_mmc_get_ro, | 781 | .get_ro = tmio_mmc_get_ro, |
782 | .get_cd = tmio_mmc_get_cd, | ||
763 | }; | 783 | }; |
764 | 784 | ||
765 | #ifdef CONFIG_PM | 785 | #ifdef CONFIG_PM |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index ec444774b9ee..60d83d983a36 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -182,7 +182,6 @@ config CHARGER_ISP1704 | |||
182 | config CHARGER_TWL4030 | 182 | config CHARGER_TWL4030 |
183 | tristate "OMAP TWL4030 BCI charger driver" | 183 | tristate "OMAP TWL4030 BCI charger driver" |
184 | depends on TWL4030_CORE | 184 | depends on TWL4030_CORE |
185 | depends on BROKEN | ||
186 | help | 185 | help |
187 | Say Y here to enable support for TWL4030 Battery Charge Interface. | 186 | Say Y here to enable support for TWL4030 Battery Charge Interface. |
188 | 187 | ||
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 28c7ae67cec9..db6b70f20511 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/mfd/ab8500.h> | 23 | #include <linux/mfd/ab8500.h> |
24 | #include <linux/mfd/abx500.h> | ||
24 | #include <linux/regulator/driver.h> | 25 | #include <linux/regulator/driver.h> |
25 | #include <linux/regulator/machine.h> | 26 | #include <linux/regulator/machine.h> |
26 | #include <linux/regulator/ab8500.h> | 27 | #include <linux/regulator/ab8500.h> |
@@ -33,9 +34,11 @@ | |||
33 | * @max_uV: maximum voltage (for variable voltage supplies) | 34 | * @max_uV: maximum voltage (for variable voltage supplies) |
34 | * @min_uV: minimum voltage (for variable voltage supplies) | 35 | * @min_uV: minimum voltage (for variable voltage supplies) |
35 | * @fixed_uV: typical voltage (for fixed voltage supplies) | 36 | * @fixed_uV: typical voltage (for fixed voltage supplies) |
37 | * @update_bank: bank to control on/off | ||
36 | * @update_reg: register to control on/off | 38 | * @update_reg: register to control on/off |
37 | * @mask: mask to enable/disable regulator | 39 | * @mask: mask to enable/disable regulator |
38 | * @enable: bits to enable the regulator in normal(high power) mode | 40 | * @enable: bits to enable the regulator in normal(high power) mode |
41 | * @voltage_bank: bank to control regulator voltage | ||
39 | * @voltage_reg: register to control regulator voltage | 42 | * @voltage_reg: register to control regulator voltage |
40 | * @voltage_mask: mask to control regulator voltage | 43 | * @voltage_mask: mask to control regulator voltage |
41 | * @supported_voltages: supported voltage table | 44 | * @supported_voltages: supported voltage table |
@@ -49,11 +52,13 @@ struct ab8500_regulator_info { | |||
49 | int max_uV; | 52 | int max_uV; |
50 | int min_uV; | 53 | int min_uV; |
51 | int fixed_uV; | 54 | int fixed_uV; |
52 | int update_reg; | 55 | u8 update_bank; |
53 | int mask; | 56 | u8 update_reg; |
54 | int enable; | 57 | u8 mask; |
55 | int voltage_reg; | 58 | u8 enable; |
56 | int voltage_mask; | 59 | u8 voltage_bank; |
60 | u8 voltage_reg; | ||
61 | u8 voltage_mask; | ||
57 | int const *supported_voltages; | 62 | int const *supported_voltages; |
58 | int voltages_len; | 63 | int voltages_len; |
59 | }; | 64 | }; |
@@ -97,8 +102,8 @@ static int ab8500_regulator_enable(struct regulator_dev *rdev) | |||
97 | if (regulator_id >= AB8500_NUM_REGULATORS) | 102 | if (regulator_id >= AB8500_NUM_REGULATORS) |
98 | return -EINVAL; | 103 | return -EINVAL; |
99 | 104 | ||
100 | ret = ab8500_set_bits(info->ab8500, info->update_reg, | 105 | ret = abx500_mask_and_set_register_interruptible(info->dev, |
101 | info->mask, info->enable); | 106 | info->update_bank, info->update_reg, info->mask, info->enable); |
102 | if (ret < 0) | 107 | if (ret < 0) |
103 | dev_err(rdev_get_dev(rdev), | 108 | dev_err(rdev_get_dev(rdev), |
104 | "couldn't set enable bits for regulator\n"); | 109 | "couldn't set enable bits for regulator\n"); |
@@ -114,8 +119,8 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) | |||
114 | if (regulator_id >= AB8500_NUM_REGULATORS) | 119 | if (regulator_id >= AB8500_NUM_REGULATORS) |
115 | return -EINVAL; | 120 | return -EINVAL; |
116 | 121 | ||
117 | ret = ab8500_set_bits(info->ab8500, info->update_reg, | 122 | ret = abx500_mask_and_set_register_interruptible(info->dev, |
118 | info->mask, 0x0); | 123 | info->update_bank, info->update_reg, info->mask, 0x0); |
119 | if (ret < 0) | 124 | if (ret < 0) |
120 | dev_err(rdev_get_dev(rdev), | 125 | dev_err(rdev_get_dev(rdev), |
121 | "couldn't set disable bits for regulator\n"); | 126 | "couldn't set disable bits for regulator\n"); |
@@ -126,19 +131,21 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) | |||
126 | { | 131 | { |
127 | int regulator_id, ret; | 132 | int regulator_id, ret; |
128 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 133 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
134 | u8 value; | ||
129 | 135 | ||
130 | regulator_id = rdev_get_id(rdev); | 136 | regulator_id = rdev_get_id(rdev); |
131 | if (regulator_id >= AB8500_NUM_REGULATORS) | 137 | if (regulator_id >= AB8500_NUM_REGULATORS) |
132 | return -EINVAL; | 138 | return -EINVAL; |
133 | 139 | ||
134 | ret = ab8500_read(info->ab8500, info->update_reg); | 140 | ret = abx500_get_register_interruptible(info->dev, |
141 | info->update_bank, info->update_reg, &value); | ||
135 | if (ret < 0) { | 142 | if (ret < 0) { |
136 | dev_err(rdev_get_dev(rdev), | 143 | dev_err(rdev_get_dev(rdev), |
137 | "couldn't read 0x%x register\n", info->update_reg); | 144 | "couldn't read 0x%x register\n", info->update_reg); |
138 | return ret; | 145 | return ret; |
139 | } | 146 | } |
140 | 147 | ||
141 | if (ret & info->mask) | 148 | if (value & info->mask) |
142 | return true; | 149 | return true; |
143 | else | 150 | else |
144 | return false; | 151 | return false; |
@@ -165,14 +172,16 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) | |||
165 | 172 | ||
166 | static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) | 173 | static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) |
167 | { | 174 | { |
168 | int regulator_id, ret, val; | 175 | int regulator_id, ret; |
169 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 176 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
177 | u8 value; | ||
170 | 178 | ||
171 | regulator_id = rdev_get_id(rdev); | 179 | regulator_id = rdev_get_id(rdev); |
172 | if (regulator_id >= AB8500_NUM_REGULATORS) | 180 | if (regulator_id >= AB8500_NUM_REGULATORS) |
173 | return -EINVAL; | 181 | return -EINVAL; |
174 | 182 | ||
175 | ret = ab8500_read(info->ab8500, info->voltage_reg); | 183 | ret = abx500_get_register_interruptible(info->dev, info->voltage_bank, |
184 | info->voltage_reg, &value); | ||
176 | if (ret < 0) { | 185 | if (ret < 0) { |
177 | dev_err(rdev_get_dev(rdev), | 186 | dev_err(rdev_get_dev(rdev), |
178 | "couldn't read voltage reg for regulator\n"); | 187 | "couldn't read voltage reg for regulator\n"); |
@@ -180,11 +189,11 @@ static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) | |||
180 | } | 189 | } |
181 | 190 | ||
182 | /* vintcore has a different layout */ | 191 | /* vintcore has a different layout */ |
183 | val = ret & info->voltage_mask; | 192 | value &= info->voltage_mask; |
184 | if (regulator_id == AB8500_LDO_INTCORE) | 193 | if (regulator_id == AB8500_LDO_INTCORE) |
185 | ret = info->supported_voltages[val >> 0x3]; | 194 | ret = info->supported_voltages[value >> 0x3]; |
186 | else | 195 | else |
187 | ret = info->supported_voltages[val]; | 196 | ret = info->supported_voltages[value]; |
188 | 197 | ||
189 | return ret; | 198 | return ret; |
190 | } | 199 | } |
@@ -224,8 +233,9 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, | |||
224 | } | 233 | } |
225 | 234 | ||
226 | /* set the registers for the request */ | 235 | /* set the registers for the request */ |
227 | ret = ab8500_set_bits(info->ab8500, info->voltage_reg, | 236 | ret = abx500_mask_and_set_register_interruptible(info->dev, |
228 | info->voltage_mask, ret); | 237 | info->voltage_bank, info->voltage_reg, |
238 | info->voltage_mask, (u8)ret); | ||
229 | if (ret < 0) | 239 | if (ret < 0) |
230 | dev_err(rdev_get_dev(rdev), | 240 | dev_err(rdev_get_dev(rdev), |
231 | "couldn't set voltage reg for regulator\n"); | 241 | "couldn't set voltage reg for regulator\n"); |
@@ -262,9 +272,9 @@ static struct regulator_ops ab8500_ldo_fixed_ops = { | |||
262 | .list_voltage = ab8500_list_voltage, | 272 | .list_voltage = ab8500_list_voltage, |
263 | }; | 273 | }; |
264 | 274 | ||
265 | #define AB8500_LDO(_id, min, max, reg, reg_mask, reg_enable, \ | 275 | #define AB8500_LDO(_id, min, max, bank, reg, reg_mask, \ |
266 | volt_reg, volt_mask, voltages, \ | 276 | reg_enable, volt_bank, volt_reg, volt_mask, \ |
267 | len_volts) \ | 277 | voltages, len_volts) \ |
268 | { \ | 278 | { \ |
269 | .desc = { \ | 279 | .desc = { \ |
270 | .name = "LDO-" #_id, \ | 280 | .name = "LDO-" #_id, \ |
@@ -275,9 +285,11 @@ static struct regulator_ops ab8500_ldo_fixed_ops = { | |||
275 | }, \ | 285 | }, \ |
276 | .min_uV = (min) * 1000, \ | 286 | .min_uV = (min) * 1000, \ |
277 | .max_uV = (max) * 1000, \ | 287 | .max_uV = (max) * 1000, \ |
288 | .update_bank = bank, \ | ||
278 | .update_reg = reg, \ | 289 | .update_reg = reg, \ |
279 | .mask = reg_mask, \ | 290 | .mask = reg_mask, \ |
280 | .enable = reg_enable, \ | 291 | .enable = reg_enable, \ |
292 | .voltage_bank = volt_bank, \ | ||
281 | .voltage_reg = volt_reg, \ | 293 | .voltage_reg = volt_reg, \ |
282 | .voltage_mask = volt_mask, \ | 294 | .voltage_mask = volt_mask, \ |
283 | .supported_voltages = voltages, \ | 295 | .supported_voltages = voltages, \ |
@@ -285,8 +297,8 @@ static struct regulator_ops ab8500_ldo_fixed_ops = { | |||
285 | .fixed_uV = 0, \ | 297 | .fixed_uV = 0, \ |
286 | } | 298 | } |
287 | 299 | ||
288 | #define AB8500_FIXED_LDO(_id, fixed, reg, reg_mask, \ | 300 | #define AB8500_FIXED_LDO(_id, fixed, bank, reg, \ |
289 | reg_enable) \ | 301 | reg_mask, reg_enable) \ |
290 | { \ | 302 | { \ |
291 | .desc = { \ | 303 | .desc = { \ |
292 | .name = "LDO-" #_id, \ | 304 | .name = "LDO-" #_id, \ |
@@ -296,6 +308,7 @@ static struct regulator_ops ab8500_ldo_fixed_ops = { | |||
296 | .owner = THIS_MODULE, \ | 308 | .owner = THIS_MODULE, \ |
297 | }, \ | 309 | }, \ |
298 | .fixed_uV = fixed * 1000, \ | 310 | .fixed_uV = fixed * 1000, \ |
311 | .update_bank = bank, \ | ||
299 | .update_reg = reg, \ | 312 | .update_reg = reg, \ |
300 | .mask = reg_mask, \ | 313 | .mask = reg_mask, \ |
301 | .enable = reg_enable, \ | 314 | .enable = reg_enable, \ |
@@ -304,28 +317,29 @@ static struct regulator_ops ab8500_ldo_fixed_ops = { | |||
304 | static struct ab8500_regulator_info ab8500_regulator_info[] = { | 317 | static struct ab8500_regulator_info ab8500_regulator_info[] = { |
305 | /* | 318 | /* |
306 | * Variable Voltage LDOs | 319 | * Variable Voltage LDOs |
307 | * name, min uV, max uV, ctrl reg, reg mask, enable mask, | 320 | * name, min uV, max uV, ctrl bank, ctrl reg, reg mask, enable mask, |
308 | * volt ctrl reg, volt ctrl mask, volt table, num supported volts | 321 | * volt ctrl bank, volt ctrl reg, volt ctrl mask, volt table, |
322 | * num supported volts | ||
309 | */ | 323 | */ |
310 | AB8500_LDO(AUX1, 1100, 3300, 0x0409, 0x3, 0x1, 0x041f, 0xf, | 324 | AB8500_LDO(AUX1, 1100, 3300, 0x04, 0x09, 0x3, 0x1, 0x04, 0x1f, 0xf, |
311 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | 325 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), |
312 | AB8500_LDO(AUX2, 1100, 3300, 0x0409, 0xc, 0x4, 0x0420, 0xf, | 326 | AB8500_LDO(AUX2, 1100, 3300, 0x04, 0x09, 0xc, 0x4, 0x04, 0x20, 0xf, |
313 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | 327 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), |
314 | AB8500_LDO(AUX3, 1100, 3300, 0x040a, 0x3, 0x1, 0x0421, 0xf, | 328 | AB8500_LDO(AUX3, 1100, 3300, 0x04, 0x0a, 0x3, 0x1, 0x04, 0x21, 0xf, |
315 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | 329 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), |
316 | AB8500_LDO(INTCORE, 1100, 3300, 0x0380, 0x4, 0x4, 0x0380, 0x38, | 330 | AB8500_LDO(INTCORE, 1100, 3300, 0x03, 0x80, 0x4, 0x4, 0x03, 0x80, 0x38, |
317 | ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)), | 331 | ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)), |
318 | 332 | ||
319 | /* | 333 | /* |
320 | * Fixed Voltage LDOs | 334 | * Fixed Voltage LDOs |
321 | * name, o/p uV, ctrl reg, enable, disable | 335 | * name, o/p uV, ctrl bank, ctrl reg, enable, disable |
322 | */ | 336 | */ |
323 | AB8500_FIXED_LDO(TVOUT, 2000, 0x0380, 0x2, 0x2), | 337 | AB8500_FIXED_LDO(TVOUT, 2000, 0x03, 0x80, 0x2, 0x2), |
324 | AB8500_FIXED_LDO(AUDIO, 2000, 0x0383, 0x2, 0x2), | 338 | AB8500_FIXED_LDO(AUDIO, 2000, 0x03, 0x83, 0x2, 0x2), |
325 | AB8500_FIXED_LDO(ANAMIC1, 2050, 0x0383, 0x4, 0x4), | 339 | AB8500_FIXED_LDO(ANAMIC1, 2050, 0x03, 0x83, 0x4, 0x4), |
326 | AB8500_FIXED_LDO(ANAMIC2, 2050, 0x0383, 0x8, 0x8), | 340 | AB8500_FIXED_LDO(ANAMIC2, 2050, 0x03, 0x83, 0x8, 0x8), |
327 | AB8500_FIXED_LDO(DMIC, 1800, 0x0383, 0x10, 0x10), | 341 | AB8500_FIXED_LDO(DMIC, 1800, 0x03, 0x83, 0x10, 0x10), |
328 | AB8500_FIXED_LDO(ANA, 1200, 0x0383, 0xc, 0x4), | 342 | AB8500_FIXED_LDO(ANA, 1200, 0x03, 0x83, 0xc, 0x4), |
329 | }; | 343 | }; |
330 | 344 | ||
331 | static inline struct ab8500_regulator_info *find_regulator_info(int id) | 345 | static inline struct ab8500_regulator_info *find_regulator_info(int id) |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index a1baf1fbe004..5c20756db607 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
@@ -39,6 +39,11 @@ struct max8998_data { | |||
39 | struct max8998_dev *iodev; | 39 | struct max8998_dev *iodev; |
40 | int num_regulators; | 40 | int num_regulators; |
41 | struct regulator_dev **rdev; | 41 | struct regulator_dev **rdev; |
42 | u8 buck1_vol[4]; /* voltages for selection */ | ||
43 | u8 buck2_vol[2]; | ||
44 | unsigned int buck1_idx; /* index to last changed voltage */ | ||
45 | /* value in a set */ | ||
46 | unsigned int buck2_idx; | ||
42 | }; | 47 | }; |
43 | 48 | ||
44 | struct voltage_map_desc { | 49 | struct voltage_map_desc { |
@@ -173,6 +178,7 @@ static int max8998_get_enable_register(struct regulator_dev *rdev, | |||
173 | static int max8998_ldo_is_enabled(struct regulator_dev *rdev) | 178 | static int max8998_ldo_is_enabled(struct regulator_dev *rdev) |
174 | { | 179 | { |
175 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | 180 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); |
181 | struct i2c_client *i2c = max8998->iodev->i2c; | ||
176 | int ret, reg, shift = 8; | 182 | int ret, reg, shift = 8; |
177 | u8 val; | 183 | u8 val; |
178 | 184 | ||
@@ -180,7 +186,7 @@ static int max8998_ldo_is_enabled(struct regulator_dev *rdev) | |||
180 | if (ret) | 186 | if (ret) |
181 | return ret; | 187 | return ret; |
182 | 188 | ||
183 | ret = max8998_read_reg(max8998->iodev, reg, &val); | 189 | ret = max8998_read_reg(i2c, reg, &val); |
184 | if (ret) | 190 | if (ret) |
185 | return ret; | 191 | return ret; |
186 | 192 | ||
@@ -190,31 +196,34 @@ static int max8998_ldo_is_enabled(struct regulator_dev *rdev) | |||
190 | static int max8998_ldo_enable(struct regulator_dev *rdev) | 196 | static int max8998_ldo_enable(struct regulator_dev *rdev) |
191 | { | 197 | { |
192 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | 198 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); |
199 | struct i2c_client *i2c = max8998->iodev->i2c; | ||
193 | int reg, shift = 8, ret; | 200 | int reg, shift = 8, ret; |
194 | 201 | ||
195 | ret = max8998_get_enable_register(rdev, ®, &shift); | 202 | ret = max8998_get_enable_register(rdev, ®, &shift); |
196 | if (ret) | 203 | if (ret) |
197 | return ret; | 204 | return ret; |
198 | 205 | ||
199 | return max8998_update_reg(max8998->iodev, reg, 1<<shift, 1<<shift); | 206 | return max8998_update_reg(i2c, reg, 1<<shift, 1<<shift); |
200 | } | 207 | } |
201 | 208 | ||
202 | static int max8998_ldo_disable(struct regulator_dev *rdev) | 209 | static int max8998_ldo_disable(struct regulator_dev *rdev) |
203 | { | 210 | { |
204 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | 211 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); |
212 | struct i2c_client *i2c = max8998->iodev->i2c; | ||
205 | int reg, shift = 8, ret; | 213 | int reg, shift = 8, ret; |
206 | 214 | ||
207 | ret = max8998_get_enable_register(rdev, ®, &shift); | 215 | ret = max8998_get_enable_register(rdev, ®, &shift); |
208 | if (ret) | 216 | if (ret) |
209 | return ret; | 217 | return ret; |
210 | 218 | ||
211 | return max8998_update_reg(max8998->iodev, reg, 0, 1<<shift); | 219 | return max8998_update_reg(i2c, reg, 0, 1<<shift); |
212 | } | 220 | } |
213 | 221 | ||
214 | static int max8998_get_voltage_register(struct regulator_dev *rdev, | 222 | static int max8998_get_voltage_register(struct regulator_dev *rdev, |
215 | int *_reg, int *_shift, int *_mask) | 223 | int *_reg, int *_shift, int *_mask) |
216 | { | 224 | { |
217 | int ldo = max8998_get_ldo(rdev); | 225 | int ldo = max8998_get_ldo(rdev); |
226 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
218 | int reg, shift = 0, mask = 0xff; | 227 | int reg, shift = 0, mask = 0xff; |
219 | 228 | ||
220 | switch (ldo) { | 229 | switch (ldo) { |
@@ -251,10 +260,10 @@ static int max8998_get_voltage_register(struct regulator_dev *rdev, | |||
251 | reg = MAX8998_REG_LDO12 + (ldo - MAX8998_LDO12); | 260 | reg = MAX8998_REG_LDO12 + (ldo - MAX8998_LDO12); |
252 | break; | 261 | break; |
253 | case MAX8998_BUCK1: | 262 | case MAX8998_BUCK1: |
254 | reg = MAX8998_REG_BUCK1_DVSARM1; | 263 | reg = MAX8998_REG_BUCK1_VOLTAGE1 + max8998->buck1_idx; |
255 | break; | 264 | break; |
256 | case MAX8998_BUCK2: | 265 | case MAX8998_BUCK2: |
257 | reg = MAX8998_REG_BUCK2_DVSINT1; | 266 | reg = MAX8998_REG_BUCK2_VOLTAGE1 + max8998->buck2_idx; |
258 | break; | 267 | break; |
259 | case MAX8998_BUCK3: | 268 | case MAX8998_BUCK3: |
260 | reg = MAX8998_REG_BUCK3; | 269 | reg = MAX8998_REG_BUCK3; |
@@ -276,6 +285,7 @@ static int max8998_get_voltage_register(struct regulator_dev *rdev, | |||
276 | static int max8998_get_voltage(struct regulator_dev *rdev) | 285 | static int max8998_get_voltage(struct regulator_dev *rdev) |
277 | { | 286 | { |
278 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | 287 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); |
288 | struct i2c_client *i2c = max8998->iodev->i2c; | ||
279 | int reg, shift = 0, mask, ret; | 289 | int reg, shift = 0, mask, ret; |
280 | u8 val; | 290 | u8 val; |
281 | 291 | ||
@@ -283,7 +293,7 @@ static int max8998_get_voltage(struct regulator_dev *rdev) | |||
283 | if (ret) | 293 | if (ret) |
284 | return ret; | 294 | return ret; |
285 | 295 | ||
286 | ret = max8998_read_reg(max8998->iodev, reg, &val); | 296 | ret = max8998_read_reg(i2c, reg, &val); |
287 | if (ret) | 297 | if (ret) |
288 | return ret; | 298 | return ret; |
289 | 299 | ||
@@ -293,18 +303,16 @@ static int max8998_get_voltage(struct regulator_dev *rdev) | |||
293 | return max8998_list_voltage(rdev, val); | 303 | return max8998_list_voltage(rdev, val); |
294 | } | 304 | } |
295 | 305 | ||
296 | static int max8998_set_voltage(struct regulator_dev *rdev, | 306 | static int max8998_set_voltage_ldo(struct regulator_dev *rdev, |
297 | int min_uV, int max_uV) | 307 | int min_uV, int max_uV) |
298 | { | 308 | { |
299 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | 309 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); |
310 | struct i2c_client *i2c = max8998->iodev->i2c; | ||
300 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | 311 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; |
301 | int previous_vol = 0; | ||
302 | const struct voltage_map_desc *desc; | 312 | const struct voltage_map_desc *desc; |
303 | int ldo = max8998_get_ldo(rdev); | 313 | int ldo = max8998_get_ldo(rdev); |
304 | int reg, shift = 0, mask, ret; | 314 | int reg, shift = 0, mask, ret; |
305 | int i = 0; | 315 | int i = 0; |
306 | u8 val; | ||
307 | bool en_ramp = false; | ||
308 | 316 | ||
309 | if (ldo >= ARRAY_SIZE(ldo_voltage_map)) | 317 | if (ldo >= ARRAY_SIZE(ldo_voltage_map)) |
310 | return -EINVAL; | 318 | return -EINVAL; |
@@ -327,24 +335,155 @@ static int max8998_set_voltage(struct regulator_dev *rdev, | |||
327 | if (ret) | 335 | if (ret) |
328 | return ret; | 336 | return ret; |
329 | 337 | ||
330 | /* wait for RAMP_UP_DELAY if rdev is BUCK1/2 and | 338 | ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift); |
331 | * ENRAMP is ON */ | 339 | |
332 | if (ldo == MAX8998_BUCK1 || ldo == MAX8998_BUCK2) { | 340 | return ret; |
333 | max8998_read_reg(max8998->iodev, MAX8998_REG_ONOFF4, &val); | 341 | } |
334 | if (val & (1 << 4)) { | 342 | |
335 | en_ramp = true; | 343 | static inline void buck1_gpio_set(int gpio1, int gpio2, int v) |
336 | previous_vol = max8998_get_voltage(rdev); | 344 | { |
337 | } | 345 | gpio_set_value(gpio1, v & 0x1); |
346 | gpio_set_value(gpio2, (v >> 1) & 0x1); | ||
347 | } | ||
348 | |||
349 | static inline void buck2_gpio_set(int gpio, int v) | ||
350 | { | ||
351 | gpio_set_value(gpio, v & 0x1); | ||
352 | } | ||
353 | |||
354 | static int max8998_set_voltage_buck(struct regulator_dev *rdev, | ||
355 | int min_uV, int max_uV) | ||
356 | { | ||
357 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
358 | struct max8998_platform_data *pdata = | ||
359 | dev_get_platdata(max8998->iodev->dev); | ||
360 | struct i2c_client *i2c = max8998->iodev->i2c; | ||
361 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
362 | const struct voltage_map_desc *desc; | ||
363 | int buck = max8998_get_ldo(rdev); | ||
364 | int reg, shift = 0, mask, ret; | ||
365 | int difference = 0, i = 0, j = 0, previous_vol = 0; | ||
366 | u8 val = 0; | ||
367 | static u8 buck1_last_val; | ||
368 | |||
369 | if (buck >= ARRAY_SIZE(ldo_voltage_map)) | ||
370 | return -EINVAL; | ||
371 | |||
372 | desc = ldo_voltage_map[buck]; | ||
373 | |||
374 | if (desc == NULL) | ||
375 | return -EINVAL; | ||
376 | |||
377 | if (max_vol < desc->min || min_vol > desc->max) | ||
378 | return -EINVAL; | ||
379 | |||
380 | while (desc->min + desc->step*i < min_vol && | ||
381 | desc->min + desc->step*i < desc->max) | ||
382 | i++; | ||
383 | |||
384 | if (desc->min + desc->step*i > max_vol) | ||
385 | return -EINVAL; | ||
386 | |||
387 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | ||
388 | if (ret) | ||
389 | return ret; | ||
390 | |||
391 | previous_vol = max8998_get_voltage(rdev); | ||
392 | |||
393 | /* Check if voltage needs to be changed */ | ||
394 | /* if previous_voltage equal new voltage, return */ | ||
395 | if (previous_vol == max8998_list_voltage(rdev, i)) { | ||
396 | dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n", | ||
397 | previous_vol, max8998_list_voltage(rdev, i)); | ||
398 | return ret; | ||
338 | } | 399 | } |
339 | 400 | ||
340 | ret = max8998_update_reg(max8998->iodev, reg, i<<shift, mask<<shift); | 401 | switch (buck) { |
402 | case MAX8998_BUCK1: | ||
403 | dev_dbg(max8998->dev, | ||
404 | "BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n\ | ||
405 | buck1_vol3:%d, buck1_vol4:%d\n", | ||
406 | i, max8998->buck1_vol[0], max8998->buck1_vol[1], | ||
407 | max8998->buck1_vol[2], max8998->buck1_vol[3]); | ||
408 | |||
409 | if (gpio_is_valid(pdata->buck1_set1) && | ||
410 | gpio_is_valid(pdata->buck1_set2)) { | ||
411 | |||
412 | /* check if requested voltage */ | ||
413 | /* value is already defined */ | ||
414 | for (j = 0; j < ARRAY_SIZE(max8998->buck1_vol); j++) { | ||
415 | if (max8998->buck1_vol[j] == i) { | ||
416 | max8998->buck1_idx = j; | ||
417 | buck1_gpio_set(pdata->buck1_set1, | ||
418 | pdata->buck1_set2, j); | ||
419 | goto buck1_exit; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /* no predefine regulator found */ | ||
424 | max8998->buck1_idx = (buck1_last_val % 2) + 2; | ||
425 | dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n", | ||
426 | max8998->buck1_idx); | ||
427 | max8998->buck1_vol[max8998->buck1_idx] = i; | ||
428 | ret = max8998_get_voltage_register(rdev, ®, | ||
429 | &shift, | ||
430 | &mask); | ||
431 | ret = max8998_write_reg(i2c, reg, i); | ||
432 | buck1_gpio_set(pdata->buck1_set1, | ||
433 | pdata->buck1_set2, max8998->buck1_idx); | ||
434 | buck1_last_val++; | ||
435 | buck1_exit: | ||
436 | dev_dbg(max8998->dev, "%s: SET1:%d, SET2:%d\n", | ||
437 | i2c->name, gpio_get_value(pdata->buck1_set1), | ||
438 | gpio_get_value(pdata->buck1_set2)); | ||
439 | break; | ||
440 | } else { | ||
441 | ret = max8998_write_reg(i2c, reg, i); | ||
442 | } | ||
443 | break; | ||
444 | |||
445 | case MAX8998_BUCK2: | ||
446 | dev_dbg(max8998->dev, | ||
447 | "BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n" | ||
448 | , i, max8998->buck2_vol[0], max8998->buck2_vol[1]); | ||
449 | if (gpio_is_valid(pdata->buck2_set3)) { | ||
450 | if (max8998->buck2_vol[0] == i) { | ||
451 | max8998->buck1_idx = 0; | ||
452 | buck2_gpio_set(pdata->buck2_set3, 0); | ||
453 | } else { | ||
454 | max8998->buck1_idx = 1; | ||
455 | ret = max8998_get_voltage_register(rdev, ®, | ||
456 | &shift, | ||
457 | &mask); | ||
458 | ret = max8998_write_reg(i2c, reg, i); | ||
459 | max8998->buck2_vol[1] = i; | ||
460 | buck2_gpio_set(pdata->buck2_set3, 1); | ||
461 | } | ||
462 | dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name, | ||
463 | gpio_get_value(pdata->buck2_set3)); | ||
464 | } else { | ||
465 | ret = max8998_write_reg(i2c, reg, i); | ||
466 | } | ||
467 | break; | ||
341 | 468 | ||
342 | if (en_ramp == true) { | 469 | case MAX8998_BUCK3: |
343 | int difference = desc->min + desc->step*i - previous_vol/1000; | 470 | case MAX8998_BUCK4: |
344 | if (difference > 0) | 471 | ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift); |
345 | udelay(difference / ((val & 0x0f) + 1)); | 472 | break; |
346 | } | 473 | } |
347 | 474 | ||
475 | /* Voltage stabilization */ | ||
476 | max8998_read_reg(i2c, MAX8998_REG_ONOFF4, &val); | ||
477 | |||
478 | /* lp3974 hasn't got ENRAMP bit - ramp is assumed as true */ | ||
479 | /* MAX8998 has ENRAMP bit implemented, so test it*/ | ||
480 | if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) | ||
481 | return ret; | ||
482 | |||
483 | difference = desc->min + desc->step*i - previous_vol/1000; | ||
484 | if (difference > 0) | ||
485 | udelay(difference / ((val & 0x0f) + 1)); | ||
486 | |||
348 | return ret; | 487 | return ret; |
349 | } | 488 | } |
350 | 489 | ||
@@ -354,7 +493,7 @@ static struct regulator_ops max8998_ldo_ops = { | |||
354 | .enable = max8998_ldo_enable, | 493 | .enable = max8998_ldo_enable, |
355 | .disable = max8998_ldo_disable, | 494 | .disable = max8998_ldo_disable, |
356 | .get_voltage = max8998_get_voltage, | 495 | .get_voltage = max8998_get_voltage, |
357 | .set_voltage = max8998_set_voltage, | 496 | .set_voltage = max8998_set_voltage_ldo, |
358 | .set_suspend_enable = max8998_ldo_enable, | 497 | .set_suspend_enable = max8998_ldo_enable, |
359 | .set_suspend_disable = max8998_ldo_disable, | 498 | .set_suspend_disable = max8998_ldo_disable, |
360 | }; | 499 | }; |
@@ -365,7 +504,7 @@ static struct regulator_ops max8998_buck_ops = { | |||
365 | .enable = max8998_ldo_enable, | 504 | .enable = max8998_ldo_enable, |
366 | .disable = max8998_ldo_disable, | 505 | .disable = max8998_ldo_disable, |
367 | .get_voltage = max8998_get_voltage, | 506 | .get_voltage = max8998_get_voltage, |
368 | .set_voltage = max8998_set_voltage, | 507 | .set_voltage = max8998_set_voltage_buck, |
369 | .set_suspend_enable = max8998_ldo_enable, | 508 | .set_suspend_enable = max8998_ldo_enable, |
370 | .set_suspend_disable = max8998_ldo_disable, | 509 | .set_suspend_disable = max8998_ldo_disable, |
371 | }; | 510 | }; |
@@ -538,6 +677,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
538 | struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); | 677 | struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); |
539 | struct regulator_dev **rdev; | 678 | struct regulator_dev **rdev; |
540 | struct max8998_data *max8998; | 679 | struct max8998_data *max8998; |
680 | struct i2c_client *i2c; | ||
541 | int i, ret, size; | 681 | int i, ret, size; |
542 | 682 | ||
543 | if (!pdata) { | 683 | if (!pdata) { |
@@ -561,6 +701,86 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
561 | max8998->iodev = iodev; | 701 | max8998->iodev = iodev; |
562 | max8998->num_regulators = pdata->num_regulators; | 702 | max8998->num_regulators = pdata->num_regulators; |
563 | platform_set_drvdata(pdev, max8998); | 703 | platform_set_drvdata(pdev, max8998); |
704 | i2c = max8998->iodev->i2c; | ||
705 | |||
706 | /* NOTE: */ | ||
707 | /* For unused GPIO NOT marked as -1 (thereof equal to 0) WARN_ON */ | ||
708 | /* will be displayed */ | ||
709 | |||
710 | /* Check if MAX8998 voltage selection GPIOs are defined */ | ||
711 | if (gpio_is_valid(pdata->buck1_set1) && | ||
712 | gpio_is_valid(pdata->buck1_set2)) { | ||
713 | /* Check if SET1 is not equal to 0 */ | ||
714 | if (!pdata->buck1_set1) { | ||
715 | printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n"); | ||
716 | WARN_ON(!pdata->buck1_set1); | ||
717 | return -EIO; | ||
718 | } | ||
719 | /* Check if SET2 is not equal to 0 */ | ||
720 | if (!pdata->buck1_set2) { | ||
721 | printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n"); | ||
722 | WARN_ON(!pdata->buck1_set2); | ||
723 | return -EIO; | ||
724 | } | ||
725 | |||
726 | gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1"); | ||
727 | gpio_direction_output(pdata->buck1_set1, | ||
728 | max8998->buck1_idx & 0x1); | ||
729 | |||
730 | |||
731 | gpio_request(pdata->buck1_set2, "MAX8998 BUCK1_SET2"); | ||
732 | gpio_direction_output(pdata->buck1_set2, | ||
733 | (max8998->buck1_idx >> 1) & 0x1); | ||
734 | /* Set predefined value for BUCK1 register 1 */ | ||
735 | i = 0; | ||
736 | while (buck12_voltage_map_desc.min + | ||
737 | buck12_voltage_map_desc.step*i | ||
738 | != (pdata->buck1_max_voltage1 / 1000)) | ||
739 | i++; | ||
740 | printk(KERN_ERR "i:%d, buck1_idx:%d\n", i, max8998->buck1_idx); | ||
741 | max8998->buck1_vol[0] = i; | ||
742 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); | ||
743 | |||
744 | /* Set predefined value for BUCK1 register 2 */ | ||
745 | i = 0; | ||
746 | while (buck12_voltage_map_desc.min + | ||
747 | buck12_voltage_map_desc.step*i | ||
748 | != (pdata->buck1_max_voltage2 / 1000)) | ||
749 | i++; | ||
750 | |||
751 | max8998->buck1_vol[1] = i; | ||
752 | printk(KERN_ERR "i:%d, buck1_idx:%d\n", i, max8998->buck1_idx); | ||
753 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i) | ||
754 | + ret; | ||
755 | if (ret) | ||
756 | return ret; | ||
757 | |||
758 | } | ||
759 | |||
760 | if (gpio_is_valid(pdata->buck2_set3)) { | ||
761 | /* Check if SET3 is not equal to 0 */ | ||
762 | if (!pdata->buck2_set3) { | ||
763 | printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n"); | ||
764 | WARN_ON(!pdata->buck2_set3); | ||
765 | return -EIO; | ||
766 | } | ||
767 | gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3"); | ||
768 | gpio_direction_output(pdata->buck2_set3, | ||
769 | max8998->buck2_idx & 0x1); | ||
770 | |||
771 | /* BUCK2 - set preset default voltage value to buck2_vol[0] */ | ||
772 | i = 0; | ||
773 | while (buck12_voltage_map_desc.min + | ||
774 | buck12_voltage_map_desc.step*i | ||
775 | != (pdata->buck2_max_voltage / 1000)) | ||
776 | i++; | ||
777 | printk(KERN_ERR "i:%d, buck2_idx:%d\n", i, max8998->buck2_idx); | ||
778 | max8998->buck2_vol[0] = i; | ||
779 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); | ||
780 | if (ret) | ||
781 | return ret; | ||
782 | |||
783 | } | ||
564 | 784 | ||
565 | for (i = 0; i < pdata->num_regulators; i++) { | 785 | for (i = 0; i < pdata->num_regulators; i++) { |
566 | const struct voltage_map_desc *desc; | 786 | const struct voltage_map_desc *desc; |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 6a77437d4f5a..2883428d5ac8 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -196,6 +196,16 @@ config RTC_DRV_MAX8925 | |||
196 | This driver can also be built as a module. If so, the module | 196 | This driver can also be built as a module. If so, the module |
197 | will be called rtc-max8925. | 197 | will be called rtc-max8925. |
198 | 198 | ||
199 | config RTC_DRV_MAX8998 | ||
200 | tristate "Maxim MAX8998" | ||
201 | depends on MFD_MAX8998 | ||
202 | help | ||
203 | If you say yes here you will get support for the | ||
204 | RTC of Maxim MAX8998 PMIC. | ||
205 | |||
206 | This driver can also be built as a module. If so, the module | ||
207 | will be called rtc-max8998. | ||
208 | |||
199 | config RTC_DRV_RS5C372 | 209 | config RTC_DRV_RS5C372 |
200 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 210 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
201 | help | 211 | help |
@@ -926,11 +936,12 @@ config RTC_DRV_PCAP | |||
926 | If you say Y here you will get support for the RTC found on | 936 | If you say Y here you will get support for the RTC found on |
927 | the PCAP2 ASIC used on some Motorola phones. | 937 | the PCAP2 ASIC used on some Motorola phones. |
928 | 938 | ||
929 | config RTC_DRV_MC13783 | 939 | config RTC_DRV_MC13XXX |
930 | depends on MFD_MC13783 | 940 | depends on MFD_MC13XXX |
931 | tristate "Freescale MC13783 RTC" | 941 | tristate "Freescale MC13xxx RTC" |
932 | help | 942 | help |
933 | This enables support for the Freescale MC13783 PMIC RTC | 943 | This enables support for the RTCs found on Freescale's PMICs |
944 | MC13783 and MC13892. | ||
934 | 945 | ||
935 | config RTC_DRV_MPC5121 | 946 | config RTC_DRV_MPC5121 |
936 | tristate "Freescale MPC5121 built-in RTC" | 947 | tristate "Freescale MPC5121 built-in RTC" |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7a7cb3228a1d..4c2832df4697 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -60,8 +60,9 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | |||
60 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | 60 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
61 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 61 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
62 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | 62 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o |
63 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o | ||
63 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 64 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
64 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o | 65 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o |
65 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 66 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
66 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | 67 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o |
67 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 68 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 2fda03125e55..e346705aae92 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c | |||
@@ -14,26 +14,26 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
17 | #include <linux/mfd/abx500.h> | ||
17 | #include <linux/mfd/ab8500.h> | 18 | #include <linux/mfd/ab8500.h> |
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | 20 | ||
20 | #define AB8500_RTC_SOFF_STAT_REG 0x0F00 | 21 | #define AB8500_RTC_SOFF_STAT_REG 0x00 |
21 | #define AB8500_RTC_CC_CONF_REG 0x0F01 | 22 | #define AB8500_RTC_CC_CONF_REG 0x01 |
22 | #define AB8500_RTC_READ_REQ_REG 0x0F02 | 23 | #define AB8500_RTC_READ_REQ_REG 0x02 |
23 | #define AB8500_RTC_WATCH_TSECMID_REG 0x0F03 | 24 | #define AB8500_RTC_WATCH_TSECMID_REG 0x03 |
24 | #define AB8500_RTC_WATCH_TSECHI_REG 0x0F04 | 25 | #define AB8500_RTC_WATCH_TSECHI_REG 0x04 |
25 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x0F05 | 26 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x05 |
26 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x0F06 | 27 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x06 |
27 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x0F07 | 28 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x07 |
28 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x0F08 | 29 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x08 |
29 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x0F09 | 30 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x09 |
30 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0F0A | 31 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0A |
31 | #define AB8500_RTC_STAT_REG 0x0F0B | 32 | #define AB8500_RTC_STAT_REG 0x0B |
32 | #define AB8500_RTC_BKUP_CHG_REG 0x0F0C | 33 | #define AB8500_RTC_BKUP_CHG_REG 0x0C |
33 | #define AB8500_RTC_FORCE_BKUP_REG 0x0F0D | 34 | #define AB8500_RTC_FORCE_BKUP_REG 0x0D |
34 | #define AB8500_RTC_CALIB_REG 0x0F0E | 35 | #define AB8500_RTC_CALIB_REG 0x0E |
35 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F0F | 36 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F |
36 | #define AB8500_REV_REG 0x1080 | ||
37 | 37 | ||
38 | /* RtcReadRequest bits */ | 38 | /* RtcReadRequest bits */ |
39 | #define RTC_READ_REQUEST 0x01 | 39 | #define RTC_READ_REQUEST 0x01 |
@@ -46,13 +46,13 @@ | |||
46 | #define COUNTS_PER_SEC (0xF000 / 60) | 46 | #define COUNTS_PER_SEC (0xF000 / 60) |
47 | #define AB8500_RTC_EPOCH 2000 | 47 | #define AB8500_RTC_EPOCH 2000 |
48 | 48 | ||
49 | static const unsigned long ab8500_rtc_time_regs[] = { | 49 | static const u8 ab8500_rtc_time_regs[] = { |
50 | AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, | 50 | AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, |
51 | AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG, | 51 | AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG, |
52 | AB8500_RTC_WATCH_TSECMID_REG | 52 | AB8500_RTC_WATCH_TSECMID_REG |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static const unsigned long ab8500_rtc_alarm_regs[] = { | 55 | static const u8 ab8500_rtc_alarm_regs[] = { |
56 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, | 56 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, |
57 | AB8500_RTC_ALRM_MIN_LOW_REG | 57 | AB8500_RTC_ALRM_MIN_LOW_REG |
58 | }; | 58 | }; |
@@ -76,29 +76,30 @@ static unsigned long get_elapsed_seconds(int year) | |||
76 | 76 | ||
77 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | 77 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) |
78 | { | 78 | { |
79 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
80 | unsigned long timeout = jiffies + HZ; | 79 | unsigned long timeout = jiffies + HZ; |
81 | int retval, i; | 80 | int retval, i; |
82 | unsigned long mins, secs; | 81 | unsigned long mins, secs; |
83 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | 82 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; |
83 | u8 value; | ||
84 | 84 | ||
85 | /* Request a data read */ | 85 | /* Request a data read */ |
86 | retval = ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, | 86 | retval = abx500_set_register_interruptible(dev, |
87 | RTC_READ_REQUEST); | 87 | AB8500_RTC, AB8500_RTC_READ_REQ_REG, RTC_READ_REQUEST); |
88 | if (retval < 0) | 88 | if (retval < 0) |
89 | return retval; | 89 | return retval; |
90 | 90 | ||
91 | /* Early AB8500 chips will not clear the rtc read request bit */ | 91 | /* Early AB8500 chips will not clear the rtc read request bit */ |
92 | if (ab8500->revision == 0) { | 92 | if (abx500_get_chip_id(dev) == 0) { |
93 | msleep(1); | 93 | msleep(1); |
94 | } else { | 94 | } else { |
95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ | 95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ |
96 | while (time_before(jiffies, timeout)) { | 96 | while (time_before(jiffies, timeout)) { |
97 | retval = ab8500_read(ab8500, AB8500_RTC_READ_REQ_REG); | 97 | retval = abx500_get_register_interruptible(dev, |
98 | AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value); | ||
98 | if (retval < 0) | 99 | if (retval < 0) |
99 | return retval; | 100 | return retval; |
100 | 101 | ||
101 | if (!(retval & RTC_READ_REQUEST)) | 102 | if (!(value & RTC_READ_REQUEST)) |
102 | break; | 103 | break; |
103 | 104 | ||
104 | msleep(1); | 105 | msleep(1); |
@@ -107,10 +108,11 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
107 | 108 | ||
108 | /* Read the Watchtime registers */ | 109 | /* Read the Watchtime registers */ |
109 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | 110 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { |
110 | retval = ab8500_read(ab8500, ab8500_rtc_time_regs[i]); | 111 | retval = abx500_get_register_interruptible(dev, |
112 | AB8500_RTC, ab8500_rtc_time_regs[i], &value); | ||
111 | if (retval < 0) | 113 | if (retval < 0) |
112 | return retval; | 114 | return retval; |
113 | buf[i] = retval; | 115 | buf[i] = value; |
114 | } | 116 | } |
115 | 117 | ||
116 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | 118 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; |
@@ -128,7 +130,6 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
128 | 130 | ||
129 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | 131 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) |
130 | { | 132 | { |
131 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
132 | int retval, i; | 133 | int retval, i; |
133 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | 134 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; |
134 | unsigned long no_secs, no_mins, secs = 0; | 135 | unsigned long no_secs, no_mins, secs = 0; |
@@ -162,27 +163,29 @@ static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
162 | buf[0] = (no_mins >> 16) & 0xFF; | 163 | buf[0] = (no_mins >> 16) & 0xFF; |
163 | 164 | ||
164 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | 165 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { |
165 | retval = ab8500_write(ab8500, ab8500_rtc_time_regs[i], buf[i]); | 166 | retval = abx500_set_register_interruptible(dev, AB8500_RTC, |
167 | ab8500_rtc_time_regs[i], buf[i]); | ||
166 | if (retval < 0) | 168 | if (retval < 0) |
167 | return retval; | 169 | return retval; |
168 | } | 170 | } |
169 | 171 | ||
170 | /* Request a data write */ | 172 | /* Request a data write */ |
171 | return ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | 173 | return abx500_set_register_interruptible(dev, AB8500_RTC, |
174 | AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | ||
172 | } | 175 | } |
173 | 176 | ||
174 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 177 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
175 | { | 178 | { |
176 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
177 | int retval, i; | 179 | int retval, i; |
178 | int rtc_ctrl; | 180 | u8 rtc_ctrl, value; |
179 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | 181 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; |
180 | unsigned long secs, mins; | 182 | unsigned long secs, mins; |
181 | 183 | ||
182 | /* Check if the alarm is enabled or not */ | 184 | /* Check if the alarm is enabled or not */ |
183 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | 185 | retval = abx500_get_register_interruptible(dev, AB8500_RTC, |
184 | if (rtc_ctrl < 0) | 186 | AB8500_RTC_STAT_REG, &rtc_ctrl); |
185 | return rtc_ctrl; | 187 | if (retval < 0) |
188 | return retval; | ||
186 | 189 | ||
187 | if (rtc_ctrl & RTC_ALARM_ENA) | 190 | if (rtc_ctrl & RTC_ALARM_ENA) |
188 | alarm->enabled = 1; | 191 | alarm->enabled = 1; |
@@ -192,10 +195,11 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
192 | alarm->pending = 0; | 195 | alarm->pending = 0; |
193 | 196 | ||
194 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | 197 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { |
195 | retval = ab8500_read(ab8500, ab8500_rtc_alarm_regs[i]); | 198 | retval = abx500_get_register_interruptible(dev, AB8500_RTC, |
199 | ab8500_rtc_alarm_regs[i], &value); | ||
196 | if (retval < 0) | 200 | if (retval < 0) |
197 | return retval; | 201 | return retval; |
198 | buf[i] = retval; | 202 | buf[i] = value; |
199 | } | 203 | } |
200 | 204 | ||
201 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); | 205 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); |
@@ -211,15 +215,13 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
211 | 215 | ||
212 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) | 216 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) |
213 | { | 217 | { |
214 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | 218 | return abx500_mask_and_set_register_interruptible(dev, AB8500_RTC, |
215 | 219 | AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | |
216 | return ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | 220 | enabled ? RTC_ALARM_ENA : 0); |
217 | enabled ? RTC_ALARM_ENA : 0); | ||
218 | } | 221 | } |
219 | 222 | ||
220 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 223 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
221 | { | 224 | { |
222 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
223 | int retval, i; | 225 | int retval, i; |
224 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | 226 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; |
225 | unsigned long mins, secs = 0; | 227 | unsigned long mins, secs = 0; |
@@ -247,7 +249,8 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
247 | 249 | ||
248 | /* Set the alarm time */ | 250 | /* Set the alarm time */ |
249 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | 251 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { |
250 | retval = ab8500_write(ab8500, ab8500_rtc_alarm_regs[i], buf[i]); | 252 | retval = abx500_set_register_interruptible(dev, AB8500_RTC, |
253 | ab8500_rtc_alarm_regs[i], buf[i]); | ||
251 | if (retval < 0) | 254 | if (retval < 0) |
252 | return retval; | 255 | return retval; |
253 | } | 256 | } |
@@ -276,10 +279,9 @@ static const struct rtc_class_ops ab8500_rtc_ops = { | |||
276 | 279 | ||
277 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | 280 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) |
278 | { | 281 | { |
279 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
280 | int err; | 282 | int err; |
281 | struct rtc_device *rtc; | 283 | struct rtc_device *rtc; |
282 | int rtc_ctrl; | 284 | u8 rtc_ctrl; |
283 | int irq; | 285 | int irq; |
284 | 286 | ||
285 | irq = platform_get_irq_byname(pdev, "ALARM"); | 287 | irq = platform_get_irq_byname(pdev, "ALARM"); |
@@ -287,17 +289,18 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | |||
287 | return irq; | 289 | return irq; |
288 | 290 | ||
289 | /* For RTC supply test */ | 291 | /* For RTC supply test */ |
290 | err = ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_STATUS_DATA, | 292 | err = abx500_mask_and_set_register_interruptible(&pdev->dev, AB8500_RTC, |
291 | RTC_STATUS_DATA); | 293 | AB8500_RTC_STAT_REG, RTC_STATUS_DATA, RTC_STATUS_DATA); |
292 | if (err < 0) | 294 | if (err < 0) |
293 | return err; | 295 | return err; |
294 | 296 | ||
295 | /* Wait for reset by the PorRtc */ | 297 | /* Wait for reset by the PorRtc */ |
296 | msleep(1); | 298 | msleep(1); |
297 | 299 | ||
298 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | 300 | err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC, |
299 | if (rtc_ctrl < 0) | 301 | AB8500_RTC_STAT_REG, &rtc_ctrl); |
300 | return rtc_ctrl; | 302 | if (err < 0) |
303 | return err; | ||
301 | 304 | ||
302 | /* Check if the RTC Supply fails */ | 305 | /* Check if the RTC Supply fails */ |
303 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { | 306 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { |
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c new file mode 100644 index 000000000000..f22dee35f330 --- /dev/null +++ b/drivers/rtc/rtc-max8998.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8998 | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Minkyu Kang <mk7.kang@samsung.com> | ||
6 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/bcd.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mfd/max8998.h> | ||
22 | #include <linux/mfd/max8998-private.h> | ||
23 | |||
24 | #define MAX8998_RTC_SEC 0x00 | ||
25 | #define MAX8998_RTC_MIN 0x01 | ||
26 | #define MAX8998_RTC_HOUR 0x02 | ||
27 | #define MAX8998_RTC_WEEKDAY 0x03 | ||
28 | #define MAX8998_RTC_DATE 0x04 | ||
29 | #define MAX8998_RTC_MONTH 0x05 | ||
30 | #define MAX8998_RTC_YEAR1 0x06 | ||
31 | #define MAX8998_RTC_YEAR2 0x07 | ||
32 | #define MAX8998_ALARM0_SEC 0x08 | ||
33 | #define MAX8998_ALARM0_MIN 0x09 | ||
34 | #define MAX8998_ALARM0_HOUR 0x0a | ||
35 | #define MAX8998_ALARM0_WEEKDAY 0x0b | ||
36 | #define MAX8998_ALARM0_DATE 0x0c | ||
37 | #define MAX8998_ALARM0_MONTH 0x0d | ||
38 | #define MAX8998_ALARM0_YEAR1 0x0e | ||
39 | #define MAX8998_ALARM0_YEAR2 0x0f | ||
40 | #define MAX8998_ALARM1_SEC 0x10 | ||
41 | #define MAX8998_ALARM1_MIN 0x11 | ||
42 | #define MAX8998_ALARM1_HOUR 0x12 | ||
43 | #define MAX8998_ALARM1_WEEKDAY 0x13 | ||
44 | #define MAX8998_ALARM1_DATE 0x14 | ||
45 | #define MAX8998_ALARM1_MONTH 0x15 | ||
46 | #define MAX8998_ALARM1_YEAR1 0x16 | ||
47 | #define MAX8998_ALARM1_YEAR2 0x17 | ||
48 | #define MAX8998_ALARM0_CONF 0x18 | ||
49 | #define MAX8998_ALARM1_CONF 0x19 | ||
50 | #define MAX8998_RTC_STATUS 0x1a | ||
51 | #define MAX8998_WTSR_SMPL_CNTL 0x1b | ||
52 | #define MAX8998_TEST 0x1f | ||
53 | |||
54 | #define HOUR_12 (1 << 7) | ||
55 | #define HOUR_PM (1 << 5) | ||
56 | #define ALARM0_STATUS (1 << 1) | ||
57 | #define ALARM1_STATUS (1 << 2) | ||
58 | |||
59 | enum { | ||
60 | RTC_SEC = 0, | ||
61 | RTC_MIN, | ||
62 | RTC_HOUR, | ||
63 | RTC_WEEKDAY, | ||
64 | RTC_DATE, | ||
65 | RTC_MONTH, | ||
66 | RTC_YEAR1, | ||
67 | RTC_YEAR2, | ||
68 | }; | ||
69 | |||
70 | struct max8998_rtc_info { | ||
71 | struct device *dev; | ||
72 | struct max8998_dev *max8998; | ||
73 | struct i2c_client *rtc; | ||
74 | struct rtc_device *rtc_dev; | ||
75 | int irq; | ||
76 | }; | ||
77 | |||
78 | static void max8998_data_to_tm(u8 *data, struct rtc_time *tm) | ||
79 | { | ||
80 | tm->tm_sec = bcd2bin(data[RTC_SEC]); | ||
81 | tm->tm_min = bcd2bin(data[RTC_MIN]); | ||
82 | if (data[RTC_HOUR] & HOUR_12) { | ||
83 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f); | ||
84 | if (data[RTC_HOUR] & HOUR_PM) | ||
85 | tm->tm_hour += 12; | ||
86 | } else | ||
87 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f); | ||
88 | |||
89 | tm->tm_wday = data[RTC_WEEKDAY] & 0x07; | ||
90 | tm->tm_mday = bcd2bin(data[RTC_DATE]); | ||
91 | tm->tm_mon = bcd2bin(data[RTC_MONTH]); | ||
92 | tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100; | ||
93 | tm->tm_year -= 1900; | ||
94 | } | ||
95 | |||
96 | static void max8998_tm_to_data(struct rtc_time *tm, u8 *data) | ||
97 | { | ||
98 | data[RTC_SEC] = bin2bcd(tm->tm_sec); | ||
99 | data[RTC_MIN] = bin2bcd(tm->tm_min); | ||
100 | data[RTC_HOUR] = bin2bcd(tm->tm_hour); | ||
101 | data[RTC_WEEKDAY] = tm->tm_wday; | ||
102 | data[RTC_DATE] = bin2bcd(tm->tm_mday); | ||
103 | data[RTC_MONTH] = bin2bcd(tm->tm_mon); | ||
104 | data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100); | ||
105 | data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100); | ||
106 | } | ||
107 | |||
108 | static int max8998_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
109 | { | ||
110 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
111 | u8 data[8]; | ||
112 | int ret; | ||
113 | |||
114 | ret = max8998_bulk_read(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | |||
118 | max8998_data_to_tm(data, tm); | ||
119 | |||
120 | return rtc_valid_tm(tm); | ||
121 | } | ||
122 | |||
123 | static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
124 | { | ||
125 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
126 | u8 data[8]; | ||
127 | |||
128 | max8998_tm_to_data(tm, data); | ||
129 | |||
130 | return max8998_bulk_write(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
131 | } | ||
132 | |||
133 | static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
134 | { | ||
135 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
136 | u8 data[8]; | ||
137 | u8 val; | ||
138 | int ret; | ||
139 | |||
140 | ret = max8998_bulk_read(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | |||
144 | max8998_data_to_tm(data, &alrm->time); | ||
145 | |||
146 | ret = max8998_read_reg(info->rtc, MAX8998_ALARM0_CONF, &val); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | alrm->enabled = !!val; | ||
151 | |||
152 | ret = max8998_read_reg(info->rtc, MAX8998_RTC_STATUS, &val); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | if (val & ALARM0_STATUS) | ||
157 | alrm->pending = 1; | ||
158 | else | ||
159 | alrm->pending = 0; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int max8998_rtc_stop_alarm(struct max8998_rtc_info *info) | ||
165 | { | ||
166 | return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0); | ||
167 | } | ||
168 | |||
169 | static int max8998_rtc_start_alarm(struct max8998_rtc_info *info) | ||
170 | { | ||
171 | return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0x77); | ||
172 | } | ||
173 | |||
174 | static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
175 | { | ||
176 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
177 | u8 data[8]; | ||
178 | int ret; | ||
179 | |||
180 | max8998_tm_to_data(&alrm->time, data); | ||
181 | |||
182 | ret = max8998_rtc_stop_alarm(info); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | |||
186 | ret = max8998_bulk_write(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | if (alrm->enabled) | ||
191 | return max8998_rtc_start_alarm(info); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int max8998_rtc_alarm_irq_enable(struct device *dev, | ||
197 | unsigned int enabled) | ||
198 | { | ||
199 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
200 | |||
201 | if (enabled) | ||
202 | return max8998_rtc_start_alarm(info); | ||
203 | else | ||
204 | return max8998_rtc_stop_alarm(info); | ||
205 | } | ||
206 | |||
207 | static irqreturn_t max8998_rtc_alarm_irq(int irq, void *data) | ||
208 | { | ||
209 | struct max8998_rtc_info *info = data; | ||
210 | |||
211 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
212 | |||
213 | return IRQ_HANDLED; | ||
214 | } | ||
215 | |||
216 | static const struct rtc_class_ops max8998_rtc_ops = { | ||
217 | .read_time = max8998_rtc_read_time, | ||
218 | .set_time = max8998_rtc_set_time, | ||
219 | .read_alarm = max8998_rtc_read_alarm, | ||
220 | .set_alarm = max8998_rtc_set_alarm, | ||
221 | .alarm_irq_enable = max8998_rtc_alarm_irq_enable, | ||
222 | }; | ||
223 | |||
224 | static int __devinit max8998_rtc_probe(struct platform_device *pdev) | ||
225 | { | ||
226 | struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent); | ||
227 | struct max8998_rtc_info *info; | ||
228 | int ret; | ||
229 | |||
230 | info = kzalloc(sizeof(struct max8998_rtc_info), GFP_KERNEL); | ||
231 | if (!info) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | info->dev = &pdev->dev; | ||
235 | info->max8998 = max8998; | ||
236 | info->rtc = max8998->rtc; | ||
237 | info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0; | ||
238 | |||
239 | info->rtc_dev = rtc_device_register("max8998-rtc", &pdev->dev, | ||
240 | &max8998_rtc_ops, THIS_MODULE); | ||
241 | |||
242 | if (IS_ERR(info->rtc_dev)) { | ||
243 | ret = PTR_ERR(info->rtc_dev); | ||
244 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
245 | goto out_rtc; | ||
246 | } | ||
247 | |||
248 | platform_set_drvdata(pdev, info); | ||
249 | |||
250 | ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0, | ||
251 | "rtc-alarm0", info); | ||
252 | if (ret < 0) | ||
253 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | ||
254 | info->irq, ret); | ||
255 | |||
256 | return 0; | ||
257 | |||
258 | out_rtc: | ||
259 | kfree(info); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | static int __devexit max8998_rtc_remove(struct platform_device *pdev) | ||
264 | { | ||
265 | struct max8998_rtc_info *info = platform_get_drvdata(pdev); | ||
266 | |||
267 | if (info) { | ||
268 | free_irq(info->irq, info); | ||
269 | rtc_device_unregister(info->rtc_dev); | ||
270 | kfree(info); | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static struct platform_driver max8998_rtc_driver = { | ||
277 | .driver = { | ||
278 | .name = "max8998-rtc", | ||
279 | .owner = THIS_MODULE, | ||
280 | }, | ||
281 | .probe = max8998_rtc_probe, | ||
282 | .remove = __devexit_p(max8998_rtc_remove), | ||
283 | }; | ||
284 | |||
285 | static int __init max8998_rtc_init(void) | ||
286 | { | ||
287 | return platform_driver_register(&max8998_rtc_driver); | ||
288 | } | ||
289 | module_init(max8998_rtc_init); | ||
290 | |||
291 | static void __exit max8998_rtc_exit(void) | ||
292 | { | ||
293 | platform_driver_unregister(&max8998_rtc_driver); | ||
294 | } | ||
295 | module_exit(max8998_rtc_exit); | ||
296 | |||
297 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | ||
298 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
299 | MODULE_DESCRIPTION("Maxim MAX8998 RTC driver"); | ||
300 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c deleted file mode 100644 index 675bfb515367..000000000000 --- a/drivers/rtc/rtc-mc13783.c +++ /dev/null | |||
@@ -1,428 +0,0 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Freescale MC13783 PMIC | ||
3 | * | ||
4 | * (C) 2009 Sascha Hauer, Pengutronix | ||
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/mfd/mc13783.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/rtc.h> | ||
18 | |||
19 | #define DRIVER_NAME "mc13783-rtc" | ||
20 | |||
21 | #define MC13783_RTCTOD 20 | ||
22 | #define MC13783_RTCTODA 21 | ||
23 | #define MC13783_RTCDAY 22 | ||
24 | #define MC13783_RTCDAYA 23 | ||
25 | |||
26 | struct mc13783_rtc { | ||
27 | struct rtc_device *rtc; | ||
28 | struct mc13783 *mc13783; | ||
29 | int valid; | ||
30 | }; | ||
31 | |||
32 | static int mc13783_rtc_irq_enable_unlocked(struct device *dev, | ||
33 | unsigned int enabled, int irq) | ||
34 | { | ||
35 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
36 | int (*func)(struct mc13783 *mc13783, int irq); | ||
37 | |||
38 | if (!priv->valid) | ||
39 | return -ENODATA; | ||
40 | |||
41 | func = enabled ? mc13783_irq_unmask : mc13783_irq_mask; | ||
42 | return func(priv->mc13783, irq); | ||
43 | } | ||
44 | |||
45 | static int mc13783_rtc_irq_enable(struct device *dev, | ||
46 | unsigned int enabled, int irq) | ||
47 | { | ||
48 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
49 | int ret; | ||
50 | |||
51 | mc13783_lock(priv->mc13783); | ||
52 | |||
53 | ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
54 | |||
55 | mc13783_unlock(priv->mc13783); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
61 | { | ||
62 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
63 | unsigned int seconds, days1, days2; | ||
64 | unsigned long s1970; | ||
65 | int ret; | ||
66 | |||
67 | mc13783_lock(priv->mc13783); | ||
68 | |||
69 | if (!priv->valid) { | ||
70 | ret = -ENODATA; | ||
71 | goto out; | ||
72 | } | ||
73 | |||
74 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days1); | ||
75 | if (unlikely(ret)) | ||
76 | goto out; | ||
77 | |||
78 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTOD, &seconds); | ||
79 | if (unlikely(ret)) | ||
80 | goto out; | ||
81 | |||
82 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days2); | ||
83 | out: | ||
84 | mc13783_unlock(priv->mc13783); | ||
85 | |||
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | if (days2 == days1 + 1) { | ||
90 | if (seconds >= 86400 / 2) | ||
91 | days2 = days1; | ||
92 | else | ||
93 | days1 = days2; | ||
94 | } | ||
95 | |||
96 | if (days1 != days2) | ||
97 | return -EIO; | ||
98 | |||
99 | s1970 = days1 * 86400 + seconds; | ||
100 | |||
101 | rtc_time_to_tm(s1970, tm); | ||
102 | |||
103 | return rtc_valid_tm(tm); | ||
104 | } | ||
105 | |||
106 | static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
107 | { | ||
108 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
109 | unsigned int seconds, days; | ||
110 | unsigned int alarmseconds; | ||
111 | int ret; | ||
112 | |||
113 | seconds = secs % 86400; | ||
114 | days = secs / 86400; | ||
115 | |||
116 | mc13783_lock(priv->mc13783); | ||
117 | |||
118 | /* | ||
119 | * temporarily invalidate alarm to prevent triggering it when the day is | ||
120 | * already updated while the time isn't yet. | ||
121 | */ | ||
122 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds); | ||
123 | if (unlikely(ret)) | ||
124 | goto out; | ||
125 | |||
126 | if (alarmseconds < 86400) { | ||
127 | ret = mc13783_reg_write(priv->mc13783, | ||
128 | MC13783_RTCTODA, 0x1ffff); | ||
129 | if (unlikely(ret)) | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * write seconds=0 to prevent a day switch between writing days | ||
135 | * and seconds below | ||
136 | */ | ||
137 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); | ||
138 | if (unlikely(ret)) | ||
139 | goto out; | ||
140 | |||
141 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAY, days); | ||
142 | if (unlikely(ret)) | ||
143 | goto out; | ||
144 | |||
145 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, seconds); | ||
146 | if (unlikely(ret)) | ||
147 | goto out; | ||
148 | |||
149 | /* restore alarm */ | ||
150 | if (alarmseconds < 86400) { | ||
151 | ret = mc13783_reg_write(priv->mc13783, | ||
152 | MC13783_RTCTODA, alarmseconds); | ||
153 | if (unlikely(ret)) | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST); | ||
158 | if (unlikely(ret)) | ||
159 | goto out; | ||
160 | |||
161 | ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST); | ||
162 | out: | ||
163 | priv->valid = !ret; | ||
164 | |||
165 | mc13783_unlock(priv->mc13783); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
171 | { | ||
172 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
173 | unsigned seconds, days; | ||
174 | unsigned long s1970; | ||
175 | int enabled, pending; | ||
176 | int ret; | ||
177 | |||
178 | mc13783_lock(priv->mc13783); | ||
179 | |||
180 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds); | ||
181 | if (unlikely(ret)) | ||
182 | goto out; | ||
183 | if (seconds >= 86400) { | ||
184 | ret = -ENODATA; | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days); | ||
189 | if (unlikely(ret)) | ||
190 | goto out; | ||
191 | |||
192 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA, | ||
193 | &enabled, &pending); | ||
194 | |||
195 | out: | ||
196 | mc13783_unlock(priv->mc13783); | ||
197 | |||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | alarm->enabled = enabled; | ||
202 | alarm->pending = pending; | ||
203 | |||
204 | s1970 = days * 86400 + seconds; | ||
205 | |||
206 | rtc_time_to_tm(s1970, &alarm->time); | ||
207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
213 | { | ||
214 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
215 | unsigned long s1970; | ||
216 | unsigned seconds, days; | ||
217 | int ret; | ||
218 | |||
219 | mc13783_lock(priv->mc13783); | ||
220 | |||
221 | /* disable alarm to prevent false triggering */ | ||
222 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff); | ||
223 | if (unlikely(ret)) | ||
224 | goto out; | ||
225 | |||
226 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA); | ||
227 | if (unlikely(ret)) | ||
228 | goto out; | ||
229 | |||
230 | ret = rtc_tm_to_time(&alarm->time, &s1970); | ||
231 | if (unlikely(ret)) | ||
232 | goto out; | ||
233 | |||
234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | ||
235 | s1970); | ||
236 | |||
237 | ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
238 | MC13783_IRQ_TODA); | ||
239 | if (unlikely(ret)) | ||
240 | goto out; | ||
241 | |||
242 | seconds = s1970 % 86400; | ||
243 | days = s1970 / 86400; | ||
244 | |||
245 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days); | ||
246 | if (unlikely(ret)) | ||
247 | goto out; | ||
248 | |||
249 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds); | ||
250 | |||
251 | out: | ||
252 | mc13783_unlock(priv->mc13783); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev) | ||
258 | { | ||
259 | struct mc13783_rtc *priv = dev; | ||
260 | struct mc13783 *mc13783 = priv->mc13783; | ||
261 | |||
262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
263 | |||
264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
265 | |||
266 | mc13783_irq_ack(mc13783, irq); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | ||
272 | { | ||
273 | struct mc13783_rtc *priv = dev; | ||
274 | struct mc13783 *mc13783 = priv->mc13783; | ||
275 | |||
276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
277 | |||
278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
279 | |||
280 | mc13783_irq_ack(mc13783, irq); | ||
281 | |||
282 | return IRQ_HANDLED; | ||
283 | } | ||
284 | |||
285 | static int mc13783_rtc_update_irq_enable(struct device *dev, | ||
286 | unsigned int enabled) | ||
287 | { | ||
288 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ); | ||
289 | } | ||
290 | |||
291 | static int mc13783_rtc_alarm_irq_enable(struct device *dev, | ||
292 | unsigned int enabled) | ||
293 | { | ||
294 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA); | ||
295 | } | ||
296 | |||
297 | static const struct rtc_class_ops mc13783_rtc_ops = { | ||
298 | .read_time = mc13783_rtc_read_time, | ||
299 | .set_mmss = mc13783_rtc_set_mmss, | ||
300 | .read_alarm = mc13783_rtc_read_alarm, | ||
301 | .set_alarm = mc13783_rtc_set_alarm, | ||
302 | .alarm_irq_enable = mc13783_rtc_alarm_irq_enable, | ||
303 | .update_irq_enable = mc13783_rtc_update_irq_enable, | ||
304 | }; | ||
305 | |||
306 | static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev) | ||
307 | { | ||
308 | struct mc13783_rtc *priv = dev; | ||
309 | struct mc13783 *mc13783 = priv->mc13783; | ||
310 | |||
311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | ||
312 | priv->valid = 0; | ||
313 | |||
314 | mc13783_irq_mask(mc13783, irq); | ||
315 | |||
316 | return IRQ_HANDLED; | ||
317 | } | ||
318 | |||
319 | static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | ||
320 | { | ||
321 | int ret; | ||
322 | struct mc13783_rtc *priv; | ||
323 | struct mc13783 *mc13783; | ||
324 | int rtcrst_pending; | ||
325 | |||
326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
327 | if (!priv) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
331 | priv->mc13783 = mc13783; | ||
332 | |||
333 | platform_set_drvdata(pdev, priv); | ||
334 | |||
335 | mc13783_lock(mc13783); | ||
336 | |||
337 | ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST, | ||
338 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); | ||
339 | if (ret) | ||
340 | goto err_reset_irq_request; | ||
341 | |||
342 | ret = mc13783_irq_status(mc13783, MC13783_IRQ_RTCRST, | ||
343 | NULL, &rtcrst_pending); | ||
344 | if (ret) | ||
345 | goto err_reset_irq_status; | ||
346 | |||
347 | priv->valid = !rtcrst_pending; | ||
348 | |||
349 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_1HZ, | ||
350 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | ||
351 | if (ret) | ||
352 | goto err_update_irq_request; | ||
353 | |||
354 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_TODA, | ||
355 | mc13783_rtc_alarm_handler, DRIVER_NAME, priv); | ||
356 | if (ret) | ||
357 | goto err_alarm_irq_request; | ||
358 | |||
359 | priv->rtc = rtc_device_register(pdev->name, | ||
360 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); | ||
361 | if (IS_ERR(priv->rtc)) { | ||
362 | ret = PTR_ERR(priv->rtc); | ||
363 | |||
364 | mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv); | ||
365 | err_alarm_irq_request: | ||
366 | |||
367 | mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv); | ||
368 | err_update_irq_request: | ||
369 | |||
370 | err_reset_irq_status: | ||
371 | |||
372 | mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv); | ||
373 | err_reset_irq_request: | ||
374 | |||
375 | platform_set_drvdata(pdev, NULL); | ||
376 | kfree(priv); | ||
377 | } | ||
378 | |||
379 | mc13783_unlock(mc13783); | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit mc13783_rtc_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); | ||
387 | |||
388 | mc13783_lock(priv->mc13783); | ||
389 | |||
390 | rtc_device_unregister(priv->rtc); | ||
391 | |||
392 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); | ||
393 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | ||
394 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | ||
395 | |||
396 | mc13783_unlock(priv->mc13783); | ||
397 | |||
398 | platform_set_drvdata(pdev, NULL); | ||
399 | |||
400 | kfree(priv); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static struct platform_driver mc13783_rtc_driver = { | ||
406 | .remove = __devexit_p(mc13783_rtc_remove), | ||
407 | .driver = { | ||
408 | .name = DRIVER_NAME, | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static int __init mc13783_rtc_init(void) | ||
414 | { | ||
415 | return platform_driver_probe(&mc13783_rtc_driver, &mc13783_rtc_probe); | ||
416 | } | ||
417 | module_init(mc13783_rtc_init); | ||
418 | |||
419 | static void __exit mc13783_rtc_exit(void) | ||
420 | { | ||
421 | platform_driver_unregister(&mc13783_rtc_driver); | ||
422 | } | ||
423 | module_exit(mc13783_rtc_exit); | ||
424 | |||
425 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
426 | MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC"); | ||
427 | MODULE_LICENSE("GPL v2"); | ||
428 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c new file mode 100644 index 000000000000..5314b153bfba --- /dev/null +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Freescale MC13XXX PMIC | ||
3 | * | ||
4 | * (C) 2009 Sascha Hauer, Pengutronix | ||
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/mfd/mc13xxx.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/rtc.h> | ||
18 | |||
19 | #define DRIVER_NAME "mc13xxx-rtc" | ||
20 | |||
21 | #define MC13XXX_RTCTOD 20 | ||
22 | #define MC13XXX_RTCTODA 21 | ||
23 | #define MC13XXX_RTCDAY 22 | ||
24 | #define MC13XXX_RTCDAYA 23 | ||
25 | |||
26 | struct mc13xxx_rtc { | ||
27 | struct rtc_device *rtc; | ||
28 | struct mc13xxx *mc13xxx; | ||
29 | int valid; | ||
30 | }; | ||
31 | |||
32 | static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev, | ||
33 | unsigned int enabled, int irq) | ||
34 | { | ||
35 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
36 | int (*func)(struct mc13xxx *mc13xxx, int irq); | ||
37 | |||
38 | if (!priv->valid) | ||
39 | return -ENODATA; | ||
40 | |||
41 | func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask; | ||
42 | return func(priv->mc13xxx, irq); | ||
43 | } | ||
44 | |||
45 | static int mc13xxx_rtc_irq_enable(struct device *dev, | ||
46 | unsigned int enabled, int irq) | ||
47 | { | ||
48 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
49 | int ret; | ||
50 | |||
51 | mc13xxx_lock(priv->mc13xxx); | ||
52 | |||
53 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
54 | |||
55 | mc13xxx_unlock(priv->mc13xxx); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
61 | { | ||
62 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
63 | unsigned int seconds, days1, days2; | ||
64 | unsigned long s1970; | ||
65 | int ret; | ||
66 | |||
67 | mc13xxx_lock(priv->mc13xxx); | ||
68 | |||
69 | if (!priv->valid) { | ||
70 | ret = -ENODATA; | ||
71 | goto out; | ||
72 | } | ||
73 | |||
74 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1); | ||
75 | if (unlikely(ret)) | ||
76 | goto out; | ||
77 | |||
78 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds); | ||
79 | if (unlikely(ret)) | ||
80 | goto out; | ||
81 | |||
82 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2); | ||
83 | out: | ||
84 | mc13xxx_unlock(priv->mc13xxx); | ||
85 | |||
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | if (days2 == days1 + 1) { | ||
90 | if (seconds >= 86400 / 2) | ||
91 | days2 = days1; | ||
92 | else | ||
93 | days1 = days2; | ||
94 | } | ||
95 | |||
96 | if (days1 != days2) | ||
97 | return -EIO; | ||
98 | |||
99 | s1970 = days1 * 86400 + seconds; | ||
100 | |||
101 | rtc_time_to_tm(s1970, tm); | ||
102 | |||
103 | return rtc_valid_tm(tm); | ||
104 | } | ||
105 | |||
106 | static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
107 | { | ||
108 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
109 | unsigned int seconds, days; | ||
110 | unsigned int alarmseconds; | ||
111 | int ret; | ||
112 | |||
113 | seconds = secs % 86400; | ||
114 | days = secs / 86400; | ||
115 | |||
116 | mc13xxx_lock(priv->mc13xxx); | ||
117 | |||
118 | /* | ||
119 | * temporarily invalidate alarm to prevent triggering it when the day is | ||
120 | * already updated while the time isn't yet. | ||
121 | */ | ||
122 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds); | ||
123 | if (unlikely(ret)) | ||
124 | goto out; | ||
125 | |||
126 | if (alarmseconds < 86400) { | ||
127 | ret = mc13xxx_reg_write(priv->mc13xxx, | ||
128 | MC13XXX_RTCTODA, 0x1ffff); | ||
129 | if (unlikely(ret)) | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * write seconds=0 to prevent a day switch between writing days | ||
135 | * and seconds below | ||
136 | */ | ||
137 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0); | ||
138 | if (unlikely(ret)) | ||
139 | goto out; | ||
140 | |||
141 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days); | ||
142 | if (unlikely(ret)) | ||
143 | goto out; | ||
144 | |||
145 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds); | ||
146 | if (unlikely(ret)) | ||
147 | goto out; | ||
148 | |||
149 | /* restore alarm */ | ||
150 | if (alarmseconds < 86400) { | ||
151 | ret = mc13xxx_reg_write(priv->mc13xxx, | ||
152 | MC13XXX_RTCTODA, alarmseconds); | ||
153 | if (unlikely(ret)) | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
158 | if (unlikely(ret)) | ||
159 | goto out; | ||
160 | |||
161 | ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
162 | out: | ||
163 | priv->valid = !ret; | ||
164 | |||
165 | mc13xxx_unlock(priv->mc13xxx); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
171 | { | ||
172 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
173 | unsigned seconds, days; | ||
174 | unsigned long s1970; | ||
175 | int enabled, pending; | ||
176 | int ret; | ||
177 | |||
178 | mc13xxx_lock(priv->mc13xxx); | ||
179 | |||
180 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds); | ||
181 | if (unlikely(ret)) | ||
182 | goto out; | ||
183 | if (seconds >= 86400) { | ||
184 | ret = -ENODATA; | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days); | ||
189 | if (unlikely(ret)) | ||
190 | goto out; | ||
191 | |||
192 | ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA, | ||
193 | &enabled, &pending); | ||
194 | |||
195 | out: | ||
196 | mc13xxx_unlock(priv->mc13xxx); | ||
197 | |||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | alarm->enabled = enabled; | ||
202 | alarm->pending = pending; | ||
203 | |||
204 | s1970 = days * 86400 + seconds; | ||
205 | |||
206 | rtc_time_to_tm(s1970, &alarm->time); | ||
207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
213 | { | ||
214 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
215 | unsigned long s1970; | ||
216 | unsigned seconds, days; | ||
217 | int ret; | ||
218 | |||
219 | mc13xxx_lock(priv->mc13xxx); | ||
220 | |||
221 | /* disable alarm to prevent false triggering */ | ||
222 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); | ||
223 | if (unlikely(ret)) | ||
224 | goto out; | ||
225 | |||
226 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA); | ||
227 | if (unlikely(ret)) | ||
228 | goto out; | ||
229 | |||
230 | ret = rtc_tm_to_time(&alarm->time, &s1970); | ||
231 | if (unlikely(ret)) | ||
232 | goto out; | ||
233 | |||
234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | ||
235 | s1970); | ||
236 | |||
237 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
238 | MC13XXX_IRQ_TODA); | ||
239 | if (unlikely(ret)) | ||
240 | goto out; | ||
241 | |||
242 | seconds = s1970 % 86400; | ||
243 | days = s1970 / 86400; | ||
244 | |||
245 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); | ||
246 | if (unlikely(ret)) | ||
247 | goto out; | ||
248 | |||
249 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds); | ||
250 | |||
251 | out: | ||
252 | mc13xxx_unlock(priv->mc13xxx); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev) | ||
258 | { | ||
259 | struct mc13xxx_rtc *priv = dev; | ||
260 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
261 | |||
262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
263 | |||
264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
265 | |||
266 | mc13xxx_irq_ack(mc13xxx, irq); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) | ||
272 | { | ||
273 | struct mc13xxx_rtc *priv = dev; | ||
274 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
275 | |||
276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
277 | |||
278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
279 | |||
280 | mc13xxx_irq_ack(mc13xxx, irq); | ||
281 | |||
282 | return IRQ_HANDLED; | ||
283 | } | ||
284 | |||
285 | static int mc13xxx_rtc_update_irq_enable(struct device *dev, | ||
286 | unsigned int enabled) | ||
287 | { | ||
288 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_1HZ); | ||
289 | } | ||
290 | |||
291 | static int mc13xxx_rtc_alarm_irq_enable(struct device *dev, | ||
292 | unsigned int enabled) | ||
293 | { | ||
294 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA); | ||
295 | } | ||
296 | |||
297 | static const struct rtc_class_ops mc13xxx_rtc_ops = { | ||
298 | .read_time = mc13xxx_rtc_read_time, | ||
299 | .set_mmss = mc13xxx_rtc_set_mmss, | ||
300 | .read_alarm = mc13xxx_rtc_read_alarm, | ||
301 | .set_alarm = mc13xxx_rtc_set_alarm, | ||
302 | .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable, | ||
303 | .update_irq_enable = mc13xxx_rtc_update_irq_enable, | ||
304 | }; | ||
305 | |||
306 | static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) | ||
307 | { | ||
308 | struct mc13xxx_rtc *priv = dev; | ||
309 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
310 | |||
311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | ||
312 | priv->valid = 0; | ||
313 | |||
314 | mc13xxx_irq_mask(mc13xxx, irq); | ||
315 | |||
316 | return IRQ_HANDLED; | ||
317 | } | ||
318 | |||
319 | static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev) | ||
320 | { | ||
321 | int ret; | ||
322 | struct mc13xxx_rtc *priv; | ||
323 | struct mc13xxx *mc13xxx; | ||
324 | int rtcrst_pending; | ||
325 | |||
326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
327 | if (!priv) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | mc13xxx = dev_get_drvdata(pdev->dev.parent); | ||
331 | priv->mc13xxx = mc13xxx; | ||
332 | |||
333 | platform_set_drvdata(pdev, priv); | ||
334 | |||
335 | mc13xxx_lock(mc13xxx); | ||
336 | |||
337 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, | ||
338 | mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); | ||
339 | if (ret) | ||
340 | goto err_reset_irq_request; | ||
341 | |||
342 | ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST, | ||
343 | NULL, &rtcrst_pending); | ||
344 | if (ret) | ||
345 | goto err_reset_irq_status; | ||
346 | |||
347 | priv->valid = !rtcrst_pending; | ||
348 | |||
349 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ, | ||
350 | mc13xxx_rtc_update_handler, DRIVER_NAME, priv); | ||
351 | if (ret) | ||
352 | goto err_update_irq_request; | ||
353 | |||
354 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA, | ||
355 | mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv); | ||
356 | if (ret) | ||
357 | goto err_alarm_irq_request; | ||
358 | |||
359 | priv->rtc = rtc_device_register(pdev->name, | ||
360 | &pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE); | ||
361 | if (IS_ERR(priv->rtc)) { | ||
362 | ret = PTR_ERR(priv->rtc); | ||
363 | |||
364 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv); | ||
365 | err_alarm_irq_request: | ||
366 | |||
367 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv); | ||
368 | err_update_irq_request: | ||
369 | |||
370 | err_reset_irq_status: | ||
371 | |||
372 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv); | ||
373 | err_reset_irq_request: | ||
374 | |||
375 | platform_set_drvdata(pdev, NULL); | ||
376 | kfree(priv); | ||
377 | } | ||
378 | |||
379 | mc13xxx_unlock(mc13xxx); | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); | ||
387 | |||
388 | mc13xxx_lock(priv->mc13xxx); | ||
389 | |||
390 | rtc_device_unregister(priv->rtc); | ||
391 | |||
392 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv); | ||
393 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_1HZ, priv); | ||
394 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv); | ||
395 | |||
396 | mc13xxx_unlock(priv->mc13xxx); | ||
397 | |||
398 | platform_set_drvdata(pdev, NULL); | ||
399 | |||
400 | kfree(priv); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | const struct platform_device_id mc13xxx_rtc_idtable[] = { | ||
406 | { | ||
407 | .name = "mc13783-rtc", | ||
408 | }, { | ||
409 | .name = "mc13892-rtc", | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static struct platform_driver mc13xxx_rtc_driver = { | ||
414 | .id_table = mc13xxx_rtc_idtable, | ||
415 | .remove = __devexit_p(mc13xxx_rtc_remove), | ||
416 | .driver = { | ||
417 | .name = DRIVER_NAME, | ||
418 | .owner = THIS_MODULE, | ||
419 | }, | ||
420 | }; | ||
421 | |||
422 | static int __init mc13xxx_rtc_init(void) | ||
423 | { | ||
424 | return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe); | ||
425 | } | ||
426 | module_init(mc13xxx_rtc_init); | ||
427 | |||
428 | static void __exit mc13xxx_rtc_exit(void) | ||
429 | { | ||
430 | platform_driver_unregister(&mc13xxx_rtc_driver); | ||
431 | } | ||
432 | module_exit(mc13xxx_rtc_exit); | ||
433 | |||
434 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
435 | MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC"); | ||
436 | MODULE_LICENSE("GPL v2"); | ||
437 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 0bc97698af15..d335f484fcd8 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -124,7 +124,6 @@ | |||
124 | #define PHY_DPLL_CLK (1 << 0) | 124 | #define PHY_DPLL_CLK (1 << 0) |
125 | 125 | ||
126 | /* In module TWL4030_MODULE_PM_MASTER */ | 126 | /* In module TWL4030_MODULE_PM_MASTER */ |
127 | #define PROTECT_KEY 0x0E | ||
128 | #define STS_HW_CONDITIONS 0x0F | 127 | #define STS_HW_CONDITIONS 0x0F |
129 | 128 | ||
130 | /* In module TWL4030_MODULE_PM_RECEIVER */ | 129 | /* In module TWL4030_MODULE_PM_RECEIVER */ |
@@ -418,8 +417,13 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) | |||
418 | static int twl4030_usb_ldo_init(struct twl4030_usb *twl) | 417 | static int twl4030_usb_ldo_init(struct twl4030_usb *twl) |
419 | { | 418 | { |
420 | /* Enable writing to power configuration registers */ | 419 | /* Enable writing to power configuration registers */ |
421 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); | 420 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
422 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); | 421 | TWL4030_PM_MASTER_KEY_CFG1, |
422 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
423 | |||
424 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, | ||
425 | TWL4030_PM_MASTER_KEY_CFG2, | ||
426 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
423 | 427 | ||
424 | /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ | 428 | /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ |
425 | /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ | 429 | /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ |
@@ -455,7 +459,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) | |||
455 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); | 459 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); |
456 | 460 | ||
457 | /* disable access to power configuration registers */ | 461 | /* disable access to power configuration registers */ |
458 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); | 462 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, |
463 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
459 | 464 | ||
460 | return 0; | 465 | return 0; |
461 | 466 | ||