diff mbox series

i2c: stm32f7: SYSCFG Fast Mode Plus support for I2C STM32F7

Message ID 20200706133132.1.Ib000bc59b2ad7201352c5a0a55ec6072221e1808@changeid
State Accepted
Commit 7ce87dcff4e87b2d067f911beee23ad221f3b467
Headers show
Series i2c: stm32f7: SYSCFG Fast Mode Plus support for I2C STM32F7 | expand

Commit Message

Patrick Delaunay July 6, 2020, 11:31 a.m. UTC
Read SYSCFG bindings to set Fast Mode Plus bits if Fast Mode Plus
speed is selected.

Handle the stm32mp15 specific compatible to handle FastMode+
registers handling which is different on the stm32mp15 compared
to the stm32f7 or stm32h7.
Indeed, on the stm32mp15, the FastMode+ set and clear registers
are separated while on the other platforms (F7 or H7) the control
is done in a unique register.

Signed-off-by: Patrick Delaunay <patrick.delaunay at st.com>
---

 drivers/i2c/stm32f7_i2c.c | 74 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 73 insertions(+), 1 deletion(-)

Comments

Heiko Schocher July 7, 2020, 5:20 a.m. UTC | #1
Hello Patrick,

Am 06.07.2020 um 13:31 schrieb Patrick Delaunay:
> Read SYSCFG bindings to set Fast Mode Plus bits if Fast Mode Plus
> speed is selected.
> 
> Handle the stm32mp15 specific compatible to handle FastMode+
> registers handling which is different on the stm32mp15 compared
> to the stm32f7 or stm32h7.
> Indeed, on the stm32mp15, the FastMode+ set and clear registers
> are separated while on the other platforms (F7 or H7) the control
> is done in a unique register.
> 
> Signed-off-by: Patrick Delaunay <patrick.delaunay at st.com>
> ---
> 
>   drivers/i2c/stm32f7_i2c.c | 74 ++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 73 insertions(+), 1 deletion(-)

Just tried to apply your patch on current mainline, but this fails
for me, reason is missing patch:

http://patchwork.ozlabs.org/project/uboot/patch/20200706112653.18951-2-patrick.delaunay at st.com/

So I add this patch also to my repo, if nobody has objections.

Beside of this:

Reviewed-by: Heiko Schocher <hs at denx.de>

Thanks!

bye,
Heiko
Patrick Delaunay July 8, 2020, 5:41 p.m. UTC | #2
Hi Heiko

> From: Heiko Schocher <hs at denx.de>
> Sent: mardi 7 juillet 2020 07:21
> 
> Hello Patrick,
> 
> Am 06.07.2020 um 13:31 schrieb Patrick Delaunay:
> > Read SYSCFG bindings to set Fast Mode Plus bits if Fast Mode Plus
> > speed is selected.
> >
> > Handle the stm32mp15 specific compatible to handle FastMode+ registers
> > handling which is different on the stm32mp15 compared to the stm32f7
> > or stm32h7.
> > Indeed, on the stm32mp15, the FastMode+ set and clear registers are
> > separated while on the other platforms (F7 or H7) the control is done
> > in a unique register.
> >
> > Signed-off-by: Patrick Delaunay <patrick.delaunay at st.com>
> > ---
> >
> >   drivers/i2c/stm32f7_i2c.c | 74
> ++++++++++++++++++++++++++++++++++++++-
> >   1 file changed, 73 insertions(+), 1 deletion(-)
> 
> Just tried to apply your patch on current mainline, but this fails for me, reason is
> missing patch:
> 
> http://patchwork.ozlabs.org/project/uboot/patch/20200706112653.18951-2-
> patrick.delaunay at st.com/
> 
> So I add this patch also to my repo, if nobody has objections.

No objection for me (as u-boot stm32 custodians / shared with Patrice Chotard),
You can take the in tiny patch in your repo.

I delegate the serie to Patrice only to have a review before merge this serie in stm32 tree.
But he is in holiday... and I wait him for my next pull request (including this serie).
 
> Beside of this:
> 
> Reviewed-by: Heiko Schocher <hs at denx.de>

Thanks.
 
> Thanks!
> 
> bye,
> Heiko

Regards,
Patrick

> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs at denx.de
Heiko Schocher July 9, 2020, 8:34 a.m. UTC | #3
Hello Patrick,

Am 06.07.2020 um 13:31 schrieb Patrick Delaunay:
> Read SYSCFG bindings to set Fast Mode Plus bits if Fast Mode Plus
> speed is selected.
> 
> Handle the stm32mp15 specific compatible to handle FastMode+
> registers handling which is different on the stm32mp15 compared
> to the stm32f7 or stm32h7.
> Indeed, on the stm32mp15, the FastMode+ set and clear registers
> are separated while on the other platforms (F7 or H7) the control
> is done in a unique register.
> 
> Signed-off-by: Patrick Delaunay <patrick.delaunay at st.com>
> ---
> 
>   drivers/i2c/stm32f7_i2c.c | 74 ++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 73 insertions(+), 1 deletion(-)

Applied to u-boot-i2c.git master

Thanks!

bye,
Heiko
diff mbox series

Patch

diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
index 593f713d6b..2f60911549 100644
--- a/drivers/i2c/stm32f7_i2c.c
+++ b/drivers/i2c/stm32f7_i2c.c
@@ -8,7 +8,9 @@ 
 #include <dm.h>
 #include <i2c.h>
 #include <log.h>
+#include <regmap.h>
 #include <reset.h>
+#include <syscon.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 
@@ -154,6 +156,7 @@  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;
@@ -162,6 +165,7 @@  struct stm32_i2c_setup {
 	u32 fall_time;
 	u8 dnf;
 	bool analog_filter;
+	u32 fmp_clr_offset;
 };
 
 /**
@@ -181,11 +185,26 @@  struct stm32_i2c_timings {
 	u8 scll;
 };
 
+/**
+ * struct stm32_i2c_priv - private data of the controller
+ * @regs: I2C registers address
+ * @clk: hw i2c clock
+ * @setup: I2C timing setup parameters
+ * @speed: I2C clock frequency of the controller. Standard, Fast or Fast+
+ * @regmap: holds SYSCFG phandle for Fast Mode Plus bit
+ * @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
+ */
 struct stm32_i2c_priv {
 	struct stm32_i2c_regs *regs;
 	struct clk clk;
 	struct stm32_i2c_setup *setup;
 	u32 speed;
+	struct regmap *regmap;
+	u32 regmap_sreg;
+	u32 regmap_creg;
+	u32 regmap_mask;
 };
 
 static const struct stm32_i2c_spec i2c_specs[] = {
@@ -237,6 +256,14 @@  static const struct stm32_i2c_setup stm32f7_setup = {
 	.analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE,
 };
 
+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,
+	.fmp_clr_offset = 0x40,
+};
+
 static int stm32_i2c_check_device_busy(struct stm32_i2c_priv *i2c_priv)
 {
 	struct stm32_i2c_regs *regs = i2c_priv->regs;
@@ -761,6 +788,29 @@  static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv,
 	return 0;
 }
 
+static int stm32_i2c_write_fm_plus_bits(struct stm32_i2c_priv *i2c_priv)
+{
+	int ret;
+	bool enable = i2c_priv->speed > I2C_SPEED_FAST_RATE;
+
+	/* Optional */
+	if (IS_ERR_OR_NULL(i2c_priv->regmap))
+		return 0;
+
+	if (i2c_priv->regmap_sreg == i2c_priv->regmap_creg)
+		ret = regmap_update_bits(i2c_priv->regmap,
+					 i2c_priv->regmap_sreg,
+					 i2c_priv->regmap_mask,
+					 enable ? i2c_priv->regmap_mask : 0);
+	else
+		ret = regmap_write(i2c_priv->regmap,
+				   enable ? i2c_priv->regmap_sreg :
+					    i2c_priv->regmap_creg,
+				   i2c_priv->regmap_mask);
+
+	return ret;
+}
+
 static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv)
 {
 	struct stm32_i2c_regs *regs = i2c_priv->regs;
@@ -775,6 +825,11 @@  static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv)
 	/* Disable I2C */
 	clrbits_le32(&regs->cr1, STM32_I2C_CR1_PE);
 
+	/* Setup Fast mode plus if necessary */
+	ret = stm32_i2c_write_fm_plus_bits(i2c_priv);
+	if (ret)
+		return ret;
+
 	/* Timing settings */
 	timing |= STM32_I2C_TIMINGR_PRESC(t.presc);
 	timing |= STM32_I2C_TIMINGR_SCLDEL(t.scldel);
@@ -850,6 +905,7 @@  static int stm32_ofdata_to_platdata(struct udevice *dev)
 {
 	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)
@@ -863,6 +919,22 @@  static int stm32_ofdata_to_platdata(struct udevice *dev)
 	if (fall_time)
 		i2c_priv->setup->fall_time = fall_time;
 
+	/* Optional */
+	i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev,
+							   "st,syscfg-fmp");
+	if (!IS_ERR(i2c_priv->regmap)) {
+		u32 fmp[3];
+
+		ret = dev_read_u32_array(dev, "st,syscfg-fmp", fmp, 3);
+		if (ret)
+			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];
+	}
+
 	return 0;
 }
 
@@ -873,7 +945,7 @@  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)&stm32f7_setup },
+	{ .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_setup },
 	{}
 };