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 }