Date: Wed, 12 Jun 2013 23:36:04 -0400 From: Ryan Stone <rysto32@gmail.com> To: "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org> Subject: Exposing driver's GPIOs through gpiobus Message-ID: <CAFMmRNzch_ZBcd2e_cd=iXKzr3TsisWD-A%2Be0F2h7MkLXTynsw@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
At $WORK we have some custom boards with multi-port uarts managed by puc. The uart devices happen to provide some GPIOs, and our hardware designers have appropriated those GPIOs for various purposes entirely unrelated to the uart. I'm looking for a clean way to provide access to the GPIOs. It occurred to me that this was a problem that should be solved through newbus, and lo and behold I have discovered that FreeBSD provides a gpiobus driver that seems suitable. I've been playing around with this for a couple of days and I have a solutions that is working, but there are aspects that I am unhappy with. I also quite unfamiliar with newbus, so there easily could be better ways to approach the problem that I haven't thought of. What I ended up doing was making gpiobus and gpioc children of the puc bus. In puc_bfe_attach() I create two new child devices of the puc device with device_add_child(), one with the gpioc devclass and one with the gpiobus devclass. I then attach both children with device_probe_and_attach(). I make the puc_pci driver itself provide implementations of the various gpio methods (like gpio_pin_get) so they can be inherited by the child devices. Things start to get somewhat messy in the gpio client code. I have the same image running on many different hardware types, so I can't use device hints to create a child device of the gpiobus. Instead my kernel module tracks down the device_t for the puc, finds the gpiobus child, and uses BUS_ADD_CHILD to create a child of the gpiobus. I had to add a new gpiobus method to allocate GPIO pins to my driver instance. Once that's done, I can toggle GPIOs and whatnot using methods on my driver instance. The things that I'm most unhappy with (newbus-wise, anyway) are: 1) By default the gpioc and gpiobus drivers were claiming the uart children of the puc. I had to decrease their priority in bus_probe to BUS_PROBE_LOW_PRIORITY to work around the problem. I really don't think that was the right solution. I guess I could introduce a new device that is a child of the puc, make sure that it will not claim the uarts, and then make the gpioc and gpiobus children of this device. 2) I'm not sure how to clean up my child device when my module is unloaded. Currently I am checking if it already exists on load and reusing it if so. I may be missing something obvious here. 3) I really don't like the way that I am adding my child to gpiobus. Upon writing this it occurs to me that device_identify would be the canonical way to do this. Previously it wasn't clear to me how to fit device_identify into the current architecture of the gpio client but I see how it can be done now.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFMmRNzch_ZBcd2e_cd=iXKzr3TsisWD-A%2Be0F2h7MkLXTynsw>