gpioc.c revision 226500
164439Scg/*- 264439Scg * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org> 364439Scg * All rights reserved. 464439Scg * 564439Scg * Redistribution and use in source and binary forms, with or without 664439Scg * modification, are permitted provided that the following conditions 764439Scg * are met: 864439Scg * 1. Redistributions of source code must retain the above copyright 964439Scg * notice, this list of conditions and the following disclaimer. 1064439Scg * 2. Redistributions in binary form must reproduce the above copyright 1164439Scg * notice, this list of conditions and the following disclaimer in the 1264439Scg * documentation and/or other materials provided with the distribution. 1364439Scg * 1464439Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1564439Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1664439Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1764439Scg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1864439Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1964439Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2064439Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2164439Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2264439Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2364439Scg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2464439Scg * SUCH DAMAGE. 2564439Scg */ 2664439Scg 2764439Scg#include <sys/cdefs.h> 2864439Scg__FBSDID("$FreeBSD: head/sys/dev/gpio/gpioc.c 226500 2011-10-18 08:09:44Z ed $"); 2964439Scg 3064439Scg#include <sys/param.h> 3164439Scg#include <sys/systm.h> 3264439Scg#include <sys/types.h> 3364439Scg 3464439Scg#include <sys/bus.h> 3564439Scg#include <sys/conf.h> 3664439Scg#include <sys/ioccom.h> 3764439Scg#include <sys/kernel.h> 3864439Scg#include <sys/malloc.h> 3964439Scg#include <sys/module.h> 4064439Scg#include <sys/queue.h> 4164439Scg#include <machine/bus.h> 4264439Scg#include <machine/resource.h> 4364439Scg 4464439Scg#include <sys/gpio.h> 45111898Sorion#include "gpio_if.h" 46111898Sorion 47112669Sorion#undef GPIOC_DEBUG 48112669Sorion#ifdef GPIOC_DEBUG 49112669Sorion#define dprintf printf 50111898Sorion#else 51111898Sorion#define dprintf(x, arg...) 52111898Sorion#endif 53111898Sorion 54111898Sorionstatic int gpioc_probe(device_t dev); 55111898Sorionstatic int gpioc_attach(device_t dev); 56111898Sorionstatic int gpioc_detach(device_t dev); 57111898Sorion 58111898Sorionstatic d_ioctl_t gpioc_ioctl; 5964439Scg 6064439Scgstatic struct cdevsw gpioc_cdevsw = { 61102010Sorion .d_version = D_VERSION, 62102010Sorion .d_ioctl = gpioc_ioctl, 6364439Scg .d_name = "gpioc", 64102010Sorion}; 65102010Sorion 6664439Scgstruct gpioc_softc { 6764439Scg device_t sc_dev; /* gpiocX dev */ 68102010Sorion device_t sc_pdev; /* gpioX dev */ 69102010Sorion struct cdev *sc_ctl_dev; /* controller device */ 7064439Scg int sc_unit; 7164439Scg}; 7264439Scg 7364439Scgstatic int 7464439Scggpioc_probe(device_t dev) 75102010Sorion{ 76102010Sorion device_set_desc(dev, "GPIO controller"); 77102010Sorion return (0); 78102010Sorion} 7964439Scg 80102010Sorionstatic int 8164439Scggpioc_attach(device_t dev) 8264439Scg{ 8364439Scg struct gpioc_softc *sc = device_get_softc(dev); 8464439Scg 8564439Scg sc->sc_dev = dev; 8664439Scg sc->sc_pdev = device_get_parent(dev); 87 sc->sc_unit = device_get_unit(dev); 88 sc->sc_ctl_dev = make_dev(&gpioc_cdevsw, sc->sc_unit, 89 UID_ROOT, GID_WHEEL, 0600, "gpioc%d", sc->sc_unit); 90 if (!sc->sc_ctl_dev) { 91 printf("Failed to create gpioc%d", sc->sc_unit); 92 return (ENXIO); 93 } 94 sc->sc_ctl_dev->si_drv1 = sc; 95 96 return (0); 97} 98 99static int 100gpioc_detach(device_t dev) 101{ 102 struct gpioc_softc *sc = device_get_softc(dev); 103 int err; 104 105 if (sc->sc_ctl_dev); 106 destroy_dev(sc->sc_ctl_dev); 107 108 if ((err = bus_generic_detach(dev)) != 0) 109 return (err); 110 111 return (0); 112} 113 114static int 115gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, 116 struct thread *td) 117{ 118 int max_pin, res; 119 struct gpioc_softc *sc = cdev->si_drv1; 120 struct gpio_pin pin; 121 struct gpio_req req; 122 123 switch (cmd) { 124 case GPIOMAXPIN: 125 max_pin = -1; 126 res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin); 127 bcopy(&max_pin, arg, sizeof(max_pin)); 128 break; 129 case GPIOGETCONFIG: 130 bcopy(arg, &pin, sizeof(pin)); 131 dprintf("get config pin %d\n", pin.gp_pin); 132 res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin, 133 &pin.gp_flags); 134 /* Fail early */ 135 if (res) 136 break; 137 GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps); 138 GPIO_PIN_GETNAME(sc->sc_pdev, pin.gp_pin, pin.gp_name); 139 bcopy(&pin, arg, sizeof(pin)); 140 break; 141 case GPIOSETCONFIG: 142 bcopy(arg, &pin, sizeof(pin)); 143 dprintf("set config pin %d\n", pin.gp_pin); 144 res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin, 145 pin.gp_flags); 146 break; 147 case GPIOGET: 148 bcopy(arg, &req, sizeof(req)); 149 res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin, 150 &req.gp_value); 151 dprintf("read pin %d -> %d\n", 152 req.gp_pin, req.gp_value); 153 bcopy(&req, arg, sizeof(req)); 154 break; 155 case GPIOSET: 156 bcopy(arg, &req, sizeof(req)); 157 res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin, 158 req.gp_value); 159 dprintf("write pin %d -> %d\n", 160 req.gp_pin, req.gp_value); 161 break; 162 case GPIOTOGGLE: 163 bcopy(arg, &req, sizeof(req)); 164 dprintf("toggle pin %d\n", 165 req.gp_pin); 166 res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin); 167 break; 168 default: 169 return (ENOTTY); 170 break; 171 } 172 173 return (res); 174} 175 176static device_method_t gpioc_methods[] = { 177 /* Device interface */ 178 DEVMETHOD(device_probe, gpioc_probe), 179 DEVMETHOD(device_attach, gpioc_attach), 180 DEVMETHOD(device_detach, gpioc_detach), 181 DEVMETHOD(device_shutdown, bus_generic_shutdown), 182 DEVMETHOD(device_suspend, bus_generic_suspend), 183 DEVMETHOD(device_resume, bus_generic_resume), 184 185 { 0, 0 } 186}; 187 188driver_t gpioc_driver = { 189 "gpioc", 190 gpioc_methods, 191 sizeof(struct gpioc_softc) 192}; 193 194devclass_t gpioc_devclass; 195 196DRIVER_MODULE(gpioc, gpio, gpioc_driver, gpioc_devclass, 0, 0); 197MODULE_VERSION(gpioc, 1); 198