Kernel DRIVER_MODULE that can toggle gpio pin on /dev/gpioc2

Hi Everyone,

Just wondering if anyone could please help me with programming GPIO pins from within a Kernel driver module? I thought was going to be a trivial but can't yet figure this out and I don't really want to use FDT for this as I think that would be total overkill for the exercise.

I am trying to write a Kernel DRIVER_MODULE that will control both, GPIO pins and I2C devices - what I am trying to do is figure out how to do this (below) but inside the foo_attach() function :-

(this is an example from userspace) :-
#include <libgpio.h>

handle = gpio_open(2); // open gpiobus2 - ie: /dev/gpioc2
gpio_pin_output(handle, 23); // set GPIO pin 23 as output
gpio_pin_low(handle, 23); // set GPIO pin 23 as low
gpio_close(handle); // close


Given I'm not using FDT and this is a ko module that I'm loading dynamically using kldload, I have found that I must implement the foo_identify() function and have it declared as a DEVMETHOD(device_identify, foo_identify) otherwise, it seems to never want to call foo_probe() ... ??

I declare the module as follows -

// Define the driver module
static device_method_t foo_methods[] = {
DEVMETHOD(device_identify, foo_identify),
DEVMETHOD(device_probe, foo_probe),
DEVMETHOD(device_attach, foo_attach),
DEVMETHOD(device_detach, foo_detach),
DEVMETHOD_END
};

DEFINE_CLASS_0(foo, foo_driver, foo_methods, sizeof(struct foo_softc));

// Declare the driver module
DRIVER_MODULE(foo, gpiobus, foo_driver, 0, 0);
MODULE_DEPEND(foo, gpiobus, 1, 1, 1);
MODULE_VERSION(foo, 1);


On the hardware I am using it has 4 x GPIO busses and foo_identify() gets called four (4) times - ie: for gpiobus0, gpiobus1, gpiobus2, gpiobus3 - the GPIO pin I am wanting to toggle/control is PIN 23 on gpiobus2.

In foo_identify(driver_t *driver, device_t parent), I try the following :-

dev = BUS_ADD_CHILD(parent, 0, "foo", -1);
int unit = device_get_unit(dev);
if (unit == 2)
{
gpio_pin_t pin;

int err = gpio_pin_get_by_child_index(dev, 23, &pin);
.
.
int value; // never gets to here because err == EBUSY
GPIO_PIN_GET(dev, 23, &value);
}


Do I need to disable the 'gpioc' driver first to free up all four (4) /dev/gpiocN devices in order to be able to do this sort of thing? Is there a better way I should be going about doing this?

Thanks very much!
Cheers,
Rod
 
Back
Top