1 1.33 riastrad /* $NetBSD: exynos_gpio.c,v 1.33 2022/02/11 23:48:50 riastradh Exp $ */ 2 1.9 skrll 3 1.1 reinoud /*- 4 1.29 skrll * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc. 5 1.1 reinoud * All rights reserved. 6 1.1 reinoud * 7 1.1 reinoud * This code is derived from software contributed to The NetBSD Foundation 8 1.29 skrll * by Reinoud Zandijk, and by Nick Hudson 9 1.1 reinoud * 10 1.1 reinoud * Redistribution and use in source and binary forms, with or without 11 1.1 reinoud * modification, are permitted provided that the following conditions 12 1.1 reinoud * are met: 13 1.1 reinoud * 1. Redistributions of source code must retain the above copyright 14 1.1 reinoud * notice, this list of conditions and the following disclaimer. 15 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 reinoud * notice, this list of conditions and the following disclaimer in the 17 1.1 reinoud * documentation and/or other materials provided with the distribution. 18 1.1 reinoud * 19 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 reinoud * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 reinoud * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 reinoud * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 reinoud * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 reinoud * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 reinoud * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 reinoud * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 reinoud * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 reinoud * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 reinoud * POSSIBILITY OF SUCH DAMAGE. 30 1.1 reinoud */ 31 1.1 reinoud 32 1.1 reinoud #include "opt_exynos.h" 33 1.1 reinoud #include "opt_arm_debug.h" 34 1.1 reinoud #include "gpio.h" 35 1.1 reinoud 36 1.1 reinoud #include <sys/cdefs.h> 37 1.33 riastrad __KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.33 2022/02/11 23:48:50 riastradh Exp $"); 38 1.1 reinoud 39 1.1 reinoud #include <sys/param.h> 40 1.1 reinoud #include <sys/bus.h> 41 1.1 reinoud #include <sys/device.h> 42 1.1 reinoud #include <sys/intr.h> 43 1.1 reinoud #include <sys/systm.h> 44 1.1 reinoud #include <sys/kmem.h> 45 1.13 marty #include <sys/gpio.h> 46 1.13 marty 47 1.13 marty #include <dev/gpio/gpiovar.h> 48 1.1 reinoud 49 1.1 reinoud #include <arm/samsung/exynos_reg.h> 50 1.15 marty #include <arm/samsung/exynos_var.h> 51 1.1 reinoud #include <arm/samsung/exynos_intr.h> 52 1.14 marty #include <arm/samsung/exynos_pinctrl.h> 53 1.14 marty 54 1.14 marty #include <dev/fdt/fdtvar.h> 55 1.1 reinoud 56 1.13 marty struct exynos_gpio_bank { 57 1.13 marty const char bank_name[6]; 58 1.13 marty device_t bank_dev; 59 1.13 marty struct gpio_chipset_tag bank_gc; 60 1.16 marty struct exynos_gpio_softc *bank_sc; 61 1.13 marty gpio_pin_t bank_pins[8]; 62 1.13 marty 63 1.13 marty const bus_addr_t bank_core_offset; 64 1.13 marty const uint8_t bank_bits; 65 1.13 marty 66 1.13 marty struct exynos_gpio_pin_cfg bank_cfg; 67 1.1 reinoud }; 68 1.1 reinoud 69 1.13 marty struct exynos_gpio_pin { 70 1.13 marty struct exynos_gpio_softc *pin_sc; 71 1.13 marty int pin_no; 72 1.13 marty u_int pin_flags; 73 1.14 marty int pin_actlo; 74 1.14 marty const struct exynos_gpio_bank *pin_bank; 75 1.1 reinoud }; 76 1.1 reinoud 77 1.1 reinoud 78 1.16 marty //#define GPIO_REG(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o)) 79 1.16 marty #define GPIO_REG(v,s,o) ((o)) 80 1.16 marty #define GPIO_GRP(v, s, o, n, b) \ 81 1.16 marty { \ 82 1.16 marty .bank_name = #n, \ 83 1.16 marty .bank_core_offset = GPIO_REG(v,s,o), \ 84 1.16 marty .bank_bits = b, \ 85 1.16 marty } 86 1.16 marty 87 1.29 skrll #define GPIO_GRP_INTR(o, n, b, i) \ 88 1.29 skrll { \ 89 1.29 skrll .bank_name = #n, \ 90 1.29 skrll .bank_core_offset = GPIO_REG(v,s,o), \ 91 1.29 skrll .bank_bits = b, \ 92 1.29 skrll } 93 1.29 skrll 94 1.29 skrll #define GPIO_GRP_NONE(o, n, b) \ 95 1.29 skrll { \ 96 1.29 skrll .bank_name = #n, \ 97 1.29 skrll .bank_core_offset = GPIO_REG(v,s,o), \ 98 1.29 skrll .bank_bits = b, \ 99 1.29 skrll } 100 1.29 skrll 101 1.29 skrll #define GPIO_GRP_WAKEUP(o, n, b, i) \ 102 1.29 skrll { \ 103 1.29 skrll .bank_name = #n, \ 104 1.29 skrll .bank_core_offset = GPIO_REG(v,s,o), \ 105 1.29 skrll .bank_bits = b, \ 106 1.29 skrll } 107 1.29 skrll 108 1.29 skrll 109 1.29 skrll 110 1.29 skrll static struct exynos_gpio_bank exynos5420_banks[] = { 111 1.16 marty GPIO_GRP(5, MUXA, 0x0000, gpy7, 8), 112 1.16 marty GPIO_GRP(5, MUXA, 0x0C00, gpx0, 8), 113 1.16 marty GPIO_GRP(5, MUXA, 0x0C20, gpx1, 8), 114 1.16 marty GPIO_GRP(5, MUXA, 0x0C40, gpx2, 8), 115 1.16 marty GPIO_GRP(5, MUXA, 0x0C60, gpx3, 8), 116 1.16 marty 117 1.16 marty GPIO_GRP(5, MUXB, 0x0000, gpc0, 8), 118 1.16 marty GPIO_GRP(5, MUXB, 0x0020, gpc1, 8), 119 1.16 marty GPIO_GRP(5, MUXB, 0x0040, gpc2, 7), 120 1.16 marty GPIO_GRP(5, MUXB, 0x0060, gpc3, 4), 121 1.16 marty GPIO_GRP(5, MUXB, 0x0080, gpc4, 2), 122 1.16 marty GPIO_GRP(5, MUXB, 0x00A0, gpd1, 8), 123 1.16 marty GPIO_GRP(5, MUXB, 0x00C0, gpy0, 6), 124 1.16 marty GPIO_GRP(5, MUXB, 0x00E0, gpy1, 4), 125 1.16 marty GPIO_GRP(5, MUXB, 0x0100, gpy2, 6), 126 1.16 marty GPIO_GRP(5, MUXB, 0x0120, gpy3, 8), 127 1.16 marty GPIO_GRP(5, MUXB, 0x0140, gpy4, 8), 128 1.16 marty GPIO_GRP(5, MUXB, 0x0160, gpy5, 8), 129 1.16 marty GPIO_GRP(5, MUXB, 0x0180, gpy6, 8), 130 1.16 marty 131 1.16 marty GPIO_GRP(5, MUXC, 0x0000, gpe0, 8), 132 1.16 marty GPIO_GRP(5, MUXC, 0x0020, gpe1, 2), 133 1.16 marty GPIO_GRP(5, MUXC, 0x0040, gpf0, 6), 134 1.16 marty GPIO_GRP(5, MUXC, 0x0060, gpf1, 8), 135 1.16 marty GPIO_GRP(5, MUXC, 0x0080, gpg0, 8), 136 1.16 marty GPIO_GRP(5, MUXC, 0x00A0, gpg1, 8), 137 1.16 marty GPIO_GRP(5, MUXC, 0x00C0, gpg2, 2), 138 1.16 marty GPIO_GRP(5, MUXC, 0x00E0, gpj4, 4), 139 1.16 marty 140 1.16 marty GPIO_GRP(5, MUXD, 0x0000, gpa0, 8), 141 1.16 marty GPIO_GRP(5, MUXD, 0x0020, gpa1, 6), 142 1.16 marty GPIO_GRP(5, MUXD, 0x0040, gpa2, 8), 143 1.16 marty GPIO_GRP(5, MUXD, 0x0060, gpb0, 5), 144 1.16 marty GPIO_GRP(5, MUXD, 0x0080, gpb1, 5), 145 1.16 marty GPIO_GRP(5, MUXD, 0x00A0, gpb2, 4), 146 1.16 marty GPIO_GRP(5, MUXD, 0x00C0, gpb3, 8), 147 1.16 marty GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2), 148 1.16 marty GPIO_GRP(5, MUXD, 0x0100, gph0, 4), 149 1.16 marty 150 1.22 marty GPIO_GRP(5, MUXE, 0x0000, gpz, 7), 151 1.29 skrll }; 152 1.29 skrll 153 1.29 skrll struct exynos_pinctrl_banks exynos5420_pinctrl_banks = { 154 1.29 skrll .epb_banks = exynos5420_banks, 155 1.29 skrll .epb_nbanks = __arraycount(exynos5420_banks) 156 1.29 skrll }; 157 1.29 skrll 158 1.29 skrll static struct exynos_gpio_bank exynos5410_banks[] = { 159 1.29 skrll /* pin-controller 0 */ 160 1.29 skrll GPIO_GRP_INTR(0x000, gpa0, 8, 0x00), 161 1.29 skrll GPIO_GRP_INTR(0x020, gpa1, 6, 0x04), 162 1.29 skrll GPIO_GRP_INTR(0x040, gpa2, 8, 0x08), 163 1.29 skrll GPIO_GRP_INTR(0x060, gpb0, 5, 0x0c), 164 1.29 skrll GPIO_GRP_INTR(0x080, gpb1, 5, 0x10), 165 1.29 skrll GPIO_GRP_INTR(0x0A0, gpb2, 4, 0x14), 166 1.29 skrll GPIO_GRP_INTR(0x0C0, gpb3, 4, 0x18), 167 1.29 skrll GPIO_GRP_INTR(0x0E0, gpc0, 7, 0x1c), 168 1.29 skrll GPIO_GRP_INTR(0x100, gpc3, 4, 0x20), 169 1.29 skrll GPIO_GRP_INTR(0x120, gpc1, 7, 0x24), 170 1.29 skrll GPIO_GRP_INTR(0x140, gpc2, 7, 0x28), 171 1.29 skrll GPIO_GRP_INTR(0x180, gpd1, 8, 0x2c), 172 1.29 skrll GPIO_GRP_INTR(0x1A0, gpe0, 8, 0x30), 173 1.29 skrll GPIO_GRP_INTR(0x1C0, gpe1, 2, 0x34), 174 1.29 skrll GPIO_GRP_INTR(0x1E0, gpf0, 6, 0x38), 175 1.29 skrll GPIO_GRP_INTR(0x200, gpf1, 8, 0x3c), 176 1.29 skrll GPIO_GRP_INTR(0x220, gpg0, 8, 0x40), 177 1.29 skrll GPIO_GRP_INTR(0x240, gpg1, 8, 0x44), 178 1.29 skrll GPIO_GRP_INTR(0x260, gpg2, 2, 0x48), 179 1.29 skrll GPIO_GRP_INTR(0x280, gph0, 4, 0x4c), 180 1.29 skrll GPIO_GRP_INTR(0x2A0, gph1, 8, 0x50), 181 1.29 skrll GPIO_GRP_NONE(0x160, gpm5, 2), 182 1.29 skrll GPIO_GRP_NONE(0x2C0, gpm7, 8), 183 1.29 skrll GPIO_GRP_NONE(0x2E0, gpy0, 6), 184 1.29 skrll GPIO_GRP_NONE(0x300, gpy1, 4), 185 1.29 skrll GPIO_GRP_NONE(0x320, gpy2, 6), 186 1.29 skrll GPIO_GRP_NONE(0x340, gpy3, 8), 187 1.29 skrll GPIO_GRP_NONE(0x360, gpy4, 8), 188 1.29 skrll GPIO_GRP_NONE(0x380, gpy5, 8), 189 1.29 skrll GPIO_GRP_NONE(0x3A0, gpy6, 8), 190 1.29 skrll GPIO_GRP_NONE(0x3C0, gpy7, 8), 191 1.29 skrll GPIO_GRP_WAKEUP(0xC00, gpx0, 8, 0x00), 192 1.29 skrll GPIO_GRP_WAKEUP(0xC20, gpx1, 8, 0x04), 193 1.29 skrll GPIO_GRP_WAKEUP(0xC40, gpx2, 8, 0x08), 194 1.29 skrll GPIO_GRP_WAKEUP(0xC60, gpx3, 8, 0x0c), 195 1.29 skrll 196 1.29 skrll /* pin-controller 1 */ 197 1.29 skrll GPIO_GRP_INTR(0x000, gpj0, 5, 0x00), 198 1.29 skrll GPIO_GRP_INTR(0x020, gpj1, 8, 0x04), 199 1.29 skrll GPIO_GRP_INTR(0x040, gpj2, 8, 0x08), 200 1.29 skrll GPIO_GRP_INTR(0x060, gpj3, 8, 0x0c), 201 1.29 skrll GPIO_GRP_INTR(0x080, gpj4, 2, 0x10), 202 1.29 skrll GPIO_GRP_INTR(0x0A0, gpk0, 8, 0x14), 203 1.29 skrll GPIO_GRP_INTR(0x0C0, gpk1, 8, 0x18), 204 1.29 skrll GPIO_GRP_INTR(0x0E0, gpk2, 8, 0x1c), 205 1.29 skrll GPIO_GRP_INTR(0x100, gpk3, 7, 0x20), 206 1.29 skrll 207 1.29 skrll /* pin-controller 2 */ 208 1.29 skrll GPIO_GRP_INTR(0x000, gpv0, 8, 0x00), 209 1.29 skrll GPIO_GRP_INTR(0x020, gpv1, 8, 0x04), 210 1.29 skrll GPIO_GRP_INTR(0x060, gpv2, 8, 0x08), 211 1.29 skrll GPIO_GRP_INTR(0x080, gpv3, 8, 0x0c), 212 1.29 skrll GPIO_GRP_INTR(0x0C0, gpv4, 2, 0x10), 213 1.29 skrll 214 1.29 skrll /* pin-controller 2 */ 215 1.29 skrll GPIO_GRP_INTR(0x000, gpz, 7, 0x00), 216 1.29 skrll }; 217 1.16 marty 218 1.29 skrll struct exynos_pinctrl_banks exynos5410_pinctrl_banks = { 219 1.29 skrll .epb_banks = exynos5410_banks, 220 1.29 skrll .epb_nbanks = __arraycount(exynos5410_banks) 221 1.16 marty }; 222 1.16 marty 223 1.16 marty 224 1.16 marty static int exynos_gpio_pin_read(void *, int); 225 1.16 marty static void exynos_gpio_pin_write(void *, int, int); 226 1.16 marty static void exynos_gpio_pin_ctl(void *, int, int); 227 1.14 marty static void *exynos_gpio_fdt_acquire(device_t, const void *, 228 1.14 marty size_t, int); 229 1.14 marty static void exynos_gpio_fdt_release(device_t, void *); 230 1.14 marty 231 1.17 jmcneill static int exynos_gpio_fdt_read(device_t, void *, bool); 232 1.17 jmcneill static void exynos_gpio_fdt_write(device_t, void *, int, bool); 233 1.16 marty static int exynos_gpio_cfprint(void *, const char *); 234 1.14 marty 235 1.14 marty struct fdtbus_gpio_controller_func exynos_gpio_funcs = { 236 1.14 marty .acquire = exynos_gpio_fdt_acquire, 237 1.14 marty .release = exynos_gpio_fdt_release, 238 1.14 marty .read = exynos_gpio_fdt_read, 239 1.14 marty .write = exynos_gpio_fdt_write 240 1.1 reinoud }; 241 1.16 marty #define GPIO_WRITE(bank, reg, val) \ 242 1.16 marty bus_space_write_4((bank)->bank_sc->sc_bst, \ 243 1.16 marty (bank)->bank_sc->sc_bsh, \ 244 1.16 marty (bank)->bank_core_offset + (reg), (val)) 245 1.16 marty #define GPIO_READ(bank, reg) \ 246 1.16 marty bus_space_read_4((bank)->bank_sc->sc_bst, \ 247 1.16 marty (bank)->bank_sc->sc_bsh, \ 248 1.16 marty (bank)->bank_core_offset + (reg)) 249 1.1 reinoud 250 1.13 marty static int 251 1.13 marty exynos_gpio_cfprint(void *priv, const char *pnp) 252 1.13 marty { 253 1.13 marty struct gpiobus_attach_args *gba = priv; 254 1.13 marty struct exynos_gpio_bank *bank = gba->gba_gc->gp_cookie; 255 1.13 marty const char *bankname = bank->bank_name; 256 1.13 marty 257 1.13 marty if (pnp) 258 1.13 marty aprint_normal("gpiobus at %s", pnp); 259 1.13 marty 260 1.13 marty aprint_normal(" (%s)", bankname); 261 1.13 marty 262 1.13 marty return UNCONF; 263 1.13 marty } 264 1.1 reinoud 265 1.16 marty static int 266 1.16 marty exynos_gpio_pin_read(void *cookie, int pin) 267 1.16 marty { 268 1.16 marty struct exynos_gpio_bank * const bank = cookie; 269 1.27 skrll uint8_t val; 270 1.16 marty 271 1.16 marty KASSERT(pin < bank->bank_bits); 272 1.27 skrll val = bus_space_read_1(bank->bank_sc->sc_bst, bank->bank_sc->sc_bsh, 273 1.27 skrll EXYNOS_GPIO_DAT); 274 1.27 skrll 275 1.27 skrll return __SHIFTOUT(val, __BIT(pin)); 276 1.16 marty } 277 1.16 marty 278 1.16 marty static void 279 1.16 marty exynos_gpio_pin_write(void *cookie, int pin, int value) 280 1.16 marty { 281 1.16 marty struct exynos_gpio_bank * const bank = cookie; 282 1.16 marty int val; 283 1.16 marty 284 1.16 marty KASSERT(pin < bank->bank_bits); 285 1.27 skrll val = bus_space_read_1(bank->bank_sc->sc_bst, bank->bank_sc->sc_bsh, 286 1.27 skrll EXYNOS_GPIO_DAT); 287 1.16 marty val &= ~__BIT(pin); 288 1.16 marty if (value) 289 1.16 marty val |= __BIT(pin); 290 1.27 skrll bus_space_write_1(bank->bank_sc->sc_bst, bank->bank_sc->sc_bsh, 291 1.27 skrll EXYNOS_GPIO_DAT, val); 292 1.16 marty } 293 1.1 reinoud 294 1.1 reinoud static void 295 1.1 reinoud exynos_gpio_pin_ctl(void *cookie, int pin, int flags) 296 1.1 reinoud { 297 1.13 marty struct exynos_gpio_bank * const bank = cookie; 298 1.25 jmcneill struct exynos_gpio_pin_cfg ncfg = { 0 }; 299 1.1 reinoud 300 1.1 reinoud /* honour pullup requests */ 301 1.25 jmcneill if (flags & GPIO_PIN_PULLUP) { 302 1.25 jmcneill ncfg.pud = EXYNOS_GPIO_PIN_PULL_UP; 303 1.25 jmcneill ncfg.pud_valid = true; 304 1.25 jmcneill } 305 1.25 jmcneill if (flags & GPIO_PIN_PULLDOWN) { 306 1.25 jmcneill ncfg.pud = EXYNOS_GPIO_PIN_PULL_DOWN; 307 1.25 jmcneill ncfg.pud_valid = true; 308 1.25 jmcneill } 309 1.1 reinoud 310 1.1 reinoud /* honour i/o */ 311 1.14 marty if (flags & GPIO_PIN_INPUT) { 312 1.25 jmcneill ncfg.cfg = EXYNOS_GPIO_FUNC_INPUT; 313 1.25 jmcneill ncfg.cfg_valid = true; 314 1.14 marty } else if (flags & GPIO_PIN_OUTPUT) { 315 1.25 jmcneill ncfg.cfg = EXYNOS_GPIO_FUNC_OUTPUT; 316 1.25 jmcneill ncfg.cfg_valid = true; 317 1.14 marty } 318 1.1 reinoud 319 1.1 reinoud /* update any config registers that changed */ 320 1.25 jmcneill exynos_gpio_pin_ctl_write(bank, &ncfg, pin); 321 1.1 reinoud } 322 1.1 reinoud 323 1.24 jmcneill void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *bank, 324 1.24 jmcneill const struct exynos_gpio_pin_cfg *cfg, 325 1.24 jmcneill int pin) 326 1.22 marty { 327 1.24 jmcneill uint32_t val; 328 1.24 jmcneill 329 1.24 jmcneill if (cfg->cfg_valid) { 330 1.24 jmcneill val = GPIO_READ(bank, EXYNOS_GPIO_CON); 331 1.24 jmcneill val &= ~(0xf << (pin * 4)); 332 1.24 jmcneill val |= (cfg->cfg << (pin * 4)); 333 1.24 jmcneill GPIO_WRITE(bank, EXYNOS_GPIO_CON, val); 334 1.24 jmcneill } 335 1.24 jmcneill 336 1.24 jmcneill if (cfg->pud_valid) { 337 1.24 jmcneill val = GPIO_READ(bank, EXYNOS_GPIO_PUD); 338 1.24 jmcneill val &= ~(0x3 << (pin * 2)); 339 1.24 jmcneill val |= (cfg->pud << (pin * 2)); 340 1.24 jmcneill GPIO_WRITE(bank, EXYNOS_GPIO_PUD, val); 341 1.24 jmcneill } 342 1.24 jmcneill 343 1.24 jmcneill if (cfg->drv_valid) { 344 1.24 jmcneill val = GPIO_READ(bank, EXYNOS_GPIO_DRV); 345 1.24 jmcneill val &= ~(0x3 << (pin * 2)); 346 1.24 jmcneill val |= (cfg->drv << (pin * 2)); 347 1.24 jmcneill GPIO_WRITE(bank, EXYNOS_GPIO_DRV, val); 348 1.24 jmcneill } 349 1.24 jmcneill 350 1.24 jmcneill if (cfg->conpwd_valid) { 351 1.24 jmcneill val = GPIO_READ(bank, EXYNOS_GPIO_CONPWD); 352 1.24 jmcneill val &= ~(0x3 << (pin * 2)); 353 1.24 jmcneill val |= (cfg->conpwd << (pin * 2)); 354 1.24 jmcneill GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, val); 355 1.24 jmcneill } 356 1.22 marty 357 1.24 jmcneill if (cfg->pudpwd_valid) { 358 1.24 jmcneill val = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD); 359 1.24 jmcneill val &= ~(0x3 << (pin * 2)); 360 1.24 jmcneill val |= (cfg->pudpwd << (pin * 2)); 361 1.24 jmcneill GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, val); 362 1.24 jmcneill } 363 1.22 marty } 364 1.22 marty 365 1.22 marty struct exynos_gpio_softc * 366 1.18 marty exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent, 367 1.18 marty const struct fdt_attach_args *faa, int node) 368 1.1 reinoud { 369 1.16 marty struct exynos_gpio_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); 370 1.16 marty struct gpiobus_attach_args gba; 371 1.16 marty struct gpio_chipset_tag *gc_tag; 372 1.14 marty char result[64]; 373 1.13 marty 374 1.16 marty OF_getprop(node, "name", result, sizeof(result)); 375 1.29 skrll struct exynos_gpio_bank *bank = 376 1.29 skrll exynos_gpio_bank_lookup(parent->sc_epb, result); 377 1.20 jmcneill if (bank == NULL) { 378 1.20 jmcneill aprint_error_dev(parent->sc_dev, "no bank found for %s\n", 379 1.20 jmcneill result); 380 1.22 marty return NULL; 381 1.20 jmcneill } 382 1.26 skrll 383 1.14 marty sc->sc_dev = parent->sc_dev; 384 1.16 marty sc->sc_bst = &armv7_generic_bs_tag; 385 1.16 marty sc->sc_bsh = parent->sc_bsh; 386 1.22 marty sc->sc_bank = bank; 387 1.22 marty 388 1.16 marty gc_tag = &bank->bank_gc; 389 1.16 marty gc_tag->gp_cookie = bank; 390 1.16 marty gc_tag->gp_pin_read = exynos_gpio_pin_read; 391 1.16 marty gc_tag->gp_pin_write = exynos_gpio_pin_write; 392 1.16 marty gc_tag->gp_pin_ctl = exynos_gpio_pin_ctl; 393 1.14 marty memset(&gba, 0, sizeof(gba)); 394 1.14 marty gba.gba_gc = &bank->bank_gc; 395 1.14 marty gba.gba_pins = bank->bank_pins; 396 1.16 marty gba.gba_npins = bank->bank_bits; 397 1.29 skrll 398 1.16 marty bank->bank_sc = sc; 399 1.31 thorpej bank->bank_dev = 400 1.32 thorpej config_found(parent->sc_dev, &gba, exynos_gpio_cfprint, CFARGS_NONE); 401 1.14 marty 402 1.14 marty /* read in our initial settings */ 403 1.16 marty bank->bank_cfg.cfg = GPIO_READ(bank, EXYNOS_GPIO_CON); 404 1.16 marty bank->bank_cfg.pud = GPIO_READ(bank, EXYNOS_GPIO_PUD); 405 1.16 marty bank->bank_cfg.drv = GPIO_READ(bank, EXYNOS_GPIO_DRV); 406 1.16 marty bank->bank_cfg.conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD); 407 1.16 marty bank->bank_cfg.pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD); 408 1.18 marty 409 1.21 jmcneill fdtbus_register_gpio_controller(bank->bank_dev, node, 410 1.18 marty &exynos_gpio_funcs); 411 1.22 marty return sc; 412 1.13 marty } 413 1.1 reinoud 414 1.22 marty /* 415 1.22 marty * This function is a bit funky. Given a string that may look like 416 1.22 marty * 'gpAN' or 'gpAN-P' it is meant to find a match to the part before 417 1.22 marty * the '-', or the four character string if the dash is not present. 418 1.22 marty */ 419 1.22 marty struct exynos_gpio_bank * 420 1.30 thorpej exynos_gpio_bank_lookup(const struct exynos_pinctrl_banks *epb, 421 1.30 thorpej const char *name) 422 1.13 marty { 423 1.22 marty struct exynos_gpio_bank *bank; 424 1.22 marty 425 1.29 skrll for (u_int n = 0; n < epb->epb_nbanks; n++) { 426 1.29 skrll bank = &epb->epb_banks[n]; 427 1.22 marty if (!strncmp(bank->bank_name, name, 428 1.22 marty strlen(bank->bank_name))) { 429 1.14 marty return bank; 430 1.1 reinoud } 431 1.16 marty } 432 1.13 marty 433 1.13 marty return NULL; 434 1.1 reinoud } 435 1.1 reinoud 436 1.20 jmcneill #if notyet 437 1.20 jmcneill static int 438 1.20 jmcneill exynos_gpio_pin_lookup(const char *name) 439 1.20 jmcneill { 440 1.20 jmcneill char *p; 441 1.20 jmcneill 442 1.20 jmcneill p = strchr(name, '-'); 443 1.20 jmcneill if (p == NULL || p[1] < '0' || p[1] > '9') 444 1.20 jmcneill return -1; 445 1.20 jmcneill 446 1.20 jmcneill return p[1] - '0'; 447 1.20 jmcneill } 448 1.20 jmcneill #endif 449 1.20 jmcneill 450 1.14 marty static void * 451 1.14 marty exynos_gpio_fdt_acquire(device_t dev, const void *data, size_t len, int flags) 452 1.13 marty { 453 1.33 riastrad device_t parent = device_parent(dev); 454 1.33 riastrad struct exynos_pinctrl_softc *sc = device_private(parent); 455 1.33 riastrad const struct exynos_pinctrl_banks *epb = sc->sc_epb; 456 1.33 riastrad struct exynos_gpio_bank *bank = NULL; 457 1.13 marty struct exynos_gpio_pin *gpin; 458 1.33 riastrad u_int n; 459 1.33 riastrad 460 1.33 riastrad KASSERT(device_is_a(parent, "exyopctl")); 461 1.13 marty 462 1.21 jmcneill if (len != 12) 463 1.20 jmcneill return NULL; 464 1.20 jmcneill 465 1.29 skrll const u_int *cells = data; 466 1.21 jmcneill const int pin = be32toh(cells[1]) & 0x0f; 467 1.21 jmcneill const int actlo = be32toh(cells[2]) & 0x01; 468 1.20 jmcneill 469 1.33 riastrad for (n = 0; n < epb->epb_nbanks; n++) { 470 1.33 riastrad if (epb->epb_banks[n].bank_dev == dev) { 471 1.33 riastrad bank = &epb->epb_banks[n]; 472 1.33 riastrad break; 473 1.33 riastrad } 474 1.33 riastrad } 475 1.33 riastrad KASSERTMSG(bank != NULL, "no such gpio bank child of %s @ %p: %s @ %p", 476 1.33 riastrad device_xname(parent), parent, device_xname(dev), dev); 477 1.13 marty 478 1.13 marty gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP); 479 1.16 marty gpin->pin_sc = bank->bank_sc; 480 1.13 marty gpin->pin_bank = bank; 481 1.13 marty gpin->pin_no = pin; 482 1.13 marty gpin->pin_flags = flags; 483 1.20 jmcneill gpin->pin_actlo = actlo; 484 1.13 marty 485 1.21 jmcneill exynos_gpio_pin_ctl(bank, gpin->pin_no, gpin->pin_flags); 486 1.13 marty 487 1.13 marty return gpin; 488 1.13 marty } 489 1.14 marty 490 1.14 marty static void 491 1.14 marty exynos_gpio_fdt_release(device_t dev, void *priv) 492 1.14 marty { 493 1.14 marty struct exynos_gpio_pin *gpin = priv; 494 1.14 marty 495 1.14 marty kmem_free(gpin, sizeof(*gpin)); 496 1.14 marty } 497 1.14 marty 498 1.14 marty static int 499 1.17 jmcneill exynos_gpio_fdt_read(device_t dev, void *priv, bool raw) 500 1.14 marty { 501 1.14 marty struct exynos_gpio_pin *gpin = priv; 502 1.14 marty int val; 503 1.14 marty 504 1.14 marty val = (bus_space_read_1(gpin->pin_sc->sc_bst, 505 1.14 marty gpin->pin_sc->sc_bsh, 506 1.14 marty EXYNOS_GPIO_DAT) >> gpin->pin_no) & 1; 507 1.14 marty 508 1.17 jmcneill if (!raw && gpin->pin_actlo) 509 1.14 marty val = !val; 510 1.14 marty 511 1.14 marty return val; 512 1.14 marty } 513 1.14 marty 514 1.14 marty static void 515 1.17 jmcneill exynos_gpio_fdt_write(device_t dev, void *priv, int val, bool raw) 516 1.14 marty { 517 1.14 marty struct exynos_gpio_pin *gpin = priv; 518 1.14 marty 519 1.17 jmcneill if (!raw && gpin->pin_actlo) 520 1.14 marty val = !val; 521 1.14 marty 522 1.14 marty val = bus_space_read_1(gpin->pin_sc->sc_bst, 523 1.14 marty gpin->pin_sc->sc_bsh, 524 1.14 marty EXYNOS_GPIO_DAT); 525 1.14 marty val &= ~__BIT(gpin->pin_no); 526 1.14 marty if (val) 527 1.14 marty val |= __BIT(gpin->pin_no); 528 1.14 marty bus_space_write_1(gpin->pin_sc->sc_bst, 529 1.14 marty gpin->pin_sc->sc_bsh, 530 1.14 marty EXYNOS_GPIO_DAT, val); 531 1.14 marty 532 1.14 marty } 533