Root/drivers/mfd/arizona-core.c

1/*
2 * Arizona core driver
3 *
4 * Copyright 2012 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
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/gpio.h>
16#include <linux/interrupt.h>
17#include <linux/mfd/core.h>
18#include <linux/module.h>
19#include <linux/pm_runtime.h>
20#include <linux/regmap.h>
21#include <linux/regulator/consumer.h>
22#include <linux/slab.h>
23
24#include <linux/mfd/arizona/core.h>
25#include <linux/mfd/arizona/registers.h>
26
27#include "arizona.h"
28
29static const char *wm5102_core_supplies[] = {
30    "AVDD",
31    "DBVDD1",
32};
33
34int arizona_clk32k_enable(struct arizona *arizona)
35{
36    int ret = 0;
37
38    mutex_lock(&arizona->clk_lock);
39
40    arizona->clk32k_ref++;
41
42    if (arizona->clk32k_ref == 1)
43        ret = regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
44                     ARIZONA_CLK_32K_ENA,
45                     ARIZONA_CLK_32K_ENA);
46
47    if (ret != 0)
48        arizona->clk32k_ref--;
49
50    mutex_unlock(&arizona->clk_lock);
51
52    return ret;
53}
54EXPORT_SYMBOL_GPL(arizona_clk32k_enable);
55
56int arizona_clk32k_disable(struct arizona *arizona)
57{
58    int ret = 0;
59
60    mutex_lock(&arizona->clk_lock);
61
62    BUG_ON(arizona->clk32k_ref <= 0);
63
64    arizona->clk32k_ref--;
65
66    if (arizona->clk32k_ref == 0)
67        regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
68                   ARIZONA_CLK_32K_ENA, 0);
69
70    mutex_unlock(&arizona->clk_lock);
71
72    return ret;
73}
74EXPORT_SYMBOL_GPL(arizona_clk32k_disable);
75
76static irqreturn_t arizona_clkgen_err(int irq, void *data)
77{
78    struct arizona *arizona = data;
79
80    dev_err(arizona->dev, "CLKGEN error\n");
81
82    return IRQ_HANDLED;
83}
84
85static irqreturn_t arizona_underclocked(int irq, void *data)
86{
87    struct arizona *arizona = data;
88    unsigned int val;
89    int ret;
90
91    ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_8,
92              &val);
93    if (ret != 0) {
94        dev_err(arizona->dev, "Failed to read underclock status: %d\n",
95            ret);
96        return IRQ_NONE;
97    }
98
99    if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
100        dev_err(arizona->dev, "AIF3 underclocked\n");
101    if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
102        dev_err(arizona->dev, "AIF3 underclocked\n");
103    if (val & ARIZONA_AIF2_UNDERCLOCKED_STS)
104        dev_err(arizona->dev, "AIF1 underclocked\n");
105    if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
106        dev_err(arizona->dev, "ISRC2 underclocked\n");
107    if (val & ARIZONA_ISRC1_UNDERCLOCKED_STS)
108        dev_err(arizona->dev, "ISRC1 underclocked\n");
109    if (val & ARIZONA_FX_UNDERCLOCKED_STS)
110        dev_err(arizona->dev, "FX underclocked\n");
111    if (val & ARIZONA_ASRC_UNDERCLOCKED_STS)
112        dev_err(arizona->dev, "ASRC underclocked\n");
113    if (val & ARIZONA_DAC_UNDERCLOCKED_STS)
114        dev_err(arizona->dev, "DAC underclocked\n");
115    if (val & ARIZONA_ADC_UNDERCLOCKED_STS)
116        dev_err(arizona->dev, "ADC underclocked\n");
117    if (val & ARIZONA_MIXER_UNDERCLOCKED_STS)
118        dev_err(arizona->dev, "Mixer underclocked\n");
119
120    return IRQ_HANDLED;
121}
122
123static irqreturn_t arizona_overclocked(int irq, void *data)
124{
125    struct arizona *arizona = data;
126    unsigned int val[2];
127    int ret;
128    
129    ret = regmap_bulk_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_6,
130                   &val[0], 2);
131    if (ret != 0) {
132        dev_err(arizona->dev, "Failed to read overclock status: %d\n",
133            ret);
134        return IRQ_NONE;
135    }
136
137    if (val[0] & ARIZONA_PWM_OVERCLOCKED_STS)
138        dev_err(arizona->dev, "PWM overclocked\n");
139    if (val[0] & ARIZONA_FX_CORE_OVERCLOCKED_STS)
140        dev_err(arizona->dev, "FX core overclocked\n");
141    if (val[0] & ARIZONA_DAC_SYS_OVERCLOCKED_STS)
142        dev_err(arizona->dev, "DAC SYS overclocked\n");
143    if (val[0] & ARIZONA_DAC_WARP_OVERCLOCKED_STS)
144        dev_err(arizona->dev, "DAC WARP overclocked\n");
145    if (val[0] & ARIZONA_ADC_OVERCLOCKED_STS)
146        dev_err(arizona->dev, "ADC overclocked\n");
147    if (val[0] & ARIZONA_MIXER_OVERCLOCKED_STS)
148        dev_err(arizona->dev, "Mixer overclocked\n");
149    if (val[0] & ARIZONA_AIF3_SYNC_OVERCLOCKED_STS)
150        dev_err(arizona->dev, "AIF3 overclocked\n");
151    if (val[0] & ARIZONA_AIF2_SYNC_OVERCLOCKED_STS)
152        dev_err(arizona->dev, "AIF2 overclocked\n");
153    if (val[0] & ARIZONA_AIF1_SYNC_OVERCLOCKED_STS)
154        dev_err(arizona->dev, "AIF1 overclocked\n");
155    if (val[0] & ARIZONA_PAD_CTRL_OVERCLOCKED_STS)
156        dev_err(arizona->dev, "Pad control overclocked\n");
157
158    if (val[1] & ARIZONA_SLIMBUS_SUBSYS_OVERCLOCKED_STS)
159        dev_err(arizona->dev, "Slimbus subsystem overclocked\n");
160    if (val[1] & ARIZONA_SLIMBUS_ASYNC_OVERCLOCKED_STS)
161        dev_err(arizona->dev, "Slimbus async overclocked\n");
162    if (val[1] & ARIZONA_SLIMBUS_SYNC_OVERCLOCKED_STS)
163        dev_err(arizona->dev, "Slimbus sync overclocked\n");
164    if (val[1] & ARIZONA_ASRC_ASYNC_SYS_OVERCLOCKED_STS)
165        dev_err(arizona->dev, "ASRC async system overclocked\n");
166    if (val[1] & ARIZONA_ASRC_ASYNC_WARP_OVERCLOCKED_STS)
167        dev_err(arizona->dev, "ASRC async WARP overclocked\n");
168    if (val[1] & ARIZONA_ASRC_SYNC_SYS_OVERCLOCKED_STS)
169        dev_err(arizona->dev, "ASRC sync system overclocked\n");
170    if (val[1] & ARIZONA_ASRC_SYNC_WARP_OVERCLOCKED_STS)
171        dev_err(arizona->dev, "ASRC sync WARP overclocked\n");
172    if (val[1] & ARIZONA_ADSP2_1_OVERCLOCKED_STS)
173        dev_err(arizona->dev, "DSP1 overclocked\n");
174    if (val[1] & ARIZONA_ISRC2_OVERCLOCKED_STS)
175        dev_err(arizona->dev, "ISRC2 overclocked\n");
176    if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS)
177        dev_err(arizona->dev, "ISRC1 overclocked\n");
178
179    return IRQ_HANDLED;
180}
181
182static int arizona_wait_for_boot(struct arizona *arizona)
183{
184    unsigned int reg;
185    int ret, i;
186
187    /*
188     * We can't use an interrupt as we need to runtime resume to do so,
189     * we won't race with the interrupt handler as it'll be blocked on
190     * runtime resume.
191     */
192    for (i = 0; i < 5; i++) {
193        msleep(1);
194
195        ret = regmap_read(arizona->regmap,
196                  ARIZONA_INTERRUPT_RAW_STATUS_5, &reg);
197        if (ret != 0) {
198            dev_err(arizona->dev, "Failed to read boot state: %d\n",
199                ret);
200            continue;
201        }
202
203        if (reg & ARIZONA_BOOT_DONE_STS)
204            break;
205    }
206
207    if (reg & ARIZONA_BOOT_DONE_STS) {
208        regmap_write(arizona->regmap, ARIZONA_INTERRUPT_STATUS_5,
209                 ARIZONA_BOOT_DONE_STS);
210    } else {
211        dev_err(arizona->dev, "Device boot timed out: %x\n", reg);
212        return -ETIMEDOUT;
213    }
214
215    pm_runtime_mark_last_busy(arizona->dev);
216
217    return 0;
218}
219
220#ifdef CONFIG_PM_RUNTIME
221static int arizona_runtime_resume(struct device *dev)
222{
223    struct arizona *arizona = dev_get_drvdata(dev);
224    int ret;
225
226    dev_dbg(arizona->dev, "Leaving AoD mode\n");
227
228    ret = regulator_enable(arizona->dcvdd);
229    if (ret != 0) {
230        dev_err(arizona->dev, "Failed to enable DCVDD: %d\n", ret);
231        return ret;
232    }
233
234    regcache_cache_only(arizona->regmap, false);
235
236    ret = arizona_wait_for_boot(arizona);
237    if (ret != 0) {
238        regulator_disable(arizona->dcvdd);
239        return ret;
240    }
241
242    regcache_sync(arizona->regmap);
243
244    return 0;
245}
246
247static int arizona_runtime_suspend(struct device *dev)
248{
249    struct arizona *arizona = dev_get_drvdata(dev);
250
251    dev_dbg(arizona->dev, "Entering AoD mode\n");
252
253    regulator_disable(arizona->dcvdd);
254    regcache_cache_only(arizona->regmap, true);
255    regcache_mark_dirty(arizona->regmap);
256
257    return 0;
258}
259#endif
260
261const struct dev_pm_ops arizona_pm_ops = {
262    SET_RUNTIME_PM_OPS(arizona_runtime_suspend,
263               arizona_runtime_resume,
264               NULL)
265};
266EXPORT_SYMBOL_GPL(arizona_pm_ops);
267
268static struct mfd_cell early_devs[] = {
269    { .name = "arizona-ldo1" },
270};
271
272static struct mfd_cell wm5102_devs[] = {
273    { .name = "arizona-extcon" },
274    { .name = "arizona-gpio" },
275    { .name = "arizona-micsupp" },
276    { .name = "arizona-pwm" },
277    { .name = "wm5102-codec" },
278};
279
280static struct mfd_cell wm5110_devs[] = {
281    { .name = "arizona-extcon" },
282    { .name = "arizona-gpio" },
283    { .name = "arizona-micsupp" },
284    { .name = "arizona-pwm" },
285    { .name = "wm5110-codec" },
286};
287
288int __devinit arizona_dev_init(struct arizona *arizona)
289{
290    struct device *dev = arizona->dev;
291    const char *type_name;
292    unsigned int reg, val;
293    int ret, i;
294
295    dev_set_drvdata(arizona->dev, arizona);
296    mutex_init(&arizona->clk_lock);
297
298    if (dev_get_platdata(arizona->dev))
299        memcpy(&arizona->pdata, dev_get_platdata(arizona->dev),
300               sizeof(arizona->pdata));
301
302    regcache_cache_only(arizona->regmap, true);
303
304    switch (arizona->type) {
305    case WM5102:
306    case WM5110:
307        for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
308            arizona->core_supplies[i].supply
309                = wm5102_core_supplies[i];
310        arizona->num_core_supplies = ARRAY_SIZE(wm5102_core_supplies);
311        break;
312    default:
313        dev_err(arizona->dev, "Unknown device type %d\n",
314            arizona->type);
315        return -EINVAL;
316    }
317
318    ret = mfd_add_devices(arizona->dev, -1, early_devs,
319                  ARRAY_SIZE(early_devs), NULL, 0, NULL);
320    if (ret != 0) {
321        dev_err(dev, "Failed to add early children: %d\n", ret);
322        return ret;
323    }
324
325    ret = devm_regulator_bulk_get(dev, arizona->num_core_supplies,
326                      arizona->core_supplies);
327    if (ret != 0) {
328        dev_err(dev, "Failed to request core supplies: %d\n",
329            ret);
330        goto err_early;
331    }
332
333    arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD");
334    if (IS_ERR(arizona->dcvdd)) {
335        ret = PTR_ERR(arizona->dcvdd);
336        dev_err(dev, "Failed to request DCVDD: %d\n", ret);
337        goto err_early;
338    }
339
340    ret = regulator_bulk_enable(arizona->num_core_supplies,
341                    arizona->core_supplies);
342    if (ret != 0) {
343        dev_err(dev, "Failed to enable core supplies: %d\n",
344            ret);
345        goto err_early;
346    }
347
348    ret = regulator_enable(arizona->dcvdd);
349    if (ret != 0) {
350        dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
351        goto err_enable;
352    }
353
354    if (arizona->pdata.reset) {
355        /* Start out with /RESET low to put the chip into reset */
356        ret = gpio_request_one(arizona->pdata.reset,
357                       GPIOF_DIR_OUT | GPIOF_INIT_LOW,
358                       "arizona /RESET");
359        if (ret != 0) {
360            dev_err(dev, "Failed to request /RESET: %d\n", ret);
361            goto err_dcvdd;
362        }
363
364        gpio_set_value_cansleep(arizona->pdata.reset, 1);
365    }
366
367    regcache_cache_only(arizona->regmap, false);
368
369    ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, &reg);
370    if (ret != 0) {
371        dev_err(dev, "Failed to read ID register: %d\n", ret);
372        goto err_reset;
373    }
374
375    ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION,
376              &arizona->rev);
377    if (ret != 0) {
378        dev_err(dev, "Failed to read revision register: %d\n", ret);
379        goto err_reset;
380    }
381    arizona->rev &= ARIZONA_DEVICE_REVISION_MASK;
382
383    switch (reg) {
384#ifdef CONFIG_MFD_WM5102
385    case 0x5102:
386        type_name = "WM5102";
387        if (arizona->type != WM5102) {
388            dev_err(arizona->dev, "WM5102 registered as %d\n",
389                arizona->type);
390            arizona->type = WM5102;
391        }
392        ret = wm5102_patch(arizona);
393        break;
394#endif
395#ifdef CONFIG_MFD_WM5110
396    case 0x5110:
397        type_name = "WM5110";
398        if (arizona->type != WM5110) {
399            dev_err(arizona->dev, "WM5110 registered as %d\n",
400                arizona->type);
401            arizona->type = WM5110;
402        }
403        ret = wm5110_patch(arizona);
404        break;
405#endif
406    default:
407        dev_err(arizona->dev, "Unknown device ID %x\n", reg);
408        goto err_reset;
409    }
410
411    dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A');
412
413    if (ret != 0)
414        dev_err(arizona->dev, "Failed to apply patch: %d\n", ret);
415
416    /* If we have a /RESET GPIO we'll already be reset */
417    if (!arizona->pdata.reset) {
418        ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0);
419        if (ret != 0) {
420            dev_err(dev, "Failed to reset device: %d\n", ret);
421            goto err_reset;
422        }
423    }
424
425    ret = arizona_wait_for_boot(arizona);
426    if (ret != 0) {
427        dev_err(arizona->dev, "Device failed initial boot: %d\n", ret);
428        goto err_reset;
429    }
430
431    for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
432        if (!arizona->pdata.gpio_defaults[i])
433            continue;
434
435        regmap_write(arizona->regmap, ARIZONA_GPIO1_CTRL + i,
436                 arizona->pdata.gpio_defaults[i]);
437    }
438
439    pm_runtime_set_autosuspend_delay(arizona->dev, 100);
440    pm_runtime_use_autosuspend(arizona->dev);
441    pm_runtime_enable(arizona->dev);
442
443    /* Chip default */
444    if (!arizona->pdata.clk32k_src)
445        arizona->pdata.clk32k_src = ARIZONA_32KZ_MCLK2;
446
447    switch (arizona->pdata.clk32k_src) {
448    case ARIZONA_32KZ_MCLK1:
449    case ARIZONA_32KZ_MCLK2:
450        regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
451                   ARIZONA_CLK_32K_SRC_MASK,
452                   arizona->pdata.clk32k_src - 1);
453        break;
454    case ARIZONA_32KZ_NONE:
455        regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
456                   ARIZONA_CLK_32K_SRC_MASK, 2);
457        break;
458    default:
459        dev_err(arizona->dev, "Invalid 32kHz clock source: %d\n",
460            arizona->pdata.clk32k_src);
461        ret = -EINVAL;
462        goto err_reset;
463    }
464
465    for (i = 0; i < ARIZONA_MAX_INPUT; i++) {
466        /* Default for both is 0 so noop with defaults */
467        val = arizona->pdata.dmic_ref[i]
468            << ARIZONA_IN1_DMIC_SUP_SHIFT;
469        val |= arizona->pdata.inmode[i] << ARIZONA_IN1_MODE_SHIFT;
470
471        regmap_update_bits(arizona->regmap,
472                   ARIZONA_IN1L_CONTROL + (i * 8),
473                   ARIZONA_IN1_DMIC_SUP_MASK |
474                   ARIZONA_IN1_MODE_MASK, val);
475    }
476
477    for (i = 0; i < ARIZONA_MAX_OUTPUT; i++) {
478        /* Default is 0 so noop with defaults */
479        if (arizona->pdata.out_mono[i])
480            val = ARIZONA_OUT1_MONO;
481        else
482            val = 0;
483
484        regmap_update_bits(arizona->regmap,
485                   ARIZONA_OUTPUT_PATH_CONFIG_1L + (i * 8),
486                   ARIZONA_OUT1_MONO, val);
487    }
488
489    for (i = 0; i < ARIZONA_MAX_PDM_SPK; i++) {
490        if (arizona->pdata.spk_mute[i])
491            regmap_update_bits(arizona->regmap,
492                       ARIZONA_PDM_SPK1_CTRL_1 + (i * 2),
493                       ARIZONA_SPK1_MUTE_ENDIAN_MASK |
494                       ARIZONA_SPK1_MUTE_SEQ1_MASK,
495                       arizona->pdata.spk_mute[i]);
496
497        if (arizona->pdata.spk_fmt[i])
498            regmap_update_bits(arizona->regmap,
499                       ARIZONA_PDM_SPK1_CTRL_2 + (i * 2),
500                       ARIZONA_SPK1_FMT_MASK,
501                       arizona->pdata.spk_fmt[i]);
502    }
503
504    /* Set up for interrupts */
505    ret = arizona_irq_init(arizona);
506    if (ret != 0)
507        goto err_reset;
508
509    arizona_request_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, "CLKGEN error",
510                arizona_clkgen_err, arizona);
511    arizona_request_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, "Overclocked",
512                arizona_overclocked, arizona);
513    arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked",
514                arizona_underclocked, arizona);
515
516    switch (arizona->type) {
517    case WM5102:
518        ret = mfd_add_devices(arizona->dev, -1, wm5102_devs,
519                      ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
520        break;
521    case WM5110:
522        ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
523                      ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
524        break;
525    }
526
527    if (ret != 0) {
528        dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret);
529        goto err_irq;
530    }
531
532#ifdef CONFIG_PM_RUNTIME
533    regulator_disable(arizona->dcvdd);
534#endif
535
536    return 0;
537
538err_irq:
539    arizona_irq_exit(arizona);
540err_reset:
541    if (arizona->pdata.reset) {
542        gpio_set_value_cansleep(arizona->pdata.reset, 1);
543        gpio_free(arizona->pdata.reset);
544    }
545err_dcvdd:
546    regulator_disable(arizona->dcvdd);
547err_enable:
548    regulator_bulk_disable(arizona->num_core_supplies,
549                   arizona->core_supplies);
550err_early:
551    mfd_remove_devices(dev);
552    return ret;
553}
554EXPORT_SYMBOL_GPL(arizona_dev_init);
555
556int __devexit arizona_dev_exit(struct arizona *arizona)
557{
558    mfd_remove_devices(arizona->dev);
559    arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
560    arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
561    arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
562    pm_runtime_disable(arizona->dev);
563    arizona_irq_exit(arizona);
564    return 0;
565}
566EXPORT_SYMBOL_GPL(arizona_dev_exit);
567

Archive Download this file



interactive