Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jan 2010 22:43:31 GMT
From:      Rafal Jaworowski <raj@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 173052 for review
Message-ID:  <201001122243.o0CMhVMV038928@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=173052

Change 173052 by raj@raj_fdt on 2010/01/12 22:43:18

	Convert uart(4) console 'attachment' to FDT conventions.

Affected files ...

.. //depot/projects/fdt/sys/dev/uart/uart_cpu_powerpc.c#2 edit

Differences ...

==== //depot/projects/fdt/sys/dev/uart/uart_cpu_powerpc.c#2 (text) ====

@@ -36,8 +36,16 @@
 
 #include <machine/bus.h>
 
-#ifndef MPC85XX
+#ifdef FDT
+#include <sys/bus.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <machine/vmparam.h>
+#endif
+
 #include <dev/ofw/openfirm.h>
+
+#ifndef FDT
 #include <machine/ofw_machdep.h>
 #endif
 
@@ -62,22 +70,6 @@
 #endif
 }
 
-#ifdef MPC85XX
-int
-uart_cpu_getdev(int devtype, struct uart_devinfo *di)
-{
-	struct uart_class *class;
-
-	class = &uart_ns8250_class;
-	if (class == NULL)
-		class = &uart_quicc_class;
-	if (class == NULL)
-		return (ENXIO);
-
-	/* Check the environment. */
-	return (uart_getenv(devtype, di, class));
-}
-#else
 static int
 ofw_get_uart_console(phandle_t opts, phandle_t *result, const char *inputdev,
     const char *outputdev)
@@ -99,6 +91,145 @@
 	return (0);
 }
 
+#ifdef FDT
+/*
+ * Since ofw_bus_is_compatible() cannot be used at this early stage, we need
+ * a similar function locally. Note the buffer has to be on the stack since
+ * malloc() is not yet available.
+ */
+static int
+fdt_is_compatible(phandle_t node, const char *compatstr)
+{
+#define FDT_COMPAT_LEN 255
+	char *buf[FDT_COMPAT_LEN];
+	char *compat;
+	int len, onelen, l, rv;
+
+	if ((len = OF_getproplen(node, "compatible")) <= 0)
+		return (0);
+
+	compat = (char *)&buf;
+	bzero(compat, FDT_COMPAT_LEN);
+
+	if (OF_getprop(node, "compatible", compat, len) < 0)
+		return (0);
+
+	onelen = strlen(compatstr);
+	rv = 0;
+	while (len > 0) {
+		if (strncasecmp(compat, compatstr, onelen) == 0) {
+			/* Found it. */
+			rv = 1;
+			break;
+		}
+		/* Slide to the next sub-string. */
+		l = strlen(compat) + 1;
+		compat += l;
+		len -= l;
+	}
+
+	return (rv);
+}
+
+static int
+fdt_uart_addr(phandle_t node, bus_space_tag_t *tag, bus_space_handle_t *handle)
+{
+	pcell_t prop[4];
+	u_long start, size;
+	pcell_t par_addr_cells, par_size_cells;
+	int rv, tuples, tuple_size;
+	ssize_t len;
+
+	if (node == 0)
+		return (EINVAL);
+	if (tag == NULL || handle == NULL)
+		return (EINVAL);
+	if ((len = OF_getproplen(node, "reg")) <= 0)
+		return (EINVAL);
+	if (len > sizeof(prop))
+		return (ERANGE);
+
+	par_addr_cells = fdt_parent_addr_cells(node);
+	if (par_addr_cells > 0) {
+		rv = OF_searchprop(OF_parent(node), "#size-cells",
+		    &par_size_cells, sizeof(par_size_cells));
+		if (rv <= 0)
+			par_size_cells = 1;
+	} else
+		par_size_cells = 0;
+
+	tuple_size = sizeof(pcell_t) * (par_addr_cells + par_size_cells);
+	len = OF_getprop(node, "reg", prop, sizeof(prop));
+	if (len % tuple_size)
+		return (ENXIO);
+
+	tuples = len / tuple_size;
+	if (tuples <= 0)
+		return (ENXIO);
+
+	start = size = 0;
+	rv = 0;
+	*tag = uart_bus_space_io;
+
+	/*
+	 * Get address/size. XXX we assume only first 'reg' tuple is used:
+	 * uart nodes usually have only one, so this will break if the range
+	 * to be used is specified in other tuples.
+	 */
+	rv = fdt_data_to_res(prop, par_addr_cells, par_size_cells,
+	    &start, &size);
+
+	/* XXX this is an MPC85XX specific hack and needs to go away. */
+	start += CCSRBAR_VA;
+
+	rv = bus_space_map(*tag, start, size, 0, handle);
+	if (rv)
+		return (ERANGE);
+
+	return (0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+	struct uart_class *class;
+	phandle_t input, opts;
+	int error;
+
+	if (devtype != UART_DEV_CONSOLE)
+		return (ENXIO);
+
+	if ((opts = OF_finddevice("/chosen")) == 0)
+		return (ENXIO);
+
+	if (ofw_get_uart_console(opts, &input, "stdin", "stdout"))
+		return (EINVAL);
+
+	class = &uart_quicc_class;
+	if (fdt_is_compatible(input, "ns16550"))
+		class = &uart_ns8250_class;
+
+	if (OF_getprop(input, "reg-shift", &di->bas.regshft,
+	    di->bas.regshft) <= 0)
+		di->bas.regshft = 0;
+
+	di->ops = uart_getops(class);
+
+	if (OF_getprop(input, "current-speed", &di->baudrate,
+	    sizeof(di->baudrate)) <= 0)
+		di->baudrate = 0;
+
+	di->databits = 8;
+	di->stopbits = 1;
+	di->parity = UART_PARITY_NONE;
+
+	error = fdt_uart_addr(input, &di->bas.bst, &di->bas.bsh);
+	if (error)
+		return (error);
+
+	return (0);
+}
+#else
 int
 uart_cpu_getdev(int devtype, struct uart_devinfo *di)
 {



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