Skip to content

Commit 473d0cb

Browse files
Shyam Sundar S Kalexandrebelloni
authored andcommitted
i3c: dw: Add quirk to address OD/PP timing issue on AMD platform
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. Reviewed-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> 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> Link: https://lore.kernel.org/r/20241114110239.660551-3-Shyam-sundar.S-k@amd.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent 0a0d851 commit 473d0cb

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

drivers/i3c/master/dw-i3c-master.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@
220220

221221
#define XFER_TIMEOUT (msecs_to_jiffies(1000))
222222
#define RPM_AUTOSUSPEND_TIMEOUT 1000 /* ms */
223+
224+
/* Timing values to configure 12.5MHz frequency */
225+
#define AMD_I3C_OD_TIMING 0x4C007C
226+
#define AMD_I3C_PP_TIMING 0x8001A
227+
228+
/* List of quirks */
229+
#define AMD_I3C_OD_PP_TIMING BIT(1)
230+
223231
struct dw_i3c_cmd {
224232
u32 cmd_lo;
225233
u32 cmd_hi;
@@ -794,6 +802,12 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
794802
return ret;
795803
}
796804

805+
static void amd_configure_od_pp_quirk(struct dw_i3c_master *master)
806+
{
807+
master->i3c_od_timing = AMD_I3C_OD_TIMING;
808+
master->i3c_pp_timing = AMD_I3C_PP_TIMING;
809+
}
810+
797811
static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
798812
struct i3c_ccc_cmd *ccc)
799813
{
@@ -803,6 +817,13 @@ static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
803817
if (ccc->id == I3C_CCC_ENTDAA)
804818
return -EINVAL;
805819

820+
/* AMD platform specific OD and PP timings */
821+
if (master->quirks & AMD_I3C_OD_PP_TIMING) {
822+
amd_configure_od_pp_quirk(master);
823+
writel(master->i3c_pp_timing, master->regs + SCL_I3C_PP_TIMING);
824+
writel(master->i3c_od_timing, master->regs + SCL_I3C_OD_TIMING);
825+
}
826+
806827
ret = pm_runtime_resume_and_get(master->dev);
807828
if (ret < 0) {
808829
dev_err(master->dev,
@@ -1602,6 +1623,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
16021623
master->maxdevs = ret >> 16;
16031624
master->free_pos = GENMASK(master->maxdevs - 1, 0);
16041625

1626+
master->quirks = (unsigned long)device_get_match_data(&pdev->dev);
1627+
16051628
INIT_WORK(&master->hj_work, dw_i3c_hj_work);
16061629
ret = i3c_master_register(&master->base, &pdev->dev,
16071630
&dw_mipi_i3c_ops, false);
@@ -1675,6 +1698,10 @@ static void dw_i3c_master_restore_addrs(struct dw_i3c_master *master)
16751698

16761699
static void dw_i3c_master_restore_timing_regs(struct dw_i3c_master *master)
16771700
{
1701+
/* AMD platform specific OD and PP timings */
1702+
if (master->quirks & AMD_I3C_OD_PP_TIMING)
1703+
amd_configure_od_pp_quirk(master);
1704+
16781705
writel(master->i3c_pp_timing, master->regs + SCL_I3C_PP_TIMING);
16791706
writel(master->bus_free_timing, master->regs + BUS_FREE_TIMING);
16801707
writel(master->i3c_od_timing, master->regs + SCL_I3C_OD_TIMING);
@@ -1749,7 +1776,7 @@ static const struct of_device_id dw_i3c_master_of_match[] = {
17491776
MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match);
17501777

17511778
static const struct acpi_device_id amd_i3c_device_match[] = {
1752-
{ "AMDI0015" },
1779+
{ "AMDI0015", AMD_I3C_OD_PP_TIMING },
17531780
{ }
17541781
};
17551782
MODULE_DEVICE_TABLE(acpi, amd_i3c_device_match);

drivers/i3c/master/dw-i3c-master.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct dw_i3c_master {
5050
u32 bus_free_timing;
5151
u32 i2c_fm_timing;
5252
u32 i2c_fmp_timing;
53+
u32 quirks;
5354
/*
5455
* Per-device hardware data, used to manage the device address table
5556
* (DAT)

0 commit comments

Comments
 (0)