* [PATCH v3 00/10] i2c: meson: series with improvements
@ 2017-03-11 17:48 Heiner Kallweit
2017-03-11 18:22 ` [PATCH v3 01/10] i2c: meson: use min instead of min_t where min_t isn't needed Heiner Kallweit
` (9 more replies)
0 siblings, 10 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 17:48 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
This patch series includes several improvements for the i2c-meson
driver.
Changes in v2:
- removed patches 8 and 12
- removed one small change in patch 6
- don't print error message in patch 7
Changes in v3:
- changed order of patches 3, 4, 5 what makes the patches more simple
- remove one change from patch 7 to still properly deal with timeouts
Heiner Kallweit (12):
i2c: meson: use min instead of min_t where min_t isn't needed
i2c: meson: remove member irq from struct meson_i2c
i2c: meson: set clock divider in probe instead of setting it for each transfer
i2c: meson: use i2c core for DT clock-frequency parsing
i2c: meson: use full 12 bits for clock divider
i2c: meson: remove variable count from meson_i2c_xfer
i2c: meson: improve interrupt handler and detect spurious interrupts
i2c: meson: don't create separate token chain just for the stop command
i2c: meson: remove meson_i2c_write_tokens
i2c: meson: improve and simplify interrupt handler
drivers/i2c/busses/i2c-meson.c | 132 ++++++++++++++++-------------------------
1 file changed, 50 insertions(+), 82 deletions(-)
--
2.12.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 01/10] i2c: meson: use min instead of min_t where min_t isn't needed
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
@ 2017-03-11 18:22 ` Heiner Kallweit
2017-03-11 18:22 ` [PATCH v3 02/10] i2c: meson: remove member irq from struct meson_i2c Heiner Kallweit
` (8 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:22 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
Use min instead of min_t where min_t isn't needed.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- no changes
v3:
- no changes
---
drivers/i2c/busses/i2c-meson.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 73b97c71..40e5da9a 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -156,10 +156,10 @@ static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len)
dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__,
rdata0, rdata1, len);
- for (i = 0; i < min_t(int, 4, len); i++)
+ for (i = 0; i < min(4, len); i++)
*buf++ = (rdata0 >> i * 8) & 0xff;
- for (i = 4; i < min_t(int, 8, len); i++)
+ for (i = 4; i < min(8, len); i++)
*buf++ = (rdata1 >> (i - 4) * 8) & 0xff;
}
@@ -168,10 +168,10 @@ static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len)
u32 wdata0 = 0, wdata1 = 0;
int i;
- for (i = 0; i < min_t(int, 4, len); i++)
+ for (i = 0; i < min(4, len); i++)
wdata0 |= *buf++ << (i * 8);
- for (i = 4; i < min_t(int, 8, len); i++)
+ for (i = 4; i < min(8, len); i++)
wdata1 |= *buf++ << ((i - 4) * 8);
writel(wdata0, i2c->regs + REG_TOK_WDATA0);
@@ -186,7 +186,7 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
bool write = !(i2c->msg->flags & I2C_M_RD);
int i;
- i2c->count = min_t(int, i2c->msg->len - i2c->pos, 8);
+ i2c->count = min(i2c->msg->len - i2c->pos, 8);
for (i = 0; i < i2c->count - 1; i++)
meson_i2c_add_token(i2c, TOKEN_DATA);
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 02/10] i2c: meson: remove member irq from struct meson_i2c
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
2017-03-11 18:22 ` [PATCH v3 01/10] i2c: meson: use min instead of min_t where min_t isn't needed Heiner Kallweit
@ 2017-03-11 18:22 ` Heiner Kallweit
2017-03-11 18:23 ` [PATCH v3 03/10] i2c: meson: set clock divider in probe instead of setting it for each transfer Heiner Kallweit
` (7 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:22 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
Member irq can be replaced with a local variable in probe
because it's nowhere else accessed.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
---
v2:
- added Reviewed-by
v3:
- no changes
---
drivers/i2c/busses/i2c-meson.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 40e5da9a..50059d09 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -82,7 +82,6 @@ struct meson_i2c {
struct device *dev;
void __iomem *regs;
struct clk *clk;
- int irq;
struct i2c_msg *msg;
int state;
@@ -391,7 +390,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct meson_i2c *i2c;
struct resource *mem;
- int ret = 0;
+ int irq, ret = 0;
i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
if (!i2c)
@@ -418,14 +417,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
if (IS_ERR(i2c->regs))
return PTR_ERR(i2c->regs);
- i2c->irq = platform_get_irq(pdev, 0);
- if (i2c->irq < 0) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
dev_err(&pdev->dev, "can't find IRQ\n");
- return i2c->irq;
+ return irq;
}
- ret = devm_request_irq(&pdev->dev, i2c->irq, meson_i2c_irq,
- 0, dev_name(&pdev->dev), i2c);
+ ret = devm_request_irq(&pdev->dev, irq, meson_i2c_irq, 0,
+ dev_name(&pdev->dev), i2c);
if (ret < 0) {
dev_err(&pdev->dev, "can't request IRQ\n");
return ret;
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 03/10] i2c: meson: set clock divider in probe instead of setting it for each transfer
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
2017-03-11 18:22 ` [PATCH v3 01/10] i2c: meson: use min instead of min_t where min_t isn't needed Heiner Kallweit
2017-03-11 18:22 ` [PATCH v3 02/10] i2c: meson: remove member irq from struct meson_i2c Heiner Kallweit
@ 2017-03-11 18:23 ` Heiner Kallweit
2017-03-11 18:23 ` [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing Heiner Kallweit
` (6 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:23 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
The bus frequency won't change, therefore we can set the clock divider
in probe already and we don't have to set it for each transfer.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- no changes
v3:
- change order of patches
---
drivers/i2c/busses/i2c-meson.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 50059d09..e597764e 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -73,7 +73,6 @@ enum {
* @error: Flag set when an error is received
* @lock: To avoid race conditions between irq handler and xfer code
* @done: Completion used to wait for transfer termination
- * @frequency: Operating frequency of I2C bus clock
* @tokens: Sequence of tokens to be written to the device
* @num_tokens: Number of tokens
*/
@@ -92,7 +91,6 @@ struct meson_i2c {
spinlock_t lock;
struct completion done;
- unsigned int frequency;
u32 tokens[2];
int num_tokens;
};
@@ -131,17 +129,17 @@ static void meson_i2c_write_tokens(struct meson_i2c *i2c)
writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
}
-static void meson_i2c_set_clk_div(struct meson_i2c *i2c)
+static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
{
unsigned long clk_rate = clk_get_rate(i2c->clk);
unsigned int div;
- div = DIV_ROUND_UP(clk_rate, i2c->frequency * 4);
+ div = DIV_ROUND_UP(clk_rate, freq * 4);
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
div << REG_CTRL_CLKDIV_SHIFT);
dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
- clk_rate, i2c->frequency, div);
+ clk_rate, freq, div);
}
static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len)
@@ -361,7 +359,6 @@ static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int i, ret = 0, count = 0;
clk_enable(i2c->clk);
- meson_i2c_set_clk_div(i2c);
for (i = 0; i < num; i++) {
ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1);
@@ -390,15 +387,15 @@ static int meson_i2c_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct meson_i2c *i2c;
struct resource *mem;
+ u32 freq;
int irq, ret = 0;
i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
- if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
- &i2c->frequency))
- i2c->frequency = DEFAULT_FREQ;
+ if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", &freq))
+ freq = DEFAULT_FREQ;
i2c->dev = &pdev->dev;
platform_set_drvdata(pdev, i2c);
@@ -456,6 +453,8 @@ static int meson_i2c_probe(struct platform_device *pdev)
return ret;
}
+ meson_i2c_set_clk_div(i2c, freq);
+
return 0;
}
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
` (2 preceding siblings ...)
2017-03-11 18:23 ` [PATCH v3 03/10] i2c: meson: set clock divider in probe instead of setting it for each transfer Heiner Kallweit
@ 2017-03-11 18:23 ` Heiner Kallweit
2017-03-13 9:01 ` Neil Armstrong
2017-03-11 18:23 ` [PATCH v3 05/10] i2c: meson: use full 12 bits for clock divider Heiner Kallweit
` (5 subsequent siblings)
9 siblings, 1 reply; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:23 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
We don't have to parse the DT manually to retrieve the bus frequency
and we don't have to maintain an own default for the bus frequency.
Let the i2c core do this for us.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
---
v2:
- added Reviewed-by
v3:
- changed order of patches
---
drivers/i2c/busses/i2c-meson.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index e597764e..ac0ac82d 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -38,7 +38,6 @@
#define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
#define I2C_TIMEOUT_MS 500
-#define DEFAULT_FREQ 100000
enum {
TOKEN_END = 0,
@@ -387,15 +386,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct meson_i2c *i2c;
struct resource *mem;
- u32 freq;
+ struct i2c_timings timings;
int irq, ret = 0;
i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
- if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", &freq))
- freq = DEFAULT_FREQ;
+ i2c_parse_fw_timings(&pdev->dev, &timings, true);
i2c->dev = &pdev->dev;
platform_set_drvdata(pdev, i2c);
@@ -453,7 +451,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
return ret;
}
- meson_i2c_set_clk_div(i2c, freq);
+ meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
return 0;
}
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 05/10] i2c: meson: use full 12 bits for clock divider
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
` (3 preceding siblings ...)
2017-03-11 18:23 ` [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing Heiner Kallweit
@ 2017-03-11 18:23 ` Heiner Kallweit
2017-03-11 18:23 ` [PATCH v3 06/10] i2c: meson: remove variable count from meson_i2c_xfer Heiner Kallweit
` (4 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:23 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
The clock divider has 12 bits, splitted into a 10 bit field and a
2 bit field. The extra 2 bits aren't used currently.
Change this to use the full 12 bits and warn if the requested
frequency is too low.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Acked-by: Jerome Brunet <jbrunet@baylibre.com>
---
v2:
- added Acked-by
v3:
- changed order of patches
---
drivers/i2c/busses/i2c-meson.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index ac0ac82d..03f70282 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -35,7 +35,9 @@
#define REG_CTRL_STATUS BIT(2)
#define REG_CTRL_ERROR BIT(3)
#define REG_CTRL_CLKDIV_SHIFT 12
-#define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
+#define REG_CTRL_CLKDIV_MASK GENMASK(21, 12)
+#define REG_CTRL_CLKDIVEXT_SHIFT 28
+#define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28)
#define I2C_TIMEOUT_MS 500
@@ -134,8 +136,15 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
unsigned int div;
div = DIV_ROUND_UP(clk_rate, freq * 4);
+
+ /* clock divider has 12 bits */
+ WARN_ON(div >= (1 << 12));
+
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
- div << REG_CTRL_CLKDIV_SHIFT);
+ (div & GENMASK(9, 0)) << REG_CTRL_CLKDIV_SHIFT);
+
+ meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK,
+ (div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
clk_rate, freq, div);
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 06/10] i2c: meson: remove variable count from meson_i2c_xfer
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
` (4 preceding siblings ...)
2017-03-11 18:23 ` [PATCH v3 05/10] i2c: meson: use full 12 bits for clock divider Heiner Kallweit
@ 2017-03-11 18:23 ` Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 07/10] i2c: meson: improve interrupt handler and detect spurious interrupts Heiner Kallweit
` (3 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:23 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
Variable count has always the same value as i, so we don't need it.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- remove one small change from v1
v3:
- no changes
---
drivers/i2c/busses/i2c-meson.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 03f70282..3fc1a715 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -364,7 +364,7 @@ static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
struct meson_i2c *i2c = adap->algo_data;
- int i, ret = 0, count = 0;
+ int i, ret = 0;
clk_enable(i2c->clk);
@@ -372,12 +372,11 @@ static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1);
if (ret)
break;
- count++;
}
clk_disable(i2c->clk);
- return ret ? ret : count;
+ return ret ?: i;
}
static u32 meson_i2c_func(struct i2c_adapter *adap)
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 07/10] i2c: meson: improve interrupt handler and detect spurious interrupts
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
` (5 preceding siblings ...)
2017-03-11 18:23 ` [PATCH v3 06/10] i2c: meson: remove variable count from meson_i2c_xfer Heiner Kallweit
@ 2017-03-11 18:24 ` Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 08/10] i2c: meson: don't create separate token chain just for the stop command Heiner Kallweit
` (2 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:24 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
If state is STATE_IDLE no interrupt should occur. Return IRQ_NONE
if such a spurious interrupt is detected.
Not having to take care of STATE_IDLE later in the interrupt handler
allows to further simplify the interrupt handler in subsequent
patches of this series.
In addition move resetting REG_CTRL_START bit to the start of the
interrupt handler to ensure that the start bit is always reset.
Currently the start bit is not reset for STATE_STOP because
i2c->state is set to STATE_IDLE.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- don't print an error if spurious interrupt is detected
v3:
- don't remove a start bit reset, we need it to properly handle timeouts
- extend commit message
---
drivers/i2c/busses/i2c-meson.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 3fc1a715..0b09e059 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -228,12 +228,18 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
spin_lock(&i2c->lock);
meson_i2c_reset_tokens(i2c);
+ meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
ctrl = readl(i2c->regs + REG_CTRL);
dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n",
i2c->state, i2c->pos, i2c->count, ctrl);
- if (ctrl & REG_CTRL_ERROR && i2c->state != STATE_IDLE) {
+ if (i2c->state == STATE_IDLE) {
+ spin_unlock(&i2c->lock);
+ return IRQ_NONE;
+ }
+
+ if (ctrl & REG_CTRL_ERROR) {
/*
* The bit is set when the IGNORE_NAK bit is cleared
* and the device didn't respond. In this case, the
@@ -276,15 +282,12 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
i2c->state = STATE_IDLE;
complete(&i2c->done);
break;
- case STATE_IDLE:
- break;
}
out:
if (i2c->state != STATE_IDLE) {
/* Restart the processing */
meson_i2c_write_tokens(i2c);
- meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START,
REG_CTRL_START);
}
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 08/10] i2c: meson: don't create separate token chain just for the stop command
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
` (6 preceding siblings ...)
2017-03-11 18:24 ` [PATCH v3 07/10] i2c: meson: improve interrupt handler and detect spurious interrupts Heiner Kallweit
@ 2017-03-11 18:24 ` Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 09/10] i2c: meson: remove meson_i2c_write_tokens Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 10/10] i2c: meson: improve and simplify interrupt handler Heiner Kallweit
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:24 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
We can directly add the stop token to the token chain including the
last transfer chunk. This is more efficient than creating a separate
token chain just for the stop command.
And it allows us to get rid of state STATE_STOP completely.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- no changes
---
drivers/i2c/busses/i2c-meson.c | 23 +++++------------------
1 file changed, 5 insertions(+), 18 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 0b09e059..6c873ed8 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -55,7 +55,6 @@ enum {
STATE_IDLE,
STATE_READ,
STATE_WRITE,
- STATE_STOP,
};
/**
@@ -205,19 +204,9 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
if (write)
meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count);
-}
-
-static void meson_i2c_stop(struct meson_i2c *i2c)
-{
- dev_dbg(i2c->dev, "%s: last %d\n", __func__, i2c->last);
- if (i2c->last) {
- i2c->state = STATE_STOP;
+ if (i2c->last && i2c->pos + i2c->count >= i2c->msg->len)
meson_i2c_add_token(i2c, TOKEN_STOP);
- } else {
- i2c->state = STATE_IDLE;
- complete(&i2c->done);
- }
}
static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
@@ -262,7 +251,8 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
}
if (i2c->pos >= i2c->msg->len) {
- meson_i2c_stop(i2c);
+ i2c->state = STATE_IDLE;
+ complete(&i2c->done);
break;
}
@@ -272,16 +262,13 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
i2c->pos += i2c->count;
if (i2c->pos >= i2c->msg->len) {
- meson_i2c_stop(i2c);
+ i2c->state = STATE_IDLE;
+ complete(&i2c->done);
break;
}
meson_i2c_prepare_xfer(i2c);
break;
- case STATE_STOP:
- i2c->state = STATE_IDLE;
- complete(&i2c->done);
- break;
}
out:
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 09/10] i2c: meson: remove meson_i2c_write_tokens
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
` (7 preceding siblings ...)
2017-03-11 18:24 ` [PATCH v3 08/10] i2c: meson: don't create separate token chain just for the stop command Heiner Kallweit
@ 2017-03-11 18:24 ` Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 10/10] i2c: meson: improve and simplify interrupt handler Heiner Kallweit
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:24 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
meson_i2c_write_tokens is always called directly after
meson_i2c_prepare_xfer (and only then). So we can simplify the code by
removing meson_i2c_write_tokens and moving the two statements of
meson_i2c_write_tokens to the end of meson_i2c_prepare_xfer.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- no changes
---
drivers/i2c/busses/i2c-meson.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 6c873ed8..23f25efa 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -123,12 +123,6 @@ static void meson_i2c_add_token(struct meson_i2c *i2c, int token)
i2c->num_tokens++;
}
-static void meson_i2c_write_tokens(struct meson_i2c *i2c)
-{
- writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0);
- writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
-}
-
static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
{
unsigned long clk_rate = clk_get_rate(i2c->clk);
@@ -207,6 +201,9 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
if (i2c->last && i2c->pos + i2c->count >= i2c->msg->len)
meson_i2c_add_token(i2c, TOKEN_STOP);
+
+ writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0);
+ writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
}
static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
@@ -272,12 +269,10 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
}
out:
- if (i2c->state != STATE_IDLE) {
+ if (i2c->state != STATE_IDLE)
/* Restart the processing */
- meson_i2c_write_tokens(i2c);
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START,
REG_CTRL_START);
- }
spin_unlock(&i2c->lock);
@@ -318,7 +313,6 @@ static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg,
i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
meson_i2c_prepare_xfer(i2c);
- meson_i2c_write_tokens(i2c);
reinit_completion(&i2c->done);
/* Start the transfer */
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 10/10] i2c: meson: improve and simplify interrupt handler
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
` (8 preceding siblings ...)
2017-03-11 18:24 ` [PATCH v3 09/10] i2c: meson: remove meson_i2c_write_tokens Heiner Kallweit
@ 2017-03-11 18:24 ` Heiner Kallweit
9 siblings, 0 replies; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-11 18:24 UTC (permalink / raw)
To: Wolfram Sang, Jerome Brunet; +Cc: linux-i2c@vger.kernel.org, linux-amlogic
The preceding changes in this patch series now allow to simplify
the interrupt handler significantly.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- rebased
v3:
- no changes
---
drivers/i2c/busses/i2c-meson.c | 40 ++++++++++------------------------------
1 file changed, 10 insertions(+), 30 deletions(-)
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 23f25efa..590715ae 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -239,41 +239,21 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
goto out;
}
- switch (i2c->state) {
- case STATE_READ:
- if (i2c->count > 0) {
- meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos,
- i2c->count);
- i2c->pos += i2c->count;
- }
-
- if (i2c->pos >= i2c->msg->len) {
- i2c->state = STATE_IDLE;
- complete(&i2c->done);
- break;
- }
-
- meson_i2c_prepare_xfer(i2c);
- break;
- case STATE_WRITE:
- i2c->pos += i2c->count;
+ if (i2c->state == STATE_READ && i2c->count)
+ meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos, i2c->count);
- if (i2c->pos >= i2c->msg->len) {
- i2c->state = STATE_IDLE;
- complete(&i2c->done);
- break;
- }
+ i2c->pos += i2c->count;
- meson_i2c_prepare_xfer(i2c);
- break;
+ if (i2c->pos >= i2c->msg->len) {
+ i2c->state = STATE_IDLE;
+ complete(&i2c->done);
+ goto out;
}
+ /* Restart the processing */
+ meson_i2c_prepare_xfer(i2c);
+ meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, REG_CTRL_START);
out:
- if (i2c->state != STATE_IDLE)
- /* Restart the processing */
- meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START,
- REG_CTRL_START);
-
spin_unlock(&i2c->lock);
return IRQ_HANDLED;
--
2.12.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing
2017-03-11 18:23 ` [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing Heiner Kallweit
@ 2017-03-13 9:01 ` Neil Armstrong
2017-03-13 19:03 ` Heiner Kallweit
0 siblings, 1 reply; 14+ messages in thread
From: Neil Armstrong @ 2017-03-13 9:01 UTC (permalink / raw)
To: linux-amlogic, Heiner Kallweit; +Cc: linux-i2c, wsa, Jerome Brunet
On 03/11/2017 07:23 PM, Heiner Kallweit wrote:
> We don't have to parse the DT manually to retrieve the bus frequency
> and we don't have to maintain an own default for the bus frequency.
> Let the i2c core do this for us.
>
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
> Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
> v2:
> - added Reviewed-by
> v3:
> - changed order of patches
> ---
> drivers/i2c/busses/i2c-meson.c | 8 +++-----
> 1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
> index e597764e..ac0ac82d 100644
> --- a/drivers/i2c/busses/i2c-meson.c
> +++ b/drivers/i2c/busses/i2c-meson.c
> @@ -38,7 +38,6 @@
> #define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
>
> #define I2C_TIMEOUT_MS 500
> -#define DEFAULT_FREQ 100000
>
> enum {
> TOKEN_END = 0,
> @@ -387,15 +386,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
> struct device_node *np = pdev->dev.of_node;
> struct meson_i2c *i2c;
> struct resource *mem;
> - u32 freq;
> + struct i2c_timings timings;
> int irq, ret = 0;
>
> i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
> if (!i2c)
> return -ENOMEM;
>
> - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", &freq))
> - freq = DEFAULT_FREQ;
> + i2c_parse_fw_timings(&pdev->dev, &timings, true);
>
> i2c->dev = &pdev->dev;
> platform_set_drvdata(pdev, i2c);
> @@ -453,7 +451,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
> return ret;
> }
>
> - meson_i2c_set_clk_div(i2c, freq);
> + meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
>
> return 0;
> }
>
Hi Heiner,
I'm sorry, but you should *really* update the dt-bindings.
The dt bindings are now strictly related to how the driver is implemented, or which
attributes are used, but how the device tree node should conform to.
In this particular case, in the recent addition of "standard" i2c attributes for
speed and timings, you should refer to this "i2c.txt" file to specify how the node
should conform.
And finally, this patch would be correct since the node will be supposed to conform
to the correct bindings.
Neil
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing
2017-03-13 9:01 ` Neil Armstrong
@ 2017-03-13 19:03 ` Heiner Kallweit
2017-03-14 11:16 ` Neil Armstrong
0 siblings, 1 reply; 14+ messages in thread
From: Heiner Kallweit @ 2017-03-13 19:03 UTC (permalink / raw)
To: Neil Armstrong, linux-amlogic; +Cc: linux-i2c, wsa, Jerome Brunet
Am 13.03.2017 um 10:01 schrieb Neil Armstrong:
> On 03/11/2017 07:23 PM, Heiner Kallweit wrote:
>> We don't have to parse the DT manually to retrieve the bus frequency
>> and we don't have to maintain an own default for the bus frequency.
>> Let the i2c core do this for us.
>>
>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
>> Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
>> ---
>> v2:
>> - added Reviewed-by
>> v3:
>> - changed order of patches
>> ---
>> drivers/i2c/busses/i2c-meson.c | 8 +++-----
>> 1 file changed, 3 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
>> index e597764e..ac0ac82d 100644
>> --- a/drivers/i2c/busses/i2c-meson.c
>> +++ b/drivers/i2c/busses/i2c-meson.c
>> @@ -38,7 +38,6 @@
>> #define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
>>
>> #define I2C_TIMEOUT_MS 500
>> -#define DEFAULT_FREQ 100000
>>
>> enum {
>> TOKEN_END = 0,
>> @@ -387,15 +386,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
>> struct device_node *np = pdev->dev.of_node;
>> struct meson_i2c *i2c;
>> struct resource *mem;
>> - u32 freq;
>> + struct i2c_timings timings;
>> int irq, ret = 0;
>>
>> i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
>> if (!i2c)
>> return -ENOMEM;
>>
>> - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", &freq))
>> - freq = DEFAULT_FREQ;
>> + i2c_parse_fw_timings(&pdev->dev, &timings, true);
>>
>> i2c->dev = &pdev->dev;
>> platform_set_drvdata(pdev, i2c);
>> @@ -453,7 +451,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
>> return ret;
>> }
>>
>> - meson_i2c_set_clk_div(i2c, freq);
>> + meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
>>
>> return 0;
>> }
>>
>
> Hi Heiner,
>
> I'm sorry, but you should *really* update the dt-bindings.
>
> The dt bindings are now strictly related to how the driver is implemented, or which
> attributes are used, but how the device tree node should conform to.
>
> In this particular case, in the recent addition of "standard" i2c attributes for
> speed and timings, you should refer to this "i2c.txt" file to specify how the node
> should conform.
>
> And finally, this patch would be correct since the node will be supposed to conform
> to the correct bindings.
>
I checked the DT documentation of all i2c drivers. Just two include something similar
to what you request:
i2c-rcar.txt
no remark for property clock-frequency
i2c-scl-falling-time-ns: see i2c.txt
nvidia,tegra186-bpmp-i2c.txt
See ../i2c/i2c.txt for details of the core I2C binding.
So you request a comment like the one in the tegra driver documentation?
The supported properties as such don't change in the meson driver, only
clock-freqeuncy is supported as optional parameter.
The timing properties are parsed by the core call but they are not used by the
driver, so I don't think we are allowed to mention them in the documentation.
Else a reader of the documentation may expect that setting such a timing
parameter actually changes the behavior of the driver.
Heiner
> Neil
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing
2017-03-13 19:03 ` Heiner Kallweit
@ 2017-03-14 11:16 ` Neil Armstrong
0 siblings, 0 replies; 14+ messages in thread
From: Neil Armstrong @ 2017-03-14 11:16 UTC (permalink / raw)
To: Heiner Kallweit, linux-amlogic; +Cc: linux-i2c, wsa, Jerome Brunet
On 03/13/2017 08:03 PM, Heiner Kallweit wrote:
> Am 13.03.2017 um 10:01 schrieb Neil Armstrong:
>> On 03/11/2017 07:23 PM, Heiner Kallweit wrote:
>>> We don't have to parse the DT manually to retrieve the bus frequency
>>> and we don't have to maintain an own default for the bus frequency.
>>> Let the i2c core do this for us.
>>>
>>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
>>> Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
>>> ---
>>> v2:
>>> - added Reviewed-by
>>> v3:
>>> - changed order of patches
>>> ---
>>> drivers/i2c/busses/i2c-meson.c | 8 +++-----
>>> 1 file changed, 3 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
>>> index e597764e..ac0ac82d 100644
>>> --- a/drivers/i2c/busses/i2c-meson.c
>>> +++ b/drivers/i2c/busses/i2c-meson.c
>>> @@ -38,7 +38,6 @@
>>> #define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
>>>
>>> #define I2C_TIMEOUT_MS 500
>>> -#define DEFAULT_FREQ 100000
>>>
>>> enum {
>>> TOKEN_END = 0,
>>> @@ -387,15 +386,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
>>> struct device_node *np = pdev->dev.of_node;
>>> struct meson_i2c *i2c;
>>> struct resource *mem;
>>> - u32 freq;
>>> + struct i2c_timings timings;
>>> int irq, ret = 0;
>>>
>>> i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
>>> if (!i2c)
>>> return -ENOMEM;
>>>
>>> - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", &freq))
>>> - freq = DEFAULT_FREQ;
>>> + i2c_parse_fw_timings(&pdev->dev, &timings, true);
>>>
>>> i2c->dev = &pdev->dev;
>>> platform_set_drvdata(pdev, i2c);
>>> @@ -453,7 +451,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
>>> return ret;
>>> }
>>>
>>> - meson_i2c_set_clk_div(i2c, freq);
>>> + meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
>>>
>>> return 0;
>>> }
>>>
>>
>> Hi Heiner,
>>
>> I'm sorry, but you should *really* update the dt-bindings.
>>
>> The dt bindings are now strictly related to how the driver is implemented, or which
>> attributes are used, but how the device tree node should conform to.
>>
>> In this particular case, in the recent addition of "standard" i2c attributes for
>> speed and timings, you should refer to this "i2c.txt" file to specify how the node
>> should conform.
>>
>> And finally, this patch would be correct since the node will be supposed to conform
>> to the correct bindings.
>>
> I checked the DT documentation of all i2c drivers. Just two include something similar
> to what you request:
>
> i2c-rcar.txt
> no remark for property clock-frequency
> i2c-scl-falling-time-ns: see i2c.txt
>
> nvidia,tegra186-bpmp-i2c.txt
> See ../i2c/i2c.txt for details of the core I2C binding.
>
> So you request a comment like the one in the tegra driver documentation?
Exactly.
>
> The supported properties as such don't change in the meson driver, only
> clock-freqeuncy is supported as optional parameter.
> The timing properties are parsed by the core call but they are not used by the
> driver, so I don't think we are allowed to mention them in the documentation.
> Else a reader of the documentation may expect that setting such a timing
> parameter actually changes the behavior of the driver.
Ignore the fact the driver does not parse them, they are marked as optional
in the bindings, so the "DT author" will know they won't be necessarily parsed
or used.
Consider the bindings to be a contract between the DTS and the driver, the DTS
*must* respect the bindings with the mandatory properties and nodes, and can add
optional properties without insurance they will be used.
On the other side, the driver that respects the bindings knows that the mandatory
properties and nodes *must* be present (and *should* fail if not present), and knows
some optional properties and nodes can be present to specify some supplementary parameters,
but in this case fallbacks *must* be available.
>
> Heiner
>
>> Neil
>>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2017-03-14 11:16 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-11 17:48 [PATCH v3 00/10] i2c: meson: series with improvements Heiner Kallweit
2017-03-11 18:22 ` [PATCH v3 01/10] i2c: meson: use min instead of min_t where min_t isn't needed Heiner Kallweit
2017-03-11 18:22 ` [PATCH v3 02/10] i2c: meson: remove member irq from struct meson_i2c Heiner Kallweit
2017-03-11 18:23 ` [PATCH v3 03/10] i2c: meson: set clock divider in probe instead of setting it for each transfer Heiner Kallweit
2017-03-11 18:23 ` [PATCH v3 04/10] i2c: meson: use i2c core for DT clock-frequency parsing Heiner Kallweit
2017-03-13 9:01 ` Neil Armstrong
2017-03-13 19:03 ` Heiner Kallweit
2017-03-14 11:16 ` Neil Armstrong
2017-03-11 18:23 ` [PATCH v3 05/10] i2c: meson: use full 12 bits for clock divider Heiner Kallweit
2017-03-11 18:23 ` [PATCH v3 06/10] i2c: meson: remove variable count from meson_i2c_xfer Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 07/10] i2c: meson: improve interrupt handler and detect spurious interrupts Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 08/10] i2c: meson: don't create separate token chain just for the stop command Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 09/10] i2c: meson: remove meson_i2c_write_tokens Heiner Kallweit
2017-03-11 18:24 ` [PATCH v3 10/10] i2c: meson: improve and simplify interrupt handler Heiner Kallweit
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).