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