Date: Thu, 27 Jun 2013 13:49:32 -0400 From: John Baldwin <jhb@freebsd.org> To: freebsd-hackers@freebsd.org Cc: Ryan Stone <rysto32@gmail.com> Subject: Re: Exposing driver's GPIOs through gpiobus Message-ID: <201306271349.32203.jhb@freebsd.org> In-Reply-To: <CAFMmRNzch_ZBcd2e_cd=iXKzr3TsisWD-A%2Be0F2h7MkLXTynsw@mail.gmail.com> References: <CAFMmRNzch_ZBcd2e_cd=iXKzr3TsisWD-A%2Be0F2h7MkLXTynsw@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday, June 12, 2013 11:36:04 pm Ryan Stone wrote: > 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. Just leave the device around and reuse it. In your identify routine do something like this: static void agp_i810_identify(driver_t *driver, device_t parent) { if (device_find_child(parent, "agp", -1) == NULL && agp_i810_match(parent)) device_add_child(parent, "agp", -1); } > > 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. Yes, device_identify is what you want. I think it will also solve problem 1 for you as well. -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306271349.32203.jhb>