[PATCH linux-next (v2) 2/3] mtd: brcmnand: Request and enable the clock if present
Florian Fainelli
f.fainelli at gmail.com
Wed Dec 9 13:02:15 PST 2015
Le 09/12/2015 12:42, Simon Arlott a écrit :
> Attempt to enable a clock named "nand" as some SoCs have a clock for the
> controller that needs to be enabled.
>
> Signed-off-by: Simon Arlott <simon at fire.lp0.eu>
Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
> ---
> Resend, no changes.
>
> drivers/mtd/nand/brcmnand/brcmnand.c | 64 ++++++++++++++++++++++++++++--------
> 1 file changed, 50 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
> index 190a99a..dca8162 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> @@ -11,6 +11,7 @@
> * GNU General Public License for more details.
> */
>
> +#include <linux/clk.h>
> #include <linux/version.h>
> #include <linux/module.h>
> #include <linux/init.h>
> @@ -122,6 +123,9 @@ struct brcmnand_controller {
> /* Some SoCs provide custom interrupt status register(s) */
> struct brcmnand_soc *soc;
>
> + /* Some SoCs have a gateable clock for the controller */
> + struct clk *clk;
> +
> int cmd_pending;
> bool dma_pending;
> struct completion done;
> @@ -2127,10 +2131,24 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> if (IS_ERR(ctrl->nand_base))
> return PTR_ERR(ctrl->nand_base);
>
> + /* Enable clock before using NAND registers */
> + ctrl->clk = devm_clk_get(dev, "nand");
> + if (!IS_ERR(ctrl->clk)) {
> + ret = clk_prepare_enable(ctrl->clk);
> + if (ret)
> + return ret;
> + } else {
> + ret = PTR_ERR(ctrl->clk);
> + if (ret == -EPROBE_DEFER)
> + return ret;
> +
> + ctrl->clk = NULL;
> + }
> +
> /* Initialize NAND revision */
> ret = brcmnand_revision_init(ctrl);
> if (ret)
> - return ret;
> + goto err;
>
> /*
> * Most chips have this cache at a fixed offset within 'nand' block.
> @@ -2139,8 +2157,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache");
> if (res) {
> ctrl->nand_fc = devm_ioremap_resource(dev, res);
> - if (IS_ERR(ctrl->nand_fc))
> - return PTR_ERR(ctrl->nand_fc);
> + if (IS_ERR(ctrl->nand_fc)) {
> + ret = PTR_ERR(ctrl->nand_fc);
> + goto err;
> + }
> } else {
> ctrl->nand_fc = ctrl->nand_base +
> ctrl->reg_offsets[BRCMNAND_FC_BASE];
> @@ -2150,8 +2170,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma");
> if (res) {
> ctrl->flash_dma_base = devm_ioremap_resource(dev, res);
> - if (IS_ERR(ctrl->flash_dma_base))
> - return PTR_ERR(ctrl->flash_dma_base);
> + if (IS_ERR(ctrl->flash_dma_base)) {
> + ret = PTR_ERR(ctrl->flash_dma_base);
> + goto err;
> + }
>
> flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
> flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
> @@ -2160,13 +2182,16 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> ctrl->dma_desc = dmam_alloc_coherent(dev,
> sizeof(*ctrl->dma_desc),
> &ctrl->dma_pa, GFP_KERNEL);
> - if (!ctrl->dma_desc)
> - return -ENOMEM;
> + if (!ctrl->dma_desc) {
> + ret = -ENOMEM;
> + goto err;
> + }
>
> ctrl->dma_irq = platform_get_irq(pdev, 1);
> if ((int)ctrl->dma_irq < 0) {
> dev_err(dev, "missing FLASH_DMA IRQ\n");
> - return -ENODEV;
> + ret = -ENODEV;
> + goto err;
> }
>
> ret = devm_request_irq(dev, ctrl->dma_irq,
> @@ -2175,7 +2200,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> if (ret < 0) {
> dev_err(dev, "can't allocate IRQ %d: error %d\n",
> ctrl->dma_irq, ret);
> - return ret;
> + goto err;
> }
>
> dev_info(dev, "enabling FLASH_DMA\n");
> @@ -2199,7 +2224,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> ctrl->irq = platform_get_irq(pdev, 0);
> if ((int)ctrl->irq < 0) {
> dev_err(dev, "no IRQ defined\n");
> - return -ENODEV;
> + ret = -ENODEV;
> + goto err;
> }
>
> /*
> @@ -2223,7 +2249,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> if (ret < 0) {
> dev_err(dev, "can't allocate IRQ %d: error %d\n",
> ctrl->irq, ret);
> - return ret;
> + goto err;
> }
>
> for_each_available_child_of_node(dn, child) {
> @@ -2233,7 +2259,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
> if (!host) {
> of_node_put(child);
> - return -ENOMEM;
> + ret = -ENOMEM;
> + goto err;
> }
> host->pdev = pdev;
> host->ctrl = ctrl;
> @@ -2249,10 +2276,17 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> }
>
> /* No chip-selects could initialize properly */
> - if (list_empty(&ctrl->host_list))
> - return -ENODEV;
> + if (list_empty(&ctrl->host_list)) {
> + ret = -ENODEV;
> + goto err;
> + }
>
> return 0;
> +
> +err:
> + clk_disable_unprepare(ctrl->clk);
> + return ret;
> +
> }
> EXPORT_SYMBOL_GPL(brcmnand_probe);
>
> @@ -2264,6 +2298,8 @@ int brcmnand_remove(struct platform_device *pdev)
> list_for_each_entry(host, &ctrl->host_list, node)
> nand_release(&host->mtd);
>
> + clk_disable_unprepare(ctrl->clk);
> +
> dev_set_drvdata(&pdev->dev, NULL);
>
> return 0;
>
--
Florian
More information about the linux-mtd
mailing list