Lines Matching full:master
13 #include <linux/i3c/master.h>
296 to_dw_i3c_master(struct i3c_master_controller *master) in to_dw_i3c_master() argument
298 return container_of(master, struct dw_i3c_master, base); in to_dw_i3c_master()
301 static void dw_i3c_master_disable(struct dw_i3c_master *master) in dw_i3c_master_disable() argument
303 writel(readl(master->regs + DEVICE_CTRL) & ~DEV_CTRL_ENABLE, in dw_i3c_master_disable()
304 master->regs + DEVICE_CTRL); in dw_i3c_master_disable()
307 static void dw_i3c_master_enable(struct dw_i3c_master *master) in dw_i3c_master_enable() argument
309 writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_ENABLE, in dw_i3c_master_enable()
310 master->regs + DEVICE_CTRL); in dw_i3c_master_enable()
313 static int dw_i3c_master_get_addr_pos(struct dw_i3c_master *master, u8 addr) in dw_i3c_master_get_addr_pos() argument
317 for (pos = 0; pos < master->maxdevs; pos++) { in dw_i3c_master_get_addr_pos()
318 if (addr == master->addrs[pos]) in dw_i3c_master_get_addr_pos()
325 static int dw_i3c_master_get_free_pos(struct dw_i3c_master *master) in dw_i3c_master_get_free_pos() argument
327 if (!(master->free_pos & GENMASK(master->maxdevs - 1, 0))) in dw_i3c_master_get_free_pos()
330 return ffs(master->free_pos) - 1; in dw_i3c_master_get_free_pos()
333 static void dw_i3c_master_wr_tx_fifo(struct dw_i3c_master *master, in dw_i3c_master_wr_tx_fifo() argument
336 writesl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4); in dw_i3c_master_wr_tx_fifo()
341 writesl(master->regs + RX_TX_DATA_PORT, &tmp, 1); in dw_i3c_master_wr_tx_fifo()
345 static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, in dw_i3c_master_read_rx_fifo() argument
348 readsl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4); in dw_i3c_master_read_rx_fifo()
352 readsl(master->regs + RX_TX_DATA_PORT, &tmp, 1); in dw_i3c_master_read_rx_fifo()
358 dw_i3c_master_alloc_xfer(struct dw_i3c_master *master, unsigned int ncmds) in dw_i3c_master_alloc_xfer() argument
378 static void dw_i3c_master_start_xfer_locked(struct dw_i3c_master *master) in dw_i3c_master_start_xfer_locked() argument
380 struct dw_i3c_xfer *xfer = master->xferqueue.cur; in dw_i3c_master_start_xfer_locked()
390 dw_i3c_master_wr_tx_fifo(master, cmd->tx_buf, cmd->tx_len); in dw_i3c_master_start_xfer_locked()
393 thld_ctrl = readl(master->regs + QUEUE_THLD_CTRL); in dw_i3c_master_start_xfer_locked()
396 writel(thld_ctrl, master->regs + QUEUE_THLD_CTRL); in dw_i3c_master_start_xfer_locked()
401 writel(cmd->cmd_hi, master->regs + COMMAND_QUEUE_PORT); in dw_i3c_master_start_xfer_locked()
402 writel(cmd->cmd_lo, master->regs + COMMAND_QUEUE_PORT); in dw_i3c_master_start_xfer_locked()
406 static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master, in dw_i3c_master_enqueue_xfer() argument
412 spin_lock_irqsave(&master->xferqueue.lock, flags); in dw_i3c_master_enqueue_xfer()
413 if (master->xferqueue.cur) { in dw_i3c_master_enqueue_xfer()
414 list_add_tail(&xfer->node, &master->xferqueue.list); in dw_i3c_master_enqueue_xfer()
416 master->xferqueue.cur = xfer; in dw_i3c_master_enqueue_xfer()
417 dw_i3c_master_start_xfer_locked(master); in dw_i3c_master_enqueue_xfer()
419 spin_unlock_irqrestore(&master->xferqueue.lock, flags); in dw_i3c_master_enqueue_xfer()
422 static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master, in dw_i3c_master_dequeue_xfer_locked() argument
425 if (master->xferqueue.cur == xfer) { in dw_i3c_master_dequeue_xfer_locked()
428 master->xferqueue.cur = NULL; in dw_i3c_master_dequeue_xfer_locked()
432 master->regs + RESET_CTRL); in dw_i3c_master_dequeue_xfer_locked()
434 readl_poll_timeout_atomic(master->regs + RESET_CTRL, status, in dw_i3c_master_dequeue_xfer_locked()
441 static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master, in dw_i3c_master_dequeue_xfer() argument
446 spin_lock_irqsave(&master->xferqueue.lock, flags); in dw_i3c_master_dequeue_xfer()
447 dw_i3c_master_dequeue_xfer_locked(master, xfer); in dw_i3c_master_dequeue_xfer()
448 spin_unlock_irqrestore(&master->xferqueue.lock, flags); in dw_i3c_master_dequeue_xfer()
451 static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr) in dw_i3c_master_end_xfer_locked() argument
453 struct dw_i3c_xfer *xfer = master->xferqueue.cur; in dw_i3c_master_end_xfer_locked()
460 nresp = readl(master->regs + QUEUE_STATUS_LEVEL); in dw_i3c_master_end_xfer_locked()
467 resp = readl(master->regs + RESPONSE_QUEUE_PORT); in dw_i3c_master_end_xfer_locked()
473 dw_i3c_master_read_rx_fifo(master, cmd->rx_buf, in dw_i3c_master_end_xfer_locked()
503 dw_i3c_master_dequeue_xfer_locked(master, xfer); in dw_i3c_master_end_xfer_locked()
504 writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME, in dw_i3c_master_end_xfer_locked()
505 master->regs + DEVICE_CTRL); in dw_i3c_master_end_xfer_locked()
508 xfer = list_first_entry_or_null(&master->xferqueue.list, in dw_i3c_master_end_xfer_locked()
514 master->xferqueue.cur = xfer; in dw_i3c_master_end_xfer_locked()
515 dw_i3c_master_start_xfer_locked(master); in dw_i3c_master_end_xfer_locked()
518 static int dw_i3c_clk_cfg(struct dw_i3c_master *master) in dw_i3c_clk_cfg() argument
524 core_rate = clk_get_rate(master->core_clk); in dw_i3c_clk_cfg()
539 writel(scl_timing, master->regs + SCL_I3C_PP_TIMING); in dw_i3c_clk_cfg()
541 if (!(readl(master->regs + DEVICE_CTRL) & DEV_CTRL_I2C_SLAVE_PRESENT)) in dw_i3c_clk_cfg()
542 writel(BUS_I3C_MST_FREE(lcnt), master->regs + BUS_FREE_TIMING); in dw_i3c_clk_cfg()
546 writel(scl_timing, master->regs + SCL_I3C_OD_TIMING); in dw_i3c_clk_cfg()
556 writel(scl_timing, master->regs + SCL_EXT_LCNT_TIMING); in dw_i3c_clk_cfg()
561 static int dw_i2c_clk_cfg(struct dw_i3c_master *master) in dw_i2c_clk_cfg() argument
567 core_rate = clk_get_rate(master->core_clk); in dw_i2c_clk_cfg()
577 writel(scl_timing, master->regs + SCL_I2C_FMP_TIMING); in dw_i2c_clk_cfg()
583 writel(scl_timing, master->regs + SCL_I2C_FM_TIMING); in dw_i2c_clk_cfg()
585 writel(BUS_I3C_MST_FREE(lcnt), master->regs + BUS_FREE_TIMING); in dw_i2c_clk_cfg()
586 writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_I2C_SLAVE_PRESENT, in dw_i2c_clk_cfg()
587 master->regs + DEVICE_CTRL); in dw_i2c_clk_cfg()
594 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_bus_init() local
603 ret = dw_i2c_clk_cfg(master); in dw_i3c_master_bus_init()
608 ret = dw_i3c_clk_cfg(master); in dw_i3c_master_bus_init()
616 thld_ctrl = readl(master->regs + QUEUE_THLD_CTRL); in dw_i3c_master_bus_init()
618 writel(thld_ctrl, master->regs + QUEUE_THLD_CTRL); in dw_i3c_master_bus_init()
620 thld_ctrl = readl(master->regs + DATA_BUFFER_THLD_CTRL); in dw_i3c_master_bus_init()
622 writel(thld_ctrl, master->regs + DATA_BUFFER_THLD_CTRL); in dw_i3c_master_bus_init()
624 writel(INTR_ALL, master->regs + INTR_STATUS); in dw_i3c_master_bus_init()
625 writel(INTR_MASTER_MASK, master->regs + INTR_STATUS_EN); in dw_i3c_master_bus_init()
626 writel(INTR_MASTER_MASK, master->regs + INTR_SIGNAL_EN); in dw_i3c_master_bus_init()
633 master->regs + DEVICE_ADDR); in dw_i3c_master_bus_init()
638 ret = i3c_master_set_info(&master->base, &info); in dw_i3c_master_bus_init()
642 writel(IBI_REQ_REJECT_ALL, master->regs + IBI_SIR_REQ_REJECT); in dw_i3c_master_bus_init()
643 writel(IBI_REQ_REJECT_ALL, master->regs + IBI_MR_REQ_REJECT); in dw_i3c_master_bus_init()
646 writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_HOT_JOIN_NACK, in dw_i3c_master_bus_init()
647 master->regs + DEVICE_CTRL); in dw_i3c_master_bus_init()
649 dw_i3c_master_enable(master); in dw_i3c_master_bus_init()
656 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_bus_cleanup() local
658 dw_i3c_master_disable(master); in dw_i3c_master_bus_cleanup()
661 static int dw_i3c_ccc_set(struct dw_i3c_master *master, in dw_i3c_ccc_set() argument
669 pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr); in dw_i3c_ccc_set()
674 xfer = dw_i3c_master_alloc_xfer(master, 1); in dw_i3c_ccc_set()
691 dw_i3c_master_enqueue_xfer(master, xfer); in dw_i3c_ccc_set()
693 dw_i3c_master_dequeue_xfer(master, xfer); in dw_i3c_ccc_set()
704 static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc) in dw_i3c_ccc_get() argument
710 pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr); in dw_i3c_ccc_get()
714 xfer = dw_i3c_master_alloc_xfer(master, 1); in dw_i3c_ccc_get()
732 dw_i3c_master_enqueue_xfer(master, xfer); in dw_i3c_ccc_get()
734 dw_i3c_master_dequeue_xfer(master, xfer); in dw_i3c_ccc_get()
747 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_send_ccc_cmd() local
754 ret = dw_i3c_ccc_get(master, ccc); in dw_i3c_master_send_ccc_cmd()
756 ret = dw_i3c_ccc_set(master, ccc); in dw_i3c_master_send_ccc_cmd()
763 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_daa() local
770 olddevs = ~(master->free_pos); in dw_i3c_master_daa()
773 for (pos = 0; pos < master->maxdevs; pos++) { in dw_i3c_master_daa()
781 master->addrs[pos] = ret; in dw_i3c_master_daa()
787 master->regs + in dw_i3c_master_daa()
788 DEV_ADDR_TABLE_LOC(master->datstartaddr, pos)); in dw_i3c_master_daa()
791 xfer = dw_i3c_master_alloc_xfer(master, 1); in dw_i3c_master_daa()
795 pos = dw_i3c_master_get_free_pos(master); in dw_i3c_master_daa()
798 cmd->cmd_lo = COMMAND_PORT_DEV_COUNT(master->maxdevs - pos) | in dw_i3c_master_daa()
805 dw_i3c_master_enqueue_xfer(master, xfer); in dw_i3c_master_daa()
807 dw_i3c_master_dequeue_xfer(master, xfer); in dw_i3c_master_daa()
809 newdevs = GENMASK(master->maxdevs - cmd->rx_len - 1, 0); in dw_i3c_master_daa()
812 for (pos = 0; pos < master->maxdevs; pos++) { in dw_i3c_master_daa()
814 i3c_master_add_i3c_dev_locked(m, master->addrs[pos]); in dw_i3c_master_daa()
828 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_priv_xfers() local
836 if (i3c_nxfers > master->caps.cmdfifodepth) in dw_i3c_master_priv_xfers()
846 if (ntxwords > master->caps.datafifodepth || in dw_i3c_master_priv_xfers()
847 nrxwords > master->caps.datafifodepth) in dw_i3c_master_priv_xfers()
850 xfer = dw_i3c_master_alloc_xfer(master, i3c_nxfers); in dw_i3c_master_priv_xfers()
881 dw_i3c_master_enqueue_xfer(master, xfer); in dw_i3c_master_priv_xfers()
883 dw_i3c_master_dequeue_xfer(master, xfer); in dw_i3c_master_priv_xfers()
896 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_reattach_i3c_dev() local
899 pos = dw_i3c_master_get_free_pos(master); in dw_i3c_master_reattach_i3c_dev()
903 master->regs + in dw_i3c_master_reattach_i3c_dev()
904 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); in dw_i3c_master_reattach_i3c_dev()
906 master->addrs[data->index] = 0; in dw_i3c_master_reattach_i3c_dev()
907 master->free_pos |= BIT(data->index); in dw_i3c_master_reattach_i3c_dev()
910 master->addrs[pos] = dev->info.dyn_addr; in dw_i3c_master_reattach_i3c_dev()
911 master->free_pos &= ~BIT(pos); in dw_i3c_master_reattach_i3c_dev()
915 master->regs + in dw_i3c_master_reattach_i3c_dev()
916 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); in dw_i3c_master_reattach_i3c_dev()
918 master->addrs[data->index] = dev->info.dyn_addr; in dw_i3c_master_reattach_i3c_dev()
926 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_attach_i3c_dev() local
930 pos = dw_i3c_master_get_free_pos(master); in dw_i3c_master_attach_i3c_dev()
939 master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr; in dw_i3c_master_attach_i3c_dev()
940 master->free_pos &= ~BIT(pos); in dw_i3c_master_attach_i3c_dev()
943 writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]), in dw_i3c_master_attach_i3c_dev()
944 master->regs + in dw_i3c_master_attach_i3c_dev()
945 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); in dw_i3c_master_attach_i3c_dev()
954 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_detach_i3c_dev() local
957 master->regs + in dw_i3c_master_detach_i3c_dev()
958 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); in dw_i3c_master_detach_i3c_dev()
961 master->addrs[data->index] = 0; in dw_i3c_master_detach_i3c_dev()
962 master->free_pos |= BIT(data->index); in dw_i3c_master_detach_i3c_dev()
972 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_i2c_xfers() local
980 if (i2c_nxfers > master->caps.cmdfifodepth) in dw_i3c_master_i2c_xfers()
990 if (ntxwords > master->caps.datafifodepth || in dw_i3c_master_i2c_xfers()
991 nrxwords > master->caps.datafifodepth) in dw_i3c_master_i2c_xfers()
994 xfer = dw_i3c_master_alloc_xfer(master, i2c_nxfers); in dw_i3c_master_i2c_xfers()
1021 dw_i3c_master_enqueue_xfer(master, xfer); in dw_i3c_master_i2c_xfers()
1023 dw_i3c_master_dequeue_xfer(master, xfer); in dw_i3c_master_i2c_xfers()
1034 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_attach_i2c_dev() local
1038 pos = dw_i3c_master_get_free_pos(master); in dw_i3c_master_attach_i2c_dev()
1047 master->addrs[pos] = dev->addr; in dw_i3c_master_attach_i2c_dev()
1048 master->free_pos &= ~BIT(pos); in dw_i3c_master_attach_i2c_dev()
1053 master->regs + in dw_i3c_master_attach_i2c_dev()
1054 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); in dw_i3c_master_attach_i2c_dev()
1063 struct dw_i3c_master *master = to_dw_i3c_master(m); in dw_i3c_master_detach_i2c_dev() local
1066 master->regs + in dw_i3c_master_detach_i2c_dev()
1067 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); in dw_i3c_master_detach_i2c_dev()
1070 master->addrs[data->index] = 0; in dw_i3c_master_detach_i2c_dev()
1071 master->free_pos |= BIT(data->index); in dw_i3c_master_detach_i2c_dev()
1077 struct dw_i3c_master *master = dev_id; in dw_i3c_master_irq_handler() local
1080 status = readl(master->regs + INTR_STATUS); in dw_i3c_master_irq_handler()
1082 if (!(status & readl(master->regs + INTR_STATUS_EN))) { in dw_i3c_master_irq_handler()
1083 writel(INTR_ALL, master->regs + INTR_STATUS); in dw_i3c_master_irq_handler()
1087 spin_lock(&master->xferqueue.lock); in dw_i3c_master_irq_handler()
1088 dw_i3c_master_end_xfer_locked(master, status); in dw_i3c_master_irq_handler()
1090 writel(INTR_TRANSFER_ERR_STAT, master->regs + INTR_STATUS); in dw_i3c_master_irq_handler()
1091 spin_unlock(&master->xferqueue.lock); in dw_i3c_master_irq_handler()
1113 struct dw_i3c_master *master; in dw_i3c_probe() local
1116 master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); in dw_i3c_probe()
1117 if (!master) in dw_i3c_probe()
1120 master->regs = devm_platform_ioremap_resource(pdev, 0); in dw_i3c_probe()
1121 if (IS_ERR(master->regs)) in dw_i3c_probe()
1122 return PTR_ERR(master->regs); in dw_i3c_probe()
1124 master->core_clk = devm_clk_get(&pdev->dev, NULL); in dw_i3c_probe()
1125 if (IS_ERR(master->core_clk)) in dw_i3c_probe()
1126 return PTR_ERR(master->core_clk); in dw_i3c_probe()
1128 master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev, in dw_i3c_probe()
1130 if (IS_ERR(master->core_rst)) in dw_i3c_probe()
1131 return PTR_ERR(master->core_rst); in dw_i3c_probe()
1133 ret = clk_prepare_enable(master->core_clk); in dw_i3c_probe()
1137 reset_control_deassert(master->core_rst); in dw_i3c_probe()
1139 spin_lock_init(&master->xferqueue.lock); in dw_i3c_probe()
1140 INIT_LIST_HEAD(&master->xferqueue.list); in dw_i3c_probe()
1142 writel(INTR_ALL, master->regs + INTR_STATUS); in dw_i3c_probe()
1146 dev_name(&pdev->dev), master); in dw_i3c_probe()
1150 platform_set_drvdata(pdev, master); in dw_i3c_probe()
1153 ret = readl(master->regs + QUEUE_STATUS_LEVEL); in dw_i3c_probe()
1154 master->caps.cmdfifodepth = QUEUE_STATUS_LEVEL_CMD(ret); in dw_i3c_probe()
1156 ret = readl(master->regs + DATA_BUFFER_STATUS_LEVEL); in dw_i3c_probe()
1157 master->caps.datafifodepth = DATA_BUFFER_STATUS_LEVEL_TX(ret); in dw_i3c_probe()
1159 ret = readl(master->regs + DEVICE_ADDR_TABLE_POINTER); in dw_i3c_probe()
1160 master->datstartaddr = ret; in dw_i3c_probe()
1161 master->maxdevs = ret >> 16; in dw_i3c_probe()
1162 master->free_pos = GENMASK(master->maxdevs - 1, 0); in dw_i3c_probe()
1164 ret = i3c_master_register(&master->base, &pdev->dev, in dw_i3c_probe()
1172 reset_control_assert(master->core_rst); in dw_i3c_probe()
1175 clk_disable_unprepare(master->core_clk); in dw_i3c_probe()
1182 struct dw_i3c_master *master = platform_get_drvdata(pdev); in dw_i3c_remove() local
1185 ret = i3c_master_unregister(&master->base); in dw_i3c_remove()
1189 reset_control_assert(master->core_rst); in dw_i3c_remove()
1191 clk_disable_unprepare(master->core_clk); in dw_i3c_remove()
1197 { .compatible = "snps,dw-i3c-master-1.00a", },
1206 .name = "dw-i3c-master",