* [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency
@ 2025-07-10 5:50 Troy Mitchell
2025-07-11 9:20 ` Andi Shyti
2025-07-11 10:10 ` kernel test robot
0 siblings, 2 replies; 4+ messages in thread
From: Troy Mitchell @ 2025-07-10 5:50 UTC (permalink / raw)
To: Andi Shyti, Yixun Lan
Cc: linux-i2c, linux-kernel, linux-riscv, spacemit, Troy Mitchell
The SpacemiT I2C controller's SCL (Serial Clock Line) frequency for
master mode operations is determined by the ILCR (I2C Load Count Register).
Previously, the driver relied on the hardware's reset default
values for this register.
The hardware's default ILCR values (SLV=0x156, FLV=0x5d) yield SCL
frequencies lower than intended. For example, with the default
31.5 MHz input clock, these default settings result in an SCL
frequency of approximately 93 kHz (standard mode) when targeting 100 kHz,
and approximately 338 kHz (fast mode) when targeting 400 kHz.
These frequencies are below the 100 kHz/400 kHz nominal speeds.
This patch integrates the SCL frequency management into
the Common Clock Framework (CCF). Specifically, the ILCR register,
which acts as a frequency divider for the SCL clock, is now registered
as a managed clock (scl_clk) within the CCF.
Additionally, the driver now validates user-provided SCL frequency values
and rejects illegal settings, rather than silently adjusting them.
This patch also cleans up unnecessary whitespace
in the included header files.
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
drivers/i2c/busses/i2c-k1.c | 170 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 154 insertions(+), 16 deletions(-)
diff --git a/drivers/i2c/busses/i2c-k1.c b/drivers/i2c/busses/i2c-k1.c
index b68a21fff0b56b59fe2032ccb7ca6953423aad32..e846156466493f748c17f38bd4eaf99f68950202 100644
--- a/drivers/i2c/busses/i2c-k1.c
+++ b/drivers/i2c/busses/i2c-k1.c
@@ -3,17 +3,21 @@
* Copyright (C) 2024-2025 Troy Mitchell <troymitchell988@gmail.com>
*/
- #include <linux/clk.h>
- #include <linux/i2c.h>
- #include <linux/iopoll.h>
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/platform_device.h>
+#include "linux/bits.h"
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/i2c.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
/* spacemit i2c registers */
#define SPACEMIT_ICR 0x0 /* Control register */
#define SPACEMIT_ISR 0x4 /* Status register */
#define SPACEMIT_IDBR 0xc /* Data buffer register */
+#define SPACEMIT_ILCR 0x10 /* Load Count Register */
#define SPACEMIT_IBMR 0x1c /* Bus monitor register */
/* SPACEMIT_ICR register fields */
@@ -80,6 +84,17 @@
#define SPACEMIT_BMR_SDA BIT(0) /* SDA line level */
#define SPACEMIT_BMR_SCL BIT(1) /* SCL line level */
+#define SPACEMIT_LCR_LV_STANDARD_SHIFT 0
+#define SPACEMIT_LCR_LV_FAST_SHIFT 9
+#define SPACEMIT_LCR_LV_STANDARD_WIDTH 9
+#define SPACEMIT_LCR_LV_FAST_WIDTH 9
+#define SPACEMIT_LCR_LV_STANDARD_MASK GENMASK(SPACEMIT_LCR_LV_STANDARD_SHIFT +\
+ SPACEMIT_LCR_LV_STANDARD_WIDTH - 1,\
+ SPACEMIT_LCR_LV_STANDARD_SHIFT)
+#define SPACEMIT_LCR_LV_FAST_MASK GENMASK(SPACEMIT_LCR_LV_FAST_SHIFT +\
+ SPACEMIT_LCR_LV_FAST_WIDTH - 1,\
+ SPACEMIT_LCR_LV_FAST_SHIFT)
+
/* i2c bus recover timeout: us */
#define SPACEMIT_I2C_BUS_BUSY_TIMEOUT 100000
@@ -95,11 +110,20 @@ enum spacemit_i2c_state {
SPACEMIT_STATE_WRITE,
};
+enum spacemit_i2c_mode {
+ SPACEMIT_MODE_STANDARD,
+ SPACEMIT_MODE_FAST
+};
+
/* i2c-spacemit driver's main struct */
struct spacemit_i2c_dev {
struct device *dev;
struct i2c_adapter adapt;
+ struct clk_hw scl_clk_hw;
+ struct clk *scl_clk;
+ enum spacemit_i2c_mode mode;
+
/* hardware resources */
void __iomem *base;
int irq;
@@ -120,6 +144,78 @@ struct spacemit_i2c_dev {
u32 status;
};
+static void spacemit_i2c_scl_clk_disable_unprepare(void *data)
+{
+ struct spacemit_i2c_dev *i2c = data;
+
+ clk_disable_unprepare(i2c->scl_clk);
+}
+
+static void spacemit_i2c_scl_clk_exclusive_put(void *data)
+{
+ struct spacemit_i2c_dev *i2c = data;
+
+ clk_rate_exclusive_put(i2c->scl_clk);
+}
+
+static int spacemit_i2c_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct spacemit_i2c_dev *i2c = container_of(hw, struct spacemit_i2c_dev, scl_clk_hw);
+ u32 lv, lcr;
+
+ lv = DIV_ROUND_UP(parent_rate, rate);
+
+ lcr = readl(i2c->base + SPACEMIT_ILCR);
+ if (i2c->mode == SPACEMIT_MODE_STANDARD) {
+ lcr &= ~SPACEMIT_LCR_LV_STANDARD_MASK;
+ lcr |= lv << SPACEMIT_LCR_LV_STANDARD_SHIFT;
+ } else if (i2c->mode == SPACEMIT_MODE_FAST) {
+ lcr &= ~SPACEMIT_LCR_LV_FAST_MASK;
+ lcr |= lv << SPACEMIT_LCR_LV_FAST_SHIFT;
+ }
+ writel(lcr, i2c->base + SPACEMIT_ILCR);
+
+ return 0;
+}
+
+static long spacemit_i2c_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u32 lv, freq;
+
+ lv = DIV_ROUND_UP(*parent_rate, rate);
+ freq = DIV_ROUND_UP(*parent_rate, lv);
+
+ return freq;
+}
+
+static unsigned long spacemit_i2c_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct spacemit_i2c_dev *i2c = container_of(hw, struct spacemit_i2c_dev, scl_clk_hw);
+ u32 lcr, lv = 0;
+
+ lcr = readl(i2c->base + SPACEMIT_ILCR);
+
+ if (i2c->mode == SPACEMIT_MODE_STANDARD)
+ lv = (lcr >> SPACEMIT_LCR_LV_STANDARD_SHIFT) &
+ GENMASK(SPACEMIT_LCR_LV_STANDARD_WIDTH - 1, 0);
+ else if (i2c->mode == SPACEMIT_MODE_FAST)
+ lv = (lcr >> SPACEMIT_LCR_LV_FAST_SHIFT) &
+ GENMASK(SPACEMIT_LCR_LV_FAST_WIDTH - 1, 0);
+ else
+ return 0;
+
+ return DIV_ROUND_UP(parent_rate, lv);
+}
+
+static const struct clk_ops spacemit_i2c_clk_ops = {
+ .set_rate = spacemit_i2c_clk_set_rate,
+ .round_rate = spacemit_i2c_clk_round_rate,
+ .recalc_rate = spacemit_i2c_clk_recalc_rate,
+};
+
static void spacemit_i2c_enable(struct spacemit_i2c_dev *i2c)
{
u32 val;
@@ -138,6 +234,27 @@ static void spacemit_i2c_disable(struct spacemit_i2c_dev *i2c)
writel(val, i2c->base + SPACEMIT_ICR);
}
+static struct clk *spacemit_i2c_register_scl_clk(struct spacemit_i2c_dev *i2c,
+ struct clk *parent)
+{
+ struct clk_init_data init;
+ char name[32];
+
+ snprintf(name, sizeof(name), "%s_scl_clk", dev_name(i2c->dev));
+
+ init.name = name;
+ init.ops = &spacemit_i2c_clk_ops;
+ init.parent_data = (struct clk_parent_data[]) {
+ { .fw_name = "func" },
+ };
+ init.num_parents = 1;
+ init.flags = 0;
+
+ i2c->scl_clk_hw.init = &init;
+
+ return devm_clk_register(i2c->dev, &i2c->scl_clk_hw);
+}
+
static void spacemit_i2c_reset(struct spacemit_i2c_dev *i2c)
{
writel(SPACEMIT_CR_UR, i2c->base + SPACEMIT_ICR);
@@ -224,7 +341,7 @@ static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c)
*/
val |= SPACEMIT_CR_DRFIE;
- if (i2c->clock_freq == SPACEMIT_I2C_MAX_FAST_MODE_FREQ)
+ if (i2c->mode == SPACEMIT_MODE_FAST)
val |= SPACEMIT_CR_MODE_FAST;
/* disable response to general call */
@@ -519,15 +636,13 @@ static int spacemit_i2c_probe(struct platform_device *pdev)
dev_warn(dev, "failed to read clock-frequency property: %d\n", ret);
/* For now, this driver doesn't support high-speed. */
- if (!i2c->clock_freq || i2c->clock_freq > SPACEMIT_I2C_MAX_FAST_MODE_FREQ) {
- dev_warn(dev, "unsupported clock frequency %u; using %u\n",
- i2c->clock_freq, SPACEMIT_I2C_MAX_FAST_MODE_FREQ);
- i2c->clock_freq = SPACEMIT_I2C_MAX_FAST_MODE_FREQ;
- } else if (i2c->clock_freq < SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ) {
- dev_warn(dev, "unsupported clock frequency %u; using %u\n",
- i2c->clock_freq, SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ);
- i2c->clock_freq = SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ;
- }
+ if (i2c->clock_freq > SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ &&
+ i2c->clock_freq <= SPACEMIT_I2C_MAX_FAST_MODE_FREQ)
+ i2c->mode = SPACEMIT_MODE_FAST;
+ else if (i2c->clock_freq && i2c->clock_freq <= SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ)
+ i2c->mode = SPACEMIT_MODE_STANDARD;
+ else
+ return -EINVAL;
i2c->dev = &pdev->dev;
@@ -548,10 +663,33 @@ static int spacemit_i2c_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk), "failed to enable func clock");
+ i2c->scl_clk = spacemit_i2c_register_scl_clk(i2c, clk);
+ if (IS_ERR(i2c->scl_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(i2c->scl_clk),
+ "failed to register scl clock\n");
+
clk = devm_clk_get_enabled(dev, "bus");
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk), "failed to enable bus clock");
+ ret = clk_set_rate_exclusive(i2c->scl_clk, i2c->clock_freq);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to set exclusive rate for SCL clock");
+
+ ret = devm_add_action_or_reset(dev, spacemit_i2c_scl_clk_exclusive_put, i2c);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to register cleanup action for exclusive SCL clock rate");
+
+ ret = clk_prepare_enable(i2c->scl_clk);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to prepare and enable clock");
+
+ ret = devm_add_action_or_reset(dev, spacemit_i2c_scl_clk_disable_unprepare, i2c);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to register cleanup action for clk disable and unprepare");
+
spacemit_i2c_reset(i2c);
i2c_set_adapdata(&i2c->adapt, i2c);
---
base-commit: 733923397fd95405a48f165c9b1fbc8c4b0a4681
change-id: 20250709-k1-i2c-ilcr-ea347e0850a4
Best regards,
--
Troy Mitchell <troy.mitchell@linux.spacemit.com>
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency
2025-07-10 5:50 [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency Troy Mitchell
@ 2025-07-11 9:20 ` Andi Shyti
2025-07-14 1:11 ` Troy Mitchell
2025-07-11 10:10 ` kernel test robot
1 sibling, 1 reply; 4+ messages in thread
From: Andi Shyti @ 2025-07-11 9:20 UTC (permalink / raw)
To: Troy Mitchell; +Cc: Yixun Lan, linux-i2c, linux-kernel, linux-riscv, spacemit
Hi Troy,
> - #include <linux/clk.h>
> - #include <linux/i2c.h>
> - #include <linux/iopoll.h>
> - #include <linux/module.h>
> - #include <linux/of_address.h>
> - #include <linux/platform_device.h>
> +#include "linux/bits.h"
this should be <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
> +#include <linux/i2c.h>
> +#include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
Is the diff a bit noisy or am I failing to see some differences?
> /* spacemit i2c registers */
> #define SPACEMIT_ICR 0x0 /* Control register */
> #define SPACEMIT_ISR 0x4 /* Status register */
> #define SPACEMIT_IDBR 0xc /* Data buffer register */
> +#define SPACEMIT_ILCR 0x10 /* Load Count Register */
> #define SPACEMIT_IBMR 0x1c /* Bus monitor register */
...
> +static int spacemit_i2c_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
here the alignment is a bit off.
> +{
> + struct spacemit_i2c_dev *i2c = container_of(hw, struct spacemit_i2c_dev, scl_clk_hw);
> + u32 lv, lcr;
> +
> + lv = DIV_ROUND_UP(parent_rate, rate);
do we want to sanity check the lv value here?
> + lcr = readl(i2c->base + SPACEMIT_ILCR);
> + if (i2c->mode == SPACEMIT_MODE_STANDARD) {
> + lcr &= ~SPACEMIT_LCR_LV_STANDARD_MASK;
> + lcr |= lv << SPACEMIT_LCR_LV_STANDARD_SHIFT;
> + } else if (i2c->mode == SPACEMIT_MODE_FAST) {
> + lcr &= ~SPACEMIT_LCR_LV_FAST_MASK;
> + lcr |= lv << SPACEMIT_LCR_LV_FAST_SHIFT;
> + }
> + writel(lcr, i2c->base + SPACEMIT_ILCR);
> +
> + return 0;
> +}
> +
> +static long spacemit_i2c_clk_round_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *parent_rate)
Alignment.
> +{
> + u32 lv, freq;
> +
> + lv = DIV_ROUND_UP(*parent_rate, rate);
> + freq = DIV_ROUND_UP(*parent_rate, lv);
> +
> + return freq;
> +}
> +
> +static unsigned long spacemit_i2c_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
alignment.
> +{
...
> @@ -519,15 +636,13 @@ static int spacemit_i2c_probe(struct platform_device *pdev)
> dev_warn(dev, "failed to read clock-frequency property: %d\n", ret);
>
> /* For now, this driver doesn't support high-speed. */
> - if (!i2c->clock_freq || i2c->clock_freq > SPACEMIT_I2C_MAX_FAST_MODE_FREQ) {
> - dev_warn(dev, "unsupported clock frequency %u; using %u\n",
> - i2c->clock_freq, SPACEMIT_I2C_MAX_FAST_MODE_FREQ);
> - i2c->clock_freq = SPACEMIT_I2C_MAX_FAST_MODE_FREQ;
> - } else if (i2c->clock_freq < SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ) {
> - dev_warn(dev, "unsupported clock frequency %u; using %u\n",
> - i2c->clock_freq, SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ);
> - i2c->clock_freq = SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ;
> - }
> + if (i2c->clock_freq > SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ &&
> + i2c->clock_freq <= SPACEMIT_I2C_MAX_FAST_MODE_FREQ)
> + i2c->mode = SPACEMIT_MODE_FAST;
> + else if (i2c->clock_freq && i2c->clock_freq <= SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ)
> + i2c->mode = SPACEMIT_MODE_STANDARD;
> + else
> + return -EINVAL;
Should we print an error here? And how likely is this case to
happen? Perhaps we can force the mode even if the frequency is
off and move forward instead of forcing the failure.
Andi
>
> i2c->dev = &pdev->dev;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency
2025-07-10 5:50 [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency Troy Mitchell
2025-07-11 9:20 ` Andi Shyti
@ 2025-07-11 10:10 ` kernel test robot
1 sibling, 0 replies; 4+ messages in thread
From: kernel test robot @ 2025-07-11 10:10 UTC (permalink / raw)
To: Troy Mitchell, Andi Shyti, Yixun Lan
Cc: oe-kbuild-all, linux-i2c, linux-kernel, linux-riscv, spacemit,
Troy Mitchell
Hi Troy,
kernel test robot noticed the following build errors:
[auto build test ERROR on 733923397fd95405a48f165c9b1fbc8c4b0a4681]
url: https://github.com/intel-lab-lkp/linux/commits/Troy-Mitchell/i2c-spacemit-configure-ILCR-for-accurate-SCL-frequency/20250710-135339
base: 733923397fd95405a48f165c9b1fbc8c4b0a4681
patch link: https://lore.kernel.org/r/20250710-k1-i2c-ilcr-v1-1-188d1f460c7d%40linux.spacemit.com
patch subject: [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency
config: mips-randconfig-r052-20250711 (https://download.01.org/0day-ci/archive/20250711/202507111742.e8PMpk5t-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 13.4.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250711/202507111742.e8PMpk5t-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/202507111742.e8PMpk5t-lkp@intel.com/
All errors (new ones prefixed by >>):
mips-linux-ld: drivers/i2c/busses/i2c-k1.o: in function `spacemit_i2c_probe':
>> drivers/i2c/busses/i2c-k1.c:(.text.spacemit_i2c_probe+0x22c): undefined reference to `devm_clk_register'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency
2025-07-11 9:20 ` Andi Shyti
@ 2025-07-14 1:11 ` Troy Mitchell
0 siblings, 0 replies; 4+ messages in thread
From: Troy Mitchell @ 2025-07-14 1:11 UTC (permalink / raw)
To: Andi Shyti, Troy Mitchell
Cc: Yixun Lan, linux-i2c, linux-kernel, linux-riscv, spacemit
Hi Andi, Thanks for your review!
On Fri, Jul 11, 2025 at 11:20:48AM +0200, Andi Shyti wrote:
> Hi Troy,
>
> > - #include <linux/clk.h>
> > - #include <linux/i2c.h>
> > - #include <linux/iopoll.h>
> > - #include <linux/module.h>
> > - #include <linux/of_address.h>
> > - #include <linux/platform_device.h>
> > +#include "linux/bits.h"
>
> this should be <linux/bits.h>
>
> > +#include <linux/clk.h>
> > +#include <linux/clkdev.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/i2c.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/platform_device.h>
>
> Is the diff a bit noisy or am I failing to see some differences?
I removed whitespaces
>
> > /* spacemit i2c registers */
> > #define SPACEMIT_ICR 0x0 /* Control register */
> > #define SPACEMIT_ISR 0x4 /* Status register */
> > #define SPACEMIT_IDBR 0xc /* Data buffer register */
> > +#define SPACEMIT_ILCR 0x10 /* Load Count Register */
> > #define SPACEMIT_IBMR 0x1c /* Bus monitor register */
>
> ...
>
> > +static int spacemit_i2c_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> > + unsigned long parent_rate)
>
> here the alignment is a bit off.
>
> > +{
> > + struct spacemit_i2c_dev *i2c = container_of(hw, struct spacemit_i2c_dev, scl_clk_hw);
> > + u32 lv, lcr;
> > +
> > + lv = DIV_ROUND_UP(parent_rate, rate);
>
> do we want to sanity check the lv value here?
Yes, I'll check it in the next version.
>
> > + lcr = readl(i2c->base + SPACEMIT_ILCR);
> > + if (i2c->mode == SPACEMIT_MODE_STANDARD) {
> > + lcr &= ~SPACEMIT_LCR_LV_STANDARD_MASK;
> > + lcr |= lv << SPACEMIT_LCR_LV_STANDARD_SHIFT;
> > + } else if (i2c->mode == SPACEMIT_MODE_FAST) {
> > + lcr &= ~SPACEMIT_LCR_LV_FAST_MASK;
> > + lcr |= lv << SPACEMIT_LCR_LV_FAST_SHIFT;
> > + }
> > + writel(lcr, i2c->base + SPACEMIT_ILCR);
> > +
> > + return 0;
> > +}
> > +
> > +static long spacemit_i2c_clk_round_rate(struct clk_hw *hw, unsigned long rate,
> > + unsigned long *parent_rate)
>
> Alignment.
>
> > +{
> > + u32 lv, freq;
> > +
> > + lv = DIV_ROUND_UP(*parent_rate, rate);
> > + freq = DIV_ROUND_UP(*parent_rate, lv);
> > +
> > + return freq;
> > +}
> > +
> > +static unsigned long spacemit_i2c_clk_recalc_rate(struct clk_hw *hw,
> > + unsigned long parent_rate)
>
> alignment.
>
> > +{
>
> ...
>
> > @@ -519,15 +636,13 @@ static int spacemit_i2c_probe(struct platform_device *pdev)
> > dev_warn(dev, "failed to read clock-frequency property: %d\n", ret);
> >
> > /* For now, this driver doesn't support high-speed. */
> > - if (!i2c->clock_freq || i2c->clock_freq > SPACEMIT_I2C_MAX_FAST_MODE_FREQ) {
> > - dev_warn(dev, "unsupported clock frequency %u; using %u\n",
> > - i2c->clock_freq, SPACEMIT_I2C_MAX_FAST_MODE_FREQ);
> > - i2c->clock_freq = SPACEMIT_I2C_MAX_FAST_MODE_FREQ;
> > - } else if (i2c->clock_freq < SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ) {
> > - dev_warn(dev, "unsupported clock frequency %u; using %u\n",
> > - i2c->clock_freq, SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ);
> > - i2c->clock_freq = SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ;
> > - }
> > + if (i2c->clock_freq > SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ &&
> > + i2c->clock_freq <= SPACEMIT_I2C_MAX_FAST_MODE_FREQ)
> > + i2c->mode = SPACEMIT_MODE_FAST;
> > + else if (i2c->clock_freq && i2c->clock_freq <= SPACEMIT_I2C_MAX_STANDARD_MODE_FREQ)
> > + i2c->mode = SPACEMIT_MODE_STANDARD;
> > + else
> > + return -EINVAL;
>
> Should we print an error here? And how likely is this case to
> happen? Perhaps we can force the mode even if the frequency is
> off and move forward instead of forcing the failure.
Yes we can force the mode to fast.
- Troy
>
> Andi
>
> >
> > i2c->dev = &pdev->dev;
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-07-14 1:12 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-10 5:50 [PATCH] i2c: spacemit: configure ILCR for accurate SCL frequency Troy Mitchell
2025-07-11 9:20 ` Andi Shyti
2025-07-14 1:11 ` Troy Mitchell
2025-07-11 10:10 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).