summaryrefslogtreecommitdiff
path: root/drivers/i3c/master/mipi-i3c-hci/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i3c/master/mipi-i3c-hci/core.c')
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/core.c127
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),