Commit 6a2277a0 authored by Miquel Raynal's avatar Miquel Raynal
Browse files

mtd: rawnand: renesas: Use runtime PM instead of the raw clock API



This NAND controller is part of a well defined power domain handled by
the runtime PM core. Let's keep the harmony with the other RZ/N1 drivers
and exclusively use the runtime PM API to enable/disable the clocks.

We still need to retrieve the external clock rate in order to derive the
NAND timings, but that is not a big deal, we can still do that in the
probe and just save this value to reuse it later.

Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/linux-mtd/20220513104957.257721-3-miquel.raynal@bootlin.com
parent 431cbce8
Loading
Loading
Loading
Loading
+23 −28
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/mtd/rawnand.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>

#define COMMAND_REG 0x00
@@ -216,8 +217,7 @@ struct rnandc {
	struct nand_controller controller;
	struct device *dev;
	void __iomem *regs;
	struct clk *hclk;
	struct clk *eclk;
	unsigned long ext_clk_rate;
	unsigned long assigned_cs;
	struct list_head chips;
	struct nand_chip *selected_chip;
@@ -891,7 +891,7 @@ static int rnandc_setup_interface(struct nand_chip *chip, int chipnr,
{
	struct rnand_chip *rnand = to_rnand(chip);
	struct rnandc *rnandc = to_rnandc(chip->controller);
	unsigned int period_ns = 1000000000 / clk_get_rate(rnandc->eclk);
	unsigned int period_ns = 1000000000 / rnandc->ext_clk_rate;
	const struct nand_sdr_timings *sdr;
	unsigned int cyc, cle, ale, bef_dly, ca_to_data;

@@ -1319,6 +1319,7 @@ static int rnandc_chips_init(struct rnandc *rnandc)
static int rnandc_probe(struct platform_device *pdev)
{
	struct rnandc *rnandc;
	struct clk *eclk;
	int irq, ret;

	rnandc = devm_kzalloc(&pdev->dev, sizeof(*rnandc), GFP_KERNEL);
@@ -1335,29 +1336,26 @@ static int rnandc_probe(struct platform_device *pdev)
	if (IS_ERR(rnandc->regs))
		return PTR_ERR(rnandc->regs);

	/* APB clock */
	rnandc->hclk = devm_clk_get(&pdev->dev, "hclk");
	if (IS_ERR(rnandc->hclk))
		return PTR_ERR(rnandc->hclk);

	/* External NAND bus clock */
	rnandc->eclk = devm_clk_get(&pdev->dev, "eclk");
	if (IS_ERR(rnandc->eclk))
		return PTR_ERR(rnandc->eclk);

	ret = clk_prepare_enable(rnandc->hclk);
	if (ret)
	devm_pm_runtime_enable(&pdev->dev);
	ret = pm_runtime_resume_and_get(&pdev->dev);
	if (ret < 0)
		return ret;

	ret = clk_prepare_enable(rnandc->eclk);
	if (ret)
		goto disable_hclk;
	/* The external NAND bus clock rate is needed for computing timings */
	eclk = clk_get(&pdev->dev, "eclk");
	if (IS_ERR(eclk)) {
		ret = PTR_ERR(eclk);
		goto dis_runtime_pm;
	}

	rnandc->ext_clk_rate = clk_get_rate(eclk);
	clk_put(eclk);

	rnandc_dis_interrupts(rnandc);
	irq = platform_get_irq_optional(pdev, 0);
	if (irq == -EPROBE_DEFER) {
		ret = irq;
		goto disable_eclk;
		goto dis_runtime_pm;
	} else if (irq < 0) {
		dev_info(&pdev->dev, "No IRQ found, fallback to polling\n");
		rnandc->use_polling = true;
@@ -1365,12 +1363,12 @@ static int rnandc_probe(struct platform_device *pdev)
		ret = devm_request_irq(&pdev->dev, irq, rnandc_irq_handler, 0,
				       "renesas-nand-controller", rnandc);
		if (ret < 0)
			goto disable_eclk;
			goto dis_runtime_pm;
	}

	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (ret)
		goto disable_eclk;
		goto dis_runtime_pm;

	rnandc_clear_fifo(rnandc);

@@ -1378,14 +1376,12 @@ static int rnandc_probe(struct platform_device *pdev)

	ret = rnandc_chips_init(rnandc);
	if (ret)
		goto disable_eclk;
		goto dis_runtime_pm;

	return 0;

disable_eclk:
	clk_disable_unprepare(rnandc->eclk);
disable_hclk:
	clk_disable_unprepare(rnandc->hclk);
dis_runtime_pm:
	pm_runtime_put(&pdev->dev);

	return ret;
}
@@ -1396,8 +1392,7 @@ static int rnandc_remove(struct platform_device *pdev)

	rnandc_chips_cleanup(rnandc);

	clk_disable_unprepare(rnandc->eclk);
	clk_disable_unprepare(rnandc->hclk);
	pm_runtime_put(&pdev->dev);

	return 0;
}