root/drivers/mfd/madera-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. madera_name_from_type
  2. madera_wait_for_boot
  3. madera_soft_reset
  4. madera_enable_hard_reset
  5. madera_disable_hard_reset
  6. madera_runtime_resume
  7. madera_runtime_suspend
  8. madera_get_reset_gpio
  9. madera_set_micbias_info
  10. madera_dev_init
  11. madera_dev_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Core MFD support for Cirrus Logic Madera codecs
   4  *
   5  * Copyright (C) 2015-2018 Cirrus Logic
   6  */
   7 
   8 #include <linux/device.h>
   9 #include <linux/delay.h>
  10 #include <linux/err.h>
  11 #include <linux/gpio.h>
  12 #include <linux/mfd/core.h>
  13 #include <linux/module.h>
  14 #include <linux/mutex.h>
  15 #include <linux/notifier.h>
  16 #include <linux/of.h>
  17 #include <linux/of_gpio.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/pm_runtime.h>
  20 #include <linux/regmap.h>
  21 #include <linux/regulator/consumer.h>
  22 #include <linux/regulator/machine.h>
  23 #include <linux/regulator/of_regulator.h>
  24 
  25 #include <linux/mfd/madera/core.h>
  26 #include <linux/mfd/madera/registers.h>
  27 
  28 #include "madera.h"
  29 
  30 #define CS47L15_SILICON_ID      0x6370
  31 #define CS47L35_SILICON_ID      0x6360
  32 #define CS47L85_SILICON_ID      0x6338
  33 #define CS47L90_SILICON_ID      0x6364
  34 #define CS47L92_SILICON_ID      0x6371
  35 
  36 #define MADERA_32KZ_MCLK2       1
  37 
  38 static const char * const madera_core_supplies[] = {
  39         "AVDD",
  40         "DBVDD1",
  41 };
  42 
  43 static const struct mfd_cell madera_ldo1_devs[] = {
  44         { .name = "madera-ldo1" },
  45 };
  46 
  47 static const char * const cs47l15_supplies[] = {
  48         "MICVDD",
  49         "CPVDD1",
  50         "SPKVDD",
  51 };
  52 
  53 static const struct mfd_cell cs47l15_devs[] = {
  54         { .name = "madera-pinctrl", },
  55         { .name = "madera-irq" },
  56         { .name = "madera-gpio" },
  57         {
  58                 .name = "madera-extcon",
  59                 .parent_supplies = cs47l15_supplies,
  60                 .num_parent_supplies = 1, /* We only need MICVDD */
  61         },
  62         {
  63                 .name = "cs47l15-codec",
  64                 .parent_supplies = cs47l15_supplies,
  65                 .num_parent_supplies = ARRAY_SIZE(cs47l15_supplies),
  66         },
  67 };
  68 
  69 static const char * const cs47l35_supplies[] = {
  70         "MICVDD",
  71         "DBVDD2",
  72         "CPVDD1",
  73         "CPVDD2",
  74         "SPKVDD",
  75 };
  76 
  77 static const struct mfd_cell cs47l35_devs[] = {
  78         { .name = "madera-pinctrl", },
  79         { .name = "madera-irq", },
  80         { .name = "madera-micsupp", },
  81         { .name = "madera-gpio", },
  82         {
  83                 .name = "madera-extcon",
  84                 .parent_supplies = cs47l35_supplies,
  85                 .num_parent_supplies = 1, /* We only need MICVDD */
  86         },
  87         {
  88                 .name = "cs47l35-codec",
  89                 .parent_supplies = cs47l35_supplies,
  90                 .num_parent_supplies = ARRAY_SIZE(cs47l35_supplies),
  91         },
  92 };
  93 
  94 static const char * const cs47l85_supplies[] = {
  95         "MICVDD",
  96         "DBVDD2",
  97         "DBVDD3",
  98         "DBVDD4",
  99         "CPVDD1",
 100         "CPVDD2",
 101         "SPKVDDL",
 102         "SPKVDDR",
 103 };
 104 
 105 static const struct mfd_cell cs47l85_devs[] = {
 106         { .name = "madera-pinctrl", },
 107         { .name = "madera-irq", },
 108         { .name = "madera-micsupp" },
 109         { .name = "madera-gpio", },
 110         {
 111                 .name = "madera-extcon",
 112                 .parent_supplies = cs47l85_supplies,
 113                 .num_parent_supplies = 1, /* We only need MICVDD */
 114         },
 115         {
 116                 .name = "cs47l85-codec",
 117                 .parent_supplies = cs47l85_supplies,
 118                 .num_parent_supplies = ARRAY_SIZE(cs47l85_supplies),
 119         },
 120 };
 121 
 122 static const char * const cs47l90_supplies[] = {
 123         "MICVDD",
 124         "DBVDD2",
 125         "DBVDD3",
 126         "DBVDD4",
 127         "CPVDD1",
 128         "CPVDD2",
 129 };
 130 
 131 static const struct mfd_cell cs47l90_devs[] = {
 132         { .name = "madera-pinctrl", },
 133         { .name = "madera-irq", },
 134         { .name = "madera-micsupp", },
 135         { .name = "madera-gpio", },
 136         {
 137                 .name = "madera-extcon",
 138                 .parent_supplies = cs47l90_supplies,
 139                 .num_parent_supplies = 1, /* We only need MICVDD */
 140         },
 141         {
 142                 .name = "cs47l90-codec",
 143                 .parent_supplies = cs47l90_supplies,
 144                 .num_parent_supplies = ARRAY_SIZE(cs47l90_supplies),
 145         },
 146 };
 147 
 148 static const char * const cs47l92_supplies[] = {
 149         "MICVDD",
 150         "CPVDD1",
 151         "CPVDD2",
 152 };
 153 
 154 static const struct mfd_cell cs47l92_devs[] = {
 155         { .name = "madera-pinctrl" },
 156         { .name = "madera-irq", },
 157         { .name = "madera-micsupp", },
 158         { .name = "madera-gpio" },
 159         {
 160                 .name = "madera-extcon",
 161                 .parent_supplies = cs47l92_supplies,
 162                 .num_parent_supplies = 1, /* We only need MICVDD */
 163         },
 164         {
 165                 .name = "cs47l92-codec",
 166                 .parent_supplies = cs47l92_supplies,
 167                 .num_parent_supplies = ARRAY_SIZE(cs47l92_supplies),
 168         },
 169 };
 170 
 171 /* Used by madera-i2c and madera-spi drivers */
 172 const char *madera_name_from_type(enum madera_type type)
 173 {
 174         switch (type) {
 175         case CS47L15:
 176                 return "CS47L15";
 177         case CS47L35:
 178                 return "CS47L35";
 179         case CS47L85:
 180                 return "CS47L85";
 181         case CS47L90:
 182                 return "CS47L90";
 183         case CS47L91:
 184                 return "CS47L91";
 185         case CS42L92:
 186                 return "CS42L92";
 187         case CS47L92:
 188                 return "CS47L92";
 189         case CS47L93:
 190                 return "CS47L93";
 191         case WM1840:
 192                 return "WM1840";
 193         default:
 194                 return "Unknown";
 195         }
 196 }
 197 EXPORT_SYMBOL_GPL(madera_name_from_type);
 198 
 199 #define MADERA_BOOT_POLL_INTERVAL_USEC          5000
 200 #define MADERA_BOOT_POLL_TIMEOUT_USEC           25000
 201 
 202 static int madera_wait_for_boot(struct madera *madera)
 203 {
 204         ktime_t timeout;
 205         unsigned int val = 0;
 206         int ret = 0;
 207 
 208         /*
 209          * We can't use an interrupt as we need to runtime resume to do so,
 210          * so we poll the status bit. This won't race with the interrupt
 211          * handler because it will be blocked on runtime resume.
 212          * The chip could NAK a read request while it is booting so ignore
 213          * errors from regmap_read.
 214          */
 215         timeout = ktime_add_us(ktime_get(), MADERA_BOOT_POLL_TIMEOUT_USEC);
 216         regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
 217         while (!(val & MADERA_BOOT_DONE_STS1) &&
 218                !ktime_after(ktime_get(), timeout)) {
 219                 usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2,
 220                              MADERA_BOOT_POLL_INTERVAL_USEC);
 221                 regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
 222         }
 223 
 224         if (!(val & MADERA_BOOT_DONE_STS1)) {
 225                 dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n");
 226                 ret = -ETIMEDOUT;
 227         }
 228 
 229         /*
 230          * BOOT_DONE defaults to unmasked on boot so we must ack it.
 231          * Do this even after a timeout to avoid interrupt storms.
 232          */
 233         regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
 234                      MADERA_BOOT_DONE_EINT1);
 235 
 236         pm_runtime_mark_last_busy(madera->dev);
 237 
 238         return ret;
 239 }
 240 
 241 static int madera_soft_reset(struct madera *madera)
 242 {
 243         int ret;
 244 
 245         ret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0);
 246         if (ret != 0) {
 247                 dev_err(madera->dev, "Failed to soft reset device: %d\n", ret);
 248                 return ret;
 249         }
 250 
 251         /* Allow time for internal clocks to startup after reset */
 252         usleep_range(1000, 2000);
 253 
 254         return 0;
 255 }
 256 
 257 static void madera_enable_hard_reset(struct madera *madera)
 258 {
 259         if (!madera->pdata.reset)
 260                 return;
 261 
 262         /*
 263          * There are many existing out-of-tree users of these codecs that we
 264          * can't break so preserve the expected behaviour of setting the line
 265          * low to assert reset.
 266          */
 267         gpiod_set_raw_value_cansleep(madera->pdata.reset, 0);
 268 }
 269 
 270 static void madera_disable_hard_reset(struct madera *madera)
 271 {
 272         if (!madera->pdata.reset)
 273                 return;
 274 
 275         gpiod_set_raw_value_cansleep(madera->pdata.reset, 1);
 276         usleep_range(1000, 2000);
 277 }
 278 
 279 static int __maybe_unused madera_runtime_resume(struct device *dev)
 280 {
 281         struct madera *madera = dev_get_drvdata(dev);
 282         int ret;
 283 
 284         dev_dbg(dev, "Leaving sleep mode\n");
 285 
 286         ret = regulator_enable(madera->dcvdd);
 287         if (ret) {
 288                 dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
 289                 return ret;
 290         }
 291 
 292         regcache_cache_only(madera->regmap, false);
 293         regcache_cache_only(madera->regmap_32bit, false);
 294 
 295         ret = madera_wait_for_boot(madera);
 296         if (ret)
 297                 goto err;
 298 
 299         ret = regcache_sync(madera->regmap);
 300         if (ret) {
 301                 dev_err(dev, "Failed to restore 16-bit register cache\n");
 302                 goto err;
 303         }
 304 
 305         ret = regcache_sync(madera->regmap_32bit);
 306         if (ret) {
 307                 dev_err(dev, "Failed to restore 32-bit register cache\n");
 308                 goto err;
 309         }
 310 
 311         return 0;
 312 
 313 err:
 314         regcache_cache_only(madera->regmap_32bit, true);
 315         regcache_cache_only(madera->regmap, true);
 316         regulator_disable(madera->dcvdd);
 317 
 318         return ret;
 319 }
 320 
 321 static int __maybe_unused madera_runtime_suspend(struct device *dev)
 322 {
 323         struct madera *madera = dev_get_drvdata(dev);
 324 
 325         dev_dbg(madera->dev, "Entering sleep mode\n");
 326 
 327         regcache_cache_only(madera->regmap, true);
 328         regcache_mark_dirty(madera->regmap);
 329         regcache_cache_only(madera->regmap_32bit, true);
 330         regcache_mark_dirty(madera->regmap_32bit);
 331 
 332         regulator_disable(madera->dcvdd);
 333 
 334         return 0;
 335 }
 336 
 337 const struct dev_pm_ops madera_pm_ops = {
 338         SET_RUNTIME_PM_OPS(madera_runtime_suspend,
 339                            madera_runtime_resume,
 340                            NULL)
 341 };
 342 EXPORT_SYMBOL_GPL(madera_pm_ops);
 343 
 344 const struct of_device_id madera_of_match[] = {
 345         { .compatible = "cirrus,cs47l15", .data = (void *)CS47L15 },
 346         { .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
 347         { .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
 348         { .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
 349         { .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 },
 350         { .compatible = "cirrus,cs42l92", .data = (void *)CS42L92 },
 351         { .compatible = "cirrus,cs47l92", .data = (void *)CS47L92 },
 352         { .compatible = "cirrus,cs47l93", .data = (void *)CS47L93 },
 353         { .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
 354         {}
 355 };
 356 MODULE_DEVICE_TABLE(of, madera_of_match);
 357 EXPORT_SYMBOL_GPL(madera_of_match);
 358 
 359 static int madera_get_reset_gpio(struct madera *madera)
 360 {
 361         struct gpio_desc *reset;
 362         int ret;
 363 
 364         if (madera->pdata.reset)
 365                 return 0;
 366 
 367         reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW);
 368         if (IS_ERR(reset)) {
 369                 ret = PTR_ERR(reset);
 370                 if (ret != -EPROBE_DEFER)
 371                         dev_err(madera->dev, "Failed to request /RESET: %d\n",
 372                                 ret);
 373                 return ret;
 374         }
 375 
 376         /*
 377          * A hard reset is needed for full reset of the chip. We allow running
 378          * without hard reset only because it can be useful for early
 379          * prototyping and some debugging, but we need to warn it's not ideal.
 380          */
 381         if (!reset)
 382                 dev_warn(madera->dev,
 383                          "Running without reset GPIO is not recommended\n");
 384 
 385         madera->pdata.reset = reset;
 386 
 387         return 0;
 388 }
 389 
 390 static void madera_set_micbias_info(struct madera *madera)
 391 {
 392         /*
 393          * num_childbias is an array because future codecs can have different
 394          * childbiases for each micbias. Unspecified values default to 0.
 395          */
 396         switch (madera->type) {
 397         case CS47L15:
 398                 madera->num_micbias = 1;
 399                 madera->num_childbias[0] = 3;
 400                 return;
 401         case CS47L35:
 402                 madera->num_micbias = 2;
 403                 madera->num_childbias[0] = 2;
 404                 madera->num_childbias[1] = 2;
 405                 return;
 406         case CS47L85:
 407         case WM1840:
 408                 madera->num_micbias = 4;
 409                 /* no child biases */
 410                 return;
 411         case CS47L90:
 412         case CS47L91:
 413                 madera->num_micbias = 2;
 414                 madera->num_childbias[0] = 4;
 415                 madera->num_childbias[1] = 4;
 416                 return;
 417         case CS42L92:
 418         case CS47L92:
 419         case CS47L93:
 420                 madera->num_micbias = 2;
 421                 madera->num_childbias[0] = 4;
 422                 madera->num_childbias[1] = 2;
 423                 return;
 424         default:
 425                 return;
 426         }
 427 }
 428 
 429 int madera_dev_init(struct madera *madera)
 430 {
 431         struct device *dev = madera->dev;
 432         unsigned int hwid;
 433         int (*patch_fn)(struct madera *) = NULL;
 434         const struct mfd_cell *mfd_devs;
 435         int n_devs = 0;
 436         int i, ret;
 437 
 438         dev_set_drvdata(madera->dev, madera);
 439         BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
 440         mutex_init(&madera->dapm_ptr_lock);
 441 
 442         madera_set_micbias_info(madera);
 443 
 444         /*
 445          * We need writable hw config info that all children can share.
 446          * Simplest to take one shared copy of pdata struct.
 447          */
 448         if (dev_get_platdata(madera->dev)) {
 449                 memcpy(&madera->pdata, dev_get_platdata(madera->dev),
 450                        sizeof(madera->pdata));
 451         }
 452 
 453         ret = madera_get_reset_gpio(madera);
 454         if (ret)
 455                 return ret;
 456 
 457         regcache_cache_only(madera->regmap, true);
 458         regcache_cache_only(madera->regmap_32bit, true);
 459 
 460         for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++)
 461                 madera->core_supplies[i].supply = madera_core_supplies[i];
 462 
 463         madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies);
 464 
 465         /*
 466          * On some codecs DCVDD could be supplied by the internal LDO1.
 467          * For those we must add the LDO1 driver before requesting DCVDD
 468          * No devm_ because we need to control shutdown order of children.
 469          */
 470         switch (madera->type) {
 471         case CS47L15:
 472         case CS47L35:
 473         case CS47L90:
 474         case CS47L91:
 475         case CS42L92:
 476         case CS47L92:
 477         case CS47L93:
 478                 break;
 479         case CS47L85:
 480         case WM1840:
 481                 ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
 482                                       madera_ldo1_devs,
 483                                       ARRAY_SIZE(madera_ldo1_devs),
 484                                       NULL, 0, NULL);
 485                 if (ret) {
 486                         dev_err(dev, "Failed to add LDO1 child: %d\n", ret);
 487                         return ret;
 488                 }
 489                 break;
 490         default:
 491                 /* No point continuing if the type is unknown */
 492                 dev_err(madera->dev, "Unknown device type %d\n", madera->type);
 493                 return -ENODEV;
 494         }
 495 
 496         ret = devm_regulator_bulk_get(dev, madera->num_core_supplies,
 497                                       madera->core_supplies);
 498         if (ret) {
 499                 dev_err(dev, "Failed to request core supplies: %d\n", ret);
 500                 goto err_devs;
 501         }
 502 
 503         /*
 504          * Don't use devres here. If the regulator is one of our children it
 505          * will already have been removed before devres cleanup on this mfd
 506          * driver tries to call put() on it. We need control of shutdown order.
 507          */
 508         madera->dcvdd = regulator_get(madera->dev, "DCVDD");
 509         if (IS_ERR(madera->dcvdd)) {
 510                 ret = PTR_ERR(madera->dcvdd);
 511                 dev_err(dev, "Failed to request DCVDD: %d\n", ret);
 512                 goto err_devs;
 513         }
 514 
 515         ret = regulator_bulk_enable(madera->num_core_supplies,
 516                                     madera->core_supplies);
 517         if (ret) {
 518                 dev_err(dev, "Failed to enable core supplies: %d\n", ret);
 519                 goto err_dcvdd;
 520         }
 521 
 522         ret = regulator_enable(madera->dcvdd);
 523         if (ret) {
 524                 dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
 525                 goto err_enable;
 526         }
 527 
 528         madera_disable_hard_reset(madera);
 529 
 530         regcache_cache_only(madera->regmap, false);
 531         regcache_cache_only(madera->regmap_32bit, false);
 532 
 533         /*
 534          * Now we can power up and verify that this is a chip we know about
 535          * before we start doing any writes to its registers.
 536          */
 537         ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid);
 538         if (ret) {
 539                 dev_err(dev, "Failed to read ID register: %d\n", ret);
 540                 goto err_reset;
 541         }
 542 
 543         switch (hwid) {
 544         case CS47L15_SILICON_ID:
 545                 if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
 546                         switch (madera->type) {
 547                         case CS47L15:
 548                                 patch_fn = &cs47l15_patch;
 549                                 mfd_devs = cs47l15_devs;
 550                                 n_devs = ARRAY_SIZE(cs47l15_devs);
 551                                 break;
 552                         default:
 553                                 break;
 554                         }
 555                 }
 556                 break;
 557         case CS47L35_SILICON_ID:
 558                 if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
 559                         switch (madera->type) {
 560                         case CS47L35:
 561                                 patch_fn = cs47l35_patch;
 562                                 mfd_devs = cs47l35_devs;
 563                                 n_devs = ARRAY_SIZE(cs47l35_devs);
 564                                 break;
 565                         default:
 566                                 break;
 567                         }
 568                 }
 569                 break;
 570         case CS47L85_SILICON_ID:
 571                 if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
 572                         switch (madera->type) {
 573                         case CS47L85:
 574                         case WM1840:
 575                                 patch_fn = cs47l85_patch;
 576                                 mfd_devs = cs47l85_devs;
 577                                 n_devs = ARRAY_SIZE(cs47l85_devs);
 578                                 break;
 579                         default:
 580                                 break;
 581                         }
 582                 }
 583                 break;
 584         case CS47L90_SILICON_ID:
 585                 if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
 586                         switch (madera->type) {
 587                         case CS47L90:
 588                         case CS47L91:
 589                                 patch_fn = cs47l90_patch;
 590                                 mfd_devs = cs47l90_devs;
 591                                 n_devs = ARRAY_SIZE(cs47l90_devs);
 592                                 break;
 593                         default:
 594                                 break;
 595                         }
 596                 }
 597                 break;
 598         case CS47L92_SILICON_ID:
 599                 if (IS_ENABLED(CONFIG_MFD_CS47L92)) {
 600                         switch (madera->type) {
 601                         case CS42L92:
 602                         case CS47L92:
 603                         case CS47L93:
 604                                 patch_fn = cs47l92_patch;
 605                                 mfd_devs = cs47l92_devs;
 606                                 n_devs = ARRAY_SIZE(cs47l92_devs);
 607                                 break;
 608                         default:
 609                                 break;
 610                         }
 611                 }
 612                 break;
 613         default:
 614                 dev_err(madera->dev, "Unknown device ID: %x\n", hwid);
 615                 ret = -EINVAL;
 616                 goto err_reset;
 617         }
 618 
 619         if (!n_devs) {
 620                 dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid,
 621                         madera->type_name);
 622                 ret = -ENODEV;
 623                 goto err_reset;
 624         }
 625 
 626         /*
 627          * It looks like a device we support. If we don't have a hard reset
 628          * we can now attempt a soft reset.
 629          */
 630         if (!madera->pdata.reset) {
 631                 ret = madera_soft_reset(madera);
 632                 if (ret)
 633                         goto err_reset;
 634         }
 635 
 636         ret = madera_wait_for_boot(madera);
 637         if (ret) {
 638                 dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
 639                 goto err_reset;
 640         }
 641 
 642         ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION,
 643                           &madera->rev);
 644         if (ret) {
 645                 dev_err(dev, "Failed to read revision register: %d\n", ret);
 646                 goto err_reset;
 647         }
 648         madera->rev &= MADERA_HW_REVISION_MASK;
 649 
 650         dev_info(dev, "%s silicon revision %d\n", madera->type_name,
 651                  madera->rev);
 652 
 653         /* Apply hardware patch */
 654         if (patch_fn) {
 655                 ret = patch_fn(madera);
 656                 if (ret) {
 657                         dev_err(madera->dev, "Failed to apply patch %d\n", ret);
 658                         goto err_reset;
 659                 }
 660         }
 661 
 662         /* Init 32k clock sourced from MCLK2 */
 663         ret = regmap_update_bits(madera->regmap,
 664                         MADERA_CLOCK_32K_1,
 665                         MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
 666                         MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);
 667         if (ret) {
 668                 dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret);
 669                 goto err_reset;
 670         }
 671 
 672         pm_runtime_set_active(madera->dev);
 673         pm_runtime_enable(madera->dev);
 674         pm_runtime_set_autosuspend_delay(madera->dev, 100);
 675         pm_runtime_use_autosuspend(madera->dev);
 676 
 677         /* No devm_ because we need to control shutdown order of children */
 678         ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
 679                               mfd_devs, n_devs,
 680                               NULL, 0, NULL);
 681         if (ret) {
 682                 dev_err(madera->dev, "Failed to add subdevices: %d\n", ret);
 683                 goto err_pm_runtime;
 684         }
 685 
 686         return 0;
 687 
 688 err_pm_runtime:
 689         pm_runtime_disable(madera->dev);
 690 err_reset:
 691         madera_enable_hard_reset(madera);
 692         regulator_disable(madera->dcvdd);
 693 err_enable:
 694         regulator_bulk_disable(madera->num_core_supplies,
 695                                madera->core_supplies);
 696 err_dcvdd:
 697         regulator_put(madera->dcvdd);
 698 err_devs:
 699         mfd_remove_devices(dev);
 700 
 701         return ret;
 702 }
 703 EXPORT_SYMBOL_GPL(madera_dev_init);
 704 
 705 int madera_dev_exit(struct madera *madera)
 706 {
 707         /* Prevent any IRQs being serviced while we clean up */
 708         disable_irq(madera->irq);
 709 
 710         /*
 711          * DCVDD could be supplied by a child node, we must disable it before
 712          * removing the children, and prevent PM runtime from turning it back on
 713          */
 714         pm_runtime_disable(madera->dev);
 715 
 716         regulator_disable(madera->dcvdd);
 717         regulator_put(madera->dcvdd);
 718 
 719         mfd_remove_devices(madera->dev);
 720         madera_enable_hard_reset(madera);
 721 
 722         regulator_bulk_disable(madera->num_core_supplies,
 723                                madera->core_supplies);
 724         return 0;
 725 }
 726 EXPORT_SYMBOL_GPL(madera_dev_exit);
 727 
 728 MODULE_DESCRIPTION("Madera core MFD driver");
 729 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
 730 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */