1 /* $OpenBSD: amlpinctrl.c,v 1.6 2020/12/17 19:43:32 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/malloc.h> 22 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_gpio.h> 28 #include <dev/ofw/ofw_pinctrl.h> 29 #include <dev/ofw/fdt.h> 30 31 #define BIAS_DISABLE 0x00 32 #define BIAS_PULL_UP 0x01 33 #define BIAS_PULL_DOWN 0x02 34 35 #define GPIOZ_0 0 36 #define GPIOZ_1 1 37 #define GPIOZ_7 7 38 #define GPIOZ_8 8 39 #define GPIOZ_14 14 40 #define GPIOZ_15 15 41 #define GPIOH_0 16 42 #define GPIOH_1 17 43 #define GPIOH_2 18 44 #define GPIOH_3 19 45 #define GPIOH_6 22 46 #define GPIOH_7 23 47 #define BOOT_0 25 48 #define BOOT_1 26 49 #define BOOT_2 27 50 #define BOOT_3 28 51 #define BOOT_4 29 52 #define BOOT_5 30 53 #define BOOT_6 31 54 #define BOOT_7 32 55 #define BOOT_8 33 56 #define BOOT_10 35 57 #define BOOT_13 38 58 #define GPIOC_0 41 59 #define GPIOC_1 42 60 #define GPIOC_2 43 61 #define GPIOC_3 44 62 #define GPIOC_4 45 63 #define GPIOC_5 46 64 #define GPIOC_6 47 65 #define GPIOA_0 49 66 #define GPIOA_14 63 67 #define GPIOA_15 64 68 #define GPIOX_0 65 69 #define GPIOX_10 75 70 #define GPIOX_11 76 71 #define GPIOX_17 82 72 #define GPIOX_18 83 73 74 #define GPIOAO_0 0 75 #define GPIOAO_1 1 76 #define GPIOAO_5 5 77 #define GPIOE_0 12 78 #define GPIOE_1 13 79 80 #define PERIPHS_PIN_MUX_0 0xb0 81 #define PERIPHS_PIN_MUX_3 0xb3 82 #define PERIPHS_PIN_MUX_6 0xb6 83 #define PERIPHS_PIN_MUX_9 0xb9 84 #define PERIPHS_PIN_MUX_B 0xbb 85 #define PERIPHS_PIN_MUX_D 0xbd 86 #define PREG_PAD_GPIO0_EN_N 0x10 87 #define PREG_PAD_GPIO0_O 0x11 88 #define PREG_PAD_GPIO0_I 0x12 89 #define PREG_PAD_GPIO1_EN_N 0x13 90 #define PREG_PAD_GPIO1_O 0x14 91 #define PREG_PAD_GPIO1_I 0x15 92 #define PREG_PAD_GPIO2_EN_N 0x16 93 #define PREG_PAD_GPIO2_O 0x16 94 #define PREG_PAD_GPIO2_I 0x18 95 #define PREG_PAD_GPIO3_EN_N 0x19 96 #define PREG_PAD_GPIO3_O 0x1a 97 #define PREG_PAD_GPIO3_I 0x1b 98 #define PREG_PAD_GPIO4_EN_N 0x1c 99 #define PREG_PAD_GPIO4_O 0x1d 100 #define PREG_PAD_GPIO4_I 0x1e 101 #define PREG_PAD_GPIO5_EN_N 0x20 102 #define PREG_PAD_GPIO5_O 0x21 103 #define PREG_PAD_GPIO5_I 0x22 104 #define PAD_PULL_UP_EN_0 0x48 105 #define PAD_PULL_UP_EN_1 0x49 106 #define PAD_PULL_UP_EN_2 0x4a 107 #define PAD_PULL_UP_EN_3 0x4b 108 #define PAD_PULL_UP_EN_4 0x4c 109 #define PAD_PULL_UP_EN_5 0x4d 110 #define PAD_PULL_UP_0 0x3a 111 #define PAD_PULL_UP_1 0x3b 112 #define PAD_PULL_UP_2 0x3c 113 #define PAD_PULL_UP_3 0x3d 114 #define PAD_PULL_UP_4 0x3e 115 #define PAD_PULL_UP_5 0x3f 116 #define PAD_DS_0A 0xd0 117 #define PAD_DS_1A 0xd1 118 #define PAD_DS_2A 0xd2 119 #define PAD_DS_3A 0xd4 120 #define PAD_DS_4A 0xd5 121 #define PAD_DS_5A 0xd6 122 123 #define AO_RTI_PINMUX_0 0x05 124 #define AO_RTI_PINMUX_1 0x06 125 #define AO_PAD_DS_A 0x07 126 #define AO_PAD_DS_B 0x08 127 #define AO_GPIO_O_EN_N 0x09 128 #define AO_GPIO_I 0x0a 129 #define AO_GPIO_O 0x0d 130 #define AO_RTI_PULL_UP 0x0b 131 #define AO_RTI_PULL_UP_EN 0x0c 132 133 struct aml_gpio_bank { 134 uint8_t first_pin, num_pins; 135 uint8_t mux_reg, mux_bit; 136 uint8_t dir_reg, dir_bit; 137 uint8_t in_reg, in_bit; 138 uint8_t out_reg, out_bit; 139 uint8_t pull_reg, pull_bit; 140 uint8_t pull_en_reg, pull_en_bit; 141 uint8_t ds_reg, ds_bit; 142 }; 143 144 struct aml_pin_group { 145 const char *name; 146 uint8_t pin; 147 uint8_t func; 148 const char *function; 149 }; 150 151 struct aml_gpio_bank aml_g12a_gpio_banks[] = { 152 /* BOOT */ 153 { BOOT_0, 16, 154 PERIPHS_PIN_MUX_0 - PERIPHS_PIN_MUX_0, 0, 155 PREG_PAD_GPIO0_EN_N - PREG_PAD_GPIO0_EN_N, 0, 156 PREG_PAD_GPIO0_I - PREG_PAD_GPIO0_EN_N, 0, 157 PREG_PAD_GPIO0_O - PREG_PAD_GPIO0_EN_N, 0, 158 PAD_PULL_UP_0 - PAD_PULL_UP_0, 0, 159 PAD_PULL_UP_EN_0 - PAD_PULL_UP_EN_0, 0, 160 PAD_DS_0A - PAD_DS_0A, 0 }, 161 162 /* GPIOC */ 163 { GPIOC_0, 8, 164 PERIPHS_PIN_MUX_9 - PERIPHS_PIN_MUX_0, 0, 165 PREG_PAD_GPIO1_EN_N - PREG_PAD_GPIO0_EN_N, 0, 166 PREG_PAD_GPIO1_I - PREG_PAD_GPIO0_EN_N, 0, 167 PREG_PAD_GPIO1_O - PREG_PAD_GPIO0_EN_N, 0, 168 PAD_PULL_UP_1 - PAD_PULL_UP_0, 0, 169 PAD_PULL_UP_EN_1 - PAD_PULL_UP_EN_0, 0, 170 PAD_DS_1A - PAD_DS_0A, 0 }, 171 172 /* GPIOX */ 173 { GPIOX_0, 20, 174 PERIPHS_PIN_MUX_3 - PERIPHS_PIN_MUX_0, 0, 175 PREG_PAD_GPIO2_EN_N - PREG_PAD_GPIO0_EN_N, 0, 176 PREG_PAD_GPIO2_I - PREG_PAD_GPIO0_EN_N, 0, 177 PREG_PAD_GPIO2_O - PREG_PAD_GPIO0_EN_N, 0, 178 PAD_PULL_UP_2 - PAD_PULL_UP_0, 0, 179 PAD_PULL_UP_EN_2 - PAD_PULL_UP_EN_0, 0, 180 PAD_DS_2A - PAD_DS_0A, 0 }, 181 182 /* GPIOH */ 183 { GPIOH_0, 9, 184 PERIPHS_PIN_MUX_B - PERIPHS_PIN_MUX_0, 0, 185 PREG_PAD_GPIO3_EN_N - PREG_PAD_GPIO0_EN_N, 0, 186 PREG_PAD_GPIO3_I - PREG_PAD_GPIO0_EN_N, 0, 187 PREG_PAD_GPIO3_O - PREG_PAD_GPIO0_EN_N, 0, 188 PAD_PULL_UP_3 - PAD_PULL_UP_0, 0, 189 PAD_PULL_UP_EN_3 - PAD_PULL_UP_EN_0, 0, 190 PAD_DS_3A - PAD_DS_0A, 0 }, 191 192 /* GPIOZ */ 193 { GPIOZ_0, 16, 194 PERIPHS_PIN_MUX_6 - PERIPHS_PIN_MUX_0, 0, 195 PREG_PAD_GPIO4_EN_N - PREG_PAD_GPIO0_EN_N, 0, 196 PREG_PAD_GPIO4_I - PREG_PAD_GPIO0_EN_N, 0, 197 PREG_PAD_GPIO4_O - PREG_PAD_GPIO0_EN_N, 0, 198 PAD_PULL_UP_4 - PAD_PULL_UP_0, 0, 199 PAD_PULL_UP_EN_4 - PAD_PULL_UP_EN_0, 0, 200 PAD_DS_4A - PAD_DS_0A, 0 }, 201 202 /* GPIOA */ 203 { GPIOA_0, 16, 204 PERIPHS_PIN_MUX_D - PERIPHS_PIN_MUX_0, 0, 205 PREG_PAD_GPIO5_EN_N - PREG_PAD_GPIO0_EN_N, 0, 206 PREG_PAD_GPIO5_I - PREG_PAD_GPIO0_EN_N, 0, 207 PREG_PAD_GPIO5_O - PREG_PAD_GPIO0_EN_N, 0, 208 PAD_PULL_UP_5 - PAD_PULL_UP_0, 0, 209 PAD_PULL_UP_EN_5 - PAD_PULL_UP_EN_0, 0, 210 PAD_DS_5A - PAD_DS_0A, 0 }, 211 212 { } 213 }; 214 215 struct aml_pin_group aml_g12a_pin_groups[] = { 216 /* GPIOZ */ 217 { "i2c0_sda_z0", GPIOZ_0, 4, "i2c0" }, 218 { "i2c0_sck_z1", GPIOZ_1, 4, "i2c0" }, 219 { "i2c0_sda_z7", GPIOZ_7, 7, "i2c0" }, 220 { "i2c0_sck_z8", GPIOZ_8, 7, "i2c0" }, 221 { "i2c2_sda_z", GPIOZ_14, 3, "i2c2" }, 222 { "i2c2_sck_z", GPIOZ_15, 3, "i2c2" }, 223 224 /* GPIOA */ 225 { "i2c3_sda_a", GPIOA_14, 2, "i2c3" }, 226 { "i2c3_sck_a", GPIOA_15, 2, "i2c3" }, 227 228 /* BOOT */ 229 { "emmc_nand_d0", BOOT_0, 1, "emmc" }, 230 { "emmc_nand_d1", BOOT_1, 1, "emmc" }, 231 { "emmc_nand_d2", BOOT_2, 1, "emmc" }, 232 { "emmc_nand_d3", BOOT_3, 1, "emmc" }, 233 { "emmc_nand_d4", BOOT_4, 1, "emmc" }, 234 { "emmc_nand_d5", BOOT_5, 1, "emmc" }, 235 { "emmc_nand_d6", BOOT_6, 1, "emmc" }, 236 { "emmc_nand_d7", BOOT_7, 1, "emmc" }, 237 { "BOOT_8", BOOT_8, 0, "gpio_periphs" }, 238 { "emmc_clk", BOOT_8, 1, "emmc" }, 239 { "emmc_cmd", BOOT_10, 1, "emmc" }, 240 { "emmc_nand_ds", BOOT_13, 1, "emmc" }, 241 242 /* GPIOC */ 243 { "sdcard_d0_c", GPIOC_0, 1, "sdcard" }, 244 { "sdcard_d1_c", GPIOC_1, 1, "sdcard" }, 245 { "sdcard_d2_c", GPIOC_2, 1, "sdcard" }, 246 { "sdcard_d3_c", GPIOC_3, 1, "sdcard" }, 247 { "GPIOC_4", GPIOC_4, 0, "gpio_periphs" }, 248 { "sdcard_clk_c", GPIOC_4, 1, "sdcard" }, 249 { "sdcard_cmd_c", GPIOC_5, 1, "sdcard" }, 250 { "i2c0_sda_c", GPIOC_5, 3, "i2c0" }, 251 { "i2c0_sck_c", GPIOC_6, 3, "i2c0" }, 252 253 /* GPIOX */ 254 { "i2c1_sda_x", GPIOX_10, 5, "i2c1" }, 255 { "i2c1_sck_x", GPIOX_11, 5, "i2c1" }, 256 { "i2c2_sda_x", GPIOX_17, 1, "i2c2" }, 257 { "i2c2_sck_x", GPIOX_18, 1, "i2c2" }, 258 259 /* GPIOH */ 260 { "i2c3_sda_h", GPIOH_0, 2, "i2c3" }, 261 { "i2c3_sck_h", GPIOH_1, 2, "i2c3" }, 262 { "i2c1_sda_h2", GPIOH_2, 2, "i2c1" }, 263 { "i2c1_sck_h3", GPIOH_3, 2, "i2c1" }, 264 { "i2c1_sda_h6", GPIOH_6, 4, "i2c1" }, 265 { "i2c1_sck_h7", GPIOH_7, 4, "i2c1" }, 266 267 { } 268 }; 269 270 struct aml_gpio_bank aml_g12a_ao_gpio_banks[] = { 271 /* GPIOAO */ 272 { GPIOAO_0, 12, 273 AO_RTI_PINMUX_0 - AO_RTI_PINMUX_0, 0, 274 AO_GPIO_O_EN_N - AO_GPIO_O_EN_N, 0, 275 AO_GPIO_I - AO_GPIO_O_EN_N, 0, 276 AO_GPIO_O - AO_GPIO_O_EN_N, 0, 277 AO_RTI_PULL_UP - AO_RTI_PULL_UP, 0, 278 AO_RTI_PULL_UP_EN - AO_RTI_PULL_UP_EN, 0, 279 AO_PAD_DS_A - AO_PAD_DS_A, 0 }, 280 281 /* GPIOE */ 282 { GPIOE_0, 3, 283 AO_RTI_PINMUX_1 - AO_RTI_PINMUX_0, 16, 284 AO_GPIO_O_EN_N - AO_GPIO_O_EN_N, 16, 285 AO_GPIO_I - AO_GPIO_O_EN_N, 16, 286 AO_GPIO_O - AO_GPIO_O_EN_N, 16, 287 AO_RTI_PULL_UP - AO_RTI_PULL_UP, 16, 288 AO_RTI_PULL_UP_EN - AO_RTI_PULL_UP_EN, 16, 289 AO_PAD_DS_B - AO_PAD_DS_A, 0 }, 290 291 { } 292 }; 293 294 struct aml_pin_group aml_g12a_ao_pin_groups[] = { 295 /* GPIOAO */ 296 { "uart_ao_a_tx", GPIOAO_0, 1, "uart_ao_a" }, 297 { "uart_ao_a_rx", GPIOAO_1, 1, "uart_ao_a" }, 298 { "remote_ao_input", GPIOAO_5, 1, "remote_ao_input" }, 299 300 /* GPIOE */ 301 { "pwm_ao_d_e", GPIOE_1, 3, "pwm_ao_d" }, 302 303 { } 304 }; 305 306 struct amlpinctrl_softc { 307 struct device sc_dev; 308 bus_space_tag_t sc_iot; 309 bus_space_handle_t sc_gpio_ioh; 310 bus_space_handle_t sc_pull_ioh; 311 bus_space_handle_t sc_pull_en_ioh; 312 bus_space_handle_t sc_mux_ioh; 313 bus_space_handle_t sc_ds_ioh; 314 int sc_nobias; 315 316 struct aml_gpio_bank *sc_gpio_banks; 317 struct aml_pin_group *sc_pin_groups; 318 319 struct gpio_controller sc_gc; 320 }; 321 322 int amlpinctrl_match(struct device *, void *, void *); 323 void amlpinctrl_attach(struct device *, struct device *, void *); 324 325 struct cfattach amlpinctrl_ca = { 326 sizeof(struct amlpinctrl_softc), amlpinctrl_match, amlpinctrl_attach 327 }; 328 329 struct cfdriver amlpinctrl_cd = { 330 NULL, "amlpinctrl", DV_DULL 331 }; 332 333 int amlpinctrl_pinctrl(uint32_t, void *); 334 void amlpinctrl_config_pin(void *, uint32_t *, int); 335 int amlpinctrl_get_pin(void *, uint32_t *); 336 void amlpinctrl_set_pin(void *, uint32_t *, int); 337 338 int 339 amlpinctrl_match(struct device *parent, void *match, void *aux) 340 { 341 struct fdt_attach_args *faa = aux; 342 int node = faa->fa_node; 343 344 return (OF_is_compatible(node, "amlogic,meson-g12a-periphs-pinctrl") || 345 OF_is_compatible(node, "amlogic,meson-g12a-aobus-pinctrl")); 346 } 347 348 void 349 amlpinctrl_attach(struct device *parent, struct device *self, void *aux) 350 { 351 struct amlpinctrl_softc *sc = (struct amlpinctrl_softc *)self; 352 struct fdt_attach_args *faa = aux; 353 uint64_t addr[5], size[5]; 354 uint32_t *cell; 355 uint32_t acells, scells; 356 uint32_t reg[20]; 357 int node = faa->fa_node; 358 int child; 359 int i, len, line; 360 361 for (child = OF_child(node); child; child = OF_peer(child)) { 362 if (OF_getproplen(child, "gpio-controller") == 0) 363 break; 364 } 365 if (child == 0) { 366 printf(": no register banks\n"); 367 return; 368 } 369 370 acells = OF_getpropint(node, "#address-cells", faa->fa_acells); 371 scells = OF_getpropint(node, "#size-cells", faa->fa_scells); 372 len = OF_getproplen(child, "reg"); 373 line = (acells + scells) * sizeof(uint32_t); 374 if (acells < 1 || acells > 2 || scells < 1 || scells > 2 || 375 len > sizeof(reg) || (len / line) > nitems(addr)) { 376 printf(": unexpected register layout\n"); 377 return; 378 } 379 380 memset(&size, 0, sizeof(size)); 381 OF_getpropintarray(child, "reg", reg, len); 382 for (i = 0, cell = reg; i < len / line; i++) { 383 addr[i] = cell[0]; 384 if (acells > 1) 385 addr[i] = (addr[i] << 32) | cell[1]; 386 cell += acells; 387 size[i] = cell[0]; 388 if (scells > 1) 389 size[i] = (size[i] << 32) | cell[1]; 390 cell += scells; 391 } 392 393 sc->sc_iot = faa->fa_iot; 394 395 i = OF_getindex(child, "gpio", "reg-names"); 396 if (i < 0 || i >= nitems(size) || size[i] == 0 || 397 bus_space_map(sc->sc_iot, addr[i], size[i], 0, &sc->sc_gpio_ioh)) { 398 printf(": can't map gpio registers\n"); 399 return; 400 } 401 i = OF_getindex(child, "mux", "reg-names"); 402 if (i < 0 || i >= nitems(size) || size[i] == 0 || 403 bus_space_map(sc->sc_iot, addr[i], size[i], 0, &sc->sc_mux_ioh)) { 404 printf(": can't map mux registers\n"); 405 return; 406 } 407 i = OF_getindex(child, "ds", "reg-names"); 408 if (i < 0 || i >= nitems(size) || size[i] == 0 || 409 bus_space_map(sc->sc_iot, addr[i], size[i], 0, &sc->sc_ds_ioh)) { 410 printf(": can't map ds registers\n"); 411 return; 412 } 413 i = OF_getindex(child, "pull", "reg-names"); 414 if (i < 0) 415 sc->sc_nobias = 1; 416 else if (i >= nitems(size) || size[i] == 0 || 417 bus_space_map(sc->sc_iot, addr[i], size[i], 0, &sc->sc_pull_ioh)) { 418 printf(": can't map pull registers\n"); 419 return; 420 } 421 i = OF_getindex(child, "pull-enable", "reg-names"); 422 if (i < 0) 423 sc->sc_nobias = 1; 424 else if (i >= nitems(size) || size[i] == 0 || 425 bus_space_map(sc->sc_iot, addr[i], size[i], 0, &sc->sc_pull_en_ioh)) { 426 printf(": can't map pull-enable registers\n"); 427 return; 428 } 429 430 printf("\n"); 431 432 if (OF_is_compatible(node, "amlogic,meson-g12a-periphs-pinctrl")) { 433 sc->sc_gpio_banks = aml_g12a_gpio_banks; 434 sc->sc_pin_groups = aml_g12a_pin_groups; 435 } else { 436 sc->sc_gpio_banks = aml_g12a_ao_gpio_banks; 437 sc->sc_pin_groups = aml_g12a_ao_pin_groups; 438 } 439 440 pinctrl_register(faa->fa_node, amlpinctrl_pinctrl, sc); 441 442 sc->sc_gc.gc_node = child; 443 sc->sc_gc.gc_cookie = sc; 444 sc->sc_gc.gc_config_pin = amlpinctrl_config_pin; 445 sc->sc_gc.gc_get_pin = amlpinctrl_get_pin; 446 sc->sc_gc.gc_set_pin = amlpinctrl_set_pin; 447 gpio_controller_register(&sc->sc_gc); 448 } 449 450 struct aml_gpio_bank * 451 amlpinctrl_lookup_bank(struct amlpinctrl_softc *sc, uint32_t pin) 452 { 453 struct aml_gpio_bank *bank; 454 455 for (bank = sc->sc_gpio_banks; bank->num_pins > 0; bank++) { 456 if (pin >= bank->first_pin && 457 pin < bank->first_pin + bank->num_pins) 458 return bank; 459 } 460 461 return NULL; 462 } 463 464 struct aml_pin_group * 465 amlpinctrl_lookup_group(struct amlpinctrl_softc *sc, const char *name) 466 { 467 struct aml_pin_group *group; 468 469 for (group = sc->sc_pin_groups; group->name; group++) { 470 if (strcmp(name, group->name) == 0) 471 return group; 472 } 473 474 return NULL; 475 } 476 477 void 478 amlpinctrl_config_func(struct amlpinctrl_softc *sc, const char *name, 479 const char *function, int bias, int ds) 480 { 481 struct aml_pin_group *group; 482 struct aml_gpio_bank *bank; 483 bus_addr_t off; 484 uint32_t pin; 485 uint32_t reg; 486 487 group = amlpinctrl_lookup_group(sc, name); 488 if (group == NULL) { 489 printf("%s: %s\n", __func__, name); 490 return; 491 } 492 if (strcmp(function, group->function) != 0) { 493 printf("%s: mismatched function %s\n", __func__, function); 494 return; 495 } 496 497 bank = amlpinctrl_lookup_bank(sc, group->pin); 498 KASSERT(bank); 499 500 pin = group->pin - bank->first_pin; 501 502 /* mux */ 503 off = (bank->mux_reg + pin / 8) << 2; 504 reg = bus_space_read_4(sc->sc_iot, sc->sc_mux_ioh, off); 505 reg &= ~(0xf << (((pin % 8) * 4) + bank->mux_bit)); 506 reg |= (group->func << (((pin % 8) * 4) + bank->mux_bit)); 507 bus_space_write_4(sc->sc_iot, sc->sc_mux_ioh, off, reg); 508 509 if (!sc->sc_nobias) { 510 /* pull */ 511 off = bank->pull_reg << 2; 512 reg = bus_space_read_4(sc->sc_iot, sc->sc_pull_ioh, off); 513 if (bias == BIAS_PULL_UP) 514 reg |= (1 << (pin + bank->pull_bit)); 515 else 516 reg &= ~(1 << (pin + bank->pull_bit)); 517 bus_space_write_4(sc->sc_iot, sc->sc_pull_ioh, off, reg); 518 519 /* pull-enable */ 520 off = bank->pull_en_reg << 2; 521 reg = bus_space_read_4(sc->sc_iot, sc->sc_pull_en_ioh, off); 522 if (bias != BIAS_DISABLE) 523 reg |= (1 << (pin + bank->pull_en_bit)); 524 else 525 reg &= ~(1 << (pin + bank->pull_en_bit)); 526 bus_space_write_4(sc->sc_iot, sc->sc_pull_en_ioh, off, reg); 527 } 528 529 if (ds < 0) 530 return; 531 else if (ds <= 500) 532 ds = 0; 533 else if (ds <= 2500) 534 ds = 1; 535 else if (ds <= 3000) 536 ds = 2; 537 else if (ds <= 4000) 538 ds = 3; 539 else { 540 printf("%s: invalid drive-strength %d\n", __func__, ds); 541 ds = 3; 542 } 543 544 /* ds */ 545 off = (bank->ds_reg + pin / 16) << 2; 546 reg = bus_space_read_4(sc->sc_iot, sc->sc_ds_ioh, off); 547 reg &= ~(0x3 << (((pin % 16) * 2) + bank->ds_bit)); 548 reg |= (ds << (((pin % 16) * 2) + bank->ds_bit)); 549 bus_space_write_4(sc->sc_iot, sc->sc_ds_ioh, off, reg); 550 } 551 552 int 553 amlpinctrl_pinctrl(uint32_t phandle, void *cookie) 554 { 555 struct amlpinctrl_softc *sc = cookie; 556 int node, child; 557 558 node = OF_getnodebyphandle(phandle); 559 if (node == 0) 560 return -1; 561 562 for (child = OF_child(node); child; child = OF_peer(child)) { 563 char function[16]; 564 char *groups; 565 char *group; 566 int bias, ds; 567 int len; 568 569 memset(function, 0, sizeof(function)); 570 OF_getprop(child, "function", function, sizeof(function)); 571 function[sizeof(function) - 1] = 0; 572 573 /* Bias */ 574 if (OF_getproplen(child, "bias-pull-up") == 0) 575 bias = BIAS_PULL_UP; 576 else if (OF_getproplen(child, "bias-pull-down") == 0) 577 bias = BIAS_PULL_DOWN; 578 else 579 bias = BIAS_DISABLE; 580 581 /* Drive-strength */ 582 ds = OF_getpropint(child, "drive-strength-microamp", -1); 583 584 len = OF_getproplen(child, "groups"); 585 if (len <= 0) { 586 printf("%s: 0x%08x\n", __func__, phandle); 587 continue; 588 } 589 590 groups = malloc(len, M_TEMP, M_WAITOK); 591 OF_getprop(child, "groups", groups, len); 592 593 group = groups; 594 while (group < groups + len) { 595 amlpinctrl_config_func(sc, group, function, bias, ds); 596 group += strlen(group) + 1; 597 } 598 599 free(groups, M_TEMP, len); 600 } 601 602 return 0; 603 } 604 605 void 606 amlpinctrl_config_pin(void *cookie, uint32_t *cells, int config) 607 { 608 struct amlpinctrl_softc *sc = cookie; 609 struct aml_gpio_bank *bank; 610 bus_addr_t off; 611 uint32_t pin = cells[0]; 612 uint32_t reg; 613 614 bank = amlpinctrl_lookup_bank(sc, pin); 615 if (bank == NULL) { 616 printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], cells[1]); 617 return; 618 } 619 620 pin = pin - bank->first_pin; 621 622 /* mux */ 623 off = (bank->mux_reg + pin / 8) << 2; 624 reg = bus_space_read_4(sc->sc_iot, sc->sc_mux_ioh, off); 625 reg &= ~(0xf << (((pin % 8) * 4) + bank->mux_bit)); 626 bus_space_write_4(sc->sc_iot, sc->sc_mux_ioh, off, reg); 627 628 /* gpio */ 629 off = bank->dir_reg << 2; 630 reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, off); 631 if (config & GPIO_CONFIG_OUTPUT) 632 reg &= ~(1 << (pin + bank->dir_bit)); 633 else 634 reg |= (1 << (pin + bank->dir_bit)); 635 bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh, off, reg); 636 } 637 638 int 639 amlpinctrl_get_pin(void *cookie, uint32_t *cells) 640 { 641 struct amlpinctrl_softc *sc = cookie; 642 struct aml_gpio_bank *bank; 643 bus_addr_t off; 644 uint32_t pin = cells[0]; 645 uint32_t flags = cells[1]; 646 uint32_t reg; 647 int val; 648 649 bank = amlpinctrl_lookup_bank(sc, pin); 650 if (bank == NULL) { 651 printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], cells[1]); 652 return 0; 653 } 654 655 pin = pin - bank->first_pin; 656 657 /* gpio */ 658 off = bank->in_reg << 2; 659 reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, off); 660 val = (reg >> (pin + bank->in_bit)) & 1; 661 if (flags & GPIO_ACTIVE_LOW) 662 val = !val; 663 664 return val; 665 } 666 667 void 668 amlpinctrl_set_pin(void *cookie, uint32_t *cells, int val) 669 { 670 struct amlpinctrl_softc *sc = cookie; 671 struct aml_gpio_bank *bank; 672 bus_addr_t off; 673 uint32_t pin = cells[0]; 674 uint32_t flags = cells[1]; 675 int reg; 676 677 bank = amlpinctrl_lookup_bank(sc, pin); 678 if (bank == NULL) { 679 printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], cells[1]); 680 return; 681 } 682 683 if (flags & GPIO_ACTIVE_LOW) 684 val = !val; 685 686 pin = pin - bank->first_pin; 687 688 /* gpio */ 689 off = bank->out_reg << 2; 690 reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, off); 691 if (val) 692 reg |= (1 << (pin + bank->out_bit)); 693 else 694 reg &= ~(1 << (pin + bank->out_bit)); 695 bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh, off, reg); 696 } 697