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