Commit c1d1c5d4 authored by Hauke Mehrtens's avatar Hauke Mehrtens Committed by John W. Linville

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: default avatarHauke Mehrtens <hauke@hauke-m.de>
Acked-by: default avatarRalf Baechle <ralf@linux-mips.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a656ffcb
...@@ -15,4 +15,17 @@ config BCM47XX_SSB ...@@ -15,4 +15,17 @@ config BCM47XX_SSB
This will generate an image with support for SSB and MIPS32 R1 instruction set. This will generate an image with support for SSB and MIPS32 R1 instruction set.
config BCM47XX_BCMA
bool "BCMA 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 endif
...@@ -36,6 +36,16 @@ int gpio_request(unsigned gpio, const char *tag) ...@@ -36,6 +36,16 @@ int gpio_request(unsigned gpio, const char *tag)
return 0; return 0;
#endif #endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
return -EINVAL;
if (test_and_set_bit(gpio, gpio_in_use))
return -EBUSY;
return 0;
#endif
} }
return -EINVAL; return -EINVAL;
} }
...@@ -57,6 +67,14 @@ void gpio_free(unsigned gpio) ...@@ -57,6 +67,14 @@ void gpio_free(unsigned gpio)
clear_bit(gpio, gpio_in_use); clear_bit(gpio, gpio_in_use);
return; return;
#endif #endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
return;
clear_bit(gpio, gpio_in_use);
return;
#endif
} }
} }
EXPORT_SYMBOL(gpio_free); EXPORT_SYMBOL(gpio_free);
...@@ -72,6 +90,10 @@ int gpio_to_irq(unsigned gpio) ...@@ -72,6 +90,10 @@ int gpio_to_irq(unsigned gpio)
return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2; return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
else else
return -EINVAL; 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 #endif
} }
return -EINVAL; return -EINVAL;
......
...@@ -28,6 +28,9 @@ static void early_nvram_init(void) ...@@ -28,6 +28,9 @@ static void early_nvram_init(void)
{ {
#ifdef CONFIG_BCM47XX_SSB #ifdef CONFIG_BCM47XX_SSB
struct ssb_mipscore *mcore_ssb; struct ssb_mipscore *mcore_ssb;
#endif
#ifdef CONFIG_BCM47XX_BCMA
struct bcma_drv_cc *bcma_cc;
#endif #endif
struct nvram_header *header; struct nvram_header *header;
int i; int i;
...@@ -43,6 +46,13 @@ static void early_nvram_init(void) ...@@ -43,6 +46,13 @@ static void early_nvram_init(void)
base = mcore_ssb->flash_window; base = mcore_ssb->flash_window;
lim = mcore_ssb->flash_window_size; lim = mcore_ssb->flash_window_size;
break; break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
base = bcma_cc->pflash.window;
lim = bcma_cc->pflash.window_size;
break;
#endif #endif
} }
......
...@@ -47,12 +47,41 @@ static int __init uart8250_init_ssb(void) ...@@ -47,12 +47,41 @@ static int __init uart8250_init_ssb(void)
} }
#endif #endif
#ifdef CONFIG_BCM47XX_BCMA
static int __init uart8250_init_bcma(void)
{
int i;
struct bcma_drv_cc *cc = &(bcm47xx_bus.bcma.bus.drv_cc);
memset(&uart8250_data, 0, sizeof(uart8250_data));
for (i = 0; i < cc->nr_serial_ports; i++) {
struct plat_serial8250_port *p = &(uart8250_data[i]);
struct bcma_serial_port *bcma_port;
bcma_port = &(cc->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) static int __init uart8250_init(void)
{ {
switch (bcm47xx_bus_type) { switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB #ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
return uart8250_init_ssb(); return uart8250_init_ssb();
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
return uart8250_init_bcma();
#endif #endif
} }
return -EINVAL; return -EINVAL;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/types.h> #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 <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/time.h> #include <asm/time.h>
...@@ -51,6 +52,11 @@ static void bcm47xx_machine_restart(char *command) ...@@ -51,6 +52,11 @@ static void bcm47xx_machine_restart(char *command)
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1); ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
break; 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 #endif
} }
while (1) while (1)
...@@ -66,6 +72,11 @@ static void bcm47xx_machine_halt(void) ...@@ -66,6 +72,11 @@ static void bcm47xx_machine_halt(void)
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
break; 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 #endif
} }
while (1) while (1)
...@@ -295,16 +306,54 @@ static void __init bcm47xx_register_ssb(void) ...@@ -295,16 +306,54 @@ static void __init bcm47xx_register_ssb(void)
} }
#endif #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) void __init plat_mem_setup(void)
{ {
struct cpuinfo_mips *c = &current_cpu_data; 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_bus_type = BCM47XX_BUS_TYPE_BCMA;
bcm47xx_register_bcma();
#endif
} else {
printk(KERN_INFO "bcm47xx: using ssb bus\n");
#ifdef CONFIG_BCM47XX_SSB #ifdef CONFIG_BCM47XX_SSB
bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
bcm47xx_register_ssb(); bcm47xx_register_ssb();
#endif #endif
}
_machine_restart = bcm47xx_machine_restart; _machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt; _machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt; pm_power_off = bcm47xx_machine_halt;
} }
static int __init bcm47xx_register_bus_complete(void)
{
switch (bcm47xx_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);
...@@ -44,6 +44,11 @@ void __init plat_time_init(void) ...@@ -44,6 +44,11 @@ void __init plat_time_init(void)
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2; hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
break; break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
break;
#endif #endif
} }
......
...@@ -20,17 +20,25 @@ ...@@ -20,17 +20,25 @@
#define __ASM_BCM47XX_H #define __ASM_BCM47XX_H
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#include <linux/bcma/bcma.h>
#include <linux/bcma/bcma_soc.h>
enum bcm47xx_bus_type { enum bcm47xx_bus_type {
#ifdef CONFIG_BCM47XX_SSB #ifdef CONFIG_BCM47XX_SSB
BCM47XX_BUS_TYPE_SSB, BCM47XX_BUS_TYPE_SSB,
#endif #endif
#ifdef CONFIG_BCM47XX_BCMA
BCM47XX_BUS_TYPE_BCMA,
#endif
}; };
union bcm47xx_bus { union bcm47xx_bus {
#ifdef CONFIG_BCM47XX_SSB #ifdef CONFIG_BCM47XX_SSB
struct ssb_bus ssb; struct ssb_bus ssb;
#endif #endif
#ifdef CONFIG_BCM47XX_BCMA
struct bcma_soc bcma;
#endif
}; };
extern union bcm47xx_bus bcm47xx_bus; extern union bcm47xx_bus bcm47xx_bus;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define __BCM47XX_GPIO_H #define __BCM47XX_GPIO_H
#include <linux/ssb/ssb_embedded.h> #include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma.h>
#include <asm/mach-bcm47xx/bcm47xx.h> #include <asm/mach-bcm47xx/bcm47xx.h>
#define BCM47XX_EXTIF_GPIO_LINES 5 #define BCM47XX_EXTIF_GPIO_LINES 5
...@@ -25,6 +26,11 @@ static inline int gpio_get_value(unsigned gpio) ...@@ -25,6 +26,11 @@ static inline int gpio_get_value(unsigned gpio)
#ifdef CONFIG_BCM47XX_SSB #ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio); 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 #endif
} }
return -EINVAL; return -EINVAL;
...@@ -37,6 +43,13 @@ static inline void gpio_set_value(unsigned gpio, int value) ...@@ -37,6 +43,13 @@ static inline void gpio_set_value(unsigned gpio, int value)
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0); 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 #endif
} }
} }
...@@ -48,6 +61,12 @@ static inline int gpio_direction_input(unsigned gpio) ...@@ -48,6 +61,12 @@ static inline int gpio_direction_input(unsigned gpio)
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0); ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
return 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 #endif
} }
return -EINVAL; return -EINVAL;
...@@ -64,6 +83,16 @@ static inline int gpio_direction_output(unsigned gpio, int value) ...@@ -64,6 +83,16 @@ static inline int gpio_direction_output(unsigned gpio, int value)
/* then set the gpio mode */ /* then set the gpio mode */
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio); ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
return 0; 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 #endif
} }
return -EINVAL; return -EINVAL;
...@@ -77,6 +106,12 @@ static inline int gpio_intmask(unsigned gpio, int value) ...@@ -77,6 +106,12 @@ static inline int gpio_intmask(unsigned gpio, int value)
ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio, ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0); value ? 1 << gpio : 0);
return 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 #endif
} }
return -EINVAL; return -EINVAL;
...@@ -90,6 +125,12 @@ static inline int gpio_polarity(unsigned gpio, int value) ...@@ -90,6 +125,12 @@ static inline int gpio_polarity(unsigned gpio, int value)
ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio, ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0); value ? 1 << gpio : 0);
return 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 #endif
} }
return -EINVAL; return -EINVAL;
......
...@@ -59,6 +59,12 @@ static inline void bcm47xx_wdt_hw_start(void) ...@@ -59,6 +59,12 @@ static inline void bcm47xx_wdt_hw_start(void)
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
break; 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 #endif
} }
} }
...@@ -69,6 +75,11 @@ static inline int bcm47xx_wdt_hw_stop(void) ...@@ -69,6 +75,11 @@ static inline int bcm47xx_wdt_hw_stop(void)
#ifdef CONFIG_BCM47XX_SSB #ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB: case BCM47XX_BUS_TYPE_SSB:
return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); 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 #endif
} }
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment