* [PATCH 1/6] i3c: dw: Add support for AMDI0015 ACPI ID
2024-10-17 15:03 [PATCH 0/6] Introduce initial support for the AMD I3C (non-HCI) to DW driver Shyam Sundar S K
@ 2024-10-17 15:03 ` Shyam Sundar S K
2024-10-17 15:03 ` [PATCH 2/6] i3c: dw: Use IRQF_SHARED flag for dw-i3c-master Shyam Sundar S K
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2024-10-17 15:03 UTC (permalink / raw)
To: Alexandre Belloni, Jarkko Nikula
Cc: Sanket.Goswami, linux-i3c, linux-kernel, Shyam Sundar S K
Add AMDI0015 _HID for Designware I3C driver so that the dw-i3c-master
driver can be probed on AMD platforms.
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/i3c/master/dw-i3c-master.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 8d694672c110..1a7c300b6d45 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -1748,12 +1748,19 @@ static const struct of_device_id dw_i3c_master_of_match[] = {
};
MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match);
+static const struct acpi_device_id amd_i3c_device_match[] = {
+ { "AMDI0015" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, amd_i3c_device_match);
+
static struct platform_driver dw_i3c_driver = {
.probe = dw_i3c_probe,
.remove_new = dw_i3c_remove,
.driver = {
.name = "dw-i3c-master",
.of_match_table = dw_i3c_master_of_match,
+ .acpi_match_table = amd_i3c_device_match,
.pm = &dw_i3c_pm_ops,
},
};
--
2.34.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 2/6] i3c: dw: Use IRQF_SHARED flag for dw-i3c-master
2024-10-17 15:03 [PATCH 0/6] Introduce initial support for the AMD I3C (non-HCI) to DW driver Shyam Sundar S K
2024-10-17 15:03 ` [PATCH 1/6] i3c: dw: Add support for AMDI0015 ACPI ID Shyam Sundar S K
@ 2024-10-17 15:03 ` Shyam Sundar S K
2024-10-17 15:03 ` [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem Shyam Sundar S K
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2024-10-17 15:03 UTC (permalink / raw)
To: Alexandre Belloni, Jarkko Nikula
Cc: Sanket.Goswami, linux-i3c, linux-kernel, Shyam Sundar S K
On AMD platforms, the IRQ lines are shared between two instances of I3C.
Add IRQF_SHARED flag during the interrupt registration process.
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/i3c/master/dw-i3c-master.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 1a7c300b6d45..fd58a95ae1c3 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -1578,7 +1578,7 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
writel(INTR_ALL, master->regs + INTR_STATUS);
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(&pdev->dev, irq,
- dw_i3c_master_irq_handler, 0,
+ dw_i3c_master_irq_handler, IRQF_SHARED,
dev_name(&pdev->dev), master);
if (ret)
goto err_assert_rst;
--
2.34.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem
2024-10-17 15:03 [PATCH 0/6] Introduce initial support for the AMD I3C (non-HCI) to DW driver Shyam Sundar S K
2024-10-17 15:03 ` [PATCH 1/6] i3c: dw: Add support for AMDI0015 ACPI ID Shyam Sundar S K
2024-10-17 15:03 ` [PATCH 2/6] i3c: dw: Use IRQF_SHARED flag for dw-i3c-master Shyam Sundar S K
@ 2024-10-17 15:03 ` Shyam Sundar S K
2024-10-20 7:46 ` kernel test robot
2024-10-20 8:17 ` kernel test robot
2024-10-17 15:03 ` [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device Shyam Sundar S K
` (2 subsequent siblings)
5 siblings, 2 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2024-10-17 15:03 UTC (permalink / raw)
To: Alexandre Belloni, Jarkko Nikula
Cc: Sanket.Goswami, linux-i3c, linux-kernel, Shyam Sundar S K
As of now, the I3C subsystem only has ARM-specific initialization, and
there is no corresponding ACPI plumbing present. To address this, ACPI
support needs to be added to both the I3C core and DW driver.
Add support to get the ACPI handle from the _HID probed and parse the apci
object to retrieve the slave information from BIOS.
Based on the acpi object information propogated via BIOS, build the i3c
board information so that the same information can be used across the
driver to handle the slave requests.
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/i3c/internals.h | 2 +
drivers/i3c/master.c | 80 ++++++++++++++++++++++++++++++
drivers/i3c/master/dw-i3c-master.c | 5 ++
include/linux/i3c/master.h | 1 +
4 files changed, 88 insertions(+)
diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
index 433f6088b7ce..d2d6c69b19dd 100644
--- a/drivers/i3c/internals.h
+++ b/drivers/i3c/internals.h
@@ -10,6 +10,8 @@
#include <linux/i3c/master.h>
+#define AMD_I3C_GET_SLAVE_ADDR 0x30
+
void i3c_bus_normaluse_lock(struct i3c_bus *bus);
void i3c_bus_normaluse_unlock(struct i3c_bus *bus);
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 6f3eb710a75d..20b83ca52d31 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2251,6 +2251,80 @@ static int of_i3c_master_add_dev(struct i3c_master_controller *master,
return ret;
}
+static int i3c_acpi_configure_master(struct i3c_master_controller *master)
+{
+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+ enum i3c_addr_slot_status addrstatus;
+ struct i3c_dev_boardinfo *boardinfo;
+ struct device *dev = &master->dev;
+ struct fwnode_handle *fwnode;
+ struct acpi_device *adev;
+ u32 slv_addr, num_dev;
+ acpi_status status;
+ u64 val;
+
+ status = acpi_evaluate_object_typed(master->ahandle, "_DSD", NULL, &buf, ACPI_TYPE_PACKAGE);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&master->dev, "Error reading _DSD:%s\n", acpi_format_exception(status));
+ return -ENODEV;
+ }
+
+ num_dev = device_get_child_node_count(dev);
+ if (!num_dev) {
+ dev_err(&master->dev, "Error: no child node present\n");
+ return -EINVAL;
+ }
+
+ device_for_each_child_node(dev, fwnode) {
+ adev = to_acpi_device_node(fwnode);
+ if (!adev)
+ return -ENODEV;
+
+ status = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &val);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&master->dev, "Error: eval _ADR failed\n");
+ return -EINVAL;
+ }
+ slv_addr = val >> AMD_I3C_GET_SLAVE_ADDR;
+
+ boardinfo = devm_kzalloc(dev, sizeof(*boardinfo), GFP_KERNEL);
+ if (!boardinfo)
+ return -ENOMEM;
+
+ if (slv_addr) {
+ if (slv_addr > I3C_MAX_ADDR)
+ return -EINVAL;
+
+ addrstatus = i3c_bus_get_addr_slot_status(&master->bus, slv_addr);
+ if (addrstatus != I3C_ADDR_SLOT_FREE)
+ return -EINVAL;
+ }
+
+ boardinfo->static_addr = slv_addr;
+ if (boardinfo->static_addr > I3C_MAX_ADDR)
+ return -EINVAL;
+
+ addrstatus = i3c_bus_get_addr_slot_status(&master->bus, boardinfo->static_addr);
+ if (addrstatus != I3C_ADDR_SLOT_FREE)
+ return -EINVAL;
+
+ boardinfo->pid = (val & GENMASK(47, 0));
+ if ((boardinfo->pid & GENMASK_ULL(63, 48)) ||
+ I3C_PID_RND_LOWER_32BITS(boardinfo->pid))
+ return -EINVAL;
+
+ /*
+ * According to the specification, SETDASA is not supported for DIMM slaves
+ * during device discovery. Therefore, AMD BIOS will populate same initial
+ * dynamic address as the static address.
+ */
+ boardinfo->init_dyn_addr = boardinfo->static_addr;
+ list_add_tail(&boardinfo->node, &master->boardinfo.i3c);
+ }
+
+ return 0;
+}
+
static int of_populate_i3c_bus(struct i3c_master_controller *master)
{
struct device *dev = &master->dev;
@@ -2771,6 +2845,12 @@ int i3c_master_register(struct i3c_master_controller *master,
master->dev.coherent_dma_mask = parent->coherent_dma_mask;
master->dev.dma_parms = parent->dma_parms;
+ if (has_acpi_companion(master->dev.parent)) {
+ ret = i3c_acpi_configure_master(master);
+ if (ret < 0)
+ return ret;
+ }
+
ret = of_populate_i3c_bus(master);
if (ret)
goto err_put_dev;
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index fd58a95ae1c3..8d4583bc2113 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -1602,6 +1602,11 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
master->maxdevs = ret >> 16;
master->free_pos = GENMASK(master->maxdevs - 1, 0);
+ ACPI_COMPANION_SET(&master->base.dev, ACPI_COMPANION(&pdev->dev));
+ master->base.ahandle = acpi_device_handle(ACPI_COMPANION(&pdev->dev));
+ if (!master->base.ahandle)
+ dev_err(&pdev->dev, "Failed to get acpi device handle\n");
+
INIT_WORK(&master->hj_work, dw_i3c_hj_work);
ret = i3c_master_register(&master->base, &pdev->dev,
&dw_mipi_i3c_ops, false);
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 2a1ed05d5782..367faf7c4bf3 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -523,6 +523,7 @@ struct i3c_master_controller {
} boardinfo;
struct i3c_bus bus;
struct workqueue_struct *wq;
+ acpi_handle ahandle;
};
/**
--
2.34.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem
2024-10-17 15:03 ` [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem Shyam Sundar S K
@ 2024-10-20 7:46 ` kernel test robot
2024-10-20 8:17 ` kernel test robot
1 sibling, 0 replies; 10+ messages in thread
From: kernel test robot @ 2024-10-20 7:46 UTC (permalink / raw)
To: Shyam Sundar S K, Alexandre Belloni, Jarkko Nikula
Cc: oe-kbuild-all, Sanket.Goswami, linux-i3c, linux-kernel,
Shyam Sundar S K
Hi Shyam,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.12-rc3 next-20241018]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Shyam-Sundar-S-K/i3c-dw-Add-support-for-AMDI0015-ACPI-ID/20241017-230810
base: linus/master
patch link: https://lore.kernel.org/r/20241017150330.3035568-4-Shyam-sundar.S-k%40amd.com
patch subject: [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem
config: arc-randconfig-001-20241020 (https://download.01.org/0day-ci/archive/20241020/202410201515.SaOuSc9G-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241020/202410201515.SaOuSc9G-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410201515.SaOuSc9G-lkp@intel.com/
All error/warnings (new ones prefixed by >>):
drivers/i3c/master/dw-i3c-master.c: In function 'dw_i3c_common_probe':
>> drivers/i3c/master/dw-i3c-master.c:1606:32: error: implicit declaration of function 'acpi_device_handle'; did you mean 'acpi_fwnode_handle'? [-Werror=implicit-function-declaration]
1606 | master->base.ahandle = acpi_device_handle(ACPI_COMPANION(&pdev->dev));
| ^~~~~~~~~~~~~~~~~~
| acpi_fwnode_handle
>> drivers/i3c/master/dw-i3c-master.c:1606:30: warning: assignment to 'acpi_handle' {aka 'void *'} from 'int' makes pointer from integer without a cast [-Wint-conversion]
1606 | master->base.ahandle = acpi_device_handle(ACPI_COMPANION(&pdev->dev));
| ^
cc1: some warnings being treated as errors
vim +1606 drivers/i3c/master/dw-i3c-master.c
1545
1546 int dw_i3c_common_probe(struct dw_i3c_master *master,
1547 struct platform_device *pdev)
1548 {
1549 int ret, irq;
1550
1551 if (!master->platform_ops)
1552 master->platform_ops = &dw_i3c_platform_ops_default;
1553
1554 master->dev = &pdev->dev;
1555
1556 master->regs = devm_platform_ioremap_resource(pdev, 0);
1557 if (IS_ERR(master->regs))
1558 return PTR_ERR(master->regs);
1559
1560 master->core_clk = devm_clk_get_enabled(&pdev->dev, NULL);
1561 if (IS_ERR(master->core_clk))
1562 return PTR_ERR(master->core_clk);
1563
1564 master->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk");
1565 if (IS_ERR(master->pclk))
1566 return PTR_ERR(master->pclk);
1567
1568 master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
1569 "core_rst");
1570 if (IS_ERR(master->core_rst))
1571 return PTR_ERR(master->core_rst);
1572
1573 reset_control_deassert(master->core_rst);
1574
1575 spin_lock_init(&master->xferqueue.lock);
1576 INIT_LIST_HEAD(&master->xferqueue.list);
1577
1578 writel(INTR_ALL, master->regs + INTR_STATUS);
1579 irq = platform_get_irq(pdev, 0);
1580 ret = devm_request_irq(&pdev->dev, irq,
1581 dw_i3c_master_irq_handler, IRQF_SHARED,
1582 dev_name(&pdev->dev), master);
1583 if (ret)
1584 goto err_assert_rst;
1585
1586 platform_set_drvdata(pdev, master);
1587
1588 pm_runtime_set_autosuspend_delay(&pdev->dev, RPM_AUTOSUSPEND_TIMEOUT);
1589 pm_runtime_use_autosuspend(&pdev->dev);
1590 pm_runtime_set_active(&pdev->dev);
1591 pm_runtime_enable(&pdev->dev);
1592
1593 /* Information regarding the FIFOs/QUEUEs depth */
1594 ret = readl(master->regs + QUEUE_STATUS_LEVEL);
1595 master->caps.cmdfifodepth = QUEUE_STATUS_LEVEL_CMD(ret);
1596
1597 ret = readl(master->regs + DATA_BUFFER_STATUS_LEVEL);
1598 master->caps.datafifodepth = DATA_BUFFER_STATUS_LEVEL_TX(ret);
1599
1600 ret = readl(master->regs + DEVICE_ADDR_TABLE_POINTER);
1601 master->datstartaddr = ret;
1602 master->maxdevs = ret >> 16;
1603 master->free_pos = GENMASK(master->maxdevs - 1, 0);
1604
1605 ACPI_COMPANION_SET(&master->base.dev, ACPI_COMPANION(&pdev->dev));
> 1606 master->base.ahandle = acpi_device_handle(ACPI_COMPANION(&pdev->dev));
1607 if (!master->base.ahandle)
1608 dev_err(&pdev->dev, "Failed to get acpi device handle\n");
1609
1610 INIT_WORK(&master->hj_work, dw_i3c_hj_work);
1611 ret = i3c_master_register(&master->base, &pdev->dev,
1612 &dw_mipi_i3c_ops, false);
1613 if (ret)
1614 goto err_disable_pm;
1615
1616 return 0;
1617
1618 err_disable_pm:
1619 pm_runtime_disable(&pdev->dev);
1620 pm_runtime_set_suspended(&pdev->dev);
1621 pm_runtime_dont_use_autosuspend(&pdev->dev);
1622
1623 err_assert_rst:
1624 reset_control_assert(master->core_rst);
1625
1626 return ret;
1627 }
1628 EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
1629
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem
2024-10-17 15:03 ` [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem Shyam Sundar S K
2024-10-20 7:46 ` kernel test robot
@ 2024-10-20 8:17 ` kernel test robot
1 sibling, 0 replies; 10+ messages in thread
From: kernel test robot @ 2024-10-20 8:17 UTC (permalink / raw)
To: Shyam Sundar S K, Alexandre Belloni, Jarkko Nikula
Cc: oe-kbuild-all, Sanket.Goswami, linux-i3c, linux-kernel,
Shyam Sundar S K
Hi Shyam,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.12-rc3 next-20241018]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Shyam-Sundar-S-K/i3c-dw-Add-support-for-AMDI0015-ACPI-ID/20241017-230810
base: linus/master
patch link: https://lore.kernel.org/r/20241017150330.3035568-4-Shyam-sundar.S-k%40amd.com
patch subject: [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem
config: openrisc-allyesconfig (https://download.01.org/0day-ci/archive/20241020/202410201553.RtPfO9pR-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241020/202410201553.RtPfO9pR-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410201553.RtPfO9pR-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/i3c/master/dw-i3c-master.c: In function 'dw_i3c_common_probe':
drivers/i3c/master/dw-i3c-master.c:1606:32: error: implicit declaration of function 'acpi_device_handle'; did you mean 'acpi_fwnode_handle'? [-Wimplicit-function-declaration]
1606 | master->base.ahandle = acpi_device_handle(ACPI_COMPANION(&pdev->dev));
| ^~~~~~~~~~~~~~~~~~
| acpi_fwnode_handle
>> drivers/i3c/master/dw-i3c-master.c:1606:30: error: assignment to 'acpi_handle' {aka 'void *'} from 'int' makes pointer from integer without a cast [-Wint-conversion]
1606 | master->base.ahandle = acpi_device_handle(ACPI_COMPANION(&pdev->dev));
| ^
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for GET_FREE_REGION
Depends on [n]: SPARSEMEM [=n]
Selected by [y]:
- RESOURCE_KUNIT_TEST [=y] && RUNTIME_TESTING_MENU [=y] && KUNIT [=y]
vim +1606 drivers/i3c/master/dw-i3c-master.c
1545
1546 int dw_i3c_common_probe(struct dw_i3c_master *master,
1547 struct platform_device *pdev)
1548 {
1549 int ret, irq;
1550
1551 if (!master->platform_ops)
1552 master->platform_ops = &dw_i3c_platform_ops_default;
1553
1554 master->dev = &pdev->dev;
1555
1556 master->regs = devm_platform_ioremap_resource(pdev, 0);
1557 if (IS_ERR(master->regs))
1558 return PTR_ERR(master->regs);
1559
1560 master->core_clk = devm_clk_get_enabled(&pdev->dev, NULL);
1561 if (IS_ERR(master->core_clk))
1562 return PTR_ERR(master->core_clk);
1563
1564 master->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk");
1565 if (IS_ERR(master->pclk))
1566 return PTR_ERR(master->pclk);
1567
1568 master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
1569 "core_rst");
1570 if (IS_ERR(master->core_rst))
1571 return PTR_ERR(master->core_rst);
1572
1573 reset_control_deassert(master->core_rst);
1574
1575 spin_lock_init(&master->xferqueue.lock);
1576 INIT_LIST_HEAD(&master->xferqueue.list);
1577
1578 writel(INTR_ALL, master->regs + INTR_STATUS);
1579 irq = platform_get_irq(pdev, 0);
1580 ret = devm_request_irq(&pdev->dev, irq,
1581 dw_i3c_master_irq_handler, IRQF_SHARED,
1582 dev_name(&pdev->dev), master);
1583 if (ret)
1584 goto err_assert_rst;
1585
1586 platform_set_drvdata(pdev, master);
1587
1588 pm_runtime_set_autosuspend_delay(&pdev->dev, RPM_AUTOSUSPEND_TIMEOUT);
1589 pm_runtime_use_autosuspend(&pdev->dev);
1590 pm_runtime_set_active(&pdev->dev);
1591 pm_runtime_enable(&pdev->dev);
1592
1593 /* Information regarding the FIFOs/QUEUEs depth */
1594 ret = readl(master->regs + QUEUE_STATUS_LEVEL);
1595 master->caps.cmdfifodepth = QUEUE_STATUS_LEVEL_CMD(ret);
1596
1597 ret = readl(master->regs + DATA_BUFFER_STATUS_LEVEL);
1598 master->caps.datafifodepth = DATA_BUFFER_STATUS_LEVEL_TX(ret);
1599
1600 ret = readl(master->regs + DEVICE_ADDR_TABLE_POINTER);
1601 master->datstartaddr = ret;
1602 master->maxdevs = ret >> 16;
1603 master->free_pos = GENMASK(master->maxdevs - 1, 0);
1604
1605 ACPI_COMPANION_SET(&master->base.dev, ACPI_COMPANION(&pdev->dev));
> 1606 master->base.ahandle = acpi_device_handle(ACPI_COMPANION(&pdev->dev));
1607 if (!master->base.ahandle)
1608 dev_err(&pdev->dev, "Failed to get acpi device handle\n");
1609
1610 INIT_WORK(&master->hj_work, dw_i3c_hj_work);
1611 ret = i3c_master_register(&master->base, &pdev->dev,
1612 &dw_mipi_i3c_ops, false);
1613 if (ret)
1614 goto err_disable_pm;
1615
1616 return 0;
1617
1618 err_disable_pm:
1619 pm_runtime_disable(&pdev->dev);
1620 pm_runtime_set_suspended(&pdev->dev);
1621 pm_runtime_dont_use_autosuspend(&pdev->dev);
1622
1623 err_assert_rst:
1624 reset_control_assert(master->core_rst);
1625
1626 return ret;
1627 }
1628 EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
1629
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device
2024-10-17 15:03 [PATCH 0/6] Introduce initial support for the AMD I3C (non-HCI) to DW driver Shyam Sundar S K
` (2 preceding siblings ...)
2024-10-17 15:03 ` [PATCH 3/6] i3c: master: Add ACPI support to i3c subsystem Shyam Sundar S K
@ 2024-10-17 15:03 ` Shyam Sundar S K
2024-10-20 11:25 ` kernel test robot
2024-10-17 15:03 ` [PATCH 5/6] i3c: master: Add support for SETAASA CCC Shyam Sundar S K
2024-10-17 15:03 ` [PATCH 6/6] i3c: dw: Add quirk to address OD/PP timing issue on AMD platform Shyam Sundar S K
5 siblings, 1 reply; 10+ messages in thread
From: Shyam Sundar S K @ 2024-10-17 15:03 UTC (permalink / raw)
To: Alexandre Belloni, Jarkko Nikula
Cc: Sanket.Goswami, linux-i3c, linux-kernel, Shyam Sundar S K
Implement the i3c_master_add_spd_dev() function in the I3C master to
handle SPD (Serial Presence Detect) device creation and map the board
information into the I3C device structure.
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/i3c/master.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 20b83ca52d31..4f149519170e 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1657,6 +1657,45 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
}
}
+static int i3c_master_add_spd_dev(struct i3c_master_controller *master,
+ struct i3c_dev_boardinfo *boardinfo)
+{
+ struct i3c_dev_desc *i3cdev;
+ int ret;
+
+ list_for_each_entry(boardinfo, &master->boardinfo.i3c, node) {
+ struct i3c_device_info info = {
+ .static_addr = boardinfo->static_addr,
+ };
+
+ ret = i3c_bus_get_addr_slot_status(&master->bus, boardinfo->static_addr);
+ if (ret != I3C_ADDR_SLOT_FREE)
+ return -EBUSY;
+
+ i3cdev = i3c_master_alloc_i3c_dev(master, &info);
+ if (IS_ERR(i3cdev))
+ return -ENOMEM;
+
+ i3cdev->boardinfo = boardinfo;
+ ret = i3c_master_attach_i3c_dev(master, i3cdev);
+ if (ret)
+ goto err_free_dev;
+
+ i3cdev->info.pid = i3cdev->boardinfo->pid;
+ i3cdev->info.dyn_addr = i3cdev->boardinfo->init_dyn_addr;
+
+ i3c_bus_normaluse_lock(&master->bus);
+ i3c_master_register_new_i3c_devs(master);
+ i3c_bus_normaluse_unlock(&master->bus);
+ }
+
+ return 0;
+
+err_free_dev:
+ i3c_master_free_i3c_dev(i3cdev);
+ return ret;
+}
+
/**
* i3c_master_do_daa() - do a DAA (Dynamic Address Assignment)
* @master: master doing the DAA
@@ -1868,6 +1907,8 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
goto err_bus_cleanup;
}
+ i3c_master_add_spd_dev(master, i3cboardinfo);
+
if (master->ops->set_speed) {
ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
if (ret)
--
2.34.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device
2024-10-17 15:03 ` [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device Shyam Sundar S K
@ 2024-10-20 11:25 ` kernel test robot
0 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2024-10-20 11:25 UTC (permalink / raw)
To: Shyam Sundar S K, Alexandre Belloni, Jarkko Nikula
Cc: oe-kbuild-all, Sanket.Goswami, linux-i3c, linux-kernel,
Shyam Sundar S K
Hi Shyam,
kernel test robot noticed the following build warnings:
[auto build test WARNING on linus/master]
[also build test WARNING on v6.12-rc3 next-20241018]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Shyam-Sundar-S-K/i3c-dw-Add-support-for-AMDI0015-ACPI-ID/20241017-230810
base: linus/master
patch link: https://lore.kernel.org/r/20241017150330.3035568-5-Shyam-sundar.S-k%40amd.com
patch subject: [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device
config: arm-randconfig-r073-20241020 (https://download.01.org/0day-ci/archive/20241020/202410201938.oiMeI2Pu-lkp@intel.com/config)
compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project bfe84f7085d82d06d61c632a7bad1e692fd159e4)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241020/202410201938.oiMeI2Pu-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410201938.oiMeI2Pu-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from drivers/i3c/master.c:21:
In file included from drivers/i3c/internals.h:11:
In file included from include/linux/i3c/master.h:14:
In file included from include/linux/i2c.h:19:
In file included from include/linux/regulator/consumer.h:35:
In file included from include/linux/suspend.h:5:
In file included from include/linux/swap.h:9:
In file included from include/linux/memcontrol.h:21:
In file included from include/linux/mm.h:2213:
include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
518 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
>> drivers/i3c/master.c:1910:33: warning: variable 'i3cboardinfo' is uninitialized when used here [-Wuninitialized]
1910 | i3c_master_add_spd_dev(master, i3cboardinfo);
| ^~~~~~~~~~~~
drivers/i3c/master.c:1856:40: note: initialize the variable 'i3cboardinfo' to silence this warning
1856 | struct i3c_dev_boardinfo *i3cboardinfo;
| ^
| = NULL
drivers/i3c/master.c:2324:12: error: call to undeclared function 'acpi_evaluate_integer'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
2324 | status = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &val);
| ^
drivers/i3c/master.c:2324:12: note: did you mean 'acpi_evaluate_object'?
include/acpi/acpixf.h:550:8: note: 'acpi_evaluate_object' declared here
550 | acpi_evaluate_object(acpi_handle object,
| ^
include/acpi/platform/aclinux.h:93:21: note: expanded from macro 'ACPI_EXTERNAL_RETURN_STATUS'
93 | static ACPI_INLINE prototype {return(AE_NOT_CONFIGURED);}
| ^
drivers/i3c/master.c:2324:38: error: incomplete definition of type 'struct acpi_device'
2324 | status = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &val);
| ~~~~^
include/linux/acpi.h:801:8: note: forward declaration of 'struct acpi_device'
801 | struct acpi_device;
| ^
drivers/i3c/master.c:2352:27: warning: shift count is negative [-Wshift-count-negative]
2352 | boardinfo->pid = (val & GENMASK(47, 0));
| ^~~~~~~~~~~~~~
include/linux/bits.h:35:31: note: expanded from macro 'GENMASK'
35 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
| ^~~~~~~~~~~~~~~
include/uapi/linux/bits.h:9:19: note: expanded from macro '__GENMASK'
9 | (~_UL(0) >> (__BITS_PER_LONG - 1 - (h))))
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 warnings and 2 errors generated.
vim +/i3cboardinfo +1910 drivers/i3c/master.c
1819
1820 /**
1821 * i3c_master_bus_init() - initialize an I3C bus
1822 * @master: main master initializing the bus
1823 *
1824 * This function is following all initialisation steps described in the I3C
1825 * specification:
1826 *
1827 * 1. Attach I2C devs to the master so that the master can fill its internal
1828 * device table appropriately
1829 *
1830 * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
1831 * the master controller. That's usually where the bus mode is selected
1832 * (pure bus or mixed fast/slow bus)
1833 *
1834 * 3. Instruct all devices on the bus to drop their dynamic address. This is
1835 * particularly important when the bus was previously configured by someone
1836 * else (for example the bootloader)
1837 *
1838 * 4. Disable all slave events.
1839 *
1840 * 5. Reserve address slots for I3C devices with init_dyn_addr. And if devices
1841 * also have static_addr, try to pre-assign dynamic addresses requested by
1842 * the FW with SETDASA and attach corresponding statically defined I3C
1843 * devices to the master.
1844 *
1845 * 6. Do a DAA (Dynamic Address Assignment) to assign dynamic addresses to all
1846 * remaining I3C devices
1847 *
1848 * Once this is done, all I3C and I2C devices should be usable.
1849 *
1850 * Return: a 0 in case of success, an negative error code otherwise.
1851 */
1852 static int i3c_master_bus_init(struct i3c_master_controller *master)
1853 {
1854 enum i3c_addr_slot_status status;
1855 struct i2c_dev_boardinfo *i2cboardinfo;
1856 struct i3c_dev_boardinfo *i3cboardinfo;
1857 struct i2c_dev_desc *i2cdev;
1858 int ret;
1859
1860 /*
1861 * First attach all devices with static definitions provided by the
1862 * FW.
1863 */
1864 list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
1865 status = i3c_bus_get_addr_slot_status(&master->bus,
1866 i2cboardinfo->base.addr);
1867 if (status != I3C_ADDR_SLOT_FREE) {
1868 ret = -EBUSY;
1869 goto err_detach_devs;
1870 }
1871
1872 i3c_bus_set_addr_slot_status(&master->bus,
1873 i2cboardinfo->base.addr,
1874 I3C_ADDR_SLOT_I2C_DEV);
1875
1876 i2cdev = i3c_master_alloc_i2c_dev(master,
1877 i2cboardinfo->base.addr,
1878 i2cboardinfo->lvr);
1879 if (IS_ERR(i2cdev)) {
1880 ret = PTR_ERR(i2cdev);
1881 goto err_detach_devs;
1882 }
1883
1884 ret = i3c_master_attach_i2c_dev(master, i2cdev);
1885 if (ret) {
1886 i3c_master_free_i2c_dev(i2cdev);
1887 goto err_detach_devs;
1888 }
1889 }
1890
1891 /*
1892 * Now execute the controller specific ->bus_init() routine, which
1893 * might configure its internal logic to match the bus limitations.
1894 */
1895 ret = master->ops->bus_init(master);
1896 if (ret)
1897 goto err_detach_devs;
1898
1899 /*
1900 * The master device should have been instantiated in ->bus_init(),
1901 * complain if this was not the case.
1902 */
1903 if (!master->this) {
1904 dev_err(&master->dev,
1905 "master_set_info() was not called in ->bus_init()\n");
1906 ret = -EINVAL;
1907 goto err_bus_cleanup;
1908 }
1909
> 1910 i3c_master_add_spd_dev(master, i3cboardinfo);
1911
1912 if (master->ops->set_speed) {
1913 ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
1914 if (ret)
1915 goto err_bus_cleanup;
1916 }
1917
1918 /*
1919 * Reset all dynamic address that may have been assigned before
1920 * (assigned by the bootloader for example).
1921 */
1922 ret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
1923 if (ret && ret != I3C_ERROR_M2)
1924 goto err_bus_cleanup;
1925
1926 if (master->ops->set_speed) {
1927 master->ops->set_speed(master, I3C_OPEN_DRAIN_NORMAL_SPEED);
1928 if (ret)
1929 goto err_bus_cleanup;
1930 }
1931
1932 /* Disable all slave events before starting DAA. */
1933 ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
1934 I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
1935 I3C_CCC_EVENT_HJ);
1936 if (ret && ret != I3C_ERROR_M2)
1937 goto err_bus_cleanup;
1938
1939 /*
1940 * Reserve init_dyn_addr first, and then try to pre-assign dynamic
1941 * address and retrieve device information if needed.
1942 * In case pre-assign dynamic address fails, setting dynamic address to
1943 * the requested init_dyn_addr is retried after DAA is done in
1944 * i3c_master_add_i3c_dev_locked().
1945 */
1946 list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
1947
1948 /*
1949 * We don't reserve a dynamic address for devices that
1950 * don't explicitly request one.
1951 */
1952 if (!i3cboardinfo->init_dyn_addr)
1953 continue;
1954
1955 ret = i3c_bus_get_addr_slot_status(&master->bus,
1956 i3cboardinfo->init_dyn_addr);
1957 if (ret != I3C_ADDR_SLOT_FREE) {
1958 ret = -EBUSY;
1959 goto err_rstdaa;
1960 }
1961
1962 i3c_bus_set_addr_slot_status(&master->bus,
1963 i3cboardinfo->init_dyn_addr,
1964 I3C_ADDR_SLOT_I3C_DEV);
1965
1966 /*
1967 * Only try to create/attach devices that have a static
1968 * address. Other devices will be created/attached when
1969 * DAA happens, and the requested dynamic address will
1970 * be set using SETNEWDA once those devices become
1971 * addressable.
1972 */
1973
1974 if (i3cboardinfo->static_addr)
1975 i3c_master_early_i3c_dev_add(master, i3cboardinfo);
1976 }
1977
1978 ret = i3c_master_do_daa(master);
1979 if (ret)
1980 goto err_rstdaa;
1981
1982 return 0;
1983
1984 err_rstdaa:
1985 i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
1986
1987 err_bus_cleanup:
1988 if (master->ops->bus_cleanup)
1989 master->ops->bus_cleanup(master);
1990
1991 err_detach_devs:
1992 i3c_master_detach_free_devs(master);
1993
1994 return ret;
1995 }
1996
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/6] i3c: master: Add support for SETAASA CCC
2024-10-17 15:03 [PATCH 0/6] Introduce initial support for the AMD I3C (non-HCI) to DW driver Shyam Sundar S K
` (3 preceding siblings ...)
2024-10-17 15:03 ` [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device Shyam Sundar S K
@ 2024-10-17 15:03 ` Shyam Sundar S K
2024-10-17 15:03 ` [PATCH 6/6] i3c: dw: Add quirk to address OD/PP timing issue on AMD platform Shyam Sundar S K
5 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2024-10-17 15:03 UTC (permalink / raw)
To: Alexandre Belloni, Jarkko Nikula
Cc: Sanket.Goswami, linux-i3c, linux-kernel, Shyam Sundar S K
I3C devices like DIMMs over SPD use SETAASA for bus discovery instead of
SETDASA. Add a new routine for I3C host controller drivers to use. If the
I3C slave on the bus is an SPD device, skip the regular DAA process.
According to the SPD spec[1], use SETAASA for bus discovery, and avoid
sending RSTDAA and DISEC, as they are considered illegal. Skip this entire
process if the slave is SPD-compliant, as indicated by the "jdec_spd" flag
from the BIOS.
[1] https://www.jedec.org/system/files/docs/JESD300-5B.01.pdf
(section 2.4 and 2.6.3)
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/i3c/master.c | 32 +++++++++++++++++++++++++++++-
drivers/i3c/master/dw-i3c-master.c | 1 +
include/linux/i3c/ccc.h | 1 +
include/linux/i3c/master.h | 1 +
4 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 4f149519170e..0fe3e315d6cb 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1657,6 +1657,21 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
}
}
+static int i3c_master_setaasa_locked(struct i3c_master_controller *master)
+{
+ struct i3c_ccc_cmd_dest dest;
+ struct i3c_ccc_cmd cmd;
+ int ret;
+
+ i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR, 0);
+ i3c_ccc_cmd_init(&cmd, false, I3C_CCC_SETAASA, &dest, 1);
+
+ ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
+ i3c_ccc_cmd_dest_cleanup(&dest);
+
+ return ret;
+}
+
static int i3c_master_add_spd_dev(struct i3c_master_controller *master,
struct i3c_dev_boardinfo *boardinfo)
{
@@ -1684,6 +1699,10 @@ static int i3c_master_add_spd_dev(struct i3c_master_controller *master,
i3cdev->info.pid = i3cdev->boardinfo->pid;
i3cdev->info.dyn_addr = i3cdev->boardinfo->init_dyn_addr;
+ ret = i3c_master_setaasa_locked(master);
+ if (ret)
+ goto err_free_dev;
+
i3c_bus_normaluse_lock(&master->bus);
i3c_master_register_new_i3c_devs(master);
i3c_bus_normaluse_unlock(&master->bus);
@@ -1907,7 +1926,14 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
goto err_bus_cleanup;
}
- i3c_master_add_spd_dev(master, i3cboardinfo);
+ /*
+ * If the I3C slave on the bus is SPD device, then do not follow the regular
+ * DAA process. Also, as per SPD spec SETAASA is required for the bus discovery
+ * and sending RSTDAA and DISEC is considered as illegal. So skip the entire process
+ * if the jdec_spd flag has been identified from the BIOS.
+ */
+ if (master->jdec_spd)
+ return i3c_master_add_spd_dev(master, i3cboardinfo);
if (master->ops->set_speed) {
ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
@@ -2310,6 +2336,10 @@ static int i3c_acpi_configure_master(struct i3c_master_controller *master)
return -ENODEV;
}
+ status = acpi_evaluate_object(master->ahandle, "_STR", NULL, NULL);
+ if (ACPI_SUCCESS(status))
+ master->jdec_spd = true;
+
num_dev = device_get_child_node_count(dev);
if (!num_dev) {
dev_err(&master->dev, "Error: no child node present\n");
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 8d4583bc2113..8f452976dd7c 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -282,6 +282,7 @@ static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
case I3C_CCC_GETSTATUS:
case I3C_CCC_GETMXDS:
case I3C_CCC_GETHDRCAP:
+ case I3C_CCC_SETAASA:
return true;
default:
return false;
diff --git a/include/linux/i3c/ccc.h b/include/linux/i3c/ccc.h
index ad59a4ae60d1..a145d766ab6f 100644
--- a/include/linux/i3c/ccc.h
+++ b/include/linux/i3c/ccc.h
@@ -32,6 +32,7 @@
#define I3C_CCC_DEFSLVS I3C_CCC_ID(0x8, true)
#define I3C_CCC_ENTTM I3C_CCC_ID(0xb, true)
#define I3C_CCC_ENTHDR(x) I3C_CCC_ID(0x20 + (x), true)
+#define I3C_CCC_SETAASA I3C_CCC_ID(0x29, true)
/* Unicast-only commands */
#define I3C_CCC_SETDASA I3C_CCC_ID(0x7, false)
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 367faf7c4bf3..cd8390d8b469 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -516,6 +516,7 @@ struct i3c_master_controller {
const struct i3c_master_controller_ops *ops;
unsigned int secondary : 1;
unsigned int init_done : 1;
+ unsigned int jdec_spd : 1;
unsigned int hotjoin: 1;
struct {
struct list_head i3c;
--
2.34.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 6/6] i3c: dw: Add quirk to address OD/PP timing issue on AMD platform
2024-10-17 15:03 [PATCH 0/6] Introduce initial support for the AMD I3C (non-HCI) to DW driver Shyam Sundar S K
` (4 preceding siblings ...)
2024-10-17 15:03 ` [PATCH 5/6] i3c: master: Add support for SETAASA CCC Shyam Sundar S K
@ 2024-10-17 15:03 ` Shyam Sundar S K
5 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2024-10-17 15:03 UTC (permalink / raw)
To: Alexandre Belloni, Jarkko Nikula
Cc: Sanket.Goswami, linux-i3c, linux-kernel, Shyam Sundar S K
The AMD Legacy I3C is having a problem with its IP, specifically with the
push-pull and open-drain pull-up registers. These registers need to be
manually programmed for every CCC submission to align with the duty cycle.
Therefore, add a quirk to address this issue.
Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/i3c/master/dw-i3c-master.c | 29 ++++++++++++++++++++++++++++-
drivers/i3c/master/dw-i3c-master.h | 1 +
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 8f452976dd7c..8500b0d0dcf3 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -220,6 +220,14 @@
#define XFER_TIMEOUT (msecs_to_jiffies(1000))
#define RPM_AUTOSUSPEND_TIMEOUT 1000 /* ms */
+
+/* Timing values to configure 12.5MHz frequency */
+#define AMD_I3C_OD_TIMING 0x4C007C
+#define AMD_I3C_PP_TIMING 0x8001A
+
+/* List of quirks */
+#define AMD_I3C_OD_PP_TIMING BIT(1)
+
struct dw_i3c_cmd {
u32 cmd_lo;
u32 cmd_hi;
@@ -795,6 +803,12 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
return ret;
}
+static void amd_configure_od_pp_quirk(struct dw_i3c_master *master)
+{
+ master->i3c_od_timing = AMD_I3C_OD_TIMING;
+ master->i3c_pp_timing = AMD_I3C_PP_TIMING;
+}
+
static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
struct i3c_ccc_cmd *ccc)
{
@@ -804,6 +818,13 @@ static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
if (ccc->id == I3C_CCC_ENTDAA)
return -EINVAL;
+ /* AMD platform specific OD and PP timings */
+ if (master->quirks & AMD_I3C_OD_PP_TIMING) {
+ amd_configure_od_pp_quirk(master);
+ writel(master->i3c_pp_timing, master->regs + SCL_I3C_PP_TIMING);
+ writel(master->i3c_od_timing, master->regs + SCL_I3C_OD_TIMING);
+ }
+
ret = pm_runtime_resume_and_get(master->dev);
if (ret < 0) {
dev_err(master->dev,
@@ -1608,6 +1629,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
if (!master->base.ahandle)
dev_err(&pdev->dev, "Failed to get acpi device handle\n");
+ master->quirks = (unsigned long)device_get_match_data(&pdev->dev);
+
INIT_WORK(&master->hj_work, dw_i3c_hj_work);
ret = i3c_master_register(&master->base, &pdev->dev,
&dw_mipi_i3c_ops, false);
@@ -1681,6 +1704,10 @@ static void dw_i3c_master_restore_addrs(struct dw_i3c_master *master)
static void dw_i3c_master_restore_timing_regs(struct dw_i3c_master *master)
{
+ /* AMD platform specific OD and PP timings */
+ if (master->quirks & AMD_I3C_OD_PP_TIMING)
+ amd_configure_od_pp_quirk(master);
+
writel(master->i3c_pp_timing, master->regs + SCL_I3C_PP_TIMING);
writel(master->bus_free_timing, master->regs + BUS_FREE_TIMING);
writel(master->i3c_od_timing, master->regs + SCL_I3C_OD_TIMING);
@@ -1755,7 +1782,7 @@ static const struct of_device_id dw_i3c_master_of_match[] = {
MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match);
static const struct acpi_device_id amd_i3c_device_match[] = {
- { "AMDI0015" },
+ { "AMDI0015", AMD_I3C_OD_PP_TIMING },
{ }
};
MODULE_DEVICE_TABLE(acpi, amd_i3c_device_match);
diff --git a/drivers/i3c/master/dw-i3c-master.h b/drivers/i3c/master/dw-i3c-master.h
index 219ff815d3a7..c5cb695c16ab 100644
--- a/drivers/i3c/master/dw-i3c-master.h
+++ b/drivers/i3c/master/dw-i3c-master.h
@@ -50,6 +50,7 @@ struct dw_i3c_master {
u32 bus_free_timing;
u32 i2c_fm_timing;
u32 i2c_fmp_timing;
+ u32 quirks;
/*
* Per-device hardware data, used to manage the device address table
* (DAT)
--
2.34.1
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 10+ messages in thread