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

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
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/mtd/rawnand.h> #include <linux/mtd/rawnand.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
#define COMMAND_REG 0x00 #define COMMAND_REG 0x00
...@@ -216,8 +217,7 @@ struct rnandc { ...@@ -216,8 +217,7 @@ struct rnandc {
struct nand_controller controller; struct nand_controller controller;
struct device *dev; struct device *dev;
void __iomem *regs; void __iomem *regs;
struct clk *hclk; unsigned long ext_clk_rate;
struct clk *eclk;
unsigned long assigned_cs; unsigned long assigned_cs;
struct list_head chips; struct list_head chips;
struct nand_chip *selected_chip; struct nand_chip *selected_chip;
...@@ -891,7 +891,7 @@ static int rnandc_setup_interface(struct nand_chip *chip, int chipnr, ...@@ -891,7 +891,7 @@ static int rnandc_setup_interface(struct nand_chip *chip, int chipnr,
{ {
struct rnand_chip *rnand = to_rnand(chip); struct rnand_chip *rnand = to_rnand(chip);
struct rnandc *rnandc = to_rnandc(chip->controller); 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; const struct nand_sdr_timings *sdr;
unsigned int cyc, cle, ale, bef_dly, ca_to_data; unsigned int cyc, cle, ale, bef_dly, ca_to_data;
...@@ -1319,6 +1319,7 @@ static int rnandc_chips_init(struct rnandc *rnandc) ...@@ -1319,6 +1319,7 @@ static int rnandc_chips_init(struct rnandc *rnandc)
static int rnandc_probe(struct platform_device *pdev) static int rnandc_probe(struct platform_device *pdev)
{ {
struct rnandc *rnandc; struct rnandc *rnandc;
struct clk *eclk;
int irq, ret; int irq, ret;
rnandc = devm_kzalloc(&pdev->dev, sizeof(*rnandc), GFP_KERNEL); rnandc = devm_kzalloc(&pdev->dev, sizeof(*rnandc), GFP_KERNEL);
...@@ -1335,29 +1336,26 @@ static int rnandc_probe(struct platform_device *pdev) ...@@ -1335,29 +1336,26 @@ static int rnandc_probe(struct platform_device *pdev)
if (IS_ERR(rnandc->regs)) if (IS_ERR(rnandc->regs))
return PTR_ERR(rnandc->regs); return PTR_ERR(rnandc->regs);
/* APB clock */ devm_pm_runtime_enable(&pdev->dev);
rnandc->hclk = devm_clk_get(&pdev->dev, "hclk"); ret = pm_runtime_resume_and_get(&pdev->dev);
if (IS_ERR(rnandc->hclk)) if (ret < 0)
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)
return ret; return ret;
ret = clk_prepare_enable(rnandc->eclk); /* The external NAND bus clock rate is needed for computing timings */
if (ret) eclk = clk_get(&pdev->dev, "eclk");
goto disable_hclk; 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); rnandc_dis_interrupts(rnandc);
irq = platform_get_irq_optional(pdev, 0); irq = platform_get_irq_optional(pdev, 0);
if (irq == -EPROBE_DEFER) { if (irq == -EPROBE_DEFER) {
ret = irq; ret = irq;
goto disable_eclk; goto dis_runtime_pm;
} else if (irq < 0) { } else if (irq < 0) {
dev_info(&pdev->dev, "No IRQ found, fallback to polling\n"); dev_info(&pdev->dev, "No IRQ found, fallback to polling\n");
rnandc->use_polling = true; rnandc->use_polling = true;
...@@ -1365,12 +1363,12 @@ static int rnandc_probe(struct platform_device *pdev) ...@@ -1365,12 +1363,12 @@ static int rnandc_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, irq, rnandc_irq_handler, 0, ret = devm_request_irq(&pdev->dev, irq, rnandc_irq_handler, 0,
"renesas-nand-controller", rnandc); "renesas-nand-controller", rnandc);
if (ret < 0) if (ret < 0)
goto disable_eclk; goto dis_runtime_pm;
} }
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret) if (ret)
goto disable_eclk; goto dis_runtime_pm;
rnandc_clear_fifo(rnandc); rnandc_clear_fifo(rnandc);
...@@ -1378,14 +1376,12 @@ static int rnandc_probe(struct platform_device *pdev) ...@@ -1378,14 +1376,12 @@ static int rnandc_probe(struct platform_device *pdev)
ret = rnandc_chips_init(rnandc); ret = rnandc_chips_init(rnandc);
if (ret) if (ret)
goto disable_eclk; goto dis_runtime_pm;
return 0; return 0;
disable_eclk: dis_runtime_pm:
clk_disable_unprepare(rnandc->eclk); pm_runtime_put(&pdev->dev);
disable_hclk:
clk_disable_unprepare(rnandc->hclk);
return ret; return ret;
} }
...@@ -1396,8 +1392,7 @@ static int rnandc_remove(struct platform_device *pdev) ...@@ -1396,8 +1392,7 @@ static int rnandc_remove(struct platform_device *pdev)
rnandc_chips_cleanup(rnandc); rnandc_chips_cleanup(rnandc);
clk_disable_unprepare(rnandc->eclk); pm_runtime_put(&pdev->dev);
clk_disable_unprepare(rnandc->hclk);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment