2 * Copyright 2016 Broadcom Limited
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.
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.
14 #include <linux/device.h>
16 #include <linux/ioport.h>
17 #include <linux/module.h>
19 #include <linux/of_address.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
23 #include "spi-bcm-qspi.h"
25 #define INTR_BASE_BIT_SHIFT 0x02
26 #define INTR_COUNT 0x07
28 struct bcm_iproc_intc
{
29 struct bcm_qspi_soc_intc soc_intc
;
30 struct platform_device
*pdev
;
31 void __iomem
*int_reg
;
32 void __iomem
*int_status_reg
;
37 static u32
bcm_iproc_qspi_get_l2_int_status(struct bcm_qspi_soc_intc
*soc_intc
)
39 struct bcm_iproc_intc
*priv
=
40 container_of(soc_intc
, struct bcm_iproc_intc
, soc_intc
);
41 void __iomem
*mmio
= priv
->int_status_reg
;
45 for (i
= 0; i
< INTR_COUNT
; i
++) {
46 if (bcm_qspi_readl(priv
->big_endian
, mmio
+ (i
* 4)))
50 if (val
& INTR_MSPI_DONE_MASK
)
53 if (val
& BSPI_LR_INTERRUPTS_ALL
)
56 if (val
& BSPI_LR_INTERRUPTS_ERROR
)
62 static void bcm_iproc_qspi_int_ack(struct bcm_qspi_soc_intc
*soc_intc
, int type
)
64 struct bcm_iproc_intc
*priv
=
65 container_of(soc_intc
, struct bcm_iproc_intc
, soc_intc
);
66 void __iomem
*mmio
= priv
->int_status_reg
;
67 u32 mask
= get_qspi_mask(type
);
70 for (i
= 0; i
< INTR_COUNT
; i
++) {
71 if (mask
& (1UL << i
))
72 bcm_qspi_writel(priv
->big_endian
, 1, mmio
+ (i
* 4));
76 static void bcm_iproc_qspi_int_set(struct bcm_qspi_soc_intc
*soc_intc
, int type
,
79 struct bcm_iproc_intc
*priv
=
80 container_of(soc_intc
, struct bcm_iproc_intc
, soc_intc
);
81 void __iomem
*mmio
= priv
->int_reg
;
82 u32 mask
= get_qspi_mask(type
);
86 spin_lock_irqsave(&priv
->soclock
, flags
);
88 val
= bcm_qspi_readl(priv
->big_endian
, mmio
);
91 val
= val
| (mask
<< INTR_BASE_BIT_SHIFT
);
93 val
= val
& ~(mask
<< INTR_BASE_BIT_SHIFT
);
95 bcm_qspi_writel(priv
->big_endian
, val
, mmio
);
97 spin_unlock_irqrestore(&priv
->soclock
, flags
);
100 static int bcm_iproc_probe(struct platform_device
*pdev
)
102 struct device
*dev
= &pdev
->dev
;
103 struct bcm_iproc_intc
*priv
;
104 struct bcm_qspi_soc_intc
*soc_intc
;
105 struct resource
*res
;
107 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
110 soc_intc
= &priv
->soc_intc
;
113 spin_lock_init(&priv
->soclock
);
115 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "intr_regs");
116 priv
->int_reg
= devm_ioremap_resource(dev
, res
);
117 if (IS_ERR(priv
->int_reg
))
118 return PTR_ERR(priv
->int_reg
);
120 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
,
122 priv
->int_status_reg
= devm_ioremap_resource(dev
, res
);
123 if (IS_ERR(priv
->int_status_reg
))
124 return PTR_ERR(priv
->int_status_reg
);
126 priv
->big_endian
= of_device_is_big_endian(dev
->of_node
);
128 bcm_iproc_qspi_int_ack(soc_intc
, MSPI_BSPI_DONE
);
129 bcm_iproc_qspi_int_set(soc_intc
, MSPI_BSPI_DONE
, false);
131 soc_intc
->bcm_qspi_int_ack
= bcm_iproc_qspi_int_ack
;
132 soc_intc
->bcm_qspi_int_set
= bcm_iproc_qspi_int_set
;
133 soc_intc
->bcm_qspi_get_int_status
= bcm_iproc_qspi_get_l2_int_status
;
135 return bcm_qspi_probe(pdev
, soc_intc
);
138 static int bcm_iproc_remove(struct platform_device
*pdev
)
140 return bcm_qspi_remove(pdev
);
143 static const struct of_device_id bcm_iproc_of_match
[] = {
144 { .compatible
= "brcm,spi-nsp-qspi" },
145 { .compatible
= "brcm,spi-ns2-qspi" },
148 MODULE_DEVICE_TABLE(of
, bcm_iproc_of_match
);
150 static struct platform_driver bcm_iproc_driver
= {
151 .probe
= bcm_iproc_probe
,
152 .remove
= bcm_iproc_remove
,
155 .pm
= &bcm_qspi_pm_ops
,
156 .of_match_table
= bcm_iproc_of_match
,
159 module_platform_driver(bcm_iproc_driver
);
161 MODULE_LICENSE("GPL v2");
162 MODULE_AUTHOR("Kamal Dasu");
163 MODULE_DESCRIPTION("SPI flash driver for Broadcom iProc SoCs");