Skip to content

Commit 1334d3b

Browse files
nkbelinwsakernel
authored andcommitted
i2c: meson: fixup rate calculation with filter delay
Apparently, 15 cycles of the peripheral clock are used by the controller for sampling and filtering. Because this was not known before, the rate calculation is slightly off. Clean up and fix the calculation taking this filtering delay into account. Fixes: 30021e3 ("i2c: add support for Amlogic Meson I2C controller") Signed-off-by: Nicolas Belin <[email protected]> Signed-off-by: Jerome Brunet <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 79e137b commit 1334d3b

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

drivers/i2c/busses/i2c-meson.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,8 @@
3434
#define REG_CTRL_ACK_IGNORE BIT(1)
3535
#define REG_CTRL_STATUS BIT(2)
3636
#define REG_CTRL_ERROR BIT(3)
37-
#define REG_CTRL_CLKDIV_SHIFT 12
38-
#define REG_CTRL_CLKDIV_MASK GENMASK(21, 12)
39-
#define REG_CTRL_CLKDIVEXT_SHIFT 28
40-
#define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28)
37+
#define REG_CTRL_CLKDIV GENMASK(21, 12)
38+
#define REG_CTRL_CLKDIVEXT GENMASK(29, 28)
4139

4240
#define REG_SLV_ADDR GENMASK(7, 0)
4341
#define REG_SLV_SDA_FILTER GENMASK(10, 8)
@@ -46,6 +44,7 @@
4644
#define REG_SLV_SCL_LOW_EN BIT(28)
4745

4846
#define I2C_TIMEOUT_MS 500
47+
#define FILTER_DELAY 15
4948

5049
enum {
5150
TOKEN_END = 0,
@@ -140,19 +139,21 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
140139
unsigned long clk_rate = clk_get_rate(i2c->clk);
141140
unsigned int div;
142141

143-
div = DIV_ROUND_UP(clk_rate, freq * i2c->data->div_factor);
142+
div = DIV_ROUND_UP(clk_rate, freq);
143+
div -= FILTER_DELAY;
144+
div = DIV_ROUND_UP(div, i2c->data->div_factor);
144145

145146
/* clock divider has 12 bits */
146-
if (div >= (1 << 12)) {
147+
if (div > GENMASK(11, 0)) {
147148
dev_err(i2c->dev, "requested bus frequency too low\n");
148-
div = (1 << 12) - 1;
149+
div = GENMASK(11, 0);
149150
}
150151

151-
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
152-
(div & GENMASK(9, 0)) << REG_CTRL_CLKDIV_SHIFT);
152+
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV,
153+
FIELD_PREP(REG_CTRL_CLKDIV, div & GENMASK(9, 0)));
153154

154-
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK,
155-
(div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
155+
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT,
156+
FIELD_PREP(REG_CTRL_CLKDIVEXT, div >> 10));
156157

157158
/* Disable HIGH/LOW mode */
158159
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0);

0 commit comments

Comments
 (0)