Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Jul 2016 17:19:47 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r303100 - head/sys/dev/uart
Message-ID:  <201607201719.u6KHJlRf018405@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Wed Jul 20 17:19:47 2016
New Revision: 303100
URL: https://svnweb.freebsd.org/changeset/base/303100

Log:
  We will be switching to a new arm64 uart cpu driver that handles both FDT
  and ACPI. As such pull out what will be the common parts of the FDT cpu
  detection to a new function that can be shared between them.
  
  Reviewed by:	manu
  Obtained from:	ABT Systems Ltd
  MFC after:	1 month
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D7262

Modified:
  head/sys/dev/uart/uart_bus_fdt.c
  head/sys/dev/uart/uart_cpu_fdt.c
  head/sys/dev/uart/uart_cpu_fdt.h

Modified: head/sys/dev/uart/uart_bus_fdt.c
==============================================================================
--- head/sys/dev/uart/uart_bus_fdt.c	Wed Jul 20 16:59:36 2016	(r303099)
+++ head/sys/dev/uart/uart_bus_fdt.c	Wed Jul 20 17:19:47 2016	(r303100)
@@ -105,6 +105,129 @@ uart_fdt_find_device(device_t dev)
 }
 
 static int
+phandle_chosen_propdev(phandle_t chosen, const char *name, phandle_t *node)
+{
+	char buf[64];
+
+	if (OF_getprop(chosen, name, buf, sizeof(buf)) <= 0)
+		return (ENXIO);
+	if ((*node = OF_finddevice(buf)) == -1)
+		return (ENXIO);
+
+	return (0);
+}
+
+static const struct ofw_compat_data *
+uart_fdt_find_compatible(phandle_t node, const struct ofw_compat_data *cd)
+{
+	const struct ofw_compat_data *ocd;
+
+	for (ocd = cd; ocd->ocd_str != NULL; ocd++) {
+		if (fdt_is_compatible(node, ocd->ocd_str))
+			return (ocd);
+	}
+	return (NULL);
+}
+
+static uintptr_t
+uart_fdt_find_by_node(phandle_t node, int class_list)
+{
+	struct ofw_compat_data **cd;
+	const struct ofw_compat_data *ocd;
+
+	if (class_list) {
+		SET_FOREACH(cd, uart_fdt_class_set) {
+			ocd = uart_fdt_find_compatible(node, *cd);
+			if ((ocd != NULL) && (ocd->ocd_data != 0))
+				return (ocd->ocd_data);
+		}
+	} else {
+		SET_FOREACH(cd, uart_fdt_class_and_device_set) {
+			ocd = uart_fdt_find_compatible(node, *cd);
+			if ((ocd != NULL) && (ocd->ocd_data != 0))
+				return (ocd->ocd_data);
+		}
+	}
+
+	return (0);
+}
+
+int
+uart_cpu_fdt_probe(struct uart_class **classp, bus_space_tag_t *bst,
+    bus_space_handle_t *bsh, int *baud, u_int *rclk, u_int *shiftp)
+{
+	const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout",
+	    "stdin-path", "stdin", NULL};
+	const char **name;
+	struct uart_class *class;
+	phandle_t node, chosen;
+	pcell_t br, clk, shift;
+	char *cp;
+	int err;
+
+	/* Has the user forced a specific device node? */
+	cp = kern_getenv("hw.fdt.console");
+	if (cp == NULL) {
+		/*
+		 * Retrieve /chosen/std{in,out}.
+		 */
+		node = -1;
+		if ((chosen = OF_finddevice("/chosen")) != -1) {
+			for (name = propnames; *name != NULL; name++) {
+				if (phandle_chosen_propdev(chosen, *name,
+				    &node) == 0)
+					break;
+			}
+		}
+		if (chosen == -1 || *name == NULL)
+			node = OF_finddevice("serial0"); /* Last ditch */
+	} else {
+		node = OF_finddevice(cp);
+	}
+
+	if (node == -1)
+		return (ENXIO);
+
+	/*
+	 * Check old style of UART definition first. Unfortunately, the common
+	 * FDT processing is not possible if we have clock, power domains and
+	 * pinmux stuff.
+	 */
+	class = (struct uart_class *)uart_fdt_find_by_node(node, 0);
+	if (class != NULL) {
+		if ((err = uart_fdt_get_clock(node, &clk)) != 0)
+			return (err);
+	} else {
+		/* Check class only linker set */
+		class =
+		    (struct uart_class *)uart_fdt_find_by_node(node, 1);
+		if (class == NULL)
+			return (ENXIO);
+		clk = 0;
+	}
+
+	/*
+	 * Retrieve serial attributes.
+	 */
+	if (uart_fdt_get_shift(node, &shift) != 0)
+		shift = uart_getregshift(class);
+
+	if (OF_getencprop(node, "current-speed", &br, sizeof(br)) <= 0)
+		br = 0;
+
+	err = OF_decode_addr(node, 0, bst, bsh, NULL);
+	if (err != 0)
+		return (err);
+
+	*classp = class;
+	*baud = br;
+	*rclk = clk;
+	*shiftp = shift;
+
+	return (0);
+}
+
+static int
 uart_fdt_probe(device_t dev)
 {
 	struct uart_softc *sc;

Modified: head/sys/dev/uart/uart_cpu_fdt.c
==============================================================================
--- head/sys/dev/uart/uart_cpu_fdt.c	Wed Jul 20 16:59:36 2016	(r303099)
+++ head/sys/dev/uart/uart_cpu_fdt.c	Wed Jul 20 17:19:47 2016	(r303100)
@@ -120,14 +120,11 @@ uart_fdt_find_by_node(phandle_t node, in
 int
 uart_cpu_getdev(int devtype, struct uart_devinfo *di)
 {
-	const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout",
-	    "stdin-path", "stdin", NULL};
-	const char **name;
 	struct uart_class *class;
-	phandle_t node, chosen;
-	pcell_t shift, br, rclk;
-	char *cp;
-	int err;
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	u_int shift, rclk;
+	int br, err;
 
 	/* Allow overriding the FDT using the environment. */
 	class = &uart_ns8250_class;
@@ -138,69 +135,24 @@ uart_cpu_getdev(int devtype, struct uart
 	if (devtype != UART_DEV_CONSOLE)
 		return (ENXIO);
 
-	/* Has the user forced a specific device node? */
-	cp = kern_getenv("hw.fdt.console");
-	if (cp == NULL) {
-		/*
-		 * Retrieve /chosen/std{in,out}.
-		 */
-		node = -1;
-		if ((chosen = OF_finddevice("/chosen")) != -1) {
-			for (name = propnames; *name != NULL; name++) {
-				if (phandle_chosen_propdev(chosen, *name,
-				    &node) == 0)
-					break;
-			}
-		}
-		if (chosen == -1 || *name == NULL)
-			node = OF_finddevice("serial0"); /* Last ditch */
-	} else {
-		node = OF_finddevice(cp);
-	}
-
-	if (node == -1) /* Can't find anything */
-		return (ENXIO);
-
-	/*
-	 * Check old style of UART definition first. Unfortunately, the common
-	 * FDT processing is not possible if we have clock, power domains and
-	 * pinmux stuff.
-	 */
-	class = (struct uart_class *)uart_fdt_find_by_node(node, 0);
-	if (class != NULL) {
-		if ((err = uart_fdt_get_clock(node, &rclk)) != 0)
-			return (err);
-	} else {
-		/* Check class only linker set */
-		class =
-		    (struct uart_class *)uart_fdt_find_by_node(node, 1);
-		if (class == NULL)
-			return (ENXIO);
-		rclk = 0;
-	}
-
-	/*
-	 * Retrieve serial attributes.
-	 */
-	if (uart_fdt_get_shift(node, &shift) != 0)
-		shift = uart_getregshift(class);
-
-	if (OF_getencprop(node, "current-speed", &br, sizeof(br)) <= 0)
-		br = 0;
+	err = uart_cpu_fdt_probe(&class, &bst, &bsh, &br, &rclk, &shift);
+	if (err != 0)
+		return (err);
 
 	/*
 	 * Finalize configuration.
 	 */
 	di->bas.chan = 0;
-	di->bas.regshft = (u_int)shift;
+	di->bas.regshft = shift;
 	di->baudrate = br;
-	di->bas.rclk = (u_int)rclk;
+	di->bas.rclk = rclk;
 	di->ops = uart_getops(class);
 	di->databits = 8;
 	di->stopbits = 1;
 	di->parity = UART_PARITY_NONE;
+	di->bas.bst = bst;
+	di->bas.bsh = bsh;
 
-	err = OF_decode_addr(node, 0, &di->bas.bst, &di->bas.bsh, NULL);
 	uart_bus_space_mem = di->bas.bst;
 	uart_bus_space_io = NULL;
 

Modified: head/sys/dev/uart/uart_cpu_fdt.h
==============================================================================
--- head/sys/dev/uart/uart_cpu_fdt.h	Wed Jul 20 16:59:36 2016	(r303099)
+++ head/sys/dev/uart/uart_cpu_fdt.h	Wed Jul 20 17:19:47 2016	(r303100)
@@ -50,6 +50,8 @@ SET_DECLARE(uart_fdt_class_set, struct o
 #define UART_FDT_CLASS(data)				\
 	DATA_SET(uart_fdt_class_set, data)
 
+int uart_cpu_fdt_probe(struct uart_class **, bus_space_tag_t *,
+    bus_space_handle_t *, int *, u_int *, u_int *);
 int uart_fdt_get_clock(phandle_t node, pcell_t *cell);
 int uart_fdt_get_shift(phandle_t node, pcell_t *cell);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607201719.u6KHJlRf018405>