Skip site navigation (1)Skip section navigation (2)
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>