Skip to content

Commit 28683e8

Browse files
jbrun3twsakernel
authored andcommitted
i2c: meson: fix clock setting overwrite
When the slave address is written in do_start(), SLAVE_ADDR is written completely. This may overwrite some setting related to the clock rate or signal filtering. Fix this by writing only the bits related to slave address. To avoid causing unexpected changed, explicitly disable filtering or high/low clock mode which may have been left over by the bootloader. Fixes: 30021e3 ("i2c: add support for Amlogic Meson I2C controller") Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
1 parent fa4d305 commit 28683e8

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

drivers/i2c/busses/i2c-meson.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
66
*/
77

8+
#include <linux/bitfield.h>
89
#include <linux/clk.h>
910
#include <linux/completion.h>
1011
#include <linux/i2c.h>
@@ -38,6 +39,12 @@
3839
#define REG_CTRL_CLKDIVEXT_SHIFT 28
3940
#define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28)
4041

42+
#define REG_SLV_ADDR GENMASK(7, 0)
43+
#define REG_SLV_SDA_FILTER GENMASK(10, 8)
44+
#define REG_SLV_SCL_FILTER GENMASK(13, 11)
45+
#define REG_SLV_SCL_LOW GENMASK(27, 16)
46+
#define REG_SLV_SCL_LOW_EN BIT(28)
47+
4148
#define I2C_TIMEOUT_MS 500
4249

4350
enum {
@@ -147,6 +154,9 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
147154
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK,
148155
(div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
149156

157+
/* Disable HIGH/LOW mode */
158+
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0);
159+
150160
dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
151161
clk_rate, freq, div);
152162
}
@@ -280,7 +290,10 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg)
280290
token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ :
281291
TOKEN_SLAVE_ADDR_WRITE;
282292

283-
writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR);
293+
294+
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_ADDR,
295+
FIELD_PREP(REG_SLV_ADDR, msg->addr << 1));
296+
284297
meson_i2c_add_token(i2c, TOKEN_START);
285298
meson_i2c_add_token(i2c, token);
286299
}
@@ -461,6 +474,10 @@ static int meson_i2c_probe(struct platform_device *pdev)
461474
return ret;
462475
}
463476

477+
/* Disable filtering */
478+
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR,
479+
REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER, 0);
480+
464481
meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
465482

466483
return 0;

0 commit comments

Comments
 (0)