Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Brian Norris | 564 | 95.27% | 2 | 40.00% |
Ray Jui | 20 | 3.38% | 1 | 20.00% |
Li Zetao | 6 | 1.01% | 1 | 20.00% |
Thomas Gleixner | 2 | 0.34% | 1 | 20.00% |
Total | 592 | 5 |
// SPDX-License-Identifier: GPL-2.0-only /* * Copyright © 2015 Broadcom Corporation */ #include <linux/device.h> #include <linux/io.h> #include <linux/ioport.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/slab.h> #include "brcmnand.h" struct iproc_nand_soc { struct brcmnand_soc soc; void __iomem *idm_base; void __iomem *ext_base; spinlock_t idm_lock; }; #define IPROC_NAND_CTLR_READY_OFFSET 0x10 #define IPROC_NAND_CTLR_READY BIT(0) #define IPROC_NAND_IO_CTRL_OFFSET 0x00 #define IPROC_NAND_APB_LE_MODE BIT(24) #define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6) static bool iproc_nand_intc_ack(struct brcmnand_soc *soc) { struct iproc_nand_soc *priv = container_of(soc, struct iproc_nand_soc, soc); void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET; u32 val = brcmnand_readl(mmio); if (val & IPROC_NAND_CTLR_READY) { brcmnand_writel(IPROC_NAND_CTLR_READY, mmio); return true; } return false; } static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en) { struct iproc_nand_soc *priv = container_of(soc, struct iproc_nand_soc, soc); void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; u32 val; unsigned long flags; spin_lock_irqsave(&priv->idm_lock, flags); val = brcmnand_readl(mmio); if (en) val |= IPROC_NAND_INT_CTRL_READ_ENABLE; else val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE; brcmnand_writel(val, mmio); spin_unlock_irqrestore(&priv->idm_lock, flags); } static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare, bool is_param) { struct iproc_nand_soc *priv = container_of(soc, struct iproc_nand_soc, soc); void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; u32 val; unsigned long flags; spin_lock_irqsave(&priv->idm_lock, flags); val = brcmnand_readl(mmio); /* * In the case of BE or when dealing with NAND data, alway configure * the APB bus to LE mode before accessing the FIFO and back to BE mode * after the access is done */ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) || !is_param) { if (prepare) val |= IPROC_NAND_APB_LE_MODE; else val &= ~IPROC_NAND_APB_LE_MODE; } else { /* when in LE accessing the parameter page, keep APB in BE */ val &= ~IPROC_NAND_APB_LE_MODE; } brcmnand_writel(val, mmio); spin_unlock_irqrestore(&priv->idm_lock, flags); } static int iproc_nand_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct iproc_nand_soc *priv; struct brcmnand_soc *soc; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; soc = &priv->soc; spin_lock_init(&priv->idm_lock); priv->idm_base = devm_platform_ioremap_resource_byname(pdev, "iproc-idm"); if (IS_ERR(priv->idm_base)) return PTR_ERR(priv->idm_base); priv->ext_base = devm_platform_ioremap_resource_byname(pdev, "iproc-ext"); if (IS_ERR(priv->ext_base)) return PTR_ERR(priv->ext_base); soc->ctlrdy_ack = iproc_nand_intc_ack; soc->ctlrdy_set_enabled = iproc_nand_intc_set; soc->prepare_data_bus = iproc_nand_apb_access; return brcmnand_probe(pdev, soc); } static const struct of_device_id iproc_nand_of_match[] = { { .compatible = "brcm,nand-iproc" }, {}, }; MODULE_DEVICE_TABLE(of, iproc_nand_of_match); static struct platform_driver iproc_nand_driver = { .probe = iproc_nand_probe, .remove = brcmnand_remove, .driver = { .name = "iproc_nand", .pm = &brcmnand_pm_ops, .of_match_table = iproc_nand_of_match, } }; module_platform_driver(iproc_nand_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Brian Norris"); MODULE_AUTHOR("Ray Jui"); MODULE_DESCRIPTION("NAND driver for Broadcom IPROC-based SoCs");
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1