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

1 // SPDX-License-Identifier: GPL-2.0
12 #include <linux/i3c/master.h>
422 to_cdns_i3c_master(struct i3c_master_controller *master) in to_cdns_i3c_master() argument
424 return container_of(master, struct cdns_i3c_master, base); in to_cdns_i3c_master()
427 static void cdns_i3c_master_wr_to_tx_fifo(struct cdns_i3c_master *master, in cdns_i3c_master_wr_to_tx_fifo() argument
430 writesl(master->regs + TX_FIFO, bytes, nbytes / 4); in cdns_i3c_master_wr_to_tx_fifo()
435 writesl(master->regs + TX_FIFO, &tmp, 1); in cdns_i3c_master_wr_to_tx_fifo()
439 static void cdns_i3c_master_rd_from_rx_fifo(struct cdns_i3c_master *master, in cdns_i3c_master_rd_from_rx_fifo() argument
442 readsl(master->regs + RX_FIFO, bytes, nbytes / 4); in cdns_i3c_master_rd_from_rx_fifo()
446 readsl(master->regs + RX_FIFO, &tmp, 1); in cdns_i3c_master_rd_from_rx_fifo()
454 if (cmd->ndests > 1) in cdns_i3c_master_supports_ccc_cmd()
457 switch (cmd->id) { in cdns_i3c_master_supports_ccc_cmd()
492 static int cdns_i3c_master_disable(struct cdns_i3c_master *master) in cdns_i3c_master_disable() argument
496 writel(readl(master->regs + CTRL) & ~CTRL_DEV_EN, master->regs + CTRL); in cdns_i3c_master_disable()
498 return readl_poll_timeout(master->regs + MST_STATUS0, status, in cdns_i3c_master_disable()
502 static void cdns_i3c_master_enable(struct cdns_i3c_master *master) in cdns_i3c_master_enable() argument
504 writel(readl(master->regs + CTRL) | CTRL_DEV_EN, master->regs + CTRL); in cdns_i3c_master_enable()
508 cdns_i3c_master_alloc_xfer(struct cdns_i3c_master *master, unsigned int ncmds) in cdns_i3c_master_alloc_xfer() argument
516 INIT_LIST_HEAD(&xfer->node); in cdns_i3c_master_alloc_xfer()
517 xfer->ncmds = ncmds; in cdns_i3c_master_alloc_xfer()
518 xfer->ret = -ETIMEDOUT; in cdns_i3c_master_alloc_xfer()
528 static void cdns_i3c_master_start_xfer_locked(struct cdns_i3c_master *master) in cdns_i3c_master_start_xfer_locked() argument
530 struct cdns_i3c_xfer *xfer = master->xferqueue.cur; in cdns_i3c_master_start_xfer_locked()
536 writel(MST_INT_CMDD_EMP, master->regs + MST_ICR); in cdns_i3c_master_start_xfer_locked()
537 for (i = 0; i < xfer->ncmds; i++) { in cdns_i3c_master_start_xfer_locked()
538 struct cdns_i3c_cmd *cmd = &xfer->cmds[i]; in cdns_i3c_master_start_xfer_locked()
540 cdns_i3c_master_wr_to_tx_fifo(master, cmd->tx_buf, in cdns_i3c_master_start_xfer_locked()
541 cmd->tx_len); in cdns_i3c_master_start_xfer_locked()
544 for (i = 0; i < xfer->ncmds; i++) { in cdns_i3c_master_start_xfer_locked()
545 struct cdns_i3c_cmd *cmd = &xfer->cmds[i]; in cdns_i3c_master_start_xfer_locked()
547 writel(cmd->cmd1 | CMD1_FIFO_CMDID(i), in cdns_i3c_master_start_xfer_locked()
548 master->regs + CMD1_FIFO); in cdns_i3c_master_start_xfer_locked()
549 writel(cmd->cmd0, master->regs + CMD0_FIFO); in cdns_i3c_master_start_xfer_locked()
552 writel(readl(master->regs + CTRL) | CTRL_MCS, in cdns_i3c_master_start_xfer_locked()
553 master->regs + CTRL); in cdns_i3c_master_start_xfer_locked()
554 writel(MST_INT_CMDD_EMP, master->regs + MST_IER); in cdns_i3c_master_start_xfer_locked()
557 static void cdns_i3c_master_end_xfer_locked(struct cdns_i3c_master *master, in cdns_i3c_master_end_xfer_locked() argument
560 struct cdns_i3c_xfer *xfer = master->xferqueue.cur; in cdns_i3c_master_end_xfer_locked()
570 writel(MST_INT_CMDD_EMP, master->regs + MST_IDR); in cdns_i3c_master_end_xfer_locked()
572 for (status0 = readl(master->regs + MST_STATUS0); in cdns_i3c_master_end_xfer_locked()
574 status0 = readl(master->regs + MST_STATUS0)) { in cdns_i3c_master_end_xfer_locked()
578 cmdr = readl(master->regs + CMDR); in cdns_i3c_master_end_xfer_locked()
582 WARN_ON(id >= xfer->ncmds)) in cdns_i3c_master_end_xfer_locked()
585 cmd = &xfer->cmds[CMDR_CMDID(cmdr)]; in cdns_i3c_master_end_xfer_locked()
586 rx_len = min_t(u32, CMDR_XFER_BYTES(cmdr), cmd->rx_len); in cdns_i3c_master_end_xfer_locked()
587 cdns_i3c_master_rd_from_rx_fifo(master, cmd->rx_buf, rx_len); in cdns_i3c_master_end_xfer_locked()
588 cmd->error = CMDR_ERROR(cmdr); in cdns_i3c_master_end_xfer_locked()
591 for (i = 0; i < xfer->ncmds; i++) { in cdns_i3c_master_end_xfer_locked()
592 switch (xfer->cmds[i].error) { in cdns_i3c_master_end_xfer_locked()
604 ret = -EIO; in cdns_i3c_master_end_xfer_locked()
609 ret = -ENOSPC; in cdns_i3c_master_end_xfer_locked()
614 ret = -EINVAL; in cdns_i3c_master_end_xfer_locked()
619 xfer->ret = ret; in cdns_i3c_master_end_xfer_locked()
620 complete(&xfer->comp); in cdns_i3c_master_end_xfer_locked()
622 xfer = list_first_entry_or_null(&master->xferqueue.list, in cdns_i3c_master_end_xfer_locked()
625 list_del_init(&xfer->node); in cdns_i3c_master_end_xfer_locked()
627 master->xferqueue.cur = xfer; in cdns_i3c_master_end_xfer_locked()
628 cdns_i3c_master_start_xfer_locked(master); in cdns_i3c_master_end_xfer_locked()
631 static void cdns_i3c_master_queue_xfer(struct cdns_i3c_master *master, in cdns_i3c_master_queue_xfer() argument
636 init_completion(&xfer->comp); in cdns_i3c_master_queue_xfer()
637 spin_lock_irqsave(&master->xferqueue.lock, flags); in cdns_i3c_master_queue_xfer()
638 if (master->xferqueue.cur) { in cdns_i3c_master_queue_xfer()
639 list_add_tail(&xfer->node, &master->xferqueue.list); in cdns_i3c_master_queue_xfer()
641 master->xferqueue.cur = xfer; in cdns_i3c_master_queue_xfer()
642 cdns_i3c_master_start_xfer_locked(master); in cdns_i3c_master_queue_xfer()
644 spin_unlock_irqrestore(&master->xferqueue.lock, flags); in cdns_i3c_master_queue_xfer()
647 static void cdns_i3c_master_unqueue_xfer(struct cdns_i3c_master *master, in cdns_i3c_master_unqueue_xfer() argument
652 spin_lock_irqsave(&master->xferqueue.lock, flags); in cdns_i3c_master_unqueue_xfer()
653 if (master->xferqueue.cur == xfer) { in cdns_i3c_master_unqueue_xfer()
656 writel(readl(master->regs + CTRL) & ~CTRL_DEV_EN, in cdns_i3c_master_unqueue_xfer()
657 master->regs + CTRL); in cdns_i3c_master_unqueue_xfer()
658 readl_poll_timeout_atomic(master->regs + MST_STATUS0, status, in cdns_i3c_master_unqueue_xfer()
661 master->xferqueue.cur = NULL; in cdns_i3c_master_unqueue_xfer()
664 master->regs + FLUSH_CTRL); in cdns_i3c_master_unqueue_xfer()
665 writel(MST_INT_CMDD_EMP, master->regs + MST_IDR); in cdns_i3c_master_unqueue_xfer()
666 writel(readl(master->regs + CTRL) | CTRL_DEV_EN, in cdns_i3c_master_unqueue_xfer()
667 master->regs + CTRL); in cdns_i3c_master_unqueue_xfer()
669 list_del_init(&xfer->node); in cdns_i3c_master_unqueue_xfer()
671 spin_unlock_irqrestore(&master->xferqueue.lock, flags); in cdns_i3c_master_unqueue_xfer()
676 switch (cmd->error) { in cdns_i3c_cmd_get_err()
697 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_send_ccc_cmd() local
702 xfer = cdns_i3c_master_alloc_xfer(master, 1); in cdns_i3c_master_send_ccc_cmd()
704 return -ENOMEM; in cdns_i3c_master_send_ccc_cmd()
706 ccmd = xfer->cmds; in cdns_i3c_master_send_ccc_cmd()
707 ccmd->cmd1 = CMD1_FIFO_CCC(cmd->id); in cdns_i3c_master_send_ccc_cmd()
708 ccmd->cmd0 = CMD0_FIFO_IS_CCC | in cdns_i3c_master_send_ccc_cmd()
709 CMD0_FIFO_PL_LEN(cmd->dests[0].payload.len); in cdns_i3c_master_send_ccc_cmd()
711 if (cmd->id & I3C_CCC_DIRECT) in cdns_i3c_master_send_ccc_cmd()
712 ccmd->cmd0 |= CMD0_FIFO_DEV_ADDR(cmd->dests[0].addr); in cdns_i3c_master_send_ccc_cmd()
714 if (cmd->rnw) { in cdns_i3c_master_send_ccc_cmd()
715 ccmd->cmd0 |= CMD0_FIFO_RNW; in cdns_i3c_master_send_ccc_cmd()
716 ccmd->rx_buf = cmd->dests[0].payload.data; in cdns_i3c_master_send_ccc_cmd()
717 ccmd->rx_len = cmd->dests[0].payload.len; in cdns_i3c_master_send_ccc_cmd()
719 ccmd->tx_buf = cmd->dests[0].payload.data; in cdns_i3c_master_send_ccc_cmd()
720 ccmd->tx_len = cmd->dests[0].payload.len; in cdns_i3c_master_send_ccc_cmd()
723 cdns_i3c_master_queue_xfer(master, xfer); in cdns_i3c_master_send_ccc_cmd()
724 if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) in cdns_i3c_master_send_ccc_cmd()
725 cdns_i3c_master_unqueue_xfer(master, xfer); in cdns_i3c_master_send_ccc_cmd()
727 ret = xfer->ret; in cdns_i3c_master_send_ccc_cmd()
728 cmd->err = cdns_i3c_cmd_get_err(&xfer->cmds[0]); in cdns_i3c_master_send_ccc_cmd()
739 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_priv_xfers() local
745 return -ENOTSUPP; in cdns_i3c_master_priv_xfers()
751 if (nxfers > master->caps.cmdfifodepth || in cdns_i3c_master_priv_xfers()
752 nxfers > master->caps.cmdrfifodepth) in cdns_i3c_master_priv_xfers()
753 return -ENOTSUPP; in cdns_i3c_master_priv_xfers()
766 if (rxslots > master->caps.rxfifodepth || in cdns_i3c_master_priv_xfers()
767 txslots > master->caps.txfifodepth) in cdns_i3c_master_priv_xfers()
768 return -ENOTSUPP; in cdns_i3c_master_priv_xfers()
770 cdns_xfer = cdns_i3c_master_alloc_xfer(master, nxfers); in cdns_i3c_master_priv_xfers()
772 return -ENOMEM; in cdns_i3c_master_priv_xfers()
775 struct cdns_i3c_cmd *ccmd = &cdns_xfer->cmds[i]; in cdns_i3c_master_priv_xfers()
778 ccmd->cmd0 = CMD0_FIFO_DEV_ADDR(dev->info.dyn_addr) | in cdns_i3c_master_priv_xfers()
782 ccmd->cmd0 |= CMD0_FIFO_RNW; in cdns_i3c_master_priv_xfers()
783 ccmd->rx_buf = xfers[i].data.in; in cdns_i3c_master_priv_xfers()
784 ccmd->rx_len = xfers[i].len; in cdns_i3c_master_priv_xfers()
787 ccmd->tx_buf = xfers[i].data.out; in cdns_i3c_master_priv_xfers()
788 ccmd->tx_len = xfers[i].len; in cdns_i3c_master_priv_xfers()
791 ccmd->cmd0 |= CMD0_FIFO_PL_LEN(pl_len); in cdns_i3c_master_priv_xfers()
793 if (i < nxfers - 1) in cdns_i3c_master_priv_xfers()
794 ccmd->cmd0 |= CMD0_FIFO_RSBC; in cdns_i3c_master_priv_xfers()
797 ccmd->cmd0 |= CMD0_FIFO_BCH; in cdns_i3c_master_priv_xfers()
800 cdns_i3c_master_queue_xfer(master, cdns_xfer); in cdns_i3c_master_priv_xfers()
801 if (!wait_for_completion_timeout(&cdns_xfer->comp, in cdns_i3c_master_priv_xfers()
803 cdns_i3c_master_unqueue_xfer(master, cdns_xfer); in cdns_i3c_master_priv_xfers()
805 ret = cdns_xfer->ret; in cdns_i3c_master_priv_xfers()
808 xfers[i].err = cdns_i3c_cmd_get_err(&cdns_xfer->cmds[i]); in cdns_i3c_master_priv_xfers()
819 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_i2c_xfers() local
824 if (nxfers > master->caps.cmdfifodepth) in cdns_i3c_master_i2c_xfers()
825 return -ENOTSUPP; in cdns_i3c_master_i2c_xfers()
829 return -ENOTSUPP; in cdns_i3c_master_i2c_xfers()
837 if (ntxwords > master->caps.txfifodepth || in cdns_i3c_master_i2c_xfers()
838 nrxwords > master->caps.rxfifodepth) in cdns_i3c_master_i2c_xfers()
839 return -ENOTSUPP; in cdns_i3c_master_i2c_xfers()
841 xfer = cdns_i3c_master_alloc_xfer(master, nxfers); in cdns_i3c_master_i2c_xfers()
843 return -ENOMEM; in cdns_i3c_master_i2c_xfers()
846 struct cdns_i3c_cmd *ccmd = &xfer->cmds[i]; in cdns_i3c_master_i2c_xfers()
848 ccmd->cmd0 = CMD0_FIFO_DEV_ADDR(xfers[i].addr) | in cdns_i3c_master_i2c_xfers()
853 ccmd->cmd0 |= CMD0_FIFO_IS_10B; in cdns_i3c_master_i2c_xfers()
856 ccmd->cmd0 |= CMD0_FIFO_RNW; in cdns_i3c_master_i2c_xfers()
857 ccmd->rx_buf = xfers[i].buf; in cdns_i3c_master_i2c_xfers()
858 ccmd->rx_len = xfers[i].len; in cdns_i3c_master_i2c_xfers()
860 ccmd->tx_buf = xfers[i].buf; in cdns_i3c_master_i2c_xfers()
861 ccmd->tx_len = xfers[i].len; in cdns_i3c_master_i2c_xfers()
865 cdns_i3c_master_queue_xfer(master, xfer); in cdns_i3c_master_i2c_xfers()
866 if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000))) in cdns_i3c_master_i2c_xfers()
867 cdns_i3c_master_unqueue_xfer(master, xfer); in cdns_i3c_master_i2c_xfers()
869 ret = xfer->ret; in cdns_i3c_master_i2c_xfers()
900 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_upd_i3c_addr() local
904 rr = prepare_rr0_dev_address(dev->info.dyn_addr ? in cdns_i3c_master_upd_i3c_addr()
905 dev->info.dyn_addr : in cdns_i3c_master_upd_i3c_addr()
906 dev->info.static_addr); in cdns_i3c_master_upd_i3c_addr()
907 writel(DEV_ID_RR0_IS_I3C | rr, master->regs + DEV_ID_RR0(data->id)); in cdns_i3c_master_upd_i3c_addr()
910 static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master, in cdns_i3c_master_get_rr_slot() argument
918 if (!master->free_rr_slots) in cdns_i3c_master_get_rr_slot()
919 return -ENOSPC; in cdns_i3c_master_get_rr_slot()
921 return ffs(master->free_rr_slots) - 1; in cdns_i3c_master_get_rr_slot()
924 activedevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; in cdns_i3c_master_get_rr_slot()
927 for_each_set_bit(i, &activedevs, master->maxdevs + 1) { in cdns_i3c_master_get_rr_slot()
928 rr = readl(master->regs + DEV_ID_RR0(i)); in cdns_i3c_master_get_rr_slot()
936 return -EINVAL; in cdns_i3c_master_get_rr_slot()
950 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_attach_i3c_dev() local
956 return -ENOMEM; in cdns_i3c_master_attach_i3c_dev()
958 slot = cdns_i3c_master_get_rr_slot(master, dev->info.dyn_addr); in cdns_i3c_master_attach_i3c_dev()
964 data->ibi = -1; in cdns_i3c_master_attach_i3c_dev()
965 data->id = slot; in cdns_i3c_master_attach_i3c_dev()
967 master->free_rr_slots &= ~BIT(slot); in cdns_i3c_master_attach_i3c_dev()
969 if (!dev->info.dyn_addr) { in cdns_i3c_master_attach_i3c_dev()
971 writel(readl(master->regs + DEVS_CTRL) | in cdns_i3c_master_attach_i3c_dev()
972 DEVS_CTRL_DEV_ACTIVE(data->id), in cdns_i3c_master_attach_i3c_dev()
973 master->regs + DEVS_CTRL); in cdns_i3c_master_attach_i3c_dev()
982 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_detach_i3c_dev() local
985 writel(readl(master->regs + DEVS_CTRL) | in cdns_i3c_master_detach_i3c_dev()
986 DEVS_CTRL_DEV_CLR(data->id), in cdns_i3c_master_detach_i3c_dev()
987 master->regs + DEVS_CTRL); in cdns_i3c_master_detach_i3c_dev()
990 master->free_rr_slots |= BIT(data->id); in cdns_i3c_master_detach_i3c_dev()
997 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_attach_i2c_dev() local
1001 slot = cdns_i3c_master_get_rr_slot(master, 0); in cdns_i3c_master_attach_i2c_dev()
1007 return -ENOMEM; in cdns_i3c_master_attach_i2c_dev()
1009 data->id = slot; in cdns_i3c_master_attach_i2c_dev()
1010 master->free_rr_slots &= ~BIT(slot); in cdns_i3c_master_attach_i2c_dev()
1013 writel(prepare_rr0_dev_address(dev->addr), in cdns_i3c_master_attach_i2c_dev()
1014 master->regs + DEV_ID_RR0(data->id)); in cdns_i3c_master_attach_i2c_dev()
1015 writel(dev->lvr, master->regs + DEV_ID_RR2(data->id)); in cdns_i3c_master_attach_i2c_dev()
1016 writel(readl(master->regs + DEVS_CTRL) | in cdns_i3c_master_attach_i2c_dev()
1017 DEVS_CTRL_DEV_ACTIVE(data->id), in cdns_i3c_master_attach_i2c_dev()
1018 master->regs + DEVS_CTRL); in cdns_i3c_master_attach_i2c_dev()
1026 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_detach_i2c_dev() local
1029 writel(readl(master->regs + DEVS_CTRL) | in cdns_i3c_master_detach_i2c_dev()
1030 DEVS_CTRL_DEV_CLR(data->id), in cdns_i3c_master_detach_i2c_dev()
1031 master->regs + DEVS_CTRL); in cdns_i3c_master_detach_i2c_dev()
1032 master->free_rr_slots |= BIT(data->id); in cdns_i3c_master_detach_i2c_dev()
1040 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_bus_cleanup() local
1042 cdns_i3c_master_disable(master); in cdns_i3c_master_bus_cleanup()
1045 static void cdns_i3c_master_dev_rr_to_info(struct cdns_i3c_master *master, in cdns_i3c_master_dev_rr_to_info() argument
1052 rr = readl(master->regs + DEV_ID_RR0(slot)); in cdns_i3c_master_dev_rr_to_info()
1053 info->dyn_addr = DEV_ID_RR0_GET_DEV_ADDR(rr); in cdns_i3c_master_dev_rr_to_info()
1054 rr = readl(master->regs + DEV_ID_RR2(slot)); in cdns_i3c_master_dev_rr_to_info()
1055 info->dcr = rr; in cdns_i3c_master_dev_rr_to_info()
1056 info->bcr = rr >> 8; in cdns_i3c_master_dev_rr_to_info()
1057 info->pid = rr >> 16; in cdns_i3c_master_dev_rr_to_info()
1058 info->pid |= (u64)readl(master->regs + DEV_ID_RR1(slot)) << 16; in cdns_i3c_master_dev_rr_to_info()
1061 static void cdns_i3c_master_upd_i3c_scl_lim(struct cdns_i3c_master *master) in cdns_i3c_master_upd_i3c_scl_lim() argument
1063 struct i3c_master_controller *m = &master->base; in cdns_i3c_master_upd_i3c_scl_lim()
1073 max_fscl = max(I3C_CCC_MAX_SDR_FSCL(dev->info.max_read_ds), in cdns_i3c_master_upd_i3c_scl_lim()
1074 I3C_CCC_MAX_SDR_FSCL(dev->info.max_write_ds)); in cdns_i3c_master_upd_i3c_scl_lim()
1099 /* Only update PRESCL_CTRL1 if the I3C SCL limitation has changed. */ in cdns_i3c_master_upd_i3c_scl_lim()
1100 if (new_i3c_scl_lim == master->i3c_scl_lim) in cdns_i3c_master_upd_i3c_scl_lim()
1102 master->i3c_scl_lim = new_i3c_scl_lim; in cdns_i3c_master_upd_i3c_scl_lim()
1105 pres_step = 1000000000UL / (bus->scl_rate.i3c * 4); in cdns_i3c_master_upd_i3c_scl_lim()
1107 /* Configure PP_LOW to meet I3C slave limitations. */ in cdns_i3c_master_upd_i3c_scl_lim()
1108 prescl1 = readl(master->regs + PRESCL_CTRL1) & in cdns_i3c_master_upd_i3c_scl_lim()
1110 ctrl = readl(master->regs + CTRL); in cdns_i3c_master_upd_i3c_scl_lim()
1112 i3c_lim_period = DIV_ROUND_UP(1000000000, master->i3c_scl_lim); in cdns_i3c_master_upd_i3c_scl_lim()
1117 ncycles -= 4; in cdns_i3c_master_upd_i3c_scl_lim()
1121 /* Disable I3C master before updating PRESCL_CTRL1. */ in cdns_i3c_master_upd_i3c_scl_lim()
1123 cdns_i3c_master_disable(master); in cdns_i3c_master_upd_i3c_scl_lim()
1125 writel(prescl1, master->regs + PRESCL_CTRL1); in cdns_i3c_master_upd_i3c_scl_lim()
1128 cdns_i3c_master_enable(master); in cdns_i3c_master_upd_i3c_scl_lim()
1133 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_do_daa() local
1139 olddevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; in cdns_i3c_master_do_daa()
1143 for_each_clear_bit(slot, &olddevs, master->maxdevs + 1) { in cdns_i3c_master_do_daa()
1146 return -ENOSPC; in cdns_i3c_master_do_daa()
1151 master->regs + DEV_ID_RR0(slot)); in cdns_i3c_master_do_daa()
1152 writel(0, master->regs + DEV_ID_RR1(slot)); in cdns_i3c_master_do_daa()
1153 writel(0, master->regs + DEV_ID_RR2(slot)); in cdns_i3c_master_do_daa()
1156 ret = i3c_master_entdaa_locked(&master->base); in cdns_i3c_master_do_daa()
1160 newdevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK; in cdns_i3c_master_do_daa()
1167 for_each_set_bit(slot, &newdevs, master->maxdevs + 1) in cdns_i3c_master_do_daa()
1171 * Clear slots that ended up not being used. Can be caused by I3C in cdns_i3c_master_do_daa()
1172 * device creation failure or when the I3C device was already known in cdns_i3c_master_do_daa()
1176 writel(readl(master->regs + DEVS_CTRL) | in cdns_i3c_master_do_daa()
1177 master->free_rr_slots << DEVS_CTRL_DEV_CLR_SHIFT, in cdns_i3c_master_do_daa()
1178 master->regs + DEVS_CTRL); in cdns_i3c_master_do_daa()
1180 i3c_master_defslvs_locked(&master->base); in cdns_i3c_master_do_daa()
1182 cdns_i3c_master_upd_i3c_scl_lim(master); in cdns_i3c_master_do_daa()
1184 /* Unmask Hot-Join and Mastership request interrupts. */ in cdns_i3c_master_do_daa()
1191 static u8 cdns_i3c_master_calculate_thd_delay(struct cdns_i3c_master *master) in cdns_i3c_master_calculate_thd_delay() argument
1193 unsigned long sysclk_rate = clk_get_rate(master->sysclk); in cdns_i3c_master_calculate_thd_delay()
1194 u8 thd_delay = DIV_ROUND_UP(master->devdata->thd_delay_ns, in cdns_i3c_master_calculate_thd_delay()
1202 return (THD_DELAY_MAX - thd_delay); in cdns_i3c_master_calculate_thd_delay()
1207 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_bus_init() local
1214 switch (bus->mode) { in cdns_i3c_master_bus_init()
1228 return -EINVAL; in cdns_i3c_master_bus_init()
1231 sysclk_rate = clk_get_rate(master->sysclk); in cdns_i3c_master_bus_init()
1233 return -EINVAL; in cdns_i3c_master_bus_init()
1235 pres = DIV_ROUND_UP(sysclk_rate, (bus->scl_rate.i3c * 4)) - 1; in cdns_i3c_master_bus_init()
1237 return -ERANGE; in cdns_i3c_master_bus_init()
1239 bus->scl_rate.i3c = sysclk_rate / ((pres + 1) * 4); in cdns_i3c_master_bus_init()
1243 low = ((I3C_BUS_TLOW_OD_MIN_NS * sysclk_rate) / (pres + 1)) - 2; in cdns_i3c_master_bus_init()
1246 max_i2cfreq = bus->scl_rate.i2c; in cdns_i3c_master_bus_init()
1248 pres = (sysclk_rate / (max_i2cfreq * 5)) - 1; in cdns_i3c_master_bus_init()
1250 return -ERANGE; in cdns_i3c_master_bus_init()
1252 bus->scl_rate.i2c = sysclk_rate / ((pres + 1) * 5); in cdns_i3c_master_bus_init()
1255 writel(prescl0, master->regs + PRESCL_CTRL0); in cdns_i3c_master_bus_init()
1258 pres_step = 1000000000 / (bus->scl_rate.i3c * 4); in cdns_i3c_master_bus_init()
1259 ncycles = DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, pres_step) - 2; in cdns_i3c_master_bus_init()
1263 writel(prescl1, master->regs + PRESCL_CTRL1); in cdns_i3c_master_bus_init()
1265 /* Get an address for the master. */ in cdns_i3c_master_bus_init()
1271 master->regs + DEV_ID_RR0(0)); in cdns_i3c_master_bus_init()
1273 cdns_i3c_master_dev_rr_to_info(master, 0, &info); in cdns_i3c_master_bus_init()
1277 ret = i3c_master_set_info(&master->base, &info); in cdns_i3c_master_bus_init()
1282 * Enable Hot-Join, and, when a Hot-Join request happens, disable all in cdns_i3c_master_bus_init()
1290 * Configure data hold delay based on device-specific data. in cdns_i3c_master_bus_init()
1292 * MIPI I3C Specification 1.0 defines non-zero minimal tHD_PP timing on in cdns_i3c_master_bus_init()
1293 * master output. This setting allows to meet this timing on master's in cdns_i3c_master_bus_init()
1296 ctrl |= CTRL_THD_DELAY(cdns_i3c_master_calculate_thd_delay(master)); in cdns_i3c_master_bus_init()
1297 writel(ctrl, master->regs + CTRL); in cdns_i3c_master_bus_init()
1299 cdns_i3c_master_enable(master); in cdns_i3c_master_bus_init()
1304 static void cdns_i3c_master_handle_ibi(struct cdns_i3c_master *master, in cdns_i3c_master_handle_ibi() argument
1319 if (id >= master->ibi.num_slots || (ibir & IBIR_ERROR)) in cdns_i3c_master_handle_ibi()
1322 dev = master->ibi.slots[id]; in cdns_i3c_master_handle_ibi()
1323 spin_lock(&master->ibi.lock); in cdns_i3c_master_handle_ibi()
1326 slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); in cdns_i3c_master_handle_ibi()
1330 buf = slot->data; in cdns_i3c_master_handle_ibi()
1333 readsl(master->regs + IBI_DATA_FIFO, buf, nbytes / 4); in cdns_i3c_master_handle_ibi()
1335 u32 tmp = __raw_readl(master->regs + IBI_DATA_FIFO); in cdns_i3c_master_handle_ibi()
1340 slot->len = min_t(unsigned int, IBIR_XFER_BYTES(ibir), in cdns_i3c_master_handle_ibi()
1341 dev->ibi->max_payload_len); in cdns_i3c_master_handle_ibi()
1346 spin_unlock(&master->ibi.lock); in cdns_i3c_master_handle_ibi()
1354 readl(master->regs + IBI_DATA_FIFO); in cdns_i3c_master_handle_ibi()
1358 static void cnds_i3c_master_demux_ibis(struct cdns_i3c_master *master) in cnds_i3c_master_demux_ibis() argument
1362 writel(MST_INT_IBIR_THR, master->regs + MST_ICR); in cnds_i3c_master_demux_ibis()
1364 for (status0 = readl(master->regs + MST_STATUS0); in cnds_i3c_master_demux_ibis()
1366 status0 = readl(master->regs + MST_STATUS0)) { in cnds_i3c_master_demux_ibis()
1367 u32 ibir = readl(master->regs + IBIR); in cnds_i3c_master_demux_ibis()
1371 cdns_i3c_master_handle_ibi(master, ibir); in cnds_i3c_master_demux_ibis()
1376 queue_work(master->base.wq, &master->hj_work); in cnds_i3c_master_demux_ibis()
1391 struct cdns_i3c_master *master = data; in cdns_i3c_master_interrupt() local
1394 status = readl(master->regs + MST_ISR); in cdns_i3c_master_interrupt()
1395 if (!(status & readl(master->regs + MST_IMR))) in cdns_i3c_master_interrupt()
1398 spin_lock(&master->xferqueue.lock); in cdns_i3c_master_interrupt()
1399 cdns_i3c_master_end_xfer_locked(master, status); in cdns_i3c_master_interrupt()
1400 spin_unlock(&master->xferqueue.lock); in cdns_i3c_master_interrupt()
1403 cnds_i3c_master_demux_ibis(master); in cdns_i3c_master_interrupt()
1411 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_disable_ibi() local
1417 ret = i3c_master_disec_locked(m, dev->info.dyn_addr, in cdns_i3c_master_disable_ibi()
1422 spin_lock_irqsave(&master->ibi.lock, flags); in cdns_i3c_master_disable_ibi()
1423 sirmap = readl(master->regs + SIR_MAP_DEV_REG(data->ibi)); in cdns_i3c_master_disable_ibi()
1424 sirmap &= ~SIR_MAP_DEV_CONF_MASK(data->ibi); in cdns_i3c_master_disable_ibi()
1425 sirmap |= SIR_MAP_DEV_CONF(data->ibi, in cdns_i3c_master_disable_ibi()
1427 writel(sirmap, master->regs + SIR_MAP_DEV_REG(data->ibi)); in cdns_i3c_master_disable_ibi()
1428 spin_unlock_irqrestore(&master->ibi.lock, flags); in cdns_i3c_master_disable_ibi()
1436 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_enable_ibi() local
1442 spin_lock_irqsave(&master->ibi.lock, flags); in cdns_i3c_master_enable_ibi()
1443 sirmap = readl(master->regs + SIR_MAP_DEV_REG(data->ibi)); in cdns_i3c_master_enable_ibi()
1444 sirmap &= ~SIR_MAP_DEV_CONF_MASK(data->ibi); in cdns_i3c_master_enable_ibi()
1445 sircfg = SIR_MAP_DEV_ROLE(dev->info.bcr >> 6) | in cdns_i3c_master_enable_ibi()
1446 SIR_MAP_DEV_DA(dev->info.dyn_addr) | in cdns_i3c_master_enable_ibi()
1447 SIR_MAP_DEV_PL(dev->info.max_ibi_len) | in cdns_i3c_master_enable_ibi()
1450 if (dev->info.bcr & I3C_BCR_MAX_DATA_SPEED_LIM) in cdns_i3c_master_enable_ibi()
1453 sirmap |= SIR_MAP_DEV_CONF(data->ibi, sircfg); in cdns_i3c_master_enable_ibi()
1454 writel(sirmap, master->regs + SIR_MAP_DEV_REG(data->ibi)); in cdns_i3c_master_enable_ibi()
1455 spin_unlock_irqrestore(&master->ibi.lock, flags); in cdns_i3c_master_enable_ibi()
1457 ret = i3c_master_enec_locked(m, dev->info.dyn_addr, in cdns_i3c_master_enable_ibi()
1460 spin_lock_irqsave(&master->ibi.lock, flags); in cdns_i3c_master_enable_ibi()
1461 sirmap = readl(master->regs + SIR_MAP_DEV_REG(data->ibi)); in cdns_i3c_master_enable_ibi()
1462 sirmap &= ~SIR_MAP_DEV_CONF_MASK(data->ibi); in cdns_i3c_master_enable_ibi()
1463 sirmap |= SIR_MAP_DEV_CONF(data->ibi, in cdns_i3c_master_enable_ibi()
1465 writel(sirmap, master->regs + SIR_MAP_DEV_REG(data->ibi)); in cdns_i3c_master_enable_ibi()
1466 spin_unlock_irqrestore(&master->ibi.lock, flags); in cdns_i3c_master_enable_ibi()
1476 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_request_ibi() local
1481 data->ibi_pool = i3c_generic_ibi_alloc_pool(dev, req); in cdns_i3c_master_request_ibi()
1482 if (IS_ERR(data->ibi_pool)) in cdns_i3c_master_request_ibi()
1483 return PTR_ERR(data->ibi_pool); in cdns_i3c_master_request_ibi()
1485 spin_lock_irqsave(&master->ibi.lock, flags); in cdns_i3c_master_request_ibi()
1486 for (i = 0; i < master->ibi.num_slots; i++) { in cdns_i3c_master_request_ibi()
1487 if (!master->ibi.slots[i]) { in cdns_i3c_master_request_ibi()
1488 data->ibi = i; in cdns_i3c_master_request_ibi()
1489 master->ibi.slots[i] = dev; in cdns_i3c_master_request_ibi()
1493 spin_unlock_irqrestore(&master->ibi.lock, flags); in cdns_i3c_master_request_ibi()
1495 if (i < master->ibi.num_slots) in cdns_i3c_master_request_ibi()
1498 i3c_generic_ibi_free_pool(data->ibi_pool); in cdns_i3c_master_request_ibi()
1499 data->ibi_pool = NULL; in cdns_i3c_master_request_ibi()
1501 return -ENOSPC; in cdns_i3c_master_request_ibi()
1507 struct cdns_i3c_master *master = to_cdns_i3c_master(m); in cdns_i3c_master_free_ibi() local
1511 spin_lock_irqsave(&master->ibi.lock, flags); in cdns_i3c_master_free_ibi()
1512 master->ibi.slots[data->ibi] = NULL; in cdns_i3c_master_free_ibi()
1513 data->ibi = -1; in cdns_i3c_master_free_ibi()
1514 spin_unlock_irqrestore(&master->ibi.lock, flags); in cdns_i3c_master_free_ibi()
1516 i3c_generic_ibi_free_pool(data->ibi_pool); in cdns_i3c_master_free_ibi()
1524 i3c_generic_ibi_recycle_slot(data->ibi_pool, slot); in cdns_i3c_master_recycle_ibi_slot()
1549 struct cdns_i3c_master *master = container_of(work, in cdns_i3c_master_hj() local
1553 i3c_master_do_daa(&master->base); in cdns_i3c_master_hj()
1561 { .compatible = "cdns,i3c-master", .data = &cdns_i3c_devdata },
1568 struct cdns_i3c_master *master; in cdns_i3c_master_probe() local
1572 master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); in cdns_i3c_master_probe()
1573 if (!master) in cdns_i3c_master_probe()
1574 return -ENOMEM; in cdns_i3c_master_probe()
1576 master->devdata = of_device_get_match_data(&pdev->dev); in cdns_i3c_master_probe()
1577 if (!master->devdata) in cdns_i3c_master_probe()
1578 return -EINVAL; in cdns_i3c_master_probe()
1580 master->regs = devm_platform_ioremap_resource(pdev, 0); in cdns_i3c_master_probe()
1581 if (IS_ERR(master->regs)) in cdns_i3c_master_probe()
1582 return PTR_ERR(master->regs); in cdns_i3c_master_probe()
1584 master->pclk = devm_clk_get(&pdev->dev, "pclk"); in cdns_i3c_master_probe()
1585 if (IS_ERR(master->pclk)) in cdns_i3c_master_probe()
1586 return PTR_ERR(master->pclk); in cdns_i3c_master_probe()
1588 master->sysclk = devm_clk_get(&pdev->dev, "sysclk"); in cdns_i3c_master_probe()
1589 if (IS_ERR(master->sysclk)) in cdns_i3c_master_probe()
1590 return PTR_ERR(master->sysclk); in cdns_i3c_master_probe()
1596 ret = clk_prepare_enable(master->pclk); in cdns_i3c_master_probe()
1600 ret = clk_prepare_enable(master->sysclk); in cdns_i3c_master_probe()
1604 if (readl(master->regs + DEV_ID) != DEV_ID_I3C_MASTER) { in cdns_i3c_master_probe()
1605 ret = -EINVAL; in cdns_i3c_master_probe()
1609 spin_lock_init(&master->xferqueue.lock); in cdns_i3c_master_probe()
1610 INIT_LIST_HEAD(&master->xferqueue.list); in cdns_i3c_master_probe()
1612 INIT_WORK(&master->hj_work, cdns_i3c_master_hj); in cdns_i3c_master_probe()
1613 writel(0xffffffff, master->regs + MST_IDR); in cdns_i3c_master_probe()
1614 writel(0xffffffff, master->regs + SLV_IDR); in cdns_i3c_master_probe()
1615 ret = devm_request_irq(&pdev->dev, irq, cdns_i3c_master_interrupt, 0, in cdns_i3c_master_probe()
1616 dev_name(&pdev->dev), master); in cdns_i3c_master_probe()
1620 platform_set_drvdata(pdev, master); in cdns_i3c_master_probe()
1622 val = readl(master->regs + CONF_STATUS0); in cdns_i3c_master_probe()
1624 /* Device ID0 is reserved to describe this master. */ in cdns_i3c_master_probe()
1625 master->maxdevs = CONF_STATUS0_DEVS_NUM(val); in cdns_i3c_master_probe()
1626 master->free_rr_slots = GENMASK(master->maxdevs, 1); in cdns_i3c_master_probe()
1627 master->caps.ibirfifodepth = CONF_STATUS0_IBIR_DEPTH(val); in cdns_i3c_master_probe()
1628 master->caps.cmdrfifodepth = CONF_STATUS0_CMDR_DEPTH(val); in cdns_i3c_master_probe()
1630 val = readl(master->regs + CONF_STATUS1); in cdns_i3c_master_probe()
1631 master->caps.cmdfifodepth = CONF_STATUS1_CMD_DEPTH(val); in cdns_i3c_master_probe()
1632 master->caps.rxfifodepth = CONF_STATUS1_RX_DEPTH(val); in cdns_i3c_master_probe()
1633 master->caps.txfifodepth = CONF_STATUS1_TX_DEPTH(val); in cdns_i3c_master_probe()
1635 spin_lock_init(&master->ibi.lock); in cdns_i3c_master_probe()
1636 master->ibi.num_slots = CONF_STATUS1_IBI_HW_RES(val); in cdns_i3c_master_probe()
1637 master->ibi.slots = devm_kcalloc(&pdev->dev, master->ibi.num_slots, in cdns_i3c_master_probe()
1638 sizeof(*master->ibi.slots), in cdns_i3c_master_probe()
1640 if (!master->ibi.slots) { in cdns_i3c_master_probe()
1641 ret = -ENOMEM; in cdns_i3c_master_probe()
1645 writel(IBIR_THR(1), master->regs + CMD_IBI_THR_CTRL); in cdns_i3c_master_probe()
1646 writel(MST_INT_IBIR_THR, master->regs + MST_IER); in cdns_i3c_master_probe()
1647 writel(DEVS_CTRL_DEV_CLR_ALL, master->regs + DEVS_CTRL); in cdns_i3c_master_probe()
1649 ret = i3c_master_register(&master->base, &pdev->dev, in cdns_i3c_master_probe()
1657 clk_disable_unprepare(master->sysclk); in cdns_i3c_master_probe()
1660 clk_disable_unprepare(master->pclk); in cdns_i3c_master_probe()
1667 struct cdns_i3c_master *master = platform_get_drvdata(pdev); in cdns_i3c_master_remove() local
1669 cancel_work_sync(&master->hj_work); in cdns_i3c_master_remove()
1670 i3c_master_unregister(&master->base); in cdns_i3c_master_remove()
1672 clk_disable_unprepare(master->sysclk); in cdns_i3c_master_remove()
1673 clk_disable_unprepare(master->pclk); in cdns_i3c_master_remove()
1680 .name = "cdns-i3c-master",
1687 MODULE_DESCRIPTION("Cadence I3C master driver");
1689 MODULE_ALIAS("platform:cdns-i3c-master");