Lines Matching refs:master
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()
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
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()
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()
223 writel(cmd->cmd0, master->regs + REG_CMD_FIFO); in adi_i3c_master_start_xfer_locked()
225 writel(cmd->cmd1, master->regs + REG_CMD_FIFO); 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()
248 adi_i3c_master_rd_from_rx_fifo(master, cmd->rx_buf, rx_len); in adi_i3c_master_end_xfer_locked()
278 xfer = list_first_entry_or_null(&master->xferqueue.list, 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
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()
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()
334 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_send_ccc_cmd() local
338 xfer = adi_i3c_master_alloc_xfer(master, 1); in adi_i3c_master_send_ccc_cmd()
359 adi_i3c_master_queue_xfer(master, xfer); in adi_i3c_master_send_ccc_cmd()
361 adi_i3c_master_unqueue_xfer(master, xfer); in adi_i3c_master_send_ccc_cmd()
373 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_priv_xfers() local
380 xfer = adi_i3c_master_alloc_xfer(master, nxfers); in adi_i3c_master_priv_xfers()
407 adi_i3c_master_queue_xfer(master, xfer); in adi_i3c_master_priv_xfers()
410 adi_i3c_master_unqueue_xfer(master, xfer); in adi_i3c_master_priv_xfers()
426 static int adi_i3c_master_get_rr_slot(struct adi_i3c_master *master, in adi_i3c_master_get_rr_slot() argument
429 if (!master->free_rr_slots) in adi_i3c_master_get_rr_slot()
432 return ffs(master->free_rr_slots) - 1; in adi_i3c_master_get_rr_slot()
438 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_reattach_i3c_dev() local
443 writel(REG_DEV_CHAR_ADDR(dyn_addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
444 writel((readl(master->regs + REG_DEV_CHAR) & in adi_i3c_master_reattach_i3c_dev()
446 master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
448 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
449 writel(readl(master->regs + REG_DEV_CHAR) | in adi_i3c_master_reattach_i3c_dev()
451 master->regs + REG_DEV_CHAR); in adi_i3c_master_reattach_i3c_dev()
459 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_attach_i3c_dev() local
468 slot = adi_i3c_master_get_rr_slot(master, dev->info.dyn_addr); in adi_i3c_master_attach_i3c_dev()
476 master->free_rr_slots &= ~BIT(slot); in adi_i3c_master_attach_i3c_dev()
480 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_attach_i3c_dev()
481 writel(readl(master->regs + REG_DEV_CHAR) | in adi_i3c_master_attach_i3c_dev()
483 master->regs + REG_DEV_CHAR); in adi_i3c_master_attach_i3c_dev()
490 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_sync_dev_char() local
498 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_sync_dev_char()
500 writel(readl(master->regs + REG_DEV_CHAR) | in adi_i3c_master_sync_dev_char()
502 master->regs + REG_DEV_CHAR); in adi_i3c_master_sync_dev_char()
509 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_detach_i3c_dev() local
515 writel(REG_DEV_CHAR_ADDR(addr), master->regs + REG_DEV_CHAR); in adi_i3c_master_detach_i3c_dev()
516 writel((readl(master->regs + REG_DEV_CHAR) & in adi_i3c_master_detach_i3c_dev()
518 master->regs + REG_DEV_CHAR); in adi_i3c_master_detach_i3c_dev()
521 master->free_rr_slots |= BIT(data->id); in adi_i3c_master_detach_i3c_dev()
528 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_attach_i2c_dev() local
532 slot = adi_i3c_master_get_rr_slot(master, 0); in adi_i3c_master_attach_i2c_dev()
541 master->free_rr_slots &= ~BIT(slot); in adi_i3c_master_attach_i2c_dev()
546 master->regs + REG_DEV_CHAR); in adi_i3c_master_attach_i2c_dev()
554 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_detach_i2c_dev() local
559 master->regs + REG_DEV_CHAR); in adi_i3c_master_detach_i2c_dev()
562 master->free_rr_slots |= BIT(data->id); in adi_i3c_master_detach_i2c_dev()
568 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_bus_cleanup() local
570 adi_i3c_master_disable(master); in adi_i3c_master_bus_cleanup()
573 static void adi_i3c_master_upd_i3c_scl_lim(struct adi_i3c_master *master) in adi_i3c_master_upd_i3c_scl_lim() argument
575 struct i3c_master_controller *m = &master->base; in adi_i3c_master_upd_i3c_scl_lim()
614 master->i3c_scl_lim = i3c_scl_lim - 1; in adi_i3c_master_upd_i3c_scl_lim()
616 pp_sg = readl(master->regs + REG_OPS) & ~REG_OPS_PP_SG_MASK; in adi_i3c_master_upd_i3c_scl_lim()
617 pp_sg |= REG_OPS_SET_SG(master->i3c_scl_lim); in adi_i3c_master_upd_i3c_scl_lim()
619 writel(pp_sg, master->regs + REG_OPS); in adi_i3c_master_upd_i3c_scl_lim()
622 static void adi_i3c_master_get_features(struct adi_i3c_master *master, in adi_i3c_master_get_features() argument
630 buf = readl(master->regs + REG_DCR_BCR_DA); in adi_i3c_master_get_features()
634 info->pid = readl(master->regs + REG_PID_L); in adi_i3c_master_get_features()
635 info->pid |= (u64)readl(master->regs + REG_PID_H) << 32; in adi_i3c_master_get_features()
640 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_do_daa() local
648 master->daa.addrs[i] = addr; in adi_i3c_master_do_daa()
651 irq_mask = readl(master->regs + REG_IRQ_MASK); in adi_i3c_master_do_daa()
653 master->regs + REG_IRQ_MASK); in adi_i3c_master_do_daa()
655 master->daa.index = 0; in adi_i3c_master_do_daa()
656 ret = i3c_master_entdaa_locked(&master->base); in adi_i3c_master_do_daa()
658 writel(irq_mask, master->regs + REG_IRQ_MASK); in adi_i3c_master_do_daa()
665 for (u8 i = 0; i < master->daa.index; i++) in adi_i3c_master_do_daa()
666 i3c_master_add_i3c_dev_locked(m, master->daa.addrs[i]); in adi_i3c_master_do_daa()
670 i3c_master_defslvs_locked(&master->base); in adi_i3c_master_do_daa()
672 adi_i3c_master_upd_i3c_scl_lim(master); in adi_i3c_master_do_daa()
679 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_bus_init() local
687 adi_i3c_master_get_features(master, 0, &info); in adi_i3c_master_bus_init()
688 ret = i3c_master_set_info(&master->base, &info); in adi_i3c_master_bus_init()
693 master->regs + REG_IBI_CONFIG); in adi_i3c_master_bus_init()
698 static void adi_i3c_master_handle_ibi(struct adi_i3c_master *master, in adi_i3c_master_handle_ibi() argument
709 for (id = 0; id < master->ibi.num_slots; id++) { in adi_i3c_master_handle_ibi()
710 if (master->ibi.slots[id] && in adi_i3c_master_handle_ibi()
711 master->ibi.slots[id]->info.dyn_addr == da) in adi_i3c_master_handle_ibi()
715 if (id == master->ibi.num_slots) in adi_i3c_master_handle_ibi()
718 dev = master->ibi.slots[id]; in adi_i3c_master_handle_ibi()
722 guard(spinlock)(&master->ibi.lock); in adi_i3c_master_handle_ibi()
733 static void adi_i3c_master_demux_ibis(struct adi_i3c_master *master) in adi_i3c_master_demux_ibis() argument
735 while (!(readl(master->regs + REG_FIFO_STATUS) & REG_FIFO_STATUS_IBI_EMPTY)) { in adi_i3c_master_demux_ibis()
736 u32 raw = readl(master->regs + REG_IBI_FIFO); in adi_i3c_master_demux_ibis()
738 adi_i3c_master_handle_ibi(master, raw); in adi_i3c_master_demux_ibis()
742 static void adi_i3c_master_handle_da_req(struct adi_i3c_master *master) in adi_i3c_master_handle_da_req() argument
747 adi_i3c_master_rd_from_rx_fifo(master, payload0, 6); in adi_i3c_master_handle_da_req()
748 addr = master->daa.addrs[master->daa.index++]; in adi_i3c_master_handle_da_req()
751 writel(addr, master->regs + REG_SDO_FIFO); in adi_i3c_master_handle_da_req()
756 struct adi_i3c_master *master = data; in adi_i3c_master_irq() local
759 pending = readl(master->regs + REG_IRQ_PENDING); in adi_i3c_master_irq()
760 writel(pending, master->regs + REG_IRQ_PENDING); in adi_i3c_master_irq()
762 scoped_guard(spinlock_irqsave, &master->xferqueue.lock) { in adi_i3c_master_irq()
763 adi_i3c_master_end_xfer_locked(master, pending); in adi_i3c_master_irq()
767 adi_i3c_master_demux_ibis(master); in adi_i3c_master_irq()
769 adi_i3c_master_handle_da_req(master); in adi_i3c_master_irq()
779 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_i2c_xfers() local
789 xfer = adi_i3c_master_alloc_xfer(master, nxfers); in adi_i3c_master_i2c_xfers()
810 adi_i3c_master_queue_xfer(master, xfer); in adi_i3c_master_i2c_xfers()
813 adi_i3c_master_unqueue_xfer(master, xfer); in adi_i3c_master_i2c_xfers()
821 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_disable_ibi() local
835 master->regs + REG_IBI_CONFIG); in adi_i3c_master_disable_ibi()
836 writel(readl(master->regs + REG_IRQ_MASK) & ~REG_IRQ_PENDING_IBI, in adi_i3c_master_disable_ibi()
837 master->regs + REG_IRQ_MASK); in adi_i3c_master_disable_ibi()
846 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_enable_ibi() local
849 master->regs + REG_IBI_CONFIG); in adi_i3c_master_enable_ibi()
851 writel(readl(master->regs + REG_IRQ_MASK) | REG_IRQ_PENDING_IBI, in adi_i3c_master_enable_ibi()
852 master->regs + REG_IRQ_MASK); in adi_i3c_master_enable_ibi()
862 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_request_ibi() local
871 scoped_guard(spinlock_irqsave, &master->ibi.lock) { in adi_i3c_master_request_ibi()
872 for (i = 0; i < master->ibi.num_slots; i++) { in adi_i3c_master_request_ibi()
873 if (!master->ibi.slots[i]) { in adi_i3c_master_request_ibi()
875 master->ibi.slots[i] = dev; in adi_i3c_master_request_ibi()
881 if (i < master->ibi.num_slots) in adi_i3c_master_request_ibi()
893 struct adi_i3c_master *master = to_adi_i3c_master(m); in adi_i3c_master_free_ibi() local
896 scoped_guard(spinlock_irqsave, &master->ibi.lock) { in adi_i3c_master_free_ibi()
897 master->ibi.slots[data->ibi] = NULL; in adi_i3c_master_free_ibi()
938 struct adi_i3c_master *master; in adi_i3c_master_probe() local
943 master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); in adi_i3c_master_probe()
944 if (!master) in adi_i3c_master_probe()
947 master->regs = devm_platform_ioremap_resource(pdev, 0); in adi_i3c_master_probe()
948 if (IS_ERR(master->regs)) in adi_i3c_master_probe()
949 return PTR_ERR(master->regs); in adi_i3c_master_probe()
960 version = readl(master->regs + ADI_AXI_REG_VERSION); in adi_i3c_master_probe()
967 writel(0x00, master->regs + REG_ENABLE); in adi_i3c_master_probe()
968 writel(0x00, master->regs + REG_IRQ_MASK); in adi_i3c_master_probe()
971 dev_name(&pdev->dev), master); in adi_i3c_master_probe()
975 platform_set_drvdata(pdev, master); in adi_i3c_master_probe()
977 master->free_rr_slots = GENMASK(ADI_MAX_DEVS, 1); in adi_i3c_master_probe()
979 writel(REG_IRQ_PENDING_CMDR, master->regs + REG_IRQ_MASK); in adi_i3c_master_probe()
981 spin_lock_init(&master->ibi.lock); in adi_i3c_master_probe()
982 master->ibi.num_slots = 15; in adi_i3c_master_probe()
983 master->ibi.slots = devm_kcalloc(&pdev->dev, master->ibi.num_slots, in adi_i3c_master_probe()
984 sizeof(*master->ibi.slots), in adi_i3c_master_probe()
986 if (!master->ibi.slots) in adi_i3c_master_probe()
989 spin_lock_init(&master->xferqueue.lock); in adi_i3c_master_probe()
990 INIT_LIST_HEAD(&master->xferqueue.list); in adi_i3c_master_probe()
992 return i3c_master_register(&master->base, &pdev->dev, in adi_i3c_master_probe()
998 struct adi_i3c_master *master = platform_get_drvdata(pdev); in adi_i3c_master_remove() local
1000 writel(0xff, master->regs + REG_IRQ_PENDING); in adi_i3c_master_remove()
1001 writel(0x00, master->regs + REG_IRQ_MASK); in adi_i3c_master_remove()
1002 writel(0x01, master->regs + REG_ENABLE); in adi_i3c_master_remove()
1004 i3c_master_unregister(&master->base); in adi_i3c_master_remove()