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