[PATCH v1 0/7] i2c: stm32f7: driver update

This series is adding/updating several driver's feature: - each I2C instance has its own private data - add DT i2c-analog-filter property support - implement digital filter setting - add DT i2c-digital-filter-width-ns and i2c-digital-filter properties support - i2cclk is computed only one time
Patrice Chotard (2): arm: dts: stm32: Add i2c-analog-filter property in I2C nodes for stm32f746 arm: dts: stm32: Add i2c-analog-filter property in I2C nodes for stm32h743
Patrick Delaunay (5): i2c: stm32f7: move driver data of each instance in a privdata i2c: stm32f7: support DT binding i2c-analog-filter i2c: stm32f7: fix configuration of the digital filter i2c: stm32f7: add support for DNF i2c-digital-filter binding i2c: stm32f7: compute i2cclk only one time
arch/arm/dts/stm32f746.dtsi | 4 ++ arch/arm/dts/stm32h743.dtsi | 4 ++ drivers/i2c/stm32f7_i2c.c | 91 +++++++++++++++++++++---------------- 3 files changed, 59 insertions(+), 40 deletions(-)

From: Patrick Delaunay patrick.delaunay@foss.st.com
Today all the I2C instance point on the same global variable stm32_i2c_setup according the compatible: i2c_priv->setup = pointer to the same driver data.
This patch changes this driver data (stm32f7_setup and stm32mp15_setup) to a const struct and move the timing struct 'setup' as element of i2c privdata, initialized in stm32_ofdata_to_platdata() with the driver configuration data.
This patch solves issues when several I2C instance have not the same clock source or not the same configuration: each timing setup is saved is the I2C privdata.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com ---
drivers/i2c/stm32f7_i2c.c | 53 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7b04a09de0..b449084b5f 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -158,7 +158,6 @@ struct stm32_i2c_spec { * @fall_time: Fall time (ns) * @dnf: Digital filter coefficient (0-16) * @analog_filter: Analog filter delay (On/Off) - * @fmp_clr_offset: Fast Mode Plus clear register offset from set register */ struct stm32_i2c_setup { u32 speed_freq; @@ -167,6 +166,13 @@ struct stm32_i2c_setup { u32 fall_time; u8 dnf; bool analog_filter; +}; + +/** + * struct stm32_i2c_data - driver data for I2C configuration by compatible + * @fmp_clr_offset: Fast Mode Plus clear register offset from set register + */ +struct stm32_i2c_data { u32 fmp_clr_offset; };
@@ -201,7 +207,7 @@ struct stm32_i2c_timings { struct stm32_i2c_priv { struct stm32_i2c_regs *regs; struct clk clk; - struct stm32_i2c_setup *setup; + struct stm32_i2c_setup setup; u32 speed; struct regmap *regmap; u32 regmap_sreg; @@ -251,18 +257,11 @@ static const struct stm32_i2c_spec i2c_specs[] = { }, };
-static const struct stm32_i2c_setup stm32f7_setup = { - .rise_time = STM32_I2C_RISE_TIME_DEFAULT, - .fall_time = STM32_I2C_FALL_TIME_DEFAULT, - .dnf = STM32_I2C_DNF_DEFAULT, - .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE, +static const struct stm32_i2c_data stm32f7_data = { + .fmp_clr_offset = 0x00, };
-static const struct stm32_i2c_setup stm32mp15_setup = { - .rise_time = STM32_I2C_RISE_TIME_DEFAULT, - .fall_time = STM32_I2C_FALL_TIME_DEFAULT, - .dnf = STM32_I2C_DNF_DEFAULT, - .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE, +static const struct stm32_i2c_data stm32mp15_data = { .fmp_clr_offset = 0x40, };
@@ -745,7 +744,7 @@ static u32 get_lower_rate(u32 rate) static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, struct stm32_i2c_timings *timing) { - struct stm32_i2c_setup *setup = i2c_priv->setup; + struct stm32_i2c_setup *setup = &i2c_priv->setup; int ret = 0;
setup->speed_freq = i2c_priv->speed; @@ -839,10 +838,11 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) writel(timing, ®s->timingr);
/* Enable I2C */ - if (i2c_priv->setup->analog_filter) + if (i2c_priv->setup.analog_filter) clrbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); + setbits_le32(®s->cr1, STM32_I2C_CR1_PE);
return 0; @@ -903,21 +903,23 @@ clk_free:
static int stm32_of_to_plat(struct udevice *dev) { + const struct stm32_i2c_data *data; struct stm32_i2c_priv *i2c_priv = dev_get_priv(dev); u32 rise_time, fall_time; int ret;
- i2c_priv->setup = (struct stm32_i2c_setup *)dev_get_driver_data(dev); - if (!i2c_priv->setup) + data = (const struct stm32_i2c_data *)dev_get_driver_data(dev); + if (!data) return -EINVAL;
- rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns", 0); - if (rise_time) - i2c_priv->setup->rise_time = rise_time; + rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns", + STM32_I2C_RISE_TIME_DEFAULT); + + fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", + STM32_I2C_FALL_TIME_DEFAULT);
- fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", 0); - if (fall_time) - i2c_priv->setup->fall_time = fall_time; + i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT; + i2c_priv->setup.analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE;
/* Optional */ i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev, @@ -930,8 +932,7 @@ static int stm32_of_to_plat(struct udevice *dev) return ret;
i2c_priv->regmap_sreg = fmp[1]; - i2c_priv->regmap_creg = fmp[1] + - i2c_priv->setup->fmp_clr_offset; + i2c_priv->regmap_creg = fmp[1] + data->fmp_clr_offset; i2c_priv->regmap_mask = fmp[2]; }
@@ -944,8 +945,8 @@ static const struct dm_i2c_ops stm32_i2c_ops = { };
static const struct udevice_id stm32_i2c_of_match[] = { - { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_setup }, - { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_setup }, + { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_data }, + { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_data }, {} };

HI Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Today all the I2C instance point on the same global variable stm32_i2c_setup according the compatible: i2c_priv->setup = pointer to the same driver data.
This patch changes this driver data (stm32f7_setup and stm32mp15_setup) to a const struct and move the timing struct 'setup' as element of i2c privdata, initialized in stm32_ofdata_to_platdata() with the driver configuration data.
This patch solves issues when several I2C instance have not the same clock source or not the same configuration: each timing setup is saved is the I2C privdata.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 53 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7b04a09de0..b449084b5f 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -158,7 +158,6 @@ struct stm32_i2c_spec {
- @fall_time: Fall time (ns)
- @dnf: Digital filter coefficient (0-16)
- @analog_filter: Analog filter delay (On/Off)
*/
- @fmp_clr_offset: Fast Mode Plus clear register offset from set register
struct stm32_i2c_setup { u32 speed_freq; @@ -167,6 +166,13 @@ struct stm32_i2c_setup { u32 fall_time; u8 dnf; bool analog_filter; +};
+/**
- struct stm32_i2c_data - driver data for I2C configuration by compatible
- @fmp_clr_offset: Fast Mode Plus clear register offset from set register
- */
+struct stm32_i2c_data { u32 fmp_clr_offset; };
@@ -201,7 +207,7 @@ struct stm32_i2c_timings { struct stm32_i2c_priv { struct stm32_i2c_regs *regs; struct clk clk;
- struct stm32_i2c_setup *setup;
- struct stm32_i2c_setup setup; u32 speed; struct regmap *regmap; u32 regmap_sreg;
@@ -251,18 +257,11 @@ static const struct stm32_i2c_spec i2c_specs[] = { }, };
-static const struct stm32_i2c_setup stm32f7_setup = {
- .rise_time = STM32_I2C_RISE_TIME_DEFAULT,
- .fall_time = STM32_I2C_FALL_TIME_DEFAULT,
- .dnf = STM32_I2C_DNF_DEFAULT,
- .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE,
+static const struct stm32_i2c_data stm32f7_data = {
- .fmp_clr_offset = 0x00,
};
-static const struct stm32_i2c_setup stm32mp15_setup = {
- .rise_time = STM32_I2C_RISE_TIME_DEFAULT,
- .fall_time = STM32_I2C_FALL_TIME_DEFAULT,
- .dnf = STM32_I2C_DNF_DEFAULT,
- .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE,
+static const struct stm32_i2c_data stm32mp15_data = { .fmp_clr_offset = 0x40, };
@@ -745,7 +744,7 @@ static u32 get_lower_rate(u32 rate) static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, struct stm32_i2c_timings *timing) {
- struct stm32_i2c_setup *setup = i2c_priv->setup;
struct stm32_i2c_setup *setup = &i2c_priv->setup; int ret = 0;
setup->speed_freq = i2c_priv->speed;
@@ -839,10 +838,11 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) writel(timing, ®s->timingr);
/* Enable I2C */
- if (i2c_priv->setup->analog_filter)
if (i2c_priv->setup.analog_filter) clrbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF);
setbits_le32(®s->cr1, STM32_I2C_CR1_PE);
return 0;
@@ -903,21 +903,23 @@ clk_free:
static int stm32_of_to_plat(struct udevice *dev) {
- const struct stm32_i2c_data *data; struct stm32_i2c_priv *i2c_priv = dev_get_priv(dev); u32 rise_time, fall_time; int ret;
- i2c_priv->setup = (struct stm32_i2c_setup *)dev_get_driver_data(dev);
- if (!i2c_priv->setup)
- data = (const struct stm32_i2c_data *)dev_get_driver_data(dev);
- if (!data) return -EINVAL;
- rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns", 0);
- if (rise_time)
i2c_priv->setup->rise_time = rise_time;
- rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns",
STM32_I2C_RISE_TIME_DEFAULT);
- fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns",
STM32_I2C_FALL_TIME_DEFAULT);
- fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", 0);
- if (fall_time)
i2c_priv->setup->fall_time = fall_time;
i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT;
i2c_priv->setup.analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE;
/* Optional */ i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev,
@@ -930,8 +932,7 @@ static int stm32_of_to_plat(struct udevice *dev) return ret;
i2c_priv->regmap_sreg = fmp[1];
i2c_priv->regmap_creg = fmp[1] +
i2c_priv->setup->fmp_clr_offset;
i2c_priv->regmap_mask = fmp[2]; }i2c_priv->regmap_creg = fmp[1] + data->fmp_clr_offset;
@@ -944,8 +945,8 @@ static const struct dm_i2c_ops stm32_i2c_ops = { };
static const struct udevice_id stm32_i2c_of_match[] = {
- { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_setup },
- { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_setup },
- { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_data },
- { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_data }, {}
};
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Hi Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Today all the I2C instance point on the same global variable stm32_i2c_setup according the compatible: i2c_priv->setup = pointer to the same driver data.
This patch changes this driver data (stm32f7_setup and stm32mp15_setup) to a const struct and move the timing struct 'setup' as element of i2c privdata, initialized in stm32_ofdata_to_platdata() with the driver configuration data.
This patch solves issues when several I2C instance have not the same clock source or not the same configuration: each timing setup is saved is the I2C privdata.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 53 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7b04a09de0..b449084b5f 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -158,7 +158,6 @@ struct stm32_i2c_spec {
- @fall_time: Fall time (ns)
- @dnf: Digital filter coefficient (0-16)
- @analog_filter: Analog filter delay (On/Off)
*/
- @fmp_clr_offset: Fast Mode Plus clear register offset from set register
struct stm32_i2c_setup { u32 speed_freq; @@ -167,6 +166,13 @@ struct stm32_i2c_setup { u32 fall_time; u8 dnf; bool analog_filter; +};
+/**
- struct stm32_i2c_data - driver data for I2C configuration by compatible
- @fmp_clr_offset: Fast Mode Plus clear register offset from set register
- */
+struct stm32_i2c_data { u32 fmp_clr_offset; };
@@ -201,7 +207,7 @@ struct stm32_i2c_timings { struct stm32_i2c_priv { struct stm32_i2c_regs *regs; struct clk clk;
- struct stm32_i2c_setup *setup;
- struct stm32_i2c_setup setup; u32 speed; struct regmap *regmap; u32 regmap_sreg;
@@ -251,18 +257,11 @@ static const struct stm32_i2c_spec i2c_specs[] = { }, };
-static const struct stm32_i2c_setup stm32f7_setup = {
- .rise_time = STM32_I2C_RISE_TIME_DEFAULT,
- .fall_time = STM32_I2C_FALL_TIME_DEFAULT,
- .dnf = STM32_I2C_DNF_DEFAULT,
- .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE,
+static const struct stm32_i2c_data stm32f7_data = {
- .fmp_clr_offset = 0x00,
};
-static const struct stm32_i2c_setup stm32mp15_setup = {
- .rise_time = STM32_I2C_RISE_TIME_DEFAULT,
- .fall_time = STM32_I2C_FALL_TIME_DEFAULT,
- .dnf = STM32_I2C_DNF_DEFAULT,
- .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE,
+static const struct stm32_i2c_data stm32mp15_data = { .fmp_clr_offset = 0x40, };
@@ -745,7 +744,7 @@ static u32 get_lower_rate(u32 rate) static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, struct stm32_i2c_timings *timing) {
- struct stm32_i2c_setup *setup = i2c_priv->setup;
struct stm32_i2c_setup *setup = &i2c_priv->setup; int ret = 0;
setup->speed_freq = i2c_priv->speed;
@@ -839,10 +838,11 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) writel(timing, ®s->timingr);
/* Enable I2C */
- if (i2c_priv->setup->analog_filter)
if (i2c_priv->setup.analog_filter) clrbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF);
setbits_le32(®s->cr1, STM32_I2C_CR1_PE);
return 0;
@@ -903,21 +903,23 @@ clk_free:
static int stm32_of_to_plat(struct udevice *dev) {
- const struct stm32_i2c_data *data; struct stm32_i2c_priv *i2c_priv = dev_get_priv(dev); u32 rise_time, fall_time; int ret;
- i2c_priv->setup = (struct stm32_i2c_setup *)dev_get_driver_data(dev);
- if (!i2c_priv->setup)
- data = (const struct stm32_i2c_data *)dev_get_driver_data(dev);
- if (!data) return -EINVAL;
- rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns", 0);
- if (rise_time)
i2c_priv->setup->rise_time = rise_time;
- rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns",
STM32_I2C_RISE_TIME_DEFAULT);
- fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns",
STM32_I2C_FALL_TIME_DEFAULT);
- fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", 0);
- if (fall_time)
i2c_priv->setup->fall_time = fall_time;
i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT;
i2c_priv->setup.analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE;
/* Optional */ i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev,
@@ -930,8 +932,7 @@ static int stm32_of_to_plat(struct udevice *dev) return ret;
i2c_priv->regmap_sreg = fmp[1];
i2c_priv->regmap_creg = fmp[1] +
i2c_priv->setup->fmp_clr_offset;
i2c_priv->regmap_mask = fmp[2]; }i2c_priv->regmap_creg = fmp[1] + data->fmp_clr_offset;
@@ -944,8 +945,8 @@ static const struct dm_i2c_ops stm32_i2c_ops = { };
static const struct udevice_id stm32_i2c_of_match[] = {
- { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_setup },
- { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_setup },
- { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_data },
- { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_data }, {}
};
Applied on u-boot-stm32 for next Thanks Patrice

Add i2c-analog-filter property in I2C nodes to enable analog filter feature.
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com ---
arch/arm/dts/stm32f746.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi index ba9b3cd03c..78facde2b5 100644 --- a/arch/arm/dts/stm32f746.dtsi +++ b/arch/arm/dts/stm32f746.dtsi @@ -313,6 +313,7 @@ clocks = <&rcc 1 CLK_I2C1>; #address-cells = <1>; #size-cells = <0>; + i2c-analog-filter; status = "disabled"; };
@@ -325,6 +326,7 @@ clocks = <&rcc 1 CLK_I2C2>; #address-cells = <1>; #size-cells = <0>; + i2c-analog-filter; status = "disabled"; };
@@ -337,6 +339,7 @@ clocks = <&rcc 1 CLK_I2C3>; #address-cells = <1>; #size-cells = <0>; + i2c-analog-filter; status = "disabled"; };
@@ -349,6 +352,7 @@ clocks = <&rcc 1 CLK_I2C4>; #address-cells = <1>; #size-cells = <0>; + i2c-analog-filter; status = "disabled"; };

Hi Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
Add i2c-analog-filter property in I2C nodes to enable analog filter feature.
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
arch/arm/dts/stm32f746.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi index ba9b3cd03c..78facde2b5 100644 --- a/arch/arm/dts/stm32f746.dtsi +++ b/arch/arm/dts/stm32f746.dtsi @@ -313,6 +313,7 @@ clocks = <&rcc 1 CLK_I2C1>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
@@ -325,6 +326,7 @@ clocks = <&rcc 1 CLK_I2C2>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
@@ -337,6 +339,7 @@ clocks = <&rcc 1 CLK_I2C3>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
@@ -349,6 +352,7 @@ clocks = <&rcc 1 CLK_I2C4>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Hi
On 8/3/21 12:05 PM, Patrice Chotard wrote:
Add i2c-analog-filter property in I2C nodes to enable analog filter feature.
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
arch/arm/dts/stm32f746.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi index ba9b3cd03c..78facde2b5 100644 --- a/arch/arm/dts/stm32f746.dtsi +++ b/arch/arm/dts/stm32f746.dtsi @@ -313,6 +313,7 @@ clocks = <&rcc 1 CLK_I2C1>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
@@ -325,6 +326,7 @@ clocks = <&rcc 1 CLK_I2C2>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
@@ -337,6 +339,7 @@ clocks = <&rcc 1 CLK_I2C3>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
@@ -349,6 +352,7 @@ clocks = <&rcc 1 CLK_I2C4>; #address-cells = <1>; #size-cells = <0>;
};i2c-analog-filter; status = "disabled";
Applied on u-boot-stm32 for next Thanks Patrice

Add i2c-analog-filter property in I2C nodes to enable analog filter feature.
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com ---
arch/arm/dts/stm32h743.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/stm32h743.dtsi b/arch/arm/dts/stm32h743.dtsi index ed6857512f..dbfebf07f2 100644 --- a/arch/arm/dts/stm32h743.dtsi +++ b/arch/arm/dts/stm32h743.dtsi @@ -124,6 +124,7 @@ <32>; resets = <&rcc STM32H7_APB1L_RESET(I2C1)>; clocks = <&rcc I2C1_CK>; + i2c-analog-filter; status = "disabled"; };
@@ -136,6 +137,7 @@ <34>; resets = <&rcc STM32H7_APB1L_RESET(I2C2)>; clocks = <&rcc I2C2_CK>; + i2c-analog-filter; status = "disabled"; };
@@ -148,6 +150,7 @@ <73>; resets = <&rcc STM32H7_APB1L_RESET(I2C3)>; clocks = <&rcc I2C3_CK>; + i2c-analog-filter; status = "disabled"; };
@@ -395,6 +398,7 @@ <96>; resets = <&rcc STM32H7_APB4_RESET(I2C4)>; clocks = <&rcc I2C4_CK>; + i2c-analog-filter; status = "disabled"; };

Hi Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
Add i2c-analog-filter property in I2C nodes to enable analog filter feature.
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
arch/arm/dts/stm32h743.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/stm32h743.dtsi b/arch/arm/dts/stm32h743.dtsi index ed6857512f..dbfebf07f2 100644 --- a/arch/arm/dts/stm32h743.dtsi +++ b/arch/arm/dts/stm32h743.dtsi @@ -124,6 +124,7 @@ <32>; resets = <&rcc STM32H7_APB1L_RESET(I2C1)>; clocks = <&rcc I2C1_CK>;
};i2c-analog-filter; status = "disabled";
@@ -136,6 +137,7 @@ <34>; resets = <&rcc STM32H7_APB1L_RESET(I2C2)>; clocks = <&rcc I2C2_CK>;
};i2c-analog-filter; status = "disabled";
@@ -148,6 +150,7 @@ <73>; resets = <&rcc STM32H7_APB1L_RESET(I2C3)>; clocks = <&rcc I2C3_CK>;
};i2c-analog-filter; status = "disabled";
@@ -395,6 +398,7 @@ <96>; resets = <&rcc STM32H7_APB4_RESET(I2C4)>; clocks = <&rcc I2C4_CK>;
};i2c-analog-filter; status = "disabled";
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Hi
On 8/3/21 12:05 PM, Patrice Chotard wrote:
Add i2c-analog-filter property in I2C nodes to enable analog filter feature.
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
arch/arm/dts/stm32h743.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/stm32h743.dtsi b/arch/arm/dts/stm32h743.dtsi index ed6857512f..dbfebf07f2 100644 --- a/arch/arm/dts/stm32h743.dtsi +++ b/arch/arm/dts/stm32h743.dtsi @@ -124,6 +124,7 @@ <32>; resets = <&rcc STM32H7_APB1L_RESET(I2C1)>; clocks = <&rcc I2C1_CK>;
};i2c-analog-filter; status = "disabled";
@@ -136,6 +137,7 @@ <34>; resets = <&rcc STM32H7_APB1L_RESET(I2C2)>; clocks = <&rcc I2C2_CK>;
};i2c-analog-filter; status = "disabled";
@@ -148,6 +150,7 @@ <73>; resets = <&rcc STM32H7_APB1L_RESET(I2C3)>; clocks = <&rcc I2C3_CK>;
};i2c-analog-filter; status = "disabled";
@@ -395,6 +398,7 @@ <96>; resets = <&rcc STM32H7_APB4_RESET(I2C4)>; clocks = <&rcc I2C4_CK>;
};i2c-analog-filter; status = "disabled";
Applied on u-boot-stm32 for next Thanks Patrice

From: Patrick Delaunay patrick.delaunay@foss.st.com
Replace driver internally coded enabling/disabling of the analog-filter with the DT binding "i2c-analog-filter".
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com ---
drivers/i2c/stm32f7_i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index b449084b5f..e71a0e0aa3 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -108,7 +108,6 @@ struct stm32_i2c_regs { #define STM32_I2C_DNF_DEFAULT 0 #define STM32_I2C_DNF_MAX 16
-#define STM32_I2C_ANALOG_FILTER_ENABLE 1 #define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */
@@ -919,7 +918,7 @@ static int stm32_of_to_plat(struct udevice *dev) STM32_I2C_FALL_TIME_DEFAULT);
i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT; - i2c_priv->setup.analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE; + i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter");
/* Optional */ i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev,

Hi Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Replace driver internally coded enabling/disabling of the analog-filter with the DT binding "i2c-analog-filter".
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index b449084b5f..e71a0e0aa3 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -108,7 +108,6 @@ struct stm32_i2c_regs { #define STM32_I2C_DNF_DEFAULT 0 #define STM32_I2C_DNF_MAX 16
-#define STM32_I2C_ANALOG_FILTER_ENABLE 1 #define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */
@@ -919,7 +918,7 @@ static int stm32_of_to_plat(struct udevice *dev) STM32_I2C_FALL_TIME_DEFAULT);
i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT;
- i2c_priv->setup.analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE;
i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter");
/* Optional */ i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev,
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Hi
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Replace driver internally coded enabling/disabling of the analog-filter with the DT binding "i2c-analog-filter".
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index b449084b5f..e71a0e0aa3 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -108,7 +108,6 @@ struct stm32_i2c_regs { #define STM32_I2C_DNF_DEFAULT 0 #define STM32_I2C_DNF_MAX 16
-#define STM32_I2C_ANALOG_FILTER_ENABLE 1 #define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */
@@ -919,7 +918,7 @@ static int stm32_of_to_plat(struct udevice *dev) STM32_I2C_FALL_TIME_DEFAULT);
i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT;
- i2c_priv->setup.analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE;
i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter");
/* Optional */ i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev,
Applied on u-boot-stm32 for next Thanks Patrice

From: Patrick Delaunay patrick.delaunay@foss.st.com
The digital filter related computation are present in the driver however the programming of the filter within the IP is missing. The maximum value for the DNF is wrong and should be 15 instead of 16.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com ---
drivers/i2c/stm32f7_i2c.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index e71a0e0aa3..7e6c65fadc 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -45,6 +45,8 @@ struct stm32_i2c_regs {
/* STM32 I2C control 1 */ #define STM32_I2C_CR1_ANFOFF BIT(12) +#define STM32_I2C_CR1_DNF_MASK GENMASK(11, 8) +#define STM32_I2C_CR1_DNF(n) (((n) & 0xf) << 8) #define STM32_I2C_CR1_ERRIE BIT(7) #define STM32_I2C_CR1_TCIE BIT(6) #define STM32_I2C_CR1_STOPIE BIT(5) @@ -106,7 +108,7 @@ struct stm32_i2c_regs { #define STM32_I2C_MAX_LEN 0xff
#define STM32_I2C_DNF_DEFAULT 0 -#define STM32_I2C_DNF_MAX 16 +#define STM32_I2C_DNF_MAX 15
#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ @@ -155,7 +157,7 @@ struct stm32_i2c_spec { * @clock_src: I2C clock source frequency (Hz) * @rise_time: Rise time (ns) * @fall_time: Fall time (ns) - * @dnf: Digital filter coefficient (0-16) + * @dnf: value of digital filter to apply * @analog_filter: Analog filter delay (On/Off) */ struct stm32_i2c_setup { @@ -842,6 +844,10 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF);
+ /* Program the Digital Filter */ + clrsetbits_le32(®s->cr1, STM32_I2C_CR1_DNF_MASK, + STM32_I2C_CR1_DNF(i2c_priv->setup.dnf)); + setbits_le32(®s->cr1, STM32_I2C_CR1_PE);
return 0;

HI Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
The digital filter related computation are present in the driver however the programming of the filter within the IP is missing. The maximum value for the DNF is wrong and should be 15 instead of 16.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index e71a0e0aa3..7e6c65fadc 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -45,6 +45,8 @@ struct stm32_i2c_regs {
/* STM32 I2C control 1 */ #define STM32_I2C_CR1_ANFOFF BIT(12) +#define STM32_I2C_CR1_DNF_MASK GENMASK(11, 8) +#define STM32_I2C_CR1_DNF(n) (((n) & 0xf) << 8) #define STM32_I2C_CR1_ERRIE BIT(7) #define STM32_I2C_CR1_TCIE BIT(6) #define STM32_I2C_CR1_STOPIE BIT(5) @@ -106,7 +108,7 @@ struct stm32_i2c_regs { #define STM32_I2C_MAX_LEN 0xff
#define STM32_I2C_DNF_DEFAULT 0 -#define STM32_I2C_DNF_MAX 16 +#define STM32_I2C_DNF_MAX 15
#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ @@ -155,7 +157,7 @@ struct stm32_i2c_spec {
- @clock_src: I2C clock source frequency (Hz)
- @rise_time: Rise time (ns)
- @fall_time: Fall time (ns)
- @dnf: Digital filter coefficient (0-16)
*/
- @dnf: value of digital filter to apply
- @analog_filter: Analog filter delay (On/Off)
struct stm32_i2c_setup { @@ -842,6 +844,10 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF);
/* Program the Digital Filter */
clrsetbits_le32(®s->cr1, STM32_I2C_CR1_DNF_MASK,
STM32_I2C_CR1_DNF(i2c_priv->setup.dnf));
setbits_le32(®s->cr1, STM32_I2C_CR1_PE);
return 0;
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

HI
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
The digital filter related computation are present in the driver however the programming of the filter within the IP is missing. The maximum value for the DNF is wrong and should be 15 instead of 16.
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index e71a0e0aa3..7e6c65fadc 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -45,6 +45,8 @@ struct stm32_i2c_regs {
/* STM32 I2C control 1 */ #define STM32_I2C_CR1_ANFOFF BIT(12) +#define STM32_I2C_CR1_DNF_MASK GENMASK(11, 8) +#define STM32_I2C_CR1_DNF(n) (((n) & 0xf) << 8) #define STM32_I2C_CR1_ERRIE BIT(7) #define STM32_I2C_CR1_TCIE BIT(6) #define STM32_I2C_CR1_STOPIE BIT(5) @@ -106,7 +108,7 @@ struct stm32_i2c_regs { #define STM32_I2C_MAX_LEN 0xff
#define STM32_I2C_DNF_DEFAULT 0 -#define STM32_I2C_DNF_MAX 16 +#define STM32_I2C_DNF_MAX 15
#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ @@ -155,7 +157,7 @@ struct stm32_i2c_spec {
- @clock_src: I2C clock source frequency (Hz)
- @rise_time: Rise time (ns)
- @fall_time: Fall time (ns)
- @dnf: Digital filter coefficient (0-16)
*/
- @dnf: value of digital filter to apply
- @analog_filter: Analog filter delay (On/Off)
struct stm32_i2c_setup { @@ -842,6 +844,10 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF);
/* Program the Digital Filter */
clrsetbits_le32(®s->cr1, STM32_I2C_CR1_DNF_MASK,
STM32_I2C_CR1_DNF(i2c_priv->setup.dnf));
setbits_le32(®s->cr1, STM32_I2C_CR1_PE);
return 0;
Applied on u-boot-stm32 for next Thanks Patrice

From: Patrick Delaunay patrick.delaunay@foss.st.com
Add the support for the i2c-digital-filter binding, allowing to enable the digital filter via the device-tree and indicate its value in the DT
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com ---
drivers/i2c/stm32f7_i2c.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7e6c65fadc..2b2dae67a3 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -107,7 +107,6 @@ struct stm32_i2c_regs {
#define STM32_I2C_MAX_LEN 0xff
-#define STM32_I2C_DNF_DEFAULT 0 #define STM32_I2C_DNF_MAX 15
#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ @@ -204,6 +203,7 @@ struct stm32_i2c_timings { * @regmap_sreg: register address for setting Fast Mode Plus bits * @regmap_creg: register address for clearing Fast Mode Plus bits * @regmap_mask: mask for Fast Mode Plus bits + * @dnf_dt: value of digital filter requested via dt */ struct stm32_i2c_priv { struct stm32_i2c_regs *regs; @@ -214,6 +214,7 @@ struct stm32_i2c_priv { u32 regmap_sreg; u32 regmap_creg; u32 regmap_mask; + u32 dnf_dt; };
static const struct stm32_i2c_spec i2c_specs[] = { @@ -684,6 +685,7 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions; + u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->clock_src); int ret;
specs = get_specs(setup->speed_freq); @@ -701,6 +703,8 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, return -EINVAL; }
+ /* Analog and Digital Filters */ + setup->dnf = DIV_ROUND_CLOSEST(i2c_priv->dnf_dt, i2cclk); if (setup->dnf > STM32_I2C_DNF_MAX) { log_err("DNF out of bound %d/%d\n", setup->dnf, STM32_I2C_DNF_MAX); @@ -923,7 +927,10 @@ static int stm32_of_to_plat(struct udevice *dev) fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", STM32_I2C_FALL_TIME_DEFAULT);
- i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT; + i2c_priv->dnf_dt = dev_read_u32_default(dev, "i2c-digital-filter-width-ns", 0); + if (!dev_read_bool(dev, "i2c-digital-filter")) + i2c_priv->dnf_dt = 0; + i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter");
/* Optional */

HI Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Add the support for the i2c-digital-filter binding, allowing to enable the digital filter via the device-tree and indicate its value in the DT
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7e6c65fadc..2b2dae67a3 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -107,7 +107,6 @@ struct stm32_i2c_regs {
#define STM32_I2C_MAX_LEN 0xff
-#define STM32_I2C_DNF_DEFAULT 0 #define STM32_I2C_DNF_MAX 15
#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ @@ -204,6 +203,7 @@ struct stm32_i2c_timings {
- @regmap_sreg: register address for setting Fast Mode Plus bits
- @regmap_creg: register address for clearing Fast Mode Plus bits
- @regmap_mask: mask for Fast Mode Plus bits
*/
- @dnf_dt: value of digital filter requested via dt
struct stm32_i2c_priv { struct stm32_i2c_regs *regs; @@ -214,6 +214,7 @@ struct stm32_i2c_priv { u32 regmap_sreg; u32 regmap_creg; u32 regmap_mask;
- u32 dnf_dt;
};
static const struct stm32_i2c_spec i2c_specs[] = { @@ -684,6 +685,7 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions;
u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->clock_src); int ret;
specs = get_specs(setup->speed_freq);
@@ -701,6 +703,8 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, return -EINVAL; }
- /* Analog and Digital Filters */
- setup->dnf = DIV_ROUND_CLOSEST(i2c_priv->dnf_dt, i2cclk); if (setup->dnf > STM32_I2C_DNF_MAX) { log_err("DNF out of bound %d/%d\n", setup->dnf, STM32_I2C_DNF_MAX);
@@ -923,7 +927,10 @@ static int stm32_of_to_plat(struct udevice *dev) fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", STM32_I2C_FALL_TIME_DEFAULT);
- i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT;
i2c_priv->dnf_dt = dev_read_u32_default(dev, "i2c-digital-filter-width-ns", 0);
if (!dev_read_bool(dev, "i2c-digital-filter"))
i2c_priv->dnf_dt = 0;
i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter");
/* Optional */
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice

Hi
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Add the support for the i2c-digital-filter binding, allowing to enable the digital filter via the device-tree and indicate its value in the DT
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7e6c65fadc..2b2dae67a3 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -107,7 +107,6 @@ struct stm32_i2c_regs {
#define STM32_I2C_MAX_LEN 0xff
-#define STM32_I2C_DNF_DEFAULT 0 #define STM32_I2C_DNF_MAX 15
#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ @@ -204,6 +203,7 @@ struct stm32_i2c_timings {
- @regmap_sreg: register address for setting Fast Mode Plus bits
- @regmap_creg: register address for clearing Fast Mode Plus bits
- @regmap_mask: mask for Fast Mode Plus bits
*/
- @dnf_dt: value of digital filter requested via dt
struct stm32_i2c_priv { struct stm32_i2c_regs *regs; @@ -214,6 +214,7 @@ struct stm32_i2c_priv { u32 regmap_sreg; u32 regmap_creg; u32 regmap_mask;
- u32 dnf_dt;
};
static const struct stm32_i2c_spec i2c_specs[] = { @@ -684,6 +685,7 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions;
u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->clock_src); int ret;
specs = get_specs(setup->speed_freq);
@@ -701,6 +703,8 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, return -EINVAL; }
- /* Analog and Digital Filters */
- setup->dnf = DIV_ROUND_CLOSEST(i2c_priv->dnf_dt, i2cclk); if (setup->dnf > STM32_I2C_DNF_MAX) { log_err("DNF out of bound %d/%d\n", setup->dnf, STM32_I2C_DNF_MAX);
@@ -923,7 +927,10 @@ static int stm32_of_to_plat(struct udevice *dev) fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", STM32_I2C_FALL_TIME_DEFAULT);
- i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT;
i2c_priv->dnf_dt = dev_read_u32_default(dev, "i2c-digital-filter-width-ns", 0);
if (!dev_read_bool(dev, "i2c-digital-filter"))
i2c_priv->dnf_dt = 0;
i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter");
/* Optional */
Applied on u-boot-stm32 for next Thanks Patrice

HI
On 10/8/21 8:44 AM, Patrice CHOTARD wrote:
Hi
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Add the support for the i2c-digital-filter binding, allowing to enable the digital filter via the device-tree and indicate its value in the DT
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7e6c65fadc..2b2dae67a3 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -107,7 +107,6 @@ struct stm32_i2c_regs {
#define STM32_I2C_MAX_LEN 0xff
-#define STM32_I2C_DNF_DEFAULT 0 #define STM32_I2C_DNF_MAX 15
#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ @@ -204,6 +203,7 @@ struct stm32_i2c_timings {
- @regmap_sreg: register address for setting Fast Mode Plus bits
- @regmap_creg: register address for clearing Fast Mode Plus bits
- @regmap_mask: mask for Fast Mode Plus bits
*/
- @dnf_dt: value of digital filter requested via dt
struct stm32_i2c_priv { struct stm32_i2c_regs *regs; @@ -214,6 +214,7 @@ struct stm32_i2c_priv { u32 regmap_sreg; u32 regmap_creg; u32 regmap_mask;
- u32 dnf_dt;
};
static const struct stm32_i2c_spec i2c_specs[] = { @@ -684,6 +685,7 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions;
u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->clock_src); int ret;
specs = get_specs(setup->speed_freq);
@@ -701,6 +703,8 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, return -EINVAL; }
- /* Analog and Digital Filters */
- setup->dnf = DIV_ROUND_CLOSEST(i2c_priv->dnf_dt, i2cclk); if (setup->dnf > STM32_I2C_DNF_MAX) { log_err("DNF out of bound %d/%d\n", setup->dnf, STM32_I2C_DNF_MAX);
@@ -923,7 +927,10 @@ static int stm32_of_to_plat(struct udevice *dev) fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", STM32_I2C_FALL_TIME_DEFAULT);
- i2c_priv->setup.dnf = STM32_I2C_DNF_DEFAULT;
i2c_priv->dnf_dt = dev_read_u32_default(dev, "i2c-digital-filter-width-ns", 0);
if (!dev_read_bool(dev, "i2c-digital-filter"))
i2c_priv->dnf_dt = 0;
i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter");
/* Optional */
Applied on u-boot-stm32 for next Thanks Patrice
Applied on u-boot-stm32 for next Thanks Patrice

From: Patrick Delaunay patrick.delaunay@foss.st.com
Compute i2cclk only one time in stm32_i2c_compute_timing() and remove setup parameter (accessible in i2c_priv).
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com ---
drivers/i2c/stm32f7_i2c.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 2b2dae67a3..c6ae65badb 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -507,14 +507,13 @@ static int stm32_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, return 0; }
-static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, +static int stm32_i2c_compute_solutions(u32 i2cclk, + struct stm32_i2c_setup *setup, const struct stm32_i2c_spec *specs, struct list_head *solutions) { struct stm32_i2c_timings *v; u32 p_prev = STM32_PRESC_MAX; - u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, - setup->clock_src); u32 af_delay_min, af_delay_max; u16 p, l, a; int sdadel_min, sdadel_max, scldel_min; @@ -582,7 +581,8 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, return ret; }
-static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, +static int stm32_i2c_choose_solution(u32 i2cclk, + struct stm32_i2c_setup *setup, const struct stm32_i2c_spec *specs, struct list_head *solutions, struct stm32_i2c_timings *s) @@ -591,8 +591,6 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, u32 i2cbus = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->speed_freq); u32 clk_error_prev = i2cbus; - u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, - setup->clock_src); u32 clk_min, clk_max; u32 af_delay_min; u32 dnf_delay; @@ -679,9 +677,9 @@ static const struct stm32_i2c_spec *get_specs(u32 rate) }
static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, - struct stm32_i2c_setup *setup, struct stm32_i2c_timings *output) { + struct stm32_i2c_setup *setup = &i2c_priv->setup; const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions; @@ -712,11 +710,11 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, }
INIT_LIST_HEAD(&solutions); - ret = stm32_i2c_compute_solutions(setup, specs, &solutions); + ret = stm32_i2c_compute_solutions(i2cclk, setup, specs, &solutions); if (ret) goto exit;
- ret = stm32_i2c_choose_solution(setup, specs, &solutions, output); + ret = stm32_i2c_choose_solution(i2cclk, setup, specs, &solutions, output); if (ret) goto exit;
@@ -761,7 +759,7 @@ static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, }
do { - ret = stm32_i2c_compute_timing(i2c_priv, setup, timing); + ret = stm32_i2c_compute_timing(i2c_priv, timing); if (ret) { log_debug("failed to compute I2C timings.\n"); if (setup->speed_freq > I2C_SPEED_STANDARD_RATE) {

HI Patrick
On 8/3/21 12:05 PM, Patrice Chotard wrote:
From: Patrick Delaunay patrick.delaunay@foss.st.com
Compute i2cclk only one time in stm32_i2c_compute_timing() and remove setup parameter (accessible in i2c_priv).
Signed-off-by: Patrick Delaunay patrick.delaunay@foss.st.com
Signed-off-by: Patrice Chotard patrice.chotard@foss.st.com
drivers/i2c/stm32f7_i2c.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 2b2dae67a3..c6ae65badb 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -507,14 +507,13 @@ static int stm32_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, return 0; }
-static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, +static int stm32_i2c_compute_solutions(u32 i2cclk,
struct stm32_i2c_setup *setup, const struct stm32_i2c_spec *specs, struct list_head *solutions)
{ struct stm32_i2c_timings *v; u32 p_prev = STM32_PRESC_MAX;
- u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC,
u32 af_delay_min, af_delay_max; u16 p, l, a; int sdadel_min, sdadel_max, scldel_min;setup->clock_src);
@@ -582,7 +581,8 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, return ret; }
-static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, +static int stm32_i2c_choose_solution(u32 i2cclk,
struct stm32_i2c_setup *setup, const struct stm32_i2c_spec *specs, struct list_head *solutions, struct stm32_i2c_timings *s)
@@ -591,8 +591,6 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, u32 i2cbus = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->speed_freq); u32 clk_error_prev = i2cbus;
- u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC,
u32 clk_min, clk_max; u32 af_delay_min; u32 dnf_delay;setup->clock_src);
@@ -679,9 +677,9 @@ static const struct stm32_i2c_spec *get_specs(u32 rate) }
static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv,
struct stm32_i2c_setup *setup, struct stm32_i2c_timings *output)
{
- struct stm32_i2c_setup *setup = &i2c_priv->setup; const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions;
@@ -712,11 +710,11 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, }
INIT_LIST_HEAD(&solutions);
- ret = stm32_i2c_compute_solutions(setup, specs, &solutions);
- ret = stm32_i2c_compute_solutions(i2cclk, setup, specs, &solutions); if (ret) goto exit;
- ret = stm32_i2c_choose_solution(setup, specs, &solutions, output);
- ret = stm32_i2c_choose_solution(i2cclk, setup, specs, &solutions, output); if (ret) goto exit;
@@ -761,7 +759,7 @@ static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, }
do {
ret = stm32_i2c_compute_timing(i2c_priv, setup, timing);
if (ret) { log_debug("failed to compute I2C timings.\n"); if (setup->speed_freq > I2C_SPEED_STANDARD_RATE) {ret = stm32_i2c_compute_timing(i2c_priv, timing);
Reviewed-by: Patrice Chotard patrice.chotard@foss.st.com
Thanks Patrice
participants (2)
-
Patrice CHOTARD
-
Patrice Chotard