1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Components shared between ASoC and HDA CS35L56 drivers
4 //
5 // Copyright (C) 2023 Cirrus Logic, Inc. and
6 // Cirrus Logic International Semiconductor Ltd.
7
8 #include <linux/regmap.h>
9 #include <linux/regulator/consumer.h>
10 #include <linux/types.h>
11
12 #include "cs35l56.h"
13
14 static const struct reg_sequence cs35l56_patch[] = {
15 /* These are not reset by a soft-reset, so patch to defaults. */
16 { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
17 { CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 },
18 { CS35L56_MAIN_POSTURE_NUMBER, 0x00000000 },
19 };
20
cs35l56_set_patch(struct cs35l56_base * cs35l56_base)21 int cs35l56_set_patch(struct cs35l56_base *cs35l56_base)
22 {
23 return regmap_register_patch(cs35l56_base->regmap, cs35l56_patch,
24 ARRAY_SIZE(cs35l56_patch));
25 }
26 EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
27
28 static const struct reg_default cs35l56_reg_defaults[] = {
29 { CS35L56_ASP1_ENABLES1, 0x00000000 },
30 { CS35L56_ASP1_CONTROL1, 0x00000028 },
31 { CS35L56_ASP1_CONTROL2, 0x18180200 },
32 { CS35L56_ASP1_CONTROL3, 0x00000002 },
33 { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 },
34 { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 },
35 { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 },
36 { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 },
37
38 /* no defaults for ASP1TX mixer */
39
40 { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 },
41 { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 },
42 { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 },
43 { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 },
44 { CS35L56_IRQ1_CFG, 0x00000000 },
45 { CS35L56_IRQ1_MASK_1, 0x83ffffff },
46 { CS35L56_IRQ1_MASK_2, 0xffff7fff },
47 { CS35L56_IRQ1_MASK_4, 0xe0ffffff },
48 { CS35L56_IRQ1_MASK_8, 0xfc000fff },
49 { CS35L56_IRQ1_MASK_18, 0x1f7df0ff },
50 { CS35L56_IRQ1_MASK_20, 0x15c00000 },
51 { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
52 { CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 },
53 { CS35L56_MAIN_POSTURE_NUMBER, 0x00000000 },
54 };
55
cs35l56_is_dsp_memory(unsigned int reg)56 static bool cs35l56_is_dsp_memory(unsigned int reg)
57 {
58 switch (reg) {
59 case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
60 case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095:
61 case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191:
62 case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
63 case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070:
64 case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141:
65 case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
66 return true;
67 default:
68 return false;
69 }
70 }
71
cs35l56_readable_reg(struct device * dev,unsigned int reg)72 static bool cs35l56_readable_reg(struct device *dev, unsigned int reg)
73 {
74 switch (reg) {
75 case CS35L56_DEVID:
76 case CS35L56_REVID:
77 case CS35L56_RELID:
78 case CS35L56_OTPID:
79 case CS35L56_SFT_RESET:
80 case CS35L56_GLOBAL_ENABLES:
81 case CS35L56_BLOCK_ENABLES:
82 case CS35L56_BLOCK_ENABLES2:
83 case CS35L56_REFCLK_INPUT:
84 case CS35L56_GLOBAL_SAMPLE_RATE:
85 case CS35L56_ASP1_ENABLES1:
86 case CS35L56_ASP1_CONTROL1:
87 case CS35L56_ASP1_CONTROL2:
88 case CS35L56_ASP1_CONTROL3:
89 case CS35L56_ASP1_FRAME_CONTROL1:
90 case CS35L56_ASP1_FRAME_CONTROL5:
91 case CS35L56_ASP1_DATA_CONTROL1:
92 case CS35L56_ASP1_DATA_CONTROL5:
93 case CS35L56_DACPCM1_INPUT:
94 case CS35L56_DACPCM2_INPUT:
95 case CS35L56_ASP1TX1_INPUT:
96 case CS35L56_ASP1TX2_INPUT:
97 case CS35L56_ASP1TX3_INPUT:
98 case CS35L56_ASP1TX4_INPUT:
99 case CS35L56_DSP1RX1_INPUT:
100 case CS35L56_DSP1RX2_INPUT:
101 case CS35L56_SWIRE_DP3_CH1_INPUT:
102 case CS35L56_SWIRE_DP3_CH2_INPUT:
103 case CS35L56_SWIRE_DP3_CH3_INPUT:
104 case CS35L56_SWIRE_DP3_CH4_INPUT:
105 case CS35L56_IRQ1_CFG:
106 case CS35L56_IRQ1_STATUS:
107 case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
108 case CS35L56_IRQ1_EINT_18:
109 case CS35L56_IRQ1_EINT_20:
110 case CS35L56_IRQ1_MASK_1:
111 case CS35L56_IRQ1_MASK_2:
112 case CS35L56_IRQ1_MASK_4:
113 case CS35L56_IRQ1_MASK_8:
114 case CS35L56_IRQ1_MASK_18:
115 case CS35L56_IRQ1_MASK_20:
116 case CS35L56_DSP_VIRTUAL1_MBOX_1:
117 case CS35L56_DSP_VIRTUAL1_MBOX_2:
118 case CS35L56_DSP_VIRTUAL1_MBOX_3:
119 case CS35L56_DSP_VIRTUAL1_MBOX_4:
120 case CS35L56_DSP_VIRTUAL1_MBOX_5:
121 case CS35L56_DSP_VIRTUAL1_MBOX_6:
122 case CS35L56_DSP_VIRTUAL1_MBOX_7:
123 case CS35L56_DSP_VIRTUAL1_MBOX_8:
124 case CS35L56_DSP_RESTRICT_STS1:
125 case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
126 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
127 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
128 case CS35L56_DSP1_SCRATCH1:
129 case CS35L56_DSP1_SCRATCH2:
130 case CS35L56_DSP1_SCRATCH3:
131 case CS35L56_DSP1_SCRATCH4:
132 return true;
133 default:
134 return cs35l56_is_dsp_memory(reg);
135 }
136 }
137
cs35l56_precious_reg(struct device * dev,unsigned int reg)138 static bool cs35l56_precious_reg(struct device *dev, unsigned int reg)
139 {
140 switch (reg) {
141 case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
142 case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
143 case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
144 return true;
145 default:
146 return false;
147 }
148 }
149
cs35l56_volatile_reg(struct device * dev,unsigned int reg)150 static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
151 {
152 switch (reg) {
153 case CS35L56_DEVID:
154 case CS35L56_REVID:
155 case CS35L56_RELID:
156 case CS35L56_OTPID:
157 case CS35L56_SFT_RESET:
158 case CS35L56_GLOBAL_ENABLES: /* owned by firmware */
159 case CS35L56_BLOCK_ENABLES: /* owned by firmware */
160 case CS35L56_BLOCK_ENABLES2: /* owned by firmware */
161 case CS35L56_REFCLK_INPUT: /* owned by firmware */
162 case CS35L56_GLOBAL_SAMPLE_RATE: /* owned by firmware */
163 case CS35L56_DACPCM1_INPUT: /* owned by firmware */
164 case CS35L56_DACPCM2_INPUT: /* owned by firmware */
165 case CS35L56_DSP1RX1_INPUT: /* owned by firmware */
166 case CS35L56_DSP1RX2_INPUT: /* owned by firmware */
167 case CS35L56_IRQ1_STATUS:
168 case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
169 case CS35L56_IRQ1_EINT_18:
170 case CS35L56_IRQ1_EINT_20:
171 case CS35L56_DSP_VIRTUAL1_MBOX_1:
172 case CS35L56_DSP_VIRTUAL1_MBOX_2:
173 case CS35L56_DSP_VIRTUAL1_MBOX_3:
174 case CS35L56_DSP_VIRTUAL1_MBOX_4:
175 case CS35L56_DSP_VIRTUAL1_MBOX_5:
176 case CS35L56_DSP_VIRTUAL1_MBOX_6:
177 case CS35L56_DSP_VIRTUAL1_MBOX_7:
178 case CS35L56_DSP_VIRTUAL1_MBOX_8:
179 case CS35L56_DSP_RESTRICT_STS1:
180 case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
181 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
182 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
183 case CS35L56_DSP1_SCRATCH1:
184 case CS35L56_DSP1_SCRATCH2:
185 case CS35L56_DSP1_SCRATCH3:
186 case CS35L56_DSP1_SCRATCH4:
187 return true;
188 case CS35L56_MAIN_RENDER_USER_MUTE:
189 case CS35L56_MAIN_RENDER_USER_VOLUME:
190 case CS35L56_MAIN_POSTURE_NUMBER:
191 return false;
192 default:
193 return cs35l56_is_dsp_memory(reg);
194 }
195 }
196
197 /*
198 * The firmware boot sequence can overwrite the ASP1 config registers so that
199 * they don't match regmap's view of their values. Rewrite the values from the
200 * regmap cache into the hardware registers.
201 */
cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base * cs35l56_base)202 int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
203 {
204 struct reg_sequence asp1_regs[] = {
205 { .reg = CS35L56_ASP1_ENABLES1 },
206 { .reg = CS35L56_ASP1_CONTROL1 },
207 { .reg = CS35L56_ASP1_CONTROL2 },
208 { .reg = CS35L56_ASP1_CONTROL3 },
209 { .reg = CS35L56_ASP1_FRAME_CONTROL1 },
210 { .reg = CS35L56_ASP1_FRAME_CONTROL5 },
211 { .reg = CS35L56_ASP1_DATA_CONTROL1 },
212 { .reg = CS35L56_ASP1_DATA_CONTROL5 },
213 };
214 int i, ret;
215
216 /* Read values from regmap cache into a write sequence */
217 for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) {
218 ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def);
219 if (ret)
220 goto err;
221 }
222
223 /* Write the values cache-bypassed so that they will be written to silicon */
224 ret = regmap_multi_reg_write_bypassed(cs35l56_base->regmap, asp1_regs,
225 ARRAY_SIZE(asp1_regs));
226 if (ret)
227 goto err;
228
229 return 0;
230
231 err:
232 dev_err(cs35l56_base->dev, "Failed to sync ASP1 registers: %d\n", ret);
233
234 return ret;
235 }
236 EXPORT_SYMBOL_NS_GPL(cs35l56_force_sync_asp1_registers_from_cache, SND_SOC_CS35L56_SHARED);
237
cs35l56_mbox_send(struct cs35l56_base * cs35l56_base,unsigned int command)238 int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command)
239 {
240 unsigned int val;
241 int ret;
242
243 regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command);
244 ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
245 val, (val == 0),
246 CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US);
247 if (ret) {
248 dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret);
249 return ret;
250 }
251
252 return 0;
253 }
254 EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED);
255
cs35l56_firmware_shutdown(struct cs35l56_base * cs35l56_base)256 int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)
257 {
258 int ret;
259 unsigned int reg;
260 unsigned int val;
261
262 ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN);
263 if (ret)
264 return ret;
265
266 if (cs35l56_base->rev < CS35L56_REVID_B0)
267 reg = CS35L56_DSP1_PM_CUR_STATE_A1;
268 else
269 reg = CS35L56_DSP1_PM_CUR_STATE;
270
271 ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg,
272 val, (val == CS35L56_HALO_STATE_SHUTDOWN),
273 CS35L56_HALO_STATE_POLL_US,
274 CS35L56_HALO_STATE_TIMEOUT_US);
275 if (ret < 0)
276 dev_err(cs35l56_base->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n",
277 val, ret);
278 return ret;
279 }
280 EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED);
281
cs35l56_wait_for_firmware_boot(struct cs35l56_base * cs35l56_base)282 int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
283 {
284 unsigned int reg;
285 unsigned int val;
286 int read_ret, poll_ret;
287
288 if (cs35l56_base->rev < CS35L56_REVID_B0)
289 reg = CS35L56_DSP1_HALO_STATE_A1;
290 else
291 reg = CS35L56_DSP1_HALO_STATE;
292
293 /*
294 * This can't be a regmap_read_poll_timeout() because cs35l56 will NAK
295 * I2C until it has booted which would terminate the poll
296 */
297 poll_ret = read_poll_timeout(regmap_read, read_ret,
298 (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
299 CS35L56_HALO_STATE_POLL_US,
300 CS35L56_HALO_STATE_TIMEOUT_US,
301 false,
302 cs35l56_base->regmap, reg, &val);
303
304 if (poll_ret) {
305 dev_err(cs35l56_base->dev, "Firmware boot timed out(%d): HALO_STATE=%#x\n",
306 read_ret, val);
307 return -EIO;
308 }
309
310 return 0;
311 }
312 EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED);
313
cs35l56_wait_control_port_ready(void)314 void cs35l56_wait_control_port_ready(void)
315 {
316 /* Wait for control port to be ready (datasheet tIRS). */
317 usleep_range(CS35L56_CONTROL_PORT_READY_US, 2 * CS35L56_CONTROL_PORT_READY_US);
318 }
319 EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, SND_SOC_CS35L56_SHARED);
320
cs35l56_wait_min_reset_pulse(void)321 void cs35l56_wait_min_reset_pulse(void)
322 {
323 /* Satisfy minimum reset pulse width spec */
324 usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US);
325 }
326 EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, SND_SOC_CS35L56_SHARED);
327
328 static const struct reg_sequence cs35l56_system_reset_seq[] = {
329 REG_SEQ0(CS35L56_DSP1_HALO_STATE, 0),
330 REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),
331 };
332
cs35l56_system_reset(struct cs35l56_base * cs35l56_base,bool is_soundwire)333 void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
334 {
335 /*
336 * Must enter cache-only first so there can't be any more register
337 * accesses other than the controlled system reset sequence below.
338 */
339 regcache_cache_only(cs35l56_base->regmap, true);
340 regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
341 cs35l56_system_reset_seq,
342 ARRAY_SIZE(cs35l56_system_reset_seq));
343
344 /* On SoundWire the registers won't be accessible until it re-enumerates. */
345 if (is_soundwire)
346 return;
347
348 cs35l56_wait_control_port_ready();
349 regcache_cache_only(cs35l56_base->regmap, false);
350 }
351 EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
352
cs35l56_irq_request(struct cs35l56_base * cs35l56_base,int irq)353 int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
354 {
355 int ret;
356
357 if (!irq)
358 return 0;
359
360 ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq,
361 IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
362 "cs35l56", cs35l56_base);
363 if (!ret)
364 cs35l56_base->irq = irq;
365 else
366 dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret);
367
368 return ret;
369 }
370 EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_SHARED);
371
cs35l56_irq(int irq,void * data)372 irqreturn_t cs35l56_irq(int irq, void *data)
373 {
374 struct cs35l56_base *cs35l56_base = data;
375 unsigned int status1 = 0, status8 = 0, status20 = 0;
376 unsigned int mask1, mask8, mask20;
377 unsigned int val;
378 int rv;
379
380 irqreturn_t ret = IRQ_NONE;
381
382 if (!cs35l56_base->init_done)
383 return IRQ_NONE;
384
385 mutex_lock(&cs35l56_base->irq_lock);
386
387 rv = pm_runtime_resume_and_get(cs35l56_base->dev);
388 if (rv < 0) {
389 dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv);
390 goto err_unlock;
391 }
392
393 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);
394 if ((val & CS35L56_IRQ1_STS_MASK) == 0) {
395 dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n");
396 goto err;
397 }
398
399 /* Ack interrupts */
400 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, &status1);
401 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, &mask1);
402 status1 &= ~mask1;
403 regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, status1);
404
405 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, &status8);
406 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, &mask8);
407 status8 &= ~mask8;
408 regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, status8);
409
410 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20);
411 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20);
412 status20 &= ~mask20;
413 /* We don't want EINT20 but they default to unmasked: force mask */
414 regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
415
416 dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8);
417
418 /* Check to see if unmasked bits are active */
419 if (!status1 && !status8 && !status20)
420 goto err;
421
422 if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK)
423 dev_crit(cs35l56_base->dev, "Amp short error\n");
424
425 if (status8 & CS35L56_TEMP_ERR_EINT1_MASK)
426 dev_crit(cs35l56_base->dev, "Overtemp error\n");
427
428 ret = IRQ_HANDLED;
429
430 err:
431 pm_runtime_put(cs35l56_base->dev);
432 err_unlock:
433 mutex_unlock(&cs35l56_base->irq_lock);
434
435 return ret;
436 }
437 EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_SHARED);
438
cs35l56_is_fw_reload_needed(struct cs35l56_base * cs35l56_base)439 int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)
440 {
441 unsigned int val;
442 int ret;
443
444 /* Nothing to re-patch if we haven't done any patching yet. */
445 if (!cs35l56_base->fw_patched)
446 return false;
447
448 /*
449 * If we have control of RESET we will have asserted it so the firmware
450 * will need re-patching.
451 */
452 if (cs35l56_base->reset_gpio)
453 return true;
454
455 /*
456 * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so
457 * can't be used here to test for memory retention.
458 * Assume that tuning must be re-loaded.
459 */
460 if (cs35l56_base->secured)
461 return true;
462
463 ret = pm_runtime_resume_and_get(cs35l56_base->dev);
464 if (ret) {
465 dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret);
466 return ret;
467 }
468
469 ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &val);
470 if (ret)
471 dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret);
472 else
473 ret = !!(val & CS35L56_FIRMWARE_MISSING);
474
475 pm_runtime_put_autosuspend(cs35l56_base->dev);
476
477 return ret;
478 }
479 EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED);
480
481 static const struct reg_sequence cs35l56_hibernate_seq[] = {
482 /* This must be the last register access */
483 REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW),
484 };
485
486 static const struct reg_sequence cs35l56_hibernate_wake_seq[] = {
487 REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP),
488 };
489
cs35l56_runtime_suspend_common(struct cs35l56_base * cs35l56_base)490 int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base)
491 {
492 unsigned int val;
493 int ret;
494
495 if (!cs35l56_base->init_done)
496 return 0;
497
498 /* Firmware must have entered a power-save state */
499 ret = regmap_read_poll_timeout(cs35l56_base->regmap,
500 CS35L56_TRANSDUCER_ACTUAL_PS,
501 val, (val >= CS35L56_PS3),
502 CS35L56_PS3_POLL_US,
503 CS35L56_PS3_TIMEOUT_US);
504 if (ret)
505 dev_warn(cs35l56_base->dev, "PS3 wait failed: %d\n", ret);
506
507 /* Clear BOOT_DONE so it can be used to detect a reboot */
508 regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);
509
510 if (!cs35l56_base->can_hibernate) {
511 regcache_cache_only(cs35l56_base->regmap, true);
512 dev_dbg(cs35l56_base->dev, "Suspended: no hibernate");
513
514 return 0;
515 }
516
517 /*
518 * Enable auto-hibernate. If it is woken by some other wake source
519 * it will automatically return to hibernate.
520 */
521 cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE);
522
523 /*
524 * Must enter cache-only first so there can't be any more register
525 * accesses other than the controlled hibernate sequence below.
526 */
527 regcache_cache_only(cs35l56_base->regmap, true);
528
529 regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
530 cs35l56_hibernate_seq,
531 ARRAY_SIZE(cs35l56_hibernate_seq));
532
533 dev_dbg(cs35l56_base->dev, "Suspended: hibernate");
534
535 return 0;
536 }
537 EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, SND_SOC_CS35L56_SHARED);
538
cs35l56_runtime_resume_common(struct cs35l56_base * cs35l56_base,bool is_soundwire)539 int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire)
540 {
541 unsigned int val;
542 int ret;
543
544 if (!cs35l56_base->init_done)
545 return 0;
546
547 if (!cs35l56_base->can_hibernate)
548 goto out_sync;
549
550 if (!is_soundwire) {
551 /*
552 * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C.
553 * Must be done before releasing cache-only.
554 */
555 regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
556 cs35l56_hibernate_wake_seq,
557 ARRAY_SIZE(cs35l56_hibernate_wake_seq));
558
559 cs35l56_wait_control_port_ready();
560 }
561
562 out_sync:
563 regcache_cache_only(cs35l56_base->regmap, false);
564
565 ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
566 if (ret) {
567 dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);
568 goto err;
569 }
570
571 ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
572 if (ret)
573 goto err;
574
575 /* BOOT_DONE will be 1 if the amp reset */
576 regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, &val);
577 if (val & CS35L56_OTP_BOOT_DONE_MASK) {
578 dev_dbg(cs35l56_base->dev, "Registers reset in suspend\n");
579 regcache_mark_dirty(cs35l56_base->regmap);
580 }
581
582 regcache_sync(cs35l56_base->regmap);
583
584 dev_dbg(cs35l56_base->dev, "Resumed");
585
586 return 0;
587
588 err:
589 regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
590 CS35L56_MBOX_CMD_HIBERNATE_NOW);
591
592 regcache_cache_only(cs35l56_base->regmap, true);
593
594 return ret;
595 }
596 EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED);
597
598 static const struct cs_dsp_region cs35l56_dsp1_regions[] = {
599 { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 },
600 { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 },
601 { .type = WMFW_HALO_YM_PACKED, .base = CS35L56_DSP1_YMEM_PACKED_0 },
602 { .type = WMFW_ADSP2_XM, .base = CS35L56_DSP1_XMEM_UNPACKED24_0 },
603 { .type = WMFW_ADSP2_YM, .base = CS35L56_DSP1_YMEM_UNPACKED24_0 },
604 };
605
cs35l56_init_cs_dsp(struct cs35l56_base * cs35l56_base,struct cs_dsp * cs_dsp)606 void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp)
607 {
608 cs_dsp->num = 1;
609 cs_dsp->type = WMFW_HALO;
610 cs_dsp->rev = 0;
611 cs_dsp->dev = cs35l56_base->dev;
612 cs_dsp->regmap = cs35l56_base->regmap;
613 cs_dsp->base = CS35L56_DSP1_CORE_BASE;
614 cs_dsp->base_sysinfo = CS35L56_DSP1_SYS_INFO_ID;
615 cs_dsp->mem = cs35l56_dsp1_regions;
616 cs_dsp->num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);
617 cs_dsp->no_core_startstop = true;
618 }
619 EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED);
620
cs35l56_hw_init(struct cs35l56_base * cs35l56_base)621 int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
622 {
623 int ret;
624 unsigned int devid, revid, otpid, secured;
625
626 /*
627 * If the system is not using a reset_gpio then issue a
628 * dummy read to force a wakeup.
629 */
630 if (!cs35l56_base->reset_gpio)
631 regmap_read(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid);
632
633 cs35l56_wait_control_port_ready();
634
635 /*
636 * The HALO_STATE register is in different locations on Ax and B0
637 * devices so the REVID needs to be determined before waiting for the
638 * firmware to boot.
639 */
640 ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid);
641 if (ret < 0) {
642 dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
643 return ret;
644 }
645 cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK);
646
647 ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
648 if (ret)
649 return ret;
650
651 ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid);
652 if (ret < 0) {
653 dev_err(cs35l56_base->dev, "Get Device ID failed\n");
654 return ret;
655 }
656 devid &= CS35L56_DEVID_MASK;
657
658 switch (devid) {
659 case 0x35A56:
660 break;
661 default:
662 dev_err(cs35l56_base->dev, "Unknown device %x\n", devid);
663 return ret;
664 }
665
666 ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
667 if (ret) {
668 dev_err(cs35l56_base->dev, "Get Secure status failed\n");
669 return ret;
670 }
671
672 /* When any bus is restricted treat the device as secured */
673 if (secured & CS35L56_RESTRICTED_MASK)
674 cs35l56_base->secured = true;
675
676 ret = regmap_read(cs35l56_base->regmap, CS35L56_OTPID, &otpid);
677 if (ret < 0) {
678 dev_err(cs35l56_base->dev, "Get OTP ID failed\n");
679 return ret;
680 }
681
682 dev_info(cs35l56_base->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n",
683 cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid);
684
685 /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
686 regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
687 regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1,
688 CS35L56_AMP_SHORT_ERR_EINT1_MASK,
689 0);
690 regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8,
691 CS35L56_TEMP_ERR_EINT1_MASK,
692 0);
693
694 return 0;
695 }
696 EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);
697
698 static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {
699 [0x0C] = 128000,
700 [0x0F] = 256000,
701 [0x11] = 384000,
702 [0x12] = 512000,
703 [0x15] = 768000,
704 [0x17] = 1024000,
705 [0x1A] = 1500000,
706 [0x1B] = 1536000,
707 [0x1C] = 2000000,
708 [0x1D] = 2048000,
709 [0x1E] = 2400000,
710 [0x20] = 3000000,
711 [0x21] = 3072000,
712 [0x23] = 4000000,
713 [0x24] = 4096000,
714 [0x25] = 4800000,
715 [0x27] = 6000000,
716 [0x28] = 6144000,
717 [0x29] = 6250000,
718 [0x2A] = 6400000,
719 [0x2E] = 8000000,
720 [0x2F] = 8192000,
721 [0x30] = 9600000,
722 [0x32] = 12000000,
723 [0x33] = 12288000,
724 [0x37] = 13500000,
725 [0x38] = 19200000,
726 [0x39] = 22579200,
727 [0x3B] = 24576000,
728 };
729
cs35l56_get_bclk_freq_id(unsigned int freq)730 int cs35l56_get_bclk_freq_id(unsigned int freq)
731 {
732 int i;
733
734 if (freq == 0)
735 return -EINVAL;
736
737 /* The BCLK frequency must be a valid PLL REFCLK */
738 for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) {
739 if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq)
740 return i;
741 }
742
743 return -EINVAL;
744 }
745 EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED);
746
747 static const char * const cs35l56_supplies[/* auto-sized */] = {
748 "VDD_P",
749 "VDD_IO",
750 "VDD_A",
751 };
752
cs35l56_fill_supply_names(struct regulator_bulk_data * data)753 void cs35l56_fill_supply_names(struct regulator_bulk_data *data)
754 {
755 int i;
756
757 BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES);
758 for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++)
759 data[i].supply = cs35l56_supplies[i];
760 }
761 EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED);
762
763 const char * const cs35l56_tx_input_texts[] = {
764 "None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH",
765 "VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4",
766 "DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON",
767 "INTERPOLATOR", "SDW1RX1", "SDW1RX2",
768 };
769 EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED);
770
771 const unsigned int cs35l56_tx_input_values[] = {
772 CS35L56_INPUT_SRC_NONE,
773 CS35L56_INPUT_SRC_ASP1RX1,
774 CS35L56_INPUT_SRC_ASP1RX2,
775 CS35L56_INPUT_SRC_VMON,
776 CS35L56_INPUT_SRC_IMON,
777 CS35L56_INPUT_SRC_ERR_VOL,
778 CS35L56_INPUT_SRC_CLASSH,
779 CS35L56_INPUT_SRC_VDDBMON,
780 CS35L56_INPUT_SRC_VBSTMON,
781 CS35L56_INPUT_SRC_DSP1TX1,
782 CS35L56_INPUT_SRC_DSP1TX2,
783 CS35L56_INPUT_SRC_DSP1TX3,
784 CS35L56_INPUT_SRC_DSP1TX4,
785 CS35L56_INPUT_SRC_DSP1TX5,
786 CS35L56_INPUT_SRC_DSP1TX6,
787 CS35L56_INPUT_SRC_DSP1TX7,
788 CS35L56_INPUT_SRC_DSP1TX8,
789 CS35L56_INPUT_SRC_TEMPMON,
790 CS35L56_INPUT_SRC_INTERPOLATOR,
791 CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1,
792 CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2,
793 };
794 EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED);
795
796 struct regmap_config cs35l56_regmap_i2c = {
797 .reg_bits = 32,
798 .val_bits = 32,
799 .reg_stride = 4,
800 .reg_format_endian = REGMAP_ENDIAN_BIG,
801 .val_format_endian = REGMAP_ENDIAN_BIG,
802 .max_register = CS35L56_DSP1_PMEM_5114,
803 .reg_defaults = cs35l56_reg_defaults,
804 .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
805 .volatile_reg = cs35l56_volatile_reg,
806 .readable_reg = cs35l56_readable_reg,
807 .precious_reg = cs35l56_precious_reg,
808 .cache_type = REGCACHE_MAPLE,
809 };
810 EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);
811
812 struct regmap_config cs35l56_regmap_spi = {
813 .reg_bits = 32,
814 .val_bits = 32,
815 .pad_bits = 16,
816 .reg_stride = 4,
817 .reg_format_endian = REGMAP_ENDIAN_BIG,
818 .val_format_endian = REGMAP_ENDIAN_BIG,
819 .max_register = CS35L56_DSP1_PMEM_5114,
820 .reg_defaults = cs35l56_reg_defaults,
821 .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
822 .volatile_reg = cs35l56_volatile_reg,
823 .readable_reg = cs35l56_readable_reg,
824 .precious_reg = cs35l56_precious_reg,
825 .cache_type = REGCACHE_MAPLE,
826 };
827 EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);
828
829 struct regmap_config cs35l56_regmap_sdw = {
830 .reg_bits = 32,
831 .val_bits = 32,
832 .reg_stride = 4,
833 .reg_format_endian = REGMAP_ENDIAN_LITTLE,
834 .val_format_endian = REGMAP_ENDIAN_BIG,
835 .max_register = CS35L56_DSP1_PMEM_5114,
836 .reg_defaults = cs35l56_reg_defaults,
837 .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
838 .volatile_reg = cs35l56_volatile_reg,
839 .readable_reg = cs35l56_readable_reg,
840 .precious_reg = cs35l56_precious_reg,
841 .cache_type = REGCACHE_MAPLE,
842 };
843 EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED);
844
845 MODULE_DESCRIPTION("ASoC CS35L56 Shared");
846 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
847 MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
848 MODULE_LICENSE("GPL");
849