1 /* $OpenBSD: axppmic.c,v 1.6 2018/02/10 22:32:01 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 #include <sys/sensors.h> 23 24 #include <dev/i2c/i2cvar.h> 25 #include <dev/fdt/rsbvar.h> 26 27 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/ofw_regulator.h> 29 #include <dev/ofw/fdt.h> 30 31 extern void (*powerdownfn)(void); 32 33 #define AXP209_SDR 0x32 34 #define AXP209_SDR_SHUTDOWN (1 << 7) 35 #define AXP209_ADC_EN1 0x82 36 #define AXP209_ADC_EN1_ACIN (3 << 4) 37 #define AXP209_ADC_EN1_VBUS (3 << 2) 38 39 #define AXP806_REG_ADDR_EXT 0xff 40 #define AXP806_REG_ADDR_EXT_MASTER_MODE (0 << 4) 41 #define AXP806_REG_ADDR_EXT_SLAVE_MODE (1 << 4) 42 43 /* Regulators for AXP209, AXP221, AXP806 and AXP809. */ 44 45 struct axppmic_regdata { 46 const char *name; 47 uint8_t ereg, emask, eval, dval; 48 uint8_t vreg, vmask; 49 uint32_t base, delta; 50 uint32_t base2, delta2; 51 }; 52 53 struct axppmic_regdata axp209_regdata[] = { 54 { "dcdc2", 0x12, (1 << 4), (1 << 4), (0 << 4), 55 0x23, 0x3f, 700000, 25000 }, 56 { "dcdc3", 0x12, (1 << 1), (1 << 1), (0 << 1), 57 0x27, 0x3f, 700000, 25000 }, 58 /* LDO1 can't be controlled */ 59 { "ldo2", 0x12, (1 << 2), (1 << 2), (0 << 2), 60 0x28, 0xf0, 1800000, (100000 >> 4) }, 61 { "ldo3", 0x12, (1 << 6), (1 << 6), (0 << 6), 62 0x29, 0x7f, 700000, 25000 }, 63 /* LDO4 voltage levels are complicated */ 64 { "ldo5", 0x90, 0x07, 0x03, 0x07, 65 0x91, 0xf0, 1800000, (100000 >> 4) }, 66 { NULL } 67 }; 68 69 struct axppmic_regdata axp221_regdata[] = { 70 { "dcdc1", 0x10, (1 << 1), (1 << 1), (0 << 1), 71 0x21, 0x1f, 1600000, 100000 }, 72 { "dcdc2", 0x10, (1 << 2), (1 << 2), (0 << 2), 73 0x22, 0x3f, 600000, 20000 }, 74 { "dcdc3", 0x10, (1 << 3), (1 << 3), (0 << 3), 75 0x23, 0x3f, 600000, 20000 }, 76 { "dcdc4", 0x10, (1 << 4), (1 << 4), (0 << 4), 77 0x24, 0x3f, 600000, 20000 }, 78 { "dcdc5", 0x10, (1 << 5), (1 << 5), (0 << 5), 79 0x25, 0x1f, 1000000, 50000 }, 80 { "dc1sw", 0x12, (1 << 7), (1 << 7), (0 << 7) }, 81 { "dc5ldo", 0x10, (1 << 0), (1 << 0), (0 << 0), 82 0x1c, 0x07, 700000, 100000 }, 83 { "aldo1", 0x10, (1 << 6), (1 << 6), (0 << 6), 84 0x28, 0x1f, 700000, 100000 }, 85 { "aldo2", 0x10, (1 << 7), (1 << 7), (0 << 7), 86 0x29, 0x1f, 700000, 100000 }, 87 { "aldo3", 0x13, (1 << 7), (1 << 7), (0 << 7), 88 0x2a, 0x1f, 700000, 100000 }, 89 { "dldo1", 0x12, (1 << 3), (1 << 3), (0 << 3), 90 0x15, 0x1f, 700000, 100000 }, 91 { "dldo2", 0x12, (1 << 4), (1 << 4), (0 << 4), 92 0x16, 0x1f, 700000, 100000 }, 93 { "dldo3", 0x12, (1 << 5), (1 << 5), (0 << 5), 94 0x17, 0x1f, 700000, 100000 }, 95 { "dldo4", 0x12, (1 << 6), (1 << 6), (0 << 6), 96 0x18, 0x1f, 700000, 100000 }, 97 { "eldo1", 0x12, (1 << 0), (1 << 0), (0 << 0), 98 0x19, 0x1f, 700000, 100000 }, 99 { "eldo2", 0x12, (1 << 1), (1 << 1), (0 << 1), 100 0x1a, 0x1f, 700000, 100000 }, 101 { "eldo3", 0x12, (1 << 2), (1 << 2), (0 << 2), 102 0x1b, 0x1f, 700000, 100000 }, 103 { "ldo_io0", 0x90, 0x07, 0x03, 0x04, 104 0x91, 0x1f, 700000, 100000 }, 105 { "ldo_io1", 0x92, 0x07, 0x03, 0x04, 106 0x93, 0x1f, 700000, 100000 }, 107 { NULL } 108 }; 109 110 struct axppmic_regdata axp803_regdata[] = { 111 { "dcdc1", 0x10, (1 << 0), (1 << 0), (0 << 0), 112 0x20, 0x1f, 1600000, 100000 }, 113 { "dcdc2", 0x10, (1 << 1), (1 << 1), (0 << 1), 114 0x21, 0x7f, 500000, 10000, 1220000, 20000 }, 115 { "dcdc3", 0x10, (1 << 2), (1 << 2), (0 << 2), 116 0x22, 0x7f, 500000, 10000, 1220000, 20000 }, 117 { "dcdc4", 0x10, (1 << 3), (1 << 3), (0 << 3), 118 0x23, 0x7f, 500000, 10000, 1220000, 20000 }, 119 { "dcdc5", 0x10, (1 << 4), (1 << 4), (0 << 4), 120 0x24, 0x7f, 800000, 10000, 1140000, 20000 }, 121 { "dcdc6", 0x10, (1 << 5), (1 << 5), (0 << 5), 122 0x25, 0x7f, 600000, 10000, 1120000, 20000 }, 123 { "dc1sw", 0x12, (1 << 7), (1 << 7), (0 << 7) }, 124 { "aldo1", 0x13, (1 << 5), (1 << 5), (0 << 5), 125 0x28, 0x1f, 700000, 100000 }, 126 { "aldo2", 0x13, (1 << 6), (1 << 6), (0 << 6), 127 0x29, 0x1f, 700000, 100000 }, 128 { "aldo3", 0x13, (1 << 7), (1 << 7), (0 << 7), 129 0x2a, 0x1f, 700000, 100000 }, 130 { "dldo1", 0x12, (1 << 3), (1 << 3), (0 << 3), 131 0x15, 0x1f, 700000, 100000 }, 132 { "dldo2", 0x12, (1 << 4), (1 << 4), (0 << 4), 133 0x16, 0x1f, 700000, 100000, 3400000, 200000 }, 134 { "dldo3", 0x12, (1 << 5), (1 << 5), (0 << 5), 135 0x17, 0x1f, 700000, 100000 }, 136 { "dldo4", 0x12, (1 << 6), (1 << 6), (0 << 6), 137 0x18, 0x1f, 700000, 100000 }, 138 { "eldo1", 0x12, (1 << 0), (1 << 0), (0 << 0), 139 0x19, 0x1f, 700000, 50000 }, 140 { "eldo2", 0x12, (1 << 1), (1 << 1), (0 << 1), 141 0x1a, 0x1f, 700000, 50000 }, 142 { "eldo3", 0x12, (1 << 2), (1 << 2), (0 << 2), 143 0x1b, 0x1f, 700000, 50000 }, 144 { "fldo1", 0x13, (1 << 2), (1 << 2), (0 << 2), 145 0x1c, 0x0f, 700000, 50000 }, 146 { "fldo2", 0x13, (1 << 3), (1 << 3), (0 << 3), 147 0x1d, 0x0f, 700000, 50000 }, 148 { "ldo-io0", 0x90, 0x07, 0x03, 0x04, 149 0x91, 0x1f, 700000, 100000 }, 150 { "ldo-io1", 0x92, 0x07, 0x03, 0x04, 151 0x93, 0x1f, 700000, 100000 }, 152 { NULL } 153 }; 154 155 struct axppmic_regdata axp806_regdata[] = { 156 { "dcdca", 0x10, (1 << 0), (1 << 0), (0 << 0), 157 0x12, 0x7f, 600000, 10000, 1120000, 20000 }, 158 { "dcdcb", 0x10, (1 << 1), (1 << 1), (0 << 1), 159 0x13, 0x1f, 1000000, 50000 }, 160 { "dcdcc", 0x10, (1 << 2), (1 << 2), (0 << 2), 161 0x14, 0x7f, 600000, 10000, 1120000, 20000 }, 162 { "dcdcd", 0x10, (1 << 3), (1 << 3), (0 << 3), 163 0x15, 0x3f, 600000, 20000, 1600000, 100000 }, 164 { "dcdce", 0x10, (1 << 4), (1 << 4), (0 << 4), 165 0x16, 0x1f, 1100000, 100000 }, 166 { "aldo1", 0x10, (1 << 5), (1 << 5), (0 << 5), 167 0x17, 0x1f, 700000, 100000 }, 168 { "aldo2", 0x10, (1 << 6), (1 << 6), (0 << 6), 169 0x18, 0x1f, 700000, 100000 }, 170 { "aldo3", 0x10, (1 << 7), (1 << 7), (0 << 7), 171 0x19, 0x1f, 700000, 100000 }, 172 { "bldo1", 0x11, (1 << 0), (1 << 0), (0 << 0), 173 0x20, 0x0f, 700000, 100000 }, 174 { "bldo2", 0x11, (1 << 1), (1 << 1), (0 << 1), 175 0x21, 0x0f, 700000, 100000 }, 176 { "bldo3", 0x11, (1 << 2), (1 << 2), (0 << 2), 177 0x22, 0x0f, 700000, 100000 }, 178 { "bldo4", 0x11, (1 << 3), (1 << 3), (0 << 3), 179 0x23, 0x0f, 700000, 100000 }, 180 { "cldo1", 0x11, (1 << 4), (1 << 4), (0 << 4), 181 0x24, 0x1f, 700000, 100000 }, 182 { "cldo2", 0x11, (1 << 5), (1 << 5), (0 << 5), 183 0x25, 0x1f, 700000, 100000, 3600000, 200000 }, 184 { "cldo3", 0x11, (1 << 6), (1 << 6), (0 << 6), 185 0x26, 0x1f, 700000, 100000 }, 186 { "sw", 0x11, (1 << 7), (1 << 7), (0 << 7) }, 187 { NULL } 188 }; 189 190 struct axppmic_regdata axp809_regdata[] = { 191 { "dcdc1", 0x10, (1 << 1), (1 << 1), (0 << 1), 192 0x21, 0x1f, 1600000, 100000 }, 193 { "dcdc2", 0x10, (1 << 2), (1 << 2), (0 << 2), 194 0x22, 0x3f, 600000, 20000 }, 195 { "dcdc3", 0x10, (1 << 3), (1 << 3), (0 << 3), 196 0x23, 0x3f, 600000, 20000 }, 197 { "dcdc4", 0x10, (1 << 4), (1 << 4), (0 << 4), 198 0x24, 0x3f, 600000, 20000, 1800000, 100000 }, 199 { "dcdc5", 0x10, (1 << 5), (1 << 5), (0 << 5), 200 0x25, 0x1f, 1000000, 50000 }, 201 { "dc5ldo", 0x10, (1 << 0), (1 << 0), (0 << 0), 202 0x1c, 0x07, 700000, 100000 }, 203 { "aldo1", 0x10, (1 << 6), (1 << 6), (0 << 6), 204 0x28, 0x1f, 700000, 100000 }, 205 { "aldo2", 0x10, (1 << 7), (1 << 7), (0 << 7), 206 0x29, 0x1f, 700000, 100000 }, 207 { "aldo3", 0x12, (1 << 5), (1 << 5), (0 << 5), 208 0x2a, 0x1f, 700000, 100000 }, 209 { "dldo1", 0x12, (1 << 3), (1 << 3), (0 << 3), 210 0x15, 0x1f, 700000, 100000 }, 211 { "dldo2", 0x12, (1 << 4), (1 << 4), (0 << 4), 212 0x16, 0x1f, 700000, 100000 }, 213 { "eldo1", 0x12, (1 << 0), (1 << 0), (0 << 0), 214 0x19, 0x1f, 700000, 100000 }, 215 { "eldo2", 0x12, (1 << 1), (1 << 1), (0 << 1), 216 0x1a, 0x1f, 700000, 100000 }, 217 { "eldo3", 0x12, (1 << 2), (1 << 2), (0 << 2), 218 0x1b, 0x1f, 700000, 100000 }, 219 { "ldo_io0", 0x90, 0x07, 0x03, 0x04, 220 0x91, 0x1f, 700000, 100000 }, 221 { "ldo_io1", 0x92, 0x07, 0x03, 0x04, 222 0x93, 0x1f, 700000, 100000 }, 223 { NULL } 224 }; 225 226 /* Sensors for AXP209 and AXP221/AXP809. */ 227 228 #define AXPPMIC_NSENSORS 8 229 230 struct axppmic_sensdata { 231 const char *name; 232 enum sensor_type type; 233 uint8_t reg; 234 uint64_t base, delta; 235 }; 236 237 struct axppmic_sensdata axp209_sensdata[] = { 238 { "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) }, 239 { "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) }, 240 { "ACIN", SENSOR_VOLTS_DC, 0x56, 0, 1700 }, 241 { "ACIN", SENSOR_AMPS, 0x58, 0, 625 }, 242 { "VBUS", SENSOR_VOLTS_DC, 0x5a, 0, 1700 }, 243 { "VBUS", SENSOR_AMPS, 0x5c, 0, 375 }, 244 { "", SENSOR_TEMP, 0x5e, 128450000, 100000 }, 245 { "APS", SENSOR_VOLTS_DC, 0x7e, 0, 1400 }, 246 { NULL } 247 }; 248 249 struct axppmic_sensdata axp221_sensdata[] = { 250 { "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) }, 251 { "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) }, 252 { "", SENSOR_TEMP, 0x56, 5450000, 105861 }, 253 { NULL } 254 }; 255 256 struct axppmic_sensdata axp803_sensdata[] = { 257 { "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) }, 258 { "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) }, 259 { "", SENSOR_TEMP, 0x56, 5450000, 106250 }, 260 { NULL } 261 }; 262 263 struct axppmic_device { 264 const char *name; 265 const char *chip; 266 struct axppmic_regdata *regdata; 267 struct axppmic_sensdata *sensdata; 268 }; 269 270 struct axppmic_device axppmic_devices[] = { 271 { "x-powers,axp152", "AXP152" }, 272 { "x-powers,axp209", "AXP209", axp209_regdata, axp209_sensdata }, 273 { "x-powers,axp221", "AXP221", axp221_regdata, axp221_sensdata }, 274 { "x-powers,axp223", "AXP223", axp221_regdata, axp221_sensdata }, 275 { "x-powers,axp803", "AXP803", axp803_regdata, axp803_sensdata }, 276 { "x-powers,axp806", "AXP806", axp806_regdata }, 277 { "x-powers,axp809", "AXP809", axp809_regdata, axp221_sensdata } 278 }; 279 280 const struct axppmic_device * 281 axppmic_lookup(const char *name) 282 { 283 int i; 284 285 for (i = 0; i < nitems(axppmic_devices); i++) { 286 if (strcmp(name, axppmic_devices[i].name) == 0) 287 return &axppmic_devices[i]; 288 } 289 290 return NULL; 291 } 292 293 struct axppmic_softc { 294 struct device sc_dev; 295 void *sc_cookie; 296 uint16_t sc_addr; 297 298 uint8_t (*sc_read)(struct axppmic_softc *, uint8_t); 299 void (*sc_write)(struct axppmic_softc *, uint8_t, uint8_t); 300 struct axppmic_regdata *sc_regdata; 301 struct axppmic_sensdata *sc_sensdata; 302 303 struct ksensor sc_sensor[AXPPMIC_NSENSORS]; 304 struct ksensordev sc_sensordev; 305 }; 306 307 inline uint8_t 308 axppmic_read_reg(struct axppmic_softc *sc, uint8_t reg) 309 { 310 return sc->sc_read(sc, reg); 311 } 312 313 inline void 314 axppmic_write_reg(struct axppmic_softc *sc, uint8_t reg, uint8_t value) 315 { 316 sc->sc_write(sc, reg, value); 317 } 318 319 void axppmic_attach_common(struct axppmic_softc *, const char *, int); 320 321 /* I2C interface */ 322 323 int axppmic_i2c_match(struct device *, void *, void *); 324 void axppmic_i2c_attach(struct device *, struct device *, void *); 325 326 struct cfattach axppmic_ca = { 327 sizeof(struct axppmic_softc), axppmic_i2c_match, axppmic_i2c_attach 328 }; 329 330 struct cfdriver axppmic_cd = { 331 NULL, "axppmic", DV_DULL 332 }; 333 334 uint8_t axppmic_i2c_read(struct axppmic_softc *, uint8_t); 335 void axppmic_i2c_write(struct axppmic_softc *, uint8_t, uint8_t); 336 337 int 338 axppmic_i2c_match(struct device *parent, void *match, void *aux) 339 { 340 struct i2c_attach_args *ia = aux; 341 342 if (axppmic_lookup(ia->ia_name)) 343 return 1; 344 return 0; 345 } 346 347 void 348 axppmic_i2c_attach(struct device *parent, struct device *self, void *aux) 349 { 350 struct axppmic_softc *sc = (struct axppmic_softc *)self; 351 struct i2c_attach_args *ia = aux; 352 int node = *(int *)ia->ia_cookie; 353 354 sc->sc_cookie = ia->ia_tag; 355 sc->sc_addr = ia->ia_addr; 356 sc->sc_read = axppmic_i2c_read; 357 sc->sc_write = axppmic_i2c_write; 358 359 axppmic_attach_common(sc, ia->ia_name, node); 360 } 361 362 uint8_t 363 axppmic_i2c_read(struct axppmic_softc *sc, uint8_t reg) 364 { 365 i2c_tag_t tag = sc->sc_cookie; 366 int flags = cold ? I2C_F_POLL : 0; 367 int error; 368 uint8_t value; 369 370 iic_acquire_bus(tag, flags); 371 error = iic_smbus_read_byte(tag, sc->sc_addr, reg, &value, flags); 372 iic_release_bus(tag, flags); 373 if (error) { 374 printf("%s: SMBus read byte from 0x%02x failed\n", 375 sc->sc_dev.dv_xname, reg); 376 return 0xff; 377 } 378 379 return value; 380 } 381 382 void 383 axppmic_i2c_write(struct axppmic_softc *sc, uint8_t reg, uint8_t value) 384 { 385 i2c_tag_t tag = sc->sc_cookie; 386 int flags = cold ? I2C_F_POLL : 0; 387 int error; 388 389 iic_acquire_bus(tag, flags); 390 error = iic_smbus_write_byte(tag, sc->sc_addr, reg, value, flags); 391 iic_release_bus(tag, flags); 392 if (error) 393 printf("%s: SMBus write byte to 0x%02x failed\n", 394 sc->sc_dev.dv_xname, reg); 395 } 396 397 /* RSB interface */ 398 399 int axppmic_rsb_match(struct device *, void *, void *); 400 void axppmic_rsb_attach(struct device *, struct device *, void *); 401 402 struct cfattach axppmic_rsb_ca = { 403 sizeof(struct axppmic_softc), axppmic_rsb_match, axppmic_rsb_attach 404 }; 405 406 struct cfdriver axppmic_rsb_cd = { 407 NULL, "axppmic", DV_DULL 408 }; 409 410 uint8_t axppmic_rsb_read(struct axppmic_softc *, uint8_t); 411 void axppmic_rsb_write(struct axppmic_softc *, uint8_t, uint8_t); 412 413 int 414 axppmic_rsb_match(struct device *parent, void *match, void *aux) 415 { 416 struct rsb_attach_args *ra = aux; 417 418 if (axppmic_lookup(ra->ra_name)) 419 return 1; 420 return 0; 421 } 422 423 void 424 axppmic_rsb_attach(struct device *parent, struct device *self, void *aux) 425 { 426 struct axppmic_softc *sc = (struct axppmic_softc *)self; 427 struct rsb_attach_args *ra = aux; 428 429 sc->sc_cookie = ra->ra_cookie; 430 sc->sc_addr = ra->ra_rta; 431 sc->sc_read = axppmic_rsb_read; 432 sc->sc_write = axppmic_rsb_write; 433 434 axppmic_attach_common(sc, ra->ra_name, ra->ra_node); 435 } 436 437 uint8_t 438 axppmic_rsb_read(struct axppmic_softc *sc, uint8_t reg) 439 { 440 return rsb_read_1(sc->sc_cookie, sc->sc_addr, reg); 441 } 442 443 void 444 axppmic_rsb_write(struct axppmic_softc *sc, uint8_t reg, uint8_t value) 445 { 446 rsb_write_1(sc->sc_cookie, sc->sc_addr, reg, value); 447 } 448 449 /* Common code */ 450 451 void axppmic_attach_regulators(struct axppmic_softc *, int); 452 void axppmic_attach_sensors(struct axppmic_softc *); 453 454 struct axppmic_softc *axppmic_sc; 455 void axp209_powerdown(void); 456 457 void 458 axppmic_attach_common(struct axppmic_softc *sc, const char *name, int node) 459 { 460 const struct axppmic_device *device; 461 462 device = axppmic_lookup(name); 463 printf(": %s\n", device->chip); 464 465 sc->sc_regdata = device->regdata; 466 sc->sc_sensdata = device->sensdata; 467 468 /* Switch AXP806 into master or slave mode. */ 469 if (strcmp(name, "x-powers,axp806") == 0) { 470 if (OF_getproplen(node, "x-powers,master-mode") == 0) { 471 axppmic_write_reg(sc, AXP806_REG_ADDR_EXT, 472 AXP806_REG_ADDR_EXT_MASTER_MODE); 473 } else { 474 axppmic_write_reg(sc, AXP806_REG_ADDR_EXT, 475 AXP806_REG_ADDR_EXT_SLAVE_MODE); 476 } 477 } 478 479 /* Enable data collecton on AXP209. */ 480 if (strcmp(name, "x-powers,axp209") == 0) { 481 uint8_t reg; 482 483 /* Turn on sampling of ACIN and VBUS voltage and current. */ 484 reg = axppmic_read_reg(sc, AXP209_ADC_EN1); 485 reg |= AXP209_ADC_EN1_ACIN; 486 reg |= AXP209_ADC_EN1_VBUS; 487 axppmic_write_reg(sc, AXP209_ADC_EN1, reg); 488 } 489 490 if (sc->sc_regdata) 491 axppmic_attach_regulators(sc, node); 492 493 if (sc->sc_sensdata) 494 axppmic_attach_sensors(sc); 495 496 #ifdef __armv7__ 497 if (strcmp(name, "x-powers,axp152") == 0 || 498 strcmp(name, "x-powers,axp209") == 0) { 499 axppmic_sc = sc; 500 powerdownfn = axp209_powerdown; 501 } 502 #endif 503 } 504 505 /* Regulators */ 506 507 struct axppmic_regulator { 508 struct axppmic_softc *ar_sc; 509 510 uint8_t ar_ereg, ar_emask; 511 uint8_t ar_eval, ar_dval; 512 513 uint8_t ar_vreg, ar_vmask; 514 uint32_t ar_base, ar_delta; 515 uint32_t ar_base2, ar_delta2; 516 517 struct regulator_device ar_rd; 518 }; 519 520 void axppmic_attach_regulator(struct axppmic_softc *, int); 521 uint32_t axppmic_get_voltage(void *); 522 int axppmic_set_voltage(void *, uint32_t); 523 int axppmic_enable(void *, int); 524 525 void 526 axppmic_attach_regulators(struct axppmic_softc *sc, int node) 527 { 528 node = OF_getnodebyname(node, "regulators"); 529 if (node == 0) 530 return; 531 532 for (node = OF_child(node); node; node = OF_peer(node)) 533 axppmic_attach_regulator(sc, node); 534 } 535 536 void 537 axppmic_attach_regulator(struct axppmic_softc *sc, int node) 538 { 539 struct axppmic_regulator *ar; 540 char name[32]; 541 int i; 542 543 name[0] = 0; 544 OF_getprop(node, "name", name, sizeof(name)); 545 name[sizeof(name) - 1] = 0; 546 for (i = 0; sc->sc_regdata[i].name; i++) { 547 if (strcmp(sc->sc_regdata[i].name, name) == 0) 548 break; 549 } 550 if (sc->sc_regdata[i].name == NULL) 551 return; 552 553 ar = malloc(sizeof(*ar), M_DEVBUF, M_WAITOK | M_ZERO); 554 ar->ar_sc = sc; 555 556 ar->ar_ereg = sc->sc_regdata[i].ereg; 557 ar->ar_emask = sc->sc_regdata[i].emask; 558 ar->ar_eval = sc->sc_regdata[i].eval; 559 ar->ar_dval = sc->sc_regdata[i].dval; 560 ar->ar_vreg = sc->sc_regdata[i].vreg; 561 ar->ar_vmask = sc->sc_regdata[i].vmask; 562 ar->ar_base = sc->sc_regdata[i].base; 563 ar->ar_delta = sc->sc_regdata[i].delta; 564 565 ar->ar_rd.rd_node = node; 566 ar->ar_rd.rd_cookie = ar; 567 ar->ar_rd.rd_get_voltage = axppmic_get_voltage; 568 ar->ar_rd.rd_set_voltage = axppmic_set_voltage; 569 ar->ar_rd.rd_enable = axppmic_enable; 570 regulator_register(&ar->ar_rd); 571 } 572 573 uint32_t 574 axppmic_get_voltage(void *cookie) 575 { 576 struct axppmic_regulator *ar = cookie; 577 uint32_t voltage; 578 uint8_t value; 579 580 value = axppmic_read_reg(ar->ar_sc, ar->ar_vreg); 581 value &= ar->ar_vmask; 582 voltage = ar->ar_base + value * ar->ar_delta; 583 if (ar->ar_base2 > 0 && voltage > ar->ar_base2) { 584 value -= (ar->ar_base2 - ar->ar_base) / ar->ar_delta; 585 voltage = ar->ar_base2 + value * ar->ar_delta2; 586 } 587 return voltage; 588 } 589 590 int 591 axppmic_set_voltage(void *cookie, uint32_t voltage) 592 { 593 struct axppmic_regulator *ar = cookie; 594 uint32_t value, reg; 595 596 if (voltage < ar->ar_base) 597 return EINVAL; 598 value = (voltage - ar->ar_base) / ar->ar_delta; 599 if (ar->ar_base2 > 0 && voltage > ar->ar_base2) { 600 value = (ar->ar_base2 - ar->ar_base) / ar->ar_delta; 601 value += (voltage - ar->ar_base2) / ar->ar_delta2; 602 } 603 if (value > ar->ar_vmask) 604 return EINVAL; 605 606 reg = axppmic_read_reg(ar->ar_sc, ar->ar_vreg); 607 reg &= ar->ar_vmask; 608 axppmic_write_reg(ar->ar_sc, ar->ar_vreg, reg | value); 609 return 0; 610 } 611 612 int 613 axppmic_enable(void *cookie, int on) 614 { 615 struct axppmic_regulator *ar = cookie; 616 uint8_t reg; 617 618 reg = axppmic_read_reg(ar->ar_sc, ar->ar_ereg); 619 reg &= ~ar->ar_emask; 620 if (on) 621 reg |= ar->ar_eval; 622 else 623 reg |= ar->ar_dval; 624 axppmic_write_reg(ar->ar_sc, ar->ar_ereg, reg); 625 return 0; 626 } 627 628 /* Sensors */ 629 630 void axppmic_update_sensors(void *); 631 void axppmic_update_indicator(struct axppmic_softc *, int); 632 void axppmic_update_sensor(struct axppmic_softc *, int); 633 634 void 635 axppmic_attach_sensors(struct axppmic_softc *sc) 636 { 637 int i; 638 639 for (i = 0; sc->sc_sensdata[i].name; i++) { 640 KASSERT(i < AXPPMIC_NSENSORS); 641 642 sc->sc_sensor[i].type = sc->sc_sensdata[i].type; 643 strlcpy(sc->sc_sensor[i].desc, sc->sc_sensdata[i].name, 644 sizeof(sc->sc_sensor[i].desc)); 645 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); 646 } 647 648 axppmic_update_sensors(sc); 649 if (sensor_task_register(sc, axppmic_update_sensors, 5) == NULL) { 650 printf(", unable to register update task\n"); 651 return; 652 } 653 654 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 655 sizeof(sc->sc_sensordev.xname)); 656 sensordev_install(&sc->sc_sensordev); 657 } 658 659 void 660 axppmic_update_sensors(void *arg) 661 { 662 struct axppmic_softc *sc = arg; 663 int i; 664 665 for (i = 0; sc->sc_sensdata[i].name; i++) { 666 if (sc->sc_sensdata[i].type == SENSOR_INDICATOR) 667 axppmic_update_indicator(sc, i); 668 else 669 axppmic_update_sensor(sc, i); 670 } 671 } 672 673 void 674 axppmic_update_indicator(struct axppmic_softc *sc, int i) 675 { 676 uint8_t reg = sc->sc_sensdata[i].reg; 677 uint8_t mask = sc->sc_sensdata[i].base; 678 uint8_t mask_ok = sc->sc_sensdata[i].delta; 679 uint8_t value; 680 681 value = axppmic_read_reg(sc, reg); 682 sc->sc_sensor[i].value = (value & mask) ? 1 : 0; 683 if (value & mask) { 684 sc->sc_sensor[i].status = 685 (value & mask_ok) ? SENSOR_S_OK : SENSOR_S_WARN; 686 } else { 687 sc->sc_sensor[i].status = SENSOR_S_UNSPEC; 688 } 689 } 690 691 void 692 axppmic_update_sensor(struct axppmic_softc *sc, int i) 693 { 694 uint8_t reg = sc->sc_sensdata[i].reg; 695 uint64_t base = sc->sc_sensdata[i].base; 696 uint64_t delta = sc->sc_sensdata[i].delta; 697 uint16_t value; 698 699 value = axppmic_read_reg(sc, reg); 700 value = (value << 4) | axppmic_read_reg(sc, reg + 1); 701 sc->sc_sensor[i].value = base + value * delta; 702 } 703 704 void 705 axp209_powerdown(void) 706 { 707 axppmic_write_reg(axppmic_sc, AXP209_SDR, AXP209_SDR_SHUTDOWN); 708 } 709