Linux Audio

Check our new training course

Loading...
v5.9
  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#ifdef CONFIG_BCM47XX
 22#include <linux/bcm47xx_nvram.h>
 23#endif
 24
 25enum bcma_boot_dev {
 26	BCMA_BOOT_DEV_UNK = 0,
 27	BCMA_BOOT_DEV_ROM,
 28	BCMA_BOOT_DEV_PARALLEL,
 29	BCMA_BOOT_DEV_SERIAL,
 30	BCMA_BOOT_DEV_NAND,
 
 
 
 
 
 
 
 
 
 31};
 32
 33/* The 47162a0 hangs when reading MIPS DMP registers registers */
 34static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
 35{
 36	return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
 37	       dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
 38}
 39
 40/* The 5357b0 hangs when reading USB20H DMP registers */
 41static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
 42{
 43	return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
 44		dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
 45	       dev->bus->chipinfo.pkg == 11 &&
 46	       dev->id.id == BCMA_CORE_USB20_HOST;
 47}
 48
 49static inline u32 mips_read32(struct bcma_drv_mips *mcore,
 50			      u16 offset)
 51{
 52	return bcma_read32(mcore->core, offset);
 53}
 54
 55static inline void mips_write32(struct bcma_drv_mips *mcore,
 56				u16 offset,
 57				u32 value)
 58{
 59	bcma_write32(mcore->core, offset, value);
 60}
 61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 62static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
 63{
 64	u32 flag;
 65
 66	if (bcma_core_mips_bcm47162a0_quirk(dev))
 67		return dev->core_index;
 68	if (bcma_core_mips_bcm5357b0_quirk(dev))
 69		return dev->core_index;
 70	flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
 71
 72	if (flag)
 73		return flag & 0x1F;
 74	else
 75		return 0x3f;
 76}
 77
 78/* Get the MIPS IRQ assignment for a specified device.
 79 * If unassigned, 0 is returned.
 80 * If disabled, 5 is returned.
 81 * If not supported, 6 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	if (irqflag == 0x3f)
 91		return 6;
 92
 93	for (irq = 0; irq <= 4; irq++)
 94		if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
 95		    (1 << irqflag))
 96			return irq;
 97
 98	return 5;
 99}
100
 
 
 
 
 
 
 
101static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
102{
103	unsigned int oldirq = bcma_core_mips_irq(dev);
104	struct bcma_bus *bus = dev->bus;
105	struct bcma_device *mdev = bus->drv_mips.core;
106	u32 irqflag;
107
108	irqflag = bcma_core_mips_irqflag(dev);
109	BUG_ON(oldirq == 6);
110
111	dev->irq = irq + 2;
112
113	/* clear the old irq */
114	if (oldirq == 0)
115		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
116			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
117			    ~(1 << irqflag));
118	else if (oldirq != 5)
119		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
120
121	/* assign the new one */
122	if (irq == 0) {
123		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
124			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
125			    (1 << irqflag));
126	} else {
127		u32 irqinitmask = bcma_read32(mdev,
128					      BCMA_MIPS_MIPS74K_INTMASK(irq));
129		if (irqinitmask) {
130			struct bcma_device *core;
131
132			/* backplane irq line is in use, find out who uses
133			 * it and set user to irq 0
134			 */
135			list_for_each_entry(core, &bus->cores, list) {
136				if ((1 << bcma_core_mips_irqflag(core)) ==
137				    irqinitmask) {
138					bcma_core_mips_set_irq(core, 0);
139					break;
140				}
141			}
142		}
143		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
144			     1 << irqflag);
145	}
146
147	bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
148		   dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
149}
150
151static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
152					u16 coreid, u8 unit)
153{
154	struct bcma_device *core;
155
156	core = bcma_find_core_unit(bus, coreid, unit);
157	if (!core) {
158		bcma_warn(bus,
159			  "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
160			  coreid, unit);
161		return;
162	}
163
164	bcma_core_mips_set_irq(core, irq);
165}
166
167static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
168{
169	int i;
170	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
171	char interrupts[25];
172	char *ints = interrupts;
173
174	for (i = 0; i < ARRAY_SIZE(irq_name); i++)
175		ints += sprintf(ints, " %s%c",
176				irq_name[i], i == irq ? '*' : ' ');
177
178	bcma_debug(dev->bus, "core 0x%04x, irq:%s\n", dev->id.id, interrupts);
179}
180
181static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
182{
183	struct bcma_device *core;
184
185	list_for_each_entry(core, &bus->cores, list) {
186		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
187	}
188}
189
190u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
191{
192	struct bcma_bus *bus = mcore->core->bus;
193
194	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
195		return bcma_pmu_get_cpu_clock(&bus->drv_cc);
196
197	bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
198	return 0;
199}
200EXPORT_SYMBOL(bcma_cpu_clock);
201
202static enum bcma_boot_dev bcma_boot_dev(struct bcma_bus *bus)
203{
 
204	struct bcma_drv_cc *cc = &bus->drv_cc;
205	u8 cc_rev = cc->core->id.rev;
206
207	if (cc_rev == 42) {
208		struct bcma_device *core;
209
210		core = bcma_find_core(bus, BCMA_CORE_NS_ROM);
211		if (core) {
212			switch (bcma_aread32(core, BCMA_IOST) &
213				BCMA_NS_ROM_IOST_BOOT_DEV_MASK) {
214			case BCMA_NS_ROM_IOST_BOOT_DEV_NOR:
215				return BCMA_BOOT_DEV_SERIAL;
216			case BCMA_NS_ROM_IOST_BOOT_DEV_NAND:
217				return BCMA_BOOT_DEV_NAND;
218			case BCMA_NS_ROM_IOST_BOOT_DEV_ROM:
219			default:
220				return BCMA_BOOT_DEV_ROM;
221			}
222		}
223	} else {
224		if (cc_rev == 38) {
225			if (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)
226				return BCMA_BOOT_DEV_NAND;
227			else if (cc->status & BIT(5))
228				return BCMA_BOOT_DEV_ROM;
229		}
230
231		if ((cc->capabilities & BCMA_CC_CAP_FLASHT) ==
232		    BCMA_CC_FLASHT_PARA)
233			return BCMA_BOOT_DEV_PARALLEL;
234		else
235			return BCMA_BOOT_DEV_SERIAL;
236	}
237
238	return BCMA_BOOT_DEV_SERIAL;
239}
240
241static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore)
242{
243	struct bcma_bus *bus = mcore->core->bus;
244	enum bcma_boot_dev boot_dev;
245
246	/* Determine flash type this SoC boots from */
247	boot_dev = bcma_boot_dev(bus);
248	switch (boot_dev) {
249	case BCMA_BOOT_DEV_PARALLEL:
250	case BCMA_BOOT_DEV_SERIAL:
251#ifdef CONFIG_BCM47XX
252		bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH2,
253					    BCMA_SOC_FLASH2_SZ);
254#endif
255		break;
256	case BCMA_BOOT_DEV_NAND:
257#ifdef CONFIG_BCM47XX
258		bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH1,
259					    BCMA_SOC_FLASH1_SZ);
260#endif
261		break;
262	default:
263		break;
 
 
 
 
 
 
 
 
264	}
265}
266
267void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
268{
269	struct bcma_bus *bus = mcore->core->bus;
270
271	if (mcore->early_setup_done)
272		return;
273
274	bcma_chipco_serial_init(&bus->drv_cc);
275	bcma_core_mips_nvram_init(mcore);
276
277	mcore->early_setup_done = true;
278}
279
280static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
281{
282	struct bcma_device *cpu, *pcie, *i2s;
283
284	/* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
285	 * (IRQ flags > 7 are ignored when setting the interrupt masks)
286	 */
287	if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
288	    bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
289		return;
290
291	cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
292	pcie = bcma_find_core(bus, BCMA_CORE_PCIE);
293	i2s = bcma_find_core(bus, BCMA_CORE_I2S);
294	if (cpu && pcie && i2s &&
295	    bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
296	    bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
297	    bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
298		bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
299		bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
300		bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
301		bcma_debug(bus,
302			   "Moved i2s interrupt to oob line 7 instead of 8\n");
303	}
304}
305
306void bcma_core_mips_init(struct bcma_drv_mips *mcore)
307{
308	struct bcma_bus *bus;
309	struct bcma_device *core;
310	bus = mcore->core->bus;
311
312	if (mcore->setup_done)
313		return;
314
315	bcma_debug(bus, "Initializing MIPS core...\n");
316
317	bcma_core_mips_early_init(mcore);
318
319	bcma_fix_i2s_irqflag(bus);
320
321	switch (bus->chipinfo.id) {
322	case BCMA_CHIP_ID_BCM4716:
323	case BCMA_CHIP_ID_BCM4748:
324		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
325		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
326		bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
327		bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
328		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
329		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
330		break;
331	case BCMA_CHIP_ID_BCM5356:
332	case BCMA_CHIP_ID_BCM47162:
333	case BCMA_CHIP_ID_BCM53572:
334		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
335		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
336		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
337		break;
338	case BCMA_CHIP_ID_BCM5357:
339	case BCMA_CHIP_ID_BCM4749:
340		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
341		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
342		bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
343		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
344		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
345		break;
346	case BCMA_CHIP_ID_BCM4706:
347		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
348		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
349					    0);
350		bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
351		bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
352		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
353					    0);
354		break;
355	default:
356		list_for_each_entry(core, &bus->cores, list) {
357			core->irq = bcma_core_irq(core, 0);
358		}
359		bcma_err(bus,
360			 "Unknown device (0x%x) found, can not configure IRQs\n",
361			 bus->chipinfo.id);
362	}
363	bcma_debug(bus, "IRQ reconfiguration done\n");
364	bcma_core_mips_dump_irq(bus);
365
366	mcore->setup_done = true;
367}
v3.15
  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/mtd/physmap.h>
 18#include <linux/platform_device.h>
 19#include <linux/serial.h>
 20#include <linux/serial_core.h>
 21#include <linux/serial_reg.h>
 22#include <linux/time.h>
 23
 24static const char * const part_probes[] = { "bcm47xxpart", NULL };
 25
 26static struct physmap_flash_data bcma_pflash_data = {
 27	.part_probe_types	= part_probes,
 28};
 29
 30static struct resource bcma_pflash_resource = {
 31	.name	= "bcma_pflash",
 32	.flags  = IORESOURCE_MEM,
 33};
 34
 35struct platform_device bcma_pflash_dev = {
 36	.name		= "physmap-flash",
 37	.dev		= {
 38		.platform_data  = &bcma_pflash_data,
 39	},
 40	.resource	= &bcma_pflash_resource,
 41	.num_resources	= 1,
 42};
 43
 44/* The 47162a0 hangs when reading MIPS DMP registers registers */
 45static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
 46{
 47	return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
 48	       dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
 49}
 50
 51/* The 5357b0 hangs when reading USB20H DMP registers */
 52static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
 53{
 54	return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
 55		dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
 56	       dev->bus->chipinfo.pkg == 11 &&
 57	       dev->id.id == BCMA_CORE_USB20_HOST;
 58}
 59
 60static inline u32 mips_read32(struct bcma_drv_mips *mcore,
 61			      u16 offset)
 62{
 63	return bcma_read32(mcore->core, offset);
 64}
 65
 66static inline void mips_write32(struct bcma_drv_mips *mcore,
 67				u16 offset,
 68				u32 value)
 69{
 70	bcma_write32(mcore->core, offset, value);
 71}
 72
 73static const u32 ipsflag_irq_mask[] = {
 74	0,
 75	BCMA_MIPS_IPSFLAG_IRQ1,
 76	BCMA_MIPS_IPSFLAG_IRQ2,
 77	BCMA_MIPS_IPSFLAG_IRQ3,
 78	BCMA_MIPS_IPSFLAG_IRQ4,
 79};
 80
 81static const u32 ipsflag_irq_shift[] = {
 82	0,
 83	BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
 84	BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
 85	BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
 86	BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
 87};
 88
 89static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
 90{
 91	u32 flag;
 92
 93	if (bcma_core_mips_bcm47162a0_quirk(dev))
 94		return dev->core_index;
 95	if (bcma_core_mips_bcm5357b0_quirk(dev))
 96		return dev->core_index;
 97	flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
 98
 99	if (flag)
100		return flag & 0x1F;
101	else
102		return 0x3f;
103}
104
105/* Get the MIPS IRQ assignment for a specified device.
106 * If unassigned, 0 is returned.
107 * If disabled, 5 is returned.
108 * If not supported, 6 is returned.
109 */
110static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
111{
112	struct bcma_device *mdev = dev->bus->drv_mips.core;
113	u32 irqflag;
114	unsigned int irq;
115
116	irqflag = bcma_core_mips_irqflag(dev);
117	if (irqflag == 0x3f)
118		return 6;
119
120	for (irq = 0; irq <= 4; irq++)
121		if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
122		    (1 << irqflag))
123			return irq;
124
125	return 5;
126}
127
128unsigned int bcma_core_irq(struct bcma_device *dev)
129{
130	unsigned int mips_irq = bcma_core_mips_irq(dev);
131	return mips_irq <= 4 ? mips_irq + 2 : 0;
132}
133EXPORT_SYMBOL(bcma_core_irq);
134
135static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
136{
137	unsigned int oldirq = bcma_core_mips_irq(dev);
138	struct bcma_bus *bus = dev->bus;
139	struct bcma_device *mdev = bus->drv_mips.core;
140	u32 irqflag;
141
142	irqflag = bcma_core_mips_irqflag(dev);
143	BUG_ON(oldirq == 6);
144
145	dev->irq = irq + 2;
146
147	/* clear the old irq */
148	if (oldirq == 0)
149		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
150			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
151			    ~(1 << irqflag));
152	else if (oldirq != 5)
153		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
154
155	/* assign the new one */
156	if (irq == 0) {
157		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
158			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
159			    (1 << irqflag));
160	} else {
161		u32 irqinitmask = bcma_read32(mdev,
162					      BCMA_MIPS_MIPS74K_INTMASK(irq));
163		if (irqinitmask) {
164			struct bcma_device *core;
165
166			/* backplane irq line is in use, find out who uses
167			 * it and set user to irq 0
168			 */
169			list_for_each_entry(core, &bus->cores, list) {
170				if ((1 << bcma_core_mips_irqflag(core)) ==
171				    irqinitmask) {
172					bcma_core_mips_set_irq(core, 0);
173					break;
174				}
175			}
176		}
177		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
178			     1 << irqflag);
179	}
180
181	bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
182		   dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
183}
184
185static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
186					u16 coreid, u8 unit)
187{
188	struct bcma_device *core;
189
190	core = bcma_find_core_unit(bus, coreid, unit);
191	if (!core) {
192		bcma_warn(bus,
193			  "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
194			  coreid, unit);
195		return;
196	}
197
198	bcma_core_mips_set_irq(core, irq);
199}
200
201static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
202{
203	int i;
204	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
205	printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
206	for (i = 0; i <= 6; i++)
207		printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
208	printk("\n");
 
 
 
 
209}
210
211static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
212{
213	struct bcma_device *core;
214
215	list_for_each_entry(core, &bus->cores, list) {
216		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
217	}
218}
219
220u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
221{
222	struct bcma_bus *bus = mcore->core->bus;
223
224	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
225		return bcma_pmu_get_cpu_clock(&bus->drv_cc);
226
227	bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
228	return 0;
229}
230EXPORT_SYMBOL(bcma_cpu_clock);
231
232static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
233{
234	struct bcma_bus *bus = mcore->core->bus;
235	struct bcma_drv_cc *cc = &bus->drv_cc;
236	struct bcma_pflash *pflash = &cc->pflash;
 
 
 
237
238	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
239	case BCMA_CC_FLASHT_STSER:
240	case BCMA_CC_FLASHT_ATSER:
241		bcma_debug(bus, "Found serial flash\n");
242		bcma_sflash_init(cc);
243		break;
244	case BCMA_CC_FLASHT_PARA:
245		bcma_debug(bus, "Found parallel flash\n");
246		pflash->present = true;
247		pflash->window = BCMA_SOC_FLASH2;
248		pflash->window_size = BCMA_SOC_FLASH2_SZ;
249
250		if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
251		     BCMA_CC_FLASH_CFG_DS) == 0)
252			pflash->buswidth = 1;
 
 
 
 
 
 
 
 
 
253		else
254			pflash->buswidth = 2;
 
 
 
 
255
256		bcma_pflash_data.width = pflash->buswidth;
257		bcma_pflash_resource.start = pflash->window;
258		bcma_pflash_resource.end = pflash->window + pflash->window_size;
 
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260		break;
261	default:
262		bcma_err(bus, "Flash type not supported\n");
263	}
264
265	if (cc->core->id.rev == 38 ||
266	    bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
267		if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
268			bcma_debug(bus, "Found NAND flash\n");
269			bcma_nflash_init(cc);
270		}
271	}
272}
273
274void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
275{
276	struct bcma_bus *bus = mcore->core->bus;
277
278	if (mcore->early_setup_done)
279		return;
280
281	bcma_chipco_serial_init(&bus->drv_cc);
282	bcma_core_mips_flash_detect(mcore);
283
284	mcore->early_setup_done = true;
285}
286
287static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
288{
289	struct bcma_device *cpu, *pcie, *i2s;
290
291	/* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
292	 * (IRQ flags > 7 are ignored when setting the interrupt masks)
293	 */
294	if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
295	    bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
296		return;
297
298	cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
299	pcie = bcma_find_core(bus, BCMA_CORE_PCIE);
300	i2s = bcma_find_core(bus, BCMA_CORE_I2S);
301	if (cpu && pcie && i2s &&
302	    bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
303	    bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
304	    bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
305		bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
306		bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
307		bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
308		bcma_debug(bus,
309			   "Moved i2s interrupt to oob line 7 instead of 8\n");
310	}
311}
312
313void bcma_core_mips_init(struct bcma_drv_mips *mcore)
314{
315	struct bcma_bus *bus;
316	struct bcma_device *core;
317	bus = mcore->core->bus;
318
319	if (mcore->setup_done)
320		return;
321
322	bcma_debug(bus, "Initializing MIPS core...\n");
323
324	bcma_core_mips_early_init(mcore);
325
326	bcma_fix_i2s_irqflag(bus);
327
328	switch (bus->chipinfo.id) {
329	case BCMA_CHIP_ID_BCM4716:
330	case BCMA_CHIP_ID_BCM4748:
331		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
332		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
333		bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
334		bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
335		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
336		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
337		break;
338	case BCMA_CHIP_ID_BCM5356:
339	case BCMA_CHIP_ID_BCM47162:
340	case BCMA_CHIP_ID_BCM53572:
341		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
342		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
343		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
344		break;
345	case BCMA_CHIP_ID_BCM5357:
346	case BCMA_CHIP_ID_BCM4749:
347		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
348		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
349		bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
350		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
351		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
352		break;
353	case BCMA_CHIP_ID_BCM4706:
354		bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
355		bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
356					    0);
357		bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
358		bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
359		bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
360					    0);
361		break;
362	default:
363		list_for_each_entry(core, &bus->cores, list) {
364			core->irq = bcma_core_irq(core);
365		}
366		bcma_err(bus,
367			 "Unknown device (0x%x) found, can not configure IRQs\n",
368			 bus->chipinfo.id);
369	}
370	bcma_debug(bus, "IRQ reconfiguration done\n");
371	bcma_core_mips_dump_irq(bus);
372
373	mcore->setup_done = true;
374}