Skip to content

Commit da69003

Browse files
committed
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: "Some more driver bugfixes for I2C. Including a revert - the updated series for it will come during the next merge window" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: owl: Clear NACK and BUS error bits Revert "i2c: imx: Fix reset of I2SR_IAL flag" i2c: meson: fixup rate calculation with filter delay i2c: meson: keep peripheral clock enabled i2c: meson: fix clock setting overwrite i2c: imx: Fix reset of I2SR_IAL flag
2 parents 64b7f67 + f5b3f43 commit da69003

File tree

2 files changed

+39
-19
lines changed

2 files changed

+39
-19
lines changed

drivers/i2c/busses/i2c-meson.c

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (C) 2014 Beniamino Galvani <[email protected]>
66
*/
77

8+
#include <linux/bitfield.h>
89
#include <linux/clk.h>
910
#include <linux/completion.h>
1011
#include <linux/i2c.h>
@@ -33,12 +34,17 @@
3334
#define REG_CTRL_ACK_IGNORE BIT(1)
3435
#define REG_CTRL_STATUS BIT(2)
3536
#define REG_CTRL_ERROR BIT(3)
36-
#define REG_CTRL_CLKDIV_SHIFT 12
37-
#define REG_CTRL_CLKDIV_MASK GENMASK(21, 12)
38-
#define REG_CTRL_CLKDIVEXT_SHIFT 28
39-
#define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28)
37+
#define REG_CTRL_CLKDIV GENMASK(21, 12)
38+
#define REG_CTRL_CLKDIVEXT GENMASK(29, 28)
39+
40+
#define REG_SLV_ADDR GENMASK(7, 0)
41+
#define REG_SLV_SDA_FILTER GENMASK(10, 8)
42+
#define REG_SLV_SCL_FILTER GENMASK(13, 11)
43+
#define REG_SLV_SCL_LOW GENMASK(27, 16)
44+
#define REG_SLV_SCL_LOW_EN BIT(28)
4045

4146
#define I2C_TIMEOUT_MS 500
47+
#define FILTER_DELAY 15
4248

4349
enum {
4450
TOKEN_END = 0,
@@ -133,19 +139,24 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
133139
unsigned long clk_rate = clk_get_rate(i2c->clk);
134140
unsigned int div;
135141

136-
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);
137145

138146
/* clock divider has 12 bits */
139-
if (div >= (1 << 12)) {
147+
if (div > GENMASK(11, 0)) {
140148
dev_err(i2c->dev, "requested bus frequency too low\n");
141-
div = (1 << 12) - 1;
149+
div = GENMASK(11, 0);
142150
}
143151

144-
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
145-
(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)));
154+
155+
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT,
156+
FIELD_PREP(REG_CTRL_CLKDIVEXT, div >> 10));
146157

147-
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK,
148-
(div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
158+
/* Disable HIGH/LOW mode */
159+
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0);
149160

150161
dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
151162
clk_rate, freq, div);
@@ -280,7 +291,10 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg)
280291
token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ :
281292
TOKEN_SLAVE_ADDR_WRITE;
282293

283-
writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR);
294+
295+
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_ADDR,
296+
FIELD_PREP(REG_SLV_ADDR, msg->addr << 1));
297+
284298
meson_i2c_add_token(i2c, TOKEN_START);
285299
meson_i2c_add_token(i2c, token);
286300
}
@@ -357,16 +371,12 @@ static int meson_i2c_xfer_messages(struct i2c_adapter *adap,
357371
struct meson_i2c *i2c = adap->algo_data;
358372
int i, ret = 0;
359373

360-
clk_enable(i2c->clk);
361-
362374
for (i = 0; i < num; i++) {
363375
ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1, atomic);
364376
if (ret)
365377
break;
366378
}
367379

368-
clk_disable(i2c->clk);
369-
370380
return ret ?: i;
371381
}
372382

@@ -435,7 +445,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
435445
return ret;
436446
}
437447

438-
ret = clk_prepare(i2c->clk);
448+
ret = clk_prepare_enable(i2c->clk);
439449
if (ret < 0) {
440450
dev_err(&pdev->dev, "can't prepare clock\n");
441451
return ret;
@@ -457,10 +467,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
457467

458468
ret = i2c_add_adapter(&i2c->adap);
459469
if (ret < 0) {
460-
clk_unprepare(i2c->clk);
470+
clk_disable_unprepare(i2c->clk);
461471
return ret;
462472
}
463473

474+
/* Disable filtering */
475+
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR,
476+
REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER, 0);
477+
464478
meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
465479

466480
return 0;
@@ -471,7 +485,7 @@ static int meson_i2c_remove(struct platform_device *pdev)
471485
struct meson_i2c *i2c = platform_get_drvdata(pdev);
472486

473487
i2c_del_adapter(&i2c->adap);
474-
clk_unprepare(i2c->clk);
488+
clk_disable_unprepare(i2c->clk);
475489

476490
return 0;
477491
}

drivers/i2c/busses/i2c-owl.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,19 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
176176
fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT);
177177
if (fifostat & OWL_I2C_FIFOSTAT_RNB) {
178178
i2c_dev->err = -ENXIO;
179+
/* Clear NACK error bit by writing "1" */
180+
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
181+
OWL_I2C_FIFOSTAT_RNB, true);
179182
goto stop;
180183
}
181184

182185
/* Handle bus error */
183186
stat = readl(i2c_dev->base + OWL_I2C_REG_STAT);
184187
if (stat & OWL_I2C_STAT_BEB) {
185188
i2c_dev->err = -EIO;
189+
/* Clear BUS error bit by writing "1" */
190+
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
191+
OWL_I2C_STAT_BEB, true);
186192
goto stop;
187193
}
188194

0 commit comments

Comments
 (0)