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
 38static const char * const madera_core_supplies[] = {
 39	"AVDD",
 40	"DBVDD1",
 41};
 42
 43static const struct mfd_cell madera_ldo1_devs[] = {
 44	{ .name = "madera-ldo1" },
 45};
 46
 47static const char * const cs47l15_supplies[] = {
 48	"MICVDD",
 49	"CPVDD1",
 50	"SPKVDD",
 51};
 52
 53static 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
 69static const char * const cs47l35_supplies[] = {
 70	"MICVDD",
 71	"DBVDD2",
 72	"CPVDD1",
 73	"CPVDD2",
 74	"SPKVDD",
 75};
 76
 77static 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
 94static const char * const cs47l85_supplies[] = {
 95	"MICVDD",
 96	"DBVDD2",
 97	"DBVDD3",
 98	"DBVDD4",
 99	"CPVDD1",
100	"CPVDD2",
101	"SPKVDDL",
102	"SPKVDDR",
103};
104
105static 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
122static const char * const cs47l90_supplies[] = {
123	"MICVDD",
124	"DBVDD2",
125	"DBVDD3",
126	"DBVDD4",
127	"CPVDD1",
128	"CPVDD2",
129};
130
131static 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
148static const char * const cs47l92_supplies[] = {
149	"MICVDD",
150	"CPVDD1",
151	"CPVDD2",
152};
153
154static 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 */
172const 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}
197EXPORT_SYMBOL_GPL(madera_name_from_type);
198
199#define MADERA_BOOT_POLL_INTERVAL_USEC		5000
200#define MADERA_BOOT_POLL_TIMEOUT_USEC		25000
201
202static 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
241static 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
257static 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
270static 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
279static 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
313err:
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
321static 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
337const struct dev_pm_ops madera_pm_ops = {
338	SET_RUNTIME_PM_OPS(madera_runtime_suspend,
339			   madera_runtime_resume,
340			   NULL)
341};
342EXPORT_SYMBOL_GPL(madera_pm_ops);
343
344const 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};
356MODULE_DEVICE_TABLE(of, madera_of_match);
357EXPORT_SYMBOL_GPL(madera_of_match);
358
359static 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
390static 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
429int 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
688err_pm_runtime:
689	pm_runtime_disable(madera->dev);
690err_reset:
691	madera_enable_hard_reset(madera);
692	regulator_disable(madera->dcvdd);
693err_enable:
694	regulator_bulk_disable(madera->num_core_supplies,
695			       madera->core_supplies);
696err_dcvdd:
697	regulator_put(madera->dcvdd);
698err_devs:
699	mfd_remove_devices(dev);
700
701	return ret;
702}
703EXPORT_SYMBOL_GPL(madera_dev_init);
704
705int 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}
726EXPORT_SYMBOL_GPL(madera_dev_exit);
727
728MODULE_DESCRIPTION("Madera core MFD driver");
729MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
730MODULE_LICENSE("GPL v2");