LWN: Comments on "GPIO in the kernel: an introduction" https://lwn.net/Articles/532714/ This is a special feed containing comments posted to the individual LWN article titled "GPIO in the kernel: an introduction". en-us Sat, 25 Oct 2025 20:28:33 +0000 Sat, 25 Oct 2025 20:28:33 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net GPIO in the kernel: an introduction https://lwn.net/Articles/780022/ https://lwn.net/Articles/780022/ jem I do think the author is still using LWN.net. :) But he may be busy with other things. Mon, 18 Feb 2019 09:38:13 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/779724/ https://lwn.net/Articles/779724/ Circuits <div class="FormattedComment"> Great information! Too bad this post was made in 2013 cause I have some questions here in 2018. Is the author or another authority still using LWN.net?<br> </div> Wed, 13 Feb 2019 16:51:56 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/714376/ https://lwn.net/Articles/714376/ asmo <div class="FormattedComment"> Hi,<br> I need to use the same GPIO output in two different drivers.<br> Is it possible to use the set of apis gpio_request/gpio_get_value/gpio_set_value in parallel in both device drivers?<br> </div> Mon, 13 Feb 2017 10:36:13 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/709538/ https://lwn.net/Articles/709538/ flussence <div class="FormattedComment"> Fun trivia: this is exactly what the NES Classic does. In their GPL code dump there's a kernel driver for the controller - it has the same wire protocol the Wiimote uses (internally!), but leaves the kernel to deal with all that hardware-related insanity and more.<br> </div> Sat, 17 Dec 2016 06:44:15 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/709378/ https://lwn.net/Articles/709378/ pizza <div class="FormattedComment"> But hardware debounce would require adding extra $0.02 worth of components and growing your board size by 2 square millimeters.<br> <p> Why spent that money on every unit when it can be done once, "for free" in software?<br> </div> Thu, 15 Dec 2016 20:32:11 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/709375/ https://lwn.net/Articles/709375/ BlueLightning <div class="FormattedComment"> Surely the answer to switch bounce is to do the debouncing in hardware?<br> </div> Thu, 15 Dec 2016 20:05:27 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/709262/ https://lwn.net/Articles/709262/ bla <div class="FormattedComment"> Ok, you c a n set a combined interrupt mask and query the pin state in the ISR on an RPi, but gpio_get_value seems to have latency, which makes this approach pretty much useless in conjunction with switch bounce and the ISR time constraints. <br> For implementing long button presses, detecting the first flank and reading the level with a thread after some delay seems to be the better approach, it also doesn't require a state change to trigger the long press signal.<br> </div> Thu, 15 Dec 2016 11:07:11 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/709015/ https://lwn.net/Articles/709015/ bla <div class="FormattedComment"> Ah, probably a gpio-controller/IRQ line limitation. I'll check if it works on a Raspberry (should, as Wiring has a BOTH option).<br> </div> Tue, 13 Dec 2016 19:11:08 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/709011/ https://lwn.net/Articles/709011/ nybble41 <div class="FormattedComment"> <font class="QuotedText">&gt; Why wouldn't IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING with request_irq work?</font><br> <p> Things may be different on ARM or x86, but in my work on embedded PowerPC targets I have yet to see an interrupt controller than can be configured to trigger on both rising and falling edges for the same signal. Typically there are four possible trigger modes, of which only one can be active at a time: rising edge, falling edge, high level, or low level.<br> </div> Tue, 13 Dec 2016 18:28:34 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/708999/ https://lwn.net/Articles/708999/ bla <div class="FormattedComment"> Why wouldn't IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING with request_irq work?<br> </div> Tue, 13 Dec 2016 16:46:51 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/708923/ https://lwn.net/Articles/708923/ nybble41 <div class="FormattedComment"> <font class="QuotedText">&gt; Anything speaking against using gpio_get_value in the isr to discern between rising and falling?</font><br> <p> The ISR will only run on the rising edge _or_ the falling edge, not both, so gpio_get_value will generally return a known result: either high for a rising-edge-triggered interrupt, or low for falling-edge.<br> </div> Tue, 13 Dec 2016 14:56:02 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/708922/ https://lwn.net/Articles/708922/ bla <div class="FormattedComment"> Anything speaking against using gpio_get_value in the isr to discern between rising and falling?<br> </div> Tue, 13 Dec 2016 14:20:54 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/702497/ https://lwn.net/Articles/702497/ annonch <div class="FormattedComment"> Wow thank you for the suggestion, it seems to work perfectly! I have configured an additional pin fed with the same signal and I think this method will work well for my project. :)<br> </div> Mon, 03 Oct 2016 22:58:49 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/702487/ https://lwn.net/Articles/702487/ nybble41 <div class="FormattedComment"> <font class="QuotedText">&gt; Is it possible to register an interrupt to both falling edge and rising edge and then distinguish which case it is inside the interrupt handler?</font><br> <p> Generally speaking, no. I'm not familiar with your specific platform, but typically one configures the interrupt controller to look for either a rising edge or a falling edge (or low/high level) for each input and it generates a single interrupt when that event occurs. As a result, there is no way to statically configure it to watch for both rising and falling edges.<br> <p> You could try dynamically reconfiguring the interrupt—set it as falling-edge in the rising-edge handler, and vice-versa—but performance would probably become an issue and you might miss some events depending on how long the handler is delayed. A better option, if you control the wiring and have a spare interrupt-capable GPIO, would be to route the same signal to two separate pins and set up a handler for each pin, one rising-edge and one falling-edge.<br> </div> Mon, 03 Oct 2016 19:27:50 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/702486/ https://lwn.net/Articles/702486/ annonch <div class="FormattedComment"> Is it possible to register an interrupt to both falling edge and rising edge and then distinguish which case it is inside the interrupt handler?<br> <p> When I try to register two interrupts I get an error resource is busy, I think because it is the same irq_number (-16)<br> <p> When I try to register the interrupts with the IRQF_SHARED | IRQF_TRIGGER_RISING flags I get Invalid argument (-22)<br> <p> So I create a interrupt with flags IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING but when the interrupt is called, I want to distinguish the two conditions separately.<br> <p> It is an arm device with kernel 4.4.21<br> <p> Any advice? :)<br> </div> Mon, 03 Oct 2016 19:12:34 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/694917/ https://lwn.net/Articles/694917/ mjg59 <div class="FormattedComment"> They're EXPORT_SYMBOL_GPL - make sure that your MODULE_LICENSE tag is GPL compatible.<br> </div> Wed, 20 Jul 2016 08:05:56 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/694916/ https://lwn.net/Articles/694916/ codename_y <div class="FormattedComment"> Hi, I have tried to make a driver that utilize linux/gpio.h, but when I try to insmod it, I keep getting this error:<br> <p> [ 3030.112044] gpiotest: Unknown symbol gpio_direction_output (err 0)<br> [ 3030.118537] gpiotest: Unknown symbol gpio_request (err 0)<br> <p> Could you give me some insight about why this happened? I have tried to find by myself but no luck so far.<br> <p> Thanks for your help<br> </div> Wed, 20 Jul 2016 07:52:34 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/534713/ https://lwn.net/Articles/534713/ BenHutchings <blockquote>1. GPIO can be both output and input at the same time. Yep you may want to read back the value of an output.</blockquote> <p>Indeed this is an absolute requirement for a GPIO used as an I2C SCL line.</p> Mon, 28 Jan 2013 21:27:53 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533423/ https://lwn.net/Articles/533423/ etienne <div class="FormattedComment"> <font class="QuotedText">&gt;&gt; #define IOWRITE32BITS(addr, val) *((volatile unsigned *)(addr)) = (val)</font><br> <font class="QuotedText">&gt; The volatile should ensure that both writes occur in that case.</font><br> <p> Last time I tried few days ago it did not work, you have to do:<br> #define IOWRITE32BITS(addr, val) do { \<br> volatile unsigned *ptr = (volatile unsigned *)(addr); \<br> *ptr = (val); \<br> } while (0)<br> <p> <font class="QuotedText">&gt; You lose control over the access size</font><br> <p> Yes, I would also like to have bitfields accessed like they are declared, i.e. "char abit : 2;" accessed as a byte and "unsigned abit :2;" accessed as a 32 bits, because it is usual to have devices which cannot do short word access (lots of system on chip).<br> <p> <font class="QuotedText">&gt; [... using "(struct my_IO_s) {}" extension ...]</font><br> <p> My system is more complex than Arduino, I have arrays of structures containing other arrays in these I/O areas, and all those #define blessed by software-quality people drive me mad.<br> #define FPGA1_FILTER_2_PARAMETER_4_ACTIVE 1<br> How to do a loop for each filters?<br> In short, in C or C++, unlike BASIC, the linker is made to manage addresses, the compiler manages offsets into these addresses; the C pre-processor has nothing to do there.<br> IHMO even GPIO in the kernel shall be identified with an address, not a #define.<br> </div> Mon, 21 Jan 2013 11:36:37 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533280/ https://lwn.net/Articles/533280/ jimparis <blockquote> Also those quality specialists tell you to use the macro:<br> #define IOWRITE32BYTE(addr, val) *((volatile unsigned *)(addr)) = (val)<br> (Hint: try to write the same addr twice with a newer compiler). </blockquote> <p>The volatile should ensure that both writes occur in that case. <blockquote> Anyway on newer architecture, those are memory mapped and IHMO it is a lot cleaner to use C to declare them:<br> volatile struct my_IO_s {<br> enum { healthy, fail } power_state : 1;<br> unsigned power_active : 1;<br> } * const my_IO = (volatile struct my_IO_s *)0xDC002000;<br> Instead of pages and pages of #define. </blockquote> <p> I agree, and I do the same in embedded development, but it's not perfect. The three biggest problems: <ul> <li>You lose control over the access size. It can vary between compilers, compiler versions, architectures, and even ABIs for particular architectures. For example, see <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23623">GCC bug #23623</a> <li>They don't map well to unusual registers. Consider an interrupt flag register which behaves like: <pre> read 0: interrupt has not occurred read 1: interrupt has occurred write 0: no action write 1: clear interrupt flag </pre> To clear a flag, you can't just do: <pre> my_IO->timer_interrupt = 1; </pre> because this can become <pre> tmp = *my_IO_addr | (1 &lt;&lt; TIMER_INTERRUPT_SHIFT); *my_IO_addr = tmp; </pre> Instead, you'd need to use something like: <pre> *my_IO = (struct my_IO_s) { .timer_interrupt = 1 }; </pre> which is not much better than the equivalent: <pre> *my_IO_addr = (1 &lt;&lt; TIMER_INTERRUPT_SHIFT); </pre> <li>Even for a more normal register like a GPIO port, it's quite difficult to set two bits simultaneously with a single write. You can't do: <pre> *my_IO_addr |= (1 &lt;&lt; PIN0_SHIFT) | (1 &lt;&lt; PIN1_SHIFT); </pre> without something like: <pre> struct my_IO_s tmp = *my_IO; tmp.pin0 = 1; tmp.pin1 = 1; *my_IO = tmp; </pre> </ul> Really it's one of the more annoying parts of C when doing embedded development on a constrained system, as it's hard to avoid without adding some layer of performance-killing indirection (like Arduino does). Sat, 19 Jan 2013 00:33:14 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533276/ https://lwn.net/Articles/533276/ jimparis <p>It sounds like your concern is accessing GPIOs from userspace, but I thought the primary intended consumer of this particular ABI was kernel drivers, and that accessing GPIOs via /sys was intended just for debugging, in lieu of a proper driver for the hardware you're playing with. <p>Then again, <a href="http://www.kernel.org/doc/Documentation/gpio.txt">Documentation/gpio.txt</a> does claim that "for some tasks, simple userspace GPIO drivers could be all that the system really needs", which at least suggests that it should be considered a production API. So complaints about API breakes are probably worth bringing up when they happen. Fri, 18 Jan 2013 23:58:31 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533187/ https://lwn.net/Articles/533187/ dougg <div class="FormattedComment"> To your second and third points, welcome to pinctrl introduced in lk 3.7 and 3.8 . And while you are at it, look at the device tree stuff (aka "open firmware" and hence lots of "of_" adorned names). gpio pin states can and should be set before the Linux kernel gets a look in (e.g. in uboot or earlier), and when it does the kernel should resist the temptation to set those lines to some arbitrary state.<br> <p> Things are moving so fast in the device tree/pinctrl area that it might be worth LWN writing another article on the subject. <br> </div> Fri, 18 Jan 2013 14:42:47 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533185/ https://lwn.net/Articles/533185/ kvaml <div class="FormattedComment"> Just in time to help with my new Raspberry Pi. Thanks.<br> </div> Fri, 18 Jan 2013 14:20:25 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533170/ https://lwn.net/Articles/533170/ etienne <div class="FormattedComment"> <font class="QuotedText">&gt; GPIO can be both output and input at the same time</font><br> <p> Reading back output GPIO is described in Documentation/gpio.txt<br> My main problem is that people (even software manager responsible of software "quality") do think it is clean to use the C preprocessor, either in C or C++.<br> That leads to massive amount of #define, to define the address, the value when active, the value when inactive, the shift position for each GPIO and the mask for that GPIO (you never know if the mask is shifted or not).<br> Then you have a set of GPIO to represent a 3 bit value, and the preprocessor will never tell you that you are trying to write 0x15 in this 3 bit value.<br> Also those quality specialists tell you to use the macro:<br> #define IOWRITE32BYTE(addr, val) *((volatile unsigned *)(addr)) = (val)<br> (Hint: try to write the same addr twice with a newer compiler).<br> Anyway on newer architecture, those are memory mapped and IHMO it is a lot cleaner to use C to declare them:<br> volatile struct my_IO_s {<br> #ifdef BIG_ENDIAN<br> enum { healthy, fail } power_state : 1;<br> unsigned power_active : 1;<br> #else<br> unsigned power_active : 1;<br> enum { healthy, fail } power_state : 1;<br> #endif<br> } * const my_IO = (volatile struct my_IO_s *)0xDC002000;<br> Instead of pages and pages of #define.<br> </div> Fri, 18 Jan 2013 11:50:06 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533160/ https://lwn.net/Articles/533160/ russell <div class="FormattedComment"> Everyone thinks GPIO is easy, and that probably explains why the interfaces are incomplete. GPIO usually has a lot more functionality than can be accessed.<br> <p> 1. GPIO can be both output and input at the same time. Yep you may want to read back the value of an output. MCUs I've used in the past offered this. After all output are really just stronger versions of the pull up/down :)<br> <p> 2. GPIO have pull up/down resistors.<br> <p> 3. And this is the BIG one. GPIO has state BEFORE the kernel boots. Bootstrap code can set the state of GPIO during the first few cycles of operation. This can eliminate the need for extra external hardware. However, the kernel blows this away and you have to wait for userspace to boot before you get control!!!! This behaviour on for example RPi required extra hardware to be added to the circuit to prevent this kind of transient boot behaviour from glitching relays.<br> </div> Fri, 18 Jan 2013 08:44:05 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533066/ https://lwn.net/Articles/533066/ zuki <div class="FormattedComment"> Frankly I don't see the point of such a stub of an article. It would be better to have all three instalments now, and nothing for two weeks, then to be teased like that.<br> <p> </div> Thu, 17 Jan 2013 21:08:34 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/533002/ https://lwn.net/Articles/533002/ dougg <div class="FormattedComment"> Here is a view from the trenches of the Linux gpio subsystem, seen from the Atmel AT91 family, specifically the AT91SAM9x5 sub-family.<br> <p> The biggest mistake was introduced initially: using a single sequence of kernel gpio numbers to represent a two level hierarchy. For example the AT91SAM9G20 has 3 banks: PA0-31, PB0-31 and PC0-31. For some crazy reason (something about not interfering with interrupt numbers) they mapped PA0 to 32 and the gpio numbers followed in sequence from there (hence PC31 is 127). Well sanity finally prevailed and around lk 3.5 they remapped PA0 to 0. Great, lots of user space code to rewrite.<br> <p> And in lk 3.8.0-rc1 they were at it again. A gpio pin that had a sysfs name of /sys/class/gpio/gpio32 suddenly became /sys/class/gpio/pioB0 . Well that's a better name but why not use /sys/class/gpio/pb0 so as to agree with Atmel's naming (apart from capitalisation)?? And more user space code needs to be rewritten.<br> <p> Back around lk 2.6.28 they removed a gpio pass-through driver leaving sysfs as (almost) the only way to get to gpios. I say almost because for serious work with AT91s mmap() is your friend. With luck in lk 3.9 we might get a well-designed block gpio driver so it will probably get vetoed or bowdlerized.<br> </div> Thu, 17 Jan 2013 18:12:03 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/532930/ https://lwn.net/Articles/532930/ corbet That's a little embarrassing...and I rechecked all those prototypes. Fixed, thanks. Thu, 17 Jan 2013 13:05:38 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/532920/ https://lwn.net/Articles/532920/ notti <div class="FormattedComment"> I think you missed the value in the gpio_set_value function<br> </div> Thu, 17 Jan 2013 11:25:53 +0000 GPIO in the kernel: an introduction https://lwn.net/Articles/532909/ https://lwn.net/Articles/532909/ linusw <div class="FormattedComment"> Fun that you're diggin into this Jon, I have just had a presentation for the ELC accepted where I try to give an overview of recent changes in GPIO and pinctrl.<br> </div> Thu, 17 Jan 2013 09:19:55 +0000