| Message ID | 20260901-b4-i3c-hci-ast2700-v1-3-19909e7cbd7e@aspeedtech.com |
|---|---|
| State | New |
| Headers | show |
| Series | i3c: mipi-i3c-hci: Add Aspeed AST2700 support | expand |
On Tue, Sep 01, 2026 at 07:35:30PM +0800, Billy Tsai wrote: > The HCI ring base registers are 64 bits wide by specification, but not > every implementation wires the upper half, so the driver leaves the > platform device at the default 32-bit DMA mask unless told otherwise. > ASPEED platforms place all of DRAM above the 32-bit boundary > (0x4_00000000), so under the default mask every dma_alloc_coherent() > call for the DMA rings fails. > > Add HCI_QUIRK_DMA_64BIT for controllers whose DMA engine drives the > full address width, and declare a 64-bit streaming and coherent DMA > mask for them before the rings are allocated. > > Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com> > Assisted-by: Claude:claude-fable-5 > --- > drivers/i3c/master/mipi-i3c-hci/core.c | 7 +++++++ > drivers/i3c/master/mipi-i3c-hci/hci.h | 1 + > 2 files changed, 8 insertions(+) > > diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c > index a624e3c40484..c03c3a9cbe4f 100644 > --- a/drivers/i3c/master/mipi-i3c-hci/core.c > +++ b/drivers/i3c/master/mipi-i3c-hci/core.c > @@ -10,6 +10,7 @@ > #include <linux/bitfield.h> > #include <linux/clk.h> > #include <linux/device.h> > +#include <linux/dma-mapping.h> > #include <linux/errno.h> > #include <linux/i3c/master.h> > #include <linux/interrupt.h> > @@ -1167,6 +1168,12 @@ static int i3c_hci_probe(struct platform_device *pdev) > hci->quirks = (unsigned long)device_get_match_data(&pdev->dev); > if (!hci->quirks && platform_get_device_id(pdev)) > hci->quirks = platform_get_device_id(pdev)->driver_data; > + if (hci->quirks & HCI_QUIRK_DMA_64BIT) { > + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); dma_set_mask_and_coherent() never return fail when bit mask >= 32 if (hci->quirks & HCI_QUIRK_DMA_64BIT) dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); Frank > + if (ret) > + return dev_err_probe(&pdev->dev, ret, > + "cannot set DMA mask\n"); > + } > > ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &clks); > if (ret < 0) > diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h > index f50fc1e22a85..2110f806a53c 100644 > --- a/drivers/i3c/master/mipi-i3c-hci/hci.h > +++ b/drivers/i3c/master/mipi-i3c-hci/hci.h > @@ -178,6 +178,7 @@ struct i3c_hci_dev_data { > #define HCI_QUIRK_DMA_ABORT_REQUIRES_PIO_RESET BIT(8) /* Do PIO queue SW resets after DMA abort */ > #define HCI_QUIRK_DMA_REQUIRES_HC_ABORT BIT(9) /* Use HC_CONTROL ABORT to abort DMA */ > #define HCI_QUIRK_DAT_INDEX_IS_ADDR BIT(10) /* DAT entries are indexed by device address */ > +#define HCI_QUIRK_DMA_64BIT BIT(11) /* Controller DMA supports 64-bit addressing */ > > /* global functions */ > void mipi_i3c_hci_resume(struct i3c_hci *hci); > > -- > 2.34.1 >
> > + if (hci->quirks & HCI_QUIRK_DMA_64BIT) { > > + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); > dma_set_mask_and_coherent() never return fail when bit mask >= 32 > > if (hci->quirks & HCI_QUIRK_DMA_64BIT) > dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); Okay, I will drop the return check. Billy
diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c index a624e3c40484..c03c3a9cbe4f 100644 --- a/drivers/i3c/master/mipi-i3c-hci/core.c +++ b/drivers/i3c/master/mipi-i3c-hci/core.c @@ -10,6 +10,7 @@ #include <linux/bitfield.h> #include <linux/clk.h> #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/errno.h> #include <linux/i3c/master.h> #include <linux/interrupt.h> @@ -1167,6 +1168,12 @@ static int i3c_hci_probe(struct platform_device *pdev) hci->quirks = (unsigned long)device_get_match_data(&pdev->dev); if (!hci->quirks && platform_get_device_id(pdev)) hci->quirks = platform_get_device_id(pdev)->driver_data; + if (hci->quirks & HCI_QUIRK_DMA_64BIT) { + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "cannot set DMA mask\n"); + } ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &clks); if (ret < 0) diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h index f50fc1e22a85..2110f806a53c 100644 --- a/drivers/i3c/master/mipi-i3c-hci/hci.h +++ b/drivers/i3c/master/mipi-i3c-hci/hci.h @@ -178,6 +178,7 @@ struct i3c_hci_dev_data { #define HCI_QUIRK_DMA_ABORT_REQUIRES_PIO_RESET BIT(8) /* Do PIO queue SW resets after DMA abort */ #define HCI_QUIRK_DMA_REQUIRES_HC_ABORT BIT(9) /* Use HC_CONTROL ABORT to abort DMA */ #define HCI_QUIRK_DAT_INDEX_IS_ADDR BIT(10) /* DAT entries are indexed by device address */ +#define HCI_QUIRK_DMA_64BIT BIT(11) /* Controller DMA supports 64-bit addressing */ /* global functions */ void mipi_i3c_hci_resume(struct i3c_hci *hci);
The HCI ring base registers are 64 bits wide by specification, but not every implementation wires the upper half, so the driver leaves the platform device at the default 32-bit DMA mask unless told otherwise. ASPEED platforms place all of DRAM above the 32-bit boundary (0x4_00000000), so under the default mask every dma_alloc_coherent() call for the DMA rings fails. Add HCI_QUIRK_DMA_64BIT for controllers whose DMA engine drives the full address width, and declare a 64-bit streaming and coherent DMA mask for them before the rings are allocated. Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com> Assisted-by: Claude:claude-fable-5 --- drivers/i3c/master/mipi-i3c-hci/core.c | 7 +++++++ drivers/i3c/master/mipi-i3c-hci/hci.h | 1 + 2 files changed, 8 insertions(+)