Commit 0016a32f authored by AngeloGioacchino Del Regno's avatar AngeloGioacchino Del Regno Committed by Wolfram Sang
Browse files

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: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: default avatarQii Wang <qii.wang@mediatek.com>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent 52c74d17
Loading
Loading
Loading
Loading
+51 −73
Original line number Diff line number Diff line
@@ -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_i2c *i2c, u16 val,
	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_adapter *adap,
	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_adapter *adap,
	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_device *pdev)
{
	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_device *pdev)
	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_device *pdev)
		}
	}

	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 device *dev)
	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 device *dev)

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