2 * Sonics Silicon Backplane
3 * Broadcom MIPS core driver
5 * Copyright 2005, Broadcom Corporation
6 * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
8 * Licensed under the GNU/GPL. See COPYING for details.
11 #include <linux/ssb/ssb.h>
13 #include <linux/serial.h>
14 #include <linux/serial_core.h>
15 #include <linux/serial_reg.h>
18 #include "ssb_private.h"
21 static inline u32
mips_read32(struct ssb_mipscore
*mcore
,
24 return ssb_read32(mcore
->dev
, offset
);
27 static inline void mips_write32(struct ssb_mipscore
*mcore
,
31 ssb_write32(mcore
->dev
, offset
, value
);
34 static const u32 ipsflag_irq_mask
[] = {
42 static const u32 ipsflag_irq_shift
[] = {
44 SSB_IPSFLAG_IRQ1_SHIFT
,
45 SSB_IPSFLAG_IRQ2_SHIFT
,
46 SSB_IPSFLAG_IRQ3_SHIFT
,
47 SSB_IPSFLAG_IRQ4_SHIFT
,
50 static inline u32
ssb_irqflag(struct ssb_device
*dev
)
52 return ssb_read32(dev
, SSB_TPSFLAG
) & SSB_TPSFLAG_BPFLAG
;
55 /* Get the MIPS IRQ assignment for a specified device.
56 * If unassigned, 0 is returned.
58 unsigned int ssb_mips_irq(struct ssb_device
*dev
)
60 struct ssb_bus
*bus
= dev
->bus
;
66 irqflag
= ssb_irqflag(dev
);
67 ipsflag
= ssb_read32(bus
->mipscore
.dev
, SSB_IPSFLAG
);
68 for (irq
= 1; irq
<= 4; irq
++) {
69 tmp
= ((ipsflag
& ipsflag_irq_mask
[irq
]) >> ipsflag_irq_shift
[irq
]);
79 static void clear_irq(struct ssb_bus
*bus
, unsigned int irq
)
81 struct ssb_device
*dev
= bus
->mipscore
.dev
;
83 /* Clear the IRQ in the MIPScore backplane registers */
85 ssb_write32(dev
, SSB_INTVEC
, 0);
87 ssb_write32(dev
, SSB_IPSFLAG
,
88 ssb_read32(dev
, SSB_IPSFLAG
) |
89 ipsflag_irq_mask
[irq
]);
93 static void set_irq(struct ssb_device
*dev
, unsigned int irq
)
95 unsigned int oldirq
= ssb_mips_irq(dev
);
96 struct ssb_bus
*bus
= dev
->bus
;
97 struct ssb_device
*mdev
= bus
->mipscore
.dev
;
98 u32 irqflag
= ssb_irqflag(dev
);
102 ssb_dprintk(KERN_INFO PFX
103 "set_irq: core 0x%04x, irq %d => %d\n",
104 dev
->id
.coreid
, oldirq
, irq
);
105 /* clear the old irq */
107 ssb_write32(mdev
, SSB_INTVEC
, (~(1 << irqflag
) & ssb_read32(mdev
, SSB_INTVEC
)));
109 clear_irq(bus
, oldirq
);
111 /* assign the new one */
113 ssb_write32(mdev
, SSB_INTVEC
, ((1 << irqflag
) & ssb_read32(mdev
, SSB_INTVEC
)));
115 irqflag
<<= ipsflag_irq_shift
[irq
];
116 irqflag
|= (ssb_read32(mdev
, SSB_IPSFLAG
) & ~ipsflag_irq_mask
[irq
]);
117 ssb_write32(mdev
, SSB_IPSFLAG
, irqflag
);
120 /* XXX: leave here or move into separate extif driver? */
121 static int ssb_extif_serial_init(struct ssb_device
*dev
, struct ssb_serial_ports
*ports
)
127 static void ssb_mips_serial_init(struct ssb_mipscore
*mcore
)
129 struct ssb_bus
*bus
= mcore
->dev
->bus
;
131 //TODO if (EXTIF available
133 extifregs_t
*eir
= (extifregs_t
*) regs
;
136 /* Determine external UART register base */
137 sb
= (sbconfig_t
*)((ulong
) eir
+ SBCONFIGOFF
);
138 base
= EXTIF_CFGIF_BASE(sb_base(R_REG(&sb
->sbadmatch1
)));
143 /* Disable GPIO interrupt initially */
144 W_REG(&eir
->gpiointpolarity
, 0);
145 W_REG(&eir
->gpiointmask
, 0);
147 /* Search for external UARTs */
149 for (i
= 0; i
< 2; i
++) {
150 regs
= (void *) REG_MAP(base
+ (i
* 8), 8);
151 if (BCMINIT(serial_exists
)(regs
)) {
152 /* Set GPIO 1 to be the external UART IRQ */
153 W_REG(&eir
->gpiointmask
, 2);
155 add(regs
, irq
, 13500000, 0);
159 /* Add internal UART if enabled */
160 if (R_REG(&eir
->corecontrol
) & CC_UE
)
162 add((void *) &eir
->uartdata
, irq
, sb_clock(sbh
), 2);
166 mcore
->nr_serial_ports
= ssb_extif_serial_init(&bus
->extif
, mcore
->serial_ports
);
167 else if (bus
->chipco
.dev
)
168 mcore
->nr_serial_ports
= ssb_chipco_serial_init(&bus
->chipco
, mcore
->serial_ports
);
170 mcore
->nr_serial_ports
= 0;
173 static void ssb_mips_flash_detect(struct ssb_mipscore
*mcore
)
175 struct ssb_bus
*bus
= mcore
->dev
->bus
;
177 if (bus
->chipco
.dev
) {
178 mcore
->flash_window
= 0x1c000000;
179 mcore
->flash_window_size
= 0x800000;
181 mcore
->flash_window
= 0x1fc00000;
182 mcore
->flash_window_size
= 0x400000;
187 static void ssb_cpu_clock(struct ssb_mipscore
*mcore
)
191 void ssb_mipscore_init(struct ssb_mipscore
*mcore
)
193 struct ssb_bus
*bus
= mcore
->dev
->bus
;
194 struct ssb_device
*dev
;
195 unsigned long hz
, ns
;
199 return; /* We don't have a MIPS core */
201 ssb_dprintk(KERN_INFO PFX
"Initializing MIPS core...\n");
203 hz
= ssb_clockspeed(bus
);
206 ns
= 1000000000 / hz
;
211 /* Initialize extif so we can get to the LEDs and external UART */
212 W_REG(&eir
->prog_config
, CF_EN
);
214 /* Set timing for the flash */
215 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
216 tmp
= tmp
| (CEIL(40, ns
) << FW_W1_SHIFT
); /* W1 = 40nS */
217 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
218 W_REG(&eir
->prog_waitcount
, tmp
); /* 0x01020a0c for a 100Mhz clock */
220 /* Set programmable interface timing for external uart */
221 tmp
= CEIL(10, ns
) << FW_W3_SHIFT
; /* W3 = 10nS */
222 tmp
= tmp
| (CEIL(20, ns
) << FW_W2_SHIFT
); /* W2 = 20nS */
223 tmp
= tmp
| (CEIL(100, ns
) << FW_W1_SHIFT
); /* W1 = 100nS */
224 tmp
= tmp
| CEIL(120, ns
); /* W0 = 120nS */
225 W_REG(&eir
->prog_waitcount
, tmp
);
230 ssb_chipco_timing_init(&bus
->chipco
, ns
);
232 /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
233 for (irq
= 2, i
= 0; i
< bus
->nr_devices
; i
++) {
234 dev
= &(bus
->devices
[i
]);
235 dev
->irq
= ssb_mips_irq(dev
) + 2;
236 switch(dev
->id
.coreid
) {
237 case SSB_DEV_USB11_HOST
:
238 /* shouldn't need a separate irq line for non-4710, most of them have a proper
239 * external usb controller on the pci */
240 if ((bus
->chip_id
== 0x4710) && (irq
<= 4)) {
245 case SSB_DEV_ETHERNET
:
247 case SSB_DEV_USB20_HOST
:
248 /* These devices get their own IRQ line if available, the rest goes on IRQ0 */
256 ssb_mips_serial_init(mcore
);
257 ssb_mips_flash_detect(mcore
);
This page took 0.066374 seconds and 5 git commands to generate.