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>
This commit is contained in:
AngeloGioacchino Del Regno 2022-03-03 10:15:47 +01:00 коммит произвёл Wolfram Sang
Родитель 52c74d17d8
Коммит 0016a32f75
1 изменённых файлов: 51 добавлений и 73 удалений

Просмотреть файл

@ -86,6 +86,27 @@
#define I2C_DRV_NAME "i2c-mt65xx" #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 { enum DMA_REGS_OFFSET {
OFFSET_INT_FLAG = 0x0, OFFSET_INT_FLAG = 0x0,
OFFSET_INT_EN = 0x04, OFFSET_INT_EN = 0x04,
@ -244,10 +265,7 @@ struct mtk_i2c {
/* set in i2c probe */ /* set in i2c probe */
void __iomem *base; /* i2c base addr */ void __iomem *base; /* i2c base addr */
void __iomem *pdmabase; /* dma base address*/ void __iomem *pdmabase; /* dma base address*/
struct clk *clk_main; /* main clock for i2c bus */ struct clk_bulk_data clocks[I2C_MT65XX_CLK_MAX]; /* clocks for i2c */
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 */
bool have_pmic; /* can use i2c pins from PMIC */ bool have_pmic; /* can use i2c pins from PMIC */
bool use_push_pull; /* IO config push-pull mode */ bool use_push_pull; /* IO config push-pull mode */
@ -449,52 +467,6 @@ static void mtk_i2c_writew(struct mtk_i2c *i2c, u16 val,
writew(val, i2c->base + i2c->dev_comp->regs[reg]); 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) static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
{ {
u16 control_reg; u16 control_reg;
@ -1191,7 +1163,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
int left_num = num; int left_num = num;
struct mtk_i2c *i2c = i2c_get_adapdata(adap); 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) if (ret)
return ret; return ret;
@ -1245,7 +1217,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
ret = num; ret = num;
err_exit: err_exit:
mtk_i2c_clock_disable(i2c); clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
return ret; return ret;
} }
@ -1323,9 +1295,8 @@ static int mtk_i2c_probe(struct platform_device *pdev)
{ {
int ret = 0; int ret = 0;
struct mtk_i2c *i2c; struct mtk_i2c *i2c;
struct clk *clk;
struct resource *res; struct resource *res;
int irq; int i, irq, speed_clk;
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) if (!i2c)
@ -1371,35 +1342,42 @@ static int mtk_i2c_probe(struct platform_device *pdev)
if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c) if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
return -EINVAL; return -EINVAL;
i2c->clk_main = devm_clk_get(&pdev->dev, "main"); /* Fill in clk-bulk IDs */
if (IS_ERR(i2c->clk_main)) { 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"); 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"); i2c->clocks[I2C_MT65XX_CLK_DMA].clk = devm_clk_get(&pdev->dev, "dma");
if (IS_ERR(i2c->clk_dma)) { if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_DMA].clk)) {
dev_err(&pdev->dev, "cannot get dma clock\n"); 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"); i2c->clocks[I2C_MT65XX_CLK_ARB].clk = devm_clk_get_optional(&pdev->dev, "arb");
if (IS_ERR(i2c->clk_arb)) if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk))
i2c->clk_arb = NULL; return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk);
clk = i2c->clk_main;
if (i2c->have_pmic) { if (i2c->have_pmic) {
i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic"); i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic");
if (IS_ERR(i2c->clk_pmic)) { if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) {
dev_err(&pdev->dev, "cannot get pmic clock\n"); 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)); 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) { if (ret) {
dev_err(&pdev->dev, "Failed to set the speed.\n"); dev_err(&pdev->dev, "Failed to set the speed.\n");
return -EINVAL; return -EINVAL;
@ -1414,13 +1392,13 @@ static int mtk_i2c_probe(struct platform_device *pdev)
} }
} }
ret = mtk_i2c_clock_enable(i2c); ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
if (ret) { if (ret) {
dev_err(&pdev->dev, "clock enable failed!\n"); dev_err(&pdev->dev, "clock enable failed!\n");
return ret; return ret;
} }
mtk_i2c_init_hw(i2c); 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, ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE, IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
@ -1465,7 +1443,7 @@ static int mtk_i2c_resume_noirq(struct device *dev)
int ret; int ret;
struct mtk_i2c *i2c = dev_get_drvdata(dev); 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) { if (ret) {
dev_err(dev, "clock enable failed!\n"); dev_err(dev, "clock enable failed!\n");
return ret; return ret;
@ -1473,7 +1451,7 @@ static int mtk_i2c_resume_noirq(struct device *dev)
mtk_i2c_init_hw(i2c); 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); i2c_mark_adapter_resumed(&i2c->adap);