Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Core MFD support for Cirrus Logic Madera codecs
0004  *
0005  * Copyright (C) 2015-2018 Cirrus Logic
0006  */
0007 
0008 #include <linux/device.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011 #include <linux/gpio.h>
0012 #include <linux/mfd/core.h>
0013 #include <linux/module.h>
0014 #include <linux/mutex.h>
0015 #include <linux/notifier.h>
0016 #include <linux/of.h>
0017 #include <linux/of_gpio.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/pm_runtime.h>
0020 #include <linux/regmap.h>
0021 #include <linux/regulator/consumer.h>
0022 #include <linux/regulator/machine.h>
0023 #include <linux/regulator/of_regulator.h>
0024 
0025 #include <linux/mfd/madera/core.h>
0026 #include <linux/mfd/madera/registers.h>
0027 
0028 #include "madera.h"
0029 
0030 #define CS47L15_SILICON_ID  0x6370
0031 #define CS47L35_SILICON_ID  0x6360
0032 #define CS47L85_SILICON_ID  0x6338
0033 #define CS47L90_SILICON_ID  0x6364
0034 #define CS47L92_SILICON_ID  0x6371
0035 
0036 #define MADERA_32KZ_MCLK2   1
0037 
0038 #define MADERA_RESET_MIN_US 2000
0039 #define MADERA_RESET_MAX_US 3000
0040 
0041 #define ERRATA_DCVDD_MIN_US 10000
0042 #define ERRATA_DCVDD_MAX_US 15000
0043 
0044 static const char * const madera_core_supplies[] = {
0045     "AVDD",
0046     "DBVDD1",
0047 };
0048 
0049 static const struct mfd_cell madera_ldo1_devs[] = {
0050     {
0051         .name = "madera-ldo1",
0052         .level = MFD_DEP_LEVEL_HIGH,
0053     },
0054 };
0055 
0056 static const char * const cs47l15_supplies[] = {
0057     "MICVDD",
0058     "CPVDD1",
0059     "SPKVDD",
0060 };
0061 
0062 static const struct mfd_cell cs47l15_devs[] = {
0063     { .name = "madera-pinctrl", },
0064     { .name = "madera-irq", },
0065     { .name = "madera-gpio", },
0066     {
0067         .name = "madera-extcon",
0068         .parent_supplies = cs47l15_supplies,
0069         .num_parent_supplies = 1, /* We only need MICVDD */
0070     },
0071     {
0072         .name = "cs47l15-codec",
0073         .parent_supplies = cs47l15_supplies,
0074         .num_parent_supplies = ARRAY_SIZE(cs47l15_supplies),
0075     },
0076 };
0077 
0078 static const char * const cs47l35_supplies[] = {
0079     "MICVDD",
0080     "DBVDD2",
0081     "CPVDD1",
0082     "CPVDD2",
0083     "SPKVDD",
0084 };
0085 
0086 static const struct mfd_cell cs47l35_devs[] = {
0087     { .name = "madera-pinctrl", },
0088     { .name = "madera-irq", },
0089     { .name = "madera-micsupp", },
0090     { .name = "madera-gpio", },
0091     {
0092         .name = "madera-extcon",
0093         .parent_supplies = cs47l35_supplies,
0094         .num_parent_supplies = 1, /* We only need MICVDD */
0095     },
0096     {
0097         .name = "cs47l35-codec",
0098         .parent_supplies = cs47l35_supplies,
0099         .num_parent_supplies = ARRAY_SIZE(cs47l35_supplies),
0100     },
0101 };
0102 
0103 static const char * const cs47l85_supplies[] = {
0104     "MICVDD",
0105     "DBVDD2",
0106     "DBVDD3",
0107     "DBVDD4",
0108     "CPVDD1",
0109     "CPVDD2",
0110     "SPKVDDL",
0111     "SPKVDDR",
0112 };
0113 
0114 static const struct mfd_cell cs47l85_devs[] = {
0115     { .name = "madera-pinctrl", },
0116     { .name = "madera-irq", },
0117     { .name = "madera-micsupp", },
0118     { .name = "madera-gpio", },
0119     {
0120         .name = "madera-extcon",
0121         .parent_supplies = cs47l85_supplies,
0122         .num_parent_supplies = 1, /* We only need MICVDD */
0123     },
0124     {
0125         .name = "cs47l85-codec",
0126         .parent_supplies = cs47l85_supplies,
0127         .num_parent_supplies = ARRAY_SIZE(cs47l85_supplies),
0128     },
0129 };
0130 
0131 static const char * const cs47l90_supplies[] = {
0132     "MICVDD",
0133     "DBVDD2",
0134     "DBVDD3",
0135     "DBVDD4",
0136     "CPVDD1",
0137     "CPVDD2",
0138 };
0139 
0140 static const struct mfd_cell cs47l90_devs[] = {
0141     { .name = "madera-pinctrl", },
0142     { .name = "madera-irq", },
0143     { .name = "madera-micsupp", },
0144     { .name = "madera-gpio", },
0145     {
0146         .name = "madera-extcon",
0147         .parent_supplies = cs47l90_supplies,
0148         .num_parent_supplies = 1, /* We only need MICVDD */
0149     },
0150     {
0151         .name = "cs47l90-codec",
0152         .parent_supplies = cs47l90_supplies,
0153         .num_parent_supplies = ARRAY_SIZE(cs47l90_supplies),
0154     },
0155 };
0156 
0157 static const char * const cs47l92_supplies[] = {
0158     "MICVDD",
0159     "CPVDD1",
0160     "CPVDD2",
0161 };
0162 
0163 static const struct mfd_cell cs47l92_devs[] = {
0164     { .name = "madera-pinctrl", },
0165     { .name = "madera-irq", },
0166     { .name = "madera-micsupp", },
0167     { .name = "madera-gpio", },
0168     {
0169         .name = "madera-extcon",
0170         .parent_supplies = cs47l92_supplies,
0171         .num_parent_supplies = 1, /* We only need MICVDD */
0172     },
0173     {
0174         .name = "cs47l92-codec",
0175         .parent_supplies = cs47l92_supplies,
0176         .num_parent_supplies = ARRAY_SIZE(cs47l92_supplies),
0177     },
0178 };
0179 
0180 /* Used by madera-i2c and madera-spi drivers */
0181 const char *madera_name_from_type(enum madera_type type)
0182 {
0183     switch (type) {
0184     case CS47L15:
0185         return "CS47L15";
0186     case CS47L35:
0187         return "CS47L35";
0188     case CS47L85:
0189         return "CS47L85";
0190     case CS47L90:
0191         return "CS47L90";
0192     case CS47L91:
0193         return "CS47L91";
0194     case CS42L92:
0195         return "CS42L92";
0196     case CS47L92:
0197         return "CS47L92";
0198     case CS47L93:
0199         return "CS47L93";
0200     case WM1840:
0201         return "WM1840";
0202     default:
0203         return "Unknown";
0204     }
0205 }
0206 EXPORT_SYMBOL_GPL(madera_name_from_type);
0207 
0208 #define MADERA_BOOT_POLL_INTERVAL_USEC      5000
0209 #define MADERA_BOOT_POLL_TIMEOUT_USEC       25000
0210 
0211 static int madera_wait_for_boot_noack(struct madera *madera)
0212 {
0213     ktime_t timeout;
0214     unsigned int val = 0;
0215     int ret = 0;
0216 
0217     /*
0218      * We can't use an interrupt as we need to runtime resume to do so,
0219      * so we poll the status bit. This won't race with the interrupt
0220      * handler because it will be blocked on runtime resume.
0221      * The chip could NAK a read request while it is booting so ignore
0222      * errors from regmap_read.
0223      */
0224     timeout = ktime_add_us(ktime_get(), MADERA_BOOT_POLL_TIMEOUT_USEC);
0225     regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
0226     while (!(val & MADERA_BOOT_DONE_STS1) &&
0227            !ktime_after(ktime_get(), timeout)) {
0228         usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2,
0229                  MADERA_BOOT_POLL_INTERVAL_USEC);
0230         regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
0231     }
0232 
0233     if (!(val & MADERA_BOOT_DONE_STS1)) {
0234         dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n");
0235         ret = -ETIMEDOUT;
0236     }
0237 
0238     return ret;
0239 }
0240 
0241 static int madera_wait_for_boot(struct madera *madera)
0242 {
0243     int ret = madera_wait_for_boot_noack(madera);
0244 
0245     /*
0246      * BOOT_DONE defaults to unmasked on boot so we must ack it.
0247      * Do this even after a timeout to avoid interrupt storms.
0248      */
0249     regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
0250              MADERA_BOOT_DONE_EINT1);
0251 
0252     pm_runtime_mark_last_busy(madera->dev);
0253 
0254     return ret;
0255 }
0256 
0257 static int madera_soft_reset(struct madera *madera)
0258 {
0259     int ret;
0260 
0261     ret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0);
0262     if (ret != 0) {
0263         dev_err(madera->dev, "Failed to soft reset device: %d\n", ret);
0264         return ret;
0265     }
0266 
0267     /* Allow time for internal clocks to startup after reset */
0268     usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US);
0269 
0270     return 0;
0271 }
0272 
0273 static void madera_enable_hard_reset(struct madera *madera)
0274 {
0275     /*
0276      * There are many existing out-of-tree users of these codecs that we
0277      * can't break so preserve the expected behaviour of setting the line
0278      * low to assert reset.
0279      */
0280     gpiod_set_raw_value_cansleep(madera->pdata.reset, 0);
0281 }
0282 
0283 static void madera_disable_hard_reset(struct madera *madera)
0284 {
0285     gpiod_set_raw_value_cansleep(madera->pdata.reset, 1);
0286 
0287     usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US);
0288 }
0289 
0290 static int __maybe_unused madera_runtime_resume(struct device *dev)
0291 {
0292     struct madera *madera = dev_get_drvdata(dev);
0293     int ret;
0294 
0295     dev_dbg(dev, "Leaving sleep mode\n");
0296 
0297     if (!madera->reset_errata)
0298         madera_enable_hard_reset(madera);
0299 
0300     ret = regulator_enable(madera->dcvdd);
0301     if (ret) {
0302         dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
0303         return ret;
0304     }
0305 
0306     regcache_cache_only(madera->regmap, false);
0307     regcache_cache_only(madera->regmap_32bit, false);
0308 
0309     if (madera->reset_errata)
0310         usleep_range(ERRATA_DCVDD_MIN_US, ERRATA_DCVDD_MAX_US);
0311     else
0312         madera_disable_hard_reset(madera);
0313 
0314     if (!madera->pdata.reset || madera->reset_errata) {
0315         ret = madera_wait_for_boot(madera);
0316         if (ret)
0317             goto err;
0318 
0319         ret = madera_soft_reset(madera);
0320         if (ret) {
0321             dev_err(dev, "Failed to reset: %d\n", ret);
0322             goto err;
0323         }
0324     }
0325 
0326     ret = madera_wait_for_boot(madera);
0327     if (ret)
0328         goto err;
0329 
0330     ret = regcache_sync(madera->regmap);
0331     if (ret) {
0332         dev_err(dev, "Failed to restore 16-bit register cache\n");
0333         goto err;
0334     }
0335 
0336     ret = regcache_sync(madera->regmap_32bit);
0337     if (ret) {
0338         dev_err(dev, "Failed to restore 32-bit register cache\n");
0339         goto err;
0340     }
0341 
0342     return 0;
0343 
0344 err:
0345     regcache_cache_only(madera->regmap_32bit, true);
0346     regcache_cache_only(madera->regmap, true);
0347     regulator_disable(madera->dcvdd);
0348 
0349     return ret;
0350 }
0351 
0352 static int __maybe_unused madera_runtime_suspend(struct device *dev)
0353 {
0354     struct madera *madera = dev_get_drvdata(dev);
0355 
0356     dev_dbg(madera->dev, "Entering sleep mode\n");
0357 
0358     regcache_cache_only(madera->regmap, true);
0359     regcache_mark_dirty(madera->regmap);
0360     regcache_cache_only(madera->regmap_32bit, true);
0361     regcache_mark_dirty(madera->regmap_32bit);
0362 
0363     regulator_disable(madera->dcvdd);
0364 
0365     return 0;
0366 }
0367 
0368 const struct dev_pm_ops madera_pm_ops = {
0369     SET_RUNTIME_PM_OPS(madera_runtime_suspend,
0370                madera_runtime_resume,
0371                NULL)
0372 };
0373 EXPORT_SYMBOL_GPL(madera_pm_ops);
0374 
0375 const struct of_device_id madera_of_match[] = {
0376     { .compatible = "cirrus,cs47l15", .data = (void *)CS47L15 },
0377     { .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
0378     { .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
0379     { .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
0380     { .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 },
0381     { .compatible = "cirrus,cs42l92", .data = (void *)CS42L92 },
0382     { .compatible = "cirrus,cs47l92", .data = (void *)CS47L92 },
0383     { .compatible = "cirrus,cs47l93", .data = (void *)CS47L93 },
0384     { .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
0385     {}
0386 };
0387 MODULE_DEVICE_TABLE(of, madera_of_match);
0388 EXPORT_SYMBOL_GPL(madera_of_match);
0389 
0390 static int madera_get_reset_gpio(struct madera *madera)
0391 {
0392     struct gpio_desc *reset;
0393 
0394     if (madera->pdata.reset)
0395         return 0;
0396 
0397     reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW);
0398     if (IS_ERR(reset))
0399         return dev_err_probe(madera->dev, PTR_ERR(reset),
0400                 "Failed to request /RESET");
0401 
0402     /*
0403      * A hard reset is needed for full reset of the chip. We allow running
0404      * without hard reset only because it can be useful for early
0405      * prototyping and some debugging, but we need to warn it's not ideal.
0406      */
0407     if (!reset)
0408         dev_warn(madera->dev,
0409              "Running without reset GPIO is not recommended\n");
0410 
0411     madera->pdata.reset = reset;
0412 
0413     return 0;
0414 }
0415 
0416 static void madera_set_micbias_info(struct madera *madera)
0417 {
0418     /*
0419      * num_childbias is an array because future codecs can have different
0420      * childbiases for each micbias. Unspecified values default to 0.
0421      */
0422     switch (madera->type) {
0423     case CS47L15:
0424         madera->num_micbias = 1;
0425         madera->num_childbias[0] = 3;
0426         return;
0427     case CS47L35:
0428         madera->num_micbias = 2;
0429         madera->num_childbias[0] = 2;
0430         madera->num_childbias[1] = 2;
0431         return;
0432     case CS47L85:
0433     case WM1840:
0434         madera->num_micbias = 4;
0435         /* no child biases */
0436         return;
0437     case CS47L90:
0438     case CS47L91:
0439         madera->num_micbias = 2;
0440         madera->num_childbias[0] = 4;
0441         madera->num_childbias[1] = 4;
0442         return;
0443     case CS42L92:
0444     case CS47L92:
0445     case CS47L93:
0446         madera->num_micbias = 2;
0447         madera->num_childbias[0] = 4;
0448         madera->num_childbias[1] = 2;
0449         return;
0450     default:
0451         return;
0452     }
0453 }
0454 
0455 int madera_dev_init(struct madera *madera)
0456 {
0457     struct device *dev = madera->dev;
0458     unsigned int hwid;
0459     int (*patch_fn)(struct madera *) = NULL;
0460     const struct mfd_cell *mfd_devs;
0461     int n_devs = 0;
0462     int i, ret;
0463 
0464     dev_set_drvdata(madera->dev, madera);
0465     BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
0466     mutex_init(&madera->dapm_ptr_lock);
0467 
0468     madera_set_micbias_info(madera);
0469 
0470     /*
0471      * We need writable hw config info that all children can share.
0472      * Simplest to take one shared copy of pdata struct.
0473      */
0474     if (dev_get_platdata(madera->dev)) {
0475         memcpy(&madera->pdata, dev_get_platdata(madera->dev),
0476                sizeof(madera->pdata));
0477     }
0478 
0479     madera->mclk[MADERA_MCLK1].id = "mclk1";
0480     madera->mclk[MADERA_MCLK2].id = "mclk2";
0481     madera->mclk[MADERA_MCLK3].id = "mclk3";
0482 
0483     ret = devm_clk_bulk_get_optional(madera->dev, ARRAY_SIZE(madera->mclk),
0484                      madera->mclk);
0485     if (ret) {
0486         dev_err(madera->dev, "Failed to get clocks: %d\n", ret);
0487         return ret;
0488     }
0489 
0490     /* Not using devm_clk_get to prevent breakage of existing DTs */
0491     if (!madera->mclk[MADERA_MCLK2].clk)
0492         dev_warn(madera->dev, "Missing MCLK2, requires 32kHz clock\n");
0493 
0494     ret = madera_get_reset_gpio(madera);
0495     if (ret)
0496         return ret;
0497 
0498     regcache_cache_only(madera->regmap, true);
0499     regcache_cache_only(madera->regmap_32bit, true);
0500 
0501     for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++)
0502         madera->core_supplies[i].supply = madera_core_supplies[i];
0503 
0504     madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies);
0505 
0506     /*
0507      * On some codecs DCVDD could be supplied by the internal LDO1.
0508      * For those we must add the LDO1 driver before requesting DCVDD
0509      * No devm_ because we need to control shutdown order of children.
0510      */
0511     switch (madera->type) {
0512     case CS47L15:
0513         madera->reset_errata = true;
0514         break;
0515     case CS47L35:
0516     case CS47L90:
0517     case CS47L91:
0518     case CS42L92:
0519     case CS47L92:
0520     case CS47L93:
0521         break;
0522     case CS47L85:
0523     case WM1840:
0524         ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
0525                       madera_ldo1_devs,
0526                       ARRAY_SIZE(madera_ldo1_devs),
0527                       NULL, 0, NULL);
0528         if (ret) {
0529             dev_err(dev, "Failed to add LDO1 child: %d\n", ret);
0530             return ret;
0531         }
0532         break;
0533     default:
0534         /* No point continuing if the type is unknown */
0535         dev_err(madera->dev, "Unknown device type %d\n", madera->type);
0536         return -ENODEV;
0537     }
0538 
0539     ret = devm_regulator_bulk_get(dev, madera->num_core_supplies,
0540                       madera->core_supplies);
0541     if (ret) {
0542         dev_err(dev, "Failed to request core supplies: %d\n", ret);
0543         goto err_devs;
0544     }
0545 
0546     /*
0547      * Don't use devres here. If the regulator is one of our children it
0548      * will already have been removed before devres cleanup on this mfd
0549      * driver tries to call put() on it. We need control of shutdown order.
0550      */
0551     madera->dcvdd = regulator_get(madera->dev, "DCVDD");
0552     if (IS_ERR(madera->dcvdd)) {
0553         ret = PTR_ERR(madera->dcvdd);
0554         dev_err(dev, "Failed to request DCVDD: %d\n", ret);
0555         goto err_devs;
0556     }
0557 
0558     ret = regulator_bulk_enable(madera->num_core_supplies,
0559                     madera->core_supplies);
0560     if (ret) {
0561         dev_err(dev, "Failed to enable core supplies: %d\n", ret);
0562         goto err_dcvdd;
0563     }
0564 
0565     if (madera->reset_errata)
0566         madera_disable_hard_reset(madera);
0567 
0568     ret = regulator_enable(madera->dcvdd);
0569     if (ret) {
0570         dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
0571         goto err_enable;
0572     }
0573 
0574     if (madera->reset_errata)
0575         usleep_range(ERRATA_DCVDD_MIN_US, ERRATA_DCVDD_MAX_US);
0576     else
0577         madera_disable_hard_reset(madera);
0578 
0579     regcache_cache_only(madera->regmap, false);
0580     regcache_cache_only(madera->regmap_32bit, false);
0581 
0582     ret = madera_wait_for_boot_noack(madera);
0583     if (ret) {
0584         dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
0585         goto err_reset;
0586     }
0587 
0588     /*
0589      * Now we can power up and verify that this is a chip we know about
0590      * before we start doing any writes to its registers.
0591      */
0592     ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid);
0593     if (ret) {
0594         dev_err(dev, "Failed to read ID register: %d\n", ret);
0595         goto err_reset;
0596     }
0597 
0598     switch (hwid) {
0599     case CS47L15_SILICON_ID:
0600         if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
0601             switch (madera->type) {
0602             case CS47L15:
0603                 patch_fn = &cs47l15_patch;
0604                 mfd_devs = cs47l15_devs;
0605                 n_devs = ARRAY_SIZE(cs47l15_devs);
0606                 break;
0607             default:
0608                 break;
0609             }
0610         }
0611         break;
0612     case CS47L35_SILICON_ID:
0613         if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
0614             switch (madera->type) {
0615             case CS47L35:
0616                 patch_fn = cs47l35_patch;
0617                 mfd_devs = cs47l35_devs;
0618                 n_devs = ARRAY_SIZE(cs47l35_devs);
0619                 break;
0620             default:
0621                 break;
0622             }
0623         }
0624         break;
0625     case CS47L85_SILICON_ID:
0626         if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
0627             switch (madera->type) {
0628             case CS47L85:
0629             case WM1840:
0630                 patch_fn = cs47l85_patch;
0631                 mfd_devs = cs47l85_devs;
0632                 n_devs = ARRAY_SIZE(cs47l85_devs);
0633                 break;
0634             default:
0635                 break;
0636             }
0637         }
0638         break;
0639     case CS47L90_SILICON_ID:
0640         if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
0641             switch (madera->type) {
0642             case CS47L90:
0643             case CS47L91:
0644                 patch_fn = cs47l90_patch;
0645                 mfd_devs = cs47l90_devs;
0646                 n_devs = ARRAY_SIZE(cs47l90_devs);
0647                 break;
0648             default:
0649                 break;
0650             }
0651         }
0652         break;
0653     case CS47L92_SILICON_ID:
0654         if (IS_ENABLED(CONFIG_MFD_CS47L92)) {
0655             switch (madera->type) {
0656             case CS42L92:
0657             case CS47L92:
0658             case CS47L93:
0659                 patch_fn = cs47l92_patch;
0660                 mfd_devs = cs47l92_devs;
0661                 n_devs = ARRAY_SIZE(cs47l92_devs);
0662                 break;
0663             default:
0664                 break;
0665             }
0666         }
0667         break;
0668     default:
0669         dev_err(madera->dev, "Unknown device ID: %x\n", hwid);
0670         ret = -EINVAL;
0671         goto err_reset;
0672     }
0673 
0674     if (!n_devs) {
0675         dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid,
0676             madera->type_name);
0677         ret = -ENODEV;
0678         goto err_reset;
0679     }
0680 
0681     /*
0682      * It looks like a device we support. If we don't have a hard reset
0683      * we can now attempt a soft reset.
0684      */
0685     if (!madera->pdata.reset || madera->reset_errata) {
0686         ret = madera_soft_reset(madera);
0687         if (ret)
0688             goto err_reset;
0689     }
0690 
0691     ret = madera_wait_for_boot(madera);
0692     if (ret) {
0693         dev_err(madera->dev, "Failed to clear boot done: %d\n", ret);
0694         goto err_reset;
0695     }
0696 
0697     ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION,
0698               &madera->rev);
0699     if (ret) {
0700         dev_err(dev, "Failed to read revision register: %d\n", ret);
0701         goto err_reset;
0702     }
0703     madera->rev &= MADERA_HW_REVISION_MASK;
0704 
0705     dev_info(dev, "%s silicon revision %d\n", madera->type_name,
0706          madera->rev);
0707 
0708     /* Apply hardware patch */
0709     if (patch_fn) {
0710         ret = patch_fn(madera);
0711         if (ret) {
0712             dev_err(madera->dev, "Failed to apply patch %d\n", ret);
0713             goto err_reset;
0714         }
0715     }
0716 
0717     /* Init 32k clock sourced from MCLK2 */
0718     ret = clk_prepare_enable(madera->mclk[MADERA_MCLK2].clk);
0719     if (ret) {
0720         dev_err(madera->dev, "Failed to enable 32k clock: %d\n", ret);
0721         goto err_reset;
0722     }
0723 
0724     ret = regmap_update_bits(madera->regmap,
0725             MADERA_CLOCK_32K_1,
0726             MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
0727             MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);
0728     if (ret) {
0729         dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret);
0730         goto err_clock;
0731     }
0732 
0733     pm_runtime_set_active(madera->dev);
0734     pm_runtime_enable(madera->dev);
0735     pm_runtime_set_autosuspend_delay(madera->dev, 100);
0736     pm_runtime_use_autosuspend(madera->dev);
0737 
0738     /* No devm_ because we need to control shutdown order of children */
0739     ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
0740                   mfd_devs, n_devs,
0741                   NULL, 0, NULL);
0742     if (ret) {
0743         dev_err(madera->dev, "Failed to add subdevices: %d\n", ret);
0744         goto err_pm_runtime;
0745     }
0746 
0747     return 0;
0748 
0749 err_pm_runtime:
0750     pm_runtime_disable(madera->dev);
0751 err_clock:
0752     clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
0753 err_reset:
0754     madera_enable_hard_reset(madera);
0755     regulator_disable(madera->dcvdd);
0756 err_enable:
0757     regulator_bulk_disable(madera->num_core_supplies,
0758                    madera->core_supplies);
0759 err_dcvdd:
0760     regulator_put(madera->dcvdd);
0761 err_devs:
0762     mfd_remove_devices(dev);
0763 
0764     return ret;
0765 }
0766 EXPORT_SYMBOL_GPL(madera_dev_init);
0767 
0768 int madera_dev_exit(struct madera *madera)
0769 {
0770     /* Prevent any IRQs being serviced while we clean up */
0771     disable_irq(madera->irq);
0772 
0773     pm_runtime_get_sync(madera->dev);
0774 
0775     mfd_remove_devices(madera->dev);
0776 
0777     pm_runtime_disable(madera->dev);
0778 
0779     regulator_disable(madera->dcvdd);
0780     regulator_put(madera->dcvdd);
0781 
0782     mfd_remove_devices_late(madera->dev);
0783 
0784     pm_runtime_set_suspended(madera->dev);
0785     pm_runtime_put_noidle(madera->dev);
0786 
0787     clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
0788 
0789     madera_enable_hard_reset(madera);
0790 
0791     regulator_bulk_disable(madera->num_core_supplies,
0792                    madera->core_supplies);
0793     return 0;
0794 }
0795 EXPORT_SYMBOL_GPL(madera_dev_exit);
0796 
0797 MODULE_DESCRIPTION("Madera core MFD driver");
0798 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
0799 MODULE_LICENSE("GPL v2");