sstar: gpio get/set/scan and the IR-cut hint on infinity6c - #222
Conversation
Infinity6C gives every pad a one-byte register (bit 0 level, bit 1 output value, bit 2 output enable, 1 = Hi-Z) at 0x1F207C00 + 2 * riu_off, per the vendor mhal_gpio table, with the two holes in it kept: the RIU offset is not linear in the pad number (pad 24, pad 42). The four vendor-only PAD_ETH_* pads sit outside the gpiochip and stay out. gpio get/set take the plain pad number and print the same mux line as the HiSilicon path; gpio scan prints one Pad: line per GPIO pad with in/out/oe_n decoded; the possible-IR-cut-GPIO heuristic keeps both of its rules with pads in place of groups. Addresses measured on a live SSC37X board and pinned by reginfo_test.
PR Summary by QodoAdd Infinity6C GPIO commands and IR-cut detection
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1.
|
Three of the four review findings had a HiSilicon twin, because the SigmaStar paths were written against the HiSilicon ones, and are fixed in the one place both share: - The level a `gpio set` writes is parsed strictly now. strtoul reads every string that is not a number as 0, and 0 is a level the command really writes, so `gpio set 12 foo` used to switch the pad to an output and drive it low. Both vendors' set paths refused after this fix only. - A /dev/mem mapping counts from its full interval, not only from the page its offset names: a daemon holding one broad RIU window from below held the GPIO registers all the same, and the walk now knows. The interval math is gpio_windows_in_mapping(), pinned by tests; both the HiSilicon group walk and the SigmaStar single-window question go through it. - The /proc walk visits every digit-named pid, including init. PID 1 running the streamer is a real shape. - `gpio scan` on either vendor now exits at the first register read that fails, instead of retrying every 100 ms and logging the same error forever while watching nothing. Verified on the SSC37X board: `gpio set 12 foo` refuses with the pad byte at 0x1f207c30 untouched (0x58 before and after), valid sets still move it 0x58/0x5b, and the board report's possible-IR-cut-GPIO is the same eleven pads as before the walk was fixed. The HiSilicon twins are not live-verified this round -- the lab HiSilicon cameras did not answer.
mem_reg() keeps its last /dev/mem window mapped, and the SigmaStar IR-cut hint reads every pad before asking the walk whether a daemon holds the pads. The walk visited every digit-named pid, ipctool's own included, so it always found the window it had just used, always answered "streamer", and on any board with more than two driving pads the hint was dropped. The fallback rule could never run. Skip getpid(). The window the hint asks about now comes from sstar_gpio_window(), and reginfo_test checks that call -- 0x1F207000 + 0xD64 -- instead of a stand-in with a different base and length.
Review fix: the
|
| case | PR head | this commit |
|---|---|---|
as found (pad 81 on SAR_MODE_0) |
0,1,2,3,4,5,32 |
0,1,2,3,4,5,32 |
| pad 81 temporarily muxed to GPIO (Hi-Z input, restored afterwards) | no hint | 0,1,2,3,4,5,32 |
a helper process holds /dev/mem @ 0x1F207000 |
no hint | no hint (streamer rule, as designed) |
Also on that board, with this commit: gpio get 32 returns the level stored in its register byte. gpio set 32 foo and gpio set 32 2 are refused and the byte stays 0x0A58. gpio set 32 0 is accepted. gpio get 99 is refused. The gpio scan baseline shows the same 58 pads as PR head.
Native builds with IPCHW_VENDORS=all|sstar|none and the arm32 musl cross build all pass, as do reginfo_test, cYAML_test and tools/test_pipeline.sh.
The three GPIO subcommands and the
possible-IR-cut-GPIOreport hint have beenHiSilicon-only since they exist:
get_chip_gpio_adress()has no SigmaStarentry, so on SigmaStar
gpio get/gpio setanswered "Platform is notsupported" and the board report silently dropped the hint. This adds
Infinity6C (SSC37X), from the vendor's own per-pad register layout.
Registers
HiSilicon banks eight pins behind a data word and a direction word. Infinity6C
gives every pad one byte: bit 0 the pin level, bit 1 the output value, bit 2
the output enable, which reads 1 while the pad drives Hi-Z (an input) and 0
while it drives. A pad's byte sits at
0x1F207C00 + 2 * riu_off, and thetable is the one the vendor driver carries (
drivers/sstar/gpio/infinity6c/ mhal_gpio.c, GPL-2) — including its two holes, at pads 24 and 42, becausethe RIU offset is not linear in the pad number. The four
PAD_ETH_*pads thevendor appends by hand sit outside the gpiochip range and stay out. 82 pads,
numbered exactly as the kernel's gpiochip numbers them, so sysfs and
gpio getdescribe the same wire.Commands
gpio get/set <pad>take the plain pad number — there is no5_6spellingto parse, nothing is banked — and print the same mux line the HiSilicon path
prints.
gpio scanprints onePad:baseline line per GPIO-muxed pad, decoded intoin/out/oe_n, then runs the same 100 ms diff loop as HiSilicon.gpio_possible_ircut()keeps both of its rules with pads in place ofgroups: a mapped streamer trims the guess to a board whose whole pad list
holds at most two driving pads, and the fallback stays "every pad currently
driving low".
SigmaStar families other than infinity6c keep today's behaviour; their tables
slot into the same shape when someone measures them.
Review round
Four Qodo findings, all taken — and three of the four had a HiSilicon twin,
because the SigmaStar paths were written to match the HiSilicon ones. Those
are fixed where the code now shares one place:
strtoulreads everynon-number as 0, and 0 is a level
gpio setreally writes, sogpio set 12 fooused to switch the pad to an output and drive it low.parse_gpio_level()— end pointer,errno, whole string, 0 or 1 — refusesit before any register bit moves, on both vendors' set paths.
window its offset starts in: a daemon holding one broad RIU window from
below holds the GPIO registers all the same. The math lives in
gpio_windows_in_mapping()(unit-tested, including the broad-windowshape) and both the group walk and the single-window question go through
it.
running the streamer is a real shape on minimal firmware.
gpio scanstops at the first failing read instead of retrying every100 ms and logging the same register forever. Same fix on both vendors.
Two
reginfo_testblocks pin the level parser and the window math: therefusals are
"",foo,1x,0x1,2,-1and the ERANGE overflow, thewindows are the exact fit, the start-below overlap, the adjacent page that
must not count, and the SigmaStar call shape (one window, ends not
page-aligned).
Verification
reginfo_testpins the measured addresses — pad 0 at0x1F207C00, 12 at0x1F207C30, 23 at0x1F207C5C, 30 at0x1F207C7C, 41 at0x1F207CA8,42 at
0x1F207CC4, 81 at0x1F207D60— so an address edit that silentlymoves the table fails the sweep (monotonic, 4-byte aligned, in range)
instead of a camera.
all,sstaronly,none, and the musl cross-toolchain), no new warnings;reginfo_testandtools/test_pipeline.shpass.gpio get 12and anindependent byte-mapped
/dev/memreader agree at0x1F207C30;gpio set 12 0moves that byte0x5b -> 0x58; after the review roundgpio set 12 foorefuses with the byte untouched (0x58before and after) while validsets still move it; the scan baseline lists the 42 GPIO-muxed pads the mux
tables predict; the board report carries
possible-IR-cut-GPIO: 0,1,2,3,4,5,11,12,30,32,80before and after thewalk fix (no process on this board maps /dev/mem, so the fallback rule is
what it exercises) — checked with a build whose report omits the sensor
sweep, which on this vendor firmware stalls against the live streamer for
minutes and is not a regression of this patch.
cameras did not answer (hung at PoE trickle; a bounce did not revive
them), so those two lines rest on the shared code path, the unit tests on
the math, and inspection. Happy to drive them when a board is back.
docs/gpio.mdupdated: the numbering paragraph and the IR-cut hint rulesnow describe the SigmaStar shape alongside the HiSilicon one.