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);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to