@@ -195,6 +195,214 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
195195 }
196196}
197197
198+ int cs35l56_mbox_send (struct cs35l56_base * cs35l56_base , unsigned int command )
199+ {
200+ unsigned int val ;
201+ int ret ;
202+
203+ regmap_write (cs35l56_base -> regmap , CS35L56_DSP_VIRTUAL1_MBOX_1 , command );
204+ ret = regmap_read_poll_timeout (cs35l56_base -> regmap , CS35L56_DSP_VIRTUAL1_MBOX_1 ,
205+ val , (val == 0 ),
206+ CS35L56_MBOX_POLL_US , CS35L56_MBOX_TIMEOUT_US );
207+ if (ret ) {
208+ dev_warn (cs35l56_base -> dev , "MBOX command %#x failed: %d\n" , command , ret );
209+ return ret ;
210+ }
211+
212+ return 0 ;
213+ }
214+ EXPORT_SYMBOL_NS_GPL (cs35l56_mbox_send , SND_SOC_CS35L56_SHARED );
215+
216+ int cs35l56_wait_for_firmware_boot (struct cs35l56_base * cs35l56_base )
217+ {
218+ unsigned int reg ;
219+ unsigned int val ;
220+ int ret ;
221+
222+ if (cs35l56_base -> rev < CS35L56_REVID_B0 )
223+ reg = CS35L56_DSP1_HALO_STATE_A1 ;
224+ else
225+ reg = CS35L56_DSP1_HALO_STATE ;
226+
227+ ret = regmap_read_poll_timeout (cs35l56_base -> regmap , reg ,
228+ val ,
229+ (val < 0xFFFF ) && (val >= CS35L56_HALO_STATE_BOOT_DONE ),
230+ CS35L56_HALO_STATE_POLL_US ,
231+ CS35L56_HALO_STATE_TIMEOUT_US );
232+
233+ if ((ret < 0 ) && (ret != - ETIMEDOUT )) {
234+ dev_err (cs35l56_base -> dev , "Failed to read HALO_STATE: %d\n" , ret );
235+ return ret ;
236+ }
237+
238+ if ((ret == - ETIMEDOUT ) || (val != CS35L56_HALO_STATE_BOOT_DONE )) {
239+ dev_err (cs35l56_base -> dev , "Firmware boot fail: HALO_STATE=%#x\n" , val );
240+ return - EIO ;
241+ }
242+
243+ return 0 ;
244+ }
245+ EXPORT_SYMBOL_NS_GPL (cs35l56_wait_for_firmware_boot , SND_SOC_CS35L56_SHARED );
246+
247+ void cs35l56_wait_min_reset_pulse (void )
248+ {
249+ /* Satisfy minimum reset pulse width spec */
250+ usleep_range (CS35L56_RESET_PULSE_MIN_US , 2 * CS35L56_RESET_PULSE_MIN_US );
251+ }
252+ EXPORT_SYMBOL_NS_GPL (cs35l56_wait_min_reset_pulse , SND_SOC_CS35L56_SHARED );
253+
254+ static const struct reg_sequence cs35l56_system_reset_seq [] = {
255+ REG_SEQ0 (CS35L56_DSP_VIRTUAL1_MBOX_1 , CS35L56_MBOX_CMD_SYSTEM_RESET ),
256+ };
257+
258+ void cs35l56_system_reset (struct cs35l56_base * cs35l56_base , bool is_soundwire )
259+ {
260+ /*
261+ * Must enter cache-only first so there can't be any more register
262+ * accesses other than the controlled system reset sequence below.
263+ */
264+ regcache_cache_only (cs35l56_base -> regmap , true);
265+ regmap_multi_reg_write_bypassed (cs35l56_base -> regmap ,
266+ cs35l56_system_reset_seq ,
267+ ARRAY_SIZE (cs35l56_system_reset_seq ));
268+
269+ /* On SoundWire the registers won't be accessible until it re-enumerates. */
270+ if (is_soundwire )
271+ return ;
272+
273+ usleep_range (CS35L56_CONTROL_PORT_READY_US , CS35L56_CONTROL_PORT_READY_US + 400 );
274+ regcache_cache_only (cs35l56_base -> regmap , false);
275+ }
276+ EXPORT_SYMBOL_NS_GPL (cs35l56_system_reset , SND_SOC_CS35L56_SHARED );
277+
278+ int cs35l56_irq_request (struct cs35l56_base * cs35l56_base , int irq )
279+ {
280+ int ret ;
281+
282+ if (!irq )
283+ return 0 ;
284+
285+ ret = devm_request_threaded_irq (cs35l56_base -> dev , irq , NULL , cs35l56_irq ,
286+ IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW ,
287+ "cs35l56" , cs35l56_base );
288+ if (!ret )
289+ cs35l56_base -> irq = irq ;
290+ else
291+ dev_err (cs35l56_base -> dev , "Failed to get IRQ: %d\n" , ret );
292+
293+ return ret ;
294+ }
295+ EXPORT_SYMBOL_NS_GPL (cs35l56_irq_request , SND_SOC_CS35L56_SHARED );
296+
297+ irqreturn_t cs35l56_irq (int irq , void * data )
298+ {
299+ struct cs35l56_base * cs35l56_base = data ;
300+ unsigned int status1 = 0 , status8 = 0 , status20 = 0 ;
301+ unsigned int mask1 , mask8 , mask20 ;
302+ unsigned int val ;
303+ int rv ;
304+
305+ irqreturn_t ret = IRQ_NONE ;
306+
307+ if (!cs35l56_base -> init_done )
308+ return IRQ_NONE ;
309+
310+ mutex_lock (& cs35l56_base -> irq_lock );
311+
312+ rv = pm_runtime_resume_and_get (cs35l56_base -> dev );
313+ if (rv < 0 ) {
314+ dev_err (cs35l56_base -> dev , "irq: failed to get pm_runtime: %d\n" , rv );
315+ goto err_unlock ;
316+ }
317+
318+ regmap_read (cs35l56_base -> regmap , CS35L56_IRQ1_STATUS , & val );
319+ if ((val & CS35L56_IRQ1_STS_MASK ) == 0 ) {
320+ dev_dbg (cs35l56_base -> dev , "Spurious IRQ: no pending interrupt\n" );
321+ goto err ;
322+ }
323+
324+ /* Ack interrupts */
325+ regmap_read (cs35l56_base -> regmap , CS35L56_IRQ1_EINT_1 , & status1 );
326+ regmap_read (cs35l56_base -> regmap , CS35L56_IRQ1_MASK_1 , & mask1 );
327+ status1 &= ~mask1 ;
328+ regmap_write (cs35l56_base -> regmap , CS35L56_IRQ1_EINT_1 , status1 );
329+
330+ regmap_read (cs35l56_base -> regmap , CS35L56_IRQ1_EINT_8 , & status8 );
331+ regmap_read (cs35l56_base -> regmap , CS35L56_IRQ1_MASK_8 , & mask8 );
332+ status8 &= ~mask8 ;
333+ regmap_write (cs35l56_base -> regmap , CS35L56_IRQ1_EINT_8 , status8 );
334+
335+ regmap_read (cs35l56_base -> regmap , CS35L56_IRQ1_EINT_20 , & status20 );
336+ regmap_read (cs35l56_base -> regmap , CS35L56_IRQ1_MASK_20 , & mask20 );
337+ status20 &= ~mask20 ;
338+ /* We don't want EINT20 but they default to unmasked: force mask */
339+ regmap_write (cs35l56_base -> regmap , CS35L56_IRQ1_MASK_20 , 0xffffffff );
340+
341+ dev_dbg (cs35l56_base -> dev , "%s: %#x %#x\n" , __func__ , status1 , status8 );
342+
343+ /* Check to see if unmasked bits are active */
344+ if (!status1 && !status8 && !status20 )
345+ goto err ;
346+
347+ if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK )
348+ dev_crit (cs35l56_base -> dev , "Amp short error\n" );
349+
350+ if (status8 & CS35L56_TEMP_ERR_EINT1_MASK )
351+ dev_crit (cs35l56_base -> dev , "Overtemp error\n" );
352+
353+ ret = IRQ_HANDLED ;
354+
355+ err :
356+ pm_runtime_put (cs35l56_base -> dev );
357+ err_unlock :
358+ mutex_unlock (& cs35l56_base -> irq_lock );
359+
360+ return ret ;
361+ }
362+ EXPORT_SYMBOL_NS_GPL (cs35l56_irq , SND_SOC_CS35L56_SHARED );
363+
364+ int cs35l56_is_fw_reload_needed (struct cs35l56_base * cs35l56_base )
365+ {
366+ unsigned int val ;
367+ int ret ;
368+
369+ /* Nothing to re-patch if we haven't done any patching yet. */
370+ if (!cs35l56_base -> fw_patched )
371+ return false;
372+
373+ /*
374+ * If we have control of RESET we will have asserted it so the firmware
375+ * will need re-patching.
376+ */
377+ if (cs35l56_base -> reset_gpio )
378+ return true;
379+
380+ /*
381+ * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so
382+ * can't be used here to test for memory retention.
383+ * Assume that tuning must be re-loaded.
384+ */
385+ if (cs35l56_base -> secured )
386+ return true;
387+
388+ ret = pm_runtime_resume_and_get (cs35l56_base -> dev );
389+ if (ret ) {
390+ dev_err (cs35l56_base -> dev , "Failed to runtime_get: %d\n" , ret );
391+ return ret ;
392+ }
393+
394+ ret = regmap_read (cs35l56_base -> regmap , CS35L56_PROTECTION_STATUS , & val );
395+ if (ret )
396+ dev_err (cs35l56_base -> dev , "Failed to read PROTECTION_STATUS: %d\n" , ret );
397+ else
398+ ret = !!(val & CS35L56_FIRMWARE_MISSING );
399+
400+ pm_runtime_put_autosuspend (cs35l56_base -> dev );
401+
402+ return ret ;
403+ }
404+ EXPORT_SYMBOL_NS_GPL (cs35l56_is_fw_reload_needed , SND_SOC_CS35L56_SHARED );
405+
198406const struct cs_dsp_region cs35l56_dsp1_regions [] = {
199407 { .type = WMFW_HALO_PM_PACKED , .base = CS35L56_DSP1_PMEM_0 },
200408 { .type = WMFW_HALO_XM_PACKED , .base = CS35L56_DSP1_XMEM_PACKED_0 },
0 commit comments