gpioc.c revision 213237
1213237Sgonzo#include <sys/cdefs.h> 2213237Sgonzo__FBSDID("$FreeBSD: head/sys/dev/gpio/gpioc.c 213237 2010-09-28 03:24:53Z gonzo $"); 3213237Sgonzo 4213237Sgonzo#include <sys/param.h> 5213237Sgonzo#include <sys/systm.h> 6213237Sgonzo#include <sys/types.h> 7213237Sgonzo 8213237Sgonzo#include <sys/bus.h> 9213237Sgonzo#include <sys/conf.h> 10213237Sgonzo#include <sys/ioccom.h> 11213237Sgonzo#include <sys/kernel.h> 12213237Sgonzo#include <sys/malloc.h> 13213237Sgonzo#include <sys/module.h> 14213237Sgonzo#include <sys/queue.h> 15213237Sgonzo#include <machine/bus.h> 16213237Sgonzo#include <machine/resource.h> 17213237Sgonzo 18213237Sgonzo#include <sys/gpio.h> 19213237Sgonzo#include "gpio_if.h" 20213237Sgonzo 21213237Sgonzo#undef GPIOC_DEBUG 22213237Sgonzo#ifdef GPIOC_DEBUG 23213237Sgonzo#define dprintf printf 24213237Sgonzo#else 25213237Sgonzo#define dprintf(x, arg...) 26213237Sgonzo#endif 27213237Sgonzo 28213237Sgonzostatic int gpioc_probe(device_t dev); 29213237Sgonzostatic int gpioc_attach(device_t dev); 30213237Sgonzostatic int gpioc_detach(device_t dev); 31213237Sgonzo 32213237Sgonzostatic d_ioctl_t gpioc_ioctl; 33213237Sgonzo 34213237Sgonzostatic struct cdevsw gpioc_cdevsw = { 35213237Sgonzo .d_version = D_VERSION, 36213237Sgonzo .d_ioctl = gpioc_ioctl, 37213237Sgonzo .d_name = "gpioc", 38213237Sgonzo#if __FreeBSD_version >= 800039 39213237Sgonzo .d_flags = D_PSEUDO | D_NEEDMINOR 40213237Sgonzo#endif 41213237Sgonzo}; 42213237Sgonzo 43213237Sgonzostruct gpioc_softc { 44213237Sgonzo device_t sc_dev; /* gpiocX dev */ 45213237Sgonzo device_t sc_pdev; /* gpioX dev */ 46213237Sgonzo struct cdev *sc_ctl_dev; /* controller device */ 47213237Sgonzo int sc_unit; 48213237Sgonzo}; 49213237Sgonzo 50213237Sgonzostatic int 51213237Sgonzogpioc_probe(device_t dev) 52213237Sgonzo{ 53213237Sgonzo device_set_desc(dev, "GPIO controller"); 54213237Sgonzo return (0); 55213237Sgonzo} 56213237Sgonzo 57213237Sgonzostatic int 58213237Sgonzogpioc_attach(device_t dev) 59213237Sgonzo{ 60213237Sgonzo struct gpioc_softc *sc = device_get_softc(dev); 61213237Sgonzo 62213237Sgonzo sc->sc_dev = dev; 63213237Sgonzo sc->sc_pdev = device_get_parent(dev); 64213237Sgonzo sc->sc_unit = device_get_unit(dev); 65213237Sgonzo sc->sc_ctl_dev = make_dev(&gpioc_cdevsw, sc->sc_unit, 66213237Sgonzo UID_ROOT, GID_WHEEL, 0600, "gpioc%d", sc->sc_unit); 67213237Sgonzo if (!sc->sc_ctl_dev) { 68213237Sgonzo printf("Failed to create gpioc%d", sc->sc_unit); 69213237Sgonzo return (ENXIO); 70213237Sgonzo } 71213237Sgonzo sc->sc_ctl_dev->si_drv1 = sc; 72213237Sgonzo 73213237Sgonzo return (0); 74213237Sgonzo} 75213237Sgonzo 76213237Sgonzostatic int 77213237Sgonzogpioc_detach(device_t dev) 78213237Sgonzo{ 79213237Sgonzo struct gpioc_softc *sc = device_get_softc(dev); 80213237Sgonzo int err; 81213237Sgonzo 82213237Sgonzo if (sc->sc_ctl_dev); 83213237Sgonzo destroy_dev(sc->sc_ctl_dev); 84213237Sgonzo 85213237Sgonzo if ((err = bus_generic_detach(dev)) != 0) 86213237Sgonzo return (err); 87213237Sgonzo 88213237Sgonzo return (0); 89213237Sgonzo} 90213237Sgonzo 91213237Sgonzostatic int 92213237Sgonzogpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, 93213237Sgonzo struct thread *td) 94213237Sgonzo{ 95213237Sgonzo int max_pin, res; 96213237Sgonzo struct gpioc_softc *sc = cdev->si_drv1; 97213237Sgonzo struct gpio_pin pin; 98213237Sgonzo struct gpio_req req; 99213237Sgonzo 100213237Sgonzo switch (cmd) { 101213237Sgonzo case GPIOMAXPIN: 102213237Sgonzo max_pin = -1; 103213237Sgonzo res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin); 104213237Sgonzo bcopy(&max_pin, arg, sizeof(max_pin)); 105213237Sgonzo break; 106213237Sgonzo case GPIOGETCONFIG: 107213237Sgonzo bcopy(arg, &pin, sizeof(pin)); 108213237Sgonzo dprintf("get config pin %d\n", pin.gp_pin); 109213237Sgonzo res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin, 110213237Sgonzo &pin.gp_flags); 111213237Sgonzo /* Fail early */ 112213237Sgonzo if (res) 113213237Sgonzo break; 114213237Sgonzo GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps); 115213237Sgonzo GPIO_PIN_GETNAME(sc->sc_pdev, pin.gp_pin, pin.gp_name); 116213237Sgonzo bcopy(&pin, arg, sizeof(pin)); 117213237Sgonzo break; 118213237Sgonzo case GPIOSETCONFIG: 119213237Sgonzo bcopy(arg, &pin, sizeof(pin)); 120213237Sgonzo dprintf("set config pin %d\n", pin.gp_pin); 121213237Sgonzo res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin, 122213237Sgonzo pin.gp_flags); 123213237Sgonzo break; 124213237Sgonzo case GPIOGET: 125213237Sgonzo bcopy(arg, &req, sizeof(req)); 126213237Sgonzo res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin, 127213237Sgonzo &req.gp_value); 128213237Sgonzo dprintf("read pin %d -> %d\n", 129213237Sgonzo req.gp_pin, req.gp_value); 130213237Sgonzo bcopy(&req, arg, sizeof(req)); 131213237Sgonzo break; 132213237Sgonzo case GPIOSET: 133213237Sgonzo bcopy(arg, &req, sizeof(req)); 134213237Sgonzo res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin, 135213237Sgonzo req.gp_value); 136213237Sgonzo dprintf("write pin %d -> %d\n", 137213237Sgonzo req.gp_pin, req.gp_value); 138213237Sgonzo break; 139213237Sgonzo case GPIOTOGGLE: 140213237Sgonzo bcopy(arg, &req, sizeof(req)); 141213237Sgonzo dprintf("toggle pin %d\n", 142213237Sgonzo req.gp_pin); 143213237Sgonzo res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin); 144213237Sgonzo break; 145213237Sgonzo default: 146213237Sgonzo return (ENOTTY); 147213237Sgonzo break; 148213237Sgonzo } 149213237Sgonzo 150213237Sgonzo return (res); 151213237Sgonzo} 152213237Sgonzo 153213237Sgonzostatic device_method_t gpioc_methods[] = { 154213237Sgonzo /* Device interface */ 155213237Sgonzo DEVMETHOD(device_probe, gpioc_probe), 156213237Sgonzo DEVMETHOD(device_attach, gpioc_attach), 157213237Sgonzo DEVMETHOD(device_detach, gpioc_detach), 158213237Sgonzo DEVMETHOD(device_shutdown, bus_generic_shutdown), 159213237Sgonzo DEVMETHOD(device_suspend, bus_generic_suspend), 160213237Sgonzo DEVMETHOD(device_resume, bus_generic_resume), 161213237Sgonzo 162213237Sgonzo { 0, 0 } 163213237Sgonzo}; 164213237Sgonzo 165213237Sgonzostatic driver_t gpioc_driver = { 166213237Sgonzo "gpioc", 167213237Sgonzo gpioc_methods, 168213237Sgonzo sizeof(struct gpioc_softc) 169213237Sgonzo}; 170213237Sgonzo 171213237Sgonzodevclass_t gpioc_devclass; 172213237Sgonzo 173213237SgonzoDRIVER_MODULE(gpioc, gpio, gpioc_driver, gpioc_devclass, 0, 0); 174213237SgonzoMODULE_VERSION(gpioc, 1); 175