From c1d1c5d4213ee96e054c4d195117368972a4c01f Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 23 Jul 2011 01:20:14 +0200 Subject: [PATCH] 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 Acked-by: Ralf Baechle Signed-off-by: John W. Linville --- 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 | 55 ++++++++++++++++++-- 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, 191 insertions(+), 3 deletions(-) diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig index 0346f92d12a2..6210b8d84109 100644 --- 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 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 diff --git a/arch/mips/bcm47xx/gpio.c b/arch/mips/bcm47xx/gpio.c index 2b804c36750b..57b425fd4d41 100644 --- a/arch/mips/bcm47xx/gpio.c +++ b/arch/mips/bcm47xx/gpio.c @@ -36,6 +36,16 @@ int gpio_request(unsigned gpio, const char *tag) return 0; #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; } @@ -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 (gpio >= BCM47XX_CHIPCO_GPIO_LINES) + return; + + clear_bit(gpio, gpio_in_use); + return; +#endif } } EXPORT_SYMBOL(gpio_free); @@ -72,6 +90,10 @@ int gpio_to_irq(unsigned gpio) return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2; 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; diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index 4e994edb1425..a84e3bb7387f 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -28,6 +28,9 @@ static void early_nvram_init(void) { #ifdef CONFIG_BCM47XX_SSB struct ssb_mipscore *mcore_ssb; +#endif +#ifdef CONFIG_BCM47XX_BCMA + struct bcma_drv_cc *bcma_cc; #endif struct nvram_header *header; int i; @@ -43,6 +46,13 @@ static void early_nvram_init(void) base = mcore_ssb->flash_window; lim = mcore_ssb->flash_window_size; 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 } diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c index fcef68836979..57981e4fe2bc 100644 --- a/arch/mips/bcm47xx/serial.c +++ b/arch/mips/bcm47xx/serial.c @@ -47,12 +47,41 @@ static int __init uart8250_init_ssb(void) } #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) { switch (bcm47xx_bus_type) { #ifdef CONFIG_BCM47XX_SSB 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; diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 142cf1bc8884..17c3d14d7c49 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,11 @@ static void bcm47xx_machine_restart(char *command) case BCM47XX_BUS_TYPE_SSB: 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) @@ -66,6 +72,11 @@ static void bcm47xx_machine_halt(void) case BCM47XX_BUS_TYPE_SSB: 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) @@ -295,16 +306,54 @@ static void __init bcm47xx_register_ssb(void) } #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 = ¤t_cpu_data; -#ifdef CONFIG_BCM47XX_SSB - bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; - bcm47xx_register_ssb(); + 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 + bcm47xx_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_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); diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c index 03dfc65b1b60..536374dcba78 100644 --- a/arch/mips/bcm47xx/time.c +++ b/arch/mips/bcm47xx/time.c @@ -44,6 +44,11 @@ void __init plat_time_init(void) case BCM47XX_BUS_TYPE_SSB: 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 } diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h index d037afb6677e..de95e0723e2b 100644 --- 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 +#include +#include 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; diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h index 1d5f5af56b5f..76961cabeedf 100644 --- 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 +#include #include #define BCM47XX_EXTIF_GPIO_LINES 5 @@ -25,6 +26,11 @@ static inline int gpio_get_value(unsigned gpio) #ifdef CONFIG_BCM47XX_SSB 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(unsigned gpio, int value) 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 } } @@ -48,6 +61,12 @@ static inline int gpio_direction_input(unsigned gpio) case BCM47XX_BUS_TYPE_SSB: 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; @@ -64,6 +83,16 @@ static inline int gpio_direction_output(unsigned gpio, int value) /* then set the gpio mode */ 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; @@ -77,6 +106,12 @@ static inline int gpio_intmask(unsigned gpio, int value) ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio, 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; @@ -90,6 +125,12 @@ static inline int gpio_polarity(unsigned gpio, int value) ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio, 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; diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 6b037024464f..5c5f4b14fd05 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c @@ -59,6 +59,12 @@ static inline void bcm47xx_wdt_hw_start(void) case BCM47XX_BUS_TYPE_SSB: 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 } } @@ -69,6 +75,11 @@ static inline int bcm47xx_wdt_hw_stop(void) #ifdef CONFIG_BCM47XX_SSB 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;