@@ -19,6 +19,7 @@ import (
1919 "periph.io/x/conn/v3/physic"
2020 "periph.io/x/conn/v3/pin"
2121 "periph.io/x/host/v3/distro"
22+ "periph.io/x/host/v3/gpioioctl"
2223 "periph.io/x/host/v3/pmem"
2324 "periph.io/x/host/v3/sysfs"
2425 "periph.io/x/host/v3/videocore"
@@ -185,7 +186,7 @@ func PinsSetup28To45(drive physic.ElectricCurrent, slewLimit, hysteresis bool) e
185186 return nil
186187}
187188
188- // Pin is a GPIO number (GPIOnn) on BCM238 (5|6|7).
189+ // Pin is a GPIO number (GPIOnn) on BCM283 (5|6|7).
189190//
190191// Pin implements gpio.PinIO.
191192type Pin struct {
@@ -195,7 +196,7 @@ type Pin struct {
195196 defaultPull gpio.Pull // Default pull at system boot, as per datasheet.
196197
197198 // Immutable after driver initialization.
198- sysfsPin * sysfs. Pin // Set to the corresponding sysfs.Pin , if any.
199+ ioctlPin * gpioioctl. GPIOLine // Set to the corresponding gpioioctl.GPIOLine , if any.
199200
200201 // Mutable.
201202 usingEdge bool // Set when edge detection is enabled.
@@ -217,7 +218,7 @@ func (p *Pin) String() string {
217218// disabled.
218219func (p * Pin ) Halt () error {
219220 if p .usingEdge {
220- if err := p .sysfsPin .Halt (); err != nil {
221+ if err := p .ioctlPin .Halt (); err != nil {
221222 return p .wrap (err )
222223 }
223224 p .usingEdge = false
@@ -245,10 +246,10 @@ func (p *Pin) Function() string {
245246// Func implements pin.PinFunc.
246247func (p * Pin ) Func () pin.Func {
247248 if drvGPIO .gpioMemory == nil {
248- if p .sysfsPin == nil {
249+ if p .ioctlPin == nil {
249250 return pin .FuncNone
250251 }
251- return p .sysfsPin .Func ()
252+ return p .ioctlPin .Func ()
252253 }
253254 switch f := p .function (); f {
254255 case in :
@@ -311,10 +312,10 @@ func (p *Pin) SupportedFuncs() []pin.Func {
311312// SetFunc implements pin.PinFunc.
312313func (p * Pin ) SetFunc (f pin.Func ) error {
313314 if drvGPIO .gpioMemory == nil {
314- if p .sysfsPin == nil {
315- return p .wrap (errors .New ("subsystem gpiomem not initialized and sysfs not accessible" ))
315+ if p .ioctlPin == nil {
316+ return p .wrap (errors .New ("subsystem gpiomem not initialized and gpioioctl not accessible" ))
316317 }
317- return p .sysfsPin .SetFunc (f )
318+ return p .ioctlPin .SetFunc (f )
318319 }
319320 switch f {
320321 case gpio .FLOAT :
@@ -369,29 +370,17 @@ func (p *Pin) SetFunc(f pin.Func) error {
369370// possible to 'read back' what value was specified for each pin.
370371//
371372// Will fail if requesting to change a pin that is set to special functionality.
372- //
373- // Using edge detection requires opening a gpio sysfs file handle. On Raspbian,
374- // make sure the user is member of group 'gpio'. The pin will be exported at
375- // /sys/class/gpio/gpio*/. Note that the pin will not be unexported at
376- // shutdown.
377- //
378- // For edge detection, the processor samples the input at its CPU clock rate
379- // and looks for '011' to rising and '100' for falling detection to avoid
380- // glitches. Because gpio sysfs is used, the latency is unpredictable.
381373func (p * Pin ) In (pull gpio.Pull , edge gpio.Edge ) error {
382374 if p .usingEdge && edge == gpio .NoEdge {
383- if err := p .sysfsPin .Halt (); err != nil {
375+ if err := p .ioctlPin .Halt (); err != nil {
384376 return p .wrap (err )
385377 }
386378 }
387379 if drvGPIO .gpioMemory == nil {
388- if p .sysfsPin == nil {
389- return p .wrap (errors .New ("subsystem gpiomem not initialized and sysfs not accessible" ))
390- }
391- if pull != gpio .PullNoChange {
392- return p .wrap (errors .New ("pull cannot be used when subsystem gpiomem not initialized" ))
380+ if p .ioctlPin == nil {
381+ return p .wrap (errors .New ("subsystem gpiomem not initialized and gpioioctl not accessible" ))
393382 }
394- if err := p .sysfsPin .In (pull , edge ); err != nil {
383+ if err := p .ioctlPin .In (pull , edge ); err != nil {
395384 return p .wrap (err )
396385 }
397386 p .usingEdge = edge != gpio .NoEdge
@@ -457,11 +446,11 @@ func (p *Pin) In(pull gpio.Pull, edge gpio.Edge) error {
457446 }
458447 }
459448 if edge != gpio .NoEdge {
460- if p .sysfsPin == nil {
461- return p .wrap (fmt .Errorf ("pin %d is not exported by sysfs " , p .number ))
449+ if p .ioctlPin == nil {
450+ return p .wrap (fmt .Errorf ("pin %d is not exported by gpioioctl " , p .number ))
462451 }
463452 // This resets pending edges.
464- if err := p .sysfsPin .In (gpio .PullNoChange , edge ); err != nil {
453+ if err := p .ioctlPin .In (gpio .PullNoChange , edge ); err != nil {
465454 return p .wrap (err )
466455 }
467456 p .usingEdge = true
@@ -474,10 +463,10 @@ func (p *Pin) In(pull gpio.Pull, edge gpio.Edge) error {
474463// This function is fast. It works even if the pin is set as output.
475464func (p * Pin ) Read () gpio.Level {
476465 if drvGPIO .gpioMemory == nil {
477- if p .sysfsPin == nil {
466+ if p .ioctlPin == nil {
478467 return gpio .Low
479468 }
480- return p .sysfsPin .Read ()
469+ return p .ioctlPin .Read ()
481470 }
482471 if p .number < 32 {
483472 // Important: do not remove the &31 here even if not necessary. Testing
@@ -501,8 +490,8 @@ func (p *Pin) FastRead() gpio.Level {
501490
502491// WaitForEdge implements gpio.PinIn.
503492func (p * Pin ) WaitForEdge (timeout time.Duration ) bool {
504- if p .sysfsPin != nil {
505- return p .sysfsPin .WaitForEdge (timeout )
493+ if p .ioctlPin != nil {
494+ return p .ioctlPin .WaitForEdge (timeout )
506495 }
507496 return false
508497}
@@ -512,7 +501,7 @@ func (p *Pin) WaitForEdge(timeout time.Duration) bool {
512501// bcm2711/bcm2838 support querying the pull resistor of all GPIO pins. Prior
513502// to it, bcm283x doesn't support querying the pull resistor of any GPIO pin.
514503func (p * Pin ) Pull () gpio.Pull {
515- // sysfs does not have the capability to read pull resistor.
504+ // gpioioctl does not have the capability to read pull resistor.
516505 if drvGPIO .gpioMemory != nil {
517506 if drvGPIO .useLegacyPull {
518507 // TODO(maruel): The best that could be added is to cache the last set value
@@ -545,10 +534,10 @@ func (p *Pin) DefaultPull() gpio.Pull {
545534// Fails if requesting to change a pin that is set to special functionality.
546535func (p * Pin ) Out (l gpio.Level ) error {
547536 if drvGPIO .gpioMemory == nil {
548- if p .sysfsPin == nil {
549- return p .wrap (errors .New ("subsystem gpiomem not initialized and sysfs not accessible" ))
537+ if p .ioctlPin == nil {
538+ return p .wrap (errors .New ("subsystem gpiomem not initialized and gpioioctl not accessible" ))
550539 }
551- return p .sysfsPin .Out (l )
540+ return p .ioctlPin .Out (l )
552541 }
553542 // TODO(maruel): This function call is very costly.
554543 if err := p .Halt (); err != nil {
@@ -973,7 +962,7 @@ var cpuPins = []Pin{
973962// Mapping may be overridden during driverGPIO.Init().
974963var mapping = mapping283x
975964
976- // BCM238x specific alternate function mapping (the default).
965+ // BCM283x specific alternate function mapping (the default).
977966var mapping283x = [][6 ]pin.Func {
978967 {"I2C0_SDA" }, // 0
979968 {"I2C0_SCL" },
@@ -1331,17 +1320,20 @@ func (d *driverGPIO) String() string {
13311320}
13321321
13331322func (d * driverGPIO ) Prerequisites () []string {
1334- return nil
1323+ return [] string { "ioctl-gpio" }
13351324}
13361325
13371326func (d * driverGPIO ) After () []string {
1338- return [] string { "sysfs-gpio" }
1327+ return nil
13391328}
13401329
13411330func (d * driverGPIO ) Init () (bool , error ) {
13421331 if ! Present () {
13431332 return false , errors .New ("bcm283x CPU not detected" )
13441333 }
1334+ if len (gpioioctl .Chips ) == 0 {
1335+ return false , errors .New ("gpioioctl not initialized" )
1336+ }
13451337 // It's kind of messy, some report bcm283x while others show bcm27xx.
13461338 // Let's play safe here.
13471339 dTCompatible := strings .Join (distro .DTCompatible (), " " )
@@ -1381,17 +1373,18 @@ func (d *driverGPIO) Init() (bool, error) {
13811373 d .gpioBaseAddr = d .baseAddr + 0x200000
13821374
13831375 // Mark the right pins as available even if the memory map fails so they can
1384- // callback to sysfs .Pins.
1376+ // callback to gpioioctl .Pins.
13851377 functions := map [pin.Func ]struct {}{}
1378+ lines := gpioioctl .Chips [0 ].Lines ()
13861379 for i := range cpuPins {
13871380 name := cpuPins [i ].name
13881381 num := strconv .Itoa (cpuPins [i ].number )
13891382
1390- // Initializes the sysfs corresponding pin right away.
1391- cpuPins [i ].sysfsPin = sysfs . Pins [cpuPins [i ].number ]
1383+ // Initializes the ioctl corresponding pin right away.
1384+ cpuPins [i ].ioctlPin = lines [cpuPins [i ].number ]
13921385
1393- // Unregister the pin if already registered. This happens with sysfs -gpio.
1394- // Do not error on it, since sysfs -gpio may have failed to load.
1386+ // Unregister the pin if already registered. This happens with ioctl -gpio.
1387+ // Do not error on it, since ioctl -gpio may have failed to load.
13951388 _ = gpioreg .Unregister (name )
13961389 _ = gpioreg .Unregister (num )
13971390
0 commit comments