brcm47xx: add initial support for devices with bcma bus.

Ethernet and wifi are not working and this is highly experimental.

SVN-Revision: 27301
lede-17.01
Hauke Mehrtens 2011-06-28 22:21:57 +00:00
parent 3f0eed15a2
commit 4c18da3df6
25 changed files with 3366 additions and 189 deletions

View File

@ -149,9 +149,9 @@ static void __init bcm4780_init(void) {
/* Enables GPIO 3 that controls HDD and led power on ASUS WL-700gE */ /* Enables GPIO 3 that controls HDD and led power on ASUS WL-700gE */
printk(MODULE_NAME ": Spinning up HDD and enabling leds\n"); printk(MODULE_NAME ": Spinning up HDD and enabling leds\n");
gpio_outen(pin, pin); ssb_gpio_outen(&ssb_bcm47xx, pin, pin);
gpio_control(pin, 0); ssb_gpio_control(&ssb_bcm47xx, pin, 0);
gpio_out(pin, pin); ssb_gpio_out(&ssb_bcm47xx, pin, pin);
/* Wait 5s, so the HDD can spin up */ /* Wait 5s, so the HDD can spin up */
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
@ -161,14 +161,14 @@ static void __init bcm4780_init(void) {
static void __init NetCenter_init(void) { static void __init NetCenter_init(void) {
/* unset pin 6 (+12V) */ /* unset pin 6 (+12V) */
int pin = 1 << 6; int pin = 1 << 6;
gpio_outen(pin, pin); ssb_gpio_outen(&ssb_bcm47xx, pin, pin);
gpio_control(pin, 0); ssb_gpio_control(&ssb_bcm47xx, pin, 0);
gpio_out(pin, pin); ssb_gpio_out(&ssb_bcm47xx, pin, pin);
/* unset pin 1 (turn off red led, blue will light alone if +5V comes up) */ /* unset pin 1 (turn off red led, blue will light alone if +5V comes up) */
pin = 1 << 1; pin = 1 << 1;
gpio_outen(pin, pin); ssb_gpio_outen(&ssb_bcm47xx, pin, pin);
gpio_control(pin, 0); ssb_gpio_control(&ssb_bcm47xx, pin, 0);
gpio_out(pin, pin); ssb_gpio_out(&ssb_bcm47xx, pin, pin);
/* unset pin 3 (+5V) and wait 5 seconds (harddisk spin up) */ /* unset pin 3 (+5V) and wait 5 seconds (harddisk spin up) */
bcm4780_init(); bcm4780_init();
} }
@ -177,9 +177,9 @@ static void __init bcm57xx_init(void) {
int pin = 1 << 2; int pin = 1 << 2;
/* FIXME: switch comes up, but port mappings/vlans not right */ /* FIXME: switch comes up, but port mappings/vlans not right */
gpio_outen(pin, pin); ssb_gpio_outen(&ssb_bcm47xx, pin, pin);
gpio_control(pin, 0); ssb_gpio_control(&ssb_bcm47xx, pin, 0);
gpio_out(pin, pin); ssb_gpio_out(&ssb_bcm47xx, pin, pin);
} }
static struct platform_t __initdata platforms[] = { static struct platform_t __initdata platforms[] = {
@ -1166,18 +1166,18 @@ static void register_buttons(struct button_t *b)
platform.button_mask &= ~gpiomask; platform.button_mask &= ~gpiomask;
gpio_outen(platform.button_mask, 0); ssb_gpio_outen(&ssb_bcm47xx, platform.button_mask, 0);
gpio_control(platform.button_mask, 0); ssb_gpio_control(&ssb_bcm47xx, platform.button_mask, 0);
platform.button_polarity = gpio_in() & platform.button_mask; platform.button_polarity = ssb_gpio_in(&ssb_bcm47xx, ~0) & platform.button_mask;
gpio_intpolarity(platform.button_mask, platform.button_polarity); ssb_gpio_polarity(&ssb_bcm47xx, platform.button_mask, platform.button_polarity);
gpio_setintmask(platform.button_mask, platform.button_mask); ssb_gpio_intmask(&ssb_bcm47xx, platform.button_mask, platform.button_mask);
gpio_set_irqenable(1, button_handler); gpio_set_irqenable(1, button_handler);
} }
static void unregister_buttons(struct button_t *b) static void unregister_buttons(struct button_t *b)
{ {
gpio_setintmask(platform.button_mask, 0); ssb_gpio_intmask(&ssb_bcm47xx, platform.button_mask, 0);
gpio_set_irqenable(0, button_handler); gpio_set_irqenable(0, button_handler);
} }
@ -1237,12 +1237,12 @@ static irqreturn_t button_handler(int irq, void *dev_id)
struct button_t *b; struct button_t *b;
u32 in, changed; u32 in, changed;
in = gpio_in() & platform.button_mask; in = ssb_gpio_in(&ssb_bcm47xx, ~0) & platform.button_mask;
gpio_intpolarity(platform.button_mask, in); ssb_gpio_polarity(&ssb_bcm47xx, platform.button_mask, in);
changed = platform.button_polarity ^ in; changed = platform.button_polarity ^ in;
platform.button_polarity = in; platform.button_polarity = in;
changed &= ~gpio_outen(0, 0); changed &= ~ssb_gpio_outen(&ssb_bcm47xx, 0, 0);
for (b = platform.buttons; b->name; b++) { for (b = platform.buttons; b->name; b++) {
struct event_t *event; struct event_t *event;
@ -1298,10 +1298,10 @@ static void register_leds(struct led_t *l)
} }
} }
gpio_outen(mask, oe_mask); ssb_gpio_outen(&ssb_bcm47xx, mask, oe_mask);
gpio_control(mask, 0); ssb_gpio_control(&ssb_bcm47xx, mask, 0);
gpio_out(mask, val); ssb_gpio_out(&ssb_bcm47xx, mask, val);
gpio_setintmask(mask, 0); ssb_gpio_intmask(&ssb_bcm47xx, mask, 0);
} }
static void unregister_leds(struct led_t *l) static void unregister_leds(struct led_t *l)
@ -1336,11 +1336,11 @@ static void led_flash(unsigned long dummy) {
mask &= ~gpiomask; mask &= ~gpiomask;
if (mask) { if (mask) {
u32 val = ~gpio_in(); u32 val = ~ssb_gpio_in(&ssb_bcm47xx, ~0);
gpio_outen(mask, mask); ssb_gpio_outen(&ssb_bcm47xx, mask, mask);
gpio_control(mask, 0); ssb_gpio_control(&ssb_bcm47xx, mask, 0);
gpio_out(mask, val); ssb_gpio_out(&ssb_bcm47xx, mask, val);
} }
if (mask || extif_blink) { if (mask || extif_blink) {
mod_timer(&led_timer, jiffies + FLASH_TIME); mod_timer(&led_timer, jiffies + FLASH_TIME);
@ -1367,7 +1367,7 @@ static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t
if (led->gpio & GPIO_TYPE_EXTIF) { if (led->gpio & GPIO_TYPE_EXTIF) {
len = sprintf(page, "%d\n", led->state); len = sprintf(page, "%d\n", led->state);
} else { } else {
u32 in = (gpio_in() & led->gpio ? 1 : 0); u32 in = (ssb_gpio_in(&ssb_bcm47xx, ~0) & led->gpio ? 1 : 0);
u8 p = (led->polarity == NORMAL ? 0 : 1); u8 p = (led->polarity == NORMAL ? 0 : 1);
len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0)); len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0));
} }
@ -1431,9 +1431,9 @@ static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count,
led->state = p ^ ((page[0] == '1') ? 1 : 0); led->state = p ^ ((page[0] == '1') ? 1 : 0);
set_led_extif(led); set_led_extif(led);
} else { } else {
gpio_outen(led->gpio, led->gpio); ssb_gpio_outen(&ssb_bcm47xx, led->gpio, led->gpio);
gpio_control(led->gpio, 0); ssb_gpio_control(&ssb_bcm47xx, led->gpio, 0);
gpio_out(led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0)); ssb_gpio_out(&ssb_bcm47xx, led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0));
} }
} }
break; break;
@ -1464,6 +1464,13 @@ static int __init diag_init(void)
static struct proc_dir_entry *p; static struct proc_dir_entry *p;
static struct platform_t *detected; static struct platform_t *detected;
#ifdef CONFIG_BCM47XX_SSB
if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) {
printk(MODULE_NAME ": bcma bus is not supported.\n");
return -ENODEV;
}
#endif
detected = platform_detect(); detected = platform_detect();
if (!detected) { if (!detected) {
printk(MODULE_NAME ": Router model not detected.\n"); printk(MODULE_NAME ": Router model not detected.\n");

View File

@ -1,46 +1,12 @@
#ifndef __DIAG_GPIO_H #ifndef __DIAG_GPIO_H
#define __DIAG_GPIO_H #define __DIAG_GPIO_H
#include <linux/interrupt.h> #include <linux/interrupt.h>
#ifndef BCMDRIVER
#include <linux/ssb/ssb_embedded.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
#include <linux/gpio.h> #include <linux/gpio.h>
#define ssb ssb_bcm47xx #include <asm/mach-bcm47xx/bcm47xx.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
#define ssb_bcm47xx bcm47xx_bus.ssb
#endif #endif
extern struct ssb_bus ssb;
static inline u32 gpio_in(void)
{
return ssb_gpio_in(&ssb, ~0);
}
static inline u32 gpio_out(u32 mask, u32 value)
{
return ssb_gpio_out(&ssb, mask, value);
}
static inline u32 gpio_outen(u32 mask, u32 value)
{
return ssb_gpio_outen(&ssb, mask, value);
}
static inline u32 gpio_control(u32 mask, u32 value)
{
return ssb_gpio_control(&ssb, mask, value);
}
static inline u32 gpio_setintmask(u32 mask, u32 value)
{
return ssb_gpio_intmask(&ssb, mask, value);
}
static inline u32 gpio_intpolarity(u32 mask, u32 value)
{
return ssb_gpio_polarity(&ssb, mask, value);
}
static inline u32 __ssb_write32_masked(struct ssb_device *dev, u16 offset, static inline u32 __ssb_write32_masked(struct ssb_device *dev, u16 offset,
u32 mask, u32 value) u32 mask, u32 value)
@ -55,16 +21,8 @@ static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *))
{ {
int irq; int irq;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
irq = gpio_to_irq(0); irq = gpio_to_irq(0);
if (irq == -EINVAL) return; if (irq == -EINVAL) return;
#else
if (ssb.chipco.dev)
irq = ssb_mips_irq(ssb.chipco.dev) + 2;
else if (ssb.extif.dev)
irq = ssb_mips_irq(ssb.extif.dev) + 2;
else return;
#endif
if (enabled) { if (enabled) {
if (request_irq(irq, handler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, "gpio", handler)) if (request_irq(irq, handler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, "gpio", handler))
@ -73,71 +31,10 @@ static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *))
free_irq(irq, handler); free_irq(irq, handler);
} }
if (ssb.chipco.dev) if (ssb_bcm47xx.chipco.dev)
__ssb_write32_masked(ssb.chipco.dev, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO, (enabled ? SSB_CHIPCO_IRQ_GPIO : 0)); __ssb_write32_masked(ssb_bcm47xx.chipco.dev, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO, (enabled ? SSB_CHIPCO_IRQ_GPIO : 0));
} }
#else
#include <typedefs.h>
#include <osl.h>
#include <bcmdevs.h>
#include <sbutils.h>
#include <sbconfig.h>
#include <sbchipc.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include <sbmips.h>
#else
#include <hndcpu.h>
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#define sbh bcm947xx_sbh
#define sbh_lock bcm947xx_sbh_lock
#endif
extern void *sbh;
extern spinlock_t sbh_lock;
#define gpio_in() sb_gpioin(sbh)
#define gpio_out(mask, value) sb_gpioout(sbh, mask, ((value) & (mask)), GPIO_DRV_PRIORITY)
#define gpio_outen(mask, value) sb_gpioouten(sbh, mask, value, GPIO_DRV_PRIORITY)
#define gpio_control(mask, value) sb_gpiocontrol(sbh, mask, value, GPIO_DRV_PRIORITY)
#define gpio_setintmask(mask, value) sb_gpiointmask(sbh, mask, value, GPIO_DRV_PRIORITY)
#define gpio_intpolarity(mask, value) sb_gpiointpolarity(sbh, mask, value, GPIO_DRV_PRIORITY)
static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *, struct pt_regs *))
{
unsigned int coreidx;
unsigned long flags;
chipcregs_t *cc;
int irq;
spin_lock_irqsave(sbh_lock, flags);
coreidx = sb_coreidx(sbh);
irq = sb_irq(sbh) + 2;
if (enabled)
request_irq(irq, handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", handler);
else
free_irq(irq, handler);
if ((cc = sb_setcore(sbh, SB_CC, 0))) {
int intmask;
intmask = readl(&cc->intmask);
if (enabled)
intmask |= CI_GPIO;
else
intmask &= ~CI_GPIO;
writel(intmask, &cc->intmask);
}
sb_setcoreidx(sbh, coreidx);
spin_unlock_irqrestore(sbh_lock, flags);
}
#endif /* BCMDRIVER */
#define EXTIF_ADDR 0x1f000000 #define EXTIF_ADDR 0x1f000000
#define EXTIF_UART (EXTIF_ADDR + 0x00800000) #define EXTIF_UART (EXTIF_ADDR + 0x00800000)

View File

@ -14,7 +14,16 @@ CONFIG_B44_PCI=y
CONFIG_B44_PCICORE_AUTOSELECT=y CONFIG_B44_PCICORE_AUTOSELECT=y
CONFIG_B44_PCI_AUTOSELECT=y CONFIG_B44_PCI_AUTOSELECT=y
CONFIG_BCM47XX=y CONFIG_BCM47XX=y
CONFIG_BCM47XX_BCMA=y
CONFIG_BCM47XX_SSB=y
CONFIG_BCM47XX_WDT=y CONFIG_BCM47XX_WDT=y
CONFIG_BCMA=y
CONFIG_BCMA_DEBUG=y
CONFIG_BCMA_DRIVER_MIPS=y
CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
CONFIG_BCMA_HOST_SOC=y
CONFIG_BCMA_POSSIBLE=y CONFIG_BCMA_POSSIBLE=y
# CONFIG_BRCMUTIL is not set # CONFIG_BRCMUTIL is not set
# CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_BSD_PROCESS_ACCT is not set
@ -31,6 +40,7 @@ CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32=y CONFIG_CPU_MIPS32=y
CONFIG_CPU_MIPS32_R1=y CONFIG_CPU_MIPS32_R1=y
# CONFIG_CPU_MIPS32_R2 is not set
CONFIG_CPU_MIPSR1=y CONFIG_CPU_MIPSR1=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_CPU_SUPPORTS_HIGHMEM=y
@ -118,6 +128,7 @@ CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_SERIAL=y CONFIG_SSB_SERIAL=y
CONFIG_SSB_SPROM=y CONFIG_SSB_SPROM=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y

View File

@ -0,0 +1,274 @@
From c4fb5adbe45b3a1cfc509a64bb92429ab0d6fc37 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 11 Jun 2011 16:47:38 +0200
Subject: [PATCH 01/14] bcma: move parsing of EEPROM into own function.
Move the parsing of the EEPROM data in scan function for one core into
an own function. Now we are able to use it in some other scan function
as well.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/scan.c | 230 ++++++++++++++++++++++++++-------------------------
1 files changed, 118 insertions(+), 112 deletions(-)
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -200,16 +200,124 @@ static s32 bcma_erom_get_addr_desc(struc
return addrl;
}
+static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
+ struct bcma_device *core)
+{
+ s32 tmp;
+ u8 i, j;
+ s32 cia, cib;
+ u8 ports[2], wrappers[2];
+
+ /* get CIs */
+ cia = bcma_erom_get_ci(bus, eromptr);
+ if (cia < 0) {
+ bcma_erom_push_ent(eromptr);
+ if (bcma_erom_is_end(bus, eromptr))
+ return -ESPIPE;
+ return -EILSEQ;
+ }
+ cib = bcma_erom_get_ci(bus, eromptr);
+ if (cib < 0)
+ return -EILSEQ;
+
+ /* parse CIs */
+ core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
+ core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
+ core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
+ ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
+ ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
+ wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
+ wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
+ core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
+
+ if (((core->id.manuf == BCMA_MANUF_ARM) &&
+ (core->id.id == 0xFFF)) ||
+ (ports[1] == 0)) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENXIO;
+ }
+
+ /* check if component is a core at all */
+ if (wrappers[0] + wrappers[1] == 0) {
+ /* we could save addrl of the router
+ if (cid == BCMA_CORE_OOB_ROUTER)
+ */
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENXIO;
+ }
+
+ if (bcma_erom_is_bridge(bus, eromptr)) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENXIO;
+ }
+
+ /* get & parse master ports */
+ for (i = 0; i < ports[0]; i++) {
+ u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
+ if (mst_port_d < 0)
+ return -EILSEQ;
+ }
+
+ /* get & parse slave ports */
+ for (i = 0; i < ports[1]; i++) {
+ for (j = 0; ; j++) {
+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
+ SCAN_ADDR_TYPE_SLAVE, i);
+ if (tmp < 0) {
+ /* no more entries for port _i_ */
+ /* pr_debug("erom: slave port %d "
+ * "has %d descriptors\n", i, j); */
+ break;
+ } else {
+ if (i == 0 && j == 0)
+ core->addr = tmp;
+ }
+ }
+ }
+
+ /* get & parse master wrappers */
+ for (i = 0; i < wrappers[0]; i++) {
+ for (j = 0; ; j++) {
+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
+ SCAN_ADDR_TYPE_MWRAP, i);
+ if (tmp < 0) {
+ /* no more entries for port _i_ */
+ /* pr_debug("erom: master wrapper %d "
+ * "has %d descriptors\n", i, j); */
+ break;
+ } else {
+ if (i == 0 && j == 0)
+ core->wrap = tmp;
+ }
+ }
+ }
+
+ /* get & parse slave wrappers */
+ for (i = 0; i < wrappers[1]; i++) {
+ u8 hack = (ports[1] == 1) ? 0 : 1;
+ for (j = 0; ; j++) {
+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
+ SCAN_ADDR_TYPE_SWRAP, i + hack);
+ if (tmp < 0) {
+ /* no more entries for port _i_ */
+ /* pr_debug("erom: master wrapper %d "
+ * has %d descriptors\n", i, j); */
+ break;
+ } else {
+ if (wrappers[0] == 0 && !i && !j)
+ core->wrap = tmp;
+ }
+ }
+ }
+ return 0;
+}
+
int bcma_bus_scan(struct bcma_bus *bus)
{
u32 erombase;
u32 __iomem *eromptr, *eromend;
- s32 cia, cib;
- u8 ports[2], wrappers[2];
-
s32 tmp;
- u8 i, j;
int err;
@@ -236,112 +344,13 @@ int bcma_bus_scan(struct bcma_bus *bus)
INIT_LIST_HEAD(&core->list);
core->bus = bus;
- /* get CIs */
- cia = bcma_erom_get_ci(bus, &eromptr);
- if (cia < 0) {
- bcma_erom_push_ent(&eromptr);
- if (bcma_erom_is_end(bus, &eromptr))
- break;
- err= -EILSEQ;
- goto out;
- }
- cib = bcma_erom_get_ci(bus, &eromptr);
- if (cib < 0) {
- err= -EILSEQ;
- goto out;
- }
-
- /* parse CIs */
- core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
- core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
- core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
- ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
- ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
- wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
- wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
- core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
-
- if (((core->id.manuf == BCMA_MANUF_ARM) &&
- (core->id.id == 0xFFF)) ||
- (ports[1] == 0)) {
- bcma_erom_skip_component(bus, &eromptr);
+ err = bcma_get_next_core(bus, &eromptr, core);
+ if (err == -ENXIO)
continue;
- }
-
- /* check if component is a core at all */
- if (wrappers[0] + wrappers[1] == 0) {
- /* we could save addrl of the router
- if (cid == BCMA_CORE_OOB_ROUTER)
- */
- bcma_erom_skip_component(bus, &eromptr);
- continue;
- }
-
- if (bcma_erom_is_bridge(bus, &eromptr)) {
- bcma_erom_skip_component(bus, &eromptr);
- continue;
- }
-
- /* get & parse master ports */
- for (i = 0; i < ports[0]; i++) {
- u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
- if (mst_port_d < 0) {
- err= -EILSEQ;
- goto out;
- }
- }
-
- /* get & parse slave ports */
- for (i = 0; i < ports[1]; i++) {
- for (j = 0; ; j++) {
- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
- SCAN_ADDR_TYPE_SLAVE, i);
- if (tmp < 0) {
- /* no more entries for port _i_ */
- /* pr_debug("erom: slave port %d "
- * "has %d descriptors\n", i, j); */
- break;
- } else {
- if (i == 0 && j == 0)
- core->addr = tmp;
- }
- }
- }
-
- /* get & parse master wrappers */
- for (i = 0; i < wrappers[0]; i++) {
- for (j = 0; ; j++) {
- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
- SCAN_ADDR_TYPE_MWRAP, i);
- if (tmp < 0) {
- /* no more entries for port _i_ */
- /* pr_debug("erom: master wrapper %d "
- * "has %d descriptors\n", i, j); */
- break;
- } else {
- if (i == 0 && j == 0)
- core->wrap = tmp;
- }
- }
- }
-
- /* get & parse slave wrappers */
- for (i = 0; i < wrappers[1]; i++) {
- u8 hack = (ports[1] == 1) ? 0 : 1;
- for (j = 0; ; j++) {
- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
- SCAN_ADDR_TYPE_SWRAP, i + hack);
- if (tmp < 0) {
- /* no more entries for port _i_ */
- /* pr_debug("erom: master wrapper %d "
- * has %d descriptors\n", i, j); */
- break;
- } else {
- if (wrappers[0] == 0 && !i && !j)
- core->wrap = tmp;
- }
- }
- }
+ else if (err == -ESPIPE)
+ break;
+ else if (err < 0)
+ return err;
pr_info("Core %d found: %s "
"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
@@ -351,9 +360,6 @@ int bcma_bus_scan(struct bcma_bus *bus)
core->core_index = bus->nr_cores++;
list_add(&core->list, &bus->cores);
- continue;
-out:
- return err;
}
return 0;

View File

@ -0,0 +1,48 @@
From dd6cbe9b9e2ae563659b34184f4cd9d905dc90d5 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 18 Jun 2011 11:55:47 +0200
Subject: [PATCH 02/14] bcma: move initializing of struct bcma_bus to own function.
This makes it possible to use this code in some other method.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/scan.c | 17 +++++++++++------
1 files changed, 11 insertions(+), 6 deletions(-)
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -312,15 +312,10 @@ static int bcma_get_next_core(struct bcm
return 0;
}
-int bcma_bus_scan(struct bcma_bus *bus)
+static void bcma_init_bus(struct bcma_bus *bus)
{
- u32 erombase;
- u32 __iomem *eromptr, *eromend;
-
s32 tmp;
- int err;
-
INIT_LIST_HEAD(&bus->cores);
bus->nr_cores = 0;
@@ -330,6 +325,16 @@ int bcma_bus_scan(struct bcma_bus *bus)
bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+}
+
+int bcma_bus_scan(struct bcma_bus *bus)
+{
+ u32 erombase;
+ u32 __iomem *eromptr, *eromend;
+
+ int err;
+
+ bcma_init_bus(bus);
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
eromptr = bus->mmio;

View File

@ -0,0 +1,307 @@
From 9a920f4d8eed485f7b73e9b13dab0e49c64d3ff8 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 18 Jun 2011 14:30:55 +0200
Subject: [PATCH 03/14] bcma: add functions to scan cores needed on SoCs
The chip common and mips core have to be setup early in the boot
process to get the cpu clock.
bcma_bus_early_register() gets pointers to some space to store the core
data and searches for the chip common and mips core and initializes
chip common. After that was done and the kernel is out of early boot we
just have to run bcma_bus_register() and it will search for the other
cores, initialize and register them.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/bcma_private.h | 7 ++
drivers/bcma/driver_chipcommon.c | 5 ++
drivers/bcma/driver_pci.c | 3 +
drivers/bcma/main.c | 45 +++++++++++++
drivers/bcma/scan.c | 95 +++++++++++++++++++++++++--
include/linux/bcma/bcma.h | 1 +
include/linux/bcma/bcma_driver_chipcommon.h | 1 +
7 files changed, 151 insertions(+), 6 deletions(-)
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -15,9 +15,16 @@ struct bcma_bus;
/* main.c */
int bcma_bus_register(struct bcma_bus *bus);
void bcma_bus_unregister(struct bcma_bus *bus);
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+ struct bcma_device *core_cc,
+ struct bcma_device *core_mips);
/* scan.c */
int bcma_bus_scan(struct bcma_bus *bus);
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+ struct bcma_device_id *match,
+ struct bcma_device *core);
+void bcma_init_bus(struct bcma_bus *bus);
/* sprom.c */
int bcma_sprom_get(struct bcma_bus *bus);
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
{
+ if (cc->setup_done)
+ return;
+
if (cc->core->id.rev >= 11)
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -38,6 +41,8 @@ void bcma_core_chipcommon_init(struct bc
bcma_pmu_init(cc);
if (cc->capabilities & BCMA_CC_CAP_PCTL)
pr_err("Power control not implemented!\n");
+
+ cc->setup_done = true;
}
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -159,7 +159,10 @@ static void bcma_pcicore_serdes_workarou
void bcma_core_pci_init(struct bcma_drv_pci *pc)
{
+ if (pc->setup_done)
+ return;
bcma_pcicore_serdes_workaround(pc);
+ pc->setup_done = true;
}
int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -167,6 +167,51 @@ void bcma_bus_unregister(struct bcma_bus
bcma_unregister_cores(bus);
}
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+ struct bcma_device *core_cc,
+ struct bcma_device *core_mips)
+{
+ int err;
+ struct bcma_device *core;
+ struct bcma_device_id match;
+
+ bcma_init_bus(bus);
+
+ match.manuf = BCMA_MANUF_BCM;
+ match.id = BCMA_CORE_CHIPCOMMON;
+ match.class = BCMA_CL_SIM;
+ match.rev = BCMA_ANY_REV;
+
+ /* Scan for devices (cores) */
+ err = bcma_bus_scan_early(bus, &match, core_cc);
+ if (err) {
+ pr_err("Failed to scan for common core: %d\n", err);
+ return -1;
+ }
+
+ match.manuf = BCMA_MANUF_MIPS;
+ match.id = BCMA_CORE_MIPS_74K;
+ match.class = BCMA_CL_SIM;
+ match.rev = BCMA_ANY_REV;
+
+ err = bcma_bus_scan_early(bus, &match, core_mips);
+ if (err) {
+ pr_err("Failed to scan for mips core: %d\n", err);
+ return -1;
+ }
+
+ /* Init CC core */
+ core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+ if (core) {
+ bus->drv_cc.core = core;
+ bcma_core_chipcommon_init(&bus->drv_cc);
+ }
+
+ pr_info("Early bus registered\n");
+
+ return 0;
+}
+
int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
{
drv->drv.name = drv->name;
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -200,7 +200,20 @@ static s32 bcma_erom_get_addr_desc(struc
return addrl;
}
+static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
+ u16 index)
+{
+ struct bcma_device *core;
+
+ list_for_each_entry(core, &bus->cores, list) {
+ if (core->core_index == index)
+ return core;
+ }
+ return NULL;
+}
+
static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
+ struct bcma_device_id *match, int core_num,
struct bcma_device *core)
{
s32 tmp;
@@ -251,6 +264,21 @@ static int bcma_get_next_core(struct bcm
return -ENXIO;
}
+ if (bcma_find_core_by_index(bus, core_num)) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENODEV;
+ }
+
+ if (match && ((match->manuf != BCMA_ANY_MANUF &&
+ match->manuf != core->id.manuf) ||
+ (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
+ (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
+ (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
+ )) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENODEV;
+ }
+
/* get & parse master ports */
for (i = 0; i < ports[0]; i++) {
u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
@@ -312,10 +340,13 @@ static int bcma_get_next_core(struct bcm
return 0;
}
-static void bcma_init_bus(struct bcma_bus *bus)
+void bcma_init_bus(struct bcma_bus *bus)
{
s32 tmp;
+ if (bus->init_done)
+ return;
+
INIT_LIST_HEAD(&bus->cores);
bus->nr_cores = 0;
@@ -325,6 +356,7 @@ static void bcma_init_bus(struct bcma_bu
bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+ bus->init_done = true;
}
int bcma_bus_scan(struct bcma_bus *bus)
@@ -332,7 +364,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
u32 erombase;
u32 __iomem *eromptr, *eromend;
- int err;
+ int err, core_num = 0;
bcma_init_bus(bus);
@@ -349,23 +381,74 @@ int bcma_bus_scan(struct bcma_bus *bus)
INIT_LIST_HEAD(&core->list);
core->bus = bus;
- err = bcma_get_next_core(bus, &eromptr, core);
- if (err == -ENXIO)
+ err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
+ if (err == -ENODEV) {
+ core_num++;
+ continue;
+ } else if (err == -ENXIO)
continue;
else if (err == -ESPIPE)
break;
else if (err < 0)
return err;
+ core->core_index = core_num++;
+ bus->nr_cores++;
+
pr_info("Core %d found: %s "
"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
- bus->nr_cores, bcma_device_name(&core->id),
+ core->core_index, bcma_device_name(&core->id),
core->id.manuf, core->id.id, core->id.rev,
core->id.class);
- core->core_index = bus->nr_cores++;
list_add(&core->list, &bus->cores);
}
return 0;
}
+
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+ struct bcma_device_id *match,
+ struct bcma_device *core)
+{
+ u32 erombase;
+ u32 __iomem *eromptr, *eromend;
+
+ int err, core_num = 0;
+
+ erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
+ eromptr = bus->mmio;
+ eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
+
+ bcma_scan_switch_core(bus, erombase);
+
+ while (eromptr < eromend) {
+ memset(core, 0, sizeof(*core));
+ INIT_LIST_HEAD(&core->list);
+ core->bus = bus;
+
+ err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
+ if (err == -ENODEV) {
+ core_num++;
+ continue;
+ } else if (err == -ENXIO)
+ continue;
+ else if (err == -ESPIPE)
+ break;
+ else if (err < 0)
+ return err;
+
+ core->core_index = core_num++;
+ bus->nr_cores++;
+ pr_info("Core %d found: %s "
+ "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+ core->core_index, bcma_device_name(&core->id),
+ core->id.manuf, core->id.id, core->id.rev,
+ core->id.class);
+
+ list_add(&core->list, &bus->cores);
+ return 0;
+ }
+
+ return -ENODEV;
+}
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -185,6 +185,7 @@ struct bcma_bus {
struct bcma_device *mapped_core;
struct list_head cores;
u8 nr_cores;
+ u8 init_done:1;
struct bcma_drv_cc drv_cc;
struct bcma_drv_pci drv_pci;
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -259,6 +259,7 @@ struct bcma_drv_cc {
u32 status;
u32 capabilities;
u32 capabilities_ext;
+ u8 setup_done:1;
/* Fast Powerup Delay constant */
u16 fast_pwrup_delay;
struct bcma_chipcommon_pmu pmu;

View File

@ -0,0 +1,323 @@
From a807b2fb233af60028ed38ba237953bcffdf33e9 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 18 Jun 2011 14:31:53 +0200
Subject: [PATCH 04/14] bcma: add SOC bus
This patch adds support for using bcma on an embedded bus. An embedded
system like the bcm4716 could register this bus and it searches for the
bcma cores then.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/Kconfig | 5 +
drivers/bcma/Makefile | 1 +
drivers/bcma/host_soc.c | 178 +++++++++++++++++++++++++++++++++++++++++
drivers/bcma/main.c | 1 +
drivers/bcma/scan.c | 24 +++++-
include/linux/bcma/bcma.h | 4 +
include/linux/bcma/bcma_soc.h | 16 ++++
7 files changed, 227 insertions(+), 2 deletions(-)
create mode 100644 drivers/bcma/host_soc.c
create mode 100644 include/linux/bcma/bcma_soc.h
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -27,6 +27,11 @@ config BCMA_HOST_PCI
bool "Support for BCMA on PCI-host bus"
depends on BCMA_HOST_PCI_POSSIBLE
+config BCMA_HOST_SOC
+ bool
+ depends on BCMA && MIPS
+ default n
+
config BCMA_DEBUG
bool "BCMA debugging"
depends on BCMA
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -2,6 +2,7 @@ bcma-y += main.o scan.o core.o sprom
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-y += driver_pci.o
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
+bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
obj-$(CONFIG_BCMA) += bcma.o
ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
--- /dev/null
+++ b/drivers/bcma/host_soc.c
@@ -0,0 +1,178 @@
+/*
+ * Broadcom specific AMBA
+ * System on Chip (SoC) Host
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include "scan.h"
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
+
+static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
+{
+ return readb(core->io_addr + offset);
+}
+
+static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
+{
+ return readw(core->io_addr + offset);
+}
+
+static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
+{
+ return readl(core->io_addr + offset);
+}
+
+static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
+ u8 value)
+{
+ writeb(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
+ u16 value)
+{
+ writew(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
+ u32 value)
+{
+ writel(value, core->io_addr + offset);
+}
+
+#ifdef CONFIG_BCMA_BLOCKIO
+static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->io_addr + offset;
+
+ switch (reg_width) {
+ case sizeof(u8): {
+ u8 *buf = buffer;
+
+ while (count) {
+ *buf = __raw_readb(addr);
+ buf++;
+ count--;
+ }
+ break;
+ }
+ case sizeof(u16): {
+ __le16 *buf = buffer;
+
+ WARN_ON(count & 1);
+ while (count) {
+ *buf = (__force __le16)__raw_readw(addr);
+ buf++;
+ count -= 2;
+ }
+ break;
+ }
+ case sizeof(u32): {
+ __le32 *buf = buffer;
+
+ WARN_ON(count & 3);
+ while (count) {
+ *buf = (__force __le32)__raw_readl(addr);
+ buf++;
+ count -= 4;
+ }
+ break;
+ }
+ default:
+ WARN_ON(1);
+ }
+}
+
+static void bcma_host_soc_block_write(struct bcma_device *core,
+ const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->io_addr + offset;
+
+ switch (reg_width) {
+ case sizeof(u8): {
+ const u8 *buf = buffer;
+
+ while (count) {
+ __raw_writeb(*buf, addr);
+ buf++;
+ count--;
+ }
+ break;
+ }
+ case sizeof(u16): {
+ const __le16 *buf = buffer;
+
+ WARN_ON(count & 1);
+ while (count) {
+ __raw_writew((__force u16)(*buf), addr);
+ buf++;
+ count -= 2;
+ }
+ break;
+ }
+ case sizeof(u32): {
+ const __le32 *buf = buffer;
+
+ WARN_ON(count & 3);
+ while (count) {
+ __raw_writel((__force u32)(*buf), addr);
+ buf++;
+ count -= 4;
+ }
+ break;
+ }
+ default:
+ WARN_ON(1);
+ }
+}
+#endif /* CONFIG_BCMA_BLOCKIO */
+
+static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
+{
+ return readl(core->io_wrap + offset);
+}
+
+static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
+ u32 value)
+{
+ writel(value, core->io_wrap + offset);
+}
+
+const struct bcma_host_ops bcma_host_soc_ops = {
+ .read8 = bcma_host_soc_read8,
+ .read16 = bcma_host_soc_read16,
+ .read32 = bcma_host_soc_read32,
+ .write8 = bcma_host_soc_write8,
+ .write16 = bcma_host_soc_write16,
+ .write32 = bcma_host_soc_write32,
+#ifdef CONFIG_BCMA_BLOCKIO
+ .block_read = bcma_host_soc_block_read,
+ .block_write = bcma_host_soc_block_write,
+#endif
+ .aread32 = bcma_host_soc_aread32,
+ .awrite32 = bcma_host_soc_awrite32,
+};
+
+int __init bcma_host_soc_register(struct bcma_soc *soc)
+{
+ struct bcma_bus *bus = &soc->bus;
+
+ /* iomap only first core. We have to read some register on this core
+ * to scan the bus.
+ */
+ bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
+ if (!bus->mmio)
+ return -ENOMEM;
+
+ /* Host specific */
+ bus->hosttype = BCMA_HOSTTYPE_SOC;
+ bus->ops = &bcma_host_soc_ops;
+
+ /* Register */
+ return bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
+}
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -95,6 +95,7 @@ static int bcma_register_cores(struct bc
break;
case BCMA_HOSTTYPE_NONE:
case BCMA_HOSTTYPE_SDIO:
+ case BCMA_HOSTTYPE_SOC:
break;
}
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -337,6 +337,14 @@ static int bcma_get_next_core(struct bcm
}
}
}
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+ core->io_addr = ioremap(core->addr, BCMA_CORE_SIZE);
+ if (!core->io_addr)
+ return -ENOMEM;
+ core->io_wrap = ioremap(core->wrap, BCMA_CORE_SIZE);
+ if (!core->io_wrap)
+ return -ENOMEM;
+ }
return 0;
}
@@ -369,7 +377,13 @@ int bcma_bus_scan(struct bcma_bus *bus)
bcma_init_bus(bus);
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
- eromptr = bus->mmio;
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+ eromptr = ioremap(erombase, BCMA_CORE_SIZE);
+ if (!eromptr)
+ return -ENOMEM;
+ } else
+ eromptr = bus->mmio;
+
eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
bcma_scan_switch_core(bus, erombase);
@@ -417,7 +431,13 @@ int __init bcma_bus_scan_early(struct bc
int err, core_num = 0;
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
- eromptr = bus->mmio;
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+ eromptr = ioremap(erombase, BCMA_CORE_SIZE);
+ if (!eromptr)
+ return -ENOMEM;
+ } else
+ eromptr = bus->mmio;
+
eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
bcma_scan_switch_core(bus, erombase);
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -17,6 +17,7 @@ enum bcma_hosttype {
BCMA_HOSTTYPE_NONE,
BCMA_HOSTTYPE_PCI,
BCMA_HOSTTYPE_SDIO,
+ BCMA_HOSTTYPE_SOC,
};
struct bcma_chipinfo {
@@ -133,6 +134,9 @@ struct bcma_device {
u32 addr;
u32 wrap;
+ void __iomem *io_addr;
+ void __iomem *io_wrap;
+
void *drvdata;
struct list_head list;
};
--- /dev/null
+++ b/include/linux/bcma/bcma_soc.h
@@ -0,0 +1,16 @@
+#ifndef LINUX_BCMA_SOC_H_
+#define LINUX_BCMA_SOC_H_
+
+#include <linux/bcma/bcma.h>
+
+struct bcma_soc {
+ struct bcma_bus bus;
+ struct bcma_device core_cc;
+ struct bcma_device core_mips;
+};
+
+int __init bcma_host_soc_register(struct bcma_soc *soc);
+
+int bcma_bus_register(struct bcma_bus *bus);
+
+#endif /* LINUX_BCMA_SOC_H_ */

View File

@ -0,0 +1,402 @@
From 0a1a5fd8aab864e7b531ab88fd317ff7278d884d Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 6 Jun 2011 00:07:32 +0200
Subject: [PATCH 05/14] 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>
---
drivers/bcma/Kconfig | 11 ++-
drivers/bcma/Makefile | 1 +
drivers/bcma/driver_mips.c | 234 +++++++++++++++++++++++++++++++++
drivers/bcma/main.c | 19 +++
include/linux/bcma/bcma.h | 2 +
include/linux/bcma/bcma_driver_mips.h | 49 +++++++
6 files changed, 315 insertions(+), 1 deletions(-)
create mode 100644 drivers/bcma/driver_mips.c
create mode 100644 include/linux/bcma/bcma_driver_mips.h
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -29,9 +29,18 @@ config BCMA_HOST_PCI
config BCMA_HOST_SOC
bool
- depends on BCMA && MIPS
+ depends on BCMA_DRIVER_MIPS
default n
+config BCMA_DRIVER_MIPS
+ bool "BCMA Broadcom MIPS core driver"
+ depends on BCMA && MIPS
+ help
+ Driver for the Broadcom MIPS core attached to Broadcom specific
+ Advanced Microcontroller Bus.
+
+ If unsure, say N
+
config BCMA_DEBUG
bool "BCMA debugging"
depends on BCMA
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -1,6 +1,7 @@
bcma-y += main.o scan.o core.o sprom.o
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-y += driver_pci.o
+bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
obj-$(CONFIG_BCMA) += bcma.o
--- /dev/null
+++ b/drivers/bcma/driver_mips.c
@@ -0,0 +1,234 @@
+/*
+ * Broadcom specific AMBA
+ * Broadcom MIPS32 74K core driver
+ *
+ * Copyright 2009, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
+ * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+
+#include <linux/bcma/bcma.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/time.h>
+
+/* The 47162a0 hangs when reading its registers */
+static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
+{
+ return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
+ dev->id.id == BCMA_CORE_MIPS_74K;
+}
+
+static inline u32 mips_read32(struct bcma_drv_mips *mcore,
+ u16 offset)
+{
+ return bcma_read32(mcore->core, offset);
+}
+
+static inline void mips_write32(struct bcma_drv_mips *mcore,
+ u16 offset,
+ u32 value)
+{
+ bcma_write32(mcore->core, offset, value);
+}
+
+static const u32 ipsflag_irq_mask[] = {
+ 0,
+ BCMA_MIPS_IPSFLAG_IRQ1,
+ BCMA_MIPS_IPSFLAG_IRQ2,
+ BCMA_MIPS_IPSFLAG_IRQ3,
+ BCMA_MIPS_IPSFLAG_IRQ4,
+};
+
+static const u32 ipsflag_irq_shift[] = {
+ 0,
+ BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
+ BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
+ BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
+ BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
+};
+
+static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
+{
+ u32 flag;
+
+ if (bcma_core_mips_bcm47162a0_quirk(dev))
+ return dev->core_index;
+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
+
+ return flag & 0x1F;
+}
+
+
+/* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
+ * If disabled, 5 is returned.
+ */
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+{
+ struct bcma_device *mdev = dev->bus->drv_mips.core;
+ u32 irqflag;
+ unsigned int irq;
+
+ irqflag = bcma_core_mips_irqflag(dev);
+
+ for (irq = 1; irq <= 4; irq++)
+ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
+ (1 << irqflag))
+ return irq;
+
+ return 0;
+}
+EXPORT_SYMBOL(bcma_core_mips_irq);
+
+static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
+{
+ unsigned int oldirq = bcma_core_mips_irq(dev);
+ struct bcma_bus *bus = dev->bus;
+ struct bcma_device *mdev = bus->drv_mips.core;
+ u32 irqflag;
+
+ irqflag = bcma_core_mips_irqflag(dev);
+ BUG_ON(oldirq == 6);
+
+ dev->irq = irq + 2;
+
+ /* clear the old irq */
+ if (oldirq == 0)
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+ ~(1 << irqflag));
+ else
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
+
+ /* assign the new one */
+ if (irq == 0) {
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
+ (1 << irqflag));
+ } else {
+ u32 oldirqflag = bcma_read32(mdev,
+ BCMA_MIPS_MIPS74K_INTMASK(irq));
+ if (oldirqflag) {
+ struct bcma_device *core;
+
+ /* backplane irq line is in use, find out who uses
+ * it and set user to irq 0
+ */
+ list_for_each_entry_reverse(core, &bus->cores, list) {
+ if ((1 << bcma_core_mips_irqflag(core)) ==
+ oldirqflag) {
+ bcma_core_mips_set_irq(core, 0);
+ break;
+ }
+ }
+ }
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
+ 1 << irqflag);
+ }
+
+ pr_info("set_irq: core 0x%04x, irq %d => %d\n",
+ dev->id.id, oldirq + 2, irq + 2);
+}
+
+static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
+{
+ int i;
+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
+ printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
+ for (i = 0; i <= 6; i++)
+ printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
+ printk("\n");
+}
+
+static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
+{
+ struct bcma_device *core;
+
+ list_for_each_entry_reverse(core, &bus->cores, list) {
+ bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
+ }
+}
+
+static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
+{
+ struct bcma_bus *bus = mcore->core->bus;
+
+ mcore->flash_buswidth = 2;
+ if (bus->drv_cc.core) {
+ mcore->flash_window = 0x1c000000;
+ mcore->flash_window_size = 0x02000000;
+ switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+ case BCMA_CC_FLASHT_STSER:
+ case BCMA_CC_FLASHT_ATSER:
+ pr_err("Serial flash not supported.\n");
+ break;
+ case BCMA_CC_FLASHT_PARA:
+ if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
+ BCMA_CC_OTPS) == 0)
+ mcore->flash_buswidth = 1;
+ break;
+ }
+ } else {
+ mcore->flash_window = 0x1fc00000;
+ mcore->flash_window_size = 0x00400000;
+ }
+}
+
+void bcma_core_mips_init(struct bcma_drv_mips *mcore)
+{
+ struct bcma_bus *bus;
+ struct bcma_device *core;
+ bus = mcore->core->bus;
+
+ pr_info("Initializing MIPS core...\n");
+
+ if (!mcore->setup_done)
+ mcore->assigned_irqs = 1;
+
+ /* Assign IRQs to all cores on the bus */
+ list_for_each_entry_reverse(core, &bus->cores, list) {
+ int mips_irq;
+ if (core->irq)
+ continue;
+
+ mips_irq = bcma_core_mips_irq(core);
+ if (mips_irq > 4)
+ core->irq = 0;
+ else
+ core->irq = mips_irq + 2;
+ if (core->irq > 5)
+ continue;
+ switch (core->id.id) {
+ case BCMA_CORE_PCI:
+ case BCMA_CORE_PCIE:
+ case BCMA_CORE_ETHERNET:
+ case BCMA_CORE_ETHERNET_GBIT:
+ case BCMA_CORE_MAC_GBIT:
+ case BCMA_CORE_80211:
+ case BCMA_CORE_USB20_HOST:
+ /* These devices get their own IRQ line if available,
+ * the rest goes on IRQ0
+ */
+ if (mcore->assigned_irqs <= 4)
+ bcma_core_mips_set_irq(core,
+ mcore->assigned_irqs++);
+ break;
+ }
+ }
+ pr_info("IRQ reconfiguration done\n");
+ bcma_core_mips_dump_irq(bus);
+
+ if (mcore->setup_done)
+ return;
+
+ bcma_core_mips_flash_detect(mcore);
+ mcore->setup_done = true;
+}
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -80,6 +80,7 @@ static int bcma_register_cores(struct bc
case BCMA_CORE_CHIPCOMMON:
case BCMA_CORE_PCI:
case BCMA_CORE_PCIE:
+ case BCMA_CORE_MIPS_74K:
continue;
}
@@ -141,6 +142,15 @@ int bcma_bus_register(struct bcma_bus *b
bcma_core_chipcommon_init(&bus->drv_cc);
}
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+ /* Init MIPS core */
+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+ if (core) {
+ bus->drv_mips.core = core;
+ bcma_core_mips_init(&bus->drv_mips);
+ }
+#endif
+
/* Init PCIE core */
core = bcma_find_core(bus, BCMA_CORE_PCIE);
if (core) {
@@ -208,6 +218,15 @@ int __init bcma_bus_early_register(struc
bcma_core_chipcommon_init(&bus->drv_cc);
}
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+ /* Init MIPS core */
+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+ if (core) {
+ bus->drv_mips.core = core;
+ bcma_core_mips_init(&bus->drv_mips);
+ }
+#endif
+
pr_info("Early bus registered\n");
return 0;
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -6,6 +6,7 @@
#include <linux/bcma/bcma_driver_chipcommon.h>
#include <linux/bcma/bcma_driver_pci.h>
+#include <linux/bcma/bcma_driver_mips.h>
#include <linux/ssb/ssb.h> /* SPROM sharing */
#include "bcma_regs.h"
@@ -193,6 +194,7 @@ struct bcma_bus {
struct bcma_drv_cc drv_cc;
struct bcma_drv_pci drv_pci;
+ struct bcma_drv_mips drv_mips;
/* We decided to share SPROM struct with SSB as long as we do not need
* any hacks for BCMA. This simplifies drivers code. */
--- /dev/null
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -0,0 +1,49 @@
+#ifndef LINUX_BCMA_DRIVER_MIPS_H_
+#define LINUX_BCMA_DRIVER_MIPS_H_
+
+#define BCMA_MIPS_IPSFLAG 0x0F08
+/* which sbflags get routed to mips interrupt 1 */
+#define BCMA_MIPS_IPSFLAG_IRQ1 0x0000003F
+#define BCMA_MIPS_IPSFLAG_IRQ1_SHIFT 0
+/* which sbflags get routed to mips interrupt 2 */
+#define BCMA_MIPS_IPSFLAG_IRQ2 0x00003F00
+#define BCMA_MIPS_IPSFLAG_IRQ2_SHIFT 8
+/* which sbflags get routed to mips interrupt 3 */
+#define BCMA_MIPS_IPSFLAG_IRQ3 0x003F0000
+#define BCMA_MIPS_IPSFLAG_IRQ3_SHIFT 16
+/* which sbflags get routed to mips interrupt 4 */
+#define BCMA_MIPS_IPSFLAG_IRQ4 0x3F000000
+#define BCMA_MIPS_IPSFLAG_IRQ4_SHIFT 24
+
+/* MIPS 74K core registers */
+#define BCMA_MIPS_MIPS74K_CORECTL 0x0000
+#define BCMA_MIPS_MIPS74K_EXCEPTBASE 0x0004
+#define BCMA_MIPS_MIPS74K_BIST 0x000C
+#define BCMA_MIPS_MIPS74K_INTMASK_INT0 0x0014
+#define BCMA_MIPS_MIPS74K_INTMASK(int) \
+ ((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0)
+#define BCMA_MIPS_MIPS74K_NMIMASK 0x002C
+#define BCMA_MIPS_MIPS74K_GPIOSEL 0x0040
+#define BCMA_MIPS_MIPS74K_GPIOOUT 0x0044
+#define BCMA_MIPS_MIPS74K_GPIOEN 0x0048
+#define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0
+
+#define BCMA_MIPS_OOBSELOUTA30 0x100
+
+struct bcma_device;
+
+struct bcma_drv_mips {
+ struct bcma_device *core;
+ u8 setup_done:1;
+ unsigned int assigned_irqs;
+
+ u8 flash_buswidth;
+ u32 flash_window;
+ u32 flash_window_size;
+};
+
+extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
+
+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
+
+#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */

View File

@ -0,0 +1,151 @@
From b7c100827012ba588089807475affe0c69a3f817 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 6 Jun 2011 00:07:33 +0200
Subject: [PATCH 06/14] bcma: add serial console support
This adds support for serial console to bcma, when operating on an
embedded device.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/bcma_private.h | 6 +++
drivers/bcma/driver_chipcommon.c | 64 +++++++++++++++++++++++++++++++++
drivers/bcma/driver_mips.c | 9 +++++
include/linux/bcma/bcma_driver_mips.h | 11 ++++++
4 files changed, 90 insertions(+), 0 deletions(-)
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -29,6 +29,12 @@ void bcma_init_bus(struct bcma_bus *bus)
/* sprom.c */
int bcma_sprom_get(struct bcma_bus *bus);
+/* driver_chipcommon.c */
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
+ struct bcma_drv_mips_serial_port *ports);
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
+
#ifdef CONFIG_BCMA_HOST_PCI
/* host_pci.c */
extern int __init bcma_host_pci_init(void);
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -92,3 +92,67 @@ u32 bcma_chipco_gpio_polarity(struct bcm
{
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
}
+
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
+ struct bcma_drv_mips_serial_port *ports)
+{
+ int nr_ports = 0;
+ u32 plltype;
+ unsigned int irq;
+ u32 baud_base, div;
+ u32 i, n;
+ unsigned int ccrev = cc->core->id.rev;
+
+ plltype = (cc->capabilities & BCMA_CC_CAP_PLLT);
+ irq = bcma_core_mips_irq(cc->core);
+
+ if ((ccrev >= 11) && (ccrev != 15) && (ccrev != 20)) {
+ /* Fixed ALP clock */
+ baud_base = 20000000;
+ if (cc->capabilities & BCMA_CC_CAP_PMU) {
+ /* FIXME: baud_base is different for devices with a PMU */
+ WARN_ON(1);
+ }
+ div = 1;
+ if (ccrev >= 21) {
+ /* Turn off UART clock before switching clocksource. */
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
+ & ~BCMA_CC_CORECTL_UARTCLKEN);
+ }
+ /* Set the override bit so we don't divide it */
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
+ | BCMA_CC_CORECTL_UARTCLK0);
+ if (ccrev >= 21) {
+ /* Re-enable the UART clock. */
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
+ | BCMA_CC_CORECTL_UARTCLKEN);
+ }
+ } else
+ pr_err("serial not supported on this device ccrev: 0x%x\n",
+ ccrev);
+
+ /* Determine the registers of the UARTs */
+ n = (cc->capabilities & BCMA_CC_CAP_NRUART);
+ for (i = 0; i < n; i++) {
+ void __iomem *cc_mmio;
+ void __iomem *uart_regs;
+
+ cc_mmio = cc->core->bus->mmio +
+ (cc->core->core_index * BCMA_CORE_SIZE);
+ uart_regs = cc_mmio + BCMA_CC_UART0_DATA;
+ uart_regs += (i * 256);
+
+ nr_ports++;
+ ports[i].regs = uart_regs;
+ ports[i].irq = irq;
+ ports[i].baud_base = baud_base;
+ ports[i].reg_shift = 0;
+ }
+
+ return nr_ports;
+}
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -157,6 +157,14 @@ static void bcma_core_mips_dump_irq(stru
}
}
+static void bcma_core_mips_serial_init(struct bcma_drv_mips *mcore)
+{
+ struct bcma_bus *bus = mcore->core->bus;
+
+ mcore->nr_serial_ports = bcma_chipco_serial_init(&bus->drv_cc,
+ mcore->serial_ports);
+}
+
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
{
struct bcma_bus *bus = mcore->core->bus;
@@ -229,6 +237,7 @@ void bcma_core_mips_init(struct bcma_drv
if (mcore->setup_done)
return;
+ bcma_core_mips_serial_init(mcore);
bcma_core_mips_flash_detect(mcore);
mcore->setup_done = true;
}
--- a/include/linux/bcma/bcma_driver_mips.h
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -32,11 +32,22 @@
struct bcma_device;
+struct bcma_drv_mips_serial_port {
+ void *regs;
+ unsigned long clockspeed;
+ unsigned int irq;
+ unsigned int baud_base;
+ unsigned int reg_shift;
+};
+
struct bcma_drv_mips {
struct bcma_device *core;
u8 setup_done:1;
unsigned int assigned_irqs;
+ int nr_serial_ports;
+ struct bcma_drv_mips_serial_port serial_ports[4];
+
u8 flash_buswidth;
u32 flash_window;
u32 flash_window_size;

View File

@ -0,0 +1,204 @@
From 257d5fe12600f08df764cac0abc17bef7b6fae9b Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 19 Jun 2011 17:51:30 +0200
Subject: [PATCH 07/14] bcma: get CPU clock
Add method to return the clock of the CPU. This is needed by the arch
code to calculate the mips_hpt_frequency.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/bcma_private.h | 3 +
drivers/bcma/driver_chipcommon_pmu.c | 87 +++++++++++++++++++++++++++
drivers/bcma/driver_mips.c | 12 ++++
include/linux/bcma/bcma_driver_chipcommon.h | 35 +++++++++++
include/linux/bcma/bcma_driver_mips.h | 1 +
5 files changed, 138 insertions(+), 0 deletions(-)
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -29,6 +29,9 @@ void bcma_init_bus(struct bcma_bus *bus)
/* sprom.c */
int bcma_sprom_get(struct bcma_bus *bus);
+/* driver_chipcommon_pmu.c */
+extern u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
+
/* driver_chipcommon.c */
#ifdef CONFIG_BCMA_DRIVER_MIPS
extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -11,6 +11,13 @@
#include "bcma_private.h"
#include <linux/bcma/bcma.h>
+static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
+{
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+ return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+}
+
static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
u32 offset, u32 mask, u32 set)
{
@@ -136,3 +143,83 @@ void bcma_pmu_init(struct bcma_drv_cc *c
bcma_pmu_swreg_init(cc);
bcma_pmu_workarounds(cc);
}
+
+static u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
+{
+ struct bcma_bus *bus = cc->core->bus;
+
+ switch (bus->chipinfo.id) {
+ case 0x4716:
+ case 0x4748:
+ case 47162:
+ /* always 20Mhz */
+ return 20000 * 1000;
+ default:
+ pr_warn("No ALP clock specified for %04X device, "
+ "pmu rev. %d, using default %d Hz\n",
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
+ }
+ return BCMA_CC_PMU_ALP_CLOCK;
+}
+
+/* Find the output of the "m" pll divider given pll controls that start with
+ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
+ */
+static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+{
+ u32 tmp, div, ndiv, p1, p2, fc;
+
+ BUG_ON(!m || m > 4);
+
+ BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
+
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
+ p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
+ p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
+
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
+ div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
+ BCMA_CC_PPL_MDIV_MASK;
+
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
+ ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
+
+ /* Do calculation in Mhz */
+ fc = bcma_pmu_alp_clock(cc) / 1000000;
+ fc = (p1 * ndiv * fc) / p2;
+
+ /* Return clock in Hertz */
+ return (fc / div) * 1000000;
+}
+
+/* query bus clock frequency for PMU-enabled chipcommon */
+u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
+{
+ struct bcma_bus *bus = cc->core->bus;
+
+ switch (bus->chipinfo.id) {
+ case 0x4716:
+ case 0x4748:
+ case 47162:
+ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
+ default:
+ pr_warn("No backplane clock specified for %04X device, "
+ "pmu rev. %d, using default %d Hz\n",
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
+ }
+ return BCMA_CC_PMU_HT_CLOCK;
+}
+
+/* query cpu clock frequency for PMU-enabled chipcommon */
+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
+{
+ struct bcma_bus *bus = cc->core->bus;
+
+ if ((cc->pmu.rev == 5 || cc->pmu.rev == 6 || cc->pmu.rev == 7) &&
+ (bus->chipinfo.id != 0x4319))
+ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_CPU);
+
+ return bcma_pmu_get_clockcontrol(cc);
+}
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -157,6 +157,18 @@ static void bcma_core_mips_dump_irq(stru
}
}
+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
+{
+ struct bcma_bus *bus = mcore->core->bus;
+
+ if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
+ return bcma_pmu_get_clockcpu(&bus->drv_cc);
+
+ pr_err("No PMU available, need this to get the cpu clock\n");
+ return 0;
+}
+EXPORT_SYMBOL(bcma_cpu_clock);
+
static void bcma_core_mips_serial_init(struct bcma_drv_mips *mcore)
{
struct bcma_bus *bus = mcore->core->bus;
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -246,6 +246,41 @@
#define BCMA_CC_PLLCTL_DATA 0x0664
#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */
+/* Divider allocation in 4716/47162/5356 */
+#define BCMA_CC_PMU5_MAINPLL_CPU 1
+#define BCMA_CC_PMU5_MAINPLL_MEM 2
+#define BCMA_CC_PMU5_MAINPLL_SSB 3
+
+/* PLL usage in 4716/47162 */
+#define BCMA_CC_PMU4716_MAINPLL_PLL0 12
+
+/* ALP clock on pre-PMU chips */
+#define BCMA_CC_PMU_ALP_CLOCK 20000000
+/* HT clock for systems with PMU-enabled chipcommon */
+#define BCMA_CC_PMU_HT_CLOCK 80000000
+
+/* PMU rev 5 (& 6) */
+#define BCMA_CC_PPL_P1P2_OFF 0
+#define BCMA_CC_PPL_P1_MASK 0x0f000000
+#define BCMA_CC_PPL_P1_SHIFT 24
+#define BCMA_CC_PPL_P2_MASK 0x00f00000
+#define BCMA_CC_PPL_P2_SHIFT 20
+#define BCMA_CC_PPL_M14_OFF 1
+#define BCMA_CC_PPL_MDIV_MASK 0x000000ff
+#define BCMA_CC_PPL_MDIV_WIDTH 8
+#define BCMA_CC_PPL_NM5_OFF 2
+#define BCMA_CC_PPL_NDIV_MASK 0xfff00000
+#define BCMA_CC_PPL_NDIV_SHIFT 20
+#define BCMA_CC_PPL_FMAB_OFF 3
+#define BCMA_CC_PPL_MRAT_MASK 0xf0000000
+#define BCMA_CC_PPL_MRAT_SHIFT 28
+#define BCMA_CC_PPL_ABRAT_MASK 0x08000000
+#define BCMA_CC_PPL_ABRAT_SHIFT 27
+#define BCMA_CC_PPL_FDIV_MASK 0x07ffffff
+#define BCMA_CC_PPL_PLLCTL_OFF 4
+#define BCMA_CC_PPL_PCHI_OFF 5
+#define BCMA_CC_PPL_PCHI_MASK 0x0000003f
+
/* Data for the PMU, if available.
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
*/
--- a/include/linux/bcma/bcma_driver_mips.h
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -54,6 +54,7 @@ struct bcma_drv_mips {
};
extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
+extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);

View File

@ -0,0 +1,140 @@
From f93062e72447b4a4a51afbe33ea086ce8c922587 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 19 Jun 2011 17:52:09 +0200
Subject: [PATCH 08/14] bcma: add pci(e) host mode
This adds some stub for a pci(e) host controller. This controller is
found on some embedded devices to attach other chips.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/Kconfig | 6 ++++
drivers/bcma/Makefile | 1 +
drivers/bcma/bcma_private.h | 6 ++++
drivers/bcma/driver_pci.c | 14 ++++++++++-
drivers/bcma/driver_pci_host.c | 43 ++++++++++++++++++++++++++++++++++
include/linux/bcma/bcma_driver_pci.h | 1 +
6 files changed, 70 insertions(+), 1 deletions(-)
create mode 100644 drivers/bcma/driver_pci_host.c
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -32,6 +32,12 @@ config BCMA_HOST_SOC
depends on BCMA_DRIVER_MIPS
default n
+config BCMA_DRIVER_PCI_HOSTMODE
+ bool "Hostmode support for BCMA PCI core"
+ depends on BCMA_DRIVER_MIPS
+ help
+ PCIcore hostmode operation (external PCI bus).
+
config BCMA_DRIVER_MIPS
bool "BCMA Broadcom MIPS core driver"
depends on BCMA && MIPS
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -1,6 +1,7 @@
bcma-y += main.o scan.o core.o sprom.o
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-y += driver_pci.o
+bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -38,6 +38,12 @@ extern int bcma_chipco_serial_init(struc
struct bcma_drv_mips_serial_port *ports);
#endif /* CONFIG_BCMA_DRIVER_MIPS */
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+/* driver_pci_host.c */
+int bcma_core_pci_in_hostmode(struct bcma_drv_pci *pc);
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
+
#ifdef CONFIG_BCMA_HOST_PCI
/* host_pci.c */
extern int __init bcma_host_pci_init(void);
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -159,9 +159,21 @@ static void bcma_pcicore_serdes_workarou
void bcma_core_pci_init(struct bcma_drv_pci *pc)
{
+ struct bcma_device *core = pc->core;
+
if (pc->setup_done)
return;
- bcma_pcicore_serdes_workaround(pc);
+
+ if (!bcma_core_is_enabled(core))
+ bcma_core_enable(core, 0);
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+ pc->hostmode = bcma_core_pci_in_hostmode(pc);
+ if (pc->hostmode)
+ bcma_core_pci_hostmode_init(pc);
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
+ if (!pc->hostmode)
+ bcma_pcicore_serdes_workaround(pc);
+
pc->setup_done = true;
}
--- /dev/null
+++ b/drivers/bcma/driver_pci_host.c
@@ -0,0 +1,43 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Host mode
+ *
+ * Copyright 2005, Broadcom Corporation
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/bcma/bcma.h>
+
+#include <asm/paccess.h>
+/* Probe a 32bit value on the bus and catch bus exceptions.
+ * Returns nonzero on a bus exception.
+ * This is MIPS specific */
+#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
+
+
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
+{
+ /* TODO: implement PCI host mode */
+}
+
+int bcma_core_pci_in_hostmode(struct bcma_drv_pci *pc)
+{
+ struct bcma_bus *bus = pc->core->bus;
+ u16 chipid_top;
+ u32 tmp;
+
+ chipid_top = (bus->chipinfo.id & 0xFF00);
+ if (chipid_top != 0x4700 &&
+ chipid_top != 0x5300)
+ return 0;
+
+/* TODO: add when sprom is available
+ * if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
+ * return 0;
+ */
+
+ return !mips_busprobe32(tmp, (bus->mmio + (pc->core->core_index *
+ BCMA_CORE_SIZE)));
+}
--- a/include/linux/bcma/bcma_driver_pci.h
+++ b/include/linux/bcma/bcma_driver_pci.h
@@ -78,6 +78,7 @@ struct pci_dev;
struct bcma_drv_pci {
struct bcma_device *core;
u8 setup_done:1;
+ u8 hostmode:1;
};
/* Register access */

View File

@ -0,0 +1,37 @@
From 5972feafaa3c71c1497b4ef4101b3c6855b7b64e Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 19 Jun 2011 19:14:11 +0200
Subject: [PATCH 09/14] bcma: add check if sprom is available before accessing it.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/bcma/main.c | 4 +++-
drivers/bcma/sprom.c | 3 +++
2 files changed, 6 insertions(+), 1 deletions(-)
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -160,7 +160,9 @@ int bcma_bus_register(struct bcma_bus *b
/* Try to get SPROM */
err = bcma_sprom_get(bus);
- if (err) {
+ if (err == -ENOENT) {
+ pr_err("No SPROM available\n");
+ } else if (err) {
pr_err("Failed to get SPROM: %d\n", err);
return -ENOENT;
}
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -143,6 +143,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
if (!bus->drv_cc.core)
return -EOPNOTSUPP;
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+ return -ENOENT;
+
sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
GFP_KERNEL);
if (!sprom)

View File

@ -0,0 +1,439 @@
From c0886db6357de20fba4f7c0602eceefba3ad343b Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 6 Jun 2011 00:07:36 +0200
Subject: [PATCH 10/14] bcm47xx: prepare to support different buses
The ssb bus is not hod directly any more. there is now a union which
contains all the supported buses, now just ssb. As just one system bus
can be used at a time the union does not cause any problems.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/gpio.c | 56 ++++++++++++++++----------
arch/mips/bcm47xx/nvram.c | 15 +++++--
arch/mips/bcm47xx/serial.c | 13 +++++-
arch/mips/bcm47xx/setup.c | 32 +++++++++++---
arch/mips/bcm47xx/time.c | 9 +++-
arch/mips/bcm47xx/wgt634u.c | 13 ++++--
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 14 ++++++-
arch/mips/include/asm/mach-bcm47xx/gpio.h | 55 ++++++++++++++++++-------
drivers/watchdog/bcm47xx_wdt.c | 12 +++++-
9 files changed, 158 insertions(+), 61 deletions(-)
--- a/arch/mips/bcm47xx/gpio.c
+++ b/arch/mips/bcm47xx/gpio.c
@@ -20,42 +20,54 @@ static DECLARE_BITMAP(gpio_in_use, BCM47
int gpio_request(unsigned gpio, const char *tag)
{
- if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
- return -EINVAL;
-
- if (ssb_extif_available(&ssb_bcm47xx.extif) &&
- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
- return -EINVAL;
-
- if (test_and_set_bit(gpio, gpio_in_use))
- return -EBUSY;
-
- return 0;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+ ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+ return -EINVAL;
+
+ if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+ ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+ return -EINVAL;
+
+ if (test_and_set_bit(gpio, gpio_in_use))
+ return -EBUSY;
+
+ return 0;
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL(gpio_request);
void gpio_free(unsigned gpio)
{
- if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
- return;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+ ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+ return;
+
+ if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+ ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+ return;
- if (ssb_extif_available(&ssb_bcm47xx.extif) &&
- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+ clear_bit(gpio, gpio_in_use);
return;
-
- clear_bit(gpio, gpio_in_use);
+ }
}
EXPORT_SYMBOL(gpio_free);
int gpio_to_irq(unsigned gpio)
{
- if (ssb_chipco_available(&ssb_bcm47xx.chipco))
- return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
- else if (ssb_extif_available(&ssb_bcm47xx.extif))
- return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
- else
- return -EINVAL;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
+ return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
+ else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
+ return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
+ else
+ return -EINVAL;
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(gpio_to_irq);
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -26,14 +26,21 @@ static char nvram_buf[NVRAM_SPACE];
/* Probe for NVRAM header */
static void early_nvram_init(void)
{
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+ struct ssb_mipscore *mcore_ssb;
struct nvram_header *header;
int i;
- u32 base, lim, off;
+ u32 base = 0;
+ u32 lim = 0;
+ u32 off;
u32 *src, *dst;
- base = mcore->flash_window;
- lim = mcore->flash_window_size;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ mcore_ssb = &bcm47xx_bus.ssb.mipscore;
+ base = mcore_ssb->flash_window;
+ lim = mcore_ssb->flash_window_size;
+ break;
+ }
off = FLASH_MIN;
while (off <= lim) {
--- a/arch/mips/bcm47xx/serial.c
+++ b/arch/mips/bcm47xx/serial.c
@@ -23,10 +23,10 @@ static struct platform_device uart8250_d
},
};
-static int __init uart8250_init(void)
+static int __init uart8250_init_ssb(void)
{
int i;
- struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore);
+ struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore);
memset(&uart8250_data, 0, sizeof(uart8250_data));
@@ -45,6 +45,15 @@ static int __init uart8250_init(void)
return platform_device_register(&uart8250_device);
}
+static int __init uart8250_init(void)
+{
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ return uart8250_init_ssb();
+ }
+ return -EINVAL;
+}
+
module_init(uart8250_init);
MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -35,15 +35,22 @@
#include <bcm47xx.h>
#include <asm/mach-bcm47xx/nvram.h>
-struct ssb_bus ssb_bcm47xx;
-EXPORT_SYMBOL(ssb_bcm47xx);
+union bcm47xx_bus bcm47xx_bus;
+EXPORT_SYMBOL(bcm47xx_bus);
+
+enum bcm47xx_bus_type bcm47xx_active_bus_type;
+EXPORT_SYMBOL(bcm47xx_active_bus_type);
static void bcm47xx_machine_restart(char *command)
{
printk(KERN_ALERT "Please stand by while rebooting the system...\n");
local_irq_disable();
/* Set the watchdog timer to reset immediately */
- ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+ break;
+ }
while (1)
cpu_relax();
}
@@ -52,7 +59,11 @@ static void bcm47xx_machine_halt(void)
{
/* Disable interrupts and watchdog and spin forever */
local_irq_disable();
- ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+ break;
+ }
while (1)
cpu_relax();
}
@@ -247,7 +258,7 @@ static int bcm47xx_get_invariants(struct
return 0;
}
-void __init plat_mem_setup(void)
+static void __init bcm47xx_register_ssb(void)
{
int err;
char buf[100];
@@ -258,12 +269,12 @@ void __init plat_mem_setup(void)
printk(KERN_WARNING "bcm47xx: someone else already registered"
" a ssb SPROM callback handler (err %d)\n", err);
- err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+ err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
bcm47xx_get_invariants);
if (err)
panic("Failed to initialize SSB bus (err %d)\n", err);
- mcore = &ssb_bcm47xx.mipscore;
+ mcore = &bcm47xx_bus.ssb.mipscore;
if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
if (strstr(buf, "console=ttyS1")) {
struct ssb_serial_port port;
@@ -276,6 +287,14 @@ void __init plat_mem_setup(void)
memcpy(&mcore->serial_ports[1], &port, sizeof(port));
}
}
+}
+
+void __init plat_mem_setup(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+
+ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB;
+ bcm47xx_register_ssb();
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -30,7 +30,7 @@
void __init plat_time_init(void)
{
- unsigned long hz;
+ unsigned long hz = 0;
/*
* Use deterministic values for initial counter interrupt
@@ -39,7 +39,12 @@ void __init plat_time_init(void)
write_c0_count(0);
write_c0_compare(0xffff);
- hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+ break;
+ }
+
if (!hz)
hz = 100000000;
--- a/arch/mips/bcm47xx/wgt634u.c
+++ b/arch/mips/bcm47xx/wgt634u.c
@@ -108,7 +108,7 @@ static irqreturn_t gpio_interrupt(int ir
/* Interrupts are shared, check if the current one is
a GPIO interrupt. */
- if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
+ if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO))
return IRQ_NONE;
@@ -133,21 +133,24 @@ static int __init wgt634u_init(void)
* been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
*/
- u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
+ if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB)
+ return -ENODEV;
+
+ u8 *et0mac = bcm47xx_bus.ssb.sprom.et0mac;
if (et0mac[0] == 0x00 &&
((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
(et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+ struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
printk(KERN_INFO "WGT634U machine detected.\n");
if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
gpio_interrupt, IRQF_SHARED,
- "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
+ "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
gpio_direction_input(WGT634U_GPIO_RESET);
gpio_intmask(WGT634U_GPIO_RESET, 1);
- ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
+ ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO,
SSB_CHIPCO_IRQ_GPIO);
}
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -19,7 +19,17 @@
#ifndef __ASM_BCM47XX_H
#define __ASM_BCM47XX_H
-/* SSB bus */
-extern struct ssb_bus ssb_bcm47xx;
+#include <linux/ssb/ssb.h>
+
+enum bcm47xx_bus_type {
+ BCM47XX_BUS_TYPE_SSB,
+};
+
+union bcm47xx_bus {
+ struct ssb_bus ssb;
+};
+
+extern union bcm47xx_bus bcm47xx_bus;
+extern enum bcm47xx_bus_type bcm47xx_active_bus_type;
#endif /* __ASM_BCM47XX_H */
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -21,41 +21,66 @@ extern int gpio_to_irq(unsigned gpio);
static inline int gpio_get_value(unsigned gpio)
{
- return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio);
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
+ }
+ return -EINVAL;
}
static inline void gpio_set_value(unsigned gpio, int value)
{
- ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ }
}
static inline int gpio_direction_input(unsigned gpio)
{
- ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
- return 0;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
+ return 0;
+ }
+ return -EINVAL;
}
static inline int gpio_direction_output(unsigned gpio, int value)
{
- /* first set the gpio out value */
- ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
- /* then set the gpio mode */
- ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
- return 0;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ /* first set the gpio out value */
+ ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ /* then set the gpio mode */
+ ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
+ return 0;
+ }
+ return -EINVAL;
}
static inline int gpio_intmask(unsigned gpio, int value)
{
- ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
- value ? 1 << gpio : 0);
- return 0;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ return 0;
+ }
+ return -EINVAL;
}
static inline int gpio_polarity(unsigned gpio, int value)
{
- ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
- value ? 1 << gpio : 0);
- return 0;
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ return 0;
+ }
+ return -EINVAL;
}
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -54,12 +54,20 @@ static atomic_t ticks;
static inline void bcm47xx_wdt_hw_start(void)
{
/* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */
- ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff);
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
+ break;
+ }
}
static inline int bcm47xx_wdt_hw_stop(void)
{
- return ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
+ switch (bcm47xx_active_bus_type) {
+ case BCM47XX_BUS_TYPE_SSB:
+ return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+ }
+ return -EINVAL;
}
static void bcm47xx_timer_tick(unsigned long unused)

View File

@ -0,0 +1,395 @@
From 82d03f33ba3e41511e56bd6ae5ae93b3b1bd0b63 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Wed, 22 Jun 2011 22:16:35 +0200
Subject: [PATCH 11/14] bcm47xx: make it possible to build bcm47xx without ssb.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/Kconfig | 8 +-------
arch/mips/bcm47xx/Kconfig | 18 ++++++++++++++++++
arch/mips/bcm47xx/Makefile | 3 ++-
arch/mips/bcm47xx/gpio.c | 6 ++++++
arch/mips/bcm47xx/nvram.c | 4 ++++
arch/mips/bcm47xx/serial.c | 4 ++++
arch/mips/bcm47xx/setup.c | 8 ++++++++
arch/mips/bcm47xx/time.c | 2 ++
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 4 ++++
arch/mips/include/asm/mach-bcm47xx/gpio.h | 12 ++++++++++++
arch/mips/pci/pci-bcm47xx.c | 6 ++++++
drivers/watchdog/bcm47xx_wdt.c | 4 ++++
12 files changed, 71 insertions(+), 8 deletions(-)
create mode 100644 arch/mips/bcm47xx/Kconfig
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -91,15 +91,8 @@ config BCM47XX
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
- select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select SSB
- select SSB_DRIVER_MIPS
- select SSB_DRIVER_EXTIF
- select SSB_EMBEDDED
- select SSB_B43_PCI_BRIDGE if PCI
- select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
select SYS_HAS_EARLY_PRINTK
select CFE
@@ -785,6 +778,7 @@ endchoice
source "arch/mips/alchemy/Kconfig"
source "arch/mips/ath79/Kconfig"
+source "arch/mips/bcm47xx/Kconfig"
source "arch/mips/bcm63xx/Kconfig"
source "arch/mips/jazz/Kconfig"
source "arch/mips/jz4740/Kconfig"
--- /dev/null
+++ b/arch/mips/bcm47xx/Kconfig
@@ -0,0 +1,18 @@
+if BCM47XX
+
+config BCM47XX_SSB
+ bool "SSB Support for Broadcom BCM47XX"
+ select SYS_HAS_CPU_MIPS32_R1
+ select SSB
+ select SSB_DRIVER_MIPS
+ select SSB_DRIVER_EXTIF
+ select SSB_EMBEDDED
+ select SSB_B43_PCI_BRIDGE if PCI
+ select SSB_PCICORE_HOSTMODE if PCI
+ default y
+ help
+ Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support bus.
+
+ This will generate an image with support for SSB and MIPS32 R2 instruction set.
+
+endif
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,5 @@
# under Linux.
#
-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
--- a/arch/mips/bcm47xx/gpio.c
+++ b/arch/mips/bcm47xx/gpio.c
@@ -21,6 +21,7 @@ static DECLARE_BITMAP(gpio_in_use, BCM47
int gpio_request(unsigned gpio, const char *tag)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
@@ -34,6 +35,7 @@ int gpio_request(unsigned gpio, const ch
return -EBUSY;
return 0;
+#endif
}
return -EINVAL;
}
@@ -42,6 +44,7 @@ EXPORT_SYMBOL(gpio_request);
void gpio_free(unsigned gpio)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
@@ -53,6 +56,7 @@ void gpio_free(unsigned gpio)
clear_bit(gpio, gpio_in_use);
return;
+#endif
}
}
EXPORT_SYMBOL(gpio_free);
@@ -60,6 +64,7 @@ EXPORT_SYMBOL(gpio_free);
int gpio_to_irq(unsigned gpio)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
@@ -67,6 +72,7 @@ int gpio_to_irq(unsigned gpio)
return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
else
return -EINVAL;
+#endif
}
return -EINVAL;
}
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -26,7 +26,9 @@ static char nvram_buf[NVRAM_SPACE];
/* Probe for NVRAM header */
static void early_nvram_init(void)
{
+#ifdef CONFIG_BCM47XX_SSB
struct ssb_mipscore *mcore_ssb;
+#endif
struct nvram_header *header;
int i;
u32 base = 0;
@@ -35,11 +37,13 @@ static void early_nvram_init(void)
u32 *src, *dst;
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
mcore_ssb = &bcm47xx_bus.ssb.mipscore;
base = mcore_ssb->flash_window;
lim = mcore_ssb->flash_window_size;
break;
+#endif
}
off = FLASH_MIN;
--- a/arch/mips/bcm47xx/serial.c
+++ b/arch/mips/bcm47xx/serial.c
@@ -23,6 +23,7 @@ static struct platform_device uart8250_d
},
};
+#ifdef CONFIG_BCM47XX_SSB
static int __init uart8250_init_ssb(void)
{
int i;
@@ -44,12 +45,15 @@ static int __init uart8250_init_ssb(void
}
return platform_device_register(&uart8250_device);
}
+#endif
static int __init uart8250_init(void)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
return uart8250_init_ssb();
+#endif
}
return -EINVAL;
}
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -47,9 +47,11 @@ static void bcm47xx_machine_restart(char
local_irq_disable();
/* Set the watchdog timer to reset immediately */
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
break;
+#endif
}
while (1)
cpu_relax();
@@ -60,14 +62,17 @@ static void bcm47xx_machine_halt(void)
/* Disable interrupts and watchdog and spin forever */
local_irq_disable();
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
break;
+#endif
}
while (1)
cpu_relax();
}
+#ifdef CONFIG_BCM47XX_SSB
#define READ_FROM_NVRAM(_outvar, name, buf) \
if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
sprom->_outvar = simple_strtoul(buf, NULL, 0);
@@ -288,13 +293,16 @@ static void __init bcm47xx_register_ssb(
}
}
}
+#endif
void __init plat_mem_setup(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
+#ifdef CONFIG_BCM47XX_SSB
bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB;
bcm47xx_register_ssb();
+#endif
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -40,9 +40,11 @@ void __init plat_time_init(void)
write_c0_compare(0xffff);
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
break;
+#endif
}
if (!hz)
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -22,11 +22,15 @@
#include <linux/ssb/ssb.h>
enum bcm47xx_bus_type {
+#ifdef CONFIG_BCM47XX_SSB
BCM47XX_BUS_TYPE_SSB,
+#endif
};
union bcm47xx_bus {
+#ifdef CONFIG_BCM47XX_SSB
struct ssb_bus ssb;
+#endif
};
extern union bcm47xx_bus bcm47xx_bus;
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -22,8 +22,10 @@ extern int gpio_to_irq(unsigned gpio);
static inline int gpio_get_value(unsigned gpio)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
+#endif
}
return -EINVAL;
}
@@ -31,18 +33,22 @@ static inline int gpio_get_value(unsigne
static inline void gpio_set_value(unsigned gpio, int value)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
+#endif
}
}
static inline int gpio_direction_input(unsigned gpio)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
return 0;
+#endif
}
return -EINVAL;
}
@@ -50,6 +56,7 @@ static inline int gpio_direction_input(u
static inline int gpio_direction_output(unsigned gpio, int value)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
/* first set the gpio out value */
ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
@@ -57,6 +64,7 @@ static inline int gpio_direction_output(
/* then set the gpio mode */
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
return 0;
+#endif
}
return -EINVAL;
}
@@ -64,10 +72,12 @@ static inline int gpio_direction_output(
static inline int gpio_intmask(unsigned gpio, int value)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
return 0;
+#endif
}
return -EINVAL;
}
@@ -75,10 +85,12 @@ static inline int gpio_intmask(unsigned
static inline int gpio_polarity(unsigned gpio, int value)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
return 0;
+#endif
}
return -EINVAL;
}
--- a/arch/mips/pci/pci-bcm47xx.c
+++ b/arch/mips/pci/pci-bcm47xx.c
@@ -25,6 +25,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ssb/ssb.h>
+#include <bcm47xx.h>
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
@@ -33,9 +34,13 @@ int __init pcibios_map_irq(const struct
int pcibios_plat_dev_init(struct pci_dev *dev)
{
+#ifdef CONFIG_BCM47XX_SSB
int res;
u8 slot, pin;
+ if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB)
+ return 0;
+
res = ssb_pcibios_plat_dev_init(dev);
if (res < 0) {
printk(KERN_ALERT "PCI: Failed to init device %s\n",
@@ -55,5 +60,6 @@ int pcibios_plat_dev_init(struct pci_dev
}
dev->irq = res;
+#endif
return 0;
}
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -55,17 +55,21 @@ static inline void bcm47xx_wdt_hw_start(
{
/* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
break;
+#endif
}
}
static inline int bcm47xx_wdt_hw_stop(void)
{
switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+#endif
}
return -EINVAL;
}

View File

@ -0,0 +1,410 @@
From 0b7b4817579b5b283e48b96de24b7b2c1a861644 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 6 Jun 2011 00:07:37 +0200
Subject: [PATCH 12/14] bcm47xx: add support for bcma bus
This patch add support for the bcma bus. Broadcom uses only Mips 74K
CPUs on the new SoC and on the old ons using ssb bus there are no Mips
74K CPUs.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/Kconfig | 13 ++++++
arch/mips/bcm47xx/gpio.c | 22 +++++++++++
arch/mips/bcm47xx/nvram.c | 10 +++++
arch/mips/bcm47xx/serial.c | 29 ++++++++++++++
arch/mips/bcm47xx/setup.c | 53 +++++++++++++++++++++++++-
arch/mips/bcm47xx/time.c | 5 ++
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 8 ++++
arch/mips/include/asm/mach-bcm47xx/gpio.h | 41 ++++++++++++++++++++
drivers/watchdog/bcm47xx_wdt.c | 11 +++++
9 files changed, 190 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm47xx/Kconfig
+++ b/arch/mips/bcm47xx/Kconfig
@@ -15,4 +15,17 @@ config BCM47XX_SSB
This will generate an image with support for SSB and MIPS32 R2 instruction set.
+config BCM47XX_BCMA
+ bool "SSB Support for Broadcom BCM47XX"
+ select SYS_HAS_CPU_MIPS32_R2
+ select BCMA
+ select BCMA_HOST_SOC
+ select BCMA_DRIVER_MIPS
+ select BCMA_DRIVER_PCI_HOSTMODE if PCI
+ default y
+ help
+ Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
+
+ This will generate an image with support for BCMA and MIPS32 R2 instruction set.
+
endif
--- a/arch/mips/bcm47xx/gpio.c
+++ b/arch/mips/bcm47xx/gpio.c
@@ -36,6 +36,16 @@ int gpio_request(unsigned gpio, const ch
return 0;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ if ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+ return -EINVAL;
+
+ if (test_and_set_bit(gpio, gpio_in_use))
+ return -EBUSY;
+
+ return 0;
+#endif
}
return -EINVAL;
}
@@ -57,6 +67,14 @@ void gpio_free(unsigned gpio)
clear_bit(gpio, gpio_in_use);
return;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ if ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+ return;
+
+ clear_bit(gpio, gpio_in_use);
+ return;
+#endif
}
}
EXPORT_SYMBOL(gpio_free);
@@ -73,6 +91,10 @@ int gpio_to_irq(unsigned gpio)
else
return -EINVAL;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
+#endif
}
return -EINVAL;
}
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -29,6 +29,9 @@ static void early_nvram_init(void)
#ifdef CONFIG_BCM47XX_SSB
struct ssb_mipscore *mcore_ssb;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ struct bcma_drv_mips *mcore_bcma;
+#endif
struct nvram_header *header;
int i;
u32 base = 0;
@@ -44,6 +47,13 @@ static void early_nvram_init(void)
lim = mcore_ssb->flash_window_size;
break;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ mcore_bcma = &bcm47xx_bus.bcma.bus.drv_mips;
+ base = mcore_bcma->flash_window;
+ lim = mcore_bcma->flash_window_size;
+ break;
+#endif
}
off = FLASH_MIN;
--- a/arch/mips/bcm47xx/serial.c
+++ b/arch/mips/bcm47xx/serial.c
@@ -47,6 +47,31 @@ static int __init uart8250_init_ssb(void
}
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+static int __init uart8250_init_bcma(void)
+{
+ int i;
+ struct bcma_drv_mips *mcore = &(bcm47xx_bus.bcma.bus.drv_mips);
+
+ memset(&uart8250_data, 0, sizeof(uart8250_data));
+
+ for (i = 0; i < mcore->nr_serial_ports; i++) {
+ struct plat_serial8250_port *p = &(uart8250_data[i]);
+ struct bcma_drv_mips_serial_port *bcma_port;
+ bcma_port = &(mcore->serial_ports[i]);
+
+ p->mapbase = (unsigned int) bcma_port->regs;
+ p->membase = (void *) bcma_port->regs;
+ p->irq = bcma_port->irq + 2;
+ p->uartclk = bcma_port->baud_base;
+ p->regshift = bcma_port->reg_shift;
+ p->iotype = UPIO_MEM;
+ p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ }
+ return platform_device_register(&uart8250_device);
+}
+#endif
+
static int __init uart8250_init(void)
{
switch (bcm47xx_active_bus_type) {
@@ -54,6 +79,10 @@ static int __init uart8250_init(void)
case BCM47XX_BUS_TYPE_SSB:
return uart8250_init_ssb();
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return uart8250_init_bcma();
+#endif
}
return -EINVAL;
}
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -29,6 +29,7 @@
#include <linux/types.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma_soc.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
@@ -52,6 +53,11 @@ static void bcm47xx_machine_restart(char
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
break;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
+ break;
+#endif
}
while (1)
cpu_relax();
@@ -67,6 +73,11 @@ static void bcm47xx_machine_halt(void)
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
break;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
+ break;
+#endif
}
while (1)
cpu_relax();
@@ -295,16 +306,54 @@ static void __init bcm47xx_register_ssb(
}
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+static void __init bcm47xx_register_bcma(void)
+{
+ int err;
+
+ err = bcma_host_soc_register(&bcm47xx_bus.bcma);
+ if (err)
+ panic("Failed to initialize BCMA bus (err %d)\n", err);
+}
+#endif
+
void __init plat_mem_setup(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
+ if (c->cputype == CPU_74K) {
+ printk(KERN_INFO "bcm47xx: using bcma bus\n");
+#ifdef CONFIG_BCM47XX_BCMA
+ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_BCMA;
+ bcm47xx_register_bcma();
+#endif
+ } else {
+ printk(KERN_INFO "bcm47xx: using ssb bus\n");
#ifdef CONFIG_BCM47XX_SSB
- bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB;
- bcm47xx_register_ssb();
+ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB;
+ bcm47xx_register_ssb();
#endif
+ }
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;
}
+
+static int __init bcm47xx_register_bus_complete(void)
+{
+ switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ /* Nothing to do */
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_bus_register(&bcm47xx_bus.bcma.bus);
+ break;
+#endif
+ }
+ return 0;
+}
+device_initcall(bcm47xx_register_bus_complete);
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -45,6 +45,11 @@ void __init plat_time_init(void)
hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
break;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
+ break;
+#endif
}
if (!hz)
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -20,17 +20,25 @@
#define __ASM_BCM47XX_H
#include <linux/ssb/ssb.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
enum bcm47xx_bus_type {
#ifdef CONFIG_BCM47XX_SSB
BCM47XX_BUS_TYPE_SSB,
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ BCM47XX_BUS_TYPE_BCMA,
+#endif
};
union bcm47xx_bus {
#ifdef CONFIG_BCM47XX_SSB
struct ssb_bus ssb;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ struct bcma_soc bcma;
+#endif
};
extern union bcm47xx_bus bcm47xx_bus;
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -10,6 +10,7 @@
#define __BCM47XX_GPIO_H
#include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
#define BCM47XX_EXTIF_GPIO_LINES 5
@@ -26,6 +27,11 @@ static inline int gpio_get_value(unsigne
case BCM47XX_BUS_TYPE_SSB:
return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
+ 1 << gpio);
+#endif
}
return -EINVAL;
}
@@ -37,6 +43,13 @@ static inline void gpio_set_value(unsign
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
+ return;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ value ? 1 << gpio : 0);
+ return;
#endif
}
}
@@ -49,6 +62,12 @@ static inline int gpio_direction_input(u
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
return 0;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ 0);
+ return 0;
+#endif
}
return -EINVAL;
}
@@ -65,6 +84,16 @@ static inline int gpio_direction_output(
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
return 0;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ /* first set the gpio out value */
+ bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ value ? 1 << gpio : 0);
+ /* then set the gpio mode */
+ bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ 1 << gpio);
+ return 0;
+#endif
}
return -EINVAL;
}
@@ -78,6 +107,12 @@ static inline int gpio_intmask(unsigned
value ? 1 << gpio : 0);
return 0;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
+ 1 << gpio, value ? 1 << gpio : 0);
+ return 0;
+#endif
}
return -EINVAL;
}
@@ -91,6 +126,12 @@ static inline int gpio_polarity(unsigned
value ? 1 << gpio : 0);
return 0;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
+ 1 << gpio, value ? 1 << gpio : 0);
+ return 0;
+#endif
}
return -EINVAL;
}
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -60,6 +60,12 @@ static inline void bcm47xx_wdt_hw_start(
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
break;
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc,
+ 0xfffffff);
+ break;
+#endif
}
}
@@ -70,6 +76,11 @@ static inline int bcm47xx_wdt_hw_stop(vo
case BCM47XX_BUS_TYPE_SSB:
return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
+ return 0;
+#endif
}
return -EINVAL;
}

View File

@ -0,0 +1,37 @@
From 360eb82fd303ac24590a1b99ad1866162f6b0171 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 6 Jun 2011 00:07:38 +0200
Subject: [PATCH 13/14] bcm47xx: fix irq assignment for new SoCs.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/irq.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
--- a/arch/mips/bcm47xx/irq.c
+++ b/arch/mips/bcm47xx/irq.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/irq_cpu.h>
+#include <bcm47xx.h>
void plat_irq_dispatch(void)
{
@@ -51,5 +52,16 @@ void plat_irq_dispatch(void)
void __init arch_init_irq(void)
{
+#ifdef CONFIG_BCM47XX_BCMA
+ if (bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA) {
+ bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core,
+ BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31);
+ /*
+ * the kernel reads the timer irq from some register and thinks
+ * it's #5, but we offset it by 2 and route to #7
+ */
+ cp0_compare_irq = 7;
+ }
+#endif
mips_cpu_irq_init();
}

View File

@ -15,16 +15,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- a/arch/mips/bcm47xx/setup.c --- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c
@@ -29,6 +29,8 @@ @@ -30,6 +30,8 @@
#include <linux/types.h>
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h> #include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma_soc.h>
+#include <linux/serial.h> +#include <linux/serial.h>
+#include <linux/serial_8250.h> +#include <linux/serial_8250.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/time.h> #include <asm/time.h>
@@ -247,6 +249,31 @@ static int bcm47xx_get_invariants(struct @@ -274,6 +276,31 @@ static int bcm47xx_get_invariants(struct
return 0; return 0;
} }
@ -53,17 +53,17 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+} +}
+#endif +#endif
+ +
void __init plat_mem_setup(void) static void __init bcm47xx_register_ssb(void)
{ {
int err; int err;
@@ -277,6 +304,10 @@ void __init plat_mem_setup(void) @@ -303,6 +330,10 @@ static void __init bcm47xx_register_ssb(
memcpy(&mcore->serial_ports[1], &port, sizeof(port));
} }
} }
+
+#ifdef CONFIG_SERIAL_8250 +#ifdef CONFIG_SERIAL_8250
+ bcm47xx_early_serial_setup(mcore); + bcm47xx_early_serial_setup(mcore);
+#endif +#endif
+ }
_machine_restart = bcm47xx_machine_restart; #endif
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;

View File

@ -16,9 +16,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- a/arch/mips/Kconfig --- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig +++ b/arch/mips/Kconfig
@@ -101,7 +101,6 @@ config BCM47XX @@ -94,7 +94,6 @@ config BCM47XX
select SSB_B43_PCI_BRIDGE if PCI select SYS_SUPPORTS_32BIT_KERNEL
select SSB_PCICORE_HOSTMODE if PCI select SYS_SUPPORTS_LITTLE_ENDIAN
select GENERIC_GPIO select GENERIC_GPIO
- select SYS_HAS_EARLY_PRINTK - select SYS_HAS_EARLY_PRINTK
select CFE select CFE

View File

@ -1,7 +1,7 @@
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -58,6 +58,10 @@ static inline int gpio_polarity(unsigned @@ -136,6 +136,10 @@ static inline int gpio_polarity(unsigned
return 0; return -EINVAL;
} }
+static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) +static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)

View File

@ -0,0 +1,78 @@
--- a/drivers/mtd/maps/bcm47xx-flash.c
+++ b/drivers/mtd/maps/bcm47xx-flash.c
@@ -46,11 +46,9 @@
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/crc32.h>
-#ifdef CONFIG_SSB
-#include <linux/ssb/ssb.h>
-#endif
#include <asm/io.h>
#include <asm/mach-bcm47xx/nvram.h>
+#include <asm/mach-bcm47xx/bcm47xx.h>
#include <asm/fw/cfe/cfe_api.h>
@@ -90,9 +88,6 @@ struct trx_header {
#define ROUTER_NETGEAR_WNR3500L 4
#define ROUTER_SIMPLETECH_SIMPLESHARE 5
-#ifdef CONFIG_SSB
-extern struct ssb_bus ssb_bcm47xx;
-#endif
static struct mtd_info *bcm47xx_mtd;
static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
@@ -552,27 +547,42 @@ init_mtd_partitions(struct mtd_info *mtd
int __init init_bcm47xx_map(void)
{
-#ifdef CONFIG_SSB
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+#ifdef CONFIG_BCM47XX_SSB
+ struct ssb_mipscore *mcore_ssb;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ struct bcma_drv_mips *mcore_bcma;
#endif
size_t size;
int ret = 0;
+ u32 window = 0;
+ u32 window_size = 0;
struct mtd_partition *parts;
int i;
-#ifdef CONFIG_SSB
- u32 window = mcore->flash_window;
- u32 window_size = mcore->flash_window_size;
+ switch (bcm47xx_active_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ mcore_ssb = &bcm47xx_bus.ssb.mipscore;
+ window = mcore_ssb->flash_window;
+ window_size = mcore_ssb->flash_window_size;
+ bcm47xx_map.bankwidth = mcore_ssb->flash_buswidth;
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ mcore_bcma = &bcm47xx_bus.bcma.bus.drv_mips;
+ window = mcore_bcma->flash_window;
+ window_size = mcore_bcma->flash_window_size;
+ bcm47xx_map.bankwidth = mcore_bcma->flash_buswidth;
+ break;
+#endif
+ }
printk("flash init: 0x%08x 0x%08x\n", window, window_size);
bcm47xx_map.phys = window;
bcm47xx_map.size = window_size;
- bcm47xx_map.bankwidth = mcore->flash_buswidth;
bcm47xx_map.virt = ioremap_nocache(window, window_size);
-#else
- printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
- bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
-#endif
if (!bcm47xx_map.virt) {
printk("Failed to ioremap\n");

View File

@ -1,6 +1,6 @@
--- a/arch/mips/bcm47xx/nvram.c --- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c
@@ -93,3 +93,30 @@ int nvram_getenv(char *name, char *val, @@ -114,3 +114,30 @@ int nvram_getenv(char *name, char *val,
return NVRAM_ERR_ENVNOTFOUND; return NVRAM_ERR_ENVNOTFOUND;
} }
EXPORT_SYMBOL(nvram_getenv); EXPORT_SYMBOL(nvram_getenv);
@ -33,10 +33,10 @@
+EXPORT_SYMBOL(nvram_get); +EXPORT_SYMBOL(nvram_get);
--- a/arch/mips/bcm47xx/setup.c --- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c
@@ -312,3 +312,20 @@ void __init plat_mem_setup(void) @@ -388,3 +388,20 @@ static int __init bcm47xx_register_bus_c
_machine_halt = bcm47xx_machine_halt; return 0;
pm_power_off = bcm47xx_machine_halt;
} }
device_initcall(bcm47xx_register_bus_complete);
+ +
+static int __init bcm47xx_register_gpiodev(void) +static int __init bcm47xx_register_gpiodev(void)
+{ +{

View File

@ -1,14 +1,13 @@
--- a/arch/mips/bcm47xx/Makefile --- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@ @@ -4,4 +4,3 @@
# under Linux.
# #
-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o -obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
--- a/arch/mips/bcm47xx/wgt634u.c --- a/arch/mips/bcm47xx/wgt634u.c
+++ /dev/null +++ /dev/null
@@ -1,166 +0,0 @@ @@ -1,169 +0,0 @@
-/* -/*
- * This file is subject to the terms and conditions of the GNU General Public - * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive - * License. See the file "COPYING" in the main directory of this archive
@ -119,7 +118,7 @@
- -
- /* Interrupts are shared, check if the current one is - /* Interrupts are shared, check if the current one is
- a GPIO interrupt. */ - a GPIO interrupt. */
- if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco, - if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
- SSB_CHIPCO_IRQ_GPIO)) - SSB_CHIPCO_IRQ_GPIO))
- return IRQ_NONE; - return IRQ_NONE;
- -
@ -144,21 +143,24 @@
- * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx. - * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
- */ - */
- -
- u8 *et0mac = ssb_bcm47xx.sprom.et0mac; - if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB)
- return -ENODEV;
-
- u8 *et0mac = bcm47xx_bus.ssb.sprom.et0mac;
- -
- if (et0mac[0] == 0x00 && - if (et0mac[0] == 0x00 &&
- ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) || - ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
- (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) { - (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; - struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
- -
- printk(KERN_INFO "WGT634U machine detected.\n"); - printk(KERN_INFO "WGT634U machine detected.\n");
- -
- if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET), - if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
- gpio_interrupt, IRQF_SHARED, - gpio_interrupt, IRQF_SHARED,
- "WGT634U GPIO", &ssb_bcm47xx.chipco)) { - "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
- gpio_direction_input(WGT634U_GPIO_RESET); - gpio_direction_input(WGT634U_GPIO_RESET);
- gpio_intmask(WGT634U_GPIO_RESET, 1); - gpio_intmask(WGT634U_GPIO_RESET, 1);
- ssb_chipco_irq_mask(&ssb_bcm47xx.chipco, - ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
- SSB_CHIPCO_IRQ_GPIO, - SSB_CHIPCO_IRQ_GPIO,
- SSB_CHIPCO_IRQ_GPIO); - SSB_CHIPCO_IRQ_GPIO);
- } - }

View File

@ -9,8 +9,8 @@ out the configuration than the in kernel cfe config reader.
# under Linux. # under Linux.
# #
-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o -obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o cfe_env.o +obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o cfe_env.o
--- /dev/null --- /dev/null
+++ b/arch/mips/bcm47xx/cfe_env.c +++ b/arch/mips/bcm47xx/cfe_env.c
@@ -0,0 +1,229 @@ @@ -0,0 +1,229 @@
@ -254,10 +254,10 @@ out the configuration than the in kernel cfe config reader.
/* Probe for NVRAM header */ /* Probe for NVRAM header */
static void early_nvram_init(void) static void early_nvram_init(void)
@@ -34,6 +36,25 @@ static void early_nvram_init(void) @@ -55,6 +57,25 @@ static void early_nvram_init(void)
break;
base = mcore->flash_window; #endif
lim = mcore->flash_window_size; }
+ cfe_env = 0; + cfe_env = 0;
+ +
+ /* XXX: hack for supporting the CFE environment stuff on WGT634U */ + /* XXX: hack for supporting the CFE environment stuff on WGT634U */
@ -280,7 +280,7 @@ out the configuration than the in kernel cfe config reader.
off = FLASH_MIN; off = FLASH_MIN;
while (off <= lim) { while (off <= lim) {
@@ -75,6 +96,12 @@ int nvram_getenv(char *name, char *val, @@ -96,6 +117,12 @@ int nvram_getenv(char *name, char *val,
if (!nvram_buf[0]) if (!nvram_buf[0])
early_nvram_init(); early_nvram_init();
@ -293,7 +293,7 @@ out the configuration than the in kernel cfe config reader.
/* Look for name=value and return value */ /* Look for name=value and return value */
var = &nvram_buf[sizeof(struct nvram_header)]; var = &nvram_buf[sizeof(struct nvram_header)];
end = nvram_buf + sizeof(nvram_buf) - 2; end = nvram_buf + sizeof(nvram_buf) - 2;
@@ -104,6 +131,9 @@ char *nvram_get(const char *name) @@ -125,6 +152,9 @@ char *nvram_get(const char *name)
if (!nvram_buf[0]) if (!nvram_buf[0])
early_nvram_init(); early_nvram_init();

View File

@ -8,7 +8,7 @@
static int wdt_time = WDT_DEFAULT_TIME; static int wdt_time = WDT_DEFAULT_TIME;
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
@@ -50,11 +51,11 @@ static unsigned long bcm47xx_wdt_busy; @@ -50,20 +51,20 @@ static unsigned long bcm47xx_wdt_busy;
static char expect_release; static char expect_release;
static struct timer_list wdt_timer; static struct timer_list wdt_timer;
static atomic_t ticks; static atomic_t ticks;
@ -18,12 +18,22 @@
+static inline void bcm47xx_wdt_hw_start(u32 ticks) +static inline void bcm47xx_wdt_hw_start(u32 ticks)
{ {
- /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ - /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */
- ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff); switch (bcm47xx_active_bus_type) {
+ ssb_watchdog_timer_set(&ssb_bcm47xx, ticks); #ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
- ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, ticks);
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc,
- 0xfffffff);
+ ticks);
break;
#endif
} }
@@ -88,33 +89,34 @@ static inline int bcm47xx_wdt_hw_stop(vo
static inline int bcm47xx_wdt_hw_stop(void)
@@ -65,33 +66,34 @@ static inline int bcm47xx_wdt_hw_stop(vo
static void bcm47xx_timer_tick(unsigned long unused) static void bcm47xx_timer_tick(unsigned long unused)
{ {
if (!atomic_dec_and_test(&ticks)) { if (!atomic_dec_and_test(&ticks)) {
@ -70,20 +80,25 @@
} }
static int bcm47xx_wdt_settimeout(int new_time) static int bcm47xx_wdt_settimeout(int new_time)
@@ -243,7 +245,15 @@ static int __init bcm47xx_wdt_init(void) @@ -266,7 +268,20 @@ static int __init bcm47xx_wdt_init(void)
if (bcm47xx_wdt_hw_stop() < 0) if (bcm47xx_wdt_hw_stop() < 0)
return -ENODEV; return -ENODEV;
- setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); - setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L);
+ /* FIXME Other cores */ + /* FIXME Other cores */
+ if(ssb_bcm47xx.chip_id == 0x5354) { +#ifdef BCM47XX_BUS_TYPE_BCMA
+ if(bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA &&
+ bcm47xx_bus.ssb.chip_id == 0x5354) {
+ /* Slow WDT clock, no pre-scaling */ + /* Slow WDT clock, no pre-scaling */
+ needs_sw_scale = 0; + needs_sw_scale = 0;
+ } else { + } else {
+#endif
+ /* Fast WDT clock, needs software pre-scaling */ + /* Fast WDT clock, needs software pre-scaling */
+ needs_sw_scale = 1; + needs_sw_scale = 1;
+ setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); + setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L);
+#ifdef BCM47XX_BUS_TYPE_BCMA
+ } + }
+#endif
if (bcm47xx_wdt_settimeout(wdt_time)) { if (bcm47xx_wdt_settimeout(wdt_time)) {
bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME); bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME);

View File

@ -1,6 +1,6 @@
--- a/arch/mips/bcm47xx/setup.c --- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c
@@ -246,6 +246,10 @@ static int bcm47xx_get_invariants(struct @@ -273,6 +273,10 @@ static int bcm47xx_get_invariants(struct
if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);