ARM: cpu topology: Add debugfs interface for cpu_power
[cmplus.git] / drivers / mfd / twl6040-codec.c
blob68dec57c897a746a704fe95ee745e93f8e84abff
1 /*
2 * MFD driver for twl6040 codec submodule
4 * Authors: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
5 * Misael Lopez Cruz <misael.lopez@ti.com>
7 * Copyright: (C) 20010 Texas Instruments, Inc.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
25 #include <linux/module.h>
26 #include <linux/types.h>
27 #include <linux/slab.h>
28 #include <linux/kernel.h>
29 #include <linux/platform_device.h>
30 #include <linux/gpio.h>
31 #include <linux/delay.h>
32 #include <linux/i2c/twl.h>
33 #include <linux/mfd/core.h>
34 #include <linux/mfd/twl6040-codec.h>
36 int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
38 int ret;
39 u8 val;
41 mutex_lock(&twl6040->io_mutex);
42 ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
43 if (ret < 0) {
44 mutex_unlock(&twl6040->io_mutex);
45 return ret;
47 mutex_unlock(&twl6040->io_mutex);
49 return val;
51 EXPORT_SYMBOL(twl6040_reg_read);
53 int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
55 int ret;
57 mutex_lock(&twl6040->io_mutex);
58 ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
59 mutex_unlock(&twl6040->io_mutex);
61 return ret;
63 EXPORT_SYMBOL(twl6040_reg_write);
65 int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
67 int ret;
68 u8 val;
70 mutex_lock(&twl6040->io_mutex);
71 ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
72 if (ret)
73 goto out;
75 val |= mask;
76 ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
77 out:
78 mutex_unlock(&twl6040->io_mutex);
79 return ret;
81 EXPORT_SYMBOL(twl6040_set_bits);
83 int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
85 int ret;
86 u8 val;
88 mutex_lock(&twl6040->io_mutex);
89 ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
90 if (ret)
91 goto out;
93 val &= ~mask;
94 ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
95 out:
96 mutex_unlock(&twl6040->io_mutex);
97 return ret;
99 EXPORT_SYMBOL(twl6040_clear_bits);
101 /* twl6040 codec manual power-up sequence */
102 static int twl6040_power_up(struct twl6040 *twl6040)
104 u8 ncpctl, ldoctl, lppllctl, accctl;
105 int ret;
107 ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
108 ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
109 lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
110 accctl = twl6040_reg_read(twl6040, TWL6040_REG_ACCCTL);
112 /* enable reference system */
113 ldoctl |= TWL6040_REFENA;
114 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
115 if (ret)
116 return ret;
117 msleep(10);
119 /* enable internal oscillator */
120 ldoctl |= TWL6040_OSCENA;
121 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
122 if (ret)
123 goto osc_err;
124 udelay(10);
126 /* enable high-side ldo */
127 ldoctl |= TWL6040_HSLDOENA;
128 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
129 if (ret)
130 goto hsldo_err;
131 udelay(244);
133 /* enable negative charge pump */
134 ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
135 ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
136 if (ret)
137 goto ncp_err;
138 udelay(488);
140 /* enable low-side ldo */
141 ldoctl |= TWL6040_LSLDOENA;
142 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
143 if (ret)
144 goto lsldo_err;
145 udelay(244);
147 /* enable low-power pll */
148 lppllctl |= TWL6040_LPLLENA;
149 ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
150 if (ret)
151 goto lppll_err;
153 /* reset state machine */
154 accctl |= TWL6040_RESETSPLIT;
155 ret = twl6040_reg_write(twl6040, TWL6040_REG_ACCCTL, accctl);
156 if (ret)
157 goto rst_err;
158 mdelay(5);
159 accctl &= ~TWL6040_RESETSPLIT;
160 ret = twl6040_reg_write(twl6040, TWL6040_REG_ACCCTL, accctl);
161 if (ret)
162 goto rst_err;
164 /* disable internal oscillator */
165 ldoctl &= ~TWL6040_OSCENA;
166 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
167 if (ret)
168 goto rst_err;
170 return 0;
172 rst_err:
173 lppllctl &= ~TWL6040_LPLLENA;
174 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
175 lppll_err:
176 ldoctl &= ~TWL6040_LSLDOENA;
177 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
178 udelay(244);
179 lsldo_err:
180 ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
181 twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
182 udelay(488);
183 ncp_err:
184 ldoctl &= ~TWL6040_HSLDOENA;
185 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
186 udelay(244);
187 hsldo_err:
188 ldoctl &= ~TWL6040_OSCENA;
189 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
190 osc_err:
191 ldoctl &= ~TWL6040_REFENA;
192 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
193 msleep(10);
195 return ret;
198 /* twl6040 codec manual power-down sequence */
199 static int twl6040_power_down(struct twl6040 *twl6040)
201 u8 ncpctl, ldoctl, lppllctl, accctl;
202 int ret;
204 ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
205 ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
206 lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
207 accctl = twl6040_reg_read(twl6040, TWL6040_REG_ACCCTL);
209 /* enable internal oscillator */
210 ldoctl |= TWL6040_OSCENA;
211 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
212 if (ret)
213 return ret;
214 udelay(10);
216 /* disable low-power pll */
217 lppllctl &= ~TWL6040_LPLLENA;
218 ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
219 if (ret)
220 goto lppll_err;
222 /* disable low-side ldo */
223 ldoctl &= ~TWL6040_LSLDOENA;
224 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
225 if (ret)
226 goto lsldo_err;
227 udelay(244);
229 /* disable negative charge pump */
230 ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
231 ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
232 if (ret)
233 goto ncp_err;
234 udelay(488);
236 /* disable high-side ldo */
237 ldoctl &= ~TWL6040_HSLDOENA;
238 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
239 if (ret)
240 goto hsldo_err;
241 udelay(244);
243 /* disable internal oscillator */
244 ldoctl &= ~TWL6040_OSCENA;
245 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
246 if (ret)
247 goto osc_err;
249 /* disable reference system */
250 ldoctl &= ~TWL6040_REFENA;
251 ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
252 if (ret)
253 goto ref_err;
254 msleep(10);
256 return 0;
258 ref_err:
259 ldoctl |= TWL6040_OSCENA;
260 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
261 udelay(10);
262 osc_err:
263 ldoctl |= TWL6040_HSLDOENA;
264 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
265 udelay(244);
266 hsldo_err:
267 ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
268 twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
269 udelay(488);
270 ncp_err:
271 ldoctl |= TWL6040_LSLDOENA;
272 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
273 udelay(244);
274 lsldo_err:
275 lppllctl |= TWL6040_LPLLENA;
276 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
277 lppll_err:
278 lppllctl |= TWL6040_LPLLENA;
279 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
280 accctl |= TWL6040_RESETSPLIT;
281 twl6040_reg_write(twl6040, TWL6040_REG_ACCCTL, accctl);
282 mdelay(5);
283 accctl &= ~TWL6040_RESETSPLIT;
284 twl6040_reg_write(twl6040, TWL6040_REG_ACCCTL, accctl);
285 ldoctl &= ~TWL6040_OSCENA;
286 twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
287 msleep(10);
289 return ret;
292 static irqreturn_t twl6040_naudint_handler(int irq, void *data)
294 struct twl6040 *twl6040 = data;
295 u8 intid;
297 intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
299 if (intid & TWL6040_READYINT)
300 complete(&twl6040->ready);
302 return IRQ_HANDLED;
305 static int twl6040_power_up_completion(struct twl6040 *twl6040,
306 int naudint)
308 int time_left;
309 int round = 0;
310 int ret = 0;
311 int retry = 0;
312 u8 intid;
313 u8 ncpctl;
314 u8 ldoctl;
315 u8 lppllctl;
316 u8 ncpctl_exp;
317 u8 ldoctl_exp;
318 u8 lppllctl_exp;
320 /* NCPCTL expected value: NCP enabled */
321 ncpctl_exp = (TWL6040_TSHUTENA | TWL6040_NCPENA);
323 /* LDOCTL expected value: HS/LS LDOs and Reference enabled */
324 ldoctl_exp = (TWL6040_REFENA | TWL6040_HSLDOENA | TWL6040_LSLDOENA);
326 /* LPPLLCTL expected value: Low-Power PLL enabled */
327 lppllctl_exp = TWL6040_LPLLENA;
329 do {
330 gpio_set_value(twl6040->audpwron, 1);
331 time_left = wait_for_completion_timeout(&twl6040->ready,
332 msecs_to_jiffies(700));
333 if (!time_left) {
334 intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
335 if (!(intid & TWL6040_READYINT)) {
336 dev_err(twl6040->dev,
337 "timeout waiting for READYINT\n");
338 return -ETIMEDOUT;
342 * Power on seemingly completed.
343 * Look for clues that the twl6040 might be still booting.
346 retry = 0;
347 ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
348 if (ncpctl != ncpctl_exp)
349 retry++;
351 ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
352 if (ldoctl != ldoctl_exp)
353 retry++;
355 lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
356 if (lppllctl != lppllctl_exp)
357 retry++;
359 if (retry) {
360 dev_err(twl6040->dev,
361 "NCPCTL: 0x%02x (should be 0x%02x)\n"
362 "LDOCTL: 0x%02x (should be 0x%02x)\n"
363 "LPLLCTL: 0x%02x (should be 0x%02x)\n",
364 ncpctl, ncpctl_exp,
365 ldoctl, ldoctl_exp,
366 lppllctl, lppllctl_exp);
367 round++;
368 gpio_set_value(twl6040->audpwron, 0);
369 usleep_range(1000, 1500);
370 continue;
372 } while (round && (round < 3));
374 if (round >= 3) {
375 dev_err(twl6040->dev,
376 "Automatic power on failed, reverting to manual\n");
377 twl6040->audpwron = -EINVAL;
378 ret = twl6040_power_up(twl6040);
379 if (ret)
380 dev_err(twl6040->dev, "Manual power-up failed\n");
383 return ret;
386 static int twl6040_power(struct twl6040 *twl6040, int enable)
388 struct twl4030_codec_data *pdata = dev_get_platdata(twl6040->dev);
389 int audpwron = twl6040->audpwron;
390 int naudint = twl6040->irq;
391 int ret = 0;
393 if (enable) {
394 /* enable 32kHz external clock */
395 if (pdata->set_ext_clk32k) {
396 ret = pdata->set_ext_clk32k(true);
397 if (ret) {
398 dev_err(twl6040->dev,
399 "failed to enable CLK32K %d\n", ret);
400 return ret;
404 /* disable internal 32kHz oscillator */
405 twl6040_clear_bits(twl6040, TWL6040_REG_ACCCTL,
406 TWL6040_CLK32KSEL);
408 if (gpio_is_valid(audpwron)) {
409 /* wait for power-up completion */
410 ret = twl6040_power_up_completion(twl6040, naudint);
411 if (ret) {
412 dev_err(twl6040->dev,
413 "automatic power-down failed\n");
414 return ret;
416 } else {
417 /* use manual power-up sequence */
418 ret = twl6040_power_up(twl6040);
419 if (ret) {
420 dev_err(twl6040->dev,
421 "manual power-up failed\n");
422 return ret;
425 twl6040->pll = TWL6040_LPPLL_ID;
426 twl6040->sysclk = 19200000;
427 } else {
428 if (gpio_is_valid(audpwron)) {
429 /* use AUDPWRON line */
430 gpio_set_value(audpwron, 0);
432 /* power-down sequence latency */
433 udelay(500);
434 } else {
435 /* use manual power-down sequence */
436 ret = twl6040_power_down(twl6040);
437 if (ret) {
438 dev_err(twl6040->dev,
439 "manual power-down failed\n");
440 return ret;
444 /* enable internal 32kHz oscillator */
445 twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL,
446 TWL6040_CLK32KSEL);
448 /* disable 32kHz external clock */
449 if (pdata->set_ext_clk32k) {
450 ret = pdata->set_ext_clk32k(false);
451 if (ret)
452 dev_err(twl6040->dev,
453 "failed to disable CLK32K %d\n", ret);
456 twl6040->pll = TWL6040_NOPLL_ID;
457 twl6040->sysclk = 0;
460 twl6040->powered = enable;
462 return ret;
465 int twl6040_enable(struct twl6040 *twl6040)
467 int ret = 0;
469 mutex_lock(&twl6040->mutex);
470 if (!twl6040->power_count++)
471 ret = twl6040_power(twl6040, 1);
472 mutex_unlock(&twl6040->mutex);
474 return ret;
476 EXPORT_SYMBOL(twl6040_enable);
478 int twl6040_disable(struct twl6040 *twl6040)
480 int ret = 0;
482 mutex_lock(&twl6040->mutex);
483 WARN(!twl6040->power_count, "TWL6040 is already disabled");
484 if (!--twl6040->power_count)
485 ret = twl6040_power(twl6040, 0);
486 mutex_unlock(&twl6040->mutex);
488 return ret;
490 EXPORT_SYMBOL(twl6040_disable);
492 int twl6040_is_enabled(struct twl6040 *twl6040)
494 return twl6040->power_count;
496 EXPORT_SYMBOL(twl6040_is_enabled);
498 int twl6040_set_pll(struct twl6040 *twl6040, enum twl6040_pll_id id,
499 unsigned int freq_in, unsigned int freq_out)
501 u8 hppllctl, lppllctl;
502 int ret = 0;
504 mutex_lock(&twl6040->mutex);
506 hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
507 lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
509 switch (id) {
510 case TWL6040_LPPLL_ID:
511 /* lppll divider */
512 switch (freq_out) {
513 case 17640000:
514 lppllctl |= TWL6040_LPLLFIN;
515 break;
516 case 19200000:
517 lppllctl &= ~TWL6040_LPLLFIN;
518 break;
519 default:
520 dev_err(twl6040->dev,
521 "freq_out %d not supported\n", freq_out);
522 ret = -EINVAL;
523 goto pll_out;
525 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
527 switch (freq_in) {
528 case 32768:
529 lppllctl |= TWL6040_LPLLENA;
530 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
531 lppllctl);
532 mdelay(5);
533 lppllctl &= ~TWL6040_HPLLSEL;
534 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
535 lppllctl);
536 hppllctl &= ~TWL6040_HPLLENA;
537 twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
538 hppllctl);
539 break;
540 default:
541 dev_err(twl6040->dev,
542 "freq_in %d not supported\n", freq_in);
543 ret = -EINVAL;
544 goto pll_out;
547 twl6040->pll = TWL6040_LPPLL_ID;
548 break;
549 case TWL6040_HPPLL_ID:
550 /* high-performance pll can provide only 19.2 MHz */
551 if (freq_out != 19200000) {
552 dev_err(twl6040->dev,
553 "freq_out %d not supported\n", freq_out);
554 ret = -EINVAL;
555 goto pll_out;
558 hppllctl &= ~TWL6040_MCLK_MSK;
560 switch (freq_in) {
561 case 12000000:
562 /* mclk input, pll enabled */
563 hppllctl |= TWL6040_MCLK_12000KHZ |
564 TWL6040_HPLLSQRBP |
565 TWL6040_HPLLENA;
566 break;
567 case 19200000:
568 /* mclk input, pll disabled */
569 hppllctl |= TWL6040_MCLK_19200KHZ |
570 TWL6040_HPLLSQRENA |
571 TWL6040_HPLLBP;
572 break;
573 case 26000000:
574 /* mclk input, pll enabled */
575 hppllctl |= TWL6040_MCLK_26000KHZ |
576 TWL6040_HPLLSQRBP |
577 TWL6040_HPLLENA;
578 break;
579 case 38400000:
580 /* clk slicer, pll disabled */
581 hppllctl |= TWL6040_MCLK_38400KHZ |
582 TWL6040_HPLLSQRENA |
583 TWL6040_HPLLBP;
584 break;
585 default:
586 dev_err(twl6040->dev,
587 "freq_in %d not supported\n", freq_in);
588 ret = -EINVAL;
589 goto pll_out;
592 twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
593 udelay(500);
594 lppllctl |= TWL6040_HPLLSEL;
595 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
596 lppllctl &= ~TWL6040_LPLLENA;
597 twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
599 twl6040->pll = TWL6040_HPPLL_ID;
600 break;
601 default:
602 dev_err(twl6040->dev, "unknown pll id %d\n", id);
603 ret = -EINVAL;
604 goto pll_out;
607 twl6040->sysclk = freq_out;
609 pll_out:
610 mutex_unlock(&twl6040->mutex);
611 return ret;
613 EXPORT_SYMBOL(twl6040_set_pll);
615 enum twl6040_pll_id twl6040_get_pll(struct twl6040 *twl6040)
617 return twl6040->pll;
619 EXPORT_SYMBOL(twl6040_get_pll);
621 unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
623 return twl6040->sysclk;
625 EXPORT_SYMBOL(twl6040_get_sysclk);
627 int twl6040_get_icrev(struct twl6040 *twl6040)
629 return twl6040->icrev;
631 EXPORT_SYMBOL(twl6040_get_icrev);
633 static int __devinit twl6040_probe(struct platform_device *pdev)
635 struct twl4030_codec_data *pdata = pdev->dev.platform_data;
636 struct twl6040 *twl6040;
637 struct mfd_cell *cell = NULL;
638 unsigned int naudint;
639 int audpwron;
640 int ret, children = 0;
641 u8 accctl;
643 if(!pdata) {
644 dev_err(&pdev->dev, "Platform data is missing\n");
645 return -EINVAL;
648 twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
649 if (!twl6040)
650 return -ENOMEM;
652 platform_set_drvdata(pdev, twl6040);
654 twl6040->dev = &pdev->dev;
655 mutex_init(&twl6040->mutex);
656 mutex_init(&twl6040->io_mutex);
658 twl6040->icrev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
659 if (twl6040->icrev < 0) {
660 ret = twl6040->icrev;
661 goto gpio1_err;
664 if (pdata && (twl6040_get_icrev(twl6040) > TWL6040_REV_1_0))
665 audpwron = pdata->audpwron_gpio;
666 else
667 audpwron = -EINVAL;
669 if (pdata)
670 naudint = pdata->naudint_irq;
671 else
672 naudint = 0;
674 twl6040->audpwron = audpwron;
675 twl6040->powered = 0;
676 twl6040->irq = naudint;
677 twl6040->irq_base = pdata->irq_base;
678 init_completion(&twl6040->ready);
680 if (gpio_is_valid(audpwron)) {
681 ret = gpio_request(audpwron, "audpwron");
682 if (ret)
683 goto gpio1_err;
685 ret = gpio_direction_output(audpwron, 0);
686 if (ret)
687 goto gpio2_err;
690 if (naudint) {
691 /* codec interrupt */
692 ret = twl6040_irq_init(twl6040);
693 if (ret)
694 goto gpio2_err;
696 ret = twl6040_request_irq(twl6040, TWL6040_IRQ_READY,
697 twl6040_naudint_handler, "twl6040_irq_ready",
698 twl6040);
699 if (ret) {
700 dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
701 ret);
702 goto irq_err;
706 /* dual-access registers controlled by I2C only */
707 accctl = twl6040_reg_read(twl6040, TWL6040_REG_ACCCTL);
708 twl6040_reg_write(twl6040, TWL6040_REG_ACCCTL, accctl | TWL6040_I2CSEL);
710 if (pdata->get_ext_clk32k) {
711 ret = pdata->get_ext_clk32k();
712 if (ret) {
713 dev_err(twl6040->dev,
714 "failed to get external 32kHz clock %d\n",
715 ret);
716 goto clk32k_err;
720 if (pdata->audio) {
721 cell = &twl6040->cells[children];
722 cell->name = "twl6040-codec";
723 cell->platform_data = pdata->audio;
724 cell->pdata_size = sizeof(*pdata->audio);
725 children++;
728 if (pdata->vibra) {
729 cell = &twl6040->cells[children];
730 cell->name = "twl6040-vibra";
731 cell->platform_data = pdata->vibra;
732 cell->pdata_size = sizeof(*pdata->vibra);
733 children++;
736 if (children) {
737 ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
738 children, NULL, 0);
739 if (ret)
740 goto mfd_err;
741 } else {
742 dev_err(&pdev->dev, "No platform data found for children\n");
743 ret = -ENODEV;
744 goto mfd_err;
747 return 0;
749 mfd_err:
750 if (pdata->put_ext_clk32k)
751 pdata->put_ext_clk32k();
752 clk32k_err:
753 if (naudint)
754 twl6040_free_irq(twl6040, TWL6040_IRQ_READY, twl6040);
755 irq_err:
756 if (naudint)
757 twl6040_irq_exit(twl6040);
758 gpio2_err:
759 if (gpio_is_valid(audpwron))
760 gpio_free(audpwron);
761 gpio1_err:
762 platform_set_drvdata(pdev, NULL);
763 kfree(twl6040);
764 return ret;
767 static int __devexit twl6040_remove(struct platform_device *pdev)
769 struct twl6040 *twl6040 = platform_get_drvdata(pdev);
770 struct twl4030_codec_data *pdata = dev_get_platdata(twl6040->dev);
771 int audpwron = twl6040->audpwron;
772 int naudint = twl6040->irq;
774 twl6040_disable(twl6040);
776 twl6040_free_irq(twl6040, TWL6040_IRQ_READY, twl6040);
778 if (gpio_is_valid(audpwron))
779 gpio_free(audpwron);
781 if (naudint)
782 twl6040_irq_exit(twl6040);
784 mfd_remove_devices(&pdev->dev);
786 if (pdata->put_ext_clk32k)
787 pdata->put_ext_clk32k();
789 platform_set_drvdata(pdev, NULL);
790 kfree(twl6040);
792 return 0;
795 static struct platform_driver twl6040_driver = {
796 .probe = twl6040_probe,
797 .remove = __devexit_p(twl6040_remove),
798 .driver = {
799 .owner = THIS_MODULE,
800 .name = "twl6040-audio",
804 static int __devinit twl6040_init(void)
806 return platform_driver_register(&twl6040_driver);
808 module_init(twl6040_init);
810 static void __devexit twl6040_exit(void)
812 platform_driver_unregister(&twl6040_driver);
815 module_exit(twl6040_exit);
817 MODULE_DESCRIPTION("TWL6040 MFD");
818 MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
819 MODULE_LICENSE("GPL");
820 MODULE_ALIAS("platform:twl6040-audio");