Author: mmel
Date: Sun Dec 13 08:17:49 2015
New Revision: 292156
URL: https://svnweb.freebsd.org/changeset/base/292156

Log:
  OFW: Add helper functions for parsing xref based lists.
  By using this functions, we can parse a list of tuples, each of them holds
  xref and variable number of values.
  This kind of list is used in DT for clocks, gpios, resets ...
  
  Discussed with:       ian, nwhitehorn
  Approved by:  kib (mentor)
  Differential Revision: https://reviews.freebsd.org/D4316

Modified:
  head/sys/dev/ofw/ofw_bus_subr.c
  head/sys/dev/ofw/ofw_bus_subr.h

Modified: head/sys/dev/ofw/ofw_bus_subr.c
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.c     Sun Dec 13 07:39:49 2015        
(r292155)
+++ head/sys/dev/ofw/ofw_bus_subr.c     Sun Dec 13 08:17:49 2015        
(r292156)
@@ -607,3 +607,134 @@ ofw_bus_find_child_device_by_phandle(dev
 
        return (retval);
 }
+
+/*
+ * Parse property that contain list of xrefs and values
+ * (like standard "clocks" and "resets" properties)
+ * Input arguments:
+ *  node - consumers device node
+ *  list_name  - name of parsed list - "clocks"
+ *  cells_name - name of size property - "#clock-cells"
+ * Output arguments:
+ *  producer - handle of producer
+ *  ncells   - number of cells in result
+ *  cells    - array of decoded cells
+ */
+int
+ofw_bus_parse_xref_list_alloc(phandle_t node, const char *list_name,
+    const char *cells_name, int idx, phandle_t *producer, int *ncells,
+    pcell_t **cells)
+{
+       phandle_t pnode;
+       phandle_t *elems;
+       uint32_t  pcells;
+       int rv, i, j, nelems, cnt;
+
+       elems = NULL;
+       nelems = OF_getencprop_alloc(node, list_name,  sizeof(*elems),
+           (void **)&elems);
+       if (nelems <= 0)
+               return (ENOENT);
+       rv = ENOENT;
+       for (i = 0, cnt = 0; i < nelems; i += pcells, cnt++) {
+               pnode = elems[i++];
+               if (OF_getencprop(OF_node_from_xref(pnode),
+                   cells_name, &pcells, sizeof(pcells)) == -1) {
+                       printf("Missing %s property\n", cells_name);
+                       rv = ENOENT;
+                       break;
+               }
+
+               if ((i + pcells) > nelems) {
+                       printf("Invalid %s property value <%d>\n", cells_name,
+                           pcells);
+                       rv = ERANGE;
+                       break;
+               }
+               if (cnt == idx) {
+                       *cells= malloc(pcells * sizeof(**cells), M_OFWPROP,
+                           M_WAITOK);
+                       *producer = pnode;
+                       *ncells = pcells;
+                       for (j = 0; j < pcells; j++)
+                               (*cells)[j] = elems[i + j];
+                       rv = 0;
+                       break;
+               }
+       }
+       if (elems != NULL)
+               free(elems, M_OFWPROP);
+       return (rv);
+}
+
+/*
+ * Find index of string in string list property (case sensitive).
+ */
+int
+ofw_bus_find_string_index(phandle_t node, const char *list_name,
+    const char *name, int *idx)
+{
+       char *elems;
+       int rv, i, cnt, nelems;
+
+       elems = NULL;
+       nelems = OF_getprop_alloc(node, list_name, 1, (void **)&elems);
+       if (nelems <= 0)
+               return (ENOENT);
+
+       rv = ENOENT;
+       for (i = 0, cnt = 0; i < nelems; cnt++) {
+               if (strcmp(elems + i, name) == 0) {
+                       *idx = cnt;
+                       rv = 0;
+                       break;
+               }
+               i += strlen(elems + i) + 1;
+       }
+
+       if (elems != NULL)
+               free(elems, M_OFWPROP);
+       return (rv);
+}
+
+/*
+ * Create zero terminated array of strings from string list property.
+ */
+int
+ofw_bus_string_list_to_array(phandle_t node, const char *list_name,
+   const char ***array)
+{
+       char *elems, *tptr;
+       int i, cnt, nelems, len;
+
+       elems = NULL;
+       nelems = OF_getprop_alloc(node, list_name, 1, (void **)&elems);
+       if (nelems <= 0)
+               return (nelems);
+
+       /* Count number of strings. */
+       for (i = 0, cnt = 0; i < nelems; cnt++)
+               i += strlen(elems + i) + 1;
+
+       /* Allocate space for arrays and all strings. */
+       *array = malloc((cnt + 1) * sizeof(char *) + nelems, M_OFWPROP,
+           M_WAITOK);
+
+       /* Get address of first string. */
+       tptr = (char *)(*array + cnt);
+
+       /* Copy strings. */
+       memcpy(tptr, elems, nelems);
+       free(elems, M_OFWPROP);
+
+       /* Fill string pointers. */
+       for (i = 0, cnt = 0; i < nelems; cnt++) {
+               len = strlen(tptr + i) + 1;
+               *array[cnt] = tptr;
+               i += len;
+               tptr += len;
+       }
+       *array[cnt] = 0;
+
+       return (cnt);
+}

Modified: head/sys/dev/ofw/ofw_bus_subr.h
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.h     Sun Dec 13 07:39:49 2015        
(r292155)
+++ head/sys/dev/ofw/ofw_bus_subr.h     Sun Dec 13 08:17:49 2015        
(r292156)
@@ -110,4 +110,13 @@ phandle_t ofw_bus_find_child(phandle_t, 
 /* Helper routine to find a device_t child matchig a given phandle_t */
 device_t ofw_bus_find_child_device_by_phandle(device_t bus, phandle_t node);
 
+/* Helper routines for parsing lists  */
+int ofw_bus_parse_xref_list_alloc(phandle_t node, const char *list_name,
+    const char *cells_name, int idx, phandle_t *producer, int *ncells,
+    pcell_t **cells);
+int ofw_bus_find_string_index(phandle_t node, const char *list_name,
+    const char *name, int *idx);
+int ofw_bus_string_list_to_array(phandle_t node, const char *list_name,
+    const char ***array);
+
 #endif /* !_DEV_OFW_OFW_BUS_SUBR_H_ */
_______________________________________________
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