Linux Audio

Check our new training course

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