Skip to contentSkip to conversation

serial: pl011: honour serial aliases in device tree

PATCH Superseded Matthew Leach 2 participants 2 messages Aug 21, 2012

Subsystems (2)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 serial: pl011: honour serial aliases in device tree

If the order of UART nodes is changed in the device tree, then tty dev devices are attached to different serial ports causing the console to be directed to a different physical serial port. The "serial" aliases in the device tree should prevent this.

This patch ensures that the UART driver creates tty devices that honour these aliases if a device tree is present.

---
 drivers/tty/serial/amba-pl011.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)
drivers/tty/serial/amba-pl011.c +39 -0
index c17923e..5919599 100644
@@ -52,6 +52,7 @@
 #include <linux/scatterlist.h>
 #include <linux/delay.h>
 #include <linux/types.h>
+#include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
 
 #include <asm/io.h>
@@ -1869,6 +1870,42 @@ static struct uart_driver amba_reg = {
 	.cons			= AMBA_CONSOLE,
 };
 
+#ifdef CONFIG_OF
+static int pl011_probe_dt_alias(int index, struct device *dev)
+{
+	struct device_node *np;
+	static bool seen_dev_with_alias = false;
+	static bool seen_dev_without_alias = false;
+	int ret = index;
+
+	np = dev->of_node;
+	if (!np)
+		return ret;
+
+	ret = of_alias_get_id(np, "serial");
+	if (IS_ERR_VALUE(ret)) {
+		seen_dev_without_alias = true;
+		ret = index;
+	} else {
+		seen_dev_with_alias = true;
+		if (ret >= ARRAY_SIZE(amba_ports) || amba_ports[ret] != NULL) {
+			dev_warn(dev, "requested serial port %d  not available.\n", ret);
+			ret = index;
+		}
+	}
+
+	if (seen_dev_with_alias && seen_dev_without_alias)
+		dev_warn(dev, "aliased and non-aliased serial devices found in device tree. Serial port enumeration may be unpredictable.\n");
+
+	return ret;
+}
+#else
+static int pl011_probe_dt_alias(int index, struct device *dev)
+{
+	return index;
+}
+#endif
+
 static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct uart_amba_port *uap;
@@ -1891,6 +1928,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		goto out;
 	}
 
+	i = pl011_probe_dt_alias(i, &dev->dev);
+
 	base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!base) {
 		ret = -ENOMEM;
Signature · 1 line
1.7.0.4
#1 lore raw

PATCH 1/1 serial: pl011: honour serial aliases in device tree

Quoted 9 lines · Matthew Leach

If the order of UART nodes is changed in the device tree, then tty dev devices are attached to different serial ports causing the console to be directed to a different physical serial port. The "serial" aliases in the device tree should prevent this.

This patch ensures that the UART driver creates tty devices that honour these aliases if a device tree is present.

One comment/question below, but otherwise:

Quoted 17 lines
---
 drivers/tty/serial/amba-pl011.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)
drivers/tty/serial/amba-pl011.c +1 -0
index c17923e..5919599 100644
@@ -52,6 +52,7 @@
 #include <linux/scatterlist.h>
 #include <linux/delay.h>
 #include <linux/types.h>
+#include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
 
 #include <asm/io.h>

drivers/tty/serial/amba-pl011.c static struct uart_driver amba_reg = { · line 1873

Quoted 4 lines
drivers/tty/serial/amba-pl011.c +1 -0
@@ -1869,6 +1870,42 @@ static struct uart_driver amba_reg = {
 	.cons			= AMBA_CONSOLE,
 };
 
+#ifdef CONFIG_OF

Now that we have IS_ENABLED, perhaps we want to put this inside the function instead?

if (!IS_ENABLED(CONFIG_OF))

	return index;
Quoted 48 lines
drivers/tty/serial/amba-pl011.c +37 -0
+static int pl011_probe_dt_alias(int index, struct device *dev)
+{
+	struct device_node *np;
+	static bool seen_dev_with_alias = false;
+	static bool seen_dev_without_alias = false;
+	int ret = index;
+
+	np = dev->of_node;
+	if (!np)
+		return ret;
+
+	ret = of_alias_get_id(np, "serial");
+	if (IS_ERR_VALUE(ret)) {
+		seen_dev_without_alias = true;
+		ret = index;
+	} else {
+		seen_dev_with_alias = true;
+		if (ret >= ARRAY_SIZE(amba_ports) || amba_ports[ret] != NULL) {
+			dev_warn(dev, "requested serial port %d  not available.\n", ret);
+			ret = index;
+		}
+	}
+
+	if (seen_dev_with_alias && seen_dev_without_alias)
+		dev_warn(dev, "aliased and non-aliased serial devices found in device tree. Serial port enumeration may be unpredictable.\n");
+
+	return ret;
+}
+#else
+static int pl011_probe_dt_alias(int index, struct device *dev)
+{
+	return index;
+}
+#endif
+
 static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct uart_amba_port *uap;
@@ -1891,6 +1928,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		goto out;
 	}
 
+	i = pl011_probe_dt_alias(i, &dev->dev);
+
 	base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!base) {
 		ret = -ENOMEM;