brintos

brintos / linux-shallow public Read only

0
0
Text · 3.7 KiB · bf46c8b Raw
150 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright © 2015 Broadcom Corporation4 */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 17struct 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       0x1026#define IPROC_NAND_CTLR_READY              BIT(0)27 28#define IPROC_NAND_IO_CTRL_OFFSET          0x0029#define IPROC_NAND_APB_LE_MODE             BIT(24)30#define IPROC_NAND_INT_CTRL_READ_ENABLE    BIT(6)31 32static 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 47static 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	else62		val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE;63 64	brcmnand_writel(val, mmio);65 66	spin_unlock_irqrestore(&priv->idm_lock, flags);67}68 69static 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 configure84	 * the APB bus to LE mode before accessing the FIFO and back to BE mode85	 * after the access is done86	 */87	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) || !is_param) {88		if (prepare)89			val |= IPROC_NAND_APB_LE_MODE;90		else91			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 101static 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 107	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);108	if (!priv)109		return -ENOMEM;110	soc = &priv->soc;111 112	spin_lock_init(&priv->idm_lock);113 114	priv->idm_base = devm_platform_ioremap_resource_byname(pdev, "iproc-idm");115	if (IS_ERR(priv->idm_base))116		return PTR_ERR(priv->idm_base);117 118	priv->ext_base = devm_platform_ioremap_resource_byname(pdev, "iproc-ext");119	if (IS_ERR(priv->ext_base))120		return PTR_ERR(priv->ext_base);121 122	soc->ctlrdy_ack = iproc_nand_intc_ack;123	soc->ctlrdy_set_enabled = iproc_nand_intc_set;124	soc->prepare_data_bus = iproc_nand_apb_access;125 126	return brcmnand_probe(pdev, soc);127}128 129static const struct of_device_id iproc_nand_of_match[] = {130	{ .compatible = "brcm,nand-iproc" },131	{},132};133MODULE_DEVICE_TABLE(of, iproc_nand_of_match);134 135static struct platform_driver iproc_nand_driver = {136	.probe			= iproc_nand_probe,137	.remove_new		= brcmnand_remove,138	.driver = {139		.name		= "iproc_nand",140		.pm		= &brcmnand_pm_ops,141		.of_match_table	= iproc_nand_of_match,142	}143};144module_platform_driver(iproc_nand_driver);145 146MODULE_LICENSE("GPL v2");147MODULE_AUTHOR("Brian Norris");148MODULE_AUTHOR("Ray Jui");149MODULE_DESCRIPTION("NAND driver for Broadcom IPROC-based SoCs");150