Merge tag 'for-linus-4.6-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.git] / drivers / mtd / nand / brcmnand / iproc_nand.c
CommitLineData
ca22f040
BN
1/*
2 * Copyright © 2015 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/device.h>
15#include <linux/io.h>
16#include <linux/ioport.h>
17#include <linux/module.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22
23#include "brcmnand.h"
24
a86c947b
BN
25struct iproc_nand_soc {
26 struct brcmnand_soc soc;
27
ca22f040
BN
28 void __iomem *idm_base;
29 void __iomem *ext_base;
30 spinlock_t idm_lock;
31};
32
33#define IPROC_NAND_CTLR_READY_OFFSET 0x10
34#define IPROC_NAND_CTLR_READY BIT(0)
35
36#define IPROC_NAND_IO_CTRL_OFFSET 0x00
37#define IPROC_NAND_APB_LE_MODE BIT(24)
38#define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6)
39
40static bool iproc_nand_intc_ack(struct brcmnand_soc *soc)
41{
a86c947b
BN
42 struct iproc_nand_soc *priv =
43 container_of(soc, struct iproc_nand_soc, soc);
ca22f040
BN
44 void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET;
45 u32 val = brcmnand_readl(mmio);
46
47 if (val & IPROC_NAND_CTLR_READY) {
48 brcmnand_writel(IPROC_NAND_CTLR_READY, mmio);
49 return true;
50 }
51
52 return false;
53}
54
55static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)
56{
a86c947b
BN
57 struct iproc_nand_soc *priv =
58 container_of(soc, struct iproc_nand_soc, soc);
ca22f040
BN
59 void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
60 u32 val;
61 unsigned long flags;
62
63 spin_lock_irqsave(&priv->idm_lock, flags);
64
65 val = brcmnand_readl(mmio);
66
67 if (en)
68 val |= IPROC_NAND_INT_CTRL_READ_ENABLE;
69 else
70 val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE;
71
72 brcmnand_writel(val, mmio);
73
74 spin_unlock_irqrestore(&priv->idm_lock, flags);
75}
76
77static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare)
78{
a86c947b
BN
79 struct iproc_nand_soc *priv =
80 container_of(soc, struct iproc_nand_soc, soc);
ca22f040
BN
81 void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
82 u32 val;
83 unsigned long flags;
84
85 spin_lock_irqsave(&priv->idm_lock, flags);
86
87 val = brcmnand_readl(mmio);
88
89 if (prepare)
90 val |= IPROC_NAND_APB_LE_MODE;
91 else
92 val &= ~IPROC_NAND_APB_LE_MODE;
93
94 brcmnand_writel(val, mmio);
95
96 spin_unlock_irqrestore(&priv->idm_lock, flags);
97}
98
99static int iproc_nand_probe(struct platform_device *pdev)
100{
101 struct device *dev = &pdev->dev;
a86c947b 102 struct iproc_nand_soc *priv;
ca22f040
BN
103 struct brcmnand_soc *soc;
104 struct resource *res;
105
ca22f040
BN
106 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
107 if (!priv)
108 return -ENOMEM;
a86c947b 109 soc = &priv->soc;
ca22f040
BN
110
111 spin_lock_init(&priv->idm_lock);
112
113 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-idm");
114 priv->idm_base = devm_ioremap_resource(dev, res);
115 if (IS_ERR(priv->idm_base))
116 return PTR_ERR(priv->idm_base);
117
118 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-ext");
119 priv->ext_base = devm_ioremap_resource(dev, res);
120 if (IS_ERR(priv->ext_base))
121 return PTR_ERR(priv->ext_base);
122
ca22f040
BN
123 soc->ctlrdy_ack = iproc_nand_intc_ack;
124 soc->ctlrdy_set_enabled = iproc_nand_intc_set;
125 soc->prepare_data_bus = iproc_nand_apb_access;
126
127 return brcmnand_probe(pdev, soc);
128}
129
130static const struct of_device_id iproc_nand_of_match[] = {
131 { .compatible = "brcm,nand-iproc" },
132 {},
133};
134MODULE_DEVICE_TABLE(of, iproc_nand_of_match);
135
136static struct platform_driver iproc_nand_driver = {
137 .probe = iproc_nand_probe,
138 .remove = brcmnand_remove,
139 .driver = {
140 .name = "iproc_nand",
141 .pm = &brcmnand_pm_ops,
142 .of_match_table = iproc_nand_of_match,
143 }
144};
145module_platform_driver(iproc_nand_driver);
146
147MODULE_LICENSE("GPL v2");
148MODULE_AUTHOR("Brian Norris");
149MODULE_AUTHOR("Ray Jui");
150MODULE_DESCRIPTION("NAND driver for Broadcom IPROC-based SoCs");
This page took 0.063187 seconds and 5 git commands to generate.