CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
-CONFIG_FW_CFE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_EARLY_PRINTK_8250=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_SWCONFIG=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
--- /dev/null
+commit 0a76092a63809a0e72e3e9552acadf42869c0293
+Author: Yoichi Yuasa <yuasa@linux-mips.org>
+Date: Mon Feb 8 20:59:39 2010 +0900
+
+ MIPS: Add 8250/16550 serial early printk driver
+
+ Signed-off-by: Yoichi Yuasa <yuasa@linux-mips.org>
+ Cc: linux-mips <linux-mips@linux-mips.org>
+ Patchwork: https://patchwork.linux-mips.org/patch/947/
+ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+
+--- a/arch/mips/Kconfig.debug
++++ b/arch/mips/Kconfig.debug
+@@ -20,6 +20,14 @@ config EARLY_PRINTK
+ doesn't cooperate with an X server. You should normally say N here,
+ unless you want to debug such a crash.
+
++config EARLY_PRINTK_8250
++ bool "8250/16550 and compatible serial early printk driver"
++ depends on EARLY_PRINTK
++ default n
++ help
++ If you say Y here, it will be possible to use a 8250/16550 serial
++ port as the boot console.
++
+ config CMDLINE_BOOL
+ bool "Built-in kernel command line"
+ default n
+--- a/arch/mips/include/asm/setup.h
++++ b/arch/mips/include/asm/setup.h
+@@ -5,6 +5,14 @@
+
+ extern void setup_early_printk(void);
+
++#ifdef CONFIG_EARLY_PRINTK_8250
++extern void setup_8250_early_printk_port(unsigned long base,
++ unsigned int reg_shift, unsigned int timeout);
++#else
++static inline void setup_8250_early_printk_port(unsigned long base,
++ unsigned int reg_shift, unsigned int timeout) {}
++#endif
++
+ extern void set_handler(unsigned long offset, void *addr, unsigned long len);
+ extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
+
+--- a/arch/mips/kernel/Makefile
++++ b/arch/mips/kernel/Makefile
+@@ -84,6 +84,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
+ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
+ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
++obj-$(CONFIG_EARLY_PRINTK_8250) += early_printk_8250.o
+ obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
+ obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
+
+--- /dev/null
++++ b/arch/mips/kernel/early_printk_8250.c
+@@ -0,0 +1,66 @@
++/*
++ * 8250/16550-type serial ports prom_putchar()
++ *
++ * Copyright (C) 2010 Yoichi Yuasa <yuasa@linux-mips.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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++#include <linux/io.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++
++static void __iomem *serial8250_base;
++static unsigned int serial8250_reg_shift;
++static unsigned int serial8250_tx_timeout;
++
++void setup_8250_early_printk_port(unsigned long base, unsigned int reg_shift,
++ unsigned int timeout)
++{
++ serial8250_base = (void __iomem *)base;
++ serial8250_reg_shift = reg_shift;
++ serial8250_tx_timeout = timeout;
++}
++
++static inline u8 serial_in(int offset)
++{
++ return readb(serial8250_base + (offset << serial8250_reg_shift));
++}
++
++static inline void serial_out(int offset, char value)
++{
++ writeb(value, serial8250_base + (offset << serial8250_reg_shift));
++}
++
++void prom_putchar(char c)
++{
++ unsigned int timeout;
++ int status, bits;
++
++ if (!serial8250_base)
++ return;
++
++ timeout = serial8250_tx_timeout;
++ bits = UART_LSR_TEMT | UART_LSR_THRE;
++
++ do {
++ status = serial_in(UART_LSR);
++
++ if (--timeout == 0)
++ break;
++ } while ((status & bits) != bits);
++
++ if (timeout)
++ serial_out(UART_TX, c);
++}
--- /dev/null
+commit 808fe9c2fa81a6b3e20fe813d5410e7fd6606efa
+Author: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun Jul 18 15:11:26 2010 +0200
+
+ MIPS: BCM47XX: Remove CFE support
+
+ bcm47xx only uses the CFE code for early print to a console, but that
+ is also possible with a early print serial 8250 driver.
+
+ The CFE api init causes hangs somewhere in prom_init_cfe() on some
+ devices like the Buffalo WHR-HP-G54 and the Asus WL-520GU.
+ This was reported in https://dev.openwrt.org/ticket/4061 and
+ https://forum.openwrt.org/viewtopic.php?id=17063
+
+ This will remove all the CFE handling code from bcm47xx.
+
+ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -112,13 +112,11 @@ config BCM47XX
+ select CEVT_R4K
+ select CSRC_R4K
+ select DMA_NONCOHERENT
+- select FW_CFE
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select NO_EXCEPT_FILL
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+- select SYS_HAS_EARLY_PRINTK
+ help
+ Support for BCM47XX based boards
+
+--- a/arch/mips/bcm47xx/prom.c
++++ b/arch/mips/bcm47xx/prom.c
+@@ -30,12 +30,9 @@
+ #include <linux/spinlock.h>
+ #include <linux/smp.h>
+ #include <asm/bootinfo.h>
+-#include <asm/fw/cfe/cfe_api.h>
+-#include <asm/fw/cfe/cfe_error.h>
+ #include <bcm47xx.h>
+ #include <bcm47xx_board.h>
+
+-static int cfe_cons_handle;
+
+ static char bcm47xx_system_type[20] = "Broadcom BCM47XX";
+
+@@ -52,91 +49,6 @@ __init void bcm47xx_set_system_type(u16
+ chip_id);
+ }
+
+-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)
+-{
+- static char buf[COMMAND_LINE_SIZE] __initdata;
+-
+- /* Get the kernel command line from CFE */
+- if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
+- buf[COMMAND_LINE_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, COMMAND_LINE_SIZE) < 0)
+- || (strncmp("uart", buf, 4)))
+- /* Default to uart0 */
+- strcpy(buf, "uart0");
+-
+- /* Compute the new command line */
+- snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
+- arcs_cmdline, buf[4]);
+- }
+-}
+-
+ static __init void prom_init_mem(void)
+ {
+ unsigned long mem;
+@@ -184,9 +96,6 @@ static __init void prom_init_mem(void)
+
+ void __init prom_init(void)
+ {
+- prom_init_cfe();
+- prom_init_console();
+- prom_init_cmdline();
+ prom_init_mem();
+ }
+
--- /dev/null
+commit 22250a38f970c173acb1b3fb30e6dce1430f697b
+Author: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu Sep 19 22:48:35 2013 +0200
+
+ MIPS: BCM47XX: add EARLY_PRINTK_8250 support
+
+ The BCM47xx SoCs have a 8250 serial compatible console at address
+ 0x18000300 and an other at 0x18000400. On most devices 0x18000300 is
+ wired to some pins on the board, we should use that.
+ This is the smae for the AI (bcma) and the SB (ssb) bus, this is some
+ offset on the chip common core.
+
+ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -117,6 +117,8 @@ config BCM47XX
+ select NO_EXCEPT_FILL
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
++ select SYS_HAS_EARLY_PRINTK
++ select EARLY_PRINTK_8250 if EARLY_PRINTK
+ help
+ Support for BCM47XX based boards
+
+--- a/arch/mips/bcm47xx/prom.c
++++ b/arch/mips/bcm47xx/prom.c
+@@ -28,6 +28,8 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/spinlock.h>
++#include <linux/ssb/ssb_driver_chipcommon.h>
++#include <linux/ssb/ssb_regs.h>
+ #include <linux/smp.h>
+ #include <asm/bootinfo.h>
+ #include <bcm47xx.h>
+@@ -94,9 +96,16 @@ static __init void prom_init_mem(void)
+ add_memory_region(0, mem, BOOT_MEM_RAM);
+ }
+
++/*
++ * This is the first serial on the chip common core, it is at this position
++ * for sb (ssb) and ai (bcma) bus.
++ */
++#define BCM47XX_SERIAL_ADDR (SSB_ENUM_BASE + SSB_CHIPCO_UART0_DATA)
++
+ void __init prom_init(void)
+ {
+ prom_init_mem();
++ setup_8250_early_printk_port(CKSEG1ADDR(BCM47XX_SERIAL_ADDR), 0, 0);
+ }
+
+ void __init prom_free_prom_memory(void)
+++ /dev/null
-From 9be402f069cc259ad5795b77567d66c4e7f6bef6 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sun, 18 Jul 2010 14:59:24 +0200
-Subject: [PATCH 4/6] MIPS: BCM47xx: Setup and register serial early
-
-Swap the first and second serial if console=ttyS1 was set.
-Set it up and register it for early serial support.
-
-This patch has been in OpenWRT for a long time.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- arch/mips/bcm47xx/setup.c | 39 ++++++++++++++++++++++++++++++++++++++-
- 1 files changed, 38 insertions(+), 1 deletions(-)
-
---- a/arch/mips/bcm47xx/setup.c
-+++ b/arch/mips/bcm47xx/setup.c
-@@ -31,6 +31,8 @@
- #include <linux/ssb/ssb.h>
- #include <linux/ssb/ssb_embedded.h>
- #include <linux/bcma/bcma_soc.h>
-+#include <linux/serial.h>
-+#include <linux/serial_8250.h>
- #include <asm/bootinfo.h>
- #include <asm/prom.h>
- #include <asm/reboot.h>
-@@ -123,6 +125,31 @@ static int bcm47xx_get_invariants(struct
- return 0;
- }
-
-+#ifdef CONFIG_SERIAL_8250
-+static void __init bcm47xx_early_serial_setup(struct ssb_mipscore *mcore)
-+{
-+ int i;
-+
-+ for (i = 0; i < mcore->nr_serial_ports; i++) {
-+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
-+ struct uart_port s;
-+
-+ memset(&s, 0, sizeof(s));
-+ s.line = i;
-+ s.mapbase = (unsigned int) port->regs;
-+ s.membase = port->regs;
-+ s.irq = port->irq + 2;
-+ s.uartclk = port->baud_base;
-+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
-+ s.iotype = SERIAL_IO_MEM;
-+ s.regshift = port->reg_shift;
-+
-+ early_serial_setup(&s);
-+ }
-+ printk(KERN_DEBUG "Serial init done.\n");
-+}
-+#endif
-+
- static void __init bcm47xx_register_ssb(void)
- {
- int err;
-@@ -152,6 +179,10 @@ static void __init bcm47xx_register_ssb(
- memcpy(&mcore->serial_ports[1], &port, sizeof(port));
- }
- }
-+
-+#ifdef CONFIG_SERIAL_8250
-+ bcm47xx_early_serial_setup(mcore);
-+#endif
- }
- #endif
-
+++ /dev/null
-From 5219981646071abb6731634bf47781a53e248764 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sun, 18 Jul 2010 15:11:26 +0200
-Subject: [PATCH 6/6] MIPS: BCM47xx: Remove CFE console
-
-Do not use the CFE console. It causes hangs on some devices like the
-Buffalo WHR-HP-G54.
-This was reported in https://dev.openwrt.org/ticket/4061 and
-https://forum.openwrt.org/viewtopic.php?id=17063
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- arch/mips/Kconfig | 1 -
- arch/mips/bcm47xx/prom.c | 82 +++------------------------------------------
- 2 files changed, 6 insertions(+), 77 deletions(-)
-
---- a/arch/mips/Kconfig
-+++ b/arch/mips/Kconfig
-@@ -118,7 +118,6 @@ config BCM47XX
- select NO_EXCEPT_FILL
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_LITTLE_ENDIAN
-- select SYS_HAS_EARLY_PRINTK
- help
- Support for BCM47XX based boards
-
---- a/arch/mips/bcm47xx/prom.c
-+++ b/arch/mips/bcm47xx/prom.c
-@@ -35,8 +35,6 @@
- #include <bcm47xx.h>
- #include <bcm47xx_board.h>
-
--static int cfe_cons_handle;
--
- static char bcm47xx_system_type[20] = "Broadcom BCM47XX";
-
- const char *get_system_type(void)
-@@ -52,89 +50,23 @@ __init void bcm47xx_set_system_type(u16
- chip_id);
- }
-
--void prom_putchar(char c)
--{
-- while (cfe_write(cfe_cons_handle, &c, 1) == 0)
-- ;
--}
--
--static __init void prom_init_cfe(void)
-+static __init int 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];
-- }
-- }
-+
-+ cfe_eptseal = (uint32_t) fw_arg3;
-+ cfe_handle = (uint32_t) fw_arg0;
-+ cfe_ept = (uint32_t) fw_arg2;
-
- 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) ;
-+ return -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)
--{
-- static char buf[COMMAND_LINE_SIZE] __initdata;
--
-- /* Get the kernel command line from CFE */
-- if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
-- buf[COMMAND_LINE_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, COMMAND_LINE_SIZE) < 0)
-- || (strncmp("uart", buf, 4)))
-- /* Default to uart0 */
-- strcpy(buf, "uart0");
--
-- /* Compute the new command line */
-- snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
-- arcs_cmdline, buf[4]);
-- }
-+ return 0;
- }
-
- static __init void prom_init_mem(void)
-@@ -185,8 +117,6 @@ static __init void prom_init_mem(void)
- void __init prom_init(void)
- {
- prom_init_cfe();
-- prom_init_console();
-- prom_init_cmdline();
- prom_init_mem();
- }
-
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
-@@ -33,6 +33,7 @@
+@@ -31,6 +31,7 @@
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma_soc.h>
- #include <linux/serial.h>
- #include <linux/serial_8250.h>
+#include <linux/gpio_wdt.h>
#include <asm/bootinfo.h>
#include <asm/prom.h>
#include <asm/reboot.h>
-@@ -260,6 +261,33 @@ void __init plat_mem_setup(void)
+@@ -229,6 +230,33 @@ void __init plat_mem_setup(void)
mips_set_machine_name(bcm47xx_board_get_name());
}
static int __init bcm47xx_register_bus_complete(void)
{
switch (bcm47xx_bus_type) {
-@@ -274,6 +302,8 @@ static int __init bcm47xx_register_bus_c
+@@ -243,6 +271,8 @@ static int __init bcm47xx_register_bus_c
break;
#endif
}
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
-@@ -123,6 +123,10 @@ static int bcm47xx_get_invariants(struct
+@@ -121,6 +121,10 @@ static int bcm47xx_get_invariants(struct
if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);