hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mfd/madera-core.c
....@@ -1,12 +1,8 @@
1
-// SPDX-License-Identifier: GPL-2.0
1
+// SPDX-License-Identifier: GPL-2.0-only
22 /*
33 * Core MFD support for Cirrus Logic Madera codecs
44 *
55 * 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.
106 */
117
128 #include <linux/device.h>
....@@ -15,6 +11,7 @@
1511 #include <linux/gpio.h>
1612 #include <linux/mfd/core.h>
1713 #include <linux/module.h>
14
+#include <linux/mutex.h>
1815 #include <linux/notifier.h>
1916 #include <linux/of.h>
2017 #include <linux/of_gpio.h>
....@@ -30,11 +27,16 @@
3027
3128 #include "madera.h"
3229
30
+#define CS47L15_SILICON_ID 0x6370
3331 #define CS47L35_SILICON_ID 0x6360
3432 #define CS47L85_SILICON_ID 0x6338
3533 #define CS47L90_SILICON_ID 0x6364
34
+#define CS47L92_SILICON_ID 0x6371
3635
3736 #define MADERA_32KZ_MCLK2 1
37
+
38
+#define MADERA_RESET_MIN_US 2000
39
+#define MADERA_RESET_MAX_US 3000
3840
3941 static const char * const madera_core_supplies[] = {
4042 "AVDD",
....@@ -42,7 +44,32 @@
4244 };
4345
4446 static const struct mfd_cell madera_ldo1_devs[] = {
45
- { .name = "madera-ldo1" },
47
+ {
48
+ .name = "madera-ldo1",
49
+ .level = MFD_DEP_LEVEL_HIGH,
50
+ },
51
+};
52
+
53
+static const char * const cs47l15_supplies[] = {
54
+ "MICVDD",
55
+ "CPVDD1",
56
+ "SPKVDD",
57
+};
58
+
59
+static 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
+ },
4673 };
4774
4875 static const char * const cs47l35_supplies[] = {
....@@ -58,7 +85,11 @@
5885 { .name = "madera-irq", },
5986 { .name = "madera-micsupp", },
6087 { .name = "madera-gpio", },
61
- { .name = "madera-extcon", },
88
+ {
89
+ .name = "madera-extcon",
90
+ .parent_supplies = cs47l35_supplies,
91
+ .num_parent_supplies = 1, /* We only need MICVDD */
92
+ },
6293 {
6394 .name = "cs47l35-codec",
6495 .parent_supplies = cs47l35_supplies,
....@@ -80,9 +111,13 @@
80111 static const struct mfd_cell cs47l85_devs[] = {
81112 { .name = "madera-pinctrl", },
82113 { .name = "madera-irq", },
83
- { .name = "madera-micsupp" },
114
+ { .name = "madera-micsupp", },
84115 { .name = "madera-gpio", },
85
- { .name = "madera-extcon", },
116
+ {
117
+ .name = "madera-extcon",
118
+ .parent_supplies = cs47l85_supplies,
119
+ .num_parent_supplies = 1, /* We only need MICVDD */
120
+ },
86121 {
87122 .name = "cs47l85-codec",
88123 .parent_supplies = cs47l85_supplies,
....@@ -104,7 +139,11 @@
104139 { .name = "madera-irq", },
105140 { .name = "madera-micsupp", },
106141 { .name = "madera-gpio", },
107
- { .name = "madera-extcon", },
142
+ {
143
+ .name = "madera-extcon",
144
+ .parent_supplies = cs47l90_supplies,
145
+ .num_parent_supplies = 1, /* We only need MICVDD */
146
+ },
108147 {
109148 .name = "cs47l90-codec",
110149 .parent_supplies = cs47l90_supplies,
....@@ -112,10 +151,35 @@
112151 },
113152 };
114153
154
+static const char * const cs47l92_supplies[] = {
155
+ "MICVDD",
156
+ "CPVDD1",
157
+ "CPVDD2",
158
+};
159
+
160
+static 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
+
115177 /* Used by madera-i2c and madera-spi drivers */
116178 const char *madera_name_from_type(enum madera_type type)
117179 {
118180 switch (type) {
181
+ case CS47L15:
182
+ return "CS47L15";
119183 case CS47L35:
120184 return "CS47L35";
121185 case CS47L85:
....@@ -124,6 +188,12 @@
124188 return "CS47L90";
125189 case CS47L91:
126190 return "CS47L91";
191
+ case CS42L92:
192
+ return "CS42L92";
193
+ case CS47L92:
194
+ return "CS47L92";
195
+ case CS47L93:
196
+ return "CS47L93";
127197 case WM1840:
128198 return "WM1840";
129199 default:
....@@ -132,32 +202,46 @@
132202 }
133203 EXPORT_SYMBOL_GPL(madera_name_from_type);
134204
135
-#define MADERA_BOOT_POLL_MAX_INTERVAL_US 5000
136
-#define MADERA_BOOT_POLL_TIMEOUT_US 25000
205
+#define MADERA_BOOT_POLL_INTERVAL_USEC 5000
206
+#define MADERA_BOOT_POLL_TIMEOUT_USEC 25000
137207
138
-static int madera_wait_for_boot(struct madera *madera)
208
+static int madera_wait_for_boot_noack(struct madera *madera)
139209 {
140
- unsigned int val;
141
- int ret;
210
+ ktime_t timeout;
211
+ unsigned int val = 0;
212
+ int ret = 0;
142213
143214 /*
144215 * We can't use an interrupt as we need to runtime resume to do so,
145216 * so we poll the status bit. This won't race with the interrupt
146217 * 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.
147220 */
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);
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
+ }
154229
155
- if (ret)
156
- dev_err(madera->dev, "Polling BOOT_DONE_STS failed: %d\n", ret);
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
+
238
+static int madera_wait_for_boot(struct madera *madera)
239
+{
240
+ int ret = madera_wait_for_boot_noack(madera);
157241
158242 /*
159243 * BOOT_DONE defaults to unmasked on boot so we must ack it.
160
- * Do this unconditionally to avoid interrupt storms.
244
+ * Do this even after a timeout to avoid interrupt storms.
161245 */
162246 regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
163247 MADERA_BOOT_DONE_EINT1);
....@@ -178,16 +262,13 @@
178262 }
179263
180264 /* Allow time for internal clocks to startup after reset */
181
- usleep_range(1000, 2000);
265
+ usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US);
182266
183267 return 0;
184268 }
185269
186270 static void madera_enable_hard_reset(struct madera *madera)
187271 {
188
- if (!madera->pdata.reset)
189
- return;
190
-
191272 /*
192273 * There are many existing out-of-tree users of these codecs that we
193274 * can't break so preserve the expected behaviour of setting the line
....@@ -198,11 +279,9 @@
198279
199280 static void madera_disable_hard_reset(struct madera *madera)
200281 {
201
- if (!madera->pdata.reset)
202
- return;
203
-
204282 gpiod_set_raw_value_cansleep(madera->pdata.reset, 1);
205
- usleep_range(1000, 2000);
283
+
284
+ usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US);
206285 }
207286
208287 static int __maybe_unused madera_runtime_resume(struct device *dev)
....@@ -220,6 +299,8 @@
220299
221300 regcache_cache_only(madera->regmap, false);
222301 regcache_cache_only(madera->regmap_32bit, false);
302
+
303
+ usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US);
223304
224305 ret = madera_wait_for_boot(madera);
225306 if (ret)
....@@ -271,10 +352,14 @@
271352 EXPORT_SYMBOL_GPL(madera_pm_ops);
272353
273354 const struct of_device_id madera_of_match[] = {
355
+ { .compatible = "cirrus,cs47l15", .data = (void *)CS47L15 },
274356 { .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
275357 { .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
276358 { .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
277359 { .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 },
278363 { .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
279364 {}
280365 };
....@@ -284,19 +369,14 @@
284369 static int madera_get_reset_gpio(struct madera *madera)
285370 {
286371 struct gpio_desc *reset;
287
- int ret;
288372
289373 if (madera->pdata.reset)
290374 return 0;
291375
292376 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
- }
377
+ if (IS_ERR(reset))
378
+ return dev_err_probe(madera->dev, PTR_ERR(reset),
379
+ "Failed to request /RESET");
300380
301381 /*
302382 * A hard reset is needed for full reset of the chip. We allow running
....@@ -319,6 +399,10 @@
319399 * childbiases for each micbias. Unspecified values default to 0.
320400 */
321401 switch (madera->type) {
402
+ case CS47L15:
403
+ madera->num_micbias = 1;
404
+ madera->num_childbias[0] = 3;
405
+ return;
322406 case CS47L35:
323407 madera->num_micbias = 2;
324408 madera->num_childbias[0] = 2;
....@@ -334,6 +418,13 @@
334418 madera->num_micbias = 2;
335419 madera->num_childbias[0] = 4;
336420 madera->num_childbias[1] = 4;
421
+ return;
422
+ case CS42L92:
423
+ case CS47L92:
424
+ case CS47L93:
425
+ madera->num_micbias = 2;
426
+ madera->num_childbias[0] = 4;
427
+ madera->num_childbias[1] = 2;
337428 return;
338429 default:
339430 return;
....@@ -351,6 +442,8 @@
351442
352443 dev_set_drvdata(madera->dev, madera);
353444 BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
445
+ mutex_init(&madera->dapm_ptr_lock);
446
+
354447 madera_set_micbias_info(madera);
355448
356449 /*
....@@ -361,6 +454,21 @@
361454 memcpy(&madera->pdata, dev_get_platdata(madera->dev),
362455 sizeof(madera->pdata));
363456 }
457
+
458
+ madera->mclk[MADERA_MCLK1].id = "mclk1";
459
+ madera->mclk[MADERA_MCLK2].id = "mclk2";
460
+ madera->mclk[MADERA_MCLK3].id = "mclk3";
461
+
462
+ ret = devm_clk_bulk_get_optional(madera->dev, ARRAY_SIZE(madera->mclk),
463
+ madera->mclk);
464
+ if (ret) {
465
+ dev_err(madera->dev, "Failed to get clocks: %d\n", ret);
466
+ return ret;
467
+ }
468
+
469
+ /* Not using devm_clk_get to prevent breakage of existing DTs */
470
+ if (!madera->mclk[MADERA_MCLK2].clk)
471
+ dev_warn(madera->dev, "Missing MCLK2, requires 32kHz clock\n");
364472
365473 ret = madera_get_reset_gpio(madera);
366474 if (ret)
....@@ -380,9 +488,13 @@
380488 * No devm_ because we need to control shutdown order of children.
381489 */
382490 switch (madera->type) {
491
+ case CS47L15:
383492 case CS47L35:
384493 case CS47L90:
385494 case CS47L91:
495
+ case CS42L92:
496
+ case CS47L92:
497
+ case CS47L93:
386498 break;
387499 case CS47L85:
388500 case WM1840:
....@@ -438,6 +550,12 @@
438550 regcache_cache_only(madera->regmap, false);
439551 regcache_cache_only(madera->regmap_32bit, false);
440552
553
+ ret = madera_wait_for_boot_noack(madera);
554
+ if (ret) {
555
+ dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
556
+ goto err_reset;
557
+ }
558
+
441559 /*
442560 * Now we can power up and verify that this is a chip we know about
443561 * before we start doing any writes to its registers.
....@@ -449,6 +567,19 @@
449567 }
450568
451569 switch (hwid) {
570
+ case CS47L15_SILICON_ID:
571
+ if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
572
+ switch (madera->type) {
573
+ case CS47L15:
574
+ patch_fn = &cs47l15_patch;
575
+ mfd_devs = cs47l15_devs;
576
+ n_devs = ARRAY_SIZE(cs47l15_devs);
577
+ break;
578
+ default:
579
+ break;
580
+ }
581
+ }
582
+ break;
452583 case CS47L35_SILICON_ID:
453584 if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
454585 switch (madera->type) {
....@@ -490,6 +621,21 @@
490621 }
491622 }
492623 break;
624
+ case CS47L92_SILICON_ID:
625
+ if (IS_ENABLED(CONFIG_MFD_CS47L92)) {
626
+ switch (madera->type) {
627
+ case CS42L92:
628
+ case CS47L92:
629
+ case CS47L93:
630
+ patch_fn = cs47l92_patch;
631
+ mfd_devs = cs47l92_devs;
632
+ n_devs = ARRAY_SIZE(cs47l92_devs);
633
+ break;
634
+ default:
635
+ break;
636
+ }
637
+ }
638
+ break;
493639 default:
494640 dev_err(madera->dev, "Unknown device ID: %x\n", hwid);
495641 ret = -EINVAL;
....@@ -515,7 +661,7 @@
515661
516662 ret = madera_wait_for_boot(madera);
517663 if (ret) {
518
- dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
664
+ dev_err(madera->dev, "Failed to clear boot done: %d\n", ret);
519665 goto err_reset;
520666 }
521667
....@@ -540,13 +686,19 @@
540686 }
541687
542688 /* Init 32k clock sourced from MCLK2 */
689
+ ret = clk_prepare_enable(madera->mclk[MADERA_MCLK2].clk);
690
+ if (ret) {
691
+ dev_err(madera->dev, "Failed to enable 32k clock: %d\n", ret);
692
+ goto err_reset;
693
+ }
694
+
543695 ret = regmap_update_bits(madera->regmap,
544696 MADERA_CLOCK_32K_1,
545697 MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
546698 MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);
547699 if (ret) {
548700 dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret);
549
- goto err_reset;
701
+ goto err_clock;
550702 }
551703
552704 pm_runtime_set_active(madera->dev);
....@@ -567,6 +719,8 @@
567719
568720 err_pm_runtime:
569721 pm_runtime_disable(madera->dev);
722
+err_clock:
723
+ clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
570724 err_reset:
571725 madera_enable_hard_reset(madera);
572726 regulator_disable(madera->dcvdd);
....@@ -587,16 +741,22 @@
587741 /* Prevent any IRQs being serviced while we clean up */
588742 disable_irq(madera->irq);
589743
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
- */
744
+ pm_runtime_get_sync(madera->dev);
745
+
746
+ mfd_remove_devices(madera->dev);
747
+
594748 pm_runtime_disable(madera->dev);
595749
596750 regulator_disable(madera->dcvdd);
597751 regulator_put(madera->dcvdd);
598752
599
- mfd_remove_devices(madera->dev);
753
+ mfd_remove_devices_late(madera->dev);
754
+
755
+ pm_runtime_set_suspended(madera->dev);
756
+ pm_runtime_put_noidle(madera->dev);
757
+
758
+ clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
759
+
600760 madera_enable_hard_reset(madera);
601761
602762 regulator_bulk_disable(madera->num_core_supplies,