Hi ARM list, I got a pinephone pro for christmas and I put OpenBSD on it but it's not ripe to even have on for lengthy periods of time. The pinephone pro is based on the Rockchip 3399.
I'm trying to adjust the /sys/dev/fdt/rkpmic.c driver but I'm running into a problem and would like to get some help understanding why I'm getting ETIMEOUT's on the i2c bus (iic), it's almost like the driver is getting the wrong info about addresses and the i2c times out because of it? Below my signature I have (a wrong) patch but it shows that on line 191 and line 202, the error is 60 which I crosschecked with man errno it's ETIMEOUT. So I hunted in the /sys/dev/fdt/rkiic.c code and made a delay loop longer which doesn't do anything really, it just delays the messages in dmesg. Could a advanced person give me a hint on this what could be happening here? The pinephone pro has a rk818 pmic which is very much compatible to rk808 and it gets detected as such from FDT. I have coded some "variant" code in there but even reading the registers for hi and lo bytes does not work. This is based off the linux driver, with changes. When this works I believe I can put charging control and apmd on this phone. Best Regards, -peter PS: use cut -c 8- to retrive the patch. 1 Index: rkpmic.c 2 =================================================================== 3 RCS file: /cvs/src/sys/dev/fdt/rkpmic.c,v 4 retrieving revision 1.9 5 diff -u -p -u -r1.9 rkpmic.c 6 --- rkpmic.c 24 Oct 2021 17:52:27 -0000 1.9 7 +++ rkpmic.c 21 Apr 2022 15:06:26 -0000 8 @@ -39,15 +39,39 @@ extern todr_chip_handle_t todr_handle; 9 #define RK80X_WEEKS 0x06 10 #define RK80X_NRTC_REGS 7 11 12 +#define RK818_SECONDS 0x00 13 +#define RK818_MINUTES 0x01 14 +#define RK818_HOURS 0x02 15 +#define RK818_DAYS 0x03 16 +#define RK818_MONTHS 0x04 17 +#define RK818_YEARS 0x05 18 +#define RK818_WEEKS 0x06 19 +#define RK818_ALARM_SECONDS 0x08 20 +#define RK818_ALARM_MINUTES 0x09 21 +#define RK818_ALARM_HOURS 0x0a 22 +#define RK818_ALARM_DAYS 0x0b 23 +#define RK818_ALARM_MONTHS 0x0c 24 +#define RK818_ALARM_YEARS 0x0d 25 +#define RK818_NRTC_REGS 13 26 + 27 #define RK805_RTC_CTRL 0x10 28 #define RK808_RTC_CTRL 0x10 29 #define RK809_RTC_CTRL 0x0d 30 +#define RK818_RTC_CTRL 0x10 31 + 32 #define RK80X_RTC_CTRL_STOP_RTC 0x01 33 +#define RK818_RTC_CTRL_STOP_RTC 0x01 34 35 #define RK805_RTC_STATUS 0x11 36 #define RK808_RTC_STATUS 0x11 37 #define RK809_RTC_STATUS 0x0e 38 +#define RK818_RTC_STATUS 0x11 39 + 40 #define RK80X_RTC_STATUS_POWER_UP 0x80 41 +#define RK818_RTC_STATUS_POWER_UP 0x80 42 + 43 +#define RK808_ID_HI 0x17 44 +#define RK808_ID_LO 0x18 45 46 struct rkpmic_vsel_range { 47 uint32_t base, delta; 48 @@ -229,6 +253,72 @@ struct rkpmic_regdata rk809_regdata[] = 49 { } 50 }; 51 52 +/* 53 + * Used by RK818 for BUCK1 & BUCK2 54 + * 0-63: 0.7125V-1.5V, step=12.5mV 55 + */ 56 +struct rkpmic_vsel_range rk818_vsel_range1[] = { 57 + { 712500, 12500, 0, 63 }, 58 + {} 59 +}; 60 + 61 +/* 62 + * Used by RK818 for BUCK4 63 + * 0-15: 1.8V-3.3V,step=100mV 64 + */ 65 +struct rkpmic_vsel_range rk818_vsel_range2[] = { 66 + { 1800000, 100000, 0, 15 }, 67 + {} 68 +}; 69 + 70 +/* 71 + * Used by RK818 for LDO1-2, 4-5, 8 72 + * 0-16: 1.8V-3.4V, step=100mV 73 + */ 74 +struct rkpmic_vsel_range rk818_vsel_range3[] = { 75 + { 1800000, 100000, 0, 16 }, 76 + {} 77 +}; 78 + 79 +/* 80 + * Used by RK818 for LDO3 81 + * 0-12: 0.8V~2.5V, step=100mV 82 + * 13: 2.2V 83 + * 15: 2.5V 84 + */ 85 +struct rkpmic_vsel_range rk818_vsel_range4[] = { 86 + { 800000, 100000, 0, 15 }, 87 + { 2200000, 0, 13, 13 }, 88 + { 2500000, 0, 15, 15 }, 89 + {} 90 +}; 91 + 92 +/* 93 + * Used by RK818 for LDO6-7 94 + * 0-17: 0.8V-2.5V,step=100mV 95 + */ 96 +struct rkpmic_vsel_range rk818_vsel_range5[] = { 97 + { 800000, 100000, 0, 17 }, 98 + {} 99 +}; 100 + 101 +/* comments for https://rockchip.fr/RK818%20datasheet%20V1.0.pdf */ 102 +struct rkpmic_regdata rk818_regdata[] = { 103 + { "DCDC_REG1", 0x2f, 0x3f, rk818_vsel_range1 }, /* pg. 58 */ 104 + { "DCDC_REG2", 0x33, 0x3f, rk818_vsel_range1 }, /* pg. 59 */ 105 + { "DCDC_REG4", 0x38, 0x0f, rk818_vsel_range2 }, /* pg. 61 */ 106 + { "LDO_REG1", 0x3b, 0x1f, rk818_vsel_range3 }, /* pg. 63 */ 107 + { "LDO_REG2", 0x3d, 0x1f, rk818_vsel_range3 }, /* pg. 63 */ 108 + { "LDO_REG3", 0x3f, 0x0f, rk818_vsel_range4 }, /* pg. 64 */ 109 + { "LDO_REG4", 0x41, 0x1f, rk818_vsel_range3 }, /* pg. 65 */ 110 + { "LDO_REG5", 0x43, 0x1f, rk818_vsel_range3 }, /* pg. 66 */ 111 + { "LDO_REG6", 0x45, 0x1f, rk818_vsel_range5 }, /* pg. 67 */ 112 + { "LDO_REG7", 0x47, 0x1f, rk818_vsel_range5 }, /* pg. 67 */ 113 + { "LDO_REG8", 0x49, 0x1f, rk818_vsel_range3 }, /* pg. 68 */ 114 + { } 115 +}; 116 + 117 + 118 struct rkpmic_softc { 119 struct device sc_dev; 120 i2c_tag_t sc_tag; 121 @@ -237,6 +327,13 @@ struct rkpmic_softc { 122 int sc_rtc_ctrl_reg, sc_rtc_status_reg; 123 struct todr_chip_handle sc_todr; 124 struct rkpmic_regdata *sc_regdata; 125 + 126 + uint16_t variant; 127 +#define RK805_VARIANT 0x8050 128 +#define RK808_VARIANT 0x0 129 +#define RK809_VARIANT 0x8090 130 +#define RK818_VARIANT 0x8180 131 +#define RK8XX_VARIANT_MASK 0xfff0 132 }; 133 134 int rkpmic_match(struct device *, void *, void *); 135 @@ -275,6 +372,7 @@ rkpmic_attach(struct device *parent, str 136 struct i2c_attach_args *ia = aux; 137 int node = *(int *)ia->ia_cookie; 138 const char *chip; 139 + uint8_t regs[2]; 140 141 sc->sc_tag = ia->ia_tag; 142 sc->sc_addr = ia->ia_addr; 143 @@ -290,17 +388,36 @@ rkpmic_attach(struct device *parent, str 144 sc->sc_rtc_ctrl_reg = RK805_RTC_CTRL; 145 sc->sc_rtc_status_reg = RK805_RTC_STATUS; 146 sc->sc_regdata = rk805_regdata; 147 + sc->variant = RK805_VARIANT; 148 } else if (OF_is_compatible(node, "rockchip,rk808")) { 149 - chip = "RK808"; 150 - sc->sc_rtc_ctrl_reg = RK808_RTC_CTRL; 151 - sc->sc_rtc_status_reg = RK808_RTC_STATUS; 152 - sc->sc_regdata = rk808_regdata; 153 + rkpmic_reg_write(sc, RK808_RTC_STATUS, RK80X_RTC_STATUS_POWER_UP); 154 + regs[0] = rkpmic_reg_read(sc, RK808_ID_HI); 155 + regs[1] = rkpmic_reg_read(sc, RK808_ID_LO); 156 + rkpmic_reg_write(sc, RK808_RTC_CTRL, 0); 157 + 158 + sc->variant = ((regs[0] << 8) | regs[1]) & RK8XX_VARIANT_MASK; 159 + 160 + switch (sc->variant) { 161 + case RK818_VARIANT: 162 + chip = "RK818"; 163 + sc->sc_rtc_ctrl_reg = RK818_RTC_CTRL; 164 + sc->sc_rtc_status_reg = RK818_RTC_STATUS; 165 + sc->sc_regdata = rk818_regdata; 166 + break; 167 + default: 168 + chip = "RK808"; 169 + sc->sc_rtc_ctrl_reg = RK808_RTC_CTRL; 170 + sc->sc_rtc_status_reg = RK808_RTC_STATUS; 171 + sc->sc_regdata = rk808_regdata; 172 + break; 173 + } 174 } else { 175 chip = "RK809"; 176 sc->sc_rtc_ctrl_reg = RK809_RTC_CTRL; 177 sc->sc_rtc_status_reg = RK809_RTC_STATUS; 178 sc->sc_regdata = rk809_regdata; 179 - } 180 + } 181 + 182 printf(": %s\n", chip); 183 184 node = OF_getnodebyname(node, "regulators"); 185 @@ -496,8 +613,8 @@ rkpmic_reg_read(struct rkpmic_softc *sc, 186 iic_release_bus(sc->sc_tag, I2C_F_POLL); 187 188 if (error) { 189 - printf("%s: can't read register 0x%02x\n", 190 - sc->sc_dev.dv_xname, reg); 191 + printf("%s: can't read register 0x%02x error=%d\n", 192 + sc->sc_dev.dv_xname, reg, error); 193 val = 0xff; 194 } 195 196 @@ -516,22 +633,31 @@ rkpmic_reg_write(struct rkpmic_softc *sc 197 iic_release_bus(sc->sc_tag, I2C_F_POLL); 198 199 if (error) { 200 - printf("%s: can't write register 0x%02x\n", 201 - sc->sc_dev.dv_xname, reg); 202 + printf("%s: can't write register 0x%02x error=%d\n", 203 + sc->sc_dev.dv_xname, reg, error); 204 } 205 } 206 207 int 208 rkpmic_clock_read(struct rkpmic_softc *sc, struct clock_ymdhms *dt) 209 { 210 - uint8_t regs[RK80X_NRTC_REGS]; 211 - uint8_t cmd = RK80X_SECONDS; 212 + uint8_t regs[RK818_NRTC_REGS]; 213 + uint8_t cmd; 214 uint8_t status; 215 + int variant818 = 0; 216 int error; 217 218 + if (sc->variant == RK818_VARIANT) { 219 + cmd = RK818_SECONDS; 220 + variant818 = 1; 221 + } else { 222 + cmd = RK80X_SECONDS; 223 + } 224 + 225 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 226 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 227 - &cmd, sizeof(cmd), regs, RK80X_NRTC_REGS, I2C_F_POLL); 228 + &cmd, sizeof(cmd), regs, (variant818) ? 229 + RK818_NRTC_REGS : RK80X_NRTC_REGS, I2C_F_POLL); 230 iic_release_bus(sc->sc_tag, I2C_F_POLL); 231 232 if (error) { 233 @@ -560,10 +686,16 @@ rkpmic_clock_read(struct rkpmic_softc *s 234 int 235 rkpmic_clock_write(struct rkpmic_softc *sc, struct clock_ymdhms *dt) 236 { 237 - uint8_t regs[RK80X_NRTC_REGS]; 238 + uint8_t regs[RK818_NRTC_REGS]; 239 uint8_t cmd = RK80X_SECONDS; 240 + int variant818 = 0; 241 int error; 242 243 + if (sc->variant == RK818_VARIANT) { 244 + cmd = RK818_SECONDS; 245 + variant818 = 1; 246 + } 247 + 248 /* 249 * Convert our time representation into something the RK80x 250 * can understand. 251 @@ -577,11 +709,13 @@ rkpmic_clock_write(struct rkpmic_softc * 252 regs[6] = TOBCD(dt->dt_wday); 253 254 /* Stop RTC such that we can write to it. */ 255 - rkpmic_reg_write(sc, sc->sc_rtc_ctrl_reg, RK80X_RTC_CTRL_STOP_RTC); 256 + rkpmic_reg_write(sc, sc->sc_rtc_ctrl_reg, (variant818) ? 257 + RK818_RTC_CTRL_STOP_RTC : RK80X_RTC_CTRL_STOP_RTC); 258 259 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 260 error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 261 - &cmd, sizeof(cmd), regs, RK80X_NRTC_REGS, I2C_F_POLL); 262 + &cmd, sizeof(cmd), regs, (variant818) ? 263 + RK818_NRTC_REGS : RK80X_NRTC_REGS, I2C_F_POLL); 264 iic_release_bus(sc->sc_tag, I2C_F_POLL); 265 266 /* Restart RTC. */ 267 @@ -593,7 +727,8 @@ rkpmic_clock_write(struct rkpmic_softc * 268 } 269 270 /* Clear POWER_UP bit to indicate the time is now valid. */ 271 - rkpmic_reg_write(sc, sc->sc_rtc_status_reg, RK80X_RTC_STATUS_POWER_UP); 272 + rkpmic_reg_write(sc, sc->sc_rtc_status_reg, (variant818) ? 273 + RK818_RTC_STATUS_POWER_UP : RK80X_RTC_STATUS_POWER_UP); 274 275 return 0; 276 }