root/drivers/mtd/nand/raw/brcmnand/iproc_nand.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iproc_nand_intc_ack
  2. iproc_nand_intc_set
  3. iproc_nand_apb_access
  4. iproc_nand_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright © 2015 Broadcom Corporation
   4  */
   5 
   6 #include <linux/device.h>
   7 #include <linux/io.h>
   8 #include <linux/ioport.h>
   9 #include <linux/module.h>
  10 #include <linux/of.h>
  11 #include <linux/of_address.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/slab.h>
  14 
  15 #include "brcmnand.h"
  16 
  17 struct iproc_nand_soc {
  18         struct brcmnand_soc soc;
  19 
  20         void __iomem *idm_base;
  21         void __iomem *ext_base;
  22         spinlock_t idm_lock;
  23 };
  24 
  25 #define IPROC_NAND_CTLR_READY_OFFSET       0x10
  26 #define IPROC_NAND_CTLR_READY              BIT(0)
  27 
  28 #define IPROC_NAND_IO_CTRL_OFFSET          0x00
  29 #define IPROC_NAND_APB_LE_MODE             BIT(24)
  30 #define IPROC_NAND_INT_CTRL_READ_ENABLE    BIT(6)
  31 
  32 static bool iproc_nand_intc_ack(struct brcmnand_soc *soc)
  33 {
  34         struct iproc_nand_soc *priv =
  35                         container_of(soc, struct iproc_nand_soc, soc);
  36         void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET;
  37         u32 val = brcmnand_readl(mmio);
  38 
  39         if (val & IPROC_NAND_CTLR_READY) {
  40                 brcmnand_writel(IPROC_NAND_CTLR_READY, mmio);
  41                 return true;
  42         }
  43 
  44         return false;
  45 }
  46 
  47 static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)
  48 {
  49         struct iproc_nand_soc *priv =
  50                         container_of(soc, struct iproc_nand_soc, soc);
  51         void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
  52         u32 val;
  53         unsigned long flags;
  54 
  55         spin_lock_irqsave(&priv->idm_lock, flags);
  56 
  57         val = brcmnand_readl(mmio);
  58 
  59         if (en)
  60                 val |= IPROC_NAND_INT_CTRL_READ_ENABLE;
  61         else
  62                 val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE;
  63 
  64         brcmnand_writel(val, mmio);
  65 
  66         spin_unlock_irqrestore(&priv->idm_lock, flags);
  67 }
  68 
  69 static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare,
  70                                   bool is_param)
  71 {
  72         struct iproc_nand_soc *priv =
  73                         container_of(soc, struct iproc_nand_soc, soc);
  74         void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
  75         u32 val;
  76         unsigned long flags;
  77 
  78         spin_lock_irqsave(&priv->idm_lock, flags);
  79 
  80         val = brcmnand_readl(mmio);
  81 
  82         /*
  83          * In the case of BE or when dealing with NAND data, alway configure
  84          * the APB bus to LE mode before accessing the FIFO and back to BE mode
  85          * after the access is done
  86          */
  87         if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) || !is_param) {
  88                 if (prepare)
  89                         val |= IPROC_NAND_APB_LE_MODE;
  90                 else
  91                         val &= ~IPROC_NAND_APB_LE_MODE;
  92         } else { /* when in LE accessing the parameter page, keep APB in BE */
  93                 val &= ~IPROC_NAND_APB_LE_MODE;
  94         }
  95 
  96         brcmnand_writel(val, mmio);
  97 
  98         spin_unlock_irqrestore(&priv->idm_lock, flags);
  99 }
 100 
 101 static int iproc_nand_probe(struct platform_device *pdev)
 102 {
 103         struct device *dev = &pdev->dev;
 104         struct iproc_nand_soc *priv;
 105         struct brcmnand_soc *soc;
 106         struct resource *res;
 107 
 108         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 109         if (!priv)
 110                 return -ENOMEM;
 111         soc = &priv->soc;
 112 
 113         spin_lock_init(&priv->idm_lock);
 114 
 115         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-idm");
 116         priv->idm_base = devm_ioremap_resource(dev, res);
 117         if (IS_ERR(priv->idm_base))
 118                 return PTR_ERR(priv->idm_base);
 119 
 120         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-ext");
 121         priv->ext_base = devm_ioremap_resource(dev, res);
 122         if (IS_ERR(priv->ext_base))
 123                 return PTR_ERR(priv->ext_base);
 124 
 125         soc->ctlrdy_ack = iproc_nand_intc_ack;
 126         soc->ctlrdy_set_enabled = iproc_nand_intc_set;
 127         soc->prepare_data_bus = iproc_nand_apb_access;
 128 
 129         return brcmnand_probe(pdev, soc);
 130 }
 131 
 132 static const struct of_device_id iproc_nand_of_match[] = {
 133         { .compatible = "brcm,nand-iproc" },
 134         {},
 135 };
 136 MODULE_DEVICE_TABLE(of, iproc_nand_of_match);
 137 
 138 static struct platform_driver iproc_nand_driver = {
 139         .probe                  = iproc_nand_probe,
 140         .remove                 = brcmnand_remove,
 141         .driver = {
 142                 .name           = "iproc_nand",
 143                 .pm             = &brcmnand_pm_ops,
 144                 .of_match_table = iproc_nand_of_match,
 145         }
 146 };
 147 module_platform_driver(iproc_nand_driver);
 148 
 149 MODULE_LICENSE("GPL v2");
 150 MODULE_AUTHOR("Brian Norris");
 151 MODULE_AUTHOR("Ray Jui");
 152 MODULE_DESCRIPTION("NAND driver for Broadcom IPROC-based SoCs");

/* [<][>][^][v][top][bottom][index][help] */