[PATCH v4 26/40] i2c: fsi: Calculate clock divider from local bus frequency
Eddie James
eajames at linux.ibm.com
Thu Jun 6 07:22:58 AEST 2024
Use the new FSI device local bus clock to calculate the proper
i2c clock divder and look up an optional clock-frequency property
from device tree. Change the default clock divider to 7 now that
the default local bus clock divider has been reduced as well.
Signed-off-by: Eddie James <eajames at linux.ibm.com>
---
Changes since v2:
- Change minimum clock div to 3
- Use DIV_ROUND_UP instead of re-implementing it
- Better logic for checking for clock-frequency property
drivers/i2c/busses/i2c-fsi.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
index 10332693edf0d..2404ace8c56fa 100644
--- a/drivers/i2c/busses/i2c-fsi.c
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -27,7 +27,8 @@
#define FSI_ENGID_I2C 0x7
-#define I2C_DEFAULT_CLK_DIV 6
+#define I2C_DEFAULT_CLK_DIV 7
+#define I2C_DEFAULT_CLK_RATE 400000
/* i2c registers */
#define I2C_FSI_FIFO 0x00
@@ -150,6 +151,7 @@ struct fsi_i2c_master {
u8 fifo_size;
struct list_head ports;
struct mutex lock;
+ u32 clock_div;
};
struct fsi_i2c_port {
@@ -194,7 +196,7 @@ static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c)
if (rc)
return rc;
- mode |= FIELD_PREP(I2C_MODE_CLKDIV, I2C_DEFAULT_CLK_DIV);
+ mode |= FIELD_PREP(I2C_MODE_CLKDIV, i2c->clock_div);
rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
if (rc)
return rc;
@@ -680,6 +682,7 @@ static int fsi_i2c_probe(struct device *dev)
struct fsi_i2c_port *port;
struct device_node *np;
u32 port_no, ports, stat;
+ u32 lbus;
int rc;
i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
@@ -689,6 +692,19 @@ static int fsi_i2c_probe(struct device *dev)
mutex_init(&i2c->lock);
i2c->fsi = to_fsi_dev(dev);
INIT_LIST_HEAD(&i2c->ports);
+ i2c->clock_div = I2C_DEFAULT_CLK_DIV;
+
+ lbus = fsi_device_local_bus_frequency(i2c->fsi);
+ if (lbus) {
+ u32 clock;
+
+ if (device_property_read_u32(dev, "clock-frequency", &clock) || !clock)
+ clock = I2C_DEFAULT_CLK_RATE;
+
+ i2c->clock_div = DIV_ROUND_UP(DIV_ROUND_UP(lbus, clock), 4) - 1;
+ if (i2c->clock_div <= 2)
+ i2c->clock_div = 3;
+ }
rc = fsi_i2c_dev_init(i2c);
if (rc)
--
2.39.3
More information about the Linux-aspeed
mailing list