1 /* 2 * Copyright (c) 2025 Stephen Hurd <shurd@FreeBSD.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <sys/param.h> 8 #include <sys/bus.h> 9 #include <sys/gpio.h> 10 #include <sys/kernel.h> 11 #include <sys/module.h> 12 13 #include <dev/ofw/openfirm.h> 14 #include <dev/ofw/ofw_bus.h> 15 #include <dev/ofw/ofw_bus_subr.h> 16 17 #include <dev/gpio/gpiobusvar.h> 18 #include <dev/syscon/syscon.h> 19 20 #include "syscon_if.h" 21 22 #define GRF_SOC_CON10 0x0428 23 #define SOC_CON10_GPIOMUT (1 << 1) 24 #define SOC_CON10_GPIOMUT_MASK ((1 << 1) << 16) 25 #define SOC_CON10_GPIOMUT_EN (1 << 0) 26 #define SOC_CON10_GPIOMUT_EN_MASK ((1 << 0) << 16) 27 28 struct rk_grf_gpio_softc { 29 device_t sc_dev; 30 device_t sc_busdev; 31 struct syscon *sc_grf; 32 bool active_high; 33 }; 34 35 static struct ofw_compat_data compat_data[] = { 36 {"rockchip,rk3328-grf-gpio", 1}, 37 {NULL, 0} 38 }; 39 40 static device_t 41 rk_grf_gpio_get_bus(device_t dev) 42 { 43 struct rk_grf_gpio_softc *sc; 44 45 sc = device_get_softc(dev); 46 47 return (sc->sc_busdev); 48 } 49 50 static int 51 rk_grf_gpio_pin_max(device_t dev, int *maxpin) 52 { 53 *maxpin = 1; 54 return (0); 55 } 56 57 static int 58 rk_grf_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 59 { 60 if (pin) 61 return (EINVAL); 62 63 snprintf(name, GPIOMAXNAME, "GPIO_MUTE"); 64 65 return (0); 66 } 67 68 static int 69 rk_grf_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 70 { 71 if (pin) 72 return (EINVAL); 73 *flags = GPIO_PIN_OUTPUT; 74 return (0); 75 } 76 77 static int 78 rk_grf_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 79 { 80 if (pin) 81 return (EINVAL); 82 if (flags != GPIO_PIN_OUTPUT) 83 return (EINVAL); 84 85 return (0); 86 } 87 88 static int 89 rk_grf_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 90 { 91 if (pin) 92 return (EINVAL); 93 94 *caps = GPIO_PIN_OUTPUT; 95 return (0); 96 } 97 98 static int 99 rk_grf_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 100 { 101 struct rk_grf_gpio_softc *sc; 102 uint32_t reg; 103 104 sc = device_get_softc(dev); 105 106 if (pin) 107 return (EINVAL); 108 109 reg = SYSCON_READ_4(sc->sc_grf, GRF_SOC_CON10); 110 if (reg & SOC_CON10_GPIOMUT) 111 *val = 1; 112 else 113 *val = 0; 114 115 return (0); 116 } 117 118 static int 119 rk_grf_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 120 { 121 struct rk_grf_gpio_softc *sc; 122 uint32_t val; 123 124 sc = device_get_softc(dev); 125 126 if (pin) 127 return (EINVAL); 128 129 val = SOC_CON10_GPIOMUT_MASK; 130 if (value) 131 val |= SOC_CON10_GPIOMUT; 132 SYSCON_WRITE_4(sc->sc_grf, GRF_SOC_CON10, val); 133 134 return (0); 135 } 136 137 static int 138 rk_grf_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, 139 pcell_t *gpios, uint32_t *pin, uint32_t *flags) 140 { 141 if (gpios[0]) 142 return (EINVAL); 143 144 /* The gpios are mapped as <pin flags> */ 145 *pin = 0; 146 /* TODO: The only valid flags are active low or active high */ 147 *flags = GPIO_PIN_OUTPUT; 148 return (0); 149 } 150 151 static int 152 rk_grf_gpio_probe(device_t dev) 153 { 154 155 if (!ofw_bus_status_okay(dev)) 156 return (ENXIO); 157 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 158 return (ENXIO); 159 160 device_set_desc(dev, "RockChip General Register File GPIO (GPIO_MUTE)"); 161 return (BUS_PROBE_DEFAULT); 162 } 163 164 static int 165 rk_grf_gpio_attach(device_t dev) 166 { 167 struct rk_grf_gpio_softc *sc; 168 phandle_t parent_node, node; 169 device_t pdev; 170 171 sc = device_get_softc(dev); 172 sc->sc_dev = dev; 173 174 node = ofw_bus_get_node(sc->sc_dev); 175 if (!OF_hasprop(node, "gpio-controller")) 176 return (ENXIO); 177 pdev = device_get_parent(dev); 178 parent_node = ofw_bus_get_node(pdev); 179 if (syscon_get_by_ofw_node(dev, parent_node, &sc->sc_grf) != 0) { 180 device_printf(dev, "cannot get parent syscon handle\n"); 181 return (ENXIO); 182 } 183 184 sc->sc_busdev = gpiobus_attach_bus(dev); 185 if (sc->sc_busdev == NULL) { 186 return (ENXIO); 187 } 188 189 return (0); 190 } 191 192 static int 193 rk_grf_gpio_detach(device_t dev) 194 { 195 struct rk_grf_gpio_softc *sc; 196 197 sc = device_get_softc(dev); 198 199 if (sc->sc_busdev) 200 gpiobus_detach_bus(dev); 201 202 return(0); 203 } 204 205 static device_method_t rk_grf_gpio_methods[] = { 206 DEVMETHOD(device_probe, rk_grf_gpio_probe), 207 DEVMETHOD(device_attach, rk_grf_gpio_attach), 208 DEVMETHOD(device_detach, rk_grf_gpio_detach), 209 210 /* GPIO protocol */ 211 DEVMETHOD(gpio_get_bus, rk_grf_gpio_get_bus), 212 DEVMETHOD(gpio_pin_max, rk_grf_gpio_pin_max), 213 DEVMETHOD(gpio_pin_getname, rk_grf_gpio_pin_getname), 214 DEVMETHOD(gpio_pin_getflags, rk_grf_gpio_pin_getflags), 215 DEVMETHOD(gpio_pin_setflags, rk_grf_gpio_pin_setflags), 216 DEVMETHOD(gpio_pin_getcaps, rk_grf_gpio_pin_getcaps), 217 DEVMETHOD(gpio_pin_get, rk_grf_gpio_pin_get), 218 DEVMETHOD(gpio_pin_set, rk_grf_gpio_pin_set), 219 DEVMETHOD(gpio_map_gpios, rk_grf_gpio_map_gpios), 220 221 DEVMETHOD_END 222 }; 223 224 static driver_t rk_grf_gpio_driver = { 225 "gpio", 226 rk_grf_gpio_methods, 227 sizeof(struct rk_grf_gpio_softc), 228 }; 229 230 /* 231 * GPIO driver is always a child of rk_grf driver and should be probed 232 * and attached within rk_grf function. Due to this, bus pass order 233 * must be same as bus pass order of rk_grf driver. 234 */ 235 EARLY_DRIVER_MODULE(rk_grf_gpio, simplebus, rk_grf_gpio_driver, 0, 0, 236 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 237