2 * Broadcom specific AMBA
3 * Broadcom MIPS32 74K core driver
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>
10 * Licensed under the GNU/GPL. See COPYING for details.
13 #include "bcma_private.h"
15 #include <linux/bcma/bcma.h>
17 #include <linux/serial.h>
18 #include <linux/serial_core.h>
19 #include <linux/serial_reg.h>
20 #include <linux/time.h>
22 /* The 47162a0 hangs when reading MIPS DMP registers registers */
23 static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device
*dev
)
25 return dev
->bus
->chipinfo
.id
== BCMA_CHIP_ID_BCM47162
&&
26 dev
->bus
->chipinfo
.rev
== 0 && dev
->id
.id
== BCMA_CORE_MIPS_74K
;
29 /* The 5357b0 hangs when reading USB20H DMP registers */
30 static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device
*dev
)
32 return (dev
->bus
->chipinfo
.id
== BCMA_CHIP_ID_BCM5357
||
33 dev
->bus
->chipinfo
.id
== BCMA_CHIP_ID_BCM4749
) &&
34 dev
->bus
->chipinfo
.pkg
== 11 &&
35 dev
->id
.id
== BCMA_CORE_USB20_HOST
;
38 static inline u32
mips_read32(struct bcma_drv_mips
*mcore
,
41 return bcma_read32(mcore
->core
, offset
);
44 static inline void mips_write32(struct bcma_drv_mips
*mcore
,
48 bcma_write32(mcore
->core
, offset
, value
);
51 static const u32 ipsflag_irq_mask
[] = {
53 BCMA_MIPS_IPSFLAG_IRQ1
,
54 BCMA_MIPS_IPSFLAG_IRQ2
,
55 BCMA_MIPS_IPSFLAG_IRQ3
,
56 BCMA_MIPS_IPSFLAG_IRQ4
,
59 static const u32 ipsflag_irq_shift
[] = {
61 BCMA_MIPS_IPSFLAG_IRQ1_SHIFT
,
62 BCMA_MIPS_IPSFLAG_IRQ2_SHIFT
,
63 BCMA_MIPS_IPSFLAG_IRQ3_SHIFT
,
64 BCMA_MIPS_IPSFLAG_IRQ4_SHIFT
,
67 static u32
bcma_core_mips_irqflag(struct bcma_device
*dev
)
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
);
80 /* Get the MIPS IRQ assignment for a specified device.
81 * If unassigned, 0 is returned.
83 unsigned int bcma_core_mips_irq(struct bcma_device
*dev
)
85 struct bcma_device
*mdev
= dev
->bus
->drv_mips
.core
;
89 irqflag
= bcma_core_mips_irqflag(dev
);
91 for (irq
= 1; irq
<= 4; irq
++)
92 if (bcma_read32(mdev
, BCMA_MIPS_MIPS74K_INTMASK(irq
)) &
98 EXPORT_SYMBOL(bcma_core_mips_irq
);
100 static void bcma_core_mips_set_irq(struct bcma_device
*dev
, unsigned int irq
)
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
;
107 irqflag
= bcma_core_mips_irqflag(dev
);
112 /* clear the old irq */
114 bcma_write32(mdev
, BCMA_MIPS_MIPS74K_INTMASK(0),
115 bcma_read32(mdev
, BCMA_MIPS_MIPS74K_INTMASK(0)) &
118 bcma_write32(mdev
, BCMA_MIPS_MIPS74K_INTMASK(irq
), 0);
120 /* assign the new one */
122 bcma_write32(mdev
, BCMA_MIPS_MIPS74K_INTMASK(0),
123 bcma_read32(mdev
, BCMA_MIPS_MIPS74K_INTMASK(0)) |
126 u32 oldirqflag
= bcma_read32(mdev
,
127 BCMA_MIPS_MIPS74K_INTMASK(irq
));
129 struct bcma_device
*core
;
131 /* backplane irq line is in use, find out who uses
132 * it and set user to irq 0
134 list_for_each_entry(core
, &bus
->cores
, list
) {
135 if ((1 << bcma_core_mips_irqflag(core
)) ==
137 bcma_core_mips_set_irq(core
, 0);
142 bcma_write32(mdev
, BCMA_MIPS_MIPS74K_INTMASK(irq
),
146 bcma_info(bus
, "set_irq: core 0x%04x, irq %d => %d\n",
147 dev
->id
.id
, oldirq
+ 2, irq
+ 2);
150 static void bcma_core_mips_print_irq(struct bcma_device
*dev
, unsigned int irq
)
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
? "*" : " ");
160 static void bcma_core_mips_dump_irq(struct bcma_bus
*bus
)
162 struct bcma_device
*core
;
164 list_for_each_entry(core
, &bus
->cores
, list
) {
165 bcma_core_mips_print_irq(core
, bcma_core_mips_irq(core
));
169 u32
bcma_cpu_clock(struct bcma_drv_mips
*mcore
)
171 struct bcma_bus
*bus
= mcore
->core
->bus
;
173 if (bus
->drv_cc
.capabilities
& BCMA_CC_CAP_PMU
)
174 return bcma_pmu_get_clockcpu(&bus
->drv_cc
);
176 bcma_err(bus
, "No PMU available, need this to get the cpu clock\n");
179 EXPORT_SYMBOL(bcma_cpu_clock
);
181 static void bcma_core_mips_flash_detect(struct bcma_drv_mips
*mcore
)
183 struct bcma_bus
*bus
= mcore
->core
->bus
;
185 switch (bus
->drv_cc
.capabilities
& BCMA_CC_CAP_FLASHT
) {
186 case BCMA_CC_FLASHT_STSER
:
187 case BCMA_CC_FLASHT_ATSER
:
188 bcma_debug(bus
, "Found serial flash\n");
189 bcma_sflash_init(&bus
->drv_cc
);
191 case BCMA_CC_FLASHT_PARA
:
192 bcma_debug(bus
, "Found parallel flash\n");
193 bus
->drv_cc
.pflash
.window
= 0x1c000000;
194 bus
->drv_cc
.pflash
.window_size
= 0x02000000;
196 if ((bcma_read32(bus
->drv_cc
.core
, BCMA_CC_FLASH_CFG
) &
197 BCMA_CC_FLASH_CFG_DS
) == 0)
198 bus
->drv_cc
.pflash
.buswidth
= 1;
200 bus
->drv_cc
.pflash
.buswidth
= 2;
203 bcma_err(bus
, "Flash type not supported\n");
206 if (bus
->drv_cc
.core
->id
.rev
== 38 ||
207 bus
->chipinfo
.id
== BCMA_CHIP_ID_BCM4706
) {
208 if (bus
->drv_cc
.capabilities
& BCMA_CC_CAP_NFLASH
) {
209 bcma_debug(bus
, "Found NAND flash\n");
210 bcma_nflash_init(&bus
->drv_cc
);
215 void bcma_core_mips_init(struct bcma_drv_mips
*mcore
)
217 struct bcma_bus
*bus
;
218 struct bcma_device
*core
;
219 bus
= mcore
->core
->bus
;
221 bcma_info(bus
, "Initializing MIPS core...\n");
223 if (!mcore
->setup_done
)
224 mcore
->assigned_irqs
= 1;
226 /* Assign IRQs to all cores on the bus */
227 list_for_each_entry(core
, &bus
->cores
, list
) {
232 mips_irq
= bcma_core_mips_irq(core
);
236 core
->irq
= mips_irq
+ 2;
239 switch (core
->id
.id
) {
242 case BCMA_CORE_ETHERNET
:
243 case BCMA_CORE_ETHERNET_GBIT
:
244 case BCMA_CORE_MAC_GBIT
:
245 case BCMA_CORE_80211
:
246 case BCMA_CORE_USB20_HOST
:
247 /* These devices get their own IRQ line if available,
248 * the rest goes on IRQ0
250 if (mcore
->assigned_irqs
<= 4)
251 bcma_core_mips_set_irq(core
,
252 mcore
->assigned_irqs
++);
256 bcma_info(bus
, "IRQ reconfiguration done\n");
257 bcma_core_mips_dump_irq(bus
);
259 if (mcore
->setup_done
)
262 bcma_chipco_serial_init(&bus
->drv_cc
);
263 bcma_core_mips_flash_detect(mcore
);
264 mcore
->setup_done
= true;