bcm27xx: update 6.1 patches from RPi foundation
[openwrt/staging/xback.git] / target / linux / bcm27xx / patches-6.1 / 950-1257-i2c-designware-Use-SCL-rise-and-fall-times-in-DT.patch
1 From b660279cc83aff2018cecfc3fb55757a8d64f607 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Tue, 16 Jan 2024 15:54:22 +0000
4 Subject: [PATCH 1257/1295] i2c: designware: Use SCL rise and fall times in DT
5
6 Calculate the HCNT and LCNT values for all modes using the rise and
7 fall times of SCL, the aim being a 50/50 mark/space ratio.
8
9 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
10 ---
11 drivers/i2c/busses/i2c-designware-master.c | 26 ++++++++++++++++++++++
12 1 file changed, 26 insertions(+)
13
14 --- a/drivers/i2c/busses/i2c-designware-master.c
15 +++ b/drivers/i2c/busses/i2c-designware-master.c
16 @@ -16,6 +16,7 @@
17 #include <linux/i2c.h>
18 #include <linux/interrupt.h>
19 #include <linux/io.h>
20 +#include <linux/math64.h>
21 #include <linux/module.h>
22 #include <linux/pm_runtime.h>
23 #include <linux/regmap.h>
24 @@ -37,6 +38,22 @@ static void i2c_dw_configure_fifo_master
25 regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
26 }
27
28 +static u16 clock_calc(struct dw_i2c_dev *dev, bool want_high)
29 +{
30 + struct i2c_timings *t = &dev->timings;
31 + u32 wanted_speed = t->bus_freq_hz;
32 + u32 clk_khz = i2c_dw_clk_rate(dev);
33 + u32 extra_ns = want_high ? t->scl_fall_ns : t->scl_rise_ns;
34 + u32 extra_cycles = (u32)div_u64((u64)clk_khz * extra_ns, 1000000);
35 + u32 period = div_u64((u64)clk_khz * 1000 + wanted_speed - 1, wanted_speed);
36 + u32 cycles = (period + want_high)/2 - extra_cycles;
37 +
38 + if (cycles > 0xffff)
39 + cycles = 0xffff;
40 +
41 + return (u16)cycles;
42 +}
43 +
44 static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
45 {
46 u32 comp_param1;
47 @@ -44,6 +61,7 @@ static int i2c_dw_set_timings_master(str
48 struct i2c_timings *t = &dev->timings;
49 const char *fp_str = "";
50 u32 ic_clk;
51 + u32 hcnt, lcnt;
52 int ret;
53
54 ret = i2c_dw_acquire_lock(dev);
55 @@ -59,6 +77,9 @@ static int i2c_dw_set_timings_master(str
56 sda_falling_time = t->sda_fall_ns ?: 300; /* ns */
57 scl_falling_time = t->scl_fall_ns ?: 300; /* ns */
58
59 + hcnt = clock_calc(dev, true);
60 + lcnt = clock_calc(dev, false);
61 +
62 /* Calculate SCL timing parameters for standard mode if not set */
63 if (!dev->ss_hcnt || !dev->ss_lcnt) {
64 ic_clk = i2c_dw_clk_rate(dev);
65 @@ -74,6 +95,8 @@ static int i2c_dw_set_timings_master(str
66 scl_falling_time,
67 0); /* No offset */
68 }
69 + dev->ss_hcnt = hcnt;
70 + dev->ss_lcnt = lcnt;
71 dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n",
72 dev->ss_hcnt, dev->ss_lcnt);
73
74 @@ -124,6 +147,8 @@ static int i2c_dw_set_timings_master(str
75 scl_falling_time,
76 0); /* No offset */
77 }
78 + dev->fs_hcnt = hcnt;
79 + dev->fs_lcnt = lcnt;
80 dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n",
81 fp_str, dev->fs_hcnt, dev->fs_lcnt);
82
83 @@ -152,6 +177,8 @@ static int i2c_dw_set_timings_master(str
84 scl_falling_time,
85 0); /* No offset */
86 }
87 + dev->hs_hcnt = hcnt;
88 + dev->hs_lcnt = lcnt;
89 dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n",
90 dev->hs_hcnt, dev->hs_lcnt);
91 }