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
25struct bcm63138_nand_soc {
26	struct brcmnand_soc soc;
27	void __iomem *base;
28};
29
30#define BCM63138_NAND_INT_STATUS		0x00
31#define BCM63138_NAND_INT_EN			0x04
32
33enum {
34	BCM63138_CTLRDY		= BIT(4),
35};
36
37static bool bcm63138_nand_intc_ack(struct brcmnand_soc *soc)
38{
39	struct bcm63138_nand_soc *priv =
40			container_of(soc, struct bcm63138_nand_soc, soc);
41	void __iomem *mmio = priv->base + BCM63138_NAND_INT_STATUS;
42	u32 val = brcmnand_readl(mmio);
43
44	if (val & BCM63138_CTLRDY) {
45		brcmnand_writel(val & ~BCM63138_CTLRDY, mmio);
46		return true;
47	}
48
49	return false;
50}
51
52static void bcm63138_nand_intc_set(struct brcmnand_soc *soc, bool en)
53{
54	struct bcm63138_nand_soc *priv =
55			container_of(soc, struct bcm63138_nand_soc, soc);
56	void __iomem *mmio = priv->base + BCM63138_NAND_INT_EN;
57	u32 val = brcmnand_readl(mmio);
58
59	if (en)
60		val |= BCM63138_CTLRDY;
61	else
62		val &= ~BCM63138_CTLRDY;
63
64	brcmnand_writel(val, mmio);
65}
66
67static int bcm63138_nand_probe(struct platform_device *pdev)
68{
69	struct device *dev = &pdev->dev;
70	struct bcm63138_nand_soc *priv;
71	struct brcmnand_soc *soc;
72	struct resource *res;
73
74	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
75	if (!priv)
76		return -ENOMEM;
77	soc = &priv->soc;
78
79	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-int-base");
80	priv->base = devm_ioremap_resource(dev, res);
81	if (IS_ERR(priv->base))
82		return PTR_ERR(priv->base);
83
84	soc->ctlrdy_ack = bcm63138_nand_intc_ack;
85	soc->ctlrdy_set_enabled = bcm63138_nand_intc_set;
86
87	return brcmnand_probe(pdev, soc);
88}
89
90static const struct of_device_id bcm63138_nand_of_match[] = {
91	{ .compatible = "brcm,nand-bcm63138" },
92	{},
93};
94MODULE_DEVICE_TABLE(of, bcm63138_nand_of_match);
95
96static struct platform_driver bcm63138_nand_driver = {
97	.probe			= bcm63138_nand_probe,
98	.remove			= brcmnand_remove,
99	.driver = {
100		.name		= "bcm63138_nand",
101		.pm		= &brcmnand_pm_ops,
102		.of_match_table	= bcm63138_nand_of_match,
103	}
104};
105module_platform_driver(bcm63138_nand_driver);
106
107MODULE_LICENSE("GPL v2");
108MODULE_AUTHOR("Brian Norris");
109MODULE_DESCRIPTION("NAND driver for BCM63138");
110