cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

madera-core.c (19169B)


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