mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
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: Miquel Raynal <miquel.raynal@bootlin.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/linux-mtd/20220513104957.257721-3-miquel.raynal@bootlin.com
This commit is contained in:
@@ -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 {
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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 @@ cleanup_chips:
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user