mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2024-12-30 10:42:22 +00:00
213b728276
Pick accepted patches from upstream Linux tree instead of having to maintain our slightly different downstream patches. Import pending patch fixing I2C on MT7981 by making sure all clocks are enabled before accessing I2C registers. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
235 lines
7.0 KiB
Diff
235 lines
7.0 KiB
Diff
From cc6faa5e0772296d815fd298c231277d47308a6a Mon Sep 17 00:00:00 2001
|
|
From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
|
Date: Thu, 3 Mar 2022 10:15:47 +0100
|
|
Subject: [PATCH 06/16] i2c: mt65xx: Simplify with clk-bulk
|
|
|
|
Since depending on the SoC or specific bus functionality some clocks
|
|
may be optional, we cannot get the benefit of using devm_clk_bulk_get()
|
|
but, by migrating to clk-bulk, we are able to remove the custom functions
|
|
mtk_i2c_clock_enable() and mtk_i2c_clock_disable(), increasing common
|
|
APIs usage, hence (lightly) decreasing kernel footprint.
|
|
|
|
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
|
Reviewed-by: Qii Wang <qii.wang@mediatek.com>
|
|
Signed-off-by: Wolfram Sang <wsa@kernel.org>
|
|
---
|
|
drivers/i2c/busses/i2c-mt65xx.c | 124 +++++++++++++-------------------
|
|
1 file changed, 51 insertions(+), 73 deletions(-)
|
|
|
|
--- a/drivers/i2c/busses/i2c-mt65xx.c
|
|
+++ b/drivers/i2c/busses/i2c-mt65xx.c
|
|
@@ -86,6 +86,27 @@
|
|
|
|
#define I2C_DRV_NAME "i2c-mt65xx"
|
|
|
|
+/**
|
|
+ * enum i2c_mt65xx_clks - Clocks enumeration for MT65XX I2C
|
|
+ *
|
|
+ * @I2C_MT65XX_CLK_MAIN: main clock for i2c bus
|
|
+ * @I2C_MT65XX_CLK_DMA: DMA clock for i2c via DMA
|
|
+ * @I2C_MT65XX_CLK_PMIC: PMIC clock for i2c from PMIC
|
|
+ * @I2C_MT65XX_CLK_ARB: Arbitrator clock for i2c
|
|
+ * @I2C_MT65XX_CLK_MAX: Number of supported clocks
|
|
+ */
|
|
+enum i2c_mt65xx_clks {
|
|
+ I2C_MT65XX_CLK_MAIN = 0,
|
|
+ I2C_MT65XX_CLK_DMA,
|
|
+ I2C_MT65XX_CLK_PMIC,
|
|
+ I2C_MT65XX_CLK_ARB,
|
|
+ I2C_MT65XX_CLK_MAX
|
|
+};
|
|
+
|
|
+static const char * const i2c_mt65xx_clk_ids[I2C_MT65XX_CLK_MAX] = {
|
|
+ "main", "dma", "pmic", "arb"
|
|
+};
|
|
+
|
|
enum DMA_REGS_OFFSET {
|
|
OFFSET_INT_FLAG = 0x0,
|
|
OFFSET_INT_EN = 0x04,
|
|
@@ -244,10 +265,7 @@ struct mtk_i2c {
|
|
/* set in i2c probe */
|
|
void __iomem *base; /* i2c base addr */
|
|
void __iomem *pdmabase; /* dma base address*/
|
|
- struct clk *clk_main; /* main clock for i2c bus */
|
|
- struct clk *clk_dma; /* DMA clock for i2c via DMA */
|
|
- struct clk *clk_pmic; /* PMIC clock for i2c from PMIC */
|
|
- struct clk *clk_arb; /* Arbitrator clock for i2c */
|
|
+ struct clk_bulk_data clocks[I2C_MT65XX_CLK_MAX]; /* clocks for i2c */
|
|
bool have_pmic; /* can use i2c pins from PMIC */
|
|
bool use_push_pull; /* IO config push-pull mode */
|
|
|
|
@@ -449,52 +467,6 @@ static void mtk_i2c_writew(struct mtk_i2
|
|
writew(val, i2c->base + i2c->dev_comp->regs[reg]);
|
|
}
|
|
|
|
-static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
|
|
-{
|
|
- int ret;
|
|
-
|
|
- ret = clk_prepare_enable(i2c->clk_dma);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- ret = clk_prepare_enable(i2c->clk_main);
|
|
- if (ret)
|
|
- goto err_main;
|
|
-
|
|
- if (i2c->have_pmic) {
|
|
- ret = clk_prepare_enable(i2c->clk_pmic);
|
|
- if (ret)
|
|
- goto err_pmic;
|
|
- }
|
|
-
|
|
- if (i2c->clk_arb) {
|
|
- ret = clk_prepare_enable(i2c->clk_arb);
|
|
- if (ret)
|
|
- goto err_arb;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-
|
|
-err_arb:
|
|
- clk_disable_unprepare(i2c->clk_pmic);
|
|
-err_pmic:
|
|
- clk_disable_unprepare(i2c->clk_main);
|
|
-err_main:
|
|
- clk_disable_unprepare(i2c->clk_dma);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
|
|
-{
|
|
- clk_disable_unprepare(i2c->clk_arb);
|
|
-
|
|
- clk_disable_unprepare(i2c->clk_pmic);
|
|
-
|
|
- clk_disable_unprepare(i2c->clk_main);
|
|
- clk_disable_unprepare(i2c->clk_dma);
|
|
-}
|
|
-
|
|
static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
|
|
{
|
|
u16 control_reg;
|
|
@@ -1191,7 +1163,7 @@ static int mtk_i2c_transfer(struct i2c_a
|
|
int left_num = num;
|
|
struct mtk_i2c *i2c = i2c_get_adapdata(adap);
|
|
|
|
- ret = mtk_i2c_clock_enable(i2c);
|
|
+ ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
|
|
if (ret)
|
|
return ret;
|
|
|
|
@@ -1245,7 +1217,7 @@ static int mtk_i2c_transfer(struct i2c_a
|
|
ret = num;
|
|
|
|
err_exit:
|
|
- mtk_i2c_clock_disable(i2c);
|
|
+ clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
|
|
return ret;
|
|
}
|
|
|
|
@@ -1323,9 +1295,8 @@ static int mtk_i2c_probe(struct platform
|
|
{
|
|
int ret = 0;
|
|
struct mtk_i2c *i2c;
|
|
- struct clk *clk;
|
|
struct resource *res;
|
|
- int irq;
|
|
+ int i, irq, speed_clk;
|
|
|
|
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
|
|
if (!i2c)
|
|
@@ -1371,35 +1342,42 @@ static int mtk_i2c_probe(struct platform
|
|
if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
|
|
return -EINVAL;
|
|
|
|
- i2c->clk_main = devm_clk_get(&pdev->dev, "main");
|
|
- if (IS_ERR(i2c->clk_main)) {
|
|
+ /* Fill in clk-bulk IDs */
|
|
+ for (i = 0; i < I2C_MT65XX_CLK_MAX; i++)
|
|
+ i2c->clocks[i].id = i2c_mt65xx_clk_ids[i];
|
|
+
|
|
+ /* Get clocks one by one, some may be optional */
|
|
+ i2c->clocks[I2C_MT65XX_CLK_MAIN].clk = devm_clk_get(&pdev->dev, "main");
|
|
+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_MAIN].clk)) {
|
|
dev_err(&pdev->dev, "cannot get main clock\n");
|
|
- return PTR_ERR(i2c->clk_main);
|
|
+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_MAIN].clk);
|
|
}
|
|
|
|
- i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
|
|
- if (IS_ERR(i2c->clk_dma)) {
|
|
+ i2c->clocks[I2C_MT65XX_CLK_DMA].clk = devm_clk_get(&pdev->dev, "dma");
|
|
+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_DMA].clk)) {
|
|
dev_err(&pdev->dev, "cannot get dma clock\n");
|
|
- return PTR_ERR(i2c->clk_dma);
|
|
+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_DMA].clk);
|
|
}
|
|
|
|
- i2c->clk_arb = devm_clk_get(&pdev->dev, "arb");
|
|
- if (IS_ERR(i2c->clk_arb))
|
|
- i2c->clk_arb = NULL;
|
|
+ i2c->clocks[I2C_MT65XX_CLK_ARB].clk = devm_clk_get_optional(&pdev->dev, "arb");
|
|
+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk))
|
|
+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk);
|
|
|
|
- clk = i2c->clk_main;
|
|
if (i2c->have_pmic) {
|
|
- i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
|
|
- if (IS_ERR(i2c->clk_pmic)) {
|
|
+ i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic");
|
|
+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) {
|
|
dev_err(&pdev->dev, "cannot get pmic clock\n");
|
|
- return PTR_ERR(i2c->clk_pmic);
|
|
+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk);
|
|
}
|
|
- clk = i2c->clk_pmic;
|
|
+ speed_clk = I2C_MT65XX_CLK_PMIC;
|
|
+ } else {
|
|
+ i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = NULL;
|
|
+ speed_clk = I2C_MT65XX_CLK_MAIN;
|
|
}
|
|
|
|
strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
|
|
|
|
- ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk));
|
|
+ ret = mtk_i2c_set_speed(i2c, clk_get_rate(i2c->clocks[speed_clk].clk));
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "Failed to set the speed.\n");
|
|
return -EINVAL;
|
|
@@ -1414,13 +1392,13 @@ static int mtk_i2c_probe(struct platform
|
|
}
|
|
}
|
|
|
|
- ret = mtk_i2c_clock_enable(i2c);
|
|
+ ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "clock enable failed!\n");
|
|
return ret;
|
|
}
|
|
mtk_i2c_init_hw(i2c);
|
|
- mtk_i2c_clock_disable(i2c);
|
|
+ clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
|
|
|
|
ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
|
|
IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
|
|
@@ -1465,7 +1443,7 @@ static int mtk_i2c_resume_noirq(struct d
|
|
int ret;
|
|
struct mtk_i2c *i2c = dev_get_drvdata(dev);
|
|
|
|
- ret = mtk_i2c_clock_enable(i2c);
|
|
+ ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
|
|
if (ret) {
|
|
dev_err(dev, "clock enable failed!\n");
|
|
return ret;
|
|
@@ -1473,7 +1451,7 @@ static int mtk_i2c_resume_noirq(struct d
|
|
|
|
mtk_i2c_init_hw(i2c);
|
|
|
|
- mtk_i2c_clock_disable(i2c);
|
|
+ clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
|
|
|
|
i2c_mark_adapter_resumed(&i2c->adap);
|
|
|