Lines Matching +full:per +full:- +full:peripheral

1 // SPDX-License-Identifier: GPL-2.0-only
37 static int cs35l56_sdw_poll_mem_status(struct sdw_slave *peripheral, in cs35l56_sdw_poll_mem_status() argument
46 false, peripheral, CS35L56_SDW_MEM_ACCESS_STATUS); in cs35l56_sdw_poll_mem_status()
56 static int cs35l56_sdw_slow_read(struct sdw_slave *peripheral, unsigned int reg, in cs35l56_sdw_slow_read() argument
65 ret = cs35l56_sdw_poll_mem_status(peripheral, in cs35l56_sdw_slow_read()
69 dev_err(&peripheral->dev, "!CMD_IN_PROGRESS fail: %d\n", ret); in cs35l56_sdw_slow_read()
74 sdw_read_no_pm(peripheral, reg + i); in cs35l56_sdw_slow_read()
77 ret = cs35l56_sdw_poll_mem_status(peripheral, in cs35l56_sdw_slow_read()
81 dev_err(&peripheral->dev, "RDATA_RDY fail: %d\n", ret); in cs35l56_sdw_slow_read()
86 ret = sdw_nread_no_pm(peripheral, CS35L56_SDW_MEM_READ_DATA, in cs35l56_sdw_slow_read()
89 dev_err(&peripheral->dev, "Late read @%#x failed: %d\n", reg + i, ret); in cs35l56_sdw_slow_read()
99 static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf) in cs35l56_sdw_read_one() argument
103 ret = sdw_nread_no_pm(peripheral, reg, 4, (u8 *)buf); in cs35l56_sdw_read_one()
105 dev_err(&peripheral->dev, "Read failed @%#x:%d\n", reg, ret); in cs35l56_sdw_read_one()
118 struct sdw_slave *peripheral = context; in cs35l56_sdw_read() local
126 return cs35l56_sdw_slow_read(peripheral, reg, buf8, val_size); in cs35l56_sdw_read()
131 return cs35l56_sdw_read_one(peripheral, reg, val_buf); in cs35l56_sdw_read()
134 bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ in cs35l56_sdw_read()
138 ret = sdw_nread_no_pm(peripheral, reg, bytes, buf8); in cs35l56_sdw_read()
140 dev_err(&peripheral->dev, "Read failed @%#x..%#x:%d\n", in cs35l56_sdw_read()
141 reg, reg + bytes - 1, ret); in cs35l56_sdw_read()
146 val_size -= bytes; in cs35l56_sdw_read()
159 for (; nbytes > 0; nbytes -= 4) in cs35l56_swab_copy()
163 static int cs35l56_sdw_write_one(struct sdw_slave *peripheral, unsigned int reg, const void *buf) in cs35l56_sdw_write_one() argument
168 ret = sdw_nwrite_no_pm(peripheral, reg, 4, (u8 *)&val_le); in cs35l56_sdw_write_one()
170 dev_err(&peripheral->dev, "Write failed @%#x:%d\n", reg, ret); in cs35l56_sdw_write_one()
181 struct sdw_slave *peripheral = context; in cs35l56_sdw_gather_write() local
183 u32 val_le_buf[64]; /* Define u32 so it is 32-bit aligned */ in cs35l56_sdw_gather_write()
191 return cs35l56_sdw_write_one(peripheral, reg, src_be); in cs35l56_sdw_gather_write()
194 bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ in cs35l56_sdw_gather_write()
202 ret = sdw_nwrite_no_pm(peripheral, reg, bytes, (u8 *)val_le_buf); in cs35l56_sdw_gather_write()
204 dev_err(&peripheral->dev, "Write failed @%#x..%#x:%d\n", in cs35l56_sdw_gather_write()
205 reg, reg + bytes - 1, ret); in cs35l56_sdw_gather_write()
209 val_size -= bytes; in cs35l56_sdw_gather_write()
222 return cs35l56_sdw_gather_write(context, &src_buf[0], 4, &src_buf[4], val_size - 4); in cs35l56_sdw_write()
226 * Registers are big-endian on I2C and SPI but little-endian on SoundWire.
227 * Exported firmware controls are big-endian on I2C/SPI but little-endian on
228 * SoundWire. Firmware files are always big-endian and are opaque blobs.
229 * Present a big-endian regmap and hide the endianness swap, so that the ALSA
246 ret = sdw_read_no_pm(cs35l56->sdw_peripheral, SDW_SCP_DEVID_0); in cs35l56_sdw_set_cal_index()
250 cs35l56->base.cal_index = ret & 0xf; in cs35l56_sdw_set_cal_index()
255 static void cs35l56_sdw_init(struct sdw_slave *peripheral) in cs35l56_sdw_init() argument
257 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_init()
260 pm_runtime_get_noresume(cs35l56->base.dev); in cs35l56_sdw_init()
262 if (cs35l56->base.cal_index < 0) { in cs35l56_sdw_init()
270 regcache_cache_only(cs35l56->base.regmap, true); in cs35l56_sdw_init()
278 if (cs35l56->base.init_done) { in cs35l56_sdw_init()
280 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, in cs35l56_sdw_init()
285 pm_runtime_mark_last_busy(cs35l56->base.dev); in cs35l56_sdw_init()
286 pm_runtime_put_autosuspend(cs35l56->base.dev); in cs35l56_sdw_init()
289 static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, in cs35l56_sdw_interrupt() argument
292 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_interrupt()
296 dev_dbg(cs35l56->base.dev, "int control_port=%#x\n", status->control_port); in cs35l56_sdw_interrupt()
298 if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0) in cs35l56_sdw_interrupt()
303 * bus-reset before the queued work has run. in cs35l56_sdw_interrupt()
305 pm_runtime_get_noresume(cs35l56->base.dev); in cs35l56_sdw_interrupt()
309 * is required as per the SoundWire spec for interrupt status bits in cs35l56_sdw_interrupt()
311 * None of the interrupts are time-critical so use the in cs35l56_sdw_interrupt()
312 * power-efficient queue. in cs35l56_sdw_interrupt()
314 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_interrupt()
315 sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_interrupt()
316 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_interrupt()
317 queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work); in cs35l56_sdw_interrupt()
328 cs35l56_irq(-1, &cs35l56->base); in cs35l56_sdw_irq_work()
331 if (!cs35l56->sdw_irq_no_unmask) in cs35l56_sdw_irq_work()
332 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, in cs35l56_sdw_irq_work()
335 pm_runtime_put_autosuspend(cs35l56->base.dev); in cs35l56_sdw_irq_work()
338 static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) in cs35l56_sdw_read_prop() argument
340 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_read_prop()
341 struct sdw_slave_prop *prop = &peripheral->prop; in cs35l56_sdw_read_prop()
344 ports = devm_kcalloc(cs35l56->base.dev, 2, sizeof(*ports), GFP_KERNEL); in cs35l56_sdw_read_prop()
346 return -ENOMEM; in cs35l56_sdw_read_prop()
348 prop->source_ports = BIT(CS35L56_SDW1_CAPTURE_PORT); in cs35l56_sdw_read_prop()
349 prop->sink_ports = BIT(CS35L56_SDW1_PLAYBACK_PORT); in cs35l56_sdw_read_prop()
350 prop->paging_support = true; in cs35l56_sdw_read_prop()
351 prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; in cs35l56_sdw_read_prop()
352 prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | SDW_SCP_INT1_IMPL_DEF; in cs35l56_sdw_read_prop()
354 /* DP1 - playback */ in cs35l56_sdw_read_prop()
358 prop->sink_dpn_prop = &ports[0]; in cs35l56_sdw_read_prop()
360 /* DP3 - capture */ in cs35l56_sdw_read_prop()
364 prop->src_dpn_prop = &ports[1]; in cs35l56_sdw_read_prop()
369 static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, in cs35l56_sdw_update_status() argument
372 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_update_status()
376 dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__); in cs35l56_sdw_update_status()
377 if (cs35l56->sdw_attached) in cs35l56_sdw_update_status()
380 if (!cs35l56->base.init_done || cs35l56->soft_resetting) in cs35l56_sdw_update_status()
381 cs35l56_sdw_init(peripheral); in cs35l56_sdw_update_status()
383 cs35l56->sdw_attached = true; in cs35l56_sdw_update_status()
386 dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__); in cs35l56_sdw_update_status()
387 cs35l56->sdw_attached = false; in cs35l56_sdw_update_status()
396 static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, in cs35l56_sdw_clk_stop() argument
400 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_clk_stop()
402 dev_dbg(cs35l56->base.dev, "%s: mode:%d type:%d\n", __func__, mode, type); in cs35l56_sdw_clk_stop()
418 struct sdw_slave *peripheral = cs35l56->sdw_peripheral; in cs35l56_sdw_handle_unattach() local
420 if (peripheral->unattach_request) { in cs35l56_sdw_handle_unattach()
421 /* Cannot access registers until bus is re-initialized. */ in cs35l56_sdw_handle_unattach()
422 dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n"); in cs35l56_sdw_handle_unattach()
423 if (!wait_for_completion_timeout(&peripheral->initialization_complete, in cs35l56_sdw_handle_unattach()
425 dev_err(cs35l56->base.dev, "initialization_complete timed out\n"); in cs35l56_sdw_handle_unattach()
426 return -ETIMEDOUT; in cs35l56_sdw_handle_unattach()
429 peripheral->unattach_request = 0; in cs35l56_sdw_handle_unattach()
444 if (!cs35l56->base.init_done) in cs35l56_sdw_runtime_suspend()
447 return cs35l56_runtime_suspend_common(&cs35l56->base); in cs35l56_sdw_runtime_suspend()
457 if (!cs35l56->base.init_done) in cs35l56_sdw_runtime_resume()
464 ret = cs35l56_runtime_resume_common(&cs35l56->base, true); in cs35l56_sdw_runtime_resume()
468 /* Re-enable SoundWire interrupts */ in cs35l56_sdw_runtime_resume()
469 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, in cs35l56_sdw_runtime_resume()
479 if (!cs35l56->base.init_done) in cs35l56_sdw_system_suspend()
484 * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. in cs35l56_sdw_system_suspend()
486 cs35l56->sdw_irq_no_unmask = true; in cs35l56_sdw_system_suspend()
487 flush_work(&cs35l56->sdw_irq_work); in cs35l56_sdw_system_suspend()
490 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_system_suspend()
491 sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_system_suspend()
492 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_system_suspend()
493 flush_work(&cs35l56->sdw_irq_work); in cs35l56_sdw_system_suspend()
502 cs35l56->sdw_irq_no_unmask = false; in cs35l56_sdw_system_resume()
503 /* runtime_resume re-enables the interrupt */ in cs35l56_sdw_system_resume()
508 static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) in cs35l56_sdw_probe() argument
510 struct device *dev = &peripheral->dev; in cs35l56_sdw_probe()
516 return -ENOMEM; in cs35l56_sdw_probe()
518 cs35l56->base.dev = dev; in cs35l56_sdw_probe()
519 cs35l56->sdw_peripheral = peripheral; in cs35l56_sdw_probe()
520 INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); in cs35l56_sdw_probe()
524 cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, in cs35l56_sdw_probe()
525 peripheral, &cs35l56_regmap_sdw); in cs35l56_sdw_probe()
526 if (IS_ERR(cs35l56->base.regmap)) { in cs35l56_sdw_probe()
527 ret = PTR_ERR(cs35l56->base.regmap); in cs35l56_sdw_probe()
531 /* Start in cache-only until device is enumerated */ in cs35l56_sdw_probe()
532 regcache_cache_only(cs35l56->base.regmap, true); in cs35l56_sdw_probe()
541 static int cs35l56_sdw_remove(struct sdw_slave *peripheral) in cs35l56_sdw_remove() argument
543 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_remove()
546 cs35l56->sdw_irq_no_unmask = true; in cs35l56_sdw_remove()
547 cancel_work_sync(&cs35l56->sdw_irq_work); in cs35l56_sdw_remove()
548 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_remove()
549 sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_remove()
550 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_remove()