PERFORCE change 173052 for review
Rafal Jaworowski
raj at FreeBSD.org
Tue Jan 12 22:43:31 UTC 2010
http://p4web.freebsd.org/chv.cgi?CH=173052
Change 173052 by raj at 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)
{
More information about the p4-projects
mailing list