Mon Nov 6 00:35:06 2023 UTC ()
gpioirq(4) version 2

This update makes this driver more than just an example and allows for:

o More than one pin to be attached to a gpioirq instance.  That is,
  the mask parameter can be greater than 0x01 now.

o A /dev/gpioirqN device that allows GPIO pin interrupts to be
  transported into userland.  This is a device that can be opened for
  reading with a simple fixed output indicating the device unit, pin
  number and current pin state.

This update was used as part of a physical intrusion detection system
where multiple switches (i.e. window magnetic reed switches and etc.)
are tied to a bunch of GPIO inputs with userland software that reacts
to the pins changing state.


(brad)
diff -r1.3015 -r1.3016 src/doc/CHANGES
diff -r1.233 -r1.234 src/etc/MAKEDEV.tmpl
diff -r1.3 -r1.4 src/share/man/man4/gpioirq.4
diff -r1.102 -r1.103 src/sys/conf/majors
diff -r1.72 -r1.73 src/sys/dev/gpio/gpio.c
diff -r1.1 -r1.2 src/sys/dev/gpio/gpioirq.c
diff -r1.18 -r1.19 src/sys/dev/gpio/gpiovar.h

cvs diff -r1.3015 -r1.3016 src/doc/CHANGES (expand / switch to unified diff)

--- src/doc/CHANGES 2023/11/05 18:32:01 1.3015
+++ src/doc/CHANGES 2023/11/06 00:35:06 1.3016
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.3015 $> 1# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.3016 $>
2# 2#
3# 3#
4# [Note: This file does not mention every change made to the NetBSD source tree. 4# [Note: This file does not mention every change made to the NetBSD source tree.
5# For an exhaustive list, please subscribe to the `source-changes' mailing list, 5# For an exhaustive list, please subscribe to the `source-changes' mailing list,
6# or see the mailing list archives. For more information, send a message 6# or see the mailing list archives. For more information, send a message
7# containing just the word `help' to `majordomo@NetBSD.org'.] 7# containing just the word `help' to `majordomo@NetBSD.org'.]
8# 8#
9# ---------------------------------------------------------------------------- 9# ----------------------------------------------------------------------------
10# PLEASE USE THE FOLLOWING STYLE WHEN ADDING ITEMS: 10# PLEASE USE THE FOLLOWING STYLE WHEN ADDING ITEMS:
11# 11#
12# theme: Content ... 12# theme: Content ...
13# more content ... 13# more content ...
14# more content. [developer DATE-FORMAT] 14# more content. [developer DATE-FORMAT]
@@ -248,13 +248,16 @@ Changes from NetBSD 10.0 to NetBSD 11.0: @@ -248,13 +248,16 @@ Changes from NetBSD 10.0 to NetBSD 11.0:
248 graphical console on EFI-only hardware. [bouyer 20231017] 248 graphical console on EFI-only hardware. [bouyer 20231017]
249 lagg(4): Copy the MTU of lagg to interfaces added to lagg 249 lagg(4): Copy the MTU of lagg to interfaces added to lagg
250 [yamaguchi 20231018] 250 [yamaguchi 20231018]
251 dhcpcd: Import version 10.0.4. [roy 20231019] 251 dhcpcd: Import version 10.0.4. [roy 20231019]
252 eqos(4): Add support for Intel Elkhart Lake internal Ethernet devices. 252 eqos(4): Add support for Intel Elkhart Lake internal Ethernet devices.
253 [msaitoh 20231019] 253 [msaitoh 20231019]
254 top(1): Add network in & out bytes to the top display. [mrg 20231021] 254 top(1): Add network in & out bytes to the top display. [mrg 20231021]
255 OpenSSL: Imported 3.0.12. [christos 20231025] 255 OpenSSL: Imported 3.0.12. [christos 20231025]
256 OpenSSH: Import 9.5. [christos 20231025] 256 OpenSSH: Import 9.5. [christos 20231025]
257 newsmips: Add support for LCD-MONO framebuffer on NWS-32x0 laptop 257 newsmips: Add support for LCD-MONO framebuffer on NWS-32x0 laptop
258 machines. [tsutsui 20231104] 258 machines. [tsutsui 20231104]
259 ena(4): MP-enable always, add RSS support, and reliability fixes. 259 ena(4): MP-enable always, add RSS support, and reliability fixes.
260 [jdolecek 20231105] 260 [jdolecek 20231105]
 261 gpioirq(4): allow multiple pins per gpioirq instance, add the ability
 262 to use a /dev/gpioirqN device to get pin interrupts into userland.
 263 [brad 20231105]

cvs diff -r1.233 -r1.234 src/etc/MAKEDEV.tmpl (expand / switch to unified diff)

--- src/etc/MAKEDEV.tmpl 2022/12/28 19:23:02 1.233
+++ src/etc/MAKEDEV.tmpl 2023/11/06 00:35:05 1.234
@@ -1,15 +1,15 @@ @@ -1,15 +1,15 @@
1#!/bin/sh - 1#!/bin/sh -
2# $NetBSD: MAKEDEV.tmpl,v 1.233 2022/12/28 19:23:02 jakllsch Exp $ 2# $NetBSD: MAKEDEV.tmpl,v 1.234 2023/11/06 00:35:05 brad Exp $
3# 3#
4# Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc. 4# Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
5# All rights reserved. 5# All rights reserved.
6# 6#
7# Redistribution and use in source and binary forms, with or without 7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions 8# modification, are permitted provided that the following conditions
9# are met: 9# are met:
10# 1. Redistributions of source code must retain the above copyright 10# 1. Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer. 11# notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright 12# 2. Redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions and the following disclaimer in the 13# notice, this list of conditions and the following disclaimer in the
14# documentation and/or other materials provided with the distribution. 14# documentation and/or other materials provided with the distribution.
15# 15#
@@ -222,26 +222,27 @@ @@ -222,26 +222,27 @@
222# cfs* Coda file system device 222# cfs* Coda file system device
223# ch* SCSI media changer 223# ch* SCSI media changer
224# cir* Consumer IR 224# cir* Consumer IR
225# clockctl clock control for non root users 225# clockctl clock control for non root users
226# cpuctl CPU control 226# cpuctl CPU control
227# crypto hardware crypto access driver 227# crypto hardware crypto access driver
228# dmoverio hardware-assisted data movers 228# dmoverio hardware-assisted data movers
229# dpt* DPT/Adaptec EATA RAID management interface 229# dpt* DPT/Adaptec EATA RAID management interface
230# dpti* DPT/Adaptec I2O RAID management interface 230# dpti* DPT/Adaptec I2O RAID management interface
231# drm* Direct Rendering Manager interface 231# drm* Direct Rendering Manager interface
232# dtv* Digital TV interface 232# dtv* Digital TV interface
233# fb* PMAX generic framebuffer pseudo-device 233# fb* PMAX generic framebuffer pseudo-device
234# fd file descriptors 234# fd file descriptors
 235# gpioirq* Interrupts on GPIO pins
235# gpiopps* 1PPS signals on GPIO pins 236# gpiopps* 1PPS signals on GPIO pins
236# grf* graphics frame buffer device 237# grf* graphics frame buffer device
237# hdaudio* High Definition audio control device 238# hdaudio* High Definition audio control device
238# hdmicec* HDMI CEC devices 239# hdmicec* HDMI CEC devices
239# hil HP300 HIL input devices 240# hil HP300 HIL input devices
240# icp ICP-Vortex/Intel RAID control interface 241# icp ICP-Vortex/Intel RAID control interface
241# iic* IIC bus device 242# iic* IIC bus device
242# io x86 IOPL access for COMPAT_10, COMPAT_FREEBSD 243# io x86 IOPL access for COMPAT_10, COMPAT_FREEBSD
243# iop* I2O IOP control interface 244# iop* I2O IOP control interface
244# ipmi* OpenIPMI compatible interface 245# ipmi* OpenIPMI compatible interface
245# ipl IP Filter 246# ipl IP Filter
246# irframe* IrDA physical frame 247# irframe* IrDA physical frame
247# ite* terminal emulator interface to HP300 graphics devices 248# ite* terminal emulator interface to HP300 graphics devices
@@ -820,27 +821,27 @@ all) @@ -820,27 +821,27 @@ all)
820 makedev fss0 fss1 fss2 fss3 821 makedev fss0 fss1 fss2 fss3
821 makedev md0 md1 822 makedev md0 md1
822 makedev raid0 raid1 raid2 raid3 raid4 raid5 raid6 raid7 823 makedev raid0 raid1 raid2 raid3 raid4 raid5 raid6 raid7
823 makedev vnd0 vnd1 vnd2 vnd3 824 makedev vnd0 vnd1 vnd2 vnd3
824 makedev iscsi0 825 makedev iscsi0
825 makedev bpf npf 826 makedev bpf npf
826 makedev tun0 tun1 tun2 tun3 827 makedev tun0 tun1 tun2 tun3
827 makedev ipl pf crypto random 828 makedev ipl pf crypto random
828 makedev lockstat clockctl cpuctl 829 makedev lockstat clockctl cpuctl
829 makedev atabus0 atabus1 atabus2 atabus3 atabus4 atabus5 atabus6 atabus7 830 makedev atabus0 atabus1 atabus2 atabus3 atabus4 atabus5 atabus6 atabus7
830 makedev srt0 srt1 srt2 srt3 831 makedev srt0 srt1 srt2 srt3
831 makedev tap tap0 tap1 tap2 tap3 832 makedev tap tap0 tap1 tap2 tap3
832 makedev gpio gpio0 gpio1 gpio2 gpio3 gpio4 gpio5 gpio6 gpio7 833 makedev gpio gpio0 gpio1 gpio2 gpio3 gpio4 gpio5 gpio6 gpio7
833 makedev gpiopps0 834 makedev gpioirq0 gpiopps0
834 makedev pad pad0 pad1 pad2 pad3 835 makedev pad pad0 pad1 pad2 pad3
835 makedev bthub 836 makedev bthub
836 makedev putter 837 makedev putter
837 makedev drvctl 838 makedev drvctl
838 makedev video 839 makedev video
839 makedev dtv 840 makedev dtv
840 makedev drm0 drm1 drm2 drm3 841 makedev drm0 drm1 drm2 drm3
841 makedev altmem 842 makedev altmem
842 makedev zfs 843 makedev zfs
843 makedev lua 844 makedev lua
844 makedev hdmicec0 845 makedev hdmicec0
845 makedev dtrace 846 makedev dtrace
846 makedev veriexec 847 makedev veriexec
@@ -863,26 +864,30 @@ audio) @@ -863,26 +864,30 @@ audio)
863 makedev audio0 audio1 audio2 audio3 864 makedev audio0 audio1 audio2 audio3
864 makedev hdaudio0 hdaudio1 hdaudio2 hdaudio3 865 makedev hdaudio0 hdaudio1 hdaudio2 hdaudio3
865 lndev sound0 sound 866 lndev sound0 sound
866 lndev audio0 audio 867 lndev audio0 audio
867 lndev mixer0 mixer 868 lndev mixer0 mixer
868 lndev audioctl0 audioctl 869 lndev audioctl0 audioctl
869 ;; 870 ;;
870 871
871gpio) 872gpio)
872 makedev gpio0 gpio1 gpio2 gpio3 gpio4 gpio5 gpio6 gpio7 873 makedev gpio0 gpio1 gpio2 gpio3 gpio4 gpio5 gpio6 gpio7
873 lndev gpio0 gpio 874 lndev gpio0 gpio
874 ;; 875 ;;
875 876
 877gpioirq)
 878 makedev gpioirq0
 879 ;;
 880
876gpiopps) 881gpiopps)
877 makedev gpiopps0 882 makedev gpiopps0
878 lndev gpiopps0 gpiopps 883 lndev gpiopps0 gpiopps
879 ;; 884 ;;
880 885
881lua) 886lua)
882 makedev lua0 887 makedev lua0
883 lndev lua0 lua 888 lndev lua0 lua
884 ;; 889 ;;
885 890
886pad) 891pad)
887 makedev pad0 pad1 pad2 pad3 892 makedev pad0 pad1 pad2 pad3
888 lndev pad0 pad 893 lndev pad0 pad
@@ -1537,26 +1542,31 @@ hdaudio[0-9]*) @@ -1537,26 +1542,31 @@ hdaudio[0-9]*)
1537 mkdev hdaudio$unit c %hdaudio_chr% $unit 644 1542 mkdev hdaudio$unit c %hdaudio_chr% $unit 644
1538 ;; 1543 ;;
1539 1544
1540hdmicec[0-9]*) 1545hdmicec[0-9]*)
1541 uint=${i#hdmicec} 1546 uint=${i#hdmicec}
1542 mkdev hdmicec$unit c %hdmicec_chr% $unit 644 1547 mkdev hdmicec$unit c %hdmicec_chr% $unit 644
1543 ;; 1548 ;;
1544 1549
1545gpio[0-9]*) 1550gpio[0-9]*)
1546 unit=${i#gpio} 1551 unit=${i#gpio}
1547 mkdev gpio$unit c %gpio_chr% $unit 664 $g_gpio 1552 mkdev gpio$unit c %gpio_chr% $unit 664 $g_gpio
1548 ;; 1553 ;;
1549 1554
 1555gpioirq[0-9]*)
 1556 unit=${i#gpioirq}
 1557 mkdev gpioirq$unit c %gpioirq_chr% $unit 444 $g_gpio
 1558 ;;
 1559
1550gpiopps[0-9]*) 1560gpiopps[0-9]*)
1551 unit=${i#gpiopps} 1561 unit=${i#gpiopps}
1552 mkdev gpiopps$unit c %gpiopps_chr% $unit 664 $g_gpio 1562 mkdev gpiopps$unit c %gpiopps_chr% $unit 664 $g_gpio
1553 ;; 1563 ;;
1554 1564
1555lua[0-9]*) 1565lua[0-9]*)
1556 unit=${i#lua} 1566 unit=${i#lua}
1557 mkdev lua$unit c %lua_chr% $unit 664 1567 mkdev lua$unit c %lua_chr% $unit 664
1558 ;; 1568 ;;
1559 1569
1560rmidi[0-9]*) 1570rmidi[0-9]*)
1561 unit=${i#rmidi} 1571 unit=${i#rmidi}
1562 mkdev rmidi$unit c %midi_chr% $unit 666 1572 mkdev rmidi$unit c %midi_chr% $unit 666

cvs diff -r1.3 -r1.4 src/share/man/man4/gpioirq.4 (expand / switch to unified diff)

--- src/share/man/man4/gpioirq.4 2023/08/01 20:39:15 1.3
+++ src/share/man/man4/gpioirq.4 2023/11/06 00:35:05 1.4
@@ -1,65 +1,66 @@ @@ -1,65 +1,66 @@
1.\" $NetBSD: gpioirq.4,v 1.3 2023/08/01 20:39:15 andvar Exp $ 1.\" $NetBSD: gpioirq.4,v 1.4 2023/11/06 00:35:05 brad Exp $
2.\" 2.\"
3.\" Copyright (c) 2016 Brad Spencer <brad@anduin.eldar.org> 3.\" Copyright (c) 2016, 2023 Brad Spencer <brad@anduin.eldar.org>
4.\" 4.\"
5.\" Permission to use, copy, modify, and distribute this software for any 5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above 6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies. 7.\" copyright notice and this permission notice appear in all copies.
8.\" 8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\" 16.\"
17.Dd May 11, 2018 17.Dd November 5, 2023
18.Dt GPIOIRQ 4 18.Dt GPIOIRQ 4
19.Os 19.Os
20.Sh NAME 20.Sh NAME
21.Nm gpioirq 21.Nm gpioirq
22.Nd Install an interrupt handler on a GPIO pin 22.Nd Install an interrupt handler on GPIO pins
23.Sh SYNOPSIS 23.Sh SYNOPSIS
24.Cd "gpioirq* at gpio? offset 0 mask 0x1 flag 0x00" 24.Cd "gpioirq* at gpio? offset 0 mask 0x1 flag 0x00"
25.Sh DESCRIPTION 25.Sh DESCRIPTION
26The 26The
27.Nm 27.Nm
28driver attaches an interrupt handler to a single GPIO pin. 28driver attaches an interrupt handler to a one or more GPIO pins.
29.Pp 29.Pp
30The pin number is specified in the kernel configuration file with the 30The base pin number is specified in the kernel configuration file with the
31.Ar offset 31.Ar offset
32locator. 32locator.
33The 33The
34.Ar mask 34.Ar mask
35locator should always be 0x1. 35locator can be 0x01 or greater to indicate that more pins should have an
 36interrupt handler attached to them.
36.Pp 37.Pp
37The 38The
38.Ar flag 39.Ar flag
39locator specifies the interrupt mode to use: 40locator specifies the interrupt mode to use:
40.Bl -tag -width "XXXXXXXX" 41.Bl -tag -width "XXXXXXXX"
41.It Dv 0x01 42.It Dv 0x01
42Interrupt on the positive 43Interrupt on the positive
43.Pq rising 44.Pq rising
44edge of the pin. 45edge of the pin.
45.It Dv 0x02 46.It Dv 0x02
46Interrupt on the negative 47Interrupt on the negative
47.Pq falling 48.Pq falling
48edge of the pin. 49edge of the pin.
49.It Dv 0x04 50.It Dv 0x04
50Interrupt on both edges of the pin. 51Interrupt on both edges of the pin.
51.It Dv 0x08 52.It Dv 0x08
52Assert the interrupt as long as the pin is high. 53Assert the intrerrupt as long as the pin is high.
53.It Dv 0x10 54.It Dv 0x10
54Assert the interrupt as long as the pin is low. 55Assert the interrupt as long as the pin is low.
55.El 56.El
56.Pp 57.Pp
57Note that the interrupts modes are mutually-exclusive, and exactly one 58Note that the interrupts modes are mutually-exclusive, and exactly one
58interrupt mode must be specified. 59interrupt mode must be specified.
59These flags correspond to the 60These flags correspond to the
60.Dv GPIO_INTR 61.Dv GPIO_INTR
61mode bits defined in 62mode bits defined in
62.Pa sys/gpio.h . 63.Pa sys/gpio.h .
63In addition to the interrupt mode, setting 64In addition to the interrupt mode, setting
64.Dv 0x1000 65.Dv 0x1000
65in 66in
@@ -70,28 +71,77 @@ interrupt handler is called. @@ -70,28 +71,77 @@ interrupt handler is called.
70The 71The
71.Ar offset , 72.Ar offset ,
72.Ar mask , 73.Ar mask ,
73and 74and
74.Ar flag 75.Ar flag
75locators can also be specified when 76locators can also be specified when
76.Nm 77.Nm
77is attached at runtime using the 78is attached at runtime using the
78.Dv GPIOATTACH 79.Dv GPIOATTACH
79.Xr ioctl 2 80.Xr ioctl 2
80on the 81on the
81.Xr gpio 4 82.Xr gpio 4
82device. 83device.
 84.Sh FILES
 85.Bl -tag -width "/dev/gpioirqu" -compact
 86.It /dev/gpioirq Ns Ar u
 87GPIOIRQ device unit
 88.Ar u
 89file.
 90The output from this device are three uint8_t bytes every time an interrupt fires.
 91The bytes contain the device unit, pin number and the current state of the pin.
 92.Sh EXAMPLES
 93The following example will output the device unit, pin and
 94the pins current state for pins 4, 5, 6, 7, 8, 9, 10, 11, 12 on gpio0:
 95.Bd -literal -offset indent
 96/etc/gpio.conf contains:
 97gpio0 attach gpioirq 4 0x1ff 0x04
 98
 99or a kernel was compiled to have the same parameters.
 100
 101#!/usr/pkg/bin/perl
 102
 103$dev = "/dev/gpioirq0";
 104
 105sysopen(DEV,$dev,O_RDONLY) || die "sysopen: $!";
 106
 107while (sysread(DEV,$b,3)) {
 108 @v = unpack("CCC",$b);
 109
 110 print join(',',@v);
 111 print "\\n";
 112}
 113
83.Sh SEE ALSO 114.Sh SEE ALSO
84.Xr gpio 4 , 115.Xr gpio 4 ,
85.Xr drvctl 8 , 116.Xr drvctl 8 ,
86.Xr gpioctl 8 117.Xr gpioctl 8
87.Sh HISTORY 118.Sh HISTORY
88The 119The
89.Nm 120.Nm
90driver first appeared in 121driver first appeared in
91.Nx 9.0 . 122.Nx 9.0 .
92.Sh AUTHORS 123.Sh AUTHORS
93.An -nosplit 124.An -nosplit
94The 125The
95.Nm 126.Nm
96driver was written by 127driver was written by
97.An Brad Spencer Aq Mt brad@anduin.eldar.org . 128.An Brad Spencer Aq Mt brad@anduin.eldar.org .
 129.Sh BUGS
 130When an interrupt fires in most devices there is not any information carried
 131along in the interrupt as to whether or not the pin is high or low. Hence the
 132driver reads the current state of the pin after the interrupt has fired and it is
 133possible that the state of the pin could have changed between the time the interrupt
 134fired and the reading of the state. As a practical matter the only time the pin state
 135will be reported wrong is if there is a very large number of interrupts happening. The
 136driver could have made some assumptions if the interrupt was only for a rising edge or falling
 137edge as in those cases it would be possible to know what the pin state would have been, but
 138in the case of the double edge, there really will not be any way to be sure with most hardware
 139and, in any case, the
 140.Xr gpio 4
 141infrastructure does not support getting at that information even if it did exist.
 142.Pp
 143It is important that if the
 144.Xr gpioirq 4
 145device is opened that it be read, as it may be possible
 146to run the kernel out of memory if the device is opened but not read and interrupts
 147occur on a pin tied to the driver.

cvs diff -r1.102 -r1.103 src/sys/conf/majors (expand / switch to unified diff)

--- src/sys/conf/majors 2022/08/12 11:15:42 1.102
+++ src/sys/conf/majors 2023/11/06 00:35:05 1.103
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: majors,v 1.102 2022/08/12 11:15:42 riastradh Exp $ 1# $NetBSD: majors,v 1.103 2023/11/06 00:35:05 brad Exp $
2# 2#
3# Device majors for Machine-Independent drivers. 3# Device majors for Machine-Independent drivers.
4# 4#
5# Majors 0-143 are reserved for machine-dependent drivers and 5# Majors 0-143 are reserved for machine-dependent drivers and
6# for traditional machine-specific MI driver major mapping. 6# for traditional machine-specific MI driver major mapping.
7# 7#
8# Majors 144-159 are reserved for local/vendor use. 8# Majors 144-159 are reserved for local/vendor use.
9# 9#
10# Majors 160-511 are used for the MI drivers. 10# Majors 160-511 are used for the MI drivers.
11 11
12device-major crypto char 160 crypto single 12device-major crypto char 160 crypto single
13device-major pf char 161 pf single 13device-major pf char 161 pf single
14#obsolete vinum char 162 vinum 14#obsolete vinum char 162 vinum
@@ -86,13 +86,14 @@ device-major spi char 347 spi @@ -86,13 +86,14 @@ device-major spi char 347 spi
86# Major 352 is reserved for external/cddl/osnet/dev/fbt/fbt.c 86# Major 352 is reserved for external/cddl/osnet/dev/fbt/fbt.c
87# Major 353 is reserved for external/cddl/osnet/dev/sdt/sdt.c 87# Major 353 is reserved for external/cddl/osnet/dev/sdt/sdt.c
88device-major ipmi char 354 ipmi 88device-major ipmi char 354 ipmi
89device-major vhci char 355 vhci 89device-major vhci char 355 vhci
90device-major vio9p char 356 vio9p 90device-major vio9p char 356 vio9p
91device-major fault char 357 fault 91device-major fault char 357 fault
92device-major wwanc char 358 wwanc 92device-major wwanc char 358 wwanc
93device-major acpi char 359 acpi 93device-major acpi char 359 acpi
94device-major smbios char 360 smbios 94device-major smbios char 360 smbios
95device-major efi char 361 efi 95device-major efi char 361 efi
96device-major sht3xtemp char 362 sht3xtemp 96device-major sht3xtemp char 362 sht3xtemp
97device-major scmd char 363 scmd 97device-major scmd char 363 scmd
98device-major viocon char 364 viocon 98device-major viocon char 364 viocon
 99device-major gpioirq char 365 gpioirq

cvs diff -r1.72 -r1.73 src/sys/dev/gpio/gpio.c (expand / switch to unified diff)

--- src/sys/dev/gpio/gpio.c 2022/12/13 21:50:43 1.72
+++ src/sys/dev/gpio/gpio.c 2023/11/06 00:35:05 1.73
@@ -1,39 +1,39 @@ @@ -1,39 +1,39 @@
1/* $NetBSD: gpio.c,v 1.72 2022/12/13 21:50:43 jakllsch Exp $ */ 1/* $NetBSD: gpio.c,v 1.73 2023/11/06 00:35:05 brad Exp $ */
2/* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */ 2/* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2008, 2009, 2010, 2011 Marc Balmer <marc@msys.ch> 5 * Copyright (c) 2008, 2009, 2010, 2011 Marc Balmer <marc@msys.ch>
6 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> 6 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
7 * 7 *
8 * Permission to use, copy, modify, and distribute this software for any 8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above 9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies. 10 * copyright notice and this permission notice appear in all copies.
11 * 11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */ 19 */
20 20
21#ifdef _KERNEL_OPT 21#ifdef _KERNEL_OPT
22#include "opt_fdt.h" 22#include "opt_fdt.h"
23#endif 23#endif
24 24
25#include <sys/cdefs.h> 25#include <sys/cdefs.h>
26__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.72 2022/12/13 21:50:43 jakllsch Exp $"); 26__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.73 2023/11/06 00:35:05 brad Exp $");
27 27
28/* 28/*
29 * General Purpose Input/Output framework. 29 * General Purpose Input/Output framework.
30 */ 30 */
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/callout.h> 33#include <sys/callout.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/conf.h> 35#include <sys/conf.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/fcntl.h> 37#include <sys/fcntl.h>
38#include <sys/ioctl.h> 38#include <sys/ioctl.h>
39#include <sys/gpio.h> 39#include <sys/gpio.h>
@@ -609,26 +609,34 @@ gpio_intr_str(void *gpio, struct gpio_pi @@ -609,26 +609,34 @@ gpio_intr_str(void *gpio, struct gpio_pi
609 return (false); 609 return (false);
610 610
611 if (! (*sc->sc_gc->gp_intr_str)(sc->sc_gc->gp_cookie, 611 if (! (*sc->sc_gc->gp_intr_str)(sc->sc_gc->gp_cookie,
612 sc->sc_pins[map->pm_map[pin]].pin_num, 612 sc->sc_pins[map->pm_map[pin]].pin_num,
613 irqmode, hwstr, sizeof(hwstr))) 613 irqmode, hwstr, sizeof(hwstr)))
614 return (false); 614 return (false);
615 615
616 (void) snprintf(intrstr, intrstrlen, "%s (%s)", hwstr, mode); 616 (void) snprintf(intrstr, intrstrlen, "%s (%s)", hwstr, mode);
617  617
618 return (true); 618 return (true);
619} 619}
620 620
621int 621int
 622gpio_pin_to_pin_num(void *gpio, struct gpio_pinmap *map, int pin)
 623{
 624 struct gpio_softc *sc = gpio;
 625
 626 return sc->sc_pins[map->pm_map[pin]].pin_num;
 627}
 628
 629int
622gpio_npins(uint32_t mask) 630gpio_npins(uint32_t mask)
623{ 631{
624 int npins, i; 632 int npins, i;
625 633
626 for (npins = 0, i = 0; i < 32; i++) 634 for (npins = 0, i = 0; i < 32; i++)
627 if (mask & (1 << i)) 635 if (mask & (1 << i))
628 npins++; 636 npins++;
629 637
630 return npins; 638 return npins;
631} 639}
632 640
633int 641int
634gpio_lock(void *data) 642gpio_lock(void *data)

cvs diff -r1.1 -r1.2 src/sys/dev/gpio/gpioirq.c (expand / switch to unified diff)

--- src/sys/dev/gpio/gpioirq.c 2018/05/19 14:15:39 1.1
+++ src/sys/dev/gpio/gpioirq.c 2023/11/06 00:35:05 1.2
@@ -1,228 +1,480 @@ @@ -1,228 +1,480 @@
1/* $NetBSD: gpioirq.c,v 1.1 2018/05/19 14:15:39 thorpej Exp $ */ 1/* $NetBSD: gpioirq.c,v 1.2 2023/11/06 00:35:05 brad Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2016 Brad Spencer <brad@anduin.eldar.org> 4 * Copyright (c) 2016, 2023 Brad Spencer <brad@anduin.eldar.org>
5 * 5 *
6 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies. 8 * copyright notice and this permission notice appear in all copies.
9 * 9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19#include <sys/cdefs.h> 19#include <sys/cdefs.h>
20__KERNEL_RCSID(0, "$NetBSD: gpioirq.c,v 1.1 2018/05/19 14:15:39 thorpej Exp $"); 20__KERNEL_RCSID(0, "$NetBSD: gpioirq.c,v 1.2 2023/11/06 00:35:05 brad Exp $");
21 21
22/* 22/*
23 * Example GPIO driver that uses interrupts. 23 * GPIO driver that uses interrupts and can send that fact to userland.
24 */ 24 */
25 25
26#include <sys/param.h> 26#include <sys/param.h>
27#include <sys/systm.h> 27#include <sys/systm.h>
28#include <sys/device.h> 28#include <sys/device.h>
 29#include <sys/device_impl.h>
29#include <sys/gpio.h> 30#include <sys/gpio.h>
30#include <sys/module.h> 31#include <sys/module.h>
 32#include <sys/conf.h>
 33#include <sys/proc.h>
 34#include <sys/pool.h>
 35#include <sys/kmem.h>
 36#include <sys/condvar.h>
31 37
32#include <dev/gpio/gpiovar.h> 38#include <dev/gpio/gpiovar.h>
33 39
34#define GPIOIRQ_NPINS 1 40#define GPIOIRQ_NPINS 64
 41
 42struct gpioirq_iv {
 43 char sc_intrstr[128];
 44 void * sc_ih;
 45 int i_thispin_index;
 46 uint8_t i_thispin_num;
 47 uint8_t i_parentunit;
 48 struct gpioirq_softc *sc;
 49};
35 50
36struct gpioirq_softc { 51struct gpioirq_softc {
37 device_t sc_dev; 52 device_t sc_dev;
 53 device_t sc_parentdev;
38 void * sc_gpio; 54 void * sc_gpio;
39 struct gpio_pinmap sc_map; 55 struct gpio_pinmap sc_map;
40 int _map[GPIOIRQ_NPINS]; 56 int _map[GPIOIRQ_NPINS];
41 char sc_intrstr[128]; 57 struct gpioirq_iv sc_intrs[GPIOIRQ_NPINS];
42 void * sc_ih; 58 int sc_npins;
43 kmutex_t sc_lock; 59 kmutex_t sc_lock;
 60 kmutex_t sc_read_mutex;
 61 kmutex_t sc_dying_mutex;
44 bool sc_verbose; 62 bool sc_verbose;
45 bool sc_functional; 63 bool sc_functional;
 64 bool sc_opened;
 65 bool sc_dying;
 66 kcondvar_t sc_condreadready;
 67 kcondvar_t sc_cond_dying;
 68 pool_cache_t sc_readpool;
 69 char *sc_readpoolname;
 70 SIMPLEQ_HEAD(,gpioirq_read_q) sc_read_queue;
 71};
 72
 73struct gpioirq_read_q {
 74 int parentunit;
 75 int thepin;
 76 int theval;
 77 SIMPLEQ_ENTRY(gpioirq_read_q) read_q;
46}; 78};
47 79
48#define GPIOIRQ_FLAGS_IRQMODE GPIO_INTR_MODE_MASK 80#define GPIOIRQ_FLAGS_IRQMODE GPIO_INTR_MODE_MASK
49#define GPIOIRQ_FLAGS_VERBOSE 0x1000 81#define GPIOIRQ_FLAGS_VERBOSE 0x1000
50 82
51static int gpioirq_match(device_t, cfdata_t, void *); 83static int gpioirq_match(device_t, cfdata_t, void *);
52static void gpioirq_attach(device_t, device_t, void *); 84static void gpioirq_attach(device_t, device_t, void *);
53static int gpioirq_detach(device_t, int); 85static int gpioirq_detach(device_t, int);
54static int gpioirq_activate(device_t, enum devact); 86static int gpioirq_activate(device_t, enum devact);
55 
56static int gpioirq_intr(void *); 87static int gpioirq_intr(void *);
 88static uint8_t gpioirq_index_to_pin_num(struct gpioirq_softc *, int);
 89static uint8_t gpioirq_parent_unit(struct gpioirq_softc *);
57 90
58CFATTACH_DECL_NEW(gpioirq, sizeof(struct gpioirq_softc), 91CFATTACH_DECL_NEW(gpioirq, sizeof(struct gpioirq_softc),
59 gpioirq_match, gpioirq_attach, 92 gpioirq_match, gpioirq_attach,
60 gpioirq_detach, gpioirq_activate); 93 gpioirq_detach, gpioirq_activate);
61 94
62extern struct cfdriver gpioirq_cd; 95extern struct cfdriver gpioirq_cd;
63 96
 97static dev_type_open(gpioirq_open);
 98static dev_type_read(gpioirq_read);
 99static dev_type_close(gpioirq_close);
 100const struct cdevsw gpioirq_cdevsw = {
 101 .d_open = gpioirq_open,
 102 .d_close = gpioirq_close,
 103 .d_read = gpioirq_read,
 104 .d_write = nowrite,
 105 .d_ioctl = noioctl,
 106 .d_stop = nostop,
 107 .d_tty = notty,
 108 .d_poll = nopoll,
 109 .d_mmap = nommap,
 110 .d_kqfilter = nokqfilter,
 111 .d_discard = nodiscard,
 112 .d_flag = D_OTHER
 113};
 114
 115static uint8_t
 116gpioirq_index_to_pin_num(struct gpioirq_softc *sc, int index)
 117{
 118 return (uint8_t)gpio_pin_to_pin_num(sc->sc_gpio, &sc->sc_map, index);
 119}
 120
 121static uint8_t
 122gpioirq_parent_unit(struct gpioirq_softc *sc)
 123{
 124 device_t parent = sc->sc_parentdev;
 125
 126 return (uint8_t)parent->dv_unit;
 127}
 128
64static int 129static int
65gpioirq_match(device_t parent, cfdata_t cf, void *aux) 130gpioirq_match(device_t parent, cfdata_t cf, void *aux)
66{ 131{
67 struct gpio_attach_args *ga = aux; 132 struct gpio_attach_args *ga = aux;
68 int npins; 
69 133
70 if (strcmp(ga->ga_dvname, cf->cf_name)) 134 if (strcmp(ga->ga_dvname, cf->cf_name))
71 return (0); 135 return (0);
72  
73 if (ga->ga_offset == -1) 
74 return (0); 
75 136
76 npins = gpio_npins(ga->ga_mask); 137 if (ga->ga_offset == -1)
77 if (npins > 1) 
78 return (0); 138 return (0);
79 139
80 return (1); 140 return (1);
81} 141}
82 142
83static void 143static void
84gpioirq_attach(device_t parent, device_t self, void *aux) 144gpioirq_attach(device_t parent, device_t self, void *aux)
85{ 145{
86 struct gpioirq_softc *sc = device_private(self); 146 struct gpioirq_softc *sc = device_private(self);
87 struct gpio_attach_args *ga = aux; 147 struct gpio_attach_args *ga = aux;
88 int npins = gpio_npins(ga->ga_mask); 148 int mask = ga->ga_mask;
89 int irqmode, flags; 149 int irqmode, flags;
90 150
91 sc->sc_dev = self; 151 sc->sc_dev = self;
 152 sc->sc_parentdev = parent;
 153 sc->sc_opened = false;
 154 sc->sc_dying = false;
 155 sc->sc_readpoolname = NULL;
92 156
93 /* Map pins */ 157 /* Map pins */
94 sc->sc_gpio = ga->ga_gpio; 158 sc->sc_gpio = ga->ga_gpio;
95 sc->sc_map.pm_map = sc->_map; 159 sc->sc_map.pm_map = sc->_map;
96 160
97 /* We always map just 1 pin. */ 161 /* Determine our pin configuation. */
 162 sc->sc_npins = gpio_npins(mask);
 163 if (sc->sc_npins == 0) {
 164 sc->sc_npins = 1;
 165 mask = 0x1;
 166 }
 167
 168 /* XXX - exit if more than allowed number of pins */
 169
98 if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, 170 if (gpio_pin_map(sc->sc_gpio, ga->ga_offset,
99 npins ? ga->ga_mask : 0x1, &sc->sc_map)) { 171 mask, &sc->sc_map)) {
100 aprint_error(": can't map pins\n"); 172 aprint_error(": can't map pins\n");
101 return; 173 return;
102 } 174 }
103 175
104 aprint_normal("\n"); 176 aprint_normal("\n");
105 177
106 if (ga->ga_flags & GPIOIRQ_FLAGS_VERBOSE) 178 if (ga->ga_flags & GPIOIRQ_FLAGS_VERBOSE)
107 sc->sc_verbose = true; 179 sc->sc_verbose = true;
108 180
109 irqmode = ga->ga_flags & GPIOIRQ_FLAGS_IRQMODE; 181 irqmode = ga->ga_flags & GPIOIRQ_FLAGS_IRQMODE;
110 182
111 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); 183 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
112 184 mutex_init(&sc->sc_dying_mutex, MUTEX_DEFAULT, IPL_VM);
113 if (!gpio_intr_str(sc->sc_gpio, &sc->sc_map, 0, irqmode, 185 mutex_init(&sc->sc_read_mutex, MUTEX_DEFAULT, IPL_VM);
114 sc->sc_intrstr, sizeof(sc->sc_intrstr))) { 186 cv_init(&sc->sc_cond_dying, "girqdie");
115 aprint_error_dev(self, "failed to decode interrupt\n"); 187 cv_init(&sc->sc_condreadready,"girqrr");
116 return; 188 sc->sc_readpoolname = kmem_asprintf("girqread%d",device_unit(self));
117 } 189 sc->sc_readpool = pool_cache_init(sizeof(struct gpioirq_read_q),0,0,0,sc->sc_readpoolname,NULL,IPL_VM,NULL,NULL,NULL);
118 190 pool_cache_sethiwat(sc->sc_readpool,100);
119 if (!gpio_pin_irqmode_issupported(sc->sc_gpio, &sc->sc_map, 0, 191 SIMPLEQ_INIT(&sc->sc_read_queue);
120 irqmode)) { 192
121 aprint_error_dev(self, 193 for(int apin = 0; apin < sc->sc_npins; apin++) {
122 "irqmode not supported: %s\n", sc->sc_intrstr); 194 if (!gpio_intr_str(sc->sc_gpio, &sc->sc_map, apin, irqmode,
123 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 195 sc->sc_intrs[apin].sc_intrstr, sizeof(sc->sc_intrs[apin].sc_intrstr))) {
124 return; 196 aprint_error_dev(self, "failed to decode interrupt\n");
125 } 197 return;
126 198 }
127 flags = gpio_pin_get_conf(sc->sc_gpio, &sc->sc_map, 0); 199
128 flags = (flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INOUT)) | 200 if (!gpio_pin_irqmode_issupported(sc->sc_gpio, &sc->sc_map, apin,
129 GPIO_PIN_INPUT; 201 irqmode)) {
130 if (!gpio_pin_set_conf(sc->sc_gpio, &sc->sc_map, 0, flags)) { 202 aprint_error_dev(self,
131 aprint_error_dev(sc->sc_dev, "pin not capable of input\n"); 203 "irqmode not supported: %s\n", sc->sc_intrs[apin].sc_intrstr);
132 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 204 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
133 return; 205 return;
 206 }
 207
 208 flags = gpio_pin_get_conf(sc->sc_gpio, &sc->sc_map, apin);
 209 flags = (flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INOUT)) |
 210 GPIO_PIN_INPUT;
 211 if (!gpio_pin_set_conf(sc->sc_gpio, &sc->sc_map, apin, flags)) {
 212 aprint_error_dev(sc->sc_dev, "pin not capable of input\n");
 213 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
 214 return;
 215 }
 216
 217 /* These are static for each pin, so just stuff them in here,
 218 * so they don't need to be looked up again.
 219 */
 220 sc->sc_intrs[apin].i_thispin_index = apin;
 221 sc->sc_intrs[apin].i_thispin_num = gpioirq_index_to_pin_num(sc,apin);
 222 sc->sc_intrs[apin].i_parentunit = gpioirq_parent_unit(sc);
 223 sc->sc_intrs[apin].sc = sc;
 224
 225 sc->sc_intrs[apin].sc_ih = gpio_intr_establish(sc->sc_gpio, &sc->sc_map, apin, IPL_VM,
 226 irqmode | GPIO_INTR_MPSAFE,
 227 gpioirq_intr, &sc->sc_intrs[apin]);
 228 if (sc->sc_intrs[apin].sc_ih == NULL) {
 229 aprint_error_dev(self,
 230 "unable to establish interrupt on %s\n", sc->sc_intrs[apin].sc_intrstr);
 231 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
 232 return;
 233 }
 234 aprint_normal_dev(self, "interrupting on %s\n", sc->sc_intrs[apin].sc_intrstr);
134 } 235 }
135 236
136 sc->sc_ih = gpio_intr_establish(sc->sc_gpio, &sc->sc_map, 0, IPL_VM, 
137 irqmode | GPIO_INTR_MPSAFE, 
138 gpioirq_intr, sc); 
139 if (sc->sc_ih == NULL) { 
140 aprint_error_dev(self, 
141 "unable to establish interrupt on %s\n", sc->sc_intrstr); 
142 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 
143 return; 
144 } 
145 aprint_normal_dev(self, "interrupting on %s\n", sc->sc_intrstr); 
146 
147 sc->sc_functional = true; 237 sc->sc_functional = true;
148} 238}
149 239
150int 240int
151gpioirq_intr(void *arg) 241gpioirq_intr(void *arg)
152{ 242{
153 struct gpioirq_softc *sc = arg; 243 struct gpioirq_iv *is = arg;
 244 struct gpioirq_softc *sc = is->sc;
 245 struct gpioirq_read_q *q;
154 int val; 246 int val;
155 247
156 mutex_enter(&sc->sc_lock); 248 mutex_enter(&sc->sc_lock);
157 249
158 val = gpio_pin_read(sc->sc_gpio, &sc->sc_map, 0); 250 val = gpio_pin_read(sc->sc_gpio, &sc->sc_map, is->i_thispin_index);
159 251
160 if (sc->sc_verbose) 252 if (sc->sc_verbose)
161 printf("%s: interrupt on %s --> %d\n", 253 printf("%s: interrupt on %s --> %d\n",
162 device_xname(sc->sc_dev), sc->sc_intrstr, val); 254 device_xname(sc->sc_dev), sc->sc_intrs[is->i_thispin_index].sc_intrstr, val);
163 255
164 mutex_exit(&sc->sc_lock); 256 mutex_exit(&sc->sc_lock);
165 257
 258 if (sc->sc_opened) {
 259 mutex_enter(&sc->sc_read_mutex);
 260 q = pool_cache_get(sc->sc_readpool,PR_NOWAIT);
 261 if (q != NULL) {
 262 q->thepin = is->i_thispin_num;
 263 q->parentunit = is->i_parentunit;
 264 q->theval = val;
 265 SIMPLEQ_INSERT_TAIL(&sc->sc_read_queue,q,read_q);
 266 cv_signal(&sc->sc_condreadready);
 267 } else {
 268 aprint_error("Could not allocate memory for read pool\n");
 269 }
 270 mutex_exit(&sc->sc_read_mutex);
 271 }
 272
166 return (1); 273 return (1);
167} 274}
168 275
 276static int
 277gpioirq_open(dev_t dev, int flags, int fmt, struct lwp *l)
 278{
 279 struct gpioirq_softc *sc;
 280
 281 sc = device_lookup_private(&gpioirq_cd, minor(dev));
 282 if (!sc)
 283 return (ENXIO);
 284
 285 if (sc->sc_opened)
 286 return (EBUSY);
 287
 288 mutex_enter(&sc->sc_lock);
 289 sc->sc_opened = true;
 290 mutex_exit(&sc->sc_lock);
 291
 292 return (0);
 293}
 294
 295static int
 296gpioirq_read(dev_t dev, struct uio *uio, int flags)
 297{
 298 struct gpioirq_softc *sc;
 299 struct gpioirq_read_q *chp;
 300 int error = 0,any;
 301 uint8_t obuf[3];
 302
 303 sc = device_lookup_private(&gpioirq_cd, minor(dev));
 304 if (!sc)
 305 return (ENXIO);
 306
 307 while (uio->uio_resid > 0) {
 308 any = 0;
 309 error = 0;
 310 mutex_enter(&sc->sc_read_mutex);
 311
 312 while (any == 0) {
 313 chp = SIMPLEQ_FIRST(&sc->sc_read_queue);
 314 if (chp != NULL) {
 315 SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
 316 any = 1;
 317 break;
 318 } else {
 319 error = cv_wait_sig(&sc->sc_condreadready,&sc->sc_read_mutex);
 320 if (sc->sc_dying)
 321 error = EIO;
 322 if (error == 0)
 323 continue;
 324 break;
 325 }
 326 }
 327
 328 if (any == 1 && error == 0) {
 329 obuf[0] = (uint8_t)chp->parentunit;
 330 obuf[1] = (uint8_t)chp->thepin;
 331 obuf[2] = (uint8_t)chp->theval;
 332 pool_cache_put(sc->sc_readpool,chp);
 333 mutex_exit(&sc->sc_read_mutex);
 334 if ((error = uiomove(&obuf[0], 3, uio)) != 0) {
 335 break;
 336 }
 337 } else {
 338 mutex_exit(&sc->sc_read_mutex);
 339 if (error) {
 340 break;
 341 }
 342 }
 343 }
 344
 345 if (sc->sc_dying) {
 346 mutex_enter(&sc->sc_dying_mutex);
 347 cv_signal(&sc->sc_cond_dying);
 348 mutex_exit(&sc->sc_dying_mutex);
 349 }
 350 return error;
 351}
 352
 353static int
 354gpioirq_close(dev_t dev, int flags, int fmt, struct lwp *l)
 355{
 356 struct gpioirq_softc *sc;
 357 struct gpioirq_read_q *q;
 358
 359 sc = device_lookup_private(&gpioirq_cd, minor(dev));
 360
 361 mutex_enter(&sc->sc_lock);
 362 while ((q = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) {
 363 SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
 364 pool_cache_put(sc->sc_readpool,q);
 365 }
 366 sc->sc_opened = false;
 367 mutex_exit(&sc->sc_lock);
 368
 369 return(0);
 370}
 371
169int 372int
170gpioirq_detach(device_t self, int flags) 373gpioirq_detach(device_t self, int flags)
171{ 374{
172 struct gpioirq_softc *sc = device_private(self); 375 struct gpioirq_softc *sc = device_private(self);
 376 struct gpioirq_read_q *q;
173 377
174 /* Clear the handler and disable the interrupt. */ 378 /* Clear the handler and disable the interrupt. */
175 gpio_intr_disestablish(sc->sc_gpio, sc->sc_ih); 379 for(int apin = 0;apin < sc->sc_npins;apin++) {
 380 gpio_intr_disestablish(sc->sc_gpio, sc->sc_intrs[apin].sc_ih);
 381 }
176 382
177 /* Release the pin. */ 383 /* Release the pin. */
178 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 384 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
179 385
 386 sc->sc_dying = true;
 387
 388 if (sc->sc_opened) {
 389 mutex_enter(&sc->sc_dying_mutex);
 390 mutex_enter(&sc->sc_read_mutex);
 391 cv_signal(&sc->sc_condreadready);
 392 mutex_exit(&sc->sc_read_mutex);
 393 /* In the worst case this will time out after 5 seconds.
 394 * It really should not take that long for the drain / whatever
 395 * to happen
 396 */
 397 cv_timedwait_sig(&sc->sc_cond_dying,
 398 &sc->sc_dying_mutex, mstohz(5000));
 399 mutex_exit(&sc->sc_dying_mutex);
 400 cv_destroy(&sc->sc_condreadready);
 401 cv_destroy(&sc->sc_cond_dying);
 402 }
 403
 404 /* Drain any read pools */
 405 while ((q = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) {
 406 SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
 407 pool_cache_put(sc->sc_readpool,q);
 408 }
 409
 410 if (sc->sc_readpoolname != NULL) {
 411 kmem_free(sc->sc_readpoolname,strlen(sc->sc_readpoolname) + 1);
 412 }
 413
 414 mutex_destroy(&sc->sc_read_mutex);
 415 mutex_destroy(&sc->sc_lock);
 416
180 return (0); 417 return (0);
181} 418}
182 419
183int 420int
184gpioirq_activate(device_t self, enum devact act) 421gpioirq_activate(device_t self, enum devact act)
185{ 422{
186 423
 424 struct gpioirq_softc *sc = device_private(self);
 425
187 switch (act) { 426 switch (act) {
188 case DVACT_DEACTIVATE: 427 case DVACT_DEACTIVATE:
189 /* We don't really need to do anything. */ 428 sc->sc_dying = true;
190 return (0); 429 return (0);
191 default: 430 default:
192 return (EOPNOTSUPP); 431 return (EOPNOTSUPP);
193 } 432 }
194} 433}
195 434
196MODULE(MODULE_CLASS_DRIVER, gpioirq, "gpio"); 435MODULE(MODULE_CLASS_DRIVER, gpioirq, "gpio");
197 436
198#ifdef _MODULE 437#ifdef _MODULE
199#include "ioconf.c" 438#include "ioconf.c"
200#endif 439#endif
201 440
202static int 441static int
203gpioirq_modcmd(modcmd_t cmd, void *opaque) 442gpioirq_modcmd(modcmd_t cmd, void *opaque)
204{ 443{
205 int error = 0; 444 int error = 0;
 445#ifdef _MODULE
 446 int bmaj = -1, cmaj = -1;
 447#endif
206 448
207 switch (cmd) { 449 switch (cmd) {
208 case MODULE_CMD_INIT: 450 case MODULE_CMD_INIT:
209#ifdef _MODULE 451#ifdef _MODULE
210 error = config_init_component(cfdriver_ioconf_gpioirq, 452 error = config_init_component(cfdriver_ioconf_gpioirq,
211 cfattach_ioconf_gpioirq, cfdata_ioconf_gpioirq); 453 cfattach_ioconf_gpioirq, cfdata_ioconf_gpioirq);
212 if (error) 454 if (error) {
213 aprint_error("%s: unable to init component\n", 455 aprint_error("%s: unable to init component\n",
214 gpioirq_cd.cd_name); 456 gpioirq_cd.cd_name);
 457 return (error);
 458 }
 459
 460 error = devsw_attach("gpioirq", NULL, &bmaj,
 461 &gpioirq_cdevsw, &cmaj);
 462 if (error) {
 463 aprint_error("%s: unable to attach devsw\n",
 464 gpioirq_cd.cd_name);
 465 config_fini_component(cfdriver_ioconf_gpioirq,
 466 cfattach_ioconf_gpioirq, cfdata_ioconf_gpioirq);
 467 }
215#endif 468#endif
216 break; 469 return (error);
217 case MODULE_CMD_FINI: 470 case MODULE_CMD_FINI:
218#ifdef _MODULE 471#ifdef _MODULE
 472 devsw_detach(NULL, &gpioirq_cdevsw);
219 config_fini_component(cfdriver_ioconf_gpioirq, 473 config_fini_component(cfdriver_ioconf_gpioirq,
220 cfattach_ioconf_gpioirq, cfdata_ioconf_gpioirq); 474 cfattach_ioconf_gpioirq, cfdata_ioconf_gpioirq);
221#endif 475#endif
222 break; 476 return (0);
223 default: 477 default:
224 error = ENOTTY; 478 return (ENOTTY);
225 } 479 }
226 
227 return (error); 
228} 480}

cvs diff -r1.18 -r1.19 src/sys/dev/gpio/gpiovar.h (expand / switch to unified diff)

--- src/sys/dev/gpio/gpiovar.h 2018/05/19 13:59:06 1.18
+++ src/sys/dev/gpio/gpiovar.h 2023/11/06 00:35:05 1.19
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gpiovar.h,v 1.18 2018/05/19 13:59:06 thorpej Exp $ */ 1/* $NetBSD: gpiovar.h,v 1.19 2023/11/06 00:35:05 brad Exp $ */
2/* $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $ */ 2/* $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> 5 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
@@ -108,18 +108,19 @@ int gpio_pin_caps(void *, struct gpio_pi @@ -108,18 +108,19 @@ int gpio_pin_caps(void *, struct gpio_pi
108int gpio_pin_get_conf(void *, struct gpio_pinmap *, int); 108int gpio_pin_get_conf(void *, struct gpio_pinmap *, int);
109bool gpio_pin_set_conf(void *, struct gpio_pinmap *, int, int); 109bool gpio_pin_set_conf(void *, struct gpio_pinmap *, int, int);
110void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int); 110void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int);
111int gpio_pin_intrcaps(void *, struct gpio_pinmap *, int); 111int gpio_pin_intrcaps(void *, struct gpio_pinmap *, int);
112bool gpio_pin_irqmode_issupported(void *, struct gpio_pinmap *, int, int); 112bool gpio_pin_irqmode_issupported(void *, struct gpio_pinmap *, int, int);
113int gpio_pin_wait(void *, int); 113int gpio_pin_wait(void *, int);
114int gpio_npins(uint32_t); 114int gpio_npins(uint32_t);
115 115
116void * gpio_intr_establish(void *, struct gpio_pinmap *, int, int, int, 116void * gpio_intr_establish(void *, struct gpio_pinmap *, int, int, int,
117 int (*)(void *), void *); 117 int (*)(void *), void *);
118void gpio_intr_disestablish(void *, void *); 118void gpio_intr_disestablish(void *, void *);
119bool gpio_intr_str(void *, struct gpio_pinmap *, int, int, 119bool gpio_intr_str(void *, struct gpio_pinmap *, int, int,
120 char *, size_t); 120 char *, size_t);
 121int gpio_pin_to_pin_num(void *, struct gpio_pinmap *, int);
121 122
122int gpio_lock(void *); 123int gpio_lock(void *);
123void gpio_unlock(void *); 124void gpio_unlock(void *);
124 125
125#endif /* !_DEV_GPIO_GPIOVAR_H_ */ 126#endif /* !_DEV_GPIO_GPIOVAR_H_ */