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
245 ret = sdw_read_no_pm(cs35l56->sdw_peripheral, SDW_SCP_DEVID_0); in cs35l56_sdw_get_unique_id()
249 cs35l56->sdw_unique_id = ret & 0xf; in cs35l56_sdw_get_unique_id()
254 static void cs35l56_sdw_init(struct sdw_slave *peripheral) in cs35l56_sdw_init() argument
256 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_init()
259 pm_runtime_get_noresume(cs35l56->base.dev); in cs35l56_sdw_init()
266 if (cs35l56->base.cal_index < 0) in cs35l56_sdw_init()
267 cs35l56->base.cal_index = cs35l56->sdw_unique_id; in cs35l56_sdw_init()
271 regcache_cache_only(cs35l56->base.regmap, true); in cs35l56_sdw_init()
279 if (cs35l56->base.init_done) { in cs35l56_sdw_init()
281 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 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()
397 struct sdw_slave *peripheral) in cs35l63_sdw_kick_divider() argument
402 if (!cs35l56->base.init_done) in cs35l63_sdw_kick_divider()
405 if (peripheral->bus->params.curr_bank) { in cs35l63_sdw_kick_divider()
419 curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); in cs35l63_sdw_kick_divider()
421 dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); in cs35l63_sdw_kick_divider()
425 next_scale = sdw_read_no_pm(peripheral, next_scale_reg); in cs35l63_sdw_kick_divider()
427 dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); in cs35l63_sdw_kick_divider()
432 next_scale = cs35l56->old_sdw_clock_scale; in cs35l63_sdw_kick_divider()
433 ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); in cs35l63_sdw_kick_divider()
435 dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", in cs35l63_sdw_kick_divider()
441 cs35l56->old_sdw_clock_scale = curr_scale; in cs35l63_sdw_kick_divider()
442 ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); in cs35l63_sdw_kick_divider()
444 dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); in cs35l63_sdw_kick_divider()
448 dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); in cs35l63_sdw_kick_divider()
453 static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, in cs35l56_sdw_bus_config() argument
456 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_bus_config()
458 if ((cs35l56->base.type == 0x63) && (cs35l56->base.rev < 0xa1)) in cs35l56_sdw_bus_config()
459 return cs35l63_sdw_kick_divider(cs35l56, peripheral); in cs35l56_sdw_bus_config()
464 static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, in cs35l56_sdw_clk_stop() argument
468 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_clk_stop()
470 dev_dbg(cs35l56->base.dev, "%s: mode:%d type:%d\n", __func__, mode, type); in cs35l56_sdw_clk_stop()
487 struct sdw_slave *peripheral = cs35l56->sdw_peripheral; in cs35l56_sdw_handle_unattach() local
489 if (peripheral->unattach_request) { in cs35l56_sdw_handle_unattach()
490 /* Cannot access registers until bus is re-initialized. */ in cs35l56_sdw_handle_unattach()
491 dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n"); in cs35l56_sdw_handle_unattach()
492 if (!wait_for_completion_timeout(&peripheral->initialization_complete, in cs35l56_sdw_handle_unattach()
494 dev_err(cs35l56->base.dev, "initialization_complete timed out\n"); in cs35l56_sdw_handle_unattach()
495 return -ETIMEDOUT; in cs35l56_sdw_handle_unattach()
498 peripheral->unattach_request = 0; in cs35l56_sdw_handle_unattach()
513 if (!cs35l56->base.init_done) in cs35l56_sdw_runtime_suspend()
516 return cs35l56_runtime_suspend_common(&cs35l56->base); in cs35l56_sdw_runtime_suspend()
526 if (!cs35l56->base.init_done) in cs35l56_sdw_runtime_resume()
533 ret = cs35l56_runtime_resume_common(&cs35l56->base, true); in cs35l56_sdw_runtime_resume()
537 /* Re-enable SoundWire interrupts */ in cs35l56_sdw_runtime_resume()
538 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, in cs35l56_sdw_runtime_resume()
548 if (!cs35l56->base.init_done) in cs35l56_sdw_system_suspend()
553 * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. in cs35l56_sdw_system_suspend()
555 cs35l56->sdw_irq_no_unmask = true; in cs35l56_sdw_system_suspend()
556 flush_work(&cs35l56->sdw_irq_work); in cs35l56_sdw_system_suspend()
559 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_system_suspend()
560 sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_system_suspend()
561 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_system_suspend()
562 flush_work(&cs35l56->sdw_irq_work); in cs35l56_sdw_system_suspend()
571 cs35l56->sdw_irq_no_unmask = false; in cs35l56_sdw_system_resume()
572 /* runtime_resume re-enables the interrupt */ in cs35l56_sdw_system_resume()
577 static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_device_id *id) in cs35l56_sdw_probe() argument
579 struct device *dev = &peripheral->dev; in cs35l56_sdw_probe()
586 return -ENOMEM; in cs35l56_sdw_probe()
588 cs35l56->base.dev = dev; in cs35l56_sdw_probe()
589 cs35l56->sdw_peripheral = peripheral; in cs35l56_sdw_probe()
590 cs35l56->sdw_link_num = peripheral->bus->link_id; in cs35l56_sdw_probe()
591 INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); in cs35l56_sdw_probe()
595 switch ((unsigned int)id->driver_data) { in cs35l56_sdw_probe()
599 cs35l56->base.fw_reg = &cs35l56_fw_reg; in cs35l56_sdw_probe()
603 cs35l56->base.fw_reg = &cs35l63_fw_reg; in cs35l56_sdw_probe()
606 return -ENODEV; in cs35l56_sdw_probe()
609 cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, in cs35l56_sdw_probe()
610 peripheral, regmap_config); in cs35l56_sdw_probe()
611 if (IS_ERR(cs35l56->base.regmap)) { in cs35l56_sdw_probe()
612 ret = PTR_ERR(cs35l56->base.regmap); in cs35l56_sdw_probe()
616 /* Start in cache-only until device is enumerated */ in cs35l56_sdw_probe()
617 regcache_cache_only(cs35l56->base.regmap, true); in cs35l56_sdw_probe()
626 static int cs35l56_sdw_remove(struct sdw_slave *peripheral) in cs35l56_sdw_remove() argument
628 struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); in cs35l56_sdw_remove()
631 cs35l56->sdw_irq_no_unmask = true; in cs35l56_sdw_remove()
632 cancel_work_sync(&cs35l56->sdw_irq_work); in cs35l56_sdw_remove()
633 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); in cs35l56_sdw_remove()
634 sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); in cs35l56_sdw_remove()
635 sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); in cs35l56_sdw_remove()