Fishwaldo opened a new pull request, #19871:
URL: https://github.com/apache/nuttx/pull/19871

   ## Summary
   
   The pinctrl interface is write only: every operation sets a property, and
   nothing reports what a pin currently holds. During board bring up the useful
   question is the opposite one, and the interface meant to describe pins cannot
   answer it.
   
   This adds an optional `get_pad` method that fills a `struct 
pinctrl_padinfo_s`
   describing one pad, and two callers for it:
   
   * `/proc/pinctrl`, under the new `CONFIG_PINCTRL_PROCFS`, printing one
     `key:value` line per pad. Every line carries the same tokens in the same
     order, with `-` for a field the pad does not have, so the file can be 
parsed.
     The framework owns the format; controllers only supply data.
   * a `PINCTRLC_GETPAD` ioctl, giving userspace the programmatic read-back that
     text cannot serve, e.g. reading a pad back after setting it. The structure
     embeds its strings rather than pointing at them, so one shape serves both
     callers across the user/kernel boundary.
   
   **Everything here is optional.** A controller that does not implement 
`get_pad`
   is still listed, and the ioctl returns `-ENOTSUP`. A pad need not have every
   field: fill what it has and set the matching `PINCTRL_HAVE_*` bit, and 
anything
   the structure has no member for goes in `extra` as further `key:value` text.
   **Pad and function names are entirely optional too** — leave them empty and 
pads
   are reported by number alone. `PINCTRL_PADNAME()` and two lookup helpers are
   provided for controllers that do want names, so each one need not invent its 
own
   table.
   
   A minimal controller is about this much:
   
   ```c
   /* Optional: one entry per pad, its name then the name of each function
    * select in select order.  NULL marks a select the manual does not name.
    */
   
   static const struct pinctrl_padname_s g_mychip_padnames[] =
   {
     [MYCHIP_PAD_I2C0_SCL] = PINCTRL_PADNAME("I2C0_SCL", "I2C0_SCL",
                                             NULL, "GPIO44"),
     [MYCHIP_PAD_SPI0_CLK] = PINCTRL_PADNAME("SPI0_CLK", "SPI0_CLK"),
     [MYCHIP_PAD_XIN]      = PINCTRL_PADNAME("XIN", NULL),
   };
   
   static int mychip_getpad(struct pinctrl_dev_s *dev, uint32_t pin,
                            struct pinctrl_padinfo_s *info)
   {
     uint32_t val = getreg32(MYCHIP_PAD(pin));
     FAR const char *name;
   
     info->have     = PINCTRL_HAVE_FUNCTION | PINCTRL_HAVE_PULL;
     info->function = (val & PAD_FUNC_MASK) >> PAD_FUNC_SHIFT;
     info->pullup   = (val & PAD_PU) != 0;
     info->pulldown = (val & PAD_PD) != 0;
   
     /* Names are optional; both helpers return NULL when a name is absent,
      * which leaves the strings empty.
      */
   
     name = pinctrl_padname(g_mychip_padnames, nitems(g_mychip_padnames),
                            pin);
     if (name != NULL)
       {
         strlcpy(info->name, name, sizeof(info->name));
       }
   
     name = pinctrl_funcname(g_mychip_padnames, nitems(g_mychip_padnames),
                             pin, info->function);
     if (name != NULL)
       {
         strlcpy(info->funcname, name, sizeof(info->funcname));
       }
   
     /* Anything the structure has no member for */
   
     snprintf(info->extra, sizeof(info->extra), "ms:%u", (val >> 8) & 3);
     return OK;
   }
   
   static const struct pinctrl_ops_s g_mychip_ops =
   {
     ...
     .get_pad = mychip_getpad,
   };
   ```
   
   The documentation is updated with the method, the validity bits, the optional
   naming and the procfs entry.
   
   ## Impact
   
   New feature, off by default. `CONFIG_PINCTRL_PROCFS` depends on
   `FS_PROCFS_REGISTER`; with it unset nothing here is compiled.
   
   `struct pinctrl_ops_s` gains one optional member and `struct pinctrl_dev_s`
   gains `npins`. There are currently **no pinctrl providers in master**, so no
   existing driver needs updating. The first consumer will be the ESWIN EIC7700X
   pad multiplexer, in a pull request following shortly; it drives 166 pads 
through
   four different field layouts, which is what the `have` bits and `extra` exist
   for.
   
   No change to the existing five operations, their ioctls or their behaviour.
   
   Worth flagging to reviewers: **no in-tree configuration enables 
`CONFIG_PINCTRL`
   at all**, so CI will not compile this code. A green run says nothing about 
it,
   and the testing below is the only evidence.
   
   ## Testing
   
   Host: macOS 15.5 (arm64), `riscv-none-elf-gcc` 13.2, Sphinx 6.2.1.
   
   **Build**, since CI cannot: `sim:nsh` with `PINCTRL`, `FS_PROCFS`,
   `FS_PROCFS_REGISTER` and `PINCTRL_PROCFS` forced on compiles
   `drivers/pinctrl/pinctrl.c` clean; also built with `PINCTRL_PROCFS` off to 
check
   the disabled path. Documentation builds with no new warnings.
   
   **Hardware**: ESWIN EIC7700 EVB (EIC7700X, 4 x RV64GC), booted over TFTP 
with an
   out-of-tree pinctrl driver implementing `get_pad` for all 166 pads.
   
   Board start up:
   
   ```
   [CPU0] clk: registered 264 clocks, 0 failed
   [CPU0] pinctrl: 166 pads, 3 configured
   ```
   
   ```
   nsh> cat /proc/pinctrl
   pinctrl0: 166 pads
   0    CHIP_MODE            func:0 sel:CHIP_MODE        ds:0 pu:0 pd:1 ie:1 
smt:1 slew:-
   5    XIN                  func:- sel:-                ds:12 pu:- pd:- ie:- 
smt:- slew:- frs:2 rd:0
   91   I2C0_SCL             func:0 sel:I2C0_SCL         ds:1 pu:0 pd:0 ie:1 
smt:0 slew:-
   141  S_MODE               func:2 sel:GPIO94           ds:1 pu:0 pd:0 ie:1 
smt:0 slew:-
   163  LPDDR_REF_CLK        func:- sel:-                ds:0 pu:0 pd:0 ie:1 
smt:0 slew:- ms:3
   164  ADDR_RGMII0_SEL_MODE func:- sel:-                ds:- pu:- pd:- ie:- 
smt:- slew:- ms1:1 ms2:1
   ```
   
   That exercises all four of the chip's pad layouts: pad 0 a general pad, 5 an
   oscillator pad with no function select and its own `frs`/`rd` fields, 163 an
   RGMII pad carrying `ms`, and 164 a mode-select pad that has almost nothing 
and
   renders as `-` throughout. `sel:GPIO94` on pad 141 is a named function 
select.
   
   Checked on that output:
   
   * all 166 pads present, strictly sequential, **no gap or repeat at any read
     boundary** — the file is far larger than one read buffer, so this 
exercises the
     `pos` accounting across many `read()` calls
   * every line carries the identical token set; an `awk` pass splitting on the
     fields finds no line that deviates
   * no trailing whitespace, and no truncated record
   
   A controller without `get_pad` was checked by removing the method: the
   controller is still listed with a note, and the ioctl returns `-ENOTSUP`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to