1 /* $OpenBSD: rkpinctrl.c,v 1.4 2017/07/23 17:08:29 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2017 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/intr.h> 24 #include <machine/bus.h> 25 #include <machine/fdt.h> 26 27 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/ofw_misc.h> 29 #include <dev/ofw/ofw_pinctrl.h> 30 #include <dev/ofw/fdt.h> 31 32 #ifdef __armv7__ 33 #include <arm/simplebus/simplebusvar.h> 34 #else 35 #include <arm64/dev/simplebusvar.h> 36 #endif 37 38 /* RK3288 registers */ 39 #define RK3288_GRF_GPIO1A_IOMUX 0x0000 40 #define RK3288_PMUGRF_GPIO0A_IOMUX 0x0084 41 42 /* RK3399 registers */ 43 #define RK3399_GRF_GPIO2A_IOMUX 0xe000 44 #define RK3399_PMUGRF_GPIO0A_IOMUX 0x0000 45 46 struct rkpinctrl_softc { 47 struct simplebus_softc sc_sbus; 48 49 struct regmap *sc_grf; 50 struct regmap *sc_pmu; 51 }; 52 53 int rkpinctrl_match(struct device *, void *, void *); 54 void rkpinctrl_attach(struct device *, struct device *, void *); 55 56 struct cfattach rkpinctrl_ca = { 57 sizeof (struct rkpinctrl_softc), rkpinctrl_match, rkpinctrl_attach 58 }; 59 60 struct cfdriver rkpinctrl_cd = { 61 NULL, "rkpinctrl", DV_DULL 62 }; 63 64 int rk3288_pinctrl(uint32_t, void *); 65 int rk3399_pinctrl(uint32_t, void *); 66 67 int 68 rkpinctrl_match(struct device *parent, void *match, void *aux) 69 { 70 struct fdt_attach_args *faa = aux; 71 72 return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") || 73 OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl")); 74 } 75 76 void 77 rkpinctrl_attach(struct device *parent, struct device *self, void *aux) 78 { 79 struct rkpinctrl_softc *sc = (struct rkpinctrl_softc *)self; 80 struct fdt_attach_args *faa = aux; 81 uint32_t grf, pmu; 82 83 grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0); 84 pmu = OF_getpropint(faa->fa_node, "rockchip,pmu", 0); 85 sc->sc_grf = regmap_byphandle(grf); 86 sc->sc_pmu = regmap_byphandle(pmu); 87 88 if (sc->sc_grf == NULL || sc->sc_pmu == NULL) { 89 printf(": no registers\n"); 90 return; 91 } 92 93 if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl")) 94 pinctrl_register(faa->fa_node, rk3288_pinctrl, sc); 95 else 96 pinctrl_register(faa->fa_node, rk3399_pinctrl, sc); 97 98 /* Attach GPIO banks. */ 99 simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa); 100 } 101 102 /* 103 * Rockchip RK3288 104 */ 105 106 int 107 rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 108 { 109 int node; 110 111 node = OF_getnodebyphandle(phandle); 112 if (node == 0) 113 return -1; 114 115 /* XXX */ 116 if (bank == 0) 117 return -1; 118 119 if (OF_getproplen(node, "bias-disable") == 0) 120 return 0; 121 if (OF_getproplen(node, "bias-pull-up") == 0) 122 return 1; 123 if (OF_getproplen(node, "bias-pull-down") == 0) 124 return 2; 125 126 return -1; 127 } 128 129 int 130 rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 131 { 132 int strength, level; 133 int levels[4] = { 2, 4, 8, 12 }; 134 int node; 135 136 node = OF_getnodebyphandle(phandle); 137 if (node == 0) 138 return -1; 139 140 /* XXX */ 141 if (bank == 0) 142 return -1; 143 144 strength = OF_getpropint(node, "drive-strength", -1); 145 if (strength == -1) 146 return -1; 147 148 /* Convert drive strength to level. */ 149 for (level = 3; level >= 0; level--) { 150 if (strength >= levels[level]) 151 break; 152 } 153 return level; 154 } 155 156 int 157 rk3288_pinctrl(uint32_t phandle, void *cookie) 158 { 159 struct rkpinctrl_softc *sc = cookie; 160 uint32_t *pins; 161 int node, len, i; 162 163 node = OF_getnodebyphandle(phandle); 164 if (node == 0) 165 return -1; 166 167 len = OF_getproplen(node, "rockchip,pins"); 168 if (len <= 0) 169 return -1; 170 171 pins = malloc(len, M_TEMP, M_WAITOK); 172 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 173 goto fail; 174 175 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 176 struct regmap *rm; 177 bus_size_t base, off; 178 uint32_t bank, idx, mux; 179 int pull, strength; 180 uint32_t mask, bits; 181 int s; 182 183 bank = pins[i]; 184 idx = pins[i + 1]; 185 mux = pins[i + 2]; 186 pull = rk3288_pull(bank, idx, pins[i + 3]); 187 strength = rk3288_strength(bank, idx, pins[i + 3]); 188 189 if (bank > 8 || idx > 32 || mux > 7) 190 continue; 191 192 /* Bank 0 lives in the PMU. */ 193 if (bank < 1) { 194 rm = sc->sc_pmu; 195 base = RK3288_PMUGRF_GPIO0A_IOMUX; 196 } else { 197 rm = sc->sc_grf; 198 base = RK3288_GRF_GPIO1A_IOMUX - 0x10; 199 } 200 201 s = splhigh(); 202 203 /* IOMUX control */ 204 off = bank * 0x10 + (idx / 8) * 0x04; 205 206 /* GPIO3D, GPIO4A and GPIO4B are special. */ 207 if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) { 208 mask = (0x7 << ((idx % 4) * 4)); 209 bits = (mux << ((idx % 4) * 4)); 210 } else { 211 mask = (0x3 << ((idx % 8) * 2)); 212 bits = (mux << ((idx % 8) * 2)); 213 } 214 if (bank > 3 || (bank == 3 && idx >= 28)) 215 off += 0x04; 216 if (bank > 4 || (bank == 4 && idx >= 4)) 217 off += 0x04; 218 if (bank > 4 || (bank == 4 && idx >= 12)) 219 off += 0x04; 220 regmap_write_4(rm, base + off, mask << 16 | bits); 221 222 /* GPIO pad pull down and pull up control */ 223 if (pull >= 0) { 224 off = 0x140 + bank * 0x10 + (idx / 8) * 0x04; 225 mask = (0x3 << ((idx % 8) * 2)); 226 bits = (pull << ((idx % 8) * 2)); 227 regmap_write_4(rm, base + off, mask << 16 | bits); 228 } 229 230 /* GPIO drive strength control */ 231 if (strength >= 0) { 232 off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04; 233 mask = (0x3 << ((idx % 8) * 2)); 234 bits = (strength << ((idx % 8) * 2)); 235 regmap_write_4(rm, base + off, mask << 16 | bits); 236 } 237 238 splx(s); 239 } 240 241 free(pins, M_TEMP, len); 242 return 0; 243 244 fail: 245 free(pins, M_TEMP, len); 246 return -1; 247 } 248 249 /* 250 * Rockchip RK3399 251 */ 252 253 int 254 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 255 { 256 int pull_up, pull_down; 257 int node; 258 259 node = OF_getnodebyphandle(phandle); 260 if (node == 0) 261 return -1; 262 263 if (bank == 2 && idx >= 16) { 264 pull_up = 3; 265 pull_down = 1; 266 } else { 267 pull_up = 1; 268 pull_down = 2; 269 } 270 271 if (OF_getproplen(node, "bias-disable") == 0) 272 return 0; 273 if (OF_getproplen(node, "bias-pull-up") == 0) 274 return pull_up; 275 if (OF_getproplen(node, "bias-pull-down") == 0) 276 return pull_down; 277 278 return -1; 279 } 280 281 /* Magic because the drive strength configurations vary wildly. */ 282 283 int rk3399_strength_levels[][8] = { 284 { 2, 4, 8, 12 }, /* default */ 285 { 3, 6, 9, 12 }, /* 1.8V or 3.0V */ 286 { 5, 10, 15, 20 }, /* 1.8V only */ 287 { 4, 6, 8, 10, 12, 14, 16, 18 }, /* 1.8V or 3.0V auto */ 288 { 4, 7, 10, 13, 16, 19, 22, 26 }, /* 3.3V */ 289 }; 290 291 int rk3399_strength_types[][4] = { 292 { 2, 2, 0, 0 }, 293 { 1, 1, 1, 1 }, 294 { 1, 1, 2, 2 }, 295 { 4, 4, 4, 1 }, 296 { 1, 3, 1, 1 }, 297 }; 298 299 int rk3399_strength_regs[][4] = { 300 { 0x0080, 0x0088, 0x0090, 0x0098 }, 301 { 0x00a0, 0x00a8, 0x00b0, 0x00b8 }, 302 { 0x0100, 0x0104, 0x0108, 0x010c }, 303 { 0x0110, 0x0118, 0x0120, 0x0128 }, 304 { 0x012c, 0x0130, 0x0138, 0x013c }, 305 }; 306 307 int 308 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 309 { 310 int strength, type, level; 311 int *levels; 312 int node; 313 314 node = OF_getnodebyphandle(phandle); 315 if (node == 0) 316 return -1; 317 318 strength = OF_getpropint(node, "drive-strength", -1); 319 if (strength == -1) 320 return -1; 321 322 /* Convert drive strength to level. */ 323 type = rk3399_strength_types[bank][idx / 8]; 324 levels = rk3399_strength_levels[type]; 325 for (level = 7; level >= 0; level--) { 326 if (strength >= levels[level] && levels[level] > 0) 327 break; 328 } 329 return level; 330 } 331 332 int 333 rk3399_pinctrl(uint32_t phandle, void *cookie) 334 { 335 struct rkpinctrl_softc *sc = cookie; 336 uint32_t *pins; 337 int node, len, i; 338 339 node = OF_getnodebyphandle(phandle); 340 if (node == 0) 341 return -1; 342 343 len = OF_getproplen(node, "rockchip,pins"); 344 if (len <= 0) 345 return -1; 346 347 pins = malloc(len, M_TEMP, M_WAITOK); 348 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 349 goto fail; 350 351 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 352 struct regmap *rm; 353 bus_size_t base, off; 354 uint32_t bank, idx, mux; 355 int pull, strength, type, shift; 356 uint32_t mask, bits; 357 int s; 358 359 bank = pins[i]; 360 idx = pins[i + 1]; 361 mux = pins[i + 2]; 362 pull = rk3399_pull(bank, idx, pins[i + 3]); 363 strength = rk3399_strength(bank, idx, pins[i + 3]); 364 365 if (bank > 5 || idx > 32 || mux > 3) 366 continue; 367 368 /* Bank 0 and 1 live in the PMU. */ 369 if (bank < 2) { 370 rm = sc->sc_pmu; 371 base = RK3399_PMUGRF_GPIO0A_IOMUX; 372 } else { 373 rm = sc->sc_grf; 374 base = RK3399_GRF_GPIO2A_IOMUX - 0x20; 375 } 376 377 s = splhigh(); 378 379 /* IOMUX control */ 380 off = bank * 0x10 + (idx / 8) * 0x04; 381 mask = (0x3 << ((idx % 8) * 2)); 382 bits = (mux << ((idx % 8) * 2)); 383 regmap_write_4(rm, base + off, mask << 16 | bits); 384 385 /* GPIO pad pull down and pull up control */ 386 if (pull >= 0) { 387 off = 0x40 + bank * 0x10 + (idx / 8) * 0x04; 388 mask = (0x3 << ((idx % 8) * 2)); 389 bits = (pull << ((idx % 8) * 2)); 390 regmap_write_4(rm, base + off, mask << 16 | bits); 391 } 392 393 /* GPIO drive strength control */ 394 if (strength >= 0) { 395 off = rk3399_strength_regs[bank][idx / 8]; 396 type = rk3399_strength_types[bank][idx / 8]; 397 shift = (type > 2) ? 3 : 2; 398 mask = (((1 << shift) - 1) << ((idx % 8) * shift)); 399 bits = (strength << ((idx % 8) * shift)); 400 if (mask & 0x0000ffff) { 401 regmap_write_4(rm, base + off, 402 mask << 16 | (bits & 0x0000ffff)); 403 } 404 if (mask & 0xffff0000) { 405 regmap_write_4(rm, base + off + 0x04, 406 (mask & 0xffff0000) | bits >> 16); 407 } 408 } 409 410 splx(s); 411 } 412 413 free(pins, M_TEMP, len); 414 return 0; 415 416 fail: 417 free(pins, M_TEMP, len); 418 return -1; 419 } 420