Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c11e3b48 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle
Browse files

MIPS: SEAD3: Probe UARTs using DT



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: default avatarPaul 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent b6d5e47e
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -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;
	};
};
+2 −0
Original line number Diff line number Diff line
@@ -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
+0 −4
Original line number Diff line number Diff line
@@ -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) */
+104 −1
Original line number Diff line number Diff line
@@ -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);
+0 −46
Original line number Diff line number Diff line
@@ -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)
Loading