diff options
Diffstat (limited to 'drivers/i3c/master/mipi-i3c-hci/core.c')
| -rw-r--r-- | drivers/i3c/master/mipi-i3c-hci/core.c | 127 |
1 files changed, 34 insertions, 93 deletions
diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c index a82c47c9986d..47e42cb4dbe7 100644 --- a/drivers/i3c/master/mipi-i3c-hci/core.c +++ b/drivers/i3c/master/mipi-i3c-hci/core.c @@ -78,10 +78,8 @@ #define INTR_SIGNAL_ENABLE 0x28 #define INTR_FORCE 0x2c #define INTR_HC_CMD_SEQ_UFLOW_STAT BIT(12) /* Cmd Sequence Underflow */ -#define INTR_HC_RESET_CANCEL BIT(11) /* HC Cancelled Reset */ +#define INTR_HC_SEQ_CANCEL BIT(11) /* HC Cancelled Transaction Sequence */ #define INTR_HC_INTERNAL_ERR BIT(10) /* HC Internal Error */ -#define INTR_HC_PIO BIT(8) /* cascaded PIO interrupt */ -#define INTR_HC_RINGS GENMASK(7, 0) #define DAT_SECTION 0x30 /* Device Address Table */ #define DAT_ENTRY_SIZE GENMASK(31, 28) @@ -123,8 +121,6 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m) struct i3c_device_info info; int ret; - DBG(""); - if (hci->cmd == &mipi_i3c_hci_cmd_v1) { ret = mipi_i3c_hci_dat_v1.init(hci); if (ret) @@ -151,7 +147,7 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m) amd_set_resp_buf_thld(hci); reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE); - DBG("HC_CONTROL = %#x", reg_read(HC_CONTROL)); + dev_dbg(&hci->master.dev, "HC_CONTROL = %#x", reg_read(HC_CONTROL)); return 0; } @@ -161,8 +157,6 @@ static void i3c_hci_bus_cleanup(struct i3c_master_controller *m) struct i3c_hci *hci = to_i3c_hci(m); struct platform_device *pdev = to_platform_device(m->dev.parent); - DBG(""); - reg_clear(HC_CONTROL, HC_CONTROL_BUS_ENABLE); synchronize_irq(platform_get_irq(pdev, 0)); hci->io->cleanup(hci); @@ -198,8 +192,8 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m, DECLARE_COMPLETION_ONSTACK(done); int i, last, ret = 0; - DBG("cmd=%#x rnw=%d ndests=%d data[0].len=%d", - ccc->id, ccc->rnw, ccc->ndests, ccc->dests[0].payload.len); + dev_dbg(&hci->master.dev, "cmd=%#x rnw=%d ndests=%d data[0].len=%d", + ccc->id, ccc->rnw, ccc->ndests, ccc->dests[0].payload.len); xfer = hci_alloc_xfer(nxfers); if (!xfer) @@ -257,8 +251,8 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m, } if (ccc->rnw) - DBG("got: %*ph", - ccc->dests[0].payload.len, ccc->dests[0].payload.data); + dev_dbg(&hci->master.dev, "got: %*ph", + ccc->dests[0].payload.len, ccc->dests[0].payload.data); out: hci_free_xfer(xfer, nxfers); @@ -269,39 +263,9 @@ static int i3c_hci_daa(struct i3c_master_controller *m) { struct i3c_hci *hci = to_i3c_hci(m); - DBG(""); - return hci->cmd->perform_daa(hci); } -static int i3c_hci_alloc_safe_xfer_buf(struct i3c_hci *hci, - struct hci_xfer *xfer) -{ - if (hci->io != &mipi_i3c_hci_dma || - xfer->data == NULL || !is_vmalloc_addr(xfer->data)) - return 0; - - if (xfer->rnw) - xfer->bounce_buf = kzalloc(xfer->data_len, GFP_KERNEL); - else - xfer->bounce_buf = kmemdup(xfer->data, - xfer->data_len, GFP_KERNEL); - - return xfer->bounce_buf == NULL ? -ENOMEM : 0; -} - -static void i3c_hci_free_safe_xfer_buf(struct i3c_hci *hci, - struct hci_xfer *xfer) -{ - if (hci->io != &mipi_i3c_hci_dma || xfer->bounce_buf == NULL) - return; - - if (xfer->rnw) - memcpy(xfer->data, xfer->bounce_buf, xfer->data_len); - - kfree(xfer->bounce_buf); -} - static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev, struct i3c_priv_xfer *i3c_xfers, int nxfers) @@ -313,7 +277,7 @@ static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev, unsigned int size_limit; int i, last, ret = 0; - DBG("nxfers = %d", nxfers); + dev_dbg(&hci->master.dev, "nxfers = %d", nxfers); xfer = hci_alloc_xfer(nxfers); if (!xfer) @@ -335,9 +299,6 @@ static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev, } hci->cmd->prep_i3c_xfer(hci, dev, &xfer[i]); xfer[i].cmd_desc[0] |= CMD_0_ROC; - ret = i3c_hci_alloc_safe_xfer_buf(hci, &xfer[i]); - if (ret) - goto out; } last = i - 1; xfer[last].cmd_desc[0] |= CMD_0_TOC; @@ -361,15 +322,12 @@ static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev, } out: - for (i = 0; i < nxfers; i++) - i3c_hci_free_safe_xfer_buf(hci, &xfer[i]); - hci_free_xfer(xfer, nxfers); return ret; } static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev, - const struct i2c_msg *i2c_xfers, int nxfers) + struct i2c_msg *i2c_xfers, int nxfers) { struct i3c_master_controller *m = i2c_dev_get_master(dev); struct i3c_hci *hci = to_i3c_hci(m); @@ -377,7 +335,7 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev, DECLARE_COMPLETION_ONSTACK(done); int i, last, ret = 0; - DBG("nxfers = %d", nxfers); + dev_dbg(&hci->master.dev, "nxfers = %d", nxfers); xfer = hci_alloc_xfer(nxfers); if (!xfer) @@ -389,9 +347,6 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev, xfer[i].rnw = i2c_xfers[i].flags & I2C_M_RD; hci->cmd->prep_i2c_xfer(hci, dev, &xfer[i]); xfer[i].cmd_desc[0] |= CMD_0_ROC; - ret = i3c_hci_alloc_safe_xfer_buf(hci, &xfer[i]); - if (ret) - goto out; } last = i - 1; xfer[last].cmd_desc[0] |= CMD_0_TOC; @@ -400,7 +355,7 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev, ret = hci->io->queue_xfer(hci, xfer, nxfers); if (ret) goto out; - if (!wait_for_completion_timeout(&done, HZ) && + if (!wait_for_completion_timeout(&done, m->i2c.timeout) && hci->io->dequeue_xfer(hci, xfer, nxfers)) { ret = -ETIME; goto out; @@ -413,9 +368,6 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev, } out: - for (i = 0; i < nxfers; i++) - i3c_hci_free_safe_xfer_buf(hci, &xfer[i]); - hci_free_xfer(xfer, nxfers); return ret; } @@ -427,8 +379,6 @@ static int i3c_hci_attach_i3c_dev(struct i3c_dev_desc *dev) struct i3c_hci_dev_data *dev_data; int ret; - DBG(""); - dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); if (!dev_data) return -ENOMEM; @@ -438,7 +388,8 @@ static int i3c_hci_attach_i3c_dev(struct i3c_dev_desc *dev) kfree(dev_data); return ret; } - mipi_i3c_hci_dat_v1.set_dynamic_addr(hci, ret, dev->info.dyn_addr); + mipi_i3c_hci_dat_v1.set_dynamic_addr(hci, ret, + dev->info.dyn_addr ?: dev->info.static_addr); dev_data->dat_idx = ret; } i3c_dev_set_master_data(dev, dev_data); @@ -451,8 +402,6 @@ static int i3c_hci_reattach_i3c_dev(struct i3c_dev_desc *dev, u8 old_dyn_addr) struct i3c_hci *hci = to_i3c_hci(m); struct i3c_hci_dev_data *dev_data = i3c_dev_get_master_data(dev); - DBG(""); - if (hci->cmd == &mipi_i3c_hci_cmd_v1) mipi_i3c_hci_dat_v1.set_dynamic_addr(hci, dev_data->dat_idx, dev->info.dyn_addr); @@ -465,8 +414,6 @@ static void i3c_hci_detach_i3c_dev(struct i3c_dev_desc *dev) struct i3c_hci *hci = to_i3c_hci(m); struct i3c_hci_dev_data *dev_data = i3c_dev_get_master_data(dev); - DBG(""); - i3c_dev_set_master_data(dev, NULL); if (hci->cmd == &mipi_i3c_hci_cmd_v1) mipi_i3c_hci_dat_v1.free_entry(hci, dev_data->dat_idx); @@ -480,8 +427,6 @@ static int i3c_hci_attach_i2c_dev(struct i2c_dev_desc *dev) struct i3c_hci_dev_data *dev_data; int ret; - DBG(""); - if (hci->cmd != &mipi_i3c_hci_cmd_v1) return 0; dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); @@ -505,8 +450,6 @@ static void i3c_hci_detach_i2c_dev(struct i2c_dev_desc *dev) struct i3c_hci *hci = to_i3c_hci(m); struct i3c_hci_dev_data *dev_data = i2c_dev_get_master_data(dev); - DBG(""); - if (dev_data) { i2c_dev_set_master_data(dev, NULL); if (hci->cmd == &mipi_i3c_hci_cmd_v1) @@ -593,34 +536,27 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id) u32 val; val = reg_read(INTR_STATUS); - DBG("INTR_STATUS = %#x", val); + reg_write(INTR_STATUS, val); + dev_dbg(&hci->master.dev, "INTR_STATUS %#x", val); - if (val) { - reg_write(INTR_STATUS, val); - } else { - /* v1.0 does not have PIO cascaded notification bits */ - val |= INTR_HC_PIO; - } + if (val) + result = IRQ_HANDLED; - if (val & INTR_HC_RESET_CANCEL) { - DBG("cancelled reset"); - val &= ~INTR_HC_RESET_CANCEL; + if (val & INTR_HC_SEQ_CANCEL) { + dev_dbg(&hci->master.dev, + "Host Controller Cancelled Transaction Sequence\n"); + val &= ~INTR_HC_SEQ_CANCEL; } if (val & INTR_HC_INTERNAL_ERR) { dev_err(&hci->master.dev, "Host Controller Internal Error\n"); val &= ~INTR_HC_INTERNAL_ERR; } - if (val & INTR_HC_PIO) { - hci->io->irq_handler(hci, 0); - val &= ~INTR_HC_PIO; - } - if (val & INTR_HC_RINGS) { - hci->io->irq_handler(hci, val & INTR_HC_RINGS); - val &= ~INTR_HC_RINGS; - } + if (val) - dev_err(&hci->master.dev, "unexpected INTR_STATUS %#x\n", val); - else + dev_warn_once(&hci->master.dev, + "unexpected INTR_STATUS %#x\n", val); + + if (hci->io->irq_handler(hci)) result = IRQ_HANDLED; return result; @@ -651,7 +587,7 @@ static int i3c_hci_init(struct i3c_hci *hci) } hci->caps = reg_read(HC_CAPABILITIES); - DBG("caps = %#x", hci->caps); + dev_dbg(&hci->master.dev, "caps = %#x", hci->caps); size_in_dwords = hci->version_major < 1 || (hci->version_major == 1 && hci->version_minor < 1); @@ -710,9 +646,14 @@ static int i3c_hci_init(struct i3c_hci *hci) if (ret) return -ENXIO; - /* Disable all interrupts and allow all signal updates */ + /* Disable all interrupts */ reg_write(INTR_SIGNAL_ENABLE, 0x0); - reg_write(INTR_STATUS_ENABLE, 0xffffffff); + /* + * Only allow bit 31:10 signal updates because + * Bit 0:9 are reserved in IP version >= 0.8 + * Bit 0:5 are defined in IP version < 0.8 but not handled by PIO code + */ + reg_write(INTR_STATUS_ENABLE, GENMASK(31, 10)); /* Make sure our data ordering fits the host's */ regval = reg_read(HC_CONTROL); @@ -853,7 +794,7 @@ MODULE_DEVICE_TABLE(acpi, i3c_hci_acpi_match); static struct platform_driver i3c_hci_driver = { .probe = i3c_hci_probe, - .remove_new = i3c_hci_remove, + .remove = i3c_hci_remove, .driver = { .name = "mipi-i3c-hci", .of_match_table = of_match_ptr(i3c_hci_of_match), |
