linux/drivers/mfd/arizona-core.c
<<
>>
Prefs
   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_AIF2_UNDERCLOCKED_STS)
 102                dev_err(arizona->dev, "AIF2 underclocked\n");
 103        if (val & ARIZONA_AIF1_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 dropped sample\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        ret = regcache_sync(arizona->regmap);
 243        if (ret != 0) {
 244                dev_err(arizona->dev, "Failed to restore register cache\n");
 245                regulator_disable(arizona->dcvdd);
 246                return ret;
 247        }
 248
 249        return 0;
 250}
 251
 252static int arizona_runtime_suspend(struct device *dev)
 253{
 254        struct arizona *arizona = dev_get_drvdata(dev);
 255
 256        dev_dbg(arizona->dev, "Entering AoD mode\n");
 257
 258        regulator_disable(arizona->dcvdd);
 259        regcache_cache_only(arizona->regmap, true);
 260        regcache_mark_dirty(arizona->regmap);
 261
 262        return 0;
 263}
 264#endif
 265
 266#ifdef CONFIG_PM_SLEEP
 267static int arizona_resume_noirq(struct device *dev)
 268{
 269        struct arizona *arizona = dev_get_drvdata(dev);
 270
 271        dev_dbg(arizona->dev, "Early resume, disabling IRQ\n");
 272        disable_irq(arizona->irq);
 273
 274        return 0;
 275}
 276
 277static int arizona_resume(struct device *dev)
 278{
 279        struct arizona *arizona = dev_get_drvdata(dev);
 280
 281        dev_dbg(arizona->dev, "Late resume, reenabling IRQ\n");
 282        enable_irq(arizona->irq);
 283
 284        return 0;
 285}
 286#endif
 287
 288const struct dev_pm_ops arizona_pm_ops = {
 289        SET_RUNTIME_PM_OPS(arizona_runtime_suspend,
 290                           arizona_runtime_resume,
 291                           NULL)
 292        SET_SYSTEM_SLEEP_PM_OPS(NULL, arizona_resume)
 293#ifdef CONFIG_PM_SLEEP
 294        .resume_noirq = arizona_resume_noirq,
 295#endif
 296};
 297EXPORT_SYMBOL_GPL(arizona_pm_ops);
 298
 299static struct mfd_cell early_devs[] = {
 300        { .name = "arizona-ldo1" },
 301};
 302
 303static struct mfd_cell wm5102_devs[] = {
 304        { .name = "arizona-micsupp" },
 305        { .name = "arizona-extcon" },
 306        { .name = "arizona-gpio" },
 307        { .name = "arizona-haptics" },
 308        { .name = "arizona-pwm" },
 309        { .name = "wm5102-codec" },
 310};
 311
 312static struct mfd_cell wm5110_devs[] = {
 313        { .name = "arizona-micsupp" },
 314        { .name = "arizona-extcon" },
 315        { .name = "arizona-gpio" },
 316        { .name = "arizona-haptics" },
 317        { .name = "arizona-pwm" },
 318        { .name = "wm5110-codec" },
 319};
 320
 321int arizona_dev_init(struct arizona *arizona)
 322{
 323        struct device *dev = arizona->dev;
 324        const char *type_name;
 325        unsigned int reg, val;
 326        int (*apply_patch)(struct arizona *) = NULL;
 327        int ret, i;
 328
 329        dev_set_drvdata(arizona->dev, arizona);
 330        mutex_init(&arizona->clk_lock);
 331
 332        if (dev_get_platdata(arizona->dev))
 333                memcpy(&arizona->pdata, dev_get_platdata(arizona->dev),
 334                       sizeof(arizona->pdata));
 335
 336        regcache_cache_only(arizona->regmap, true);
 337
 338        switch (arizona->type) {
 339        case WM5102:
 340        case WM5110:
 341                for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
 342                        arizona->core_supplies[i].supply
 343                                = wm5102_core_supplies[i];
 344                arizona->num_core_supplies = ARRAY_SIZE(wm5102_core_supplies);
 345                break;
 346        default:
 347                dev_err(arizona->dev, "Unknown device type %d\n",
 348                        arizona->type);
 349                return -EINVAL;
 350        }
 351
 352        ret = mfd_add_devices(arizona->dev, -1, early_devs,
 353                              ARRAY_SIZE(early_devs), NULL, 0, NULL);
 354        if (ret != 0) {
 355                dev_err(dev, "Failed to add early children: %d\n", ret);
 356                return ret;
 357        }
 358
 359        ret = devm_regulator_bulk_get(dev, arizona->num_core_supplies,
 360                                      arizona->core_supplies);
 361        if (ret != 0) {
 362                dev_err(dev, "Failed to request core supplies: %d\n",
 363                        ret);
 364                goto err_early;
 365        }
 366
 367        arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD");
 368        if (IS_ERR(arizona->dcvdd)) {
 369                ret = PTR_ERR(arizona->dcvdd);
 370                dev_err(dev, "Failed to request DCVDD: %d\n", ret);
 371                goto err_early;
 372        }
 373
 374        ret = regulator_bulk_enable(arizona->num_core_supplies,
 375                                    arizona->core_supplies);
 376        if (ret != 0) {
 377                dev_err(dev, "Failed to enable core supplies: %d\n",
 378                        ret);
 379                goto err_early;
 380        }
 381
 382        ret = regulator_enable(arizona->dcvdd);
 383        if (ret != 0) {
 384                dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
 385                goto err_enable;
 386        }
 387
 388        if (arizona->pdata.reset) {
 389                /* Start out with /RESET low to put the chip into reset */
 390                ret = gpio_request_one(arizona->pdata.reset,
 391                                       GPIOF_DIR_OUT | GPIOF_INIT_LOW,
 392                                       "arizona /RESET");
 393                if (ret != 0) {
 394                        dev_err(dev, "Failed to request /RESET: %d\n", ret);
 395                        goto err_dcvdd;
 396                }
 397
 398                gpio_set_value_cansleep(arizona->pdata.reset, 1);
 399        }
 400
 401        regcache_cache_only(arizona->regmap, false);
 402
 403        ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, &reg);
 404        if (ret != 0) {
 405                dev_err(dev, "Failed to read ID register: %d\n", ret);
 406                goto err_reset;
 407        }
 408
 409        ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION,
 410                          &arizona->rev);
 411        if (ret != 0) {
 412                dev_err(dev, "Failed to read revision register: %d\n", ret);
 413                goto err_reset;
 414        }
 415        arizona->rev &= ARIZONA_DEVICE_REVISION_MASK;
 416
 417        switch (reg) {
 418#ifdef CONFIG_MFD_WM5102
 419        case 0x5102:
 420                type_name = "WM5102";
 421                if (arizona->type != WM5102) {
 422                        dev_err(arizona->dev, "WM5102 registered as %d\n",
 423                                arizona->type);
 424                        arizona->type = WM5102;
 425                }
 426                apply_patch = wm5102_patch;
 427                break;
 428#endif
 429#ifdef CONFIG_MFD_WM5110
 430        case 0x5110:
 431                type_name = "WM5110";
 432                if (arizona->type != WM5110) {
 433                        dev_err(arizona->dev, "WM5110 registered as %d\n",
 434                                arizona->type);
 435                        arizona->type = WM5110;
 436                }
 437                apply_patch = wm5110_patch;
 438                break;
 439#endif
 440        default:
 441                dev_err(arizona->dev, "Unknown device ID %x\n", reg);
 442                goto err_reset;
 443        }
 444
 445        dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A');
 446
 447        /* If we have a /RESET GPIO we'll already be reset */
 448        if (!arizona->pdata.reset) {
 449                regcache_mark_dirty(arizona->regmap);
 450
 451                ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0);
 452                if (ret != 0) {
 453                        dev_err(dev, "Failed to reset device: %d\n", ret);
 454                        goto err_reset;
 455                }
 456
 457                ret = regcache_sync(arizona->regmap);
 458                if (ret != 0) {
 459                        dev_err(dev, "Failed to sync device: %d\n", ret);
 460                        goto err_reset;
 461                }
 462        }
 463
 464        ret = arizona_wait_for_boot(arizona);
 465        if (ret != 0) {
 466                dev_err(arizona->dev, "Device failed initial boot: %d\n", ret);
 467                goto err_reset;
 468        }
 469
 470        if (apply_patch) {
 471                ret = apply_patch(arizona);
 472                if (ret != 0) {
 473                        dev_err(arizona->dev, "Failed to apply patch: %d\n",
 474                                ret);
 475                        goto err_reset;
 476                }
 477        }
 478
 479        for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
 480                if (!arizona->pdata.gpio_defaults[i])
 481                        continue;
 482
 483                regmap_write(arizona->regmap, ARIZONA_GPIO1_CTRL + i,
 484                             arizona->pdata.gpio_defaults[i]);
 485        }
 486
 487        pm_runtime_set_autosuspend_delay(arizona->dev, 100);
 488        pm_runtime_use_autosuspend(arizona->dev);
 489        pm_runtime_enable(arizona->dev);
 490
 491        /* Chip default */
 492        if (!arizona->pdata.clk32k_src)
 493                arizona->pdata.clk32k_src = ARIZONA_32KZ_MCLK2;
 494
 495        switch (arizona->pdata.clk32k_src) {
 496        case ARIZONA_32KZ_MCLK1:
 497        case ARIZONA_32KZ_MCLK2:
 498                regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
 499                                   ARIZONA_CLK_32K_SRC_MASK,
 500                                   arizona->pdata.clk32k_src - 1);
 501                break;
 502        case ARIZONA_32KZ_NONE:
 503                regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
 504                                   ARIZONA_CLK_32K_SRC_MASK, 2);
 505                break;
 506        default:
 507                dev_err(arizona->dev, "Invalid 32kHz clock source: %d\n",
 508                        arizona->pdata.clk32k_src);
 509                ret = -EINVAL;
 510                goto err_reset;
 511        }
 512
 513        for (i = 0; i < ARIZONA_MAX_MICBIAS; i++) {
 514                if (!arizona->pdata.micbias[i].mV)
 515                        continue;
 516
 517                val = (arizona->pdata.micbias[i].mV - 1500) / 100;
 518                val <<= ARIZONA_MICB1_LVL_SHIFT;
 519
 520                if (arizona->pdata.micbias[i].ext_cap)
 521                        val |= ARIZONA_MICB1_EXT_CAP;
 522
 523                if (arizona->pdata.micbias[i].discharge)
 524                        val |= ARIZONA_MICB1_DISCH;
 525
 526                if (arizona->pdata.micbias[i].fast_start)
 527                        val |= ARIZONA_MICB1_RATE;
 528
 529                regmap_update_bits(arizona->regmap,
 530                                   ARIZONA_MIC_BIAS_CTRL_1 + i,
 531                                   ARIZONA_MICB1_LVL_MASK |
 532                                   ARIZONA_MICB1_DISCH |
 533                                   ARIZONA_MICB1_RATE, val);
 534        }
 535
 536        for (i = 0; i < ARIZONA_MAX_INPUT; i++) {
 537                /* Default for both is 0 so noop with defaults */
 538                val = arizona->pdata.dmic_ref[i]
 539                        << ARIZONA_IN1_DMIC_SUP_SHIFT;
 540                val |= arizona->pdata.inmode[i] << ARIZONA_IN1_MODE_SHIFT;
 541
 542                regmap_update_bits(arizona->regmap,
 543                                   ARIZONA_IN1L_CONTROL + (i * 8),
 544                                   ARIZONA_IN1_DMIC_SUP_MASK |
 545                                   ARIZONA_IN1_MODE_MASK, val);
 546        }
 547
 548        for (i = 0; i < ARIZONA_MAX_OUTPUT; i++) {
 549                /* Default is 0 so noop with defaults */
 550                if (arizona->pdata.out_mono[i])
 551                        val = ARIZONA_OUT1_MONO;
 552                else
 553                        val = 0;
 554
 555                regmap_update_bits(arizona->regmap,
 556                                   ARIZONA_OUTPUT_PATH_CONFIG_1L + (i * 8),
 557                                   ARIZONA_OUT1_MONO, val);
 558        }
 559
 560        for (i = 0; i < ARIZONA_MAX_PDM_SPK; i++) {
 561                if (arizona->pdata.spk_mute[i])
 562                        regmap_update_bits(arizona->regmap,
 563                                           ARIZONA_PDM_SPK1_CTRL_1 + (i * 2),
 564                                           ARIZONA_SPK1_MUTE_ENDIAN_MASK |
 565                                           ARIZONA_SPK1_MUTE_SEQ1_MASK,
 566                                           arizona->pdata.spk_mute[i]);
 567
 568                if (arizona->pdata.spk_fmt[i])
 569                        regmap_update_bits(arizona->regmap,
 570                                           ARIZONA_PDM_SPK1_CTRL_2 + (i * 2),
 571                                           ARIZONA_SPK1_FMT_MASK,
 572                                           arizona->pdata.spk_fmt[i]);
 573        }
 574
 575        /* Set up for interrupts */
 576        ret = arizona_irq_init(arizona);
 577        if (ret != 0)
 578                goto err_reset;
 579
 580        arizona_request_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, "CLKGEN error",
 581                            arizona_clkgen_err, arizona);
 582        arizona_request_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, "Overclocked",
 583                            arizona_overclocked, arizona);
 584        arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked",
 585                            arizona_underclocked, arizona);
 586
 587        switch (arizona->type) {
 588        case WM5102:
 589                ret = mfd_add_devices(arizona->dev, -1, wm5102_devs,
 590                                      ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
 591                break;
 592        case WM5110:
 593                ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
 594                                      ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
 595                break;
 596        }
 597
 598        if (ret != 0) {
 599                dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret);
 600                goto err_irq;
 601        }
 602
 603#ifdef CONFIG_PM_RUNTIME
 604        regulator_disable(arizona->dcvdd);
 605#endif
 606
 607        return 0;
 608
 609err_irq:
 610        arizona_irq_exit(arizona);
 611err_reset:
 612        if (arizona->pdata.reset) {
 613                gpio_set_value_cansleep(arizona->pdata.reset, 1);
 614                gpio_free(arizona->pdata.reset);
 615        }
 616err_dcvdd:
 617        regulator_disable(arizona->dcvdd);
 618err_enable:
 619        regulator_bulk_disable(arizona->num_core_supplies,
 620                               arizona->core_supplies);
 621err_early:
 622        mfd_remove_devices(dev);
 623        return ret;
 624}
 625EXPORT_SYMBOL_GPL(arizona_dev_init);
 626
 627int arizona_dev_exit(struct arizona *arizona)
 628{
 629        mfd_remove_devices(arizona->dev);
 630        arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
 631        arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
 632        arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
 633        pm_runtime_disable(arizona->dev);
 634        arizona_irq_exit(arizona);
 635        return 0;
 636}
 637EXPORT_SYMBOL_GPL(arizona_dev_exit);
 638
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.