Lines Matching +full:i3c +full:- +full:master

1 // SPDX-License-Identifier: GPL-2.0-only
3 * I3C Controller driver
13 #include <linux/adi-axi-common.h>
14 #include <linux/i3c/master.h>
126 static inline struct adi_i3c_master *to_adi_i3c_master(struct i3c_master_controller *master) in to_adi_i3c_master() argument
128 return container_of(master, struct adi_i3c_master, base); in to_adi_i3c_master()
131 static void adi_i3c_master_wr_to_tx_fifo(struct adi_i3c_master *master, in adi_i3c_master_wr_to_tx_fifo() argument
136 n = readl(master->regs + REG_SDO_FIFO_ROOM); in adi_i3c_master_wr_to_tx_fifo()
138 i3c_writel_fifo(master->regs + REG_SDO_FIFO, buf, m); in adi_i3c_master_wr_to_tx_fifo()
141 static void adi_i3c_master_rd_from_rx_fifo(struct adi_i3c_master *master, in adi_i3c_master_rd_from_rx_fifo() argument
144 i3c_readl_fifo(master->regs + REG_SDI_FIFO, buf, nbytes); in adi_i3c_master_rd_from_rx_fifo()
150 if (cmd->ndests > 1) in adi_i3c_master_supports_ccc_cmd()
153 switch (cmd->id) { in adi_i3c_master_supports_ccc_cmd()
178 static int adi_i3c_master_disable(struct adi_i3c_master *master) in adi_i3c_master_disable() argument
180 writel(0, master->regs + REG_IBI_CONFIG); in adi_i3c_master_disable()
185 static struct adi_i3c_xfer *adi_i3c_master_alloc_xfer(struct adi_i3c_master *master, in adi_i3c_master_alloc_xfer() argument
194 INIT_LIST_HEAD(&xfer->node); in adi_i3c_master_alloc_xfer()
195 xfer->ncmds = ncmds; in adi_i3c_master_alloc_xfer()
196 xfer->ret = -ETIMEDOUT; in adi_i3c_master_alloc_xfer()
201 static void adi_i3c_master_start_xfer_locked(struct adi_i3c_master *master) in adi_i3c_master_start_xfer_locked() argument
203 struct adi_i3c_xfer *xfer = master->xferqueue.cur; in adi_i3c_master_start_xfer_locked()
209 for (i = 0; i < xfer->ncmds; i++) { in adi_i3c_master_start_xfer_locked()
210 struct adi_i3c_cmd *cmd = &xfer->cmds[i]; in adi_i3c_master_start_xfer_locked()
212 if (!(cmd->cmd0 & REG_CMD_FIFO_0_RNW)) in adi_i3c_master_start_xfer_locked()
213 adi_i3c_master_wr_to_tx_fifo(master, cmd->tx_buf, cmd->tx_len); in adi_i3c_master_start_xfer_locked()
216 n = readl(master->regs + REG_CMD_FIFO_ROOM); in adi_i3c_master_start_xfer_locked()
217 for (i = 0; i < xfer->ncmds; i++) { in adi_i3c_master_start_xfer_locked()
218 struct adi_i3c_cmd *cmd = &xfer->cmds[i]; in adi_i3c_master_start_xfer_locked()
220 m = cmd->cmd0 & REG_CMD_FIFO_0_IS_CCC ? 2 : 1; in adi_i3c_master_start_xfer_locked()
223 writel(cmd->cmd0, master->regs + REG_CMD_FIFO); in adi_i3c_master_start_xfer_locked()
224 if (cmd->cmd0 & REG_CMD_FIFO_0_IS_CCC) in adi_i3c_master_start_xfer_locked()
225 writel(cmd->cmd1, master->regs + REG_CMD_FIFO); in adi_i3c_master_start_xfer_locked()
226 n -= m; in adi_i3c_master_start_xfer_locked()
230 static void adi_i3c_master_end_xfer_locked(struct adi_i3c_master *master, in adi_i3c_master_end_xfer_locked() argument
233 struct adi_i3c_xfer *xfer = master->xferqueue.cur; in adi_i3c_master_end_xfer_locked()
239 while (!(readl(master->regs + REG_FIFO_STATUS) & REG_FIFO_STATUS_CMDR_EMPTY)) { in adi_i3c_master_end_xfer_locked()
243 cmdr = readl(master->regs + REG_CMDR_FIFO); in adi_i3c_master_end_xfer_locked()
245 cmd = &xfer->cmds[xfer->ncmds_comp++]; in adi_i3c_master_end_xfer_locked()
246 if (cmd->cmd0 & REG_CMD_FIFO_0_RNW) { in adi_i3c_master_end_xfer_locked()
247 rx_len = min_t(u32, REG_CMDR_FIFO_XFER_BYTES(cmdr), cmd->rx_len); in adi_i3c_master_end_xfer_locked()
248 adi_i3c_master_rd_from_rx_fifo(master, cmd->rx_buf, rx_len); in adi_i3c_master_end_xfer_locked()
250 cmd->error = REG_CMDR_FIFO_ERROR(cmdr); in adi_i3c_master_end_xfer_locked()
253 for (i = 0; i < xfer->ncmds_comp; i++) { in adi_i3c_master_end_xfer_locked()
254 switch (xfer->cmds[i].error) { in adi_i3c_master_end_xfer_locked()
262 ret = -EIO; in adi_i3c_master_end_xfer_locked()
266 ret = -EINVAL; in adi_i3c_master_end_xfer_locked()
271 xfer->ret = ret; in adi_i3c_master_end_xfer_locked()
273 if (xfer->ncmds_comp != xfer->ncmds) in adi_i3c_master_end_xfer_locked()
276 complete(&xfer->comp); in adi_i3c_master_end_xfer_locked()
278 xfer = list_first_entry_or_null(&master->xferqueue.list, in adi_i3c_master_end_xfer_locked()
281 list_del_init(&xfer->node); in adi_i3c_master_end_xfer_locked()
283 master->xferqueue.cur = xfer; in adi_i3c_master_end_xfer_locked()
284 adi_i3c_master_start_xfer_locked(master); in adi_i3c_master_end_xfer_locked()
287 static void adi_i3c_master_queue_xfer(struct adi_i3c_master *master, in adi_i3c_master_queue_xfer() argument
290 init_completion(&xfer->comp); in adi_i3c_master_queue_xfer()
291 guard(spinlock_irqsave)(&master->xferqueue.lock); in adi_i3c_master_queue_xfer()
292 if (master->xferqueue.cur) { in adi_i3c_master_queue_xfer()
293 list_add_tail(&xfer->node, &master->xferqueue.list); in adi_i3c_master_queue_xfer()
295 master->xferqueue.cur = xfer; in adi_i3c_master_queue_xfer()
296 adi_i3c_master_start_xfer_locked(master); in adi_i3c_master_queue_xfer()
300 static void adi_i3c_master_unqueue_xfer(struct adi_i3c_master *master, in adi_i3c_master_unqueue_xfer() argument
303 guard(spinlock_irqsave)(&master->xferqueue.lock); in adi_i3c_master_unqueue_xfer()
304 if (master->xferqueue.cur == xfer) in adi_i3c_master_unqueue_xfer()
305 master->xferqueue.cur = NULL; in adi_i3c_master_unqueue_xfer()
307 list_del_init(&xfer->node); in adi_i3c_master_unqueue_xfer()
309 writel(0x01, master->regs + REG_ENABLE); in adi_i3c_master_unqueue_xfer()
310 writel(0x00, master->regs + REG_ENABLE); in adi_i3c_master_unqueue_xfer()
311 writel(REG_IRQ_PENDING_CMDR, master->regs + REG_IRQ_MASK); in adi_i3c_master_unqueue_xfer()
316 switch (cmd->error) { in adi_i3c_cmd_get_err()
334 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_send_ccc_cmd() local
337 struct adi_i3c_xfer *xfer __free(kfree) = adi_i3c_master_alloc_xfer(master, 1); in adi_i3c_master_send_ccc_cmd()
339 return -ENOMEM; in adi_i3c_master_send_ccc_cmd()
341 ccmd = xfer->cmds; in adi_i3c_master_send_ccc_cmd()
342 ccmd->cmd1 = REG_CMD_FIFO_1_CCC(cmd->id); in adi_i3c_master_send_ccc_cmd()
343 ccmd->cmd0 = REG_CMD_FIFO_0_IS_CCC | in adi_i3c_master_send_ccc_cmd()
344 REG_CMD_FIFO_0_LEN(cmd->dests[0].payload.len); in adi_i3c_master_send_ccc_cmd()
346 if (cmd->id & I3C_CCC_DIRECT) in adi_i3c_master_send_ccc_cmd()
347 ccmd->cmd0 |= REG_CMD_FIFO_0_DEV_ADDR(cmd->dests[0].addr); in adi_i3c_master_send_ccc_cmd()
349 if (cmd->rnw) { in adi_i3c_master_send_ccc_cmd()
350 ccmd->cmd0 |= REG_CMD_FIFO_0_RNW; in adi_i3c_master_send_ccc_cmd()
351 ccmd->rx_buf = cmd->dests[0].payload.data; in adi_i3c_master_send_ccc_cmd()
352 ccmd->rx_len = cmd->dests[0].payload.len; in adi_i3c_master_send_ccc_cmd()
354 ccmd->tx_buf = cmd->dests[0].payload.data; in adi_i3c_master_send_ccc_cmd()
355 ccmd->tx_len = cmd->dests[0].payload.len; in adi_i3c_master_send_ccc_cmd()
358 adi_i3c_master_queue_xfer(master, xfer); in adi_i3c_master_send_ccc_cmd()
359 if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) in adi_i3c_master_send_ccc_cmd()
360 adi_i3c_master_unqueue_xfer(master, xfer); in adi_i3c_master_send_ccc_cmd()
362 cmd->err = adi_i3c_cmd_get_err(&xfer->cmds[0]); in adi_i3c_master_send_ccc_cmd()
372 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_i3c_xfers() local
378 struct adi_i3c_xfer *xfer __free(kfree) = adi_i3c_master_alloc_xfer(master, nxfers); in adi_i3c_master_i3c_xfers()
380 return -ENOMEM; in adi_i3c_master_i3c_xfers()
383 struct adi_i3c_cmd *ccmd = &xfer->cmds[i]; in adi_i3c_master_i3c_xfers()
385 ccmd->cmd0 = REG_CMD_FIFO_0_DEV_ADDR(dev->info.dyn_addr); in adi_i3c_master_i3c_xfers()
388 ccmd->cmd0 |= REG_CMD_FIFO_0_RNW; in adi_i3c_master_i3c_xfers()
389 ccmd->rx_buf = xfers[i].data.in; in adi_i3c_master_i3c_xfers()
390 ccmd->rx_len = xfers[i].len; in adi_i3c_master_i3c_xfers()
392 ccmd->tx_buf = xfers[i].data.out; in adi_i3c_master_i3c_xfers()
393 ccmd->tx_len = xfers[i].len; in adi_i3c_master_i3c_xfers()
396 ccmd->cmd0 |= REG_CMD_FIFO_0_LEN(xfers[i].len); in adi_i3c_master_i3c_xfers()
398 if (i < nxfers - 1) in adi_i3c_master_i3c_xfers()
399 ccmd->cmd0 |= REG_CMD_FIFO_0_SR; in adi_i3c_master_i3c_xfers()
402 ccmd->cmd0 |= REG_CMD_FIFO_0_BCAST; in adi_i3c_master_i3c_xfers()
405 adi_i3c_master_queue_xfer(master, xfer); in adi_i3c_master_i3c_xfers()
406 if (!wait_for_completion_timeout(&xfer->comp, in adi_i3c_master_i3c_xfers()
408 adi_i3c_master_unqueue_xfer(master, xfer); in adi_i3c_master_i3c_xfers()
410 ret = xfer->ret; in adi_i3c_master_i3c_xfers()
413 xfers[i].err = adi_i3c_cmd_get_err(&xfer->cmds[i]); in adi_i3c_master_i3c_xfers()
424 static int adi_i3c_master_get_rr_slot(struct adi_i3c_master *master, in adi_i3c_master_get_rr_slot() argument
427 if (!master->free_rr_slots) in adi_i3c_master_get_rr_slot()
428 return -ENOSPC; in adi_i3c_master_get_rr_slot()
430 return ffs(master->free_rr_slots) - 1; in adi_i3c_master_get_rr_slot()
436 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_reattach_i3c_dev() local
439 addr = dev->info.dyn_addr ? dev->info.dyn_addr : dev->info.static_addr; in adi_i3c_master_reattach_i3c_dev()
441 writel(REG_DEV_CHAR_ADDR(dyn_addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
442 writel((readl(master->regs + REG_DEV_CHAR) & in adi_i3c_master_reattach_i3c_dev()
444 master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
446 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
447 writel(readl(master->regs + REG_DEV_CHAR) | in adi_i3c_master_reattach_i3c_dev()
449 master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
457 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_attach_i3c_dev() local
464 return -ENOMEM; in adi_i3c_master_attach_i3c_dev()
466 slot = adi_i3c_master_get_rr_slot(master, dev->info.dyn_addr); in adi_i3c_master_attach_i3c_dev()
472 data->id = slot; in adi_i3c_master_attach_i3c_dev()
474 master->free_rr_slots &= ~BIT(slot); in adi_i3c_master_attach_i3c_dev()
476 addr = dev->info.dyn_addr ? dev->info.dyn_addr : dev->info.static_addr; in adi_i3c_master_attach_i3c_dev()
478 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_attach_i3c_dev()
479 writel(readl(master->regs + REG_DEV_CHAR) | in adi_i3c_master_attach_i3c_dev()
481 master->regs + REG_DEV_CHAR); in adi_i3c_master_attach_i3c_dev()
488 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_sync_dev_char() local
493 i3c_bus_for_each_i3cdev(&m->bus, i3cdev) { in adi_i3c_master_sync_dev_char()
494 addr = i3cdev->info.dyn_addr ? in adi_i3c_master_sync_dev_char()
495 i3cdev->info.dyn_addr : i3cdev->info.static_addr; in adi_i3c_master_sync_dev_char()
496 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_sync_dev_char()
497 bcr_ibi = FIELD_GET(I3C_BCR_IBI_PAYLOAD | I3C_BCR_IBI_REQ_CAP, (i3cdev->info.bcr)); in adi_i3c_master_sync_dev_char()
498 writel(readl(master->regs + REG_DEV_CHAR) | in adi_i3c_master_sync_dev_char()
500 master->regs + REG_DEV_CHAR); in adi_i3c_master_sync_dev_char()
507 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_detach_i3c_dev() local
511 addr = dev->info.dyn_addr ? dev->info.dyn_addr : dev->info.static_addr; in adi_i3c_master_detach_i3c_dev()
513 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_detach_i3c_dev()
514 writel((readl(master->regs + REG_DEV_CHAR) & in adi_i3c_master_detach_i3c_dev()
516 master->regs + REG_DEV_CHAR); in adi_i3c_master_detach_i3c_dev()
519 master->free_rr_slots |= BIT(data->id); in adi_i3c_master_detach_i3c_dev()
526 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_attach_i2c_dev() local
530 slot = adi_i3c_master_get_rr_slot(master, 0); in adi_i3c_master_attach_i2c_dev()
536 return -ENOMEM; in adi_i3c_master_attach_i2c_dev()
538 data->id = slot; in adi_i3c_master_attach_i2c_dev()
539 master->free_rr_slots &= ~BIT(slot); in adi_i3c_master_attach_i2c_dev()
542 writel(REG_DEV_CHAR_ADDR(dev->addr) | in adi_i3c_master_attach_i2c_dev()
544 master->regs + REG_DEV_CHAR); in adi_i3c_master_attach_i2c_dev()
552 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_detach_i2c_dev() local
555 writel(REG_DEV_CHAR_ADDR(dev->addr) | in adi_i3c_master_detach_i2c_dev()
557 master->regs + REG_DEV_CHAR); in adi_i3c_master_detach_i2c_dev()
560 master->free_rr_slots |= BIT(data->id); in adi_i3c_master_detach_i2c_dev()
566 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_bus_cleanup() local
568 adi_i3c_master_disable(master); in adi_i3c_master_bus_cleanup()
571 static void adi_i3c_master_upd_i3c_scl_lim(struct adi_i3c_master *master) in adi_i3c_master_upd_i3c_scl_lim() argument
573 struct i3c_master_controller *m = &master->base; in adi_i3c_master_upd_i3c_scl_lim()
582 max_fscl = max(I3C_CCC_MAX_SDR_FSCL(dev->info.max_read_ds), in adi_i3c_master_upd_i3c_scl_lim()
583 I3C_CCC_MAX_SDR_FSCL(dev->info.max_write_ds)); in adi_i3c_master_upd_i3c_scl_lim()
612 master->i3c_scl_lim = i3c_scl_lim - 1; in adi_i3c_master_upd_i3c_scl_lim()
614 pp_sg = readl(master->regs + REG_OPS) & ~REG_OPS_PP_SG_MASK; in adi_i3c_master_upd_i3c_scl_lim()
615 pp_sg |= REG_OPS_SET_SG(master->i3c_scl_lim); in adi_i3c_master_upd_i3c_scl_lim()
617 writel(pp_sg, master->regs + REG_OPS); in adi_i3c_master_upd_i3c_scl_lim()
620 static void adi_i3c_master_get_features(struct adi_i3c_master *master, in adi_i3c_master_get_features() argument
628 buf = readl(master->regs + REG_DCR_BCR_DA); in adi_i3c_master_get_features()
629 info->dyn_addr = REG_DCR_BCR_DA_GET_DA(buf); in adi_i3c_master_get_features()
630 info->dcr = REG_DCR_BCR_DA_GET_DCR(buf); in adi_i3c_master_get_features()
631 info->bcr = REG_DCR_BCR_DA_GET_BCR(buf); in adi_i3c_master_get_features()
632 info->pid = readl(master->regs + REG_PID_L); in adi_i3c_master_get_features()
633 info->pid |= (u64)readl(master->regs + REG_PID_H) << 32; in adi_i3c_master_get_features()
638 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_do_daa() local
646 master->daa.addrs[i] = addr; in adi_i3c_master_do_daa()
649 irq_mask = readl(master->regs + REG_IRQ_MASK); in adi_i3c_master_do_daa()
651 master->regs + REG_IRQ_MASK); in adi_i3c_master_do_daa()
653 master->daa.index = 0; in adi_i3c_master_do_daa()
654 ret = i3c_master_entdaa_locked(&master->base); in adi_i3c_master_do_daa()
656 writel(irq_mask, master->regs + REG_IRQ_MASK); in adi_i3c_master_do_daa()
662 /* Add I3C devices discovered */ in adi_i3c_master_do_daa()
663 for (u8 i = 0; i < master->daa.index; i++) in adi_i3c_master_do_daa()
664 i3c_master_add_i3c_dev_locked(m, master->daa.addrs[i]); in adi_i3c_master_do_daa()
668 i3c_master_defslvs_locked(&master->base); in adi_i3c_master_do_daa()
670 adi_i3c_master_upd_i3c_scl_lim(master); in adi_i3c_master_do_daa()
677 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_bus_init() local
685 adi_i3c_master_get_features(master, 0, &info); in adi_i3c_master_bus_init()
686 ret = i3c_master_set_info(&master->base, &info); in adi_i3c_master_bus_init()
691 master->regs + REG_IBI_CONFIG); in adi_i3c_master_bus_init()
696 static void adi_i3c_master_handle_ibi(struct adi_i3c_master *master, in adi_i3c_master_handle_ibi() argument
707 for (id = 0; id < master->ibi.num_slots; id++) { in adi_i3c_master_handle_ibi()
708 if (master->ibi.slots[id] && in adi_i3c_master_handle_ibi()
709 master->ibi.slots[id]->info.dyn_addr == da) in adi_i3c_master_handle_ibi()
713 if (id == master->ibi.num_slots) in adi_i3c_master_handle_ibi()
716 dev = master->ibi.slots[id]; in adi_i3c_master_handle_ibi()
717 len = ADI_HAS_MDB_FROM_BCR(dev->info.bcr); in adi_i3c_master_handle_ibi()
720 guard(spinlock)(&master->ibi.lock); in adi_i3c_master_handle_ibi()
721 slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); in adi_i3c_master_handle_ibi()
725 slot->len = len; in adi_i3c_master_handle_ibi()
726 buf = slot->data; in adi_i3c_master_handle_ibi()
731 static void adi_i3c_master_demux_ibis(struct adi_i3c_master *master) in adi_i3c_master_demux_ibis() argument
733 while (!(readl(master->regs + REG_FIFO_STATUS) & REG_FIFO_STATUS_IBI_EMPTY)) { in adi_i3c_master_demux_ibis()
734 u32 raw = readl(master->regs + REG_IBI_FIFO); in adi_i3c_master_demux_ibis()
736 adi_i3c_master_handle_ibi(master, raw); in adi_i3c_master_demux_ibis()
740 static void adi_i3c_master_handle_da_req(struct adi_i3c_master *master) in adi_i3c_master_handle_da_req() argument
745 adi_i3c_master_rd_from_rx_fifo(master, payload0, 6); in adi_i3c_master_handle_da_req()
746 addr = master->daa.addrs[master->daa.index++]; in adi_i3c_master_handle_da_req()
749 writel(addr, master->regs + REG_SDO_FIFO); in adi_i3c_master_handle_da_req()
754 struct adi_i3c_master *master = data; in adi_i3c_master_irq() local
757 pending = readl(master->regs + REG_IRQ_PENDING); in adi_i3c_master_irq()
758 writel(pending, master->regs + REG_IRQ_PENDING); in adi_i3c_master_irq()
760 scoped_guard(spinlock_irqsave, &master->xferqueue.lock) { in adi_i3c_master_irq()
761 adi_i3c_master_end_xfer_locked(master, pending); in adi_i3c_master_irq()
765 adi_i3c_master_demux_ibis(master); in adi_i3c_master_irq()
767 adi_i3c_master_handle_da_req(master); in adi_i3c_master_irq()
777 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_i2c_xfers() local
784 return -EOPNOTSUPP; in adi_i3c_master_i2c_xfers()
787 struct adi_i3c_xfer *xfer __free(kfree) = adi_i3c_master_alloc_xfer(master, nxfers); in adi_i3c_master_i2c_xfers()
789 return -ENOMEM; in adi_i3c_master_i2c_xfers()
792 struct adi_i3c_cmd *ccmd = &xfer->cmds[i]; in adi_i3c_master_i2c_xfers()
794 ccmd->cmd0 = REG_CMD_FIFO_0_DEV_ADDR(xfers[i].addr); in adi_i3c_master_i2c_xfers()
797 ccmd->cmd0 |= REG_CMD_FIFO_0_RNW; in adi_i3c_master_i2c_xfers()
798 ccmd->rx_buf = xfers[i].buf; in adi_i3c_master_i2c_xfers()
799 ccmd->rx_len = xfers[i].len; in adi_i3c_master_i2c_xfers()
801 ccmd->tx_buf = xfers[i].buf; in adi_i3c_master_i2c_xfers()
802 ccmd->tx_len = xfers[i].len; in adi_i3c_master_i2c_xfers()
805 ccmd->cmd0 |= REG_CMD_FIFO_0_LEN(xfers[i].len); in adi_i3c_master_i2c_xfers()
808 adi_i3c_master_queue_xfer(master, xfer); in adi_i3c_master_i2c_xfers()
809 if (!wait_for_completion_timeout(&xfer->comp, in adi_i3c_master_i2c_xfers()
810 m->i2c.timeout)) in adi_i3c_master_i2c_xfers()
811 adi_i3c_master_unqueue_xfer(master, xfer); in adi_i3c_master_i2c_xfers()
813 return xfer->ret; in adi_i3c_master_i2c_xfers()
819 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_disable_ibi() local
824 ret = i3c_master_disec_locked(m, dev->info.dyn_addr, in adi_i3c_master_disable_ibi()
827 i3c_bus_for_each_i3cdev(&m->bus, i3cdev) { in adi_i3c_master_disable_ibi()
828 if (dev != i3cdev && i3cdev->ibi) in adi_i3c_master_disable_ibi()
829 enabled |= i3cdev->ibi->enabled; in adi_i3c_master_disable_ibi()
833 master->regs + REG_IBI_CONFIG); in adi_i3c_master_disable_ibi()
834 writel(readl(master->regs + REG_IRQ_MASK) & ~REG_IRQ_PENDING_IBI, in adi_i3c_master_disable_ibi()
835 master->regs + REG_IRQ_MASK); in adi_i3c_master_disable_ibi()
844 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_enable_ibi() local
847 master->regs + REG_IBI_CONFIG); in adi_i3c_master_enable_ibi()
849 writel(readl(master->regs + REG_IRQ_MASK) | REG_IRQ_PENDING_IBI, in adi_i3c_master_enable_ibi()
850 master->regs + REG_IRQ_MASK); in adi_i3c_master_enable_ibi()
852 return i3c_master_enec_locked(m, dev->info.dyn_addr, in adi_i3c_master_enable_ibi()
860 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_request_ibi() local
865 data->ibi_pool = i3c_generic_ibi_alloc_pool(dev, req); in adi_i3c_master_request_ibi()
866 if (IS_ERR(data->ibi_pool)) in adi_i3c_master_request_ibi()
867 return PTR_ERR(data->ibi_pool); in adi_i3c_master_request_ibi()
869 scoped_guard(spinlock_irqsave, &master->ibi.lock) { in adi_i3c_master_request_ibi()
870 for (i = 0; i < master->ibi.num_slots; i++) { in adi_i3c_master_request_ibi()
871 if (!master->ibi.slots[i]) { in adi_i3c_master_request_ibi()
872 data->ibi = i; in adi_i3c_master_request_ibi()
873 master->ibi.slots[i] = dev; in adi_i3c_master_request_ibi()
879 if (i < master->ibi.num_slots) in adi_i3c_master_request_ibi()
882 i3c_generic_ibi_free_pool(data->ibi_pool); in adi_i3c_master_request_ibi()
883 data->ibi_pool = NULL; in adi_i3c_master_request_ibi()
885 return -ENOSPC; in adi_i3c_master_request_ibi()
891 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_free_ibi() local
894 scoped_guard(spinlock_irqsave, &master->ibi.lock) { in adi_i3c_master_free_ibi()
895 master->ibi.slots[data->ibi] = NULL; in adi_i3c_master_free_ibi()
898 i3c_generic_ibi_free_pool(data->ibi_pool); in adi_i3c_master_free_ibi()
906 i3c_generic_ibi_recycle_slot(data->ibi_pool, slot); in adi_i3c_master_recycle_ibi_slot()
930 { .compatible = "adi,i3c-master-v1" },
936 struct adi_i3c_master *master; in adi_i3c_master_probe() local
941 master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); in adi_i3c_master_probe()
942 if (!master) in adi_i3c_master_probe()
943 return -ENOMEM; in adi_i3c_master_probe()
945 master->regs = devm_platform_ioremap_resource(pdev, 0); in adi_i3c_master_probe()
946 if (IS_ERR(master->regs)) in adi_i3c_master_probe()
947 return PTR_ERR(master->regs); in adi_i3c_master_probe()
949 ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &clk); in adi_i3c_master_probe()
951 return dev_err_probe(&pdev->dev, ret, in adi_i3c_master_probe()
958 version = readl(master->regs + ADI_AXI_REG_VERSION); in adi_i3c_master_probe()
960 dev_err_probe(&pdev->dev, -ENODEV, "Unsupported peripheral version %u.%u.%u\n", in adi_i3c_master_probe()
965 writel(0x00, master->regs + REG_ENABLE); in adi_i3c_master_probe()
966 writel(0x00, master->regs + REG_IRQ_MASK); in adi_i3c_master_probe()
968 ret = devm_request_irq(&pdev->dev, irq, adi_i3c_master_irq, 0, in adi_i3c_master_probe()
969 dev_name(&pdev->dev), master); in adi_i3c_master_probe()
973 platform_set_drvdata(pdev, master); in adi_i3c_master_probe()
975 master->free_rr_slots = GENMASK(ADI_MAX_DEVS, 1); in adi_i3c_master_probe()
977 writel(REG_IRQ_PENDING_CMDR, master->regs + REG_IRQ_MASK); in adi_i3c_master_probe()
979 spin_lock_init(&master->ibi.lock); in adi_i3c_master_probe()
980 master->ibi.num_slots = 15; in adi_i3c_master_probe()
981 master->ibi.slots = devm_kcalloc(&pdev->dev, master->ibi.num_slots, in adi_i3c_master_probe()
982 sizeof(*master->ibi.slots), in adi_i3c_master_probe()
984 if (!master->ibi.slots) in adi_i3c_master_probe()
985 return -ENOMEM; in adi_i3c_master_probe()
987 spin_lock_init(&master->xferqueue.lock); in adi_i3c_master_probe()
988 INIT_LIST_HEAD(&master->xferqueue.list); in adi_i3c_master_probe()
990 return i3c_master_register(&master->base, &pdev->dev, in adi_i3c_master_probe()
996 struct adi_i3c_master *master = platform_get_drvdata(pdev); in adi_i3c_master_remove() local
998 writel(0xff, master->regs + REG_IRQ_PENDING); in adi_i3c_master_remove()
999 writel(0x00, master->regs + REG_IRQ_MASK); in adi_i3c_master_remove()
1000 writel(0x01, master->regs + REG_ENABLE); in adi_i3c_master_remove()
1002 i3c_master_unregister(&master->base); in adi_i3c_master_remove()
1009 .name = "adi-i3c-master",
1016 MODULE_DESCRIPTION("Analog Devices I3C master driver");