This serie add support for the analog and digital filter binding
for the stm32f7 i2c driver.
An additional patch add also debug informations, displayed in case
of errors.
Alain Volmat (5):
i2c: stm32f7: fix configuration of the digital filter
i2c: stm32f7: support DT binding i2c-analog-filter
i2c: stm32f7: add support for DNF i2c-digital-filter binding
ARM: dts: stm32: enable the analog filter for all I2C nodes in
stm32mp151
i2c: stm32f7: indicate the address being accessed on errors
arch/arm/boot/dts/stm32mp151.dtsi | 6 +++
drivers/i2c/busses/i2c-stm32f7.c | 63 ++++++++++++++++++++-----------
2 files changed, 46 insertions(+), 23 deletions(-)
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: Alain Volmat <[email protected]>
---
drivers/i2c/busses/i2c-stm32f7.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index 0c539fea2754..f77cd6512a86 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -222,7 +222,6 @@ struct stm32f7_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)
* @fmp_clr_offset: Fast Mode Plus clear register offset from set register
*/
struct stm32f7_i2c_setup {
@@ -230,7 +229,6 @@ struct stm32f7_i2c_setup {
u32 clock_src;
u32 rise_time;
u32 fall_time;
- u8 dnf;
u32 fmp_clr_offset;
};
@@ -310,6 +308,8 @@ struct stm32f7_i2c_msg {
* @smbus_mode: states that the controller is configured in SMBus mode
* @host_notify_client: SMBus host-notify client
* @analog_filter: boolean to indicate enabling of the analog filter
+ * @dnf_dt: value of digital filter requested via dt
+ * @dnf: value of digital filter to apply
*/
struct stm32f7_i2c_dev {
struct i2c_adapter adap;
@@ -339,6 +339,8 @@ struct stm32f7_i2c_dev {
bool smbus_mode;
struct i2c_client *host_notify_client;
bool analog_filter;
+ u32 dnf_dt;
+ u32 dnf;
};
/*
@@ -384,13 +386,11 @@ static struct stm32f7_i2c_spec stm32f7_i2c_specs[] = {
static const struct stm32f7_i2c_setup stm32f7_setup = {
.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
- .dnf = STM32F7_I2C_DNF_DEFAULT,
};
static const struct stm32f7_i2c_setup stm32mp15_setup = {
.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
- .dnf = STM32F7_I2C_DNF_DEFAULT,
.fmp_clr_offset = 0x40,
};
@@ -459,10 +459,11 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
return -EINVAL;
}
- if (setup->dnf > STM32F7_I2C_DNF_MAX) {
+ i2c_dev->dnf = DIV_ROUND_CLOSEST(i2c_dev->dnf_dt, i2cclk);
+ if (i2c_dev->dnf > STM32F7_I2C_DNF_MAX) {
dev_err(i2c_dev->dev,
"DNF out of bound %d/%d\n",
- setup->dnf, STM32F7_I2C_DNF_MAX);
+ i2c_dev->dnf * i2cclk, STM32F7_I2C_DNF_MAX * i2cclk);
return -EINVAL;
}
@@ -473,13 +474,13 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
af_delay_max =
(i2c_dev->analog_filter ?
STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0);
- dnf_delay = setup->dnf * i2cclk;
+ dnf_delay = i2c_dev->dnf * i2cclk;
sdadel_min = specs->hddat_min + setup->fall_time -
- af_delay_min - (setup->dnf + 3) * i2cclk;
+ af_delay_min - (i2c_dev->dnf + 3) * i2cclk;
sdadel_max = specs->vddat_max - setup->rise_time -
- af_delay_max - (setup->dnf + 4) * i2cclk;
+ af_delay_max - (i2c_dev->dnf + 4) * i2cclk;
scldel_min = setup->rise_time + specs->sudat_min;
@@ -645,6 +646,7 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
setup->speed_freq = t->bus_freq_hz;
i2c_dev->setup.rise_time = t->scl_rise_ns;
i2c_dev->setup.fall_time = t->scl_fall_ns;
+ i2c_dev->dnf_dt = t->digital_filter_width_ns;
setup->clock_src = clk_get_rate(i2c_dev->clk);
if (!setup->clock_src) {
@@ -652,6 +654,9 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
return -EINVAL;
}
+ if (!of_property_read_bool(i2c_dev->dev->of_node, "i2c-digital-filter"))
+ i2c_dev->dnf_dt = STM32F7_I2C_DNF_DEFAULT;
+
do {
ret = stm32f7_i2c_compute_timing(i2c_dev, setup,
&i2c_dev->timing);
@@ -681,7 +686,7 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n",
setup->rise_time, setup->fall_time);
dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n",
- (i2c_dev->analog_filter ? "On" : "Off"), setup->dnf);
+ (i2c_dev->analog_filter ? "On" : "Off"), i2c_dev->dnf);
i2c_dev->bus_rate = setup->speed_freq;
@@ -732,7 +737,7 @@ static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)
stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
STM32F7_I2C_CR1_DNF_MASK);
stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
- STM32F7_I2C_CR1_DNF(i2c_dev->setup.dnf));
+ STM32F7_I2C_CR1_DNF(i2c_dev->dnf));
stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
STM32F7_I2C_CR1_PE);
--
2.17.1
Hello all
Looks good to me
Signed-off-by: Pierre-Yves MORDRET <[email protected]>
Regards
On 2/5/21 9:51 AM, Alain Volmat wrote:
> This serie add support for the analog and digital filter binding
> for the stm32f7 i2c driver.
> An additional patch add also debug informations, displayed in case
> of errors.
>
> Alain Volmat (5):
> i2c: stm32f7: fix configuration of the digital filter
> i2c: stm32f7: support DT binding i2c-analog-filter
> i2c: stm32f7: add support for DNF i2c-digital-filter binding
> ARM: dts: stm32: enable the analog filter for all I2C nodes in
> stm32mp151
> i2c: stm32f7: indicate the address being accessed on errors
>
> arch/arm/boot/dts/stm32mp151.dtsi | 6 +++
> drivers/i2c/busses/i2c-stm32f7.c | 63 ++++++++++++++++++++-----------
> 2 files changed, 46 insertions(+), 23 deletions(-)
>
--
--
~ Py MORDRET
--
Hello all
Looks good to me
Signed-off-by: Pierre-Yves MORDRET <[email protected]>
Regards
On 2/5/21 9:51 AM, Alain Volmat wrote:
> 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: Alain Volmat <[email protected]>
> ---
> drivers/i2c/busses/i2c-stm32f7.c | 27 ++++++++++++++++-----------
> 1 file changed, 16 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
> index 0c539fea2754..f77cd6512a86 100644
> --- a/drivers/i2c/busses/i2c-stm32f7.c
> +++ b/drivers/i2c/busses/i2c-stm32f7.c
> @@ -222,7 +222,6 @@ struct stm32f7_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)
> * @fmp_clr_offset: Fast Mode Plus clear register offset from set register
> */
> struct stm32f7_i2c_setup {
> @@ -230,7 +229,6 @@ struct stm32f7_i2c_setup {
> u32 clock_src;
> u32 rise_time;
> u32 fall_time;
> - u8 dnf;
> u32 fmp_clr_offset;
> };
>
> @@ -310,6 +308,8 @@ struct stm32f7_i2c_msg {
> * @smbus_mode: states that the controller is configured in SMBus mode
> * @host_notify_client: SMBus host-notify client
> * @analog_filter: boolean to indicate enabling of the analog filter
> + * @dnf_dt: value of digital filter requested via dt
> + * @dnf: value of digital filter to apply
> */
> struct stm32f7_i2c_dev {
> struct i2c_adapter adap;
> @@ -339,6 +339,8 @@ struct stm32f7_i2c_dev {
> bool smbus_mode;
> struct i2c_client *host_notify_client;
> bool analog_filter;
> + u32 dnf_dt;
> + u32 dnf;
> };
>
> /*
> @@ -384,13 +386,11 @@ static struct stm32f7_i2c_spec stm32f7_i2c_specs[] = {
> static const struct stm32f7_i2c_setup stm32f7_setup = {
> .rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
> .fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
> - .dnf = STM32F7_I2C_DNF_DEFAULT,
> };
>
> static const struct stm32f7_i2c_setup stm32mp15_setup = {
> .rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
> .fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
> - .dnf = STM32F7_I2C_DNF_DEFAULT,
> .fmp_clr_offset = 0x40,
> };
>
> @@ -459,10 +459,11 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
> return -EINVAL;
> }
>
> - if (setup->dnf > STM32F7_I2C_DNF_MAX) {
> + i2c_dev->dnf = DIV_ROUND_CLOSEST(i2c_dev->dnf_dt, i2cclk);
> + if (i2c_dev->dnf > STM32F7_I2C_DNF_MAX) {
> dev_err(i2c_dev->dev,
> "DNF out of bound %d/%d\n",
> - setup->dnf, STM32F7_I2C_DNF_MAX);
> + i2c_dev->dnf * i2cclk, STM32F7_I2C_DNF_MAX * i2cclk);
> return -EINVAL;
> }
>
> @@ -473,13 +474,13 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
> af_delay_max =
> (i2c_dev->analog_filter ?
> STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0);
> - dnf_delay = setup->dnf * i2cclk;
> + dnf_delay = i2c_dev->dnf * i2cclk;
>
> sdadel_min = specs->hddat_min + setup->fall_time -
> - af_delay_min - (setup->dnf + 3) * i2cclk;
> + af_delay_min - (i2c_dev->dnf + 3) * i2cclk;
>
> sdadel_max = specs->vddat_max - setup->rise_time -
> - af_delay_max - (setup->dnf + 4) * i2cclk;
> + af_delay_max - (i2c_dev->dnf + 4) * i2cclk;
>
> scldel_min = setup->rise_time + specs->sudat_min;
>
> @@ -645,6 +646,7 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
> setup->speed_freq = t->bus_freq_hz;
> i2c_dev->setup.rise_time = t->scl_rise_ns;
> i2c_dev->setup.fall_time = t->scl_fall_ns;
> + i2c_dev->dnf_dt = t->digital_filter_width_ns;
> setup->clock_src = clk_get_rate(i2c_dev->clk);
>
> if (!setup->clock_src) {
> @@ -652,6 +654,9 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
> return -EINVAL;
> }
>
> + if (!of_property_read_bool(i2c_dev->dev->of_node, "i2c-digital-filter"))
> + i2c_dev->dnf_dt = STM32F7_I2C_DNF_DEFAULT;
> +
> do {
> ret = stm32f7_i2c_compute_timing(i2c_dev, setup,
> &i2c_dev->timing);
> @@ -681,7 +686,7 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
> dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n",
> setup->rise_time, setup->fall_time);
> dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n",
> - (i2c_dev->analog_filter ? "On" : "Off"), setup->dnf);
> + (i2c_dev->analog_filter ? "On" : "Off"), i2c_dev->dnf);
>
> i2c_dev->bus_rate = setup->speed_freq;
>
> @@ -732,7 +737,7 @@ static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)
> stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
> STM32F7_I2C_CR1_DNF_MASK);
> stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
> - STM32F7_I2C_CR1_DNF(i2c_dev->setup.dnf));
> + STM32F7_I2C_CR1_DNF(i2c_dev->dnf));
>
> stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
> STM32F7_I2C_CR1_PE);
>
--
--
~ Py MORDRET
--
On Fri, Feb 05, 2021 at 09:51:42AM +0100, Alain Volmat wrote:
> 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: Alain Volmat <[email protected]>
Applied to for-next, thanks!