periph / host

Go·Hardware·Lean - Host drivers
https://periph.io
Apache License 2.0
57 stars 32 forks source link

Support GPIO pins on Jetson Orin boards #26

Open penguinland opened 1 year ago

penguinland commented 1 year ago

What kind of new feature are you looking for?

Do you plan to:

Description of the problem For most sysfs systems, you can enable a GPIO pin by writing a number into /sys/class/gpio/export, at which point you get a new symlink named /sys/class/gpio/gpioN (where N is the number you wrote). This is so universally common that it's hard-coded into this repo, at https://github.com/periph/host/blob/main/sysfs/gpio.go#L493.

Unfortunately, the Jetson Orin (at least, the AGX model, not sure about the others) doesn't name their symlinks gpioN. For example, if you cd /sys/class/gpio; echo "336" > export, instead of getting a symlink named gpio336, you get one named PDD.00. However, the gpio.go file in this repo hardcodes that the symlink should always be at gpio336 (or another number), and then we get "file not found"/"pin not exported" errors later if we try to use any of the GPIO pins.

To support the Jetson Orin AGX (and possibly other boards in the Jetson Orin family, though I haven't tried any of them yet), please make this configurable. The line that needs to change is https://github.com/periph/host/blob/main/sysfs/gpio.go#L493, though various other things probably need to change along with it (maybe the pin definitions need a new field? but that sounds like a lot of work, and hopefully there's an easier approach I haven't thought of).

I'd be happy to help brainstorm ideas of what to do, if that would help. I'm on the fence for whether I'm also willing to make the changes myself, but I'm not a flat-out "no" on that end.

penguinland commented 1 year ago

If it helps, Nvidia themselves have published a very similar Python library at https://github.com/NVIDIA/jetson-gpio, and perhaps we could take inspiration from that to adapt support for Go as well. I haven't looked at enough details to see how Nvidia's version differs from Periph's version (aside from being written in a different language).

maruel commented 1 year ago

Thanks for the report. That's really interesting. Can you confirm which kernel version you are running and from which distro it is based from? You can check out via /etc/os-release. The python package you linked to seems to imply it's based on Debian. Maybe there's a way to gather the exported name?

penguinland commented 1 year ago
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
penguinland commented 1 year ago

I'd love to have a way to gather the exported names, but I've looked around in a handful of places within /sys/class/gpio, but haven't found anything useful yet. Then again, a month ago I'd never used sysfs, so don't really know what I'm doing yet and might be looking in the wrong places.

Instead, I've got this PDF, pages 38-39, which says what the symlinks will be named in the "SoC GPIO Port #" column of that table. but to be even more complete, I looked for every pin I could find on the machine:

viam@orindevkit2:~$ cd /sys/class/gpio/
viam@orindevkit2:/sys/class/gpio$ ls
export  gpiochip316  gpiochip348  unexport
viam@orindevkit2:/sys/class/gpio$ cat gpiochip316/base 
316
viam@orindevkit2:/sys/class/gpio$ cat gpiochip316/ngpio 
32
viam@orindevkit2:/sys/class/gpio$ cat gpiochip348/base
348
viam@orindevkit2:/sys/class/gpio$ cat gpiochip348/ngpio 
164

and then tried exporting them all to see what all their names are:

viam@orindevkit2:/sys/class/gpio$ for i in `seq 316 512`; do echo "$i: $(echo $i > export; ls|grep -v export|grep -v gpiochip3; echo $i > unexport)"; done
316: PAA.00
317: PAA.01
318: PAA.02
319: PAA.03
320: PAA.04
321: PAA.05
322: PAA.06
323: PAA.07
324: PBB.00
325: PBB.01
326: PBB.02
327: PBB.03
328: PCC.00
329: PCC.01
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
330: 
331: PCC.03
332: PCC.04
333: PCC.05
334: PCC.06
335: PCC.07
336: PDD.00
337: PDD.01
338: PDD.02
339: PEE.00
340: PEE.01
341: PEE.02
342: PEE.03
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
343: 
344: PEE.05
345: PEE.06
346: PEE.07
347: PGG.00
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
348: 
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
349: 
350: PA.02
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
351: 
352: PA.04
353: PA.05
354: PA.06
355: PA.07
356: PB.00
357: PC.00
358: PC.01
359: PC.02
360: PC.03
361: PC.04
362: PC.05
363: PC.06
364: PC.07
365: PD.00
366: PD.01
367: PD.02
368: PD.03
369: PE.00
370: PE.01
371: PE.02
372: PE.03
373: PE.04
374: PE.05
375: PE.06
376: PE.07
377: PF.00
378: PF.01
379: PF.02
380: PF.03
381: PF.04
382: PF.05
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
383: 
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
384: 
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
385: 
386: PG.03
387: PG.04
388: PG.05
389: PG.06
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
390: 
391: PH.00
392: PH.01
393: PH.02
394: PH.03
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
395: 
396: PH.05
397: PH.06
398: PH.07
399: PI.00
400: PI.01
401: PI.02
402: PI.03
403: PI.04
404: PI.05
405: PI.06
406: PJ.00
407: PJ.01
408: PJ.02
409: PJ.03
410: PJ.04
411: PJ.05
412: PK.00
413: PK.01
414: PK.02
415: PK.03
416: PK.04
417: PK.05
418: PK.06
419: PK.07
420: PL.00
421: PL.01
422: PL.02
423: PL.03
424: PM.00
425: PM.01
426: PM.02
427: PM.03
428: PM.04
429: PM.05
430: PM.06
431: PM.07
432: PN.00
433: PN.01
434: PN.02
435: PN.03
436: PN.04
437: PN.05
438: PN.06
439: PN.07
440: PP.00
441: PP.01
442: PP.02
443: PP.03
444: PP.04
445: PP.05
446: PP.06
447: PP.07
448: PQ.00
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
449: 
450: PQ.02
451: PQ.03
452: PQ.04
453: PQ.05
454: PQ.06
455: PQ.07
456: PR.00
457: PR.01
458: PR.02
459: PR.03
460: PR.04
461: PR.05
462: PX.00
463: PX.01
464: PX.02
465: PX.03
466: PX.04
467: PX.05
468: PX.06
469: PX.07
470: PY.00
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
471: 
472: PY.02
473: PY.03
474: PY.04
475: PY.05
476: PY.06
477: PY.07
478: PZ.00
479: PZ.01
480: PZ.02
481: PZ.03
482: PZ.04
483: PZ.05
484: PZ.06
485: PZ.07
486: PAC.00
487: PAC.01
488: PAC.02
489: PAC.03
490: PAC.04
491: PAC.05
492: PAC.06
-bash: echo: write error: Device or resource busy
-bash: echo: write error: Invalid argument
493: 
494: PAD.00
495: PAD.01
496: PAD.02
497: PAD.03
498: PAE.00
499: PAE.01
500: PAF.00
501: PAF.01
502: PAF.02
503: PAF.03
504: PAG.00
505: PAG.01
506: PAG.02
507: PAG.03
508: PAG.04
509: PAG.05
510: PAG.06
511: PAG.07
-bash: echo: write error: Invalid argument
-bash: echo: write error: Invalid argument
512: 
penguinland commented 1 year ago

You also wanted the kernel version:

viam@orindevkit2:/sys/class/gpio$ uname -a
Linux orindevkit2 5.10.104-tegra #1 SMP PREEMPT Wed Aug 10 20:17:07 PDT 2022 aarch64 aarch64 aarch64 GNU/Linux
maruel commented 1 year ago

The best would be to search for the linux kernel driver source that generate these.

When exploring /sys, I recommend using ls -la as it will print out the symlink destination.

Searching for gpiochip348 tegra, I found https://developer.nvidia.com/docs/drive/drive-os/archives/6.0.3/linux/sdk/oxy_ex-1/common/topics/sys_components/CalculatingGPIOIndexinLinux32.html

and https://developer.download.nvidia.com/assets/embedded/secure/jetson/agx_orin/Adaptation_and_Bringup_for_Jetson_AGX_Orin.pdf?LBKj9NpLo9EB8mwRVFJTb-f62Rr9jdlFSWGMmllVOd90fKgg8ETpxfU_U1aIEyNft8SDZQCHoJKPJJL1c1ocqeLsb1OWi1mO3IEgTg955uEhk-dFtMg0fplXEUOikIGX1-0Qt6d3jnwbBxU-g66_SvkKlTqTSvNH9XBFIg3fL6nLagF6FYq-piug_gRCRhFtGLyeRQ==

The gpio pin number calculation seems to be of a similar type than what allwinner does. You can check the calculation in periph's driver.

penguinland commented 1 year ago

Your second link doesn't work for me, even if I'm logged into my Nvidia account. What does it describe?

Your first link seems like an excellent way to map a (bank, pin) pair to an index, but I think we're looking for the inverse mapping (from an index like 466 back to a bank/pin like PS.05). I'll think some more about whether there's an easy way to compute that inverse without just hardcoding a map of 200ish items.

maruel commented 1 year ago

This link should work: https://developer.nvidia.com/downloads/adaptation-and-bringup-jetson-agx-orinpdf

And yes, we want the reverse mapping.

penguinland commented 1 year ago

I've made https://github.com/periph/host/pull/27 to fix this. and it works, but I suspect there should have been a more elegant approach. I'm willing to some more cleanup/refactoring/reorganizing if it would help get this merged, but I'm also perfectly happy for it not to be merged at all, and I can just continue on my fork. :shrug: