[PATCH v2 03/19] MIPS: SEAD3: Probe UARTs using DT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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@xxxxxxxxxx>

---

Changes in v2:
- #include <asm/fw/fw.h>, thanks kbuild test robot!

 arch/mips/boot/dts/mti/sead3.dts             |  37 ++++++++++
 arch/mips/configs/sead3_defconfig            |   2 +
 arch/mips/include/asm/mips-boards/sead3int.h |   4 -
 arch/mips/mti-sead3/sead3-dtshim.c           | 105 ++++++++++++++++++++++++++-
 arch/mips/mti-sead3/sead3-init.c             |  46 ------------
 arch/mips/mti-sead3/sead3-platform.c         |  30 --------
 6 files changed, 143 insertions(+), 81 deletions(-)

diff --git a/arch/mips/boot/dts/mti/sead3.dts b/arch/mips/boot/dts/mti/sead3.dts
index 051b3a9..3f681c5 100644
--- a/arch/mips/boot/dts/mti/sead3.dts
+++ b/arch/mips/boot/dts/mti/sead3.dts
@@ -12,6 +12,15 @@
 	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";
@@ -50,4 +59,32 @@
 			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;
+	};
 };
diff --git a/arch/mips/configs/sead3_defconfig b/arch/mips/configs/sead3_defconfig
index dae9354..deb48fb 100644
--- a/arch/mips/configs/sead3_defconfig
+++ b/arch/mips/configs/sead3_defconfig
@@ -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
diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h
index bd85da3..3a5e079 100644
--- a/arch/mips/include/asm/mips-boards/sead3int.h
+++ b/arch/mips/include/asm/mips-boards/sead3int.h
@@ -14,14 +14,10 @@
 
 /* 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) */
diff --git a/arch/mips/mti-sead3/sead3-dtshim.c b/arch/mips/mti-sead3/sead3-dtshim.c
index 3283a7e..b462f65 100644
--- a/arch/mips/mti-sead3/sead3-dtshim.c
+++ b/arch/mips/mti-sead3/sead3-dtshim.c
@@ -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);
diff --git a/arch/mips/mti-sead3/sead3-init.c b/arch/mips/mti-sead3/sead3-init.c
index 3572ea3..e81f5b7 100644
--- a/arch/mips/mti-sead3/sead3-init.c
+++ b/arch/mips/mti-sead3/sead3-init.c
@@ -17,47 +17,6 @@
 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)
diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c
index d6be029..538a6f8 100644
--- a/arch/mips/mti-sead3/sead3-platform.c
+++ b/arch/mips/mti-sead3/sead3-platform.c
@@ -14,35 +14,10 @@
 #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 =
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux