aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2011-07-22 19:20:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-08 14:29:26 -0400
commit21e0534ad7415559bb8dee0dc00e39646fed83c9 (patch)
treee9e082dfdf6ce9798d6201f1ae4109b68b11920a
parentecd177c21640e92b059a71139f5850243a8f0942 (diff)
bcma: add mips driver
This adds a mips driver to bcma. This is only found on embedded devices. For now the driver just initializes the irqs used on this system. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Acked-by: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/bcma/Kconfig9
-rw-r--r--drivers/bcma/Makefile1
-rw-r--r--drivers/bcma/driver_mips.c243
-rw-r--r--drivers/bcma/main.c15
-rw-r--r--include/linux/bcma/bcma.h3
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h13
-rw-r--r--include/linux/bcma/bcma_driver_mips.h49
7 files changed, 333 insertions, 0 deletions
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index 4a062f858e7a..c1172dafdffa 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -35,7 +35,16 @@ config BCMA_DRIVER_PCI_HOSTMODE
35 35
36config BCMA_HOST_SOC 36config BCMA_HOST_SOC
37 bool 37 bool
38 depends on BCMA_DRIVER_MIPS
39
40config BCMA_DRIVER_MIPS
41 bool "BCMA Broadcom MIPS core driver"
38 depends on BCMA && MIPS 42 depends on BCMA && MIPS
43 help
44 Driver for the Broadcom MIPS core attached to Broadcom specific
45 Advanced Microcontroller Bus.
46
47 If unsure, say N
39 48
40config BCMA_DEBUG 49config BCMA_DEBUG
41 bool "BCMA debugging" 50 bool "BCMA debugging"
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 8dc730de7786..82de24e5340c 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -2,6 +2,7 @@ bcma-y += main.o scan.o core.o sprom.o
2bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o 2bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
3bcma-y += driver_pci.o 3bcma-y += driver_pci.o
4bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o 4bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
5bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
5bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o 6bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
6bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o 7bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
7obj-$(CONFIG_BCMA) += bcma.o 8obj-$(CONFIG_BCMA) += bcma.o
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
new file mode 100644
index 000000000000..4b60c9f95839
--- /dev/null
+++ b/drivers/bcma/driver_mips.c
@@ -0,0 +1,243 @@
1/*
2 * Broadcom specific AMBA
3 * Broadcom MIPS32 74K core driver
4 *
5 * Copyright 2009, Broadcom Corporation
6 * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
7 * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
8 * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
9 *
10 * Licensed under the GNU/GPL. See COPYING for details.
11 */
12
13#include "bcma_private.h"
14
15#include <linux/bcma/bcma.h>
16
17#include <linux/serial.h>
18#include <linux/serial_core.h>
19#include <linux/serial_reg.h>
20#include <linux/time.h>
21
22/* The 47162a0 hangs when reading MIPS DMP registers registers */
23static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
24{
25 return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
26 dev->id.id == BCMA_CORE_MIPS_74K;
27}
28
29/* The 5357b0 hangs when reading USB20H DMP registers */
30static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
31{
32 return (dev->bus->chipinfo.id == 0x5357 ||
33 dev->bus->chipinfo.id == 0x4749) &&
34 dev->bus->chipinfo.pkg == 11 &&
35 dev->id.id == BCMA_CORE_USB20_HOST;
36}
37
38static inline u32 mips_read32(struct bcma_drv_mips *mcore,
39 u16 offset)
40{
41 return bcma_read32(mcore->core, offset);
42}
43
44static inline void mips_write32(struct bcma_drv_mips *mcore,
45 u16 offset,
46 u32 value)
47{
48 bcma_write32(mcore->core, offset, value);
49}
50
51static const u32 ipsflag_irq_mask[] = {
52 0,
53 BCMA_MIPS_IPSFLAG_IRQ1,
54 BCMA_MIPS_IPSFLAG_IRQ2,
55 BCMA_MIPS_IPSFLAG_IRQ3,
56 BCMA_MIPS_IPSFLAG_IRQ4,
57};
58
59static const u32 ipsflag_irq_shift[] = {
60 0,
61 BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
62 BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
63 BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
64 BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
65};
66
67static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
68{
69 u32 flag;
70
71 if (bcma_core_mips_bcm47162a0_quirk(dev))
72 return dev->core_index;
73 if (bcma_core_mips_bcm5357b0_quirk(dev))
74 return dev->core_index;
75 flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
76
77 return flag & 0x1F;
78}
79
80/* Get the MIPS IRQ assignment for a specified device.
81 * If unassigned, 0 is returned.
82 */
83unsigned int bcma_core_mips_irq(struct bcma_device *dev)
84{
85 struct bcma_device *mdev = dev->bus->drv_mips.core;
86 u32 irqflag;
87 unsigned int irq;
88
89 irqflag = bcma_core_mips_irqflag(dev);
90
91 for (irq = 1; irq <= 4; irq++)
92 if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
93 (1 << irqflag))
94 return irq;
95
96 return 0;
97}
98EXPORT_SYMBOL(bcma_core_mips_irq);
99
100static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
101{
102 unsigned int oldirq = bcma_core_mips_irq(dev);
103 struct bcma_bus *bus = dev->bus;
104 struct bcma_device *mdev = bus->drv_mips.core;
105 u32 irqflag;
106
107 irqflag = bcma_core_mips_irqflag(dev);
108 BUG_ON(oldirq == 6);
109
110 dev->irq = irq + 2;
111
112 /* clear the old irq */
113 if (oldirq == 0)
114 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
115 bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
116 ~(1 << irqflag));
117 else
118 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
119
120 /* assign the new one */
121 if (irq == 0) {
122 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
123 bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
124 (1 << irqflag));
125 } else {
126 u32 oldirqflag = bcma_read32(mdev,
127 BCMA_MIPS_MIPS74K_INTMASK(irq));
128 if (oldirqflag) {
129 struct bcma_device *core;
130
131 /* backplane irq line is in use, find out who uses
132 * it and set user to irq 0
133 */
134 list_for_each_entry_reverse(core, &bus->cores, list) {
135 if ((1 << bcma_core_mips_irqflag(core)) ==
136 oldirqflag) {
137 bcma_core_mips_set_irq(core, 0);
138 break;
139 }
140 }
141 }
142 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
143 1 << irqflag);
144 }
145
146 pr_info("set_irq: core 0x%04x, irq %d => %d\n",
147 dev->id.id, oldirq + 2, irq + 2);
148}
149
150static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
151{
152 int i;
153 static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
154 printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
155 for (i = 0; i <= 6; i++)
156 printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
157 printk("\n");
158}
159
160static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
161{
162 struct bcma_device *core;
163
164 list_for_each_entry_reverse(core, &bus->cores, list) {
165 bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
166 }
167}
168
169static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
170{
171 struct bcma_bus *bus = mcore->core->bus;
172
173 switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
174 case BCMA_CC_FLASHT_STSER:
175 case BCMA_CC_FLASHT_ATSER:
176 pr_err("Serial flash not supported.\n");
177 break;
178 case BCMA_CC_FLASHT_PARA:
179 pr_info("found parallel flash.\n");
180 bus->drv_cc.pflash.window = 0x1c000000;
181 bus->drv_cc.pflash.window_size = 0x02000000;
182
183 if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
184 BCMA_CC_FLASH_CFG_DS) == 0)
185 bus->drv_cc.pflash.buswidth = 1;
186 else
187 bus->drv_cc.pflash.buswidth = 2;
188 break;
189 default:
190 pr_err("flash not supported.\n");
191 }
192}
193
194void bcma_core_mips_init(struct bcma_drv_mips *mcore)
195{
196 struct bcma_bus *bus;
197 struct bcma_device *core;
198 bus = mcore->core->bus;
199
200 pr_info("Initializing MIPS core...\n");
201
202 if (!mcore->setup_done)
203 mcore->assigned_irqs = 1;
204
205 /* Assign IRQs to all cores on the bus */
206 list_for_each_entry_reverse(core, &bus->cores, list) {
207 int mips_irq;
208 if (core->irq)
209 continue;
210
211 mips_irq = bcma_core_mips_irq(core);
212 if (mips_irq > 4)
213 core->irq = 0;
214 else
215 core->irq = mips_irq + 2;
216 if (core->irq > 5)
217 continue;
218 switch (core->id.id) {
219 case BCMA_CORE_PCI:
220 case BCMA_CORE_PCIE:
221 case BCMA_CORE_ETHERNET:
222 case BCMA_CORE_ETHERNET_GBIT:
223 case BCMA_CORE_MAC_GBIT:
224 case BCMA_CORE_80211:
225 case BCMA_CORE_USB20_HOST:
226 /* These devices get their own IRQ line if available,
227 * the rest goes on IRQ0
228 */
229 if (mcore->assigned_irqs <= 4)
230 bcma_core_mips_set_irq(core,
231 mcore->assigned_irqs++);
232 break;
233 }
234 }
235 pr_info("IRQ reconfiguration done\n");
236 bcma_core_mips_dump_irq(bus);
237
238 if (mcore->setup_done)
239 return;
240
241 bcma_core_mips_flash_detect(mcore);
242 mcore->setup_done = true;
243}
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 2648522432be..7072216a2a3f 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -84,6 +84,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
84 case BCMA_CORE_CHIPCOMMON: 84 case BCMA_CORE_CHIPCOMMON:
85 case BCMA_CORE_PCI: 85 case BCMA_CORE_PCI:
86 case BCMA_CORE_PCIE: 86 case BCMA_CORE_PCIE:
87 case BCMA_CORE_MIPS_74K:
87 continue; 88 continue;
88 } 89 }
89 90
@@ -147,6 +148,13 @@ int bcma_bus_register(struct bcma_bus *bus)
147 bcma_core_chipcommon_init(&bus->drv_cc); 148 bcma_core_chipcommon_init(&bus->drv_cc);
148 } 149 }
149 150
151 /* Init MIPS core */
152 core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
153 if (core) {
154 bus->drv_mips.core = core;
155 bcma_core_mips_init(&bus->drv_mips);
156 }
157
150 /* Init PCIE core */ 158 /* Init PCIE core */
151 core = bcma_find_core(bus, BCMA_CORE_PCIE); 159 core = bcma_find_core(bus, BCMA_CORE_PCIE);
152 if (core) { 160 if (core) {
@@ -217,6 +225,13 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
217 bcma_core_chipcommon_init(&bus->drv_cc); 225 bcma_core_chipcommon_init(&bus->drv_cc);
218 } 226 }
219 227
228 /* Init MIPS core */
229 core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
230 if (core) {
231 bus->drv_mips.core = core;
232 bcma_core_mips_init(&bus->drv_mips);
233 }
234
220 pr_info("Early bus registered\n"); 235 pr_info("Early bus registered\n");
221 236
222 return 0; 237 return 0;
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index c70cec59d80e..5dbd7055cb86 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -6,6 +6,7 @@
6 6
7#include <linux/bcma/bcma_driver_chipcommon.h> 7#include <linux/bcma/bcma_driver_chipcommon.h>
8#include <linux/bcma/bcma_driver_pci.h> 8#include <linux/bcma/bcma_driver_pci.h>
9#include <linux/bcma/bcma_driver_mips.h>
9#include <linux/ssb/ssb.h> /* SPROM sharing */ 10#include <linux/ssb/ssb.h> /* SPROM sharing */
10 11
11#include "bcma_regs.h" 12#include "bcma_regs.h"
@@ -130,6 +131,7 @@ struct bcma_device {
130 131
131 struct device dev; 132 struct device dev;
132 struct device *dma_dev; 133 struct device *dma_dev;
134
133 unsigned int irq; 135 unsigned int irq;
134 bool dev_registered; 136 bool dev_registered;
135 137
@@ -197,6 +199,7 @@ struct bcma_bus {
197 199
198 struct bcma_drv_cc drv_cc; 200 struct bcma_drv_cc drv_cc;
199 struct bcma_drv_pci drv_pci; 201 struct bcma_drv_pci drv_pci;
202 struct bcma_drv_mips drv_mips;
200 203
201 /* We decided to share SPROM struct with SSB as long as we do not need 204 /* We decided to share SPROM struct with SSB as long as we do not need
202 * any hacks for BCMA. This simplifies drivers code. */ 205 * any hacks for BCMA. This simplifies drivers code. */
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index c8b4cf7f9fae..03cde8d22e5f 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -24,6 +24,7 @@
24#define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */ 24#define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */
25#define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */ 25#define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */
26#define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */ 26#define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */
27#define BCMA_CC_FLASHT_NFLASH 0x00000200
27#define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */ 28#define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */
28#define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */ 29#define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */
29#define BCMA_PLLTYPE_NONE 0x00000000 30#define BCMA_PLLTYPE_NONE 0x00000000
@@ -178,6 +179,7 @@
178#define BCMA_CC_PROG_CFG 0x0120 179#define BCMA_CC_PROG_CFG 0x0120
179#define BCMA_CC_PROG_WAITCNT 0x0124 180#define BCMA_CC_PROG_WAITCNT 0x0124
180#define BCMA_CC_FLASH_CFG 0x0128 181#define BCMA_CC_FLASH_CFG 0x0128
182#define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
181#define BCMA_CC_FLASH_WAITCNT 0x012C 183#define BCMA_CC_FLASH_WAITCNT 0x012C
182/* 0x1E0 is defined as shared BCMA_CLKCTLST */ 184/* 0x1E0 is defined as shared BCMA_CLKCTLST */
183#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ 185#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
@@ -247,6 +249,14 @@ struct bcma_chipcommon_pmu {
247 u32 crystalfreq; /* The active crystal frequency (in kHz) */ 249 u32 crystalfreq; /* The active crystal frequency (in kHz) */
248}; 250};
249 251
252#ifdef CONFIG_BCMA_DRIVER_MIPS
253struct bcma_pflash {
254 u8 buswidth;
255 u32 window;
256 u32 window_size;
257};
258#endif /* CONFIG_BCMA_DRIVER_MIPS */
259
250struct bcma_drv_cc { 260struct bcma_drv_cc {
251 struct bcma_device *core; 261 struct bcma_device *core;
252 u32 status; 262 u32 status;
@@ -256,6 +266,9 @@ struct bcma_drv_cc {
256 /* Fast Powerup Delay constant */ 266 /* Fast Powerup Delay constant */
257 u16 fast_pwrup_delay; 267 u16 fast_pwrup_delay;
258 struct bcma_chipcommon_pmu pmu; 268 struct bcma_chipcommon_pmu pmu;
269#ifdef CONFIG_BCMA_DRIVER_MIPS
270 struct bcma_pflash pflash;
271#endif /* CONFIG_BCMA_DRIVER_MIPS */
259}; 272};
260 273
261/* Register access */ 274/* Register access */
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h
new file mode 100644
index 000000000000..82b3bfd32c76
--- /dev/null
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -0,0 +1,49 @@
1#ifndef LINUX_BCMA_DRIVER_MIPS_H_
2#define LINUX_BCMA_DRIVER_MIPS_H_
3
4#define BCMA_MIPS_IPSFLAG 0x0F08
5/* which sbflags get routed to mips interrupt 1 */
6#define BCMA_MIPS_IPSFLAG_IRQ1 0x0000003F
7#define BCMA_MIPS_IPSFLAG_IRQ1_SHIFT 0
8/* which sbflags get routed to mips interrupt 2 */
9#define BCMA_MIPS_IPSFLAG_IRQ2 0x00003F00
10#define BCMA_MIPS_IPSFLAG_IRQ2_SHIFT 8
11/* which sbflags get routed to mips interrupt 3 */
12#define BCMA_MIPS_IPSFLAG_IRQ3 0x003F0000
13#define BCMA_MIPS_IPSFLAG_IRQ3_SHIFT 16
14/* which sbflags get routed to mips interrupt 4 */
15#define BCMA_MIPS_IPSFLAG_IRQ4 0x3F000000
16#define BCMA_MIPS_IPSFLAG_IRQ4_SHIFT 24
17
18/* MIPS 74K core registers */
19#define BCMA_MIPS_MIPS74K_CORECTL 0x0000
20#define BCMA_MIPS_MIPS74K_EXCEPTBASE 0x0004
21#define BCMA_MIPS_MIPS74K_BIST 0x000C
22#define BCMA_MIPS_MIPS74K_INTMASK_INT0 0x0014
23#define BCMA_MIPS_MIPS74K_INTMASK(int) \
24 ((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0)
25#define BCMA_MIPS_MIPS74K_NMIMASK 0x002C
26#define BCMA_MIPS_MIPS74K_GPIOSEL 0x0040
27#define BCMA_MIPS_MIPS74K_GPIOOUT 0x0044
28#define BCMA_MIPS_MIPS74K_GPIOEN 0x0048
29#define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0
30
31#define BCMA_MIPS_OOBSELOUTA30 0x100
32
33struct bcma_device;
34
35struct bcma_drv_mips {
36 struct bcma_device *core;
37 u8 setup_done:1;
38 unsigned int assigned_irqs;
39};
40
41#ifdef CONFIG_BCMA_DRIVER_MIPS
42extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
43#else
44static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
45#endif
46
47extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
48
49#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */