Commit da690031 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 64b7f674 f5b3f433
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
*/ */
#include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -33,12 +34,17 @@ ...@@ -33,12 +34,17 @@
#define REG_CTRL_ACK_IGNORE BIT(1) #define REG_CTRL_ACK_IGNORE BIT(1)
#define REG_CTRL_STATUS BIT(2) #define REG_CTRL_STATUS BIT(2)
#define REG_CTRL_ERROR BIT(3) #define REG_CTRL_ERROR BIT(3)
#define REG_CTRL_CLKDIV_SHIFT 12 #define REG_CTRL_CLKDIV GENMASK(21, 12)
#define REG_CTRL_CLKDIV_MASK GENMASK(21, 12) #define REG_CTRL_CLKDIVEXT GENMASK(29, 28)
#define REG_CTRL_CLKDIVEXT_SHIFT 28
#define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28) #define REG_SLV_ADDR GENMASK(7, 0)
#define REG_SLV_SDA_FILTER GENMASK(10, 8)
#define REG_SLV_SCL_FILTER GENMASK(13, 11)
#define REG_SLV_SCL_LOW GENMASK(27, 16)
#define REG_SLV_SCL_LOW_EN BIT(28)
#define I2C_TIMEOUT_MS 500 #define I2C_TIMEOUT_MS 500
#define FILTER_DELAY 15
enum { enum {
TOKEN_END = 0, TOKEN_END = 0,
...@@ -133,19 +139,24 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq) ...@@ -133,19 +139,24 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
unsigned long clk_rate = clk_get_rate(i2c->clk); unsigned long clk_rate = clk_get_rate(i2c->clk);
unsigned int div; unsigned int div;
div = DIV_ROUND_UP(clk_rate, freq * i2c->data->div_factor); div = DIV_ROUND_UP(clk_rate, freq);
div -= FILTER_DELAY;
div = DIV_ROUND_UP(div, i2c->data->div_factor);
/* clock divider has 12 bits */ /* clock divider has 12 bits */
if (div >= (1 << 12)) { if (div > GENMASK(11, 0)) {
dev_err(i2c->dev, "requested bus frequency too low\n"); dev_err(i2c->dev, "requested bus frequency too low\n");
div = (1 << 12) - 1; div = GENMASK(11, 0);
} }
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK, meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV,
(div & GENMASK(9, 0)) << REG_CTRL_CLKDIV_SHIFT); FIELD_PREP(REG_CTRL_CLKDIV, div & GENMASK(9, 0)));
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT,
FIELD_PREP(REG_CTRL_CLKDIVEXT, div >> 10));
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK, /* Disable HIGH/LOW mode */
(div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT); meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0);
dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__, dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
clk_rate, freq, div); clk_rate, freq, div);
...@@ -280,7 +291,10 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg) ...@@ -280,7 +291,10 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg)
token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ : token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ :
TOKEN_SLAVE_ADDR_WRITE; TOKEN_SLAVE_ADDR_WRITE;
writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR);
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_ADDR,
FIELD_PREP(REG_SLV_ADDR, msg->addr << 1));
meson_i2c_add_token(i2c, TOKEN_START); meson_i2c_add_token(i2c, TOKEN_START);
meson_i2c_add_token(i2c, token); meson_i2c_add_token(i2c, token);
} }
...@@ -357,16 +371,12 @@ static int meson_i2c_xfer_messages(struct i2c_adapter *adap, ...@@ -357,16 +371,12 @@ static int meson_i2c_xfer_messages(struct i2c_adapter *adap,
struct meson_i2c *i2c = adap->algo_data; struct meson_i2c *i2c = adap->algo_data;
int i, ret = 0; int i, ret = 0;
clk_enable(i2c->clk);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1, atomic); ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1, atomic);
if (ret) if (ret)
break; break;
} }
clk_disable(i2c->clk);
return ret ?: i; return ret ?: i;
} }
...@@ -435,7 +445,7 @@ static int meson_i2c_probe(struct platform_device *pdev) ...@@ -435,7 +445,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = clk_prepare(i2c->clk); ret = clk_prepare_enable(i2c->clk);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "can't prepare clock\n"); dev_err(&pdev->dev, "can't prepare clock\n");
return ret; return ret;
...@@ -457,10 +467,14 @@ static int meson_i2c_probe(struct platform_device *pdev) ...@@ -457,10 +467,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&i2c->adap); ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) { if (ret < 0) {
clk_unprepare(i2c->clk); clk_disable_unprepare(i2c->clk);
return ret; return ret;
} }
/* Disable filtering */
meson_i2c_set_mask(i2c, REG_SLAVE_ADDR,
REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER, 0);
meson_i2c_set_clk_div(i2c, timings.bus_freq_hz); meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
return 0; return 0;
...@@ -471,7 +485,7 @@ static int meson_i2c_remove(struct platform_device *pdev) ...@@ -471,7 +485,7 @@ static int meson_i2c_remove(struct platform_device *pdev)
struct meson_i2c *i2c = platform_get_drvdata(pdev); struct meson_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap); i2c_del_adapter(&i2c->adap);
clk_unprepare(i2c->clk); clk_disable_unprepare(i2c->clk);
return 0; return 0;
} }
......
...@@ -176,6 +176,9 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) ...@@ -176,6 +176,9 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT); fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT);
if (fifostat & OWL_I2C_FIFOSTAT_RNB) { if (fifostat & OWL_I2C_FIFOSTAT_RNB) {
i2c_dev->err = -ENXIO; i2c_dev->err = -ENXIO;
/* Clear NACK error bit by writing "1" */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
OWL_I2C_FIFOSTAT_RNB, true);
goto stop; goto stop;
} }
...@@ -183,6 +186,9 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) ...@@ -183,6 +186,9 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
stat = readl(i2c_dev->base + OWL_I2C_REG_STAT); stat = readl(i2c_dev->base + OWL_I2C_REG_STAT);
if (stat & OWL_I2C_STAT_BEB) { if (stat & OWL_I2C_STAT_BEB) {
i2c_dev->err = -EIO; i2c_dev->err = -EIO;
/* Clear BUS error bit by writing "1" */
owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
OWL_I2C_STAT_BEB, true);
goto stop; goto stop;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment