* [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers
@ 2024-08-02 13:01 Adrian Huang
2024-08-05 14:27 ` Jarkko Nikula
2024-08-05 17:26 ` Andi Shyti
0 siblings, 2 replies; 5+ messages in thread
From: Adrian Huang @ 2024-08-02 13:01 UTC (permalink / raw)
To: Jarkko Nikula, Andy Shevchenko, Mika Westerberg, Jan Dabros
Cc: Andi Shyti, linux-i2c, Adrian Huang, Dong Wang
From: Adrian Huang <ahuang12@lenovo.com>
When disabling CONFIG_X86_AMD_PLATFORM_DEVICE option, the driver
'drivers/acpi/acpi_apd.c' won't be compiled. This leads to a situation
where BMC (Baseboard Management Controller) cannot retrieve the memory
temperature via the i2c interface after i2c DW driver is loaded. Note
that BMC can retrieve the memory temperature before booting into OS.
[Debugging Detail]
1. dev->pclk and dev->clk are NULL when calling devm_clk_get_optional()
in dw_i2c_plat_probe().
2. The callings of i2c_dw_scl_hcnt() in i2c_dw_set_timings_master()
return 65528 (-8 in integer format) or 65533 (-3 in integer format).
The following log shows SS's HCNT/LCNT:
i2c_designware AMDI0010:01: Standard Mode HCNT:LCNT = 65533:65535
3. The callings of i2c_dw_scl_lcnt() in i2c_dw_set_timings_master()
return 65535 (-1 in integer format). The following log shows SS's
HCNT/LCNT:
i2c_designware AMDI0010:01: Fast Mode HCNT:LCNT = 65533:65535
4. i2c_dw_init_master() configures the register IC_SS_SCL_HCNT with
the value 65533. However, the DW i2c databook mentioned the value
cannot be higher than 65525. Quote from the DW i2c databook:
NOTE: This register must not be programmed to a value higher than
65525, because DW_apb_i2c uses a 16-bit counter to flag an
I2C bus idle condition when this counter reaches a value of
IC_SS_SCL_HCNT + 10.
5. Since ss_hcnt, ss_lcnt, fs_hcnt, and fs_lcnt are the invalid
values, we should not write the corresponding registers.
Fix the issue by reading dev->{ss,fs,hs}_hcnt and dev->{ss,fs,hs}_lcnt
from HW registers if ic_clk is not set.
Link: https://lore.kernel.org/linux-i2c/8295cbe1-a7c5-4a35-a189-5d0bff51ede6@linux.intel.com/
Suggested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Adrian Huang <ahuang12@lenovo.com>
Reported-by: Dong Wang <wangdong28@lenovo.com>
Tested-by: Dong Wang <wangdong28@lenovo.com>
---
drivers/i2c/busses/i2c-designware-common.c | 27 ++++++++++++++++--
drivers/i2c/busses/i2c-designware-core.h | 6 ++--
drivers/i2c/busses/i2c-designware-master.c | 32 ++++++++++++++++------
3 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index e8a688d04aee..4160c5e57df4 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -332,8 +332,27 @@ void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev)
}
EXPORT_SYMBOL_GPL(i2c_dw_adjust_bus_speed);
-u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
+static u32 i2c_dw_read_scl_reg(struct dw_i2c_dev *dev, u32 reg)
{
+ u32 val;
+ int ret;
+
+ ret = i2c_dw_acquire_lock(dev);
+ if (ret)
+ return 0;
+
+ ret = regmap_read(dev->map, reg, &val);
+ i2c_dw_release_lock(dev);
+
+ return ret ? 0 : val;
+}
+
+u32 i2c_dw_scl_hcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
+ u32 tSYMBOL, u32 tf, int cond, int offset)
+{
+ if (!ic_clk)
+ return i2c_dw_read_scl_reg(dev, reg);
+
/*
* DesignWare I2C core doesn't seem to have solid strategy to meet
* the tHD;STA timing spec. Configuring _HCNT based on tHIGH spec
@@ -372,8 +391,12 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
3 + offset;
}
-u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
+u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
+ u32 tLOW, u32 tf, int offset)
{
+ if (!ic_clk)
+ return i2c_dw_read_scl_reg(dev, reg);
+
/*
* Conditional expression:
*
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index e9606c00b8d1..3e48f446ce53 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -329,8 +329,10 @@ struct i2c_dw_semaphore_callbacks {
};
int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
-u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
-u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
+u32 i2c_dw_scl_hcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
+ u32 tSYMBOL, u32 tf, int cond, int offset);
+u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
+ u32 tLOW, u32 tf, int offset);
int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
u32 i2c_dw_clk_rate(struct dw_i2c_dev *dev);
int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index c7e56002809a..d3b466592be4 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -64,13 +64,17 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
if (!dev->ss_hcnt || !dev->ss_lcnt) {
ic_clk = i2c_dw_clk_rate(dev);
dev->ss_hcnt =
- i2c_dw_scl_hcnt(ic_clk,
+ i2c_dw_scl_hcnt(dev,
+ DW_IC_SS_SCL_HCNT,
+ ic_clk,
4000, /* tHD;STA = tHIGH = 4.0 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
dev->ss_lcnt =
- i2c_dw_scl_lcnt(ic_clk,
+ i2c_dw_scl_lcnt(dev,
+ DW_IC_SS_SCL_LCNT,
+ ic_clk,
4700, /* tLOW = 4.7 us */
scl_falling_time,
0); /* No offset */
@@ -94,13 +98,17 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
} else {
ic_clk = i2c_dw_clk_rate(dev);
dev->fs_hcnt =
- i2c_dw_scl_hcnt(ic_clk,
+ i2c_dw_scl_hcnt(dev,
+ DW_IC_FS_SCL_HCNT,
+ ic_clk,
260, /* tHIGH = 260 ns */
sda_falling_time,
0, /* DW default */
0); /* No offset */
dev->fs_lcnt =
- i2c_dw_scl_lcnt(ic_clk,
+ i2c_dw_scl_lcnt(dev,
+ DW_IC_FS_SCL_LCNT,
+ ic_clk,
500, /* tLOW = 500 ns */
scl_falling_time,
0); /* No offset */
@@ -114,13 +122,17 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
if (!dev->fs_hcnt || !dev->fs_lcnt) {
ic_clk = i2c_dw_clk_rate(dev);
dev->fs_hcnt =
- i2c_dw_scl_hcnt(ic_clk,
+ i2c_dw_scl_hcnt(dev,
+ DW_IC_FS_SCL_HCNT,
+ ic_clk,
600, /* tHD;STA = tHIGH = 0.6 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
dev->fs_lcnt =
- i2c_dw_scl_lcnt(ic_clk,
+ i2c_dw_scl_lcnt(dev,
+ DW_IC_FS_SCL_LCNT,
+ ic_clk,
1300, /* tLOW = 1.3 us */
scl_falling_time,
0); /* No offset */
@@ -142,13 +154,17 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
} else if (!dev->hs_hcnt || !dev->hs_lcnt) {
ic_clk = i2c_dw_clk_rate(dev);
dev->hs_hcnt =
- i2c_dw_scl_hcnt(ic_clk,
+ i2c_dw_scl_hcnt(dev,
+ DW_IC_HS_SCL_HCNT,
+ ic_clk,
160, /* tHIGH = 160 ns */
sda_falling_time,
0, /* DW default */
0); /* No offset */
dev->hs_lcnt =
- i2c_dw_scl_lcnt(ic_clk,
+ i2c_dw_scl_lcnt(dev,
+ DW_IC_HS_SCL_LCNT,
+ ic_clk,
320, /* tLOW = 320 ns */
scl_falling_time,
0); /* No offset */
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers
2024-08-02 13:01 [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers Adrian Huang
@ 2024-08-05 14:27 ` Jarkko Nikula
2024-08-05 17:26 ` Andi Shyti
1 sibling, 0 replies; 5+ messages in thread
From: Jarkko Nikula @ 2024-08-05 14:27 UTC (permalink / raw)
To: Adrian Huang, Andy Shevchenko, Mika Westerberg, Jan Dabros
Cc: Andi Shyti, linux-i2c, Adrian Huang, Dong Wang
On 8/2/24 4:01 PM, Adrian Huang wrote:
> From: Adrian Huang <ahuang12@lenovo.com>
>
> When disabling CONFIG_X86_AMD_PLATFORM_DEVICE option, the driver
> 'drivers/acpi/acpi_apd.c' won't be compiled. This leads to a situation
> where BMC (Baseboard Management Controller) cannot retrieve the memory
> temperature via the i2c interface after i2c DW driver is loaded. Note
> that BMC can retrieve the memory temperature before booting into OS.
>
> [Debugging Detail]
> 1. dev->pclk and dev->clk are NULL when calling devm_clk_get_optional()
> in dw_i2c_plat_probe().
>
> 2. The callings of i2c_dw_scl_hcnt() in i2c_dw_set_timings_master()
> return 65528 (-8 in integer format) or 65533 (-3 in integer format).
> The following log shows SS's HCNT/LCNT:
>
> i2c_designware AMDI0010:01: Standard Mode HCNT:LCNT = 65533:65535
>
> 3. The callings of i2c_dw_scl_lcnt() in i2c_dw_set_timings_master()
> return 65535 (-1 in integer format). The following log shows SS's
> HCNT/LCNT:
>
> i2c_designware AMDI0010:01: Fast Mode HCNT:LCNT = 65533:65535
>
> 4. i2c_dw_init_master() configures the register IC_SS_SCL_HCNT with
> the value 65533. However, the DW i2c databook mentioned the value
> cannot be higher than 65525. Quote from the DW i2c databook:
>
> NOTE: This register must not be programmed to a value higher than
> 65525, because DW_apb_i2c uses a 16-bit counter to flag an
> I2C bus idle condition when this counter reaches a value of
> IC_SS_SCL_HCNT + 10.
>
> 5. Since ss_hcnt, ss_lcnt, fs_hcnt, and fs_lcnt are the invalid
> values, we should not write the corresponding registers.
>
> Fix the issue by reading dev->{ss,fs,hs}_hcnt and dev->{ss,fs,hs}_lcnt
> from HW registers if ic_clk is not set.
>
> Link: https://lore.kernel.org/linux-i2c/8295cbe1-a7c5-4a35-a189-5d0bff51ede6@linux.intel.com/
> Suggested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> Signed-off-by: Adrian Huang <ahuang12@lenovo.com>
> Reported-by: Dong Wang <wangdong28@lenovo.com>
> Tested-by: Dong Wang <wangdong28@lenovo.com>
>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers
2024-08-02 13:01 [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers Adrian Huang
2024-08-05 14:27 ` Jarkko Nikula
@ 2024-08-05 17:26 ` Andi Shyti
2024-08-06 12:10 ` Huang Adrian
2024-08-12 17:13 ` Andy Shevchenko
1 sibling, 2 replies; 5+ messages in thread
From: Andi Shyti @ 2024-08-05 17:26 UTC (permalink / raw)
To: Adrian Huang
Cc: Jarkko Nikula, Andy Shevchenko, Mika Westerberg, Jan Dabros,
linux-i2c, Adrian Huang, Dong Wang
Hi Adrian,
> Link: https://lore.kernel.org/linux-i2c/8295cbe1-a7c5-4a35-a189-5d0bff51ede6@linux.intel.com/
> Suggested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> Signed-off-by: Adrian Huang <ahuang12@lenovo.com>
> Reported-by: Dong Wang <wangdong28@lenovo.com>
> Tested-by: Dong Wang <wangdong28@lenovo.com>
At first I thought that we need a Fixes tag, but on a second
thought I judged this more as a behavioural fix. Please, let me
konw if you think we want to have the Fixes tag here.
Meantime, I'm going to re-arrange the tag section. It's common to
sort the tags in a chronological order:
Reported-by: (it first gets reported)
Suggested-by: (then someone suggested the fix)
Signed-off-by: (then someone implemented the fix)
Tested-by: (finally someone tested it)
Link: (as reference)
I will also appreciate that the Reviewed-by and Tested-by and
Acked-by happen transparently and openly in the mailing list
rather behind the curtains.
Said that, thanks for your patch, I merged it into i2c/i2c-host.
Andi
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers
2024-08-05 17:26 ` Andi Shyti
@ 2024-08-06 12:10 ` Huang Adrian
2024-08-12 17:13 ` Andy Shevchenko
1 sibling, 0 replies; 5+ messages in thread
From: Huang Adrian @ 2024-08-06 12:10 UTC (permalink / raw)
To: Andi Shyti
Cc: Jarkko Nikula, Andy Shevchenko, Mika Westerberg, Jan Dabros,
linux-i2c, Adrian Huang, Dong Wang
Hi Andi,
On Tue, Aug 6, 2024 at 1:27 AM Andi Shyti <andi.shyti@kernel.org> wrote:
>
> Hi Adrian,
>
> > Link: https://lore.kernel.org/linux-i2c/8295cbe1-a7c5-4a35-a189-5d0bff51ede6@linux.intel.com/
> > Suggested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> > Signed-off-by: Adrian Huang <ahuang12@lenovo.com>
> > Reported-by: Dong Wang <wangdong28@lenovo.com>
> > Tested-by: Dong Wang <wangdong28@lenovo.com>
>
> At first I thought that we need a Fixes tag, but on a second
> thought I judged this more as a behavioural fix. Please, let me
> konw if you think we want to have the Fixes tag here.
Agree with your second thought, so no need to add the Fixes tag.
> Meantime, I'm going to re-arrange the tag section. It's common to
> sort the tags in a chronological order:
>
> Reported-by: (it first gets reported)
> Suggested-by: (then someone suggested the fix)
> Signed-off-by: (then someone implemented the fix)
> Tested-by: (finally someone tested it)
> Link: (as reference)
>
> I will also appreciate that the Reviewed-by and Tested-by and
> Acked-by happen transparently and openly in the mailing list
> rather behind the curtains.
I'm sorry for the inconvenience. Wil pay more attention in the future.
> Said that, thanks for your patch, I merged it into i2c/i2c-host.
Thank you.
-- Adrian
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers
2024-08-05 17:26 ` Andi Shyti
2024-08-06 12:10 ` Huang Adrian
@ 2024-08-12 17:13 ` Andy Shevchenko
1 sibling, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2024-08-12 17:13 UTC (permalink / raw)
To: Andi Shyti
Cc: Adrian Huang, Jarkko Nikula, Mika Westerberg, Jan Dabros,
linux-i2c, Adrian Huang, Dong Wang
On Mon, Aug 05, 2024 at 07:26:55PM +0200, Andi Shyti wrote:
> Hi Adrian,
>
> > Link: https://lore.kernel.org/linux-i2c/8295cbe1-a7c5-4a35-a189-5d0bff51ede6@linux.intel.com/
> > Suggested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
> > Signed-off-by: Adrian Huang <ahuang12@lenovo.com>
> > Reported-by: Dong Wang <wangdong28@lenovo.com>
> > Tested-by: Dong Wang <wangdong28@lenovo.com>
>
> At first I thought that we need a Fixes tag, but on a second
> thought I judged this more as a behavioural fix. Please, let me
> konw if you think we want to have the Fixes tag here.
>
> Meantime, I'm going to re-arrange the tag section. It's common to
> sort the tags in a chronological order:
>
> Reported-by: (it first gets reported)
> Suggested-by: (then someone suggested the fix)
> Signed-off-by: (then someone implemented the fix)
> Tested-by: (finally someone tested it)
> Link: (as reference)
If you use `b4`, you may configure it to do this automatically and keep nice
with contributors :-)
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-08-12 17:13 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-02 13:01 [PATCH v2 1/1] i2c: designware: Fix wrong setting for {ss,fs,hs}_{h,l}cnt registers Adrian Huang
2024-08-05 14:27 ` Jarkko Nikula
2024-08-05 17:26 ` Andi Shyti
2024-08-06 12:10 ` Huang Adrian
2024-08-12 17:13 ` Andy Shevchenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox