1 /* $OpenBSD: rkpmic.c,v 1.6 2018/07/31 10:09:25 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 <dev/ofw/openfirm.h> 24 #include <dev/ofw/ofw_regulator.h> 25 #include <dev/ofw/fdt.h> 26 27 #include <dev/i2c/i2cvar.h> 28 29 #include <dev/clock_subr.h> 30 31 extern todr_chip_handle_t todr_handle; 32 33 #define RK808_SECONDS 0x00 34 #define RK808_MINUTES 0x01 35 #define RK808_HOURS 0x02 36 #define RK808_DAYS 0x03 37 #define RK808_MONTHS 0x04 38 #define RK808_YEARS 0x05 39 #define RK808_WEEKS 0x06 40 #define RK808_RTC_CTRL 0x10 41 #define RK808_RTC_CTRL_STOP_RTC 0x01 42 #define RK808_RTC_STATUS 0x11 43 #define RK808_RTC_STATUS_POWER_UP 0x80 44 45 #define RK808_NRTC_REGS 7 46 47 struct rkpmic_regdata { 48 const char *name; 49 uint8_t reg, mask; 50 uint32_t base, delta; 51 }; 52 53 struct rkpmic_regdata rk805_regdata[] = { 54 { "DCDC_REG1", 0x2f, 0x3f, 712500, 12500 }, 55 { "DCDC_REG2", 0x33, 0x3f, 712500, 12500 }, 56 { "DCDC_REG4", 0x38, 0x1f, 800000, 100000 }, 57 { "LDO_REG1", 0x3b, 0x1f, 800000, 100000 }, 58 { "LDO_REG2", 0x3d, 0x1f, 800000, 100000 }, 59 { "LDO_REG3", 0x3f, 0x1f, 800000, 100000 }, 60 { } 61 }; 62 63 struct rkpmic_regdata rk808_regdata[] = { 64 { "DCDC_REG1", 0x2f, 0x3f, 712500, 12500 }, 65 { "DCDC_REG2", 0x33, 0x3f, 712500, 12500 }, 66 { "DCDC_REG4", 0x38, 0x0f, 1800000, 100000 }, 67 { "LDO_REG1", 0x3b, 0x1f, 1800000, 100000 }, 68 { "LDO_REG2", 0x3d, 0x1f, 1800000, 100000 }, 69 { "LDO_REG3", 0x3f, 0x0f, 800000, 100000 }, 70 { "LDO_REG4", 0x41, 0x1f, 1800000, 100000 }, 71 { "LDO_REG5", 0x43, 0x1f, 1800000, 100000 }, 72 { "LDO_REG6", 0x45, 0x1f, 800000, 100000 }, 73 { "LDO_REG7", 0x47, 0x1f, 800000, 100000 }, 74 { "LDO_REG8", 0x49, 0x1f, 1800000, 100000 }, 75 { } 76 }; 77 78 struct rkpmic_softc { 79 struct device sc_dev; 80 i2c_tag_t sc_tag; 81 i2c_addr_t sc_addr; 82 83 struct todr_chip_handle sc_todr; 84 struct rkpmic_regdata *sc_regdata; 85 }; 86 87 int rkpmic_match(struct device *, void *, void *); 88 void rkpmic_attach(struct device *, struct device *, void *); 89 90 struct cfattach rkpmic_ca = { 91 sizeof(struct rkpmic_softc), rkpmic_match, rkpmic_attach 92 }; 93 94 struct cfdriver rkpmic_cd = { 95 NULL, "rkpmic", DV_DULL 96 }; 97 98 void rkpmic_attach_regulator(struct rkpmic_softc *, int); 99 uint8_t rkpmic_reg_read(struct rkpmic_softc *, int); 100 void rkpmic_reg_write(struct rkpmic_softc *, int, uint8_t); 101 int rkpmic_clock_read(struct rkpmic_softc *, struct clock_ymdhms *); 102 int rkpmic_clock_write(struct rkpmic_softc *, struct clock_ymdhms *); 103 int rkpmic_gettime(struct todr_chip_handle *, struct timeval *); 104 int rkpmic_settime(struct todr_chip_handle *, struct timeval *); 105 106 int 107 rkpmic_match(struct device *parent, void *match, void *aux) 108 { 109 struct i2c_attach_args *ia = aux; 110 int node = *(int *)ia->ia_cookie; 111 112 return (OF_is_compatible(node, "rockchip,rk805") || 113 OF_is_compatible(node, "rockchip,rk808")); 114 } 115 116 void 117 rkpmic_attach(struct device *parent, struct device *self, void *aux) 118 { 119 struct rkpmic_softc *sc = (struct rkpmic_softc *)self; 120 struct i2c_attach_args *ia = aux; 121 int node = *(int *)ia->ia_cookie; 122 const char *chip; 123 124 sc->sc_tag = ia->ia_tag; 125 sc->sc_addr = ia->ia_addr; 126 127 sc->sc_todr.cookie = sc; 128 sc->sc_todr.todr_gettime = rkpmic_gettime; 129 sc->sc_todr.todr_settime = rkpmic_settime; 130 if (todr_handle == NULL) 131 todr_handle = &sc->sc_todr; 132 133 if (OF_is_compatible(node, "rockchip,rk805")) { 134 chip = "RK805"; 135 sc->sc_regdata = rk805_regdata; 136 } else { 137 chip = "RK808"; 138 sc->sc_regdata = rk808_regdata; 139 } 140 printf(": %s\n", chip); 141 142 node = OF_getnodebyname(node, "regulators"); 143 if (node == 0) 144 return; 145 for (node = OF_child(node); node; node = OF_peer(node)) 146 rkpmic_attach_regulator(sc, node); 147 } 148 149 struct rkpmic_regulator { 150 struct rkpmic_softc *rr_sc; 151 152 uint8_t rr_reg, rr_mask; 153 uint32_t rr_base, rr_delta; 154 155 struct regulator_device rr_rd; 156 }; 157 158 uint32_t rkpmic_get_voltage(void *); 159 int rkpmic_set_voltage(void *, uint32_t); 160 161 void 162 rkpmic_attach_regulator(struct rkpmic_softc *sc, int node) 163 { 164 struct rkpmic_regulator *rr; 165 char name[32]; 166 int i; 167 168 name[0] = 0; 169 OF_getprop(node, "name", name, sizeof(name)); 170 name[sizeof(name) - 1] = 0; 171 for (i = 0; sc->sc_regdata[i].name; i++) { 172 if (strcmp(sc->sc_regdata[i].name, name) == 0) 173 break; 174 } 175 if (sc->sc_regdata[i].name == NULL) 176 return; 177 178 rr = malloc(sizeof(*rr), M_DEVBUF, M_WAITOK | M_ZERO); 179 rr->rr_sc = sc; 180 181 rr->rr_reg = sc->sc_regdata[i].reg; 182 rr->rr_mask = sc->sc_regdata[i].mask; 183 rr->rr_base = sc->sc_regdata[i].base; 184 rr->rr_delta = sc->sc_regdata[i].delta; 185 186 rr->rr_rd.rd_node = node; 187 rr->rr_rd.rd_cookie = rr; 188 rr->rr_rd.rd_get_voltage = rkpmic_get_voltage; 189 rr->rr_rd.rd_set_voltage = rkpmic_set_voltage; 190 regulator_register(&rr->rr_rd); 191 } 192 193 uint32_t 194 rkpmic_get_voltage(void *cookie) 195 { 196 struct rkpmic_regulator *rr = cookie; 197 uint8_t vsel; 198 199 vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg); 200 return rr->rr_base + (vsel & rr->rr_mask) * rr->rr_delta; 201 } 202 203 int 204 rkpmic_set_voltage(void *cookie, uint32_t voltage) 205 { 206 struct rkpmic_regulator *rr = cookie; 207 uint32_t vmin = rr->rr_base; 208 uint32_t vmax = vmin + rr->rr_mask * rr->rr_delta; 209 uint8_t vsel; 210 211 if (voltage < vmin || voltage > vmax) 212 return EINVAL; 213 214 vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg); 215 vsel &= ~rr->rr_mask; 216 vsel |= (voltage - rr->rr_base) / rr->rr_delta; 217 rkpmic_reg_write(rr->rr_sc, rr->rr_reg, vsel); 218 219 return 0; 220 } 221 222 int 223 rkpmic_gettime(struct todr_chip_handle *handle, struct timeval *tv) 224 { 225 struct rkpmic_softc *sc = handle->cookie; 226 struct clock_ymdhms dt; 227 time_t secs; 228 int error; 229 230 error = rkpmic_clock_read(sc, &dt); 231 if (error) 232 return error; 233 234 if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 || 235 dt.dt_day > 31 || dt.dt_day == 0 || 236 dt.dt_mon > 12 || dt.dt_mon == 0 || 237 dt.dt_year < POSIX_BASE_YEAR) 238 return EINVAL; 239 240 /* 241 * The RTC thinks November has 31 days. Match what Linux does 242 * and undo the damage by considering the calenders to be in 243 * sync on January 1st 2016. 244 */ 245 secs = clock_ymdhms_to_secs(&dt); 246 secs += (dt.dt_year - 2016 + (dt.dt_mon == 12 ? 1 : 0)) * 86400; 247 248 tv->tv_sec = secs; 249 tv->tv_usec = 0; 250 return 0; 251 } 252 253 int 254 rkpmic_settime(struct todr_chip_handle *handle, struct timeval *tv) 255 { 256 struct rkpmic_softc *sc = handle->cookie; 257 struct clock_ymdhms dt; 258 time_t secs; 259 260 /* 261 * Take care of the November 31st braindamage here as well. 262 * Don't try to be clever, just do the conversion in two 263 * steps, first taking care of November 31 in previous years, 264 * and then taking care of days in December of the current 265 * year. Decmber 1st turns into November 31st! 266 */ 267 secs = tv->tv_sec; 268 clock_secs_to_ymdhms(secs, &dt); 269 secs -= (dt.dt_year - 2016) * 86400; 270 clock_secs_to_ymdhms(secs, &dt); 271 if (dt.dt_mon == 12) { 272 dt.dt_day--; 273 if (dt.dt_day == 0) { 274 dt.dt_mon = 11; 275 dt.dt_day = 31; 276 } 277 } 278 279 return rkpmic_clock_write(sc, &dt); 280 } 281 282 uint8_t 283 rkpmic_reg_read(struct rkpmic_softc *sc, int reg) 284 { 285 uint8_t cmd = reg; 286 uint8_t val; 287 int error; 288 289 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 290 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 291 &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL); 292 iic_release_bus(sc->sc_tag, I2C_F_POLL); 293 294 if (error) { 295 printf("%s: can't read register 0x%02x\n", 296 sc->sc_dev.dv_xname, reg); 297 val = 0xff; 298 } 299 300 return val; 301 } 302 303 void 304 rkpmic_reg_write(struct rkpmic_softc *sc, int reg, uint8_t val) 305 { 306 uint8_t cmd = reg; 307 int error; 308 309 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 310 error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 311 &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL); 312 iic_release_bus(sc->sc_tag, I2C_F_POLL); 313 314 if (error) { 315 printf("%s: can't write register 0x%02x\n", 316 sc->sc_dev.dv_xname, reg); 317 } 318 } 319 320 int 321 rkpmic_clock_read(struct rkpmic_softc *sc, struct clock_ymdhms *dt) 322 { 323 uint8_t regs[RK808_NRTC_REGS]; 324 uint8_t cmd = RK808_SECONDS; 325 uint8_t status; 326 int error; 327 328 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 329 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 330 &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL); 331 iic_release_bus(sc->sc_tag, I2C_F_POLL); 332 333 if (error) { 334 printf("%s: can't read RTC\n", sc->sc_dev.dv_xname); 335 return error; 336 } 337 338 /* 339 * Convert the RK808's register values into something useable. 340 */ 341 dt->dt_sec = FROMBCD(regs[0]); 342 dt->dt_min = FROMBCD(regs[1]); 343 dt->dt_hour = FROMBCD(regs[2]); 344 dt->dt_day = FROMBCD(regs[3]); 345 dt->dt_mon = FROMBCD(regs[4]); 346 dt->dt_year = FROMBCD(regs[5]) + 2000; 347 348 /* Consider the time to be invalid if the POWER_UP bit is set. */ 349 status = rkpmic_reg_read(sc, RK808_RTC_STATUS); 350 if (status & RK808_RTC_STATUS_POWER_UP) 351 return EINVAL; 352 353 return 0; 354 } 355 356 int 357 rkpmic_clock_write(struct rkpmic_softc *sc, struct clock_ymdhms *dt) 358 { 359 uint8_t regs[RK808_NRTC_REGS]; 360 uint8_t cmd = RK808_SECONDS; 361 int error; 362 363 /* 364 * Convert our time representation into something the RK808 365 * can understand. 366 */ 367 regs[0] = TOBCD(dt->dt_sec); 368 regs[1] = TOBCD(dt->dt_min); 369 regs[2] = TOBCD(dt->dt_hour); 370 regs[3] = TOBCD(dt->dt_day); 371 regs[4] = TOBCD(dt->dt_mon); 372 regs[5] = TOBCD(dt->dt_year - 2000); 373 regs[6] = TOBCD(dt->dt_wday); 374 375 /* Stop RTC such that we can write to it. */ 376 rkpmic_reg_write(sc, RK808_RTC_CTRL, RK808_RTC_CTRL_STOP_RTC); 377 378 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 379 error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 380 &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL); 381 iic_release_bus(sc->sc_tag, I2C_F_POLL); 382 383 /* Restart RTC. */ 384 rkpmic_reg_write(sc, RK808_RTC_CTRL, 0); 385 386 if (error) { 387 printf("%s: can't write RTC\n", sc->sc_dev.dv_xname); 388 return error; 389 } 390 391 /* Clear POWER_UP bit to indicate the time is now valid. */ 392 rkpmic_reg_write(sc, RK808_RTC_STATUS, RK808_RTC_STATUS_POWER_UP); 393 394 return 0; 395 } 396