1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/bus.h> 34 #include <sys/kernel.h> 35 #include <sys/module.h> 36 #include <sys/mutex.h> 37 #include <sys/rman.h> 38 #include <machine/bus.h> 39 40 #include <dev/iicbus/iiconf.h> 41 #include <dev/iicbus/iicbus.h> 42 43 #include <dev/ofw/ofw_bus.h> 44 #include <dev/ofw/ofw_bus_subr.h> 45 46 #include <dev/extres/regulator/regulator.h> 47 48 #include <dev/iicbus/pmic/act8846.h> 49 50 #include "regdev_if.h" 51 52 MALLOC_DEFINE(M_ACT8846_REG, "ACT8846 regulator", "ACT8846 power regulator"); 53 54 #if 0 55 #define dprintf(sc, format, arg...) 56 device_printf(sc->base_sc->dev, "%s: " format, __func__, arg) */ 57 #else 58 #define dprintf(sc, format, arg...) 59 #endif 60 61 enum act8846_reg_id { 62 ACT8846_REG_ID_REG1, 63 ACT8846_REG_ID_REG2, 64 ACT8846_REG_ID_REG3, 65 ACT8846_REG_ID_REG4, 66 ACT8846_REG_ID_REG5, 67 ACT8846_REG_ID_REG6, 68 ACT8846_REG_ID_REG7, 69 ACT8846_REG_ID_REG8, 70 ACT8846_REG_ID_REG9, 71 ACT8846_REG_ID_REG10, 72 ACT8846_REG_ID_REG11, 73 ACT8846_REG_ID_REG12, 74 ACT8846_REG_ID_REG13, 75 }; 76 77 struct act8846_regdef { 78 intptr_t id; /* ID */ 79 char *name; /* Regulator name */ 80 char *supply_name; /* Source property name */ 81 uint8_t enable_reg; 82 uint8_t enable_mask; 83 uint8_t voltage_reg; 84 uint8_t voltage_mask; 85 struct regulator_range *ranges; 86 int nranges; 87 }; 88 struct act8846_softc; 89 90 struct act8846_reg_sc { 91 struct regnode *regnode; 92 struct act8846_softc *base_sc; 93 struct act8846_regdef *def; 94 phandle_t xref; 95 struct regnode_std_param *param; 96 }; 97 98 99 static struct regulator_range act8846_ranges[] = { 100 REG_RANGE_INIT( 0, 23, 600000, 25000), 101 REG_RANGE_INIT( 24, 47, 1200000, 50000), 102 REG_RANGE_INIT( 48, 64, 2400000, 100000), 103 }; 104 105 static struct act8846_regdef act8846_regdefs[] = { 106 { 107 .id = ACT8846_REG_ID_REG1, 108 .name = "REG1", 109 .supply_name = "vp1", 110 .enable_reg = ACT8846_REG1_CTRL, 111 .enable_mask = ACT8846_CTRL_ENA, 112 }, 113 { 114 .id = ACT8846_REG_ID_REG2, 115 .name = "REG2", 116 .supply_name = "vp2", 117 .enable_reg = ACT8846_REG2_CTRL, 118 .enable_mask = ACT8846_CTRL_ENA, 119 .voltage_reg = ACT8846_REG2_VSET0, 120 .voltage_mask = ACT8846_VSEL_MASK, 121 .ranges = act8846_ranges, 122 .nranges = nitems(act8846_ranges), 123 }, 124 { 125 .id = ACT8846_REG_ID_REG3, 126 .name = "REG3", 127 .supply_name = "vp3", 128 .enable_reg = ACT8846_REG3_CTRL, 129 .enable_mask = ACT8846_CTRL_ENA, 130 .voltage_reg = ACT8846_REG3_VSET0, 131 .voltage_mask = ACT8846_VSEL_MASK, 132 .ranges = act8846_ranges, 133 .nranges = nitems(act8846_ranges), 134 }, 135 { 136 .id = ACT8846_REG_ID_REG4, 137 .name = "REG4", 138 .supply_name = "vp4", 139 .enable_reg = ACT8846_REG4_CTRL, 140 .enable_mask = ACT8846_CTRL_ENA, 141 .voltage_reg = ACT8846_REG4_VSET0, 142 .voltage_mask = ACT8846_VSEL_MASK, 143 .ranges = act8846_ranges, 144 .nranges = nitems(act8846_ranges), 145 }, 146 { 147 .id = ACT8846_REG_ID_REG5, 148 .name = "REG5", 149 .supply_name = "inl1", 150 .enable_reg = ACT8846_REG5_CTRL, 151 .enable_mask = ACT8846_CTRL_ENA, 152 .voltage_reg = ACT8846_REG5_VSET, 153 .voltage_mask = ACT8846_VSEL_MASK, 154 .ranges = act8846_ranges, 155 .nranges = nitems(act8846_ranges), 156 }, 157 { 158 .id = ACT8846_REG_ID_REG6, 159 .name = "REG6", 160 .supply_name = "inl1", 161 .enable_reg = ACT8846_REG6_CTRL, 162 .enable_mask = ACT8846_CTRL_ENA, 163 .voltage_reg = ACT8846_REG6_VSET, 164 .voltage_mask = ACT8846_VSEL_MASK, 165 .ranges = act8846_ranges, 166 .nranges = nitems(act8846_ranges), 167 }, 168 { 169 .id = ACT8846_REG_ID_REG7, 170 .name = "REG7", 171 .supply_name = "inl1", 172 .enable_reg = ACT8846_REG7_CTRL, 173 .enable_mask = ACT8846_CTRL_ENA, 174 .voltage_reg = ACT8846_REG7_VSET, 175 .voltage_mask = ACT8846_VSEL_MASK, 176 .ranges = act8846_ranges, 177 .nranges = nitems(act8846_ranges), 178 }, 179 { 180 .id = ACT8846_REG_ID_REG8, 181 .name = "REG8", 182 .supply_name = "inl2", 183 .enable_reg = ACT8846_REG8_CTRL, 184 .enable_mask = ACT8846_CTRL_ENA, 185 .voltage_reg = ACT8846_REG8_VSET, 186 .voltage_mask = ACT8846_VSEL_MASK, 187 .ranges = act8846_ranges, 188 .nranges = nitems(act8846_ranges), 189 }, 190 { 191 .id = ACT8846_REG_ID_REG9, 192 .name = "REG9", 193 .supply_name = "inl2", 194 .enable_reg = ACT8846_REG9_CTRL, 195 .enable_mask = ACT8846_CTRL_ENA, 196 .voltage_reg = ACT8846_REG9_VSET, 197 .voltage_mask = ACT8846_VSEL_MASK, 198 .ranges = act8846_ranges, 199 .nranges = nitems(act8846_ranges), 200 }, 201 { 202 .id = ACT8846_REG_ID_REG10, 203 .name = "REG10", 204 .supply_name = "inl3", 205 .enable_reg = ACT8846_REG10_CTRL, 206 .enable_mask = ACT8846_CTRL_ENA, 207 .voltage_reg = ACT8846_REG10_VSET, 208 .voltage_mask = ACT8846_VSEL_MASK, 209 .ranges = act8846_ranges, 210 .nranges = nitems(act8846_ranges), 211 }, 212 { 213 .id = ACT8846_REG_ID_REG11, 214 .name = "REG11", 215 .supply_name = "inl3", 216 .enable_reg = ACT8846_REG11_CTRL, 217 .enable_mask = ACT8846_CTRL_ENA, 218 .voltage_reg = ACT8846_REG11_VSET, 219 .voltage_mask = ACT8846_VSEL_MASK, 220 .ranges = act8846_ranges, 221 .nranges = nitems(act8846_ranges), 222 }, 223 { 224 .id = ACT8846_REG_ID_REG12, 225 .name = "REG12", 226 .supply_name = "inl3", 227 .enable_reg = ACT8846_REG12_CTRL, 228 .enable_mask = ACT8846_CTRL_ENA, 229 .voltage_reg = ACT8846_REG12_VSET, 230 .voltage_mask = ACT8846_VSEL_MASK, 231 .ranges = act8846_ranges, 232 .nranges = nitems(act8846_ranges), 233 }, 234 { 235 .id = ACT8846_REG_ID_REG13, 236 .name = "REG13", 237 .supply_name = "inl1", 238 .enable_reg = ACT8846_REG13_CTRL, 239 .enable_mask = ACT8846_CTRL_ENA, 240 }, 241 }; 242 243 static int 244 act8846_read_sel(struct act8846_reg_sc *sc, uint8_t *sel) 245 { 246 int rv; 247 248 rv = RD1(sc->base_sc, sc->def->voltage_reg, sel); 249 if (rv != 0) 250 return (rv); 251 *sel &= sc->def->voltage_mask; 252 *sel >>= ffs(sc->def->voltage_mask) - 1; 253 return (0); 254 } 255 256 static int 257 act8846_write_sel(struct act8846_reg_sc *sc, uint8_t sel) 258 { 259 int rv; 260 261 sel <<= ffs(sc->def->voltage_mask) - 1; 262 sel &= sc->def->voltage_mask; 263 264 rv = RM1(sc->base_sc, sc->def->voltage_reg, 265 sc->def->voltage_mask, sel); 266 if (rv != 0) 267 return (rv); 268 return (rv); 269 } 270 271 static int 272 act8846_regnode_init(struct regnode *regnode) 273 { 274 return (0); 275 } 276 277 static int 278 act8846_regnode_enable(struct regnode *regnode, bool enable, int *udelay) 279 { 280 struct act8846_reg_sc *sc; 281 int rv; 282 283 sc = regnode_get_softc(regnode); 284 285 dprintf(sc, "%sabling regulator %s\n", 286 enable ? "En" : "Dis", 287 sc->def->name); 288 rv = RM1(sc->base_sc, sc->def->enable_reg, 289 sc->def->enable_mask, enable ? sc->def->enable_mask: 0); 290 *udelay = sc->param->enable_delay; 291 292 return (rv); 293 } 294 295 static int 296 act8846_regnode_set_voltage(struct regnode *regnode, int min_uvolt, 297 int max_uvolt, int *udelay) 298 { 299 struct act8846_reg_sc *sc; 300 uint8_t sel; 301 int uvolt, rv; 302 303 sc = regnode_get_softc(regnode); 304 305 if (sc->def->ranges == NULL) 306 return (ENXIO); 307 308 dprintf(sc, "Setting %s to %d<->%d uvolts\n", 309 sc->def->name, 310 min_uvolt, 311 max_uvolt); 312 rv = regulator_range_volt_to_sel8(sc->def->ranges, sc->def->nranges, 313 min_uvolt, max_uvolt, &sel); 314 if (rv != 0) 315 return (rv); 316 *udelay = sc->param->ramp_delay; 317 rv = act8846_write_sel(sc, sel); 318 319 act8846_read_sel(sc, &sel); 320 regulator_range_sel8_to_volt(sc->def->ranges, sc->def->nranges, 321 sel, &uvolt); 322 dprintf(sc, "Regulator %s set to %d uvolt\n", sc->def->name, 323 uvolt); 324 325 return (rv); 326 } 327 328 static int 329 act8846_regnode_get_voltage(struct regnode *regnode, int *uvolt) 330 { 331 struct act8846_reg_sc *sc; 332 uint8_t sel; 333 int rv; 334 335 sc = regnode_get_softc(regnode); 336 337 if (sc->def->ranges == NULL) { 338 if (sc->def->id == ACT8846_REG_ID_REG13) { 339 *uvolt = 1800000; 340 return (0); 341 } 342 return (ENXIO); 343 } 344 345 rv = act8846_read_sel(sc, &sel); 346 if (rv != 0) 347 return (rv); 348 rv = regulator_range_sel8_to_volt(sc->def->ranges, sc->def->nranges, 349 sel, uvolt); 350 dprintf(sc, "Regulator %s is at %d uvolt\n", sc->def->name, 351 *uvolt); 352 353 return (rv); 354 } 355 356 static regnode_method_t act8846_regnode_methods[] = { 357 /* Regulator interface */ 358 REGNODEMETHOD(regnode_init, act8846_regnode_init), 359 REGNODEMETHOD(regnode_enable, act8846_regnode_enable), 360 REGNODEMETHOD(regnode_set_voltage, act8846_regnode_set_voltage), 361 REGNODEMETHOD(regnode_get_voltage, act8846_regnode_get_voltage), 362 REGNODEMETHOD_END 363 }; 364 DEFINE_CLASS_1(act8846_regnode, act8846_regnode_class, act8846_regnode_methods, 365 sizeof(struct act8846_reg_sc), regnode_class); 366 367 static int 368 act8846_fdt_parse(struct act8846_softc *sc, phandle_t pnode, phandle_t node, 369 struct act8846_regdef *def, struct regnode_init_def *init_def) 370 { 371 int rv; 372 phandle_t supply_node; 373 char prop_name[64]; /* Maximum OFW property name length. */ 374 375 rv = regulator_parse_ofw_stdparam(sc->dev, node, init_def); 376 377 /* Get parent supply. */ 378 if (def->supply_name == NULL) 379 return (0); 380 381 snprintf(prop_name, sizeof(prop_name), "%s-supply", 382 def->supply_name); 383 rv = OF_getencprop(pnode, prop_name, &supply_node, 384 sizeof(supply_node)); 385 if (rv <= 0) 386 return (rv); 387 supply_node = OF_node_from_xref(supply_node); 388 rv = OF_getprop_alloc(supply_node, "regulator-name", 389 (void **)&init_def->parent_name); 390 if (rv <= 0) 391 init_def->parent_name = NULL; 392 return (0); 393 } 394 395 static struct act8846_reg_sc * 396 act8846_attach(struct act8846_softc *sc, phandle_t pnode, phandle_t node, 397 struct act8846_regdef *def) 398 { 399 struct act8846_reg_sc *reg_sc; 400 struct regnode_init_def initdef; 401 struct regnode *regnode; 402 403 memset(&initdef, 0, sizeof(initdef)); 404 if (act8846_fdt_parse(sc, pnode, node, def, &initdef) != 0) { 405 device_printf(sc->dev, "cannot parse FDT data for regulator\n"); 406 return (NULL); 407 } 408 initdef.id = def->id; 409 initdef.ofw_node = node; 410 411 regnode = regnode_create(sc->dev, &act8846_regnode_class, &initdef); 412 if (regnode == NULL) { 413 device_printf(sc->dev, "cannot create regulator\n"); 414 return (NULL); 415 } 416 417 reg_sc = regnode_get_softc(regnode); 418 reg_sc->base_sc = sc; 419 reg_sc->def = def; 420 reg_sc->xref = OF_xref_from_node(node); 421 reg_sc->param = regnode_get_stdparam(regnode); 422 423 regnode_register(regnode); 424 425 if (bootverbose) { 426 int volt, rv; 427 regnode_topo_slock(); 428 rv = regnode_get_voltage(regnode, &volt); 429 if (rv == ENODEV) { 430 device_printf(sc->dev, 431 " Regulator %s: parent doesn't exist yet.\n", 432 regnode_get_name(regnode)); 433 } else if (rv != 0) { 434 device_printf(sc->dev, 435 " Regulator %s: voltage: INVALID!!!\n", 436 regnode_get_name(regnode)); 437 } else { 438 device_printf(sc->dev, 439 " Regulator %s: voltage: %d uV\n", 440 regnode_get_name(regnode), volt); 441 } 442 regnode_topo_unlock(); 443 } 444 445 return (reg_sc); 446 } 447 448 449 int 450 act8846_regulator_attach(struct act8846_softc *sc, phandle_t node) 451 { 452 struct act8846_reg_sc *reg; 453 phandle_t child, rnode; 454 int i; 455 456 rnode = ofw_bus_find_child(node, "regulators"); 457 if (rnode <= 0) { 458 device_printf(sc->dev, " Cannot find regulators subnode\n"); 459 return (ENXIO); 460 } 461 462 /* ACT8846 specific definitio. */ 463 sc->nregs = nitems(act8846_regdefs); 464 sc->regs = malloc(sizeof(struct act8846_reg_sc *) * sc->nregs, 465 M_ACT8846_REG, M_WAITOK | M_ZERO); 466 467 468 /* Attach all known regulators if exist in DT. */ 469 for (i = 0; i < sc->nregs; i++) { 470 child = ofw_bus_find_child(rnode, act8846_regdefs[i].name); 471 if (child == 0) { 472 if (bootverbose) 473 device_printf(sc->dev, 474 "Regulator %s missing in DT\n", 475 act8846_regdefs[i].name); 476 continue; 477 } 478 reg = act8846_attach(sc, node, child, act8846_regdefs + i); 479 if (reg == NULL) { 480 device_printf(sc->dev, "Cannot attach regulator: %s\n", 481 act8846_regdefs[i].name); 482 return (ENXIO); 483 } 484 sc->regs[i] = reg; 485 } 486 return (0); 487 } 488 489 int 490 act8846_regulator_map(device_t dev, phandle_t xref, int ncells, 491 pcell_t *cells, int *num) 492 { 493 struct act8846_softc *sc; 494 int i; 495 496 sc = device_get_softc(dev); 497 for (i = 0; i < sc->nregs; i++) { 498 if (sc->regs[i] == NULL) 499 continue; 500 if (sc->regs[i]->xref == xref) { 501 *num = sc->regs[i]->def->id; 502 return (0); 503 } 504 } 505 return (ENXIO); 506 } 507