Lines Matching +full:per +full:- +full:peripheral
1 // SPDX-License-Identifier: GPL-2.0-only
26 static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf) in cs35l56_sdw_read_one() argument
30 ret = sdw_nread_no_pm(peripheral, reg, 4, (u8 *)buf); in cs35l56_sdw_read_one()
32 dev_err(&peripheral->dev, "Read failed @%#x:%d\n", reg, ret); in cs35l56_sdw_read_one()
45 struct sdw_slave *peripheral = context; in cs35l56_sdw_read() local
54 return cs35l56_sdw_read_one(peripheral, reg, val_buf); in cs35l56_sdw_read()
57 bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ in cs35l56_sdw_read()
61 ret = sdw_nread_no_pm(peripheral, reg, bytes, buf8); in cs35l56_sdw_read()
63 dev_err(&peripheral->dev, "Read failed @%#x..%#x:%d\n", in cs35l56_sdw_read()
64 reg, reg + bytes - 1, ret); in cs35l56_sdw_read()
69 val_size -= bytes; in cs35l56_sdw_read()
82 for (; nbytes > 0; nbytes -= 4) in cs35l56_swab_copy()
86 static int cs35l56_sdw_write_one(struct sdw_slave *peripheral, unsigned int reg, const void *buf) in cs35l56_sdw_write_one() argument
91 ret = sdw_nwrite_no_pm(peripheral, reg, 4, (u8 *)&val_le); in cs35l56_sdw_write_one()
93 dev_err(&peripheral->dev, "Write failed @%#x:%d\n", reg, ret); in cs35l56_sdw_write_one()
104 struct sdw_slave *peripheral = context; in cs35l56_sdw_gather_write() local
106 u32 val_le_buf[64]; /* Define u32 so it is 32-bit aligned */ in cs35l56_sdw_gather_write()
114 return cs35l56_sdw_write_one(peripheral, reg, src_be); in cs35l56_sdw_gather_write()
117 bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ in cs35l56_sdw_gather_write()
125 ret = sdw_nwrite_no_pm(peripheral, reg, bytes, (u8 *)val_le_buf); in cs35l56_sdw_gather_write()
127 dev_err(&peripheral->dev, "Write failed @%#x..%#x:%d\n", in cs35l56_sdw_gather_write()
128 reg, reg + bytes - 1, ret); in cs35l56_sdw_gather_write()
132 val_size -= bytes; in cs35l56_sdw_gather_write()
145 return cs35l56_sdw_gather_write(context, &src_buf[0], 4, &src_buf[4], val_size - 4); in cs35l56_sdw_write()
149 * Registers are big-endian on I2C and SPI but little-endian on SoundWire.
150 * Exported firmware controls are big-endian on I2C/SPI but little-endian on
151 * SoundWire. Firmware files are always big-endian and are opaque blobs.
152 * Present a big-endian regmap and hide the endianness swap, so that the ALSA
164 static void cs35l56_sdw_init(struct sdw_slave *peripheral) in cs35l56_sdw_init() argument
166 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_init()
169 pm_runtime_get_noresume(cs35l56->base.dev); in cs35l56_sdw_init()
171 regcache_cache_only(cs35l56->base.regmap, false); in cs35l56_sdw_init()
175 regcache_cache_only(cs35l56->base.regmap, true); in cs35l56_sdw_init()
183 if (cs35l56->base.init_done) { in cs35l56_sdw_init()
185 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, in cs35l56_sdw_init()
190 pm_runtime_mark_last_busy(cs35l56->base.dev); in cs35l56_sdw_init()
191 pm_runtime_put_autosuspend(cs35l56->base.dev); in cs35l56_sdw_init()
194 static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, in cs35l56_sdw_interrupt() argument
197 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_interrupt()
201 dev_dbg(cs35l56->base.dev, "int control_port=%#x\n", status->control_port); in cs35l56_sdw_interrupt()
203 if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0) in cs35l56_sdw_interrupt()
208 * bus-reset before the queued work has run. in cs35l56_sdw_interrupt()
210 pm_runtime_get_noresume(cs35l56->base.dev); in cs35l56_sdw_interrupt()
214 * is required as per the SoundWire spec for interrupt status bits in cs35l56_sdw_interrupt()
216 * None of the interrupts are time-critical so use the in cs35l56_sdw_interrupt()
217 * power-efficient queue. in cs35l56_sdw_interrupt()
219 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_interrupt()
220 sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_interrupt()
221 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_interrupt()
222 queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work); in cs35l56_sdw_interrupt()
233 cs35l56_irq(-1, &cs35l56->base); in cs35l56_sdw_irq_work()
236 if (!cs35l56->sdw_irq_no_unmask) in cs35l56_sdw_irq_work()
237 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, in cs35l56_sdw_irq_work()
240 pm_runtime_put_autosuspend(cs35l56->base.dev); in cs35l56_sdw_irq_work()
243 static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral) in cs35l56_sdw_read_prop() argument
245 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_read_prop()
246 struct sdw_slave_prop *prop = &peripheral->prop; in cs35l56_sdw_read_prop()
249 ports = devm_kcalloc(cs35l56->base.dev, 2, sizeof(*ports), GFP_KERNEL); in cs35l56_sdw_read_prop()
251 return -ENOMEM; in cs35l56_sdw_read_prop()
253 prop->source_ports = BIT(CS35L56_SDW1_CAPTURE_PORT); in cs35l56_sdw_read_prop()
254 prop->sink_ports = BIT(CS35L56_SDW1_PLAYBACK_PORT); in cs35l56_sdw_read_prop()
255 prop->paging_support = true; in cs35l56_sdw_read_prop()
256 prop->clk_stop_mode1 = false; in cs35l56_sdw_read_prop()
257 prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; in cs35l56_sdw_read_prop()
258 prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | SDW_SCP_INT1_IMPL_DEF; in cs35l56_sdw_read_prop()
260 /* DP1 - playback */ in cs35l56_sdw_read_prop()
264 prop->sink_dpn_prop = &ports[0]; in cs35l56_sdw_read_prop()
266 /* DP3 - capture */ in cs35l56_sdw_read_prop()
270 prop->src_dpn_prop = &ports[1]; in cs35l56_sdw_read_prop()
275 static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, in cs35l56_sdw_update_status() argument
278 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_update_status()
282 dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__); in cs35l56_sdw_update_status()
283 if (cs35l56->sdw_attached) in cs35l56_sdw_update_status()
286 if (!cs35l56->base.init_done || cs35l56->soft_resetting) in cs35l56_sdw_update_status()
287 cs35l56_sdw_init(peripheral); in cs35l56_sdw_update_status()
289 cs35l56->sdw_attached = true; in cs35l56_sdw_update_status()
292 dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__); in cs35l56_sdw_update_status()
293 cs35l56->sdw_attached = false; in cs35l56_sdw_update_status()
303 struct sdw_slave *peripheral) in cs35l56_a1_kick_divider() argument
308 if (!cs35l56->base.init_done) in cs35l56_a1_kick_divider()
311 if (peripheral->bus->params.curr_bank) { in cs35l56_a1_kick_divider()
325 curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); in cs35l56_a1_kick_divider()
327 dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); in cs35l56_a1_kick_divider()
331 next_scale = sdw_read_no_pm(peripheral, next_scale_reg); in cs35l56_a1_kick_divider()
333 dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); in cs35l56_a1_kick_divider()
338 next_scale = cs35l56->old_sdw_clock_scale; in cs35l56_a1_kick_divider()
339 ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); in cs35l56_a1_kick_divider()
341 dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", in cs35l56_a1_kick_divider()
347 cs35l56->old_sdw_clock_scale = curr_scale; in cs35l56_a1_kick_divider()
348 ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); in cs35l56_a1_kick_divider()
350 dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); in cs35l56_a1_kick_divider()
354 dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); in cs35l56_a1_kick_divider()
359 static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, in cs35l56_sdw_bus_config() argument
362 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_bus_config()
365 sclk = params->curr_dr_freq / 2; in cs35l56_sdw_bus_config()
366 dev_dbg(cs35l56->base.dev, "%s: sclk=%u c=%u r=%u\n", in cs35l56_sdw_bus_config()
367 __func__, sclk, params->col, params->row); in cs35l56_sdw_bus_config()
369 if (cs35l56->base.rev < 0xb0) in cs35l56_sdw_bus_config()
370 return cs35l56_a1_kick_divider(cs35l56, peripheral); in cs35l56_sdw_bus_config()
375 static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, in cs35l56_sdw_clk_stop() argument
379 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_clk_stop()
381 dev_dbg(cs35l56->base.dev, "%s: mode:%d type:%d\n", __func__, mode, type); in cs35l56_sdw_clk_stop()
398 struct sdw_slave *peripheral = cs35l56->sdw_peripheral; in cs35l56_sdw_handle_unattach() local
400 if (peripheral->unattach_request) { in cs35l56_sdw_handle_unattach()
401 /* Cannot access registers until bus is re-initialized. */ in cs35l56_sdw_handle_unattach()
402 dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n"); in cs35l56_sdw_handle_unattach()
403 if (!wait_for_completion_timeout(&peripheral->initialization_complete, in cs35l56_sdw_handle_unattach()
405 dev_err(cs35l56->base.dev, "initialization_complete timed out\n"); in cs35l56_sdw_handle_unattach()
406 return -ETIMEDOUT; in cs35l56_sdw_handle_unattach()
409 peripheral->unattach_request = 0; in cs35l56_sdw_handle_unattach()
424 if (!cs35l56->base.init_done) in cs35l56_sdw_runtime_suspend()
427 return cs35l56_runtime_suspend_common(&cs35l56->base); in cs35l56_sdw_runtime_suspend()
437 if (!cs35l56->base.init_done) in cs35l56_sdw_runtime_resume()
444 ret = cs35l56_runtime_resume_common(&cs35l56->base, true); in cs35l56_sdw_runtime_resume()
448 /* Re-enable SoundWire interrupts */ in cs35l56_sdw_runtime_resume()
449 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, in cs35l56_sdw_runtime_resume()
459 if (!cs35l56->base.init_done) in cs35l56_sdw_system_suspend()
464 * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. in cs35l56_sdw_system_suspend()
466 cs35l56->sdw_irq_no_unmask = true; in cs35l56_sdw_system_suspend()
467 flush_work(&cs35l56->sdw_irq_work); in cs35l56_sdw_system_suspend()
470 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_system_suspend()
471 sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_system_suspend()
472 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_system_suspend()
473 flush_work(&cs35l56->sdw_irq_work); in cs35l56_sdw_system_suspend()
482 cs35l56->sdw_irq_no_unmask = false; in cs35l56_sdw_system_resume()
483 /* runtime_resume re-enables the interrupt */ in cs35l56_sdw_system_resume()
488 static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) in cs35l56_sdw_probe() argument
490 struct device *dev = &peripheral->dev; in cs35l56_sdw_probe()
496 return -ENOMEM; in cs35l56_sdw_probe()
498 cs35l56->base.dev = dev; in cs35l56_sdw_probe()
499 cs35l56->sdw_peripheral = peripheral; in cs35l56_sdw_probe()
500 INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); in cs35l56_sdw_probe()
504 cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, in cs35l56_sdw_probe()
505 peripheral, &cs35l56_regmap_sdw); in cs35l56_sdw_probe()
506 if (IS_ERR(cs35l56->base.regmap)) { in cs35l56_sdw_probe()
507 ret = PTR_ERR(cs35l56->base.regmap); in cs35l56_sdw_probe()
511 /* Start in cache-only until device is enumerated */ in cs35l56_sdw_probe()
512 regcache_cache_only(cs35l56->base.regmap, true); in cs35l56_sdw_probe()
521 static int cs35l56_sdw_remove(struct sdw_slave *peripheral) in cs35l56_sdw_remove() argument
523 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_remove()
526 cs35l56->sdw_irq_no_unmask = true; in cs35l56_sdw_remove()
527 cancel_work_sync(&cs35l56->sdw_irq_work); in cs35l56_sdw_remove()
528 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_remove()
529 sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_remove()
530 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_remove()