]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
MIPS: SEAD3: Probe UARTs using DT
authorPaul Burton <paul.burton@imgtec.com>
Fri, 26 Aug 2016 14:17:35 +0000 (15:17 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Tue, 4 Oct 2016 23:31:20 +0000 (01:31 +0200)
Probe the UARTs on SEAD3 boards using device tree rather than platform
code, in order to reduce the amount of the latter. This requires that
CONFIG_SERIAL_OF_PLATFORM be enabled, so enable it in sead3_defconfig.
The SEAD3 DT shim code is extended to read bootloader environment
variables to determine the appropriate UART & mode for kernel console
output & set the stdout-path property of the chosen node accordingly.

In contrast to the old platform code, which appears to have only ever
set "console=ttyS0,38400n8r" with the code in console_config never
having an effect, this will honor the "yamontty" environment variable to
select between the 2 UARTs on the board and then check the "modetty0" or
"modetty1" variable as appropriate to determine the UART configuration.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: linux-mips@linux-mips.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/14048/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/boot/dts/mti/sead3.dts
arch/mips/configs/sead3_defconfig
arch/mips/include/asm/mips-boards/sead3int.h
arch/mips/mti-sead3/sead3-dtshim.c
arch/mips/mti-sead3/sead3-init.c
arch/mips/mti-sead3/sead3-platform.c

index 051b3a9e5a9e50cd62a952ab92974cac06f7a04b..3f681c5300824c5ff497a9f97debc248fdec2a3f 100644 (file)
        compatible = "mti,sead-3";
        interrupt-parent = <&gic>;
 
+       chosen {
+               stdout-path = "uart1:115200";
+       };
+
+       aliases {
+               uart0 = &uart0;
+               uart1 = &uart1;
+       };
+
        cpus {
                cpu@0 {
                        compatible = "mti,mips14KEc", "mti,mips14Kc";
                        interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
                };
        };
+
+       /* UART connected to FTDI & miniUSB socket */
+       uart0: uart@1f000900 {
+               compatible = "ns16550a";
+               reg = <0x1f000900 0x20>;
+               reg-io-width = <4>;
+               reg-shift = <2>;
+
+               clock-frequency = <14745600>;
+
+               interrupts = <3>; /* GIC 3 or CPU 4 */
+
+               no-loopback-test;
+       };
+
+       /* UART connected to RS232 socket */
+       uart1: uart@1f000800 {
+               compatible = "ns16550a";
+               reg = <0x1f000800 0x20>;
+               reg-io-width = <4>;
+               reg-shift = <2>;
+
+               clock-frequency = <14745600>;
+
+               interrupts = <2>; /* GIC 2 or CPU 4 */
+
+               no-loopback-test;
+       };
 };
index dae9354b62563f8b4d97309861220b25b25be129..deb48fb77d1fd565441970dfcca736a933b9fa38 100644 (file)
@@ -39,6 +39,7 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_GLUEBI=y
+CONFIG_OF=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_SCSI=y
@@ -70,6 +71,7 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
index bd85da3d6770adc9d55674f36b214b9124e534c2..3a5e079fda7626640a341e1a2b5a83eb3c04ae03 100644 (file)
 
 /* CPU interrupt offsets */
 #define CPU_INT_EHCI           2
-#define CPU_INT_UART0          4
-#define CPU_INT_UART1          4
 #define CPU_INT_NET            6
 
 /* GIC interrupt offsets */
 #define GIC_INT_NET            GIC_SHARED_TO_HWIRQ(0)
-#define GIC_INT_UART1          GIC_SHARED_TO_HWIRQ(2)
-#define GIC_INT_UART0          GIC_SHARED_TO_HWIRQ(3)
 #define GIC_INT_EHCI           GIC_SHARED_TO_HWIRQ(5)
 
 #endif /* !(_MIPS_SEAD3INT_H) */
index 3283a7e19a8899f28ff7f5c6935dd580dacb6ad4..b462f65b8ce07b9117b4be23fccdebf568ff33ba 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/libfdt.h>
 #include <linux/printk.h>
 
+#include <asm/fw/fw.h>
 #include <asm/io.h>
 
 #define SEAD_CONFIG                    CKSEG1ADDR(0x1b100110)
@@ -23,7 +24,8 @@ static unsigned char fdt_buf[16 << 10] __initdata;
 
 static int remove_gic(void *fdt)
 {
-       int gic_off, cpu_off, err;
+       const unsigned int cpu_uart_int = 4;
+       int gic_off, cpu_off, uart_off, err;
        uint32_t cfg, cpu_phandle;
 
        /* leave the GIC node intact if a GIC is present */
@@ -62,6 +64,103 @@ static int remove_gic(void *fdt)
                return err;
        }
 
+       uart_off = fdt_node_offset_by_compatible(fdt, -1, "ns16550a");
+       while (uart_off >= 0) {
+               err = fdt_setprop_u32(fdt, uart_off, "interrupts",
+                                     cpu_uart_int);
+               if (err) {
+                       pr_err("unable to set UART interrupts property: %d\n",
+                              err);
+                       return err;
+               }
+
+               uart_off = fdt_node_offset_by_compatible(fdt, uart_off,
+                                                        "ns16550a");
+       }
+       if (uart_off != -FDT_ERR_NOTFOUND) {
+               pr_err("error searching for UART DT node: %d\n", uart_off);
+               return uart_off;
+       }
+
+       return 0;
+}
+
+static int serial_config(void *fdt)
+{
+       const char *yamontty, *mode_var;
+       char mode_var_name[9], path[18], parity;
+       unsigned int uart, baud, stop_bits;
+       bool hw_flow;
+       int chosen_off, err;
+
+       yamontty = fw_getenv("yamontty");
+       if (!yamontty || !strcmp(yamontty, "tty0")) {
+               uart = 0;
+       } else if (!strcmp(yamontty, "tty1")) {
+               uart = 1;
+       } else {
+               pr_warn("yamontty environment variable '%s' invalid\n",
+                       yamontty);
+               uart = 0;
+       }
+
+       baud = stop_bits = 0;
+       parity = 0;
+       hw_flow = false;
+
+       snprintf(mode_var_name, sizeof(mode_var_name), "modetty%u", uart);
+       mode_var = fw_getenv(mode_var_name);
+       if (mode_var) {
+               while (mode_var[0] >= '0' && mode_var[0] <= '9') {
+                       baud *= 10;
+                       baud += mode_var[0] - '0';
+                       mode_var++;
+               }
+               if (mode_var[0] == ',')
+                       mode_var++;
+               if (mode_var[0])
+                       parity = mode_var[0];
+               if (mode_var[0] == ',')
+                       mode_var++;
+               if (mode_var[0])
+                       stop_bits = mode_var[0] - '0';
+               if (mode_var[0] == ',')
+                       mode_var++;
+               if (!strcmp(mode_var, "hw"))
+                       hw_flow = true;
+       }
+
+       if (!baud)
+               baud = 38400;
+
+       if (parity != 'e' && parity != 'n' && parity != 'o')
+               parity = 'n';
+
+       if (stop_bits != 7 && stop_bits != 8)
+               stop_bits = 8;
+
+       WARN_ON(snprintf(path, sizeof(path), "uart%u:%u%c%u%s",
+                        uart, baud, parity, stop_bits,
+                        hw_flow ? "r" : "") >= sizeof(path));
+
+       /* find or add chosen node */
+       chosen_off = fdt_path_offset(fdt, "/chosen");
+       if (chosen_off == -FDT_ERR_NOTFOUND)
+               chosen_off = fdt_path_offset(fdt, "/chosen@0");
+       if (chosen_off == -FDT_ERR_NOTFOUND)
+               chosen_off = fdt_add_subnode(fdt, 0, "chosen");
+       if (chosen_off < 0) {
+               pr_err("Unable to find or add DT chosen node: %d\n",
+                      chosen_off);
+               return chosen_off;
+       }
+
+       err = fdt_setprop_string(fdt, chosen_off, "stdout-path", path);
+       if (err) {
+               pr_err("Unable to set stdout-path property: %d\n", err);
+               return err;
+       }
+
        return 0;
 }
 
@@ -84,6 +183,10 @@ void __init *sead3_dt_shim(void *fdt)
        if (err)
                panic("Unable to patch FDT: %d", err);
 
+       err = serial_config(fdt_buf);
+       if (err)
+               panic("Unable to patch FDT: %d", err);
+
        err = fdt_pack(fdt_buf);
        if (err)
                panic("Unable to pack FDT: %d\n", err);
index 3572ea30173ef0e42932866effc0e1b720466b32..e81f5b7657f0cfe6000e794265dcaf1e7b3f78f7 100644 (file)
 extern char except_vec_nmi;
 extern char except_vec_ejtag_debug;
 
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-static void __init console_config(void)
-{
-       char console_string[40];
-       int baud = 0;
-       char parity = '\0', bits = '\0', flow = '\0';
-       char *s;
-
-       if ((strstr(fw_getcmdline(), "console=")) == NULL) {
-               s = fw_getenv("modetty0");
-               if (s) {
-                       while (*s >= '0' && *s <= '9')
-                               baud = baud*10 + *s++ - '0';
-                       if (*s == ',')
-                               s++;
-                       if (*s)
-                               parity = *s++;
-                       if (*s == ',')
-                               s++;
-                       if (*s)
-                               bits = *s++;
-                       if (*s == ',')
-                               s++;
-                       if (*s == 'h')
-                               flow = 'r';
-               }
-               if (baud == 0)
-                       baud = 38400;
-               if (parity != 'n' && parity != 'o' && parity != 'e')
-                       parity = 'n';
-               if (bits != '7' && bits != '8')
-                       bits = '8';
-               if (flow == '\0')
-                       flow = 'r';
-               sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
-                       parity, bits, flow);
-               strcat(fw_getcmdline(), console_string);
-       }
-}
-#endif
-
 static void __init mips_nmi_setup(void)
 {
        void *base;
@@ -140,11 +99,6 @@ void __init prom_init(void)
        else if ((strstr(fw_getcmdline(), "console=ttyS1")) != NULL)
                fw_init_early_console(1);
 #endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-       if ((strstr(fw_getcmdline(), "console=")) == NULL)
-               strcat(fw_getcmdline(), " console=ttyS0,38400n8r");
-       console_config();
-#endif
 }
 
 void __init prom_free_prom_memory(void)
index d6be0298056a3341f8a5fc95d7a7df6934b57317..538a6f8f09175506ac18a19024d6900a2afec2bb 100644 (file)
 #include <linux/mtd/physmap.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/serial_8250.h>
 #include <linux/smsc911x.h>
 
 #include <asm/mips-boards/sead3int.h>
 
-#define UART(base)                                                     \
-{                                                                      \
-       .mapbase        = base,                                         \
-       .irq            = -1,                                           \
-       .uartclk        = 14745600,                                     \
-       .iotype         = UPIO_MEM32,                                   \
-       .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
-       .regshift       = 2,                                            \
-}
-
-static struct plat_serial8250_port uart8250_data[] = {
-       UART(0x1f000900),   /* ttyS0 = USB   */
-       UART(0x1f000800),   /* ttyS1 = RS232 */
-       { },
-};
-
-static struct platform_device uart8250_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_PLATFORM2,
-       .dev                    = {
-               .platform_data  = uart8250_data,
-       },
-};
-
 static struct smsc911x_platform_config sead3_smsc911x_data = {
        .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
        .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
@@ -195,7 +170,6 @@ static struct platform_device ehci_device = {
 };
 
 static struct platform_device *sead3_platform_devices[] __initdata = {
-       &uart8250_device,
        &sead3_flash,
        &pled_device,
        &fled_device,
@@ -228,15 +202,11 @@ static int __init sead3_platforms_device_init(void)
        }
 
        if (gic_present) {
-               uart8250_data[0].irq = irq_create_mapping(irqd, GIC_INT_UART0);
-               uart8250_data[1].irq = irq_create_mapping(irqd, GIC_INT_UART1);
                ehci_resources[1].start =
                        irq_create_mapping(irqd, GIC_INT_EHCI);
                sead3_net_resources[1].start =
                        irq_create_mapping(irqd, GIC_INT_NET);
        } else {
-               uart8250_data[0].irq = irq_create_mapping(irqd, CPU_INT_UART0);
-               uart8250_data[1].irq = irq_create_mapping(irqd, CPU_INT_UART1);
                ehci_resources[1].start =
                        irq_create_mapping(irqd, CPU_INT_EHCI);
                sead3_net_resources[1].start =