diff mbox series

[3/8] i3c: mipi-i3c-hci: Add a quirk for 64-bit DMA addressing

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

Commit Message

Billy Tsai Sept. 1, 2026, 11:35 a.m. UTC
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(+)

Comments

Frank Li Sept. 1, 2026, 8:51 p.m. UTC | #1
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
>
Billy Tsai Sept. 9, 2026, 5:37 a.m. UTC | #2
> > +     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 mbox series

Patch

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);