1*b2f0caf1SEmmanuel Vadot /*- 2*b2f0caf1SEmmanuel Vadot * Copyright 2016 Michal Meloun <mmel@FreeBSD.org> 3*b2f0caf1SEmmanuel Vadot * All rights reserved. 4*b2f0caf1SEmmanuel Vadot * 5*b2f0caf1SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 6*b2f0caf1SEmmanuel Vadot * modification, are permitted provided that the following conditions 7*b2f0caf1SEmmanuel Vadot * are met: 8*b2f0caf1SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 9*b2f0caf1SEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 10*b2f0caf1SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 11*b2f0caf1SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 12*b2f0caf1SEmmanuel Vadot * documentation and/or other materials provided with the distribution. 13*b2f0caf1SEmmanuel Vadot * 14*b2f0caf1SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*b2f0caf1SEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*b2f0caf1SEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*b2f0caf1SEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*b2f0caf1SEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*b2f0caf1SEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*b2f0caf1SEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*b2f0caf1SEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*b2f0caf1SEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*b2f0caf1SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*b2f0caf1SEmmanuel Vadot * SUCH DAMAGE. 25*b2f0caf1SEmmanuel Vadot */ 26*b2f0caf1SEmmanuel Vadot 27*b2f0caf1SEmmanuel Vadot #include <sys/cdefs.h> 28*b2f0caf1SEmmanuel Vadot #include "opt_platform.h" 29*b2f0caf1SEmmanuel Vadot #include <sys/param.h> 30*b2f0caf1SEmmanuel Vadot #include <sys/systm.h> 31*b2f0caf1SEmmanuel Vadot #include <sys/bus.h> 32*b2f0caf1SEmmanuel Vadot #include <sys/conf.h> 33*b2f0caf1SEmmanuel Vadot #include <sys/gpio.h> 34*b2f0caf1SEmmanuel Vadot #include <sys/kernel.h> 35*b2f0caf1SEmmanuel Vadot #include <sys/kobj.h> 36*b2f0caf1SEmmanuel Vadot #include <sys/module.h> 37*b2f0caf1SEmmanuel Vadot #include <sys/mutex.h> 38*b2f0caf1SEmmanuel Vadot 39*b2f0caf1SEmmanuel Vadot #ifdef FDT 40*b2f0caf1SEmmanuel Vadot #include <dev/fdt/fdt_common.h> 41*b2f0caf1SEmmanuel Vadot #include <dev/ofw/ofw_bus.h> 42*b2f0caf1SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h> 43*b2f0caf1SEmmanuel Vadot #endif 44*b2f0caf1SEmmanuel Vadot #include <dev/gpio/gpiobusvar.h> 45*b2f0caf1SEmmanuel Vadot #include <dev/regulator/regulator_fixed.h> 46*b2f0caf1SEmmanuel Vadot 47*b2f0caf1SEmmanuel Vadot #ifdef FDT 48*b2f0caf1SEmmanuel Vadot #include "regdev_if.h" 49*b2f0caf1SEmmanuel Vadot #endif 50*b2f0caf1SEmmanuel Vadot 51*b2f0caf1SEmmanuel Vadot MALLOC_DEFINE(M_FIXEDREGULATOR, "fixedregulator", "Fixed regulator"); 52*b2f0caf1SEmmanuel Vadot 53*b2f0caf1SEmmanuel Vadot /* GPIO list for shared pins. */ 54*b2f0caf1SEmmanuel Vadot typedef TAILQ_HEAD(gpio_list, gpio_entry) gpio_list_t; 55*b2f0caf1SEmmanuel Vadot struct gpio_entry { 56*b2f0caf1SEmmanuel Vadot TAILQ_ENTRY(gpio_entry) link; 57*b2f0caf1SEmmanuel Vadot struct gpiobus_pin gpio_pin; 58*b2f0caf1SEmmanuel Vadot int use_cnt; 59*b2f0caf1SEmmanuel Vadot int enable_cnt; 60*b2f0caf1SEmmanuel Vadot bool always_on; 61*b2f0caf1SEmmanuel Vadot }; 62*b2f0caf1SEmmanuel Vadot static gpio_list_t gpio_list = TAILQ_HEAD_INITIALIZER(gpio_list); 63*b2f0caf1SEmmanuel Vadot static struct mtx gpio_list_mtx; 64*b2f0caf1SEmmanuel Vadot MTX_SYSINIT(gpio_list_lock, &gpio_list_mtx, "Regulator GPIO lock", MTX_DEF); 65*b2f0caf1SEmmanuel Vadot 66*b2f0caf1SEmmanuel Vadot struct regnode_fixed_sc { 67*b2f0caf1SEmmanuel Vadot struct regnode_std_param *param; 68*b2f0caf1SEmmanuel Vadot bool gpio_open_drain; 69*b2f0caf1SEmmanuel Vadot struct gpio_entry *gpio_entry; 70*b2f0caf1SEmmanuel Vadot }; 71*b2f0caf1SEmmanuel Vadot 72*b2f0caf1SEmmanuel Vadot static int regnode_fixed_init(struct regnode *regnode); 73*b2f0caf1SEmmanuel Vadot static int regnode_fixed_enable(struct regnode *regnode, bool enable, 74*b2f0caf1SEmmanuel Vadot int *udelay); 75*b2f0caf1SEmmanuel Vadot static int regnode_fixed_status(struct regnode *regnode, int *status); 76*b2f0caf1SEmmanuel Vadot static int regnode_fixed_stop(struct regnode *regnode, int *udelay); 77*b2f0caf1SEmmanuel Vadot static int regnode_fixed_get_voltage(struct regnode *regnode, int *uvolt); 78*b2f0caf1SEmmanuel Vadot 79*b2f0caf1SEmmanuel Vadot static regnode_method_t regnode_fixed_methods[] = { 80*b2f0caf1SEmmanuel Vadot /* Regulator interface */ 81*b2f0caf1SEmmanuel Vadot REGNODEMETHOD(regnode_init, regnode_fixed_init), 82*b2f0caf1SEmmanuel Vadot REGNODEMETHOD(regnode_enable, regnode_fixed_enable), 83*b2f0caf1SEmmanuel Vadot REGNODEMETHOD(regnode_status, regnode_fixed_status), 84*b2f0caf1SEmmanuel Vadot REGNODEMETHOD(regnode_stop, regnode_fixed_stop), 85*b2f0caf1SEmmanuel Vadot REGNODEMETHOD(regnode_get_voltage, regnode_fixed_get_voltage), 86*b2f0caf1SEmmanuel Vadot REGNODEMETHOD(regnode_check_voltage, regnode_method_check_voltage), 87*b2f0caf1SEmmanuel Vadot REGNODEMETHOD_END 88*b2f0caf1SEmmanuel Vadot }; 89*b2f0caf1SEmmanuel Vadot DEFINE_CLASS_1(regnode_fixed, regnode_fixed_class, regnode_fixed_methods, 90*b2f0caf1SEmmanuel Vadot sizeof(struct regnode_fixed_sc), regnode_class); 91*b2f0caf1SEmmanuel Vadot 92*b2f0caf1SEmmanuel Vadot /* 93*b2f0caf1SEmmanuel Vadot * GPIO list functions. 94*b2f0caf1SEmmanuel Vadot * Two or more regulators can share single GPIO pins, so we must track all 95*b2f0caf1SEmmanuel Vadot * GPIOs in gpio_list. 96*b2f0caf1SEmmanuel Vadot * The GPIO pin is registerd and reseved for first consumer, all others share 97*b2f0caf1SEmmanuel Vadot * gpio_entry with it. 98*b2f0caf1SEmmanuel Vadot */ 99*b2f0caf1SEmmanuel Vadot static struct gpio_entry * 100*b2f0caf1SEmmanuel Vadot regnode_get_gpio_entry(struct gpiobus_pin *gpio_pin) 101*b2f0caf1SEmmanuel Vadot { 102*b2f0caf1SEmmanuel Vadot struct gpio_entry *entry, *tmp; 103*b2f0caf1SEmmanuel Vadot device_t busdev; 104*b2f0caf1SEmmanuel Vadot int rv; 105*b2f0caf1SEmmanuel Vadot 106*b2f0caf1SEmmanuel Vadot busdev = GPIO_GET_BUS(gpio_pin->dev); 107*b2f0caf1SEmmanuel Vadot if (busdev == NULL) 108*b2f0caf1SEmmanuel Vadot return (NULL); 109*b2f0caf1SEmmanuel Vadot entry = malloc(sizeof(struct gpio_entry), M_FIXEDREGULATOR, 110*b2f0caf1SEmmanuel Vadot M_WAITOK | M_ZERO); 111*b2f0caf1SEmmanuel Vadot 112*b2f0caf1SEmmanuel Vadot mtx_lock(&gpio_list_mtx); 113*b2f0caf1SEmmanuel Vadot 114*b2f0caf1SEmmanuel Vadot TAILQ_FOREACH(tmp, &gpio_list, link) { 115*b2f0caf1SEmmanuel Vadot if (tmp->gpio_pin.dev == gpio_pin->dev && 116*b2f0caf1SEmmanuel Vadot tmp->gpio_pin.pin == gpio_pin->pin) { 117*b2f0caf1SEmmanuel Vadot tmp->use_cnt++; 118*b2f0caf1SEmmanuel Vadot mtx_unlock(&gpio_list_mtx); 119*b2f0caf1SEmmanuel Vadot free(entry, M_FIXEDREGULATOR); 120*b2f0caf1SEmmanuel Vadot return (tmp); 121*b2f0caf1SEmmanuel Vadot } 122*b2f0caf1SEmmanuel Vadot } 123*b2f0caf1SEmmanuel Vadot 124*b2f0caf1SEmmanuel Vadot /* Reserve pin. */ 125*b2f0caf1SEmmanuel Vadot /* XXX Can we call gpiobus_acquire_pin() with gpio_list_mtx held? */ 126*b2f0caf1SEmmanuel Vadot rv = gpiobus_acquire_pin(busdev, gpio_pin->pin); 127*b2f0caf1SEmmanuel Vadot if (rv != 0) { 128*b2f0caf1SEmmanuel Vadot mtx_unlock(&gpio_list_mtx); 129*b2f0caf1SEmmanuel Vadot free(entry, M_FIXEDREGULATOR); 130*b2f0caf1SEmmanuel Vadot return (NULL); 131*b2f0caf1SEmmanuel Vadot } 132*b2f0caf1SEmmanuel Vadot /* Everything is OK, build new entry and insert it to list. */ 133*b2f0caf1SEmmanuel Vadot entry->gpio_pin = *gpio_pin; 134*b2f0caf1SEmmanuel Vadot entry->use_cnt = 1; 135*b2f0caf1SEmmanuel Vadot TAILQ_INSERT_TAIL(&gpio_list, entry, link); 136*b2f0caf1SEmmanuel Vadot 137*b2f0caf1SEmmanuel Vadot mtx_unlock(&gpio_list_mtx); 138*b2f0caf1SEmmanuel Vadot return (entry); 139*b2f0caf1SEmmanuel Vadot } 140*b2f0caf1SEmmanuel Vadot 141*b2f0caf1SEmmanuel Vadot 142*b2f0caf1SEmmanuel Vadot /* 143*b2f0caf1SEmmanuel Vadot * Regulator class implementation. 144*b2f0caf1SEmmanuel Vadot */ 145*b2f0caf1SEmmanuel Vadot static int 146*b2f0caf1SEmmanuel Vadot regnode_fixed_init(struct regnode *regnode) 147*b2f0caf1SEmmanuel Vadot { 148*b2f0caf1SEmmanuel Vadot device_t dev; 149*b2f0caf1SEmmanuel Vadot struct regnode_fixed_sc *sc; 150*b2f0caf1SEmmanuel Vadot struct gpiobus_pin *pin; 151*b2f0caf1SEmmanuel Vadot uint32_t flags; 152*b2f0caf1SEmmanuel Vadot int rv; 153*b2f0caf1SEmmanuel Vadot 154*b2f0caf1SEmmanuel Vadot sc = regnode_get_softc(regnode); 155*b2f0caf1SEmmanuel Vadot dev = regnode_get_device(regnode); 156*b2f0caf1SEmmanuel Vadot sc->param = regnode_get_stdparam(regnode); 157*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry == NULL) 158*b2f0caf1SEmmanuel Vadot return (0); 159*b2f0caf1SEmmanuel Vadot pin = &sc->gpio_entry->gpio_pin; 160*b2f0caf1SEmmanuel Vadot 161*b2f0caf1SEmmanuel Vadot flags = GPIO_PIN_OUTPUT; 162*b2f0caf1SEmmanuel Vadot if (sc->gpio_open_drain) 163*b2f0caf1SEmmanuel Vadot flags |= GPIO_PIN_OPENDRAIN; 164*b2f0caf1SEmmanuel Vadot if (sc->param->boot_on || sc->param->always_on) { 165*b2f0caf1SEmmanuel Vadot rv = GPIO_PIN_SET(pin->dev, pin->pin, sc->param->enable_active_high); 166*b2f0caf1SEmmanuel Vadot if (rv != 0) { 167*b2f0caf1SEmmanuel Vadot device_printf(dev, "Cannot set GPIO pin: %d\n", 168*b2f0caf1SEmmanuel Vadot pin->pin); 169*b2f0caf1SEmmanuel Vadot return (rv); 170*b2f0caf1SEmmanuel Vadot } 171*b2f0caf1SEmmanuel Vadot } 172*b2f0caf1SEmmanuel Vadot 173*b2f0caf1SEmmanuel Vadot rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags); 174*b2f0caf1SEmmanuel Vadot if (rv != 0) { 175*b2f0caf1SEmmanuel Vadot device_printf(dev, "Cannot configure GPIO pin: %d\n", pin->pin); 176*b2f0caf1SEmmanuel Vadot return (rv); 177*b2f0caf1SEmmanuel Vadot } 178*b2f0caf1SEmmanuel Vadot 179*b2f0caf1SEmmanuel Vadot return (0); 180*b2f0caf1SEmmanuel Vadot } 181*b2f0caf1SEmmanuel Vadot 182*b2f0caf1SEmmanuel Vadot /* 183*b2f0caf1SEmmanuel Vadot * Enable/disable regulator. 184*b2f0caf1SEmmanuel Vadot * Take shared GPIO pins in account 185*b2f0caf1SEmmanuel Vadot */ 186*b2f0caf1SEmmanuel Vadot static int 187*b2f0caf1SEmmanuel Vadot regnode_fixed_enable(struct regnode *regnode, bool enable, int *udelay) 188*b2f0caf1SEmmanuel Vadot { 189*b2f0caf1SEmmanuel Vadot device_t dev; 190*b2f0caf1SEmmanuel Vadot struct regnode_fixed_sc *sc; 191*b2f0caf1SEmmanuel Vadot struct gpiobus_pin *pin; 192*b2f0caf1SEmmanuel Vadot int rv; 193*b2f0caf1SEmmanuel Vadot 194*b2f0caf1SEmmanuel Vadot sc = regnode_get_softc(regnode); 195*b2f0caf1SEmmanuel Vadot dev = regnode_get_device(regnode); 196*b2f0caf1SEmmanuel Vadot 197*b2f0caf1SEmmanuel Vadot *udelay = 0; 198*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry == NULL) 199*b2f0caf1SEmmanuel Vadot return (0); 200*b2f0caf1SEmmanuel Vadot pin = &sc->gpio_entry->gpio_pin; 201*b2f0caf1SEmmanuel Vadot if (enable) { 202*b2f0caf1SEmmanuel Vadot sc->gpio_entry->enable_cnt++; 203*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry->enable_cnt > 1) 204*b2f0caf1SEmmanuel Vadot return (0); 205*b2f0caf1SEmmanuel Vadot } else { 206*b2f0caf1SEmmanuel Vadot KASSERT(sc->gpio_entry->enable_cnt > 0, 207*b2f0caf1SEmmanuel Vadot ("Invalid enable count")); 208*b2f0caf1SEmmanuel Vadot sc->gpio_entry->enable_cnt--; 209*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry->enable_cnt >= 1) 210*b2f0caf1SEmmanuel Vadot return (0); 211*b2f0caf1SEmmanuel Vadot } 212*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry->always_on && !enable) 213*b2f0caf1SEmmanuel Vadot return (0); 214*b2f0caf1SEmmanuel Vadot if (!sc->param->enable_active_high) 215*b2f0caf1SEmmanuel Vadot enable = !enable; 216*b2f0caf1SEmmanuel Vadot rv = GPIO_PIN_SET(pin->dev, pin->pin, enable); 217*b2f0caf1SEmmanuel Vadot if (rv != 0) { 218*b2f0caf1SEmmanuel Vadot device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin); 219*b2f0caf1SEmmanuel Vadot return (rv); 220*b2f0caf1SEmmanuel Vadot } 221*b2f0caf1SEmmanuel Vadot *udelay = sc->param->enable_delay; 222*b2f0caf1SEmmanuel Vadot return (0); 223*b2f0caf1SEmmanuel Vadot } 224*b2f0caf1SEmmanuel Vadot 225*b2f0caf1SEmmanuel Vadot /* 226*b2f0caf1SEmmanuel Vadot * Stop (physicaly shutdown) regulator. 227*b2f0caf1SEmmanuel Vadot * Take shared GPIO pins in account 228*b2f0caf1SEmmanuel Vadot */ 229*b2f0caf1SEmmanuel Vadot static int 230*b2f0caf1SEmmanuel Vadot regnode_fixed_stop(struct regnode *regnode, int *udelay) 231*b2f0caf1SEmmanuel Vadot { 232*b2f0caf1SEmmanuel Vadot device_t dev; 233*b2f0caf1SEmmanuel Vadot struct regnode_fixed_sc *sc; 234*b2f0caf1SEmmanuel Vadot struct gpiobus_pin *pin; 235*b2f0caf1SEmmanuel Vadot int rv; 236*b2f0caf1SEmmanuel Vadot 237*b2f0caf1SEmmanuel Vadot sc = regnode_get_softc(regnode); 238*b2f0caf1SEmmanuel Vadot dev = regnode_get_device(regnode); 239*b2f0caf1SEmmanuel Vadot 240*b2f0caf1SEmmanuel Vadot *udelay = 0; 241*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry == NULL) 242*b2f0caf1SEmmanuel Vadot return (0); 243*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry->always_on) 244*b2f0caf1SEmmanuel Vadot return (0); 245*b2f0caf1SEmmanuel Vadot pin = &sc->gpio_entry->gpio_pin; 246*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry->enable_cnt > 0) { 247*b2f0caf1SEmmanuel Vadot /* Other regulator(s) are enabled. */ 248*b2f0caf1SEmmanuel Vadot /* XXXX Any diagnostic message? Or error? */ 249*b2f0caf1SEmmanuel Vadot return (0); 250*b2f0caf1SEmmanuel Vadot } 251*b2f0caf1SEmmanuel Vadot rv = GPIO_PIN_SET(pin->dev, pin->pin, 252*b2f0caf1SEmmanuel Vadot sc->param->enable_active_high ? false: true); 253*b2f0caf1SEmmanuel Vadot if (rv != 0) { 254*b2f0caf1SEmmanuel Vadot device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin); 255*b2f0caf1SEmmanuel Vadot return (rv); 256*b2f0caf1SEmmanuel Vadot } 257*b2f0caf1SEmmanuel Vadot *udelay = sc->param->enable_delay; 258*b2f0caf1SEmmanuel Vadot return (0); 259*b2f0caf1SEmmanuel Vadot } 260*b2f0caf1SEmmanuel Vadot 261*b2f0caf1SEmmanuel Vadot static int 262*b2f0caf1SEmmanuel Vadot regnode_fixed_status(struct regnode *regnode, int *status) 263*b2f0caf1SEmmanuel Vadot { 264*b2f0caf1SEmmanuel Vadot struct regnode_fixed_sc *sc; 265*b2f0caf1SEmmanuel Vadot struct gpiobus_pin *pin; 266*b2f0caf1SEmmanuel Vadot uint32_t val; 267*b2f0caf1SEmmanuel Vadot int rv; 268*b2f0caf1SEmmanuel Vadot 269*b2f0caf1SEmmanuel Vadot sc = regnode_get_softc(regnode); 270*b2f0caf1SEmmanuel Vadot 271*b2f0caf1SEmmanuel Vadot *status = 0; 272*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry == NULL) { 273*b2f0caf1SEmmanuel Vadot *status = REGULATOR_STATUS_ENABLED; 274*b2f0caf1SEmmanuel Vadot return (0); 275*b2f0caf1SEmmanuel Vadot } 276*b2f0caf1SEmmanuel Vadot pin = &sc->gpio_entry->gpio_pin; 277*b2f0caf1SEmmanuel Vadot 278*b2f0caf1SEmmanuel Vadot rv = GPIO_PIN_GET(pin->dev, pin->pin, &val); 279*b2f0caf1SEmmanuel Vadot if (rv == 0) { 280*b2f0caf1SEmmanuel Vadot if (!sc->param->enable_active_high ^ (val != 0)) 281*b2f0caf1SEmmanuel Vadot *status = REGULATOR_STATUS_ENABLED; 282*b2f0caf1SEmmanuel Vadot } 283*b2f0caf1SEmmanuel Vadot return (rv); 284*b2f0caf1SEmmanuel Vadot } 285*b2f0caf1SEmmanuel Vadot 286*b2f0caf1SEmmanuel Vadot static int 287*b2f0caf1SEmmanuel Vadot regnode_fixed_get_voltage(struct regnode *regnode, int *uvolt) 288*b2f0caf1SEmmanuel Vadot { 289*b2f0caf1SEmmanuel Vadot struct regnode_fixed_sc *sc; 290*b2f0caf1SEmmanuel Vadot 291*b2f0caf1SEmmanuel Vadot sc = regnode_get_softc(regnode); 292*b2f0caf1SEmmanuel Vadot *uvolt = sc->param->min_uvolt; 293*b2f0caf1SEmmanuel Vadot return (0); 294*b2f0caf1SEmmanuel Vadot } 295*b2f0caf1SEmmanuel Vadot 296*b2f0caf1SEmmanuel Vadot int 297*b2f0caf1SEmmanuel Vadot regnode_fixed_register(device_t dev, struct regnode_fixed_init_def *init_def) 298*b2f0caf1SEmmanuel Vadot { 299*b2f0caf1SEmmanuel Vadot struct regnode *regnode; 300*b2f0caf1SEmmanuel Vadot struct regnode_fixed_sc *sc; 301*b2f0caf1SEmmanuel Vadot 302*b2f0caf1SEmmanuel Vadot regnode = regnode_create(dev, ®node_fixed_class, 303*b2f0caf1SEmmanuel Vadot &init_def->reg_init_def); 304*b2f0caf1SEmmanuel Vadot if (regnode == NULL) { 305*b2f0caf1SEmmanuel Vadot device_printf(dev, "Cannot create regulator.\n"); 306*b2f0caf1SEmmanuel Vadot return(ENXIO); 307*b2f0caf1SEmmanuel Vadot } 308*b2f0caf1SEmmanuel Vadot sc = regnode_get_softc(regnode); 309*b2f0caf1SEmmanuel Vadot sc->gpio_open_drain = init_def->gpio_open_drain; 310*b2f0caf1SEmmanuel Vadot if (init_def->gpio_pin != NULL) { 311*b2f0caf1SEmmanuel Vadot sc->gpio_entry = regnode_get_gpio_entry(init_def->gpio_pin); 312*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry == NULL) 313*b2f0caf1SEmmanuel Vadot return(ENXIO); 314*b2f0caf1SEmmanuel Vadot } 315*b2f0caf1SEmmanuel Vadot regnode = regnode_register(regnode); 316*b2f0caf1SEmmanuel Vadot if (regnode == NULL) { 317*b2f0caf1SEmmanuel Vadot device_printf(dev, "Cannot register regulator.\n"); 318*b2f0caf1SEmmanuel Vadot return(ENXIO); 319*b2f0caf1SEmmanuel Vadot } 320*b2f0caf1SEmmanuel Vadot 321*b2f0caf1SEmmanuel Vadot if (sc->gpio_entry != NULL) 322*b2f0caf1SEmmanuel Vadot sc->gpio_entry->always_on |= sc->param->always_on; 323*b2f0caf1SEmmanuel Vadot 324*b2f0caf1SEmmanuel Vadot return (0); 325*b2f0caf1SEmmanuel Vadot } 326*b2f0caf1SEmmanuel Vadot 327*b2f0caf1SEmmanuel Vadot /* 328*b2f0caf1SEmmanuel Vadot * OFW Driver implementation. 329*b2f0caf1SEmmanuel Vadot */ 330*b2f0caf1SEmmanuel Vadot #ifdef FDT 331*b2f0caf1SEmmanuel Vadot 332*b2f0caf1SEmmanuel Vadot struct regfix_softc 333*b2f0caf1SEmmanuel Vadot { 334*b2f0caf1SEmmanuel Vadot device_t dev; 335*b2f0caf1SEmmanuel Vadot bool attach_done; 336*b2f0caf1SEmmanuel Vadot struct regnode_fixed_init_def init_def; 337*b2f0caf1SEmmanuel Vadot phandle_t gpio_prodxref; 338*b2f0caf1SEmmanuel Vadot pcell_t *gpio_cells; 339*b2f0caf1SEmmanuel Vadot int gpio_ncells; 340*b2f0caf1SEmmanuel Vadot struct gpiobus_pin gpio_pin; 341*b2f0caf1SEmmanuel Vadot }; 342*b2f0caf1SEmmanuel Vadot 343*b2f0caf1SEmmanuel Vadot static struct ofw_compat_data compat_data[] = { 344*b2f0caf1SEmmanuel Vadot {"regulator-fixed", 1}, 345*b2f0caf1SEmmanuel Vadot {NULL, 0}, 346*b2f0caf1SEmmanuel Vadot }; 347*b2f0caf1SEmmanuel Vadot 348*b2f0caf1SEmmanuel Vadot static int 349*b2f0caf1SEmmanuel Vadot regfix_get_gpio(struct regfix_softc * sc) 350*b2f0caf1SEmmanuel Vadot { 351*b2f0caf1SEmmanuel Vadot device_t busdev; 352*b2f0caf1SEmmanuel Vadot phandle_t node; 353*b2f0caf1SEmmanuel Vadot 354*b2f0caf1SEmmanuel Vadot int rv; 355*b2f0caf1SEmmanuel Vadot 356*b2f0caf1SEmmanuel Vadot if (sc->gpio_prodxref == 0) 357*b2f0caf1SEmmanuel Vadot return (0); 358*b2f0caf1SEmmanuel Vadot 359*b2f0caf1SEmmanuel Vadot node = ofw_bus_get_node(sc->dev); 360*b2f0caf1SEmmanuel Vadot 361*b2f0caf1SEmmanuel Vadot /* Test if controller exist. */ 362*b2f0caf1SEmmanuel Vadot sc->gpio_pin.dev = OF_device_from_xref(sc->gpio_prodxref); 363*b2f0caf1SEmmanuel Vadot if (sc->gpio_pin.dev == NULL) 364*b2f0caf1SEmmanuel Vadot return (ENODEV); 365*b2f0caf1SEmmanuel Vadot 366*b2f0caf1SEmmanuel Vadot /* Test if GPIO bus already exist. */ 367*b2f0caf1SEmmanuel Vadot busdev = GPIO_GET_BUS(sc->gpio_pin.dev); 368*b2f0caf1SEmmanuel Vadot if (busdev == NULL) 369*b2f0caf1SEmmanuel Vadot return (ENODEV); 370*b2f0caf1SEmmanuel Vadot 371*b2f0caf1SEmmanuel Vadot rv = gpio_map_gpios(sc->gpio_pin.dev, node, 372*b2f0caf1SEmmanuel Vadot OF_node_from_xref(sc->gpio_prodxref), sc->gpio_ncells, 373*b2f0caf1SEmmanuel Vadot sc->gpio_cells, &(sc->gpio_pin.pin), &(sc->gpio_pin.flags)); 374*b2f0caf1SEmmanuel Vadot if (rv != 0) { 375*b2f0caf1SEmmanuel Vadot device_printf(sc->dev, "Cannot map the gpio property.\n"); 376*b2f0caf1SEmmanuel Vadot return (ENXIO); 377*b2f0caf1SEmmanuel Vadot } 378*b2f0caf1SEmmanuel Vadot sc->init_def.gpio_pin = &sc->gpio_pin; 379*b2f0caf1SEmmanuel Vadot return (0); 380*b2f0caf1SEmmanuel Vadot } 381*b2f0caf1SEmmanuel Vadot 382*b2f0caf1SEmmanuel Vadot static int 383*b2f0caf1SEmmanuel Vadot regfix_parse_fdt(struct regfix_softc * sc) 384*b2f0caf1SEmmanuel Vadot { 385*b2f0caf1SEmmanuel Vadot phandle_t node; 386*b2f0caf1SEmmanuel Vadot int rv; 387*b2f0caf1SEmmanuel Vadot struct regnode_init_def *init_def; 388*b2f0caf1SEmmanuel Vadot 389*b2f0caf1SEmmanuel Vadot node = ofw_bus_get_node(sc->dev); 390*b2f0caf1SEmmanuel Vadot init_def = &sc->init_def.reg_init_def; 391*b2f0caf1SEmmanuel Vadot 392*b2f0caf1SEmmanuel Vadot rv = regulator_parse_ofw_stdparam(sc->dev, node, init_def); 393*b2f0caf1SEmmanuel Vadot if (rv != 0) { 394*b2f0caf1SEmmanuel Vadot device_printf(sc->dev, "Cannot parse standard parameters.\n"); 395*b2f0caf1SEmmanuel Vadot return(rv); 396*b2f0caf1SEmmanuel Vadot } 397*b2f0caf1SEmmanuel Vadot 398*b2f0caf1SEmmanuel Vadot if (init_def->std_param.min_uvolt != init_def->std_param.max_uvolt) { 399*b2f0caf1SEmmanuel Vadot device_printf(sc->dev, "min_uvolt != max_uvolt\n"); 400*b2f0caf1SEmmanuel Vadot return (ENXIO); 401*b2f0caf1SEmmanuel Vadot } 402*b2f0caf1SEmmanuel Vadot /* Fixed regulator uses 'startup-delay-us' property for enable_delay */ 403*b2f0caf1SEmmanuel Vadot rv = OF_getencprop(node, "startup-delay-us", 404*b2f0caf1SEmmanuel Vadot &init_def->std_param.enable_delay, 405*b2f0caf1SEmmanuel Vadot sizeof(init_def->std_param.enable_delay)); 406*b2f0caf1SEmmanuel Vadot if (rv <= 0) 407*b2f0caf1SEmmanuel Vadot init_def->std_param.enable_delay = 0; 408*b2f0caf1SEmmanuel Vadot /* GPIO pin */ 409*b2f0caf1SEmmanuel Vadot if (OF_hasprop(node, "gpio-open-drain")) 410*b2f0caf1SEmmanuel Vadot sc->init_def.gpio_open_drain = true; 411*b2f0caf1SEmmanuel Vadot 412*b2f0caf1SEmmanuel Vadot if (!OF_hasprop(node, "gpio")) 413*b2f0caf1SEmmanuel Vadot return (0); 414*b2f0caf1SEmmanuel Vadot rv = ofw_bus_parse_xref_list_alloc(node, "gpio", "#gpio-cells", 0, 415*b2f0caf1SEmmanuel Vadot &sc->gpio_prodxref, &sc->gpio_ncells, &sc->gpio_cells); 416*b2f0caf1SEmmanuel Vadot if (rv != 0) { 417*b2f0caf1SEmmanuel Vadot sc->gpio_prodxref = 0; 418*b2f0caf1SEmmanuel Vadot device_printf(sc->dev, "Malformed gpio property\n"); 419*b2f0caf1SEmmanuel Vadot return (ENXIO); 420*b2f0caf1SEmmanuel Vadot } 421*b2f0caf1SEmmanuel Vadot return (0); 422*b2f0caf1SEmmanuel Vadot } 423*b2f0caf1SEmmanuel Vadot 424*b2f0caf1SEmmanuel Vadot static void 425*b2f0caf1SEmmanuel Vadot regfix_new_pass(device_t dev) 426*b2f0caf1SEmmanuel Vadot { 427*b2f0caf1SEmmanuel Vadot struct regfix_softc * sc; 428*b2f0caf1SEmmanuel Vadot int rv; 429*b2f0caf1SEmmanuel Vadot 430*b2f0caf1SEmmanuel Vadot sc = device_get_softc(dev); 431*b2f0caf1SEmmanuel Vadot bus_generic_new_pass(dev); 432*b2f0caf1SEmmanuel Vadot 433*b2f0caf1SEmmanuel Vadot if (sc->attach_done) 434*b2f0caf1SEmmanuel Vadot return; 435*b2f0caf1SEmmanuel Vadot 436*b2f0caf1SEmmanuel Vadot /* Try to get and configure GPIO. */ 437*b2f0caf1SEmmanuel Vadot rv = regfix_get_gpio(sc); 438*b2f0caf1SEmmanuel Vadot if (rv != 0) 439*b2f0caf1SEmmanuel Vadot return; 440*b2f0caf1SEmmanuel Vadot 441*b2f0caf1SEmmanuel Vadot /* Register regulator. */ 442*b2f0caf1SEmmanuel Vadot regnode_fixed_register(sc->dev, &sc->init_def); 443*b2f0caf1SEmmanuel Vadot sc->attach_done = true; 444*b2f0caf1SEmmanuel Vadot } 445*b2f0caf1SEmmanuel Vadot 446*b2f0caf1SEmmanuel Vadot static int 447*b2f0caf1SEmmanuel Vadot regfix_probe(device_t dev) 448*b2f0caf1SEmmanuel Vadot { 449*b2f0caf1SEmmanuel Vadot 450*b2f0caf1SEmmanuel Vadot if (!ofw_bus_status_okay(dev)) 451*b2f0caf1SEmmanuel Vadot return (ENXIO); 452*b2f0caf1SEmmanuel Vadot 453*b2f0caf1SEmmanuel Vadot if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 454*b2f0caf1SEmmanuel Vadot return (ENXIO); 455*b2f0caf1SEmmanuel Vadot 456*b2f0caf1SEmmanuel Vadot device_set_desc(dev, "Fixed Regulator"); 457*b2f0caf1SEmmanuel Vadot return (BUS_PROBE_DEFAULT); 458*b2f0caf1SEmmanuel Vadot } 459*b2f0caf1SEmmanuel Vadot 460*b2f0caf1SEmmanuel Vadot static int 461*b2f0caf1SEmmanuel Vadot regfix_detach(device_t dev) 462*b2f0caf1SEmmanuel Vadot { 463*b2f0caf1SEmmanuel Vadot 464*b2f0caf1SEmmanuel Vadot /* This device is always present. */ 465*b2f0caf1SEmmanuel Vadot return (EBUSY); 466*b2f0caf1SEmmanuel Vadot } 467*b2f0caf1SEmmanuel Vadot 468*b2f0caf1SEmmanuel Vadot static int 469*b2f0caf1SEmmanuel Vadot regfix_attach(device_t dev) 470*b2f0caf1SEmmanuel Vadot { 471*b2f0caf1SEmmanuel Vadot struct regfix_softc * sc; 472*b2f0caf1SEmmanuel Vadot int rv; 473*b2f0caf1SEmmanuel Vadot 474*b2f0caf1SEmmanuel Vadot sc = device_get_softc(dev); 475*b2f0caf1SEmmanuel Vadot sc->dev = dev; 476*b2f0caf1SEmmanuel Vadot 477*b2f0caf1SEmmanuel Vadot /* Parse FDT data. */ 478*b2f0caf1SEmmanuel Vadot rv = regfix_parse_fdt(sc); 479*b2f0caf1SEmmanuel Vadot if (rv != 0) 480*b2f0caf1SEmmanuel Vadot return(ENXIO); 481*b2f0caf1SEmmanuel Vadot 482*b2f0caf1SEmmanuel Vadot /* Fill reset of init. */ 483*b2f0caf1SEmmanuel Vadot sc->init_def.reg_init_def.id = 1; 484*b2f0caf1SEmmanuel Vadot sc->init_def.reg_init_def.flags = REGULATOR_FLAGS_STATIC; 485*b2f0caf1SEmmanuel Vadot 486*b2f0caf1SEmmanuel Vadot /* Try to get and configure GPIO. */ 487*b2f0caf1SEmmanuel Vadot rv = regfix_get_gpio(sc); 488*b2f0caf1SEmmanuel Vadot if (rv != 0) 489*b2f0caf1SEmmanuel Vadot return (bus_generic_attach(dev)); 490*b2f0caf1SEmmanuel Vadot 491*b2f0caf1SEmmanuel Vadot /* Register regulator. */ 492*b2f0caf1SEmmanuel Vadot regnode_fixed_register(sc->dev, &sc->init_def); 493*b2f0caf1SEmmanuel Vadot sc->attach_done = true; 494*b2f0caf1SEmmanuel Vadot 495*b2f0caf1SEmmanuel Vadot return (bus_generic_attach(dev)); 496*b2f0caf1SEmmanuel Vadot } 497*b2f0caf1SEmmanuel Vadot 498*b2f0caf1SEmmanuel Vadot static device_method_t regfix_methods[] = { 499*b2f0caf1SEmmanuel Vadot /* Device interface */ 500*b2f0caf1SEmmanuel Vadot DEVMETHOD(device_probe, regfix_probe), 501*b2f0caf1SEmmanuel Vadot DEVMETHOD(device_attach, regfix_attach), 502*b2f0caf1SEmmanuel Vadot DEVMETHOD(device_detach, regfix_detach), 503*b2f0caf1SEmmanuel Vadot /* Bus interface */ 504*b2f0caf1SEmmanuel Vadot DEVMETHOD(bus_new_pass, regfix_new_pass), 505*b2f0caf1SEmmanuel Vadot /* Regdev interface */ 506*b2f0caf1SEmmanuel Vadot DEVMETHOD(regdev_map, regdev_default_ofw_map), 507*b2f0caf1SEmmanuel Vadot 508*b2f0caf1SEmmanuel Vadot DEVMETHOD_END 509*b2f0caf1SEmmanuel Vadot }; 510*b2f0caf1SEmmanuel Vadot 511*b2f0caf1SEmmanuel Vadot DEFINE_CLASS_0(regfix, regfix_driver, regfix_methods, 512*b2f0caf1SEmmanuel Vadot sizeof(struct regfix_softc)); 513*b2f0caf1SEmmanuel Vadot EARLY_DRIVER_MODULE(regfix, simplebus, regfix_driver, 0, 0, BUS_PASS_BUS); 514*b2f0caf1SEmmanuel Vadot 515*b2f0caf1SEmmanuel Vadot #endif /* FDT */ 516