* Re: [PATCH 1/4][MIPS] Add support for BCM47XX CPUs.
2007-09-25 13:38 [PATCH 0/4] Rename BCM947XX into BCM47XX Aurelien Jarno
@ 2007-09-25 13:40 ` Aurelien Jarno
2007-09-25 14:06 ` Ralf Baechle
2007-09-25 13:41 ` [PATCH 2/4][MIPS] Add CFE support to BCM47XX Aurelien Jarno
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Aurelien Jarno @ 2007-09-25 13:40 UTC (permalink / raw)
To: linux-mips; +Cc: Ralf Baechle
This patch replaces commit ceb550f7d4b24ee5d5de1a8f7ac07f8a2fe3bf1d in
order to replace BCM947XX into BCM47XX.
[MIPS] Add support for BCM47XX CPUs.
Note that the BCM4710 does not support the wait instruction, this
is not a mistake in the code.
It originally comes from the OpenWrt patches.
Cc: Michael Buesch <mb@bu3sch.de>
Cc: Felix Fietkau <nbd@openwrt.org>
Cc: Florian Schirmer <jolt@tuxbox.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -44,6 +44,20 @@ config BASLER_EXCITE_PROTOTYPE
note that a kernel built with this option selected will not be
able to run on normal units.
+config BCM47XX
+ bool "BCM47XX based boards"
+ 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 GENERIC_GPIO
+ help
+ Support for BCM47XX based boards
+
config MIPS_COBALT
bool "Cobalt Server"
select DMA_NONCOHERENT
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -535,6 +535,13 @@ libs-$(CONFIG_SIBYTE_BIGSUR) += arch/mips/sibyte/swarm/
load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000
#
+# Broadcom BCM47XX boards
+#
+core-$(CONFIG_BCM47XX) += arch/mips/bcm47xx/
+cflags-$(CONFIG_BCM47XX) += -Iinclude/asm-mips/mach-bcm47xx
+load-$(CONFIG_BCM47XX) := 0xffffffff80001000
+
+#
# SNI RM
#
core-$(CONFIG_SNI_RM) += arch/mips/sni/
--- /dev/null
+++ b/arch/mips/bcm47xx/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the BCM47XX specific kernel interface routines
+# under Linux.
+#
+
+obj-y := irq.o prom.o serial.o setup.o time.o
--- /dev/null
+++ b/arch/mips/bcm47xx/irq.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq_cpu.h>
+
+void plat_irq_dispatch(void)
+{
+ u32 cause;
+
+ cause = read_c0_cause() & read_c0_status() & CAUSEF_IP;
+
+ clear_c0_status(cause);
+
+ if (cause & CAUSEF_IP7)
+ do_IRQ(7);
+ if (cause & CAUSEF_IP2)
+ do_IRQ(2);
+ if (cause & CAUSEF_IP3)
+ do_IRQ(3);
+ if (cause & CAUSEF_IP4)
+ do_IRQ(4);
+ if (cause & CAUSEF_IP5)
+ do_IRQ(5);
+ if (cause & CAUSEF_IP6)
+ do_IRQ(6);
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+}
--- /dev/null
+++ b/arch/mips/bcm47xx/prom.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+const char *get_system_type(void)
+{
+ return "Broadcom BCM47XX";
+}
+
+void __init prom_init(void)
+{
+ unsigned long mem;
+
+ /* Figure out memory size by finding aliases */
+ for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
+ if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
+ *(unsigned long *)(prom_init))
+ break;
+ }
+
+ add_memory_region(0, mem, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
--- /dev/null
+++ b/arch/mips/bcm47xx/serial.c
@@ -0,0 +1,52 @@
+/*
+ * 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
+ * for more details.
+ *
+ * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/ssb/ssb.h>
+#include <bcm47xx.h>
+
+static struct plat_serial8250_port uart8250_data[5];
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ int i;
+ struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore);
+
+ 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 ssb_serial_port *ssb_port = &(mcore->serial_ports[i]);
+
+ p->mapbase = (unsigned int) ssb_port->regs;
+ p->membase = (void *) ssb_port->regs;
+ p->irq = ssb_port->irq + 2;
+ p->uartclk = ssb_port->baud_base;
+ p->regshift = ssb_port->reg_shift;
+ p->iotype = UPIO_MEM;
+ p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ }
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the BCM47XX platforms");
--- /dev/null
+++ b/arch/mips/bcm47xx/setup.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/ssb/ssb.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <bcm47xx.h>
+
+struct ssb_bus ssb_bcm47xx;
+EXPORT_SYMBOL(ssb_bcm47xx);
+
+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_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 1);
+ while (1)
+ cpu_relax();
+}
+
+static void bcm47xx_machine_halt(void)
+{
+ /* Disable interrupts and watchdog and spin forever */
+ local_irq_disable();
+ ssb_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 0);
+ while (1)
+ cpu_relax();
+}
+
+static int bcm47xx_get_invariants(struct ssb_bus *bus,
+ struct ssb_init_invariants *iv)
+{
+ /* TODO: fill ssb_init_invariants using boardtype/boardrev
+ * CFE environment variables.
+ */
+ return 0;
+}
+
+void __init plat_mem_setup(void)
+{
+ int err;
+
+ err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+ bcm47xx_get_invariants);
+ if (err)
+ panic("Failed to initialize SSB bus (err %d)\n", err);
+
+ _machine_restart = bcm47xx_machine_restart;
+ _machine_halt = bcm47xx_machine_halt;
+ pm_power_off = bcm47xx_machine_halt;
+ board_time_init = bcm47xx_time_init;
+}
+
--- /dev/null
+++ b/arch/mips/bcm47xx/time.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/init.h>
+#include <linux/ssb/ssb.h>
+#include <asm/time.h>
+#include <bcm47xx.h>
+
+void __init
+bcm47xx_time_init(void)
+{
+ unsigned long hz;
+
+ /*
+ * Use deterministic values for initial counter interrupt
+ * so that calibrate delay avoids encountering a counter wrap.
+ */
+ write_c0_count(0);
+ write_c0_compare(0xffff);
+
+ hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2;
+ if (!hz)
+ hz = 100000000;
+
+ /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */
+ mips_hpt_frequency = hz;
+}
+
+void __init
+plat_timer_setup(struct irqaction *irq)
+{
+ /* Enable the timer interrupt */
+ setup_irq(7, irq);
+}
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -159,6 +159,7 @@ static inline void check_wait(void)
case CPU_5KC:
case CPU_25KF:
case CPU_PR4450:
+ case CPU_BCM3302:
cpu_wait = r4k_wait;
break;
@@ -793,6 +794,22 @@ static inline void cpu_probe_philips(struct cpuinfo_mips *c)
}
+static inline void cpu_probe_broadcom(struct cpuinfo_mips *c)
+{
+ decode_configs(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_BCM3302:
+ c->cputype = CPU_BCM3302;
+ break;
+ case PRID_IMP_BCM4710:
+ c->cputype = CPU_BCM4710;
+ break;
+ default:
+ c->cputype = CPU_UNKNOWN;
+ break;
+ }
+}
+
__init void cpu_probe(void)
{
struct cpuinfo_mips *c = ¤t_cpu_data;
@@ -815,6 +832,9 @@ __init void cpu_probe(void)
case PRID_COMP_SIBYTE:
cpu_probe_sibyte(c);
break;
+ case PRID_COMP_BROADCOM:
+ cpu_probe_broadcom(c);
+ break;
case PRID_COMP_SANDCRAFT:
cpu_probe_sandcraft(c);
break;
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -82,6 +82,8 @@ static const char *cpu_name[] = {
[CPU_VR4181] = "NEC VR4181",
[CPU_VR4181A] = "NEC VR4181A",
[CPU_SR71000] = "Sandcraft SR71000",
+ [CPU_BCM3302] = "Broadcom BCM3302",
+ [CPU_BCM4710] = "Broadcom BCM4710",
[CPU_PR4450] = "Philips PR4450",
[CPU_LOONGSON2] = "ICT Loongson-2",
};
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -908,6 +908,8 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_4KSC:
case CPU_20KC:
case CPU_25KF:
+ case CPU_BCM3302:
+ case CPU_BCM4710:
case CPU_LOONGSON2:
if (m4kc_tlbp_war())
i_nop(p);
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -215,6 +215,12 @@
#define MACH_GROUP_WINDRIVER 28 /* Windriver boards */
#define MACH_WRPPMC 1
+/*
+ * Valid machtype for group Broadcom
+ */
+#define MACH_GROUP_BRCM 23 /* Broadcom */
+#define MACH_BCM47XX 1 /* Broadcom BCM47XX */
+
#define CL_SIZE COMMAND_LINE_SIZE
const char *get_system_type(void);
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -106,6 +106,13 @@
#define PRID_IMP_SR71000 0x0400
/*
+ * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
+ */
+
+#define PRID_IMP_BCM4710 0x4000
+#define PRID_IMP_BCM3302 0x9000
+
+/*
* Definitions for 7:0 on legacy processors
*/
@@ -217,8 +224,9 @@
#define CPU_R14000 64
#define CPU_LOONGSON1 65
#define CPU_LOONGSON2 66
-
-#define CPU_LAST 66
+#define CPU_BCM3302 67
+#define CPU_BCM4710 68
+#define CPU_LAST 68
/*
* ISA Level encodings
--- /dev/null
+++ b/include/asm-mips/mach-bcm47xx/bcm47xx.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ASM_BCM47XX_H
+#define __ASM_BCM47XX_H
+
+/* SSB bus */
+extern struct ssb_bus ssb_bcm47xx;
+
+extern void bcm47xx_time_init(void);
+
+#endif /* __ASM_BCM47XX_H */
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 2/4][MIPS] Add CFE support to BCM47XX
2007-09-25 13:38 [PATCH 0/4] Rename BCM947XX into BCM47XX Aurelien Jarno
2007-09-25 13:40 ` [PATCH 1/4][MIPS] Add support for BCM47XX CPUs Aurelien Jarno
@ 2007-09-25 13:41 ` Aurelien Jarno
2007-09-25 13:42 ` [PATCH 3/4][MIPS] Add gpio support to the BCM47XX platform Aurelien Jarno
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Aurelien Jarno @ 2007-09-25 13:41 UTC (permalink / raw)
To: linux-mips; +Cc: Ralf Baechle
This patch replaces commit 787f3e9ffdc30eabe8aa9062782dcff719ddac28 in
order to replace BCM947XX into BCM47XX.
[MIPS] Add CFE support to BCM47XX
Add CFE support to the BCM47XX code. That includes querying CFE environment
variables as well as using CFE to print messages before the serial port is
initialized (early printk).
Signed-off-by: Aurelien Jarno <aurel32@farad.aurel32.net>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -55,6 +55,8 @@ config BCM47XX
select SSB
select SSB_DRIVER_MIPS
select GENERIC_GPIO
+ select SYS_HAS_EARLY_PRINTK
+ select CFE
help
Support for BCM47XX based boards
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -23,18 +24,117 @@
*/
#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
#include <asm/bootinfo.h>
+#include <asm/fw/cfe/cfe_api.h>
+#include <asm/fw/cfe/cfe_error.h>
+
+static int cfe_cons_handle;
const char *get_system_type(void)
{
return "Broadcom BCM47XX";
}
-void __init prom_init(void)
+void prom_putchar(char c)
+{
+ while (cfe_write(cfe_cons_handle, &c, 1) == 0)
+ ;
+}
+
+static __init void prom_init_cfe(void)
+{
+ uint32_t cfe_ept;
+ uint32_t cfe_handle;
+ uint32_t cfe_eptseal;
+ int argc = fw_arg0;
+ char **envp = (char **) fw_arg2;
+ int *prom_vec = (int *) fw_arg3;
+
+ /*
+ * Check if a loader was used; if NOT, the 4 arguments are
+ * what CFE gives us (handle, 0, EPT and EPTSEAL)
+ */
+ if (argc < 0) {
+ cfe_handle = (uint32_t)argc;
+ cfe_ept = (uint32_t)envp;
+ cfe_eptseal = (uint32_t)prom_vec;
+ } else {
+ if ((int)prom_vec < 0) {
+ /*
+ * Old loader; all it gives us is the handle,
+ * so use the "known" entrypoint and assume
+ * the seal.
+ */
+ cfe_handle = (uint32_t)prom_vec;
+ cfe_ept = 0xBFC00500;
+ cfe_eptseal = CFE_EPTSEAL;
+ } else {
+ /*
+ * Newer loaders bundle the handle/ept/eptseal
+ * Note: prom_vec is in the loader's useg
+ * which is still alive in the TLB.
+ */
+ cfe_handle = prom_vec[0];
+ cfe_ept = prom_vec[2];
+ cfe_eptseal = prom_vec[3];
+ }
+ }
+
+ if (cfe_eptseal != CFE_EPTSEAL) {
+ /* too early for panic to do any good */
+ printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
+ while (1) ;
+ }
+
+ cfe_init(cfe_handle, cfe_ept);
+}
+
+static __init void prom_init_console(void)
+{
+ /* Initialize CFE console */
+ cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
+}
+
+static __init void prom_init_cmdline(void)
+{
+ char buf[CL_SIZE];
+
+ /* Get the kernel command line from CFE */
+ if (cfe_getenv("LINUX_CMDLINE", buf, CL_SIZE) >= 0) {
+ buf[CL_SIZE-1] = 0;
+ strcpy(arcs_cmdline, buf);
+ }
+
+ /* Force a console handover by adding a console= argument if needed,
+ * as CFE is not available anymore later in the boot process. */
+ if ((strstr(arcs_cmdline, "console=")) == NULL) {
+ /* Try to read the default serial port used by CFE */
+ if ((cfe_getenv("BOOT_CONSOLE", buf, CL_SIZE) < 0)
+ || (strncmp("uart", buf, 4)))
+ /* Default to uart0 */
+ strcpy(buf, "uart0");
+
+ /* Compute the new command line */
+ snprintf(arcs_cmdline, CL_SIZE, "%s console=ttyS%c,115200",
+ arcs_cmdline, buf[4]);
+ }
+}
+
+static __init void prom_init_mem(void)
{
unsigned long mem;
- /* Figure out memory size by finding aliases */
+ /* Figure out memory size by finding aliases.
+ *
+ * We should theoretically use the mapping from CFE using cfe_enummem().
+ * However as the BCM47XX is mostly used on low-memory systems, we
+ * want to reuse the memory used by CFE (around 4MB). That means cfe_*
+ * functions stop to work at some point during the boot, we should only
+ * call them at the beginning of the boot.
+ */
for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
*(unsigned long *)(prom_init))
@@ -44,6 +144,15 @@ void __init prom_init(void)
add_memory_region(0, mem, BOOT_MEM_RAM);
}
+void __init prom_init(void)
+{
+ prom_init_cfe();
+ prom_init_console();
+ prom_init_cmdline();
+ prom_init_mem();
+}
+
void __init prom_free_prom_memory(void)
{
}
+
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -27,9 +27,11 @@
#include <linux/types.h>
#include <linux/ssb/ssb.h>
+#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <bcm47xx.h>
+#include <asm/fw/cfe/cfe_api.h>
struct ssb_bus ssb_bcm47xx;
EXPORT_SYMBOL(ssb_bcm47xx);
@@ -53,12 +55,55 @@ static void bcm47xx_machine_halt(void)
cpu_relax();
}
+static void str2eaddr(char *str, char *dest)
+{
+ int i = 0;
+
+ if (str == NULL) {
+ memset(dest, 0, 6);
+ return;
+ }
+
+ for (;;) {
+ dest[i++] = (char) simple_strtoul(str, NULL, 16);
+ str += 2;
+ if (!*str++ || i == 6)
+ break;
+ }
+}
+
static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
- /* TODO: fill ssb_init_invariants using boardtype/boardrev
- * CFE environment variables.
- */
+ char buf[100];
+
+ /* Fill boardinfo structure */
+ memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
+
+ if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+ iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
+ if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
+ iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
+ if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
+ iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
+
+ /* Fill sprom structure */
+ memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
+ iv->sprom.revision = 3;
+
+ if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, iv->sprom.r1.et0mac);
+ if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, iv->sprom.r1.et1mac);
+ if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
+ iv->sprom.r1.et0phyaddr = simple_strtoul(buf, NULL, 10);
+ if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
+ iv->sprom.r1.et1phyaddr = simple_strtoul(buf, NULL, 10);
+ if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
+ iv->sprom.r1.et0mdcport = simple_strtoul(buf, NULL, 10);
+ if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
+ iv->sprom.r1.et1mdcport = simple_strtoul(buf, NULL, 10);
+
return 0;
}
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
^ permalink raw reply [flat|nested] 8+ messages in thread