This is an automated email from the ASF dual-hosted git repository.

GUIDINGLI pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 774397b3328 drivers/reset: Add line read-back and a procfs entry.
774397b3328 is described below

commit 774397b33286112eada0e4efe40bd7c3b94174c1
Author: Justin Hammond <[email protected]>
AuthorDate: Sun Aug 2 16:11:01 2026 +0800

    drivers/reset: Add line read-back and a procfs entry.
    
    status() reads one reset line at a time, and only for a caller that
    already knows the id.  Nothing else in the interface says how many lines
    a controller has or what any of them resets, so the lines a board is
    holding cannot be surveyed.
    
    Adds an optional get_line method describing one line as a structure: its
    name, and a text member for controller specific fields the structure
    does not cover.  The asserted state stays with status(), which already
    reports it, so a controller does not supply the same fact twice.
    Returning -ENODEV reports an id that names no line, which is how
    controllers with gaps in their numbering are handled.
    reset_controller_dev gains the line count that bounds the ids.
    
    CONFIG_RESET_PROCFS adds /proc/reset, one key:value line per reset line,
    every line the same tokens in the same order so the file is machine
    parseable.  A controller without get_line is listed by name and a note.
    
    The controller list already existed for reset_control_get() to search,
    so the renderer only walks what was there.  /proc/reset is claimed when
    the first controller registers; procfs_register() requires that procfs
    is not yet mounted, which holds because controllers register during
    board or architecture start up, and it appends without checking for
    duplicates, so the entry is claimed once for the lifetime of the system.
    
    Documents the framework, which had a page with nothing on it: the
    consumer interface and what shared and exclusive handles mean, the
    controller interface, the new method, and /proc/reset.
    
    Off by default and costs nothing when off.  No in-tree configuration
    enables RESET, so this builds only when a board turns it on.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Justin Hammond <[email protected]>
---
 Documentation/components/drivers/special/reset.rst | 225 ++++++++++++++
 drivers/reset/Kconfig                              |  14 +
 drivers/reset/core.c                               | 346 +++++++++++++++++++++
 include/nuttx/reset/reset-controller.h             |  40 +++
 4 files changed, 625 insertions(+)

diff --git a/Documentation/components/drivers/special/reset.rst 
b/Documentation/components/drivers/special/reset.rst
index 64bf4683e4c..bc679709e7e 100644
--- a/Documentation/components/drivers/special/reset.rst
+++ b/Documentation/components/drivers/special/reset.rst
@@ -1,3 +1,228 @@
 ============
 Reset Driver
 ============
+
+Many SoCs hold their peripherals in reset until software releases them, and
+share one reset line between several peripherals.  The reset framework lets a
+driver ask for the line its device needs and assert or release it, without
+knowing which register holds the bit or who else shares it.
+
+A **reset controller** is the hardware block that owns the lines, described by
+``struct reset_controller_dev`` and registered by an architecture or board.  A
+**reset control** is one consumer's handle on one line, obtained by name or by
+index and released when the consumer is done.
+
+``include/nuttx/reset/reset.h`` declares what a consumer uses;
+``include/nuttx/reset/reset-controller.h`` declares what a controller
+implements.  ``CONFIG_RESET`` builds the framework.
+
+Consumer interface
+==================
+
+A consumer obtains a handle on one line of a named controller, uses it, and
+puts it back:
+
+.. code-block:: c
+
+   FAR struct reset_control *rstc;
+
+   rstc = reset_control_get_exclusive_by_index("mychip-reset", 12);
+   if (rstc == NULL)
+     {
+       return -ENODEV;
+     }
+
+   reset_control_deassert(rstc);           /* let the peripheral run */
+   ...
+   reset_control_put(rstc);
+
+``reset_control_get()`` takes the controller name, the line's index, and
+whether the handle is shared and already acquired.  The wrappers name the
+usual combinations, and are what a driver should normally call:
+
+   ========================================== ============================
+   Function                                   Handle
+   ========================================== ============================
+   ``reset_control_get_exclusive()``          exclusive, acquired
+   ``reset_control_get_exclusive_released()`` exclusive, not yet acquired
+   ``reset_control_get_shared()``             shared
+   ``reset_control_get_exclusive_by_index()`` exclusive, acquired, by index
+   ``reset_control_get_shared_by_index()``    shared, by index
+   ========================================== ============================
+
+``reset_control_array_get()`` takes several lines of one controller as a
+single handle, so that one call asserts or releases all of them.
+
+The operations are:
+
+``reset_control_assert()``
+  Put the line into reset and leave it there.
+
+``reset_control_deassert()``
+  Take the line out of reset.
+
+``reset_control_reset()``
+  Pulse a self deasserting reset: the controller asserts and releases the line
+  itself.  For a line that resets automatically this is the only correct
+  operation; asserting such a line by hand is not meaningful.
+
+``reset_control_status()``
+  Report the line's state.  Returns 1 while the line is asserted, 0 once it is
+  released, or a negated errno.  ``-ENOTSUP`` means the controller cannot read
+  the line back.
+
+``reset_control_acquire()`` and ``reset_control_release()``
+  Take and give back the right to drive an exclusive line.  A handle from
+  ``reset_control_get_exclusive()`` arrives already acquired; one from
+  ``reset_control_get_exclusive_released()`` does not, and asserting it before
+  acquiring returns ``-EPERM``.  This lets two drivers share a line in turn
+  without either holding it permanently.
+
+``reset_control_put()``
+  Give the handle back.
+
+``reset_control_device_reset()``
+  Pulse the reset of a named device without holding a handle across the call.
+
+Shared and exclusive lines
+--------------------------
+
+One line often resets several peripherals at once, and a **shared** handle is
+how a driver says it is not the only user.  Shared handles are counted:
+``reset_control_deassert()`` releases the line on the first call and only
+counts on later ones, and ``reset_control_assert()`` asserts it only when the
+last consumer has asserted.  A driver therefore gets its peripheral running
+without deciding on behalf of the others when it may stop.
+
+An **exclusive** handle assumes a single owner and drives the line
+immediately.  Mixing the two on one line defeats the counting, so ask for what
+the hardware really is: an exclusive handle on a shared line lets one driver
+reset a peripheral another is still using.
+
+Shared handles must not be pulsed and asserted by the same consumer:
+``reset_control_reset()`` and ``reset_control_assert()`` each refuse with
+``-EINVAL`` if the other has been used on that handle.
+
+Controller interface
+====================
+
+A controller fills in ``struct reset_controller_dev`` and calls
+``reset_controller_register()``:
+
+.. code-block:: c
+
+   static struct reset_controller_dev g_mychip_rcdev =
+   {
+     .name   = "mychip-reset",
+     .ops    = &g_mychip_reset_ops,
+     .nlines = MYCHIP_NRESETS,
+   };
+
+   reset_controller_register(&g_mychip_rcdev);
+
+``name`` identifies the controller to ``reset_control_get()`` and heads its
+section in ``/proc/reset``.  ``nlines`` bounds the ids ``get_line()`` is asked
+about, which are 0 to ``nlines - 1``; since controllers commonly leave gaps it
+is an id space rather than a count of real lines.  Leave it zero if the
+controller does not implement ``get_line()``.  The structure must outlive 
registration, since the
+framework stores the pointer rather than copying.
+
+``struct reset_control_ops`` is the call table.  Every member is optional; a
+consumer calling an operation the controller does not provide gets an error
+rather than silence, though which error depends on the path:
+
+   ============== =========================================================
+   Method         Purpose
+   ============== =========================================================
+   ``reset``      Pulse a self deasserting reset on one line
+   ``assert``     Put one line into reset
+   ``deassert``   Take one line out of reset
+   ``status``     Report whether one line is asserted; 1 asserted, 0 not
+   ``acquire``    Claim a shared line
+   ``release``    Give a shared line back
+   ``get_line``   Describe one line for ``/proc/reset``
+   ============== =========================================================
+
+Each takes the line's ``id``, whose meaning is the controller's own: usually an
+index into its own register layout, and often with gaps where an id inside the
+range names no line.
+
+``reset_controller_unregister()`` removes a controller.  Consumers must have
+put their handles back first.
+
+Reading the lines back
+======================
+
+``status()`` answers for one line at a time, and only for a caller that already
+knows the id.  Nothing else in the interface says how many lines a controller
+has or what any of them is for, so the framework cannot enumerate them on a
+controller's behalf.
+
+``get_line`` supplies exactly what is missing.  It is **optional**: a 
controller
+without it is still listed in ``/proc/reset``, with a note.
+
+.. code-block:: c
+
+   struct reset_lineinfo_s
+   {
+     char name[RESET_NAME_MAX];    /* What this line resets */
+     char extra[RESET_EXTRA_MAX];  /* Controller specific key:value text */
+   };
+
+Both members are optional too.  An empty name reports the line by its id alone.
+``extra`` carries anything the structure has no member for, in the same
+``key:value`` form, and is appended to the line's entry.
+
+The state is **not** in the structure: the framework calls ``status()`` for it,
+so a controller does not report the same fact twice.
+
+Return ``-ENODEV`` for an id that names no line.  That is how a gap in the
+numbering is reported, and the renderer skips it:
+
+.. code-block:: c
+
+   static int mychip_getline(FAR struct reset_controller_dev *rcdev,
+                             unsigned int id,
+                             FAR struct reset_lineinfo_s *info)
+   {
+     if (id >= nitems(g_mychip_lines) || g_mychip_lines[id].name == NULL)
+       {
+         return -ENODEV;              /* a gap in the numbering */
+       }
+
+     strlcpy(info->name, g_mychip_lines[id].name, sizeof(info->name));
+
+     /* Anything the structure has no member for */
+
+     snprintf(info->extra, sizeof(info->extra), "reg:0x%03x bit:%u",
+              MYCHIP_RESET_REG(id), MYCHIP_RESET_BIT(id));
+     return OK;
+   }
+
+/proc/reset
+===========
+
+``CONFIG_RESET_PROCFS`` adds ``/proc/reset``, which lists every registered
+controller and, for those implementing ``get_line``, one line per reset line.
+Every line carries the same tokens in the same order, so the file can be
+parsed:
+
+.. code-block:: text
+
+   eic7700x-reset:
+   0    noc_nsp                  state:released reg:0x400 bit:0
+   9    gpio0                    state:held     reg:0x400 bit:9
+
+A controller with no ``get_line`` appears as its name and a note.  ``state:-``
+means the controller has no ``status()`` or the call failed.
+
+The option depends on ``FS_PROCFS_REGISTER`` and is off by default.
+
+Remote controllers
+==================
+
+``CONFIG_RESET_RPMSG`` lets a consumer on one core drive a reset controller
+owned by another, over rpmsg.  The consumer side calls ``reset_rpmsg_get()``
+for a handle to the remote controller; the core that owns the hardware runs
+``reset_rpmsg_server_init()``.  Consumers use the ordinary interface either
+way.
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index e4f3f117089..284497bd9d3 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -15,3 +15,17 @@ config RESET_RPMSG
        default n
        ---help---
                This selection enables rpmsg support for reset.
+
+config RESET_PROCFS
+       bool "Reset procfs entry"
+       depends on RESET && FS_PROCFS && FS_PROCFS_REGISTER
+       default n
+       ---help---
+               Create /proc/reset, listing every registered reset controller 
and,
+               for those that supply a get_line method, one line per reset line
+               in key:value form.
+
+               status() reads one line at a time, but nothing else in the
+               interface says how many lines a controller has or what any of 
them
+               is called, so without this the only way to see which peripherals
+               are held is a program that knows the numbering already.
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 2495009ed07..d58ecf9edaf 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -33,6 +33,15 @@
 #include <nuttx/reset/reset.h>
 #include <nuttx/reset/reset-controller.h>
 
+#ifdef CONFIG_RESET_PROCFS
+#  include <sys/stat.h>
+#  include <fcntl.h>
+#  include <stdarg.h>
+#  include <stdio.h>
+#  include <string.h>
+#  include <nuttx/fs/procfs.h>
+#endif
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -419,6 +428,328 @@ reset_controller_get_by_name(FAR const char *name)
   return NULL;
 }
 
+#ifdef CONFIG_RESET_PROCFS
+
+/****************************************************************************
+ * Name: reset_procfs_open
+ *
+ * Description:
+ *   Open /proc/reset.  The entry is read only, and holds no state of
+ *   its own beyond the position accounting procfs does for every
+ *   file.
+ *
+ * Input Parameters:
+ *   filep   - The file structure to attach the open file to
+ *   relpath - The path below /proc being opened
+ *   oflags  - Open flags; anything but read only is refused
+ *   mode    - Ignored, the entry cannot be created
+ *
+ * Returned Value:
+ *   Zero on success, or a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int reset_procfs_open(FAR struct file *filep,
+                             FAR const char *relpath,
+                             int oflags, mode_t mode)
+{
+  FAR struct procfs_file_s *priv;
+
+  if ((oflags & O_ACCMODE) != O_RDONLY)
+    {
+      return -EACCES;
+    }
+
+  priv = kmm_zalloc(sizeof(struct procfs_file_s));
+  if (priv == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  filep->f_priv = priv;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: reset_procfs_close
+ *
+ * Description:
+ *   Close /proc/reset and free what open() allocated.
+ *
+ * Input Parameters:
+ *   filep - The open file
+ *
+ * Returned Value:
+ *   Zero on success, or a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int reset_procfs_close(FAR struct file *filep)
+{
+  kmm_free(filep->f_priv);
+  filep->f_priv = NULL;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: reset_procfs_append
+ *
+ * Description:
+ *   Append formatted text at offset n, clamping to the buffer.  snprintf
+ *   returns the length it wanted, so an unclamped sum would carry the
+ *   offset past the buffer and wrap the remaining size.  The offset
+ *   returned never exceeds len - 1.
+ *
+ * Input Parameters:
+ *   line - The line being built
+ *   len  - Size of line
+ *   n    - Offset to append at
+ *   fmt  - Format string, followed by its arguments
+ *
+ * Returned Value:
+ *   The offset after the text, never more than len - 1.
+ *
+ ****************************************************************************/
+
+static size_t reset_procfs_append(FAR char *line, size_t len, size_t n,
+                                  FAR const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start(ap, fmt);
+  n += vsnprintf(line + n, len - n, fmt, ap);
+  va_end(ap);
+
+  return n < len ? n : len - 1;
+}
+
+/****************************************************************************
+ * Name: reset_procfs_line
+ *
+ * Description:
+ *   Render one reset line as key:value tokens, every line the same tokens
+ *   in the same order, then the controller's extra fields.  The state
+ *   comes from status(), which a controller need not implement either; it
+ *   renders as - when absent or when the call fails.
+ *
+ * Input Parameters:
+ *   line  - Where to render the line
+ *   len   - Size of line
+ *   rcdev - The controller owning the line
+ *   id    - The line's id within that controller
+ *   info  - What the controller reported for it
+ *
+ * Returned Value:
+ *   The length of the rendered line.
+ *
+ ****************************************************************************/
+
+static size_t reset_procfs_line(FAR char *line, size_t len,
+                                FAR struct reset_controller_dev *rcdev,
+                                unsigned int id,
+                                FAR const struct reset_lineinfo_s *info)
+{
+  FAR const char *state = "-";
+  size_t n;
+  int ret;
+
+  if (rcdev->ops->status != NULL)
+    {
+      ret = rcdev->ops->status(rcdev, id);
+      if (ret >= 0)
+        {
+          state = ret > 0 ? "asserted" : "released";
+        }
+    }
+
+  n = reset_procfs_append(line, len, 0, "%-4u %-24s state:%-8s", id,
+                          info->name[0] != '\0' ? info->name : "-", state);
+
+  if (info->extra[0] != '\0')
+    {
+      n = reset_procfs_append(line, len, n, " %s", info->extra);
+    }
+
+  n = reset_procfs_append(line, len, n, "\n");
+
+  /* A truncated line still has to end the record */
+
+  if (line[n - 1] != '\n')
+    {
+      line[n - 1] = '\n';
+    }
+
+  return n;
+}
+
+/****************************************************************************
+ * Name: reset_procfs_read
+ *
+ * Description:
+ *   Describe every registered controller's lines, in registration order.
+ *   A controller with no get_line method contributes its name and a note.
+ *
+ * Input Parameters:
+ *   filep  - The open file, carrying the offset reached so far
+ *   buffer - Where to return the text
+ *   buflen - Size of buffer
+ *
+ * Returned Value:
+ *   The number of bytes returned, zero at end of file, or a negated errno
+ *   on failure.
+ *
+ ****************************************************************************/
+
+static ssize_t reset_procfs_read(FAR struct file *filep,
+                                 FAR char *buffer, size_t buflen)
+{
+  FAR struct reset_controller_dev *rcdev;
+  struct reset_lineinfo_s info;
+  size_t remaining = buflen;
+  FAR char *dest = buffer;
+  off_t pos = filep->f_pos;
+  char line[96];
+  unsigned int id;
+  size_t n;
+  int ret;
+
+  ret = nxmutex_lock(&g_reset_list_mutex);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  list_for_every_entry(&g_reset_controller_list, rcdev,
+                       struct reset_controller_dev, list)
+    {
+      if (remaining == 0)
+        {
+          break;
+        }
+
+      /* The name alone: nlines is an id space rather than a count of
+       * real lines, so reporting it here would overstate what follows.
+       */
+
+      n = snprintf(line, sizeof(line), "%s:\n", rcdev->name);
+      n = procfs_memcpy(line, n, dest, remaining, &pos);
+      dest += n;
+      remaining -= n;
+
+      if (rcdev->ops->get_line == NULL)
+        {
+          n = snprintf(line, sizeof(line),
+                       "  no detail, lines are not enumerable\n");
+          n = procfs_memcpy(line, n, dest, remaining, &pos);
+          dest += n;
+          remaining -= n;
+          continue;
+        }
+
+      for (id = 0; id < rcdev->nlines && remaining > 0; id++)
+        {
+          memset(&info, 0, sizeof(info));
+          if (rcdev->ops->get_line(rcdev, id, &info) < 0)
+            {
+              continue;
+            }
+
+          n = reset_procfs_line(line, sizeof(line), rcdev, id, &info);
+          n = procfs_memcpy(line, n, dest, remaining, &pos);
+          dest += n;
+          remaining -= n;
+        }
+    }
+
+  nxmutex_unlock(&g_reset_list_mutex);
+
+  filep->f_pos += (dest - buffer);
+  return dest - buffer;
+}
+
+/****************************************************************************
+ * Name: reset_procfs_dup
+ *
+ * Description:
+ *   Duplicate an open /proc/reset, copying the position reached so
+ *   that the new file continues where the old one had got to.
+ *
+ * Input Parameters:
+ *   oldp - The open file being duplicated
+ *   newp - The file structure to attach the duplicate to
+ *
+ * Returned Value:
+ *   Zero on success, or a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int reset_procfs_dup(FAR const struct file *oldp,
+                            FAR struct file *newp)
+{
+  FAR struct procfs_file_s *priv;
+
+  priv = kmm_zalloc(sizeof(struct procfs_file_s));
+  if (priv == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  memcpy(priv, oldp->f_priv, sizeof(struct procfs_file_s));
+  newp->f_priv = priv;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: reset_procfs_stat
+ *
+ * Description:
+ *   Report /proc/reset as a read only regular file.
+ *
+ * Input Parameters:
+ *   relpath - The path below /proc being queried
+ *   buf     - Where to return the status
+ *
+ * Returned Value:
+ *   Zero on success, or a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int reset_procfs_stat(FAR const char *relpath, FAR struct stat *buf)
+{
+  buf->st_mode    = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
+  buf->st_size    = 0;
+  buf->st_blksize = 0;
+  buf->st_blocks  = 0;
+  return OK;
+}
+
+static const struct procfs_operations g_reset_procfs_ops =
+{
+  reset_procfs_open,     /* open */
+  reset_procfs_close,    /* close */
+  reset_procfs_read,     /* read */
+  NULL,                  /* write */
+  NULL,                  /* poll */
+
+  reset_procfs_dup,      /* dup */
+
+  NULL,                  /* opendir */
+  NULL,                  /* closedir */
+  NULL,                  /* readdir */
+  NULL,                  /* rewinddir */
+
+  reset_procfs_stat,     /* stat */
+};
+
+static const struct procfs_entry_s g_reset_procfs =
+{
+  "reset", &g_reset_procfs_ops, PROCFS_FILE_TYPE
+};
+
+static bool g_reset_procfs_added;
+
+#endif /* CONFIG_RESET_PROCFS */
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -1005,6 +1336,21 @@ int reset_controller_register(FAR struct 
reset_controller_dev *rcdev)
   list_initialize(&rcdev->reset_control_head);
 
   nxmutex_lock(&g_reset_list_mutex);
+
+#ifdef CONFIG_RESET_PROCFS
+  /* procfs_register() wants to run before procfs is mounted, which holds:
+   * controllers register during board or architecture start up.  It
+   * appends without checking for a duplicate, so the entry is claimed once
+   * for the lifetime of the system rather than whenever the list is empty.
+   */
+
+  if (!g_reset_procfs_added)
+    {
+      procfs_register(&g_reset_procfs);
+      g_reset_procfs_added = true;
+    }
+#endif
+
   list_add_after(&g_reset_controller_list, &rcdev->list);
   nxmutex_unlock(&g_reset_list_mutex);
 
diff --git a/include/nuttx/reset/reset-controller.h 
b/include/nuttx/reset/reset-controller.h
index 301b5bd66f0..54f3d2917d5 100644
--- a/include/nuttx/reset/reset-controller.h
+++ b/include/nuttx/reset/reset-controller.h
@@ -32,12 +32,32 @@
 #include <nuttx/list.h>
 #include <nuttx/compiler.h>
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RESET_NAME_MAX  24
+#define RESET_EXTRA_MAX 32
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
 
 struct reset_controller_dev;
 
+/* What a controller can say about one reset line, beyond the asserted
+ * state that status() already reports.  Both members are optional; an
+ * empty name is reported as - and the line by its id alone.
+ */
+
+struct reset_lineinfo_s
+{
+  char name[RESET_NAME_MAX];    /* What this line resets */
+  char extra[RESET_EXTRA_MAX];  /* Controller specific key:value fields,
+                                 * appended to the line's /proc/reset
+                                 * entry */
+};
+
 /* struct reset_control_ops - reset controller driver operations
  * reset: for self-deasserting resets, does all necessary
  *         things to reset the device
@@ -60,6 +80,21 @@ struct reset_control_ops
                        unsigned int id);
   CODE int (*status)(FAR struct reset_controller_dev *rcdev,
                      unsigned int id);
+
+  /* Describe one reset line, for /proc/reset.
+   *
+   * Optional; a controller without it is listed by name alone.  status()
+   * already reports whether a line is asserted, so this supplies only what
+   * the framework cannot derive: the line's name, and anything else the
+   * controller wants shown.  Zero the structure and fill what applies.
+   *
+   * Returns OK, or -ENODEV for an id that names no line, which is how a
+   * gap in the numbering is reported.
+   */
+
+  CODE int (*get_line)(FAR struct reset_controller_dev *rcdev,
+                       unsigned int id,
+                       FAR struct reset_lineinfo_s *info);
 };
 
 /* struct reset_controller_dev - reset controller entity that might
@@ -68,6 +103,10 @@ struct reset_control_ops
  * ops: a pointer to device specific struct reset_control_ops
  * list: internal list of reset controller devices
  * reset_control_head: head of internal list of requested reset controls
+ * nlines: the id space, so get_line() is asked about 0 to nlines - 1.
+ *         Controllers commonly leave gaps, which get_line() reports, so
+ *         this is a bound rather than a count of real lines.  Zero if the
+ *         controller has no get_line().
  */
 
 struct reset_controller_dev
@@ -76,6 +115,7 @@ struct reset_controller_dev
   FAR const struct reset_control_ops *ops;
   struct list_node list;
   struct list_node reset_control_head;
+  unsigned int nlines;
 };
 
 /****************************************************************************

Reply via email to