1 /* $NetBSD: meson_rtc.c,v 1.3 2021/01/27 03:10:18 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2015 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: meson_rtc.c,v 1.3 2021/01/27 03:10:18 thorpej Exp $");
31
32 #include <sys/param.h>
33 #include <sys/atomic.h>
34 #include <sys/device.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
37
38 #include <dev/clock_subr.h>
39
40 #include <arm/amlogic/meson_rtcreg.h>
41
42 #include <dev/fdt/fdtvar.h>
43
44 #define RESET_RETRY_TIMES 3
45 #define RTC_COMM_DELAY 5
46 #define RTC_RESET_DELAY 100
47 #define RTC_STATIC_VALUE_INIT 0x180a /* XXX: MAGIC? */
48
49 struct meson_rtc_softc {
50 device_t sc_dev;
51 bus_space_tag_t sc_bst;
52 bus_space_handle_t sc_bsh;
53 struct todr_chip_handle sc_todr;
54 int sc_osc_failed;
55 unsigned int sc_busy;
56 };
57
58 static const struct device_compatible_entry compat_data[] = {
59 { .compat = "amlogic,meson8b-rtc" },
60 DEVICE_COMPAT_EOL
61 };
62
63 static int meson_rtc_match(device_t, cfdata_t, void *);
64 static void meson_rtc_attach(device_t, device_t, void *);
65 static int meson_rtc_todr_gettime(todr_chip_handle_t, struct timeval *);
66 static int meson_rtc_todr_settime(todr_chip_handle_t, struct timeval *);
67
68 CFATTACH_DECL_NEW(meson_rtc, sizeof(struct meson_rtc_softc),
69 meson_rtc_match, meson_rtc_attach, NULL, NULL);
70
71 #define RTC_WRITE(sc, reg, val) \
72 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
73 #define RTC_READ(sc, reg) \
74 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
75
76 static inline void
setbits(struct meson_rtc_softc * sc,uint32_t reg,uint32_t bits)77 setbits(struct meson_rtc_softc *sc, uint32_t reg, uint32_t bits)
78 {
79
80 RTC_WRITE(sc, reg, RTC_READ(sc, reg) | bits);
81 }
82
83 static inline void
clrbits(struct meson_rtc_softc * sc,uint32_t reg,uint32_t bits)84 clrbits(struct meson_rtc_softc *sc, uint32_t reg, uint32_t bits)
85 {
86
87 RTC_WRITE(sc, reg, RTC_READ(sc, reg) & ~bits);
88 }
89
90 static int
meson_rtc_check_osc_clk(struct meson_rtc_softc * sc)91 meson_rtc_check_osc_clk(struct meson_rtc_softc *sc)
92 {
93 uint32_t cnt1, cnt2;
94
95 setbits(sc, AO_RTC_REG3, AO_RTC_REG3_COUNT_ALWAYS);
96
97 /*
98 * Wait for 50uS. 32.768khz is 30.5uS. This should be long
99 * enough for one full cycle of 32.768 khz.
100 */
101 cnt1 = RTC_READ(sc, AO_RTC_REG2);
102 delay(50);
103 cnt2 = RTC_READ(sc, AO_RTC_REG2);
104
105 clrbits(sc, AO_RTC_REG3, AO_RTC_REG3_COUNT_ALWAYS);
106
107 return cnt1 == cnt2;
108 }
109
110 static int
meson_rtc_match(device_t parent,cfdata_t cf,void * aux)111 meson_rtc_match(device_t parent, cfdata_t cf, void *aux)
112 {
113 struct fdt_attach_args * const faa = aux;
114
115 return of_compatible_match(faa->faa_phandle, compat_data);
116 }
117
118 static void
meson_rtc_attach(device_t parent,device_t self,void * aux)119 meson_rtc_attach(device_t parent, device_t self, void *aux)
120 {
121 struct meson_rtc_softc * const sc = device_private(self);
122 struct fdt_attach_args * const faa = aux;
123 const int phandle = faa->faa_phandle;
124 bus_addr_t addr;
125 bus_size_t size;
126
127 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
128 aprint_error(": couldn't map registers\n");
129 return;
130 }
131
132 sc->sc_dev = self;
133 sc->sc_bst = faa->faa_bst;
134 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
135 aprint_error(": couldn't map registers\n");
136 return;
137 }
138
139 sc->sc_osc_failed = meson_rtc_check_osc_clk(sc);
140
141 memset(&sc->sc_todr, 0, sizeof(sc->sc_todr));
142 sc->sc_todr.cookie = sc;
143 sc->sc_todr.todr_gettime = meson_rtc_todr_gettime;
144 sc->sc_todr.todr_settime = meson_rtc_todr_settime;
145
146 aprint_naive("\n");
147 aprint_normal(": RTC");
148 if (sc->sc_osc_failed) {
149 aprint_normal(" battery not present or discharged\n");
150 } else {
151 aprint_normal("\n");
152 fdtbus_todr_attach(self, phandle, &sc->sc_todr);
153 }
154 }
155
156 static void
meson_rtc_sclk_pulse(struct meson_rtc_softc * sc)157 meson_rtc_sclk_pulse(struct meson_rtc_softc *sc)
158 {
159
160 delay(RTC_COMM_DELAY);
161 setbits(sc, AO_RTC_REG0, AO_RTC_REG0_SCLK);
162
163 delay(RTC_COMM_DELAY);
164 clrbits(sc, AO_RTC_REG0, AO_RTC_REG0_SCLK);
165 }
166
167 static void
meson_rtc_send_bit(struct meson_rtc_softc * sc,uint32_t bitset)168 meson_rtc_send_bit(struct meson_rtc_softc *sc, uint32_t bitset)
169 {
170
171 if (bitset)
172 setbits(sc, AO_RTC_REG0, AO_RTC_REG0_SDI);
173 else
174 clrbits(sc, AO_RTC_REG0, AO_RTC_REG0_SDI);
175
176 meson_rtc_sclk_pulse(sc);
177 }
178
179 #define SERIAL_ADDR_BITS 3
180 #define SERIAL_DATA_BITS 32
181 #define SERIAL_TYPE_ADDR (1 << (SERIAL_ADDR_BITS - 1))
182 #define SERIAL_TYPE_DATA (1 << (SERIAL_DATA_BITS - 1))
183
184 static void
meson_rtc_send_data(struct meson_rtc_softc * sc,uint32_t nextbit,uint32_t data)185 meson_rtc_send_data(struct meson_rtc_softc *sc,
186 uint32_t nextbit, uint32_t data)
187 {
188
189 KASSERT(nextbit == SERIAL_TYPE_ADDR || nextbit == SERIAL_TYPE_DATA);
190
191 while (nextbit) {
192 meson_rtc_send_bit(sc, data & nextbit);
193 nextbit >>= 1;
194 }
195 }
196
197 static uint32_t
meson_rtc_get_data(struct meson_rtc_softc * sc)198 meson_rtc_get_data(struct meson_rtc_softc *sc)
199 {
200 uint32_t data;
201 size_t i;
202
203 data = 0;
204 for (i = 0; i < SERIAL_DATA_BITS; i++) {
205 meson_rtc_sclk_pulse(sc);
206 data <<= 1;
207 data |= __SHIFTOUT(RTC_READ(sc, AO_RTC_REG1), AO_RTC_REG1_SDO);
208 }
209 return data;
210 }
211
212 enum serial_mode {
213 SERIAL_MODE_READ,
214 SERIAL_MODE_WRITE,
215 };
216
217 static void
meson_rtc_set_mode(struct meson_rtc_softc * sc,enum serial_mode mode)218 meson_rtc_set_mode(struct meson_rtc_softc *sc, enum serial_mode mode)
219 {
220
221 clrbits(sc, AO_RTC_REG0, AO_RTC_REG0_SEN);
222
223 switch(mode) {
224 case SERIAL_MODE_READ:
225 clrbits(sc, AO_RTC_REG0, AO_RTC_REG0_SDI);
226 break;
227 case SERIAL_MODE_WRITE:
228 setbits(sc, AO_RTC_REG0, AO_RTC_REG0_SDI);
229 break;
230 default:
231 KASSERT(1);
232 return;
233 }
234 meson_rtc_sclk_pulse(sc);
235
236 clrbits(sc, AO_RTC_REG0, AO_RTC_REG0_SDI);
237 }
238
239 static int
meson_rtc_wait_s_ready(struct meson_rtc_softc * sc)240 meson_rtc_wait_s_ready(struct meson_rtc_softc *sc)
241 {
242 size_t s_nrdy_cnt, retry_cnt;
243
244 s_nrdy_cnt = 40000;
245 retry_cnt = 0;
246 while (!(RTC_READ(sc, AO_RTC_REG1) & AO_RTC_REG1_S_READY)) {
247 if (s_nrdy_cnt-- == 0) {
248 s_nrdy_cnt = 40000;
249 if (retry_cnt++ == RESET_RETRY_TIMES)
250 return 0;
251 /* XXX: reset_s_ready? Linux does not. */
252 setbits(sc, AO_RTC_REG1, AO_RTC_REG1_S_READY);
253 delay(RTC_RESET_DELAY);
254 }
255 }
256 return 1;
257 }
258
259 static int
meson_rtc_comm_init(struct meson_rtc_softc * sc)260 meson_rtc_comm_init(struct meson_rtc_softc *sc)
261 {
262
263 clrbits(sc, AO_RTC_REG0,
264 AO_RTC_REG0_SEN | AO_RTC_REG0_SCLK | AO_RTC_REG0_SDI);
265
266 if (meson_rtc_wait_s_ready(sc)) {
267 setbits(sc, AO_RTC_REG0, AO_RTC_REG0_SEN);
268 return 0;
269 }
270 return -1;
271 }
272
273 static void
meson_rtc_static_register_write(struct meson_rtc_softc * sc,uint32_t data)274 meson_rtc_static_register_write(struct meson_rtc_softc *sc, uint32_t data)
275 {
276 uint32_t u;
277
278 /* Program MSB 15-8 */
279 u = RTC_READ(sc, AO_RTC_REG4);
280 u &= AO_RTC_REG4_STATIC_REG_MSB;
281 u |= __SHIFTIN(data, AO_RTC_REG4_STATIC_REG_MSB);
282 RTC_WRITE(sc, AO_RTC_REG4, u);
283
284 /* Program LSB 7-0, and start serializing */
285 u = RTC_READ(sc, AO_RTC_REG0);
286 u &= ~AO_RTC_REG0_STATIC_REG_LSB;
287 u |= __SHIFTIN(data, AO_RTC_REG0_STATIC_REG_LSB);
288 u |= AO_RTC_REG0_SERIAL_START;
289 RTC_WRITE(sc, AO_RTC_REG0, u);
290
291 /* Poll auto_serializer_busy bit until it's low (IDLE) */
292 while ((RTC_READ(sc, AO_RTC_REG0) & AO_RTC_REG0_SERIAL_BUSY) != 0)
293 continue;
294 }
295
296 static void
meson_rtc_reset(struct meson_rtc_softc * sc)297 meson_rtc_reset(struct meson_rtc_softc *sc)
298 {
299
300 meson_rtc_static_register_write(sc, RTC_STATIC_VALUE_INIT);
301 }
302
303 static int
meson_rtc_serial_init(struct meson_rtc_softc * sc)304 meson_rtc_serial_init(struct meson_rtc_softc *sc)
305 {
306 size_t init_cnt, retry_cnt;
307
308 init_cnt = 0;
309 retry_cnt = 0;
310 while (meson_rtc_comm_init(sc) == -1) {
311 if (init_cnt++ == RESET_RETRY_TIMES) {
312 init_cnt = 0;
313 if (retry_cnt++ == RESET_RETRY_TIMES) {
314 aprint_error_dev(sc->sc_dev,
315 "cannot init rtc\n");
316 return -1;
317 }
318 meson_rtc_reset(sc);
319 }
320 delay(RTC_RESET_DELAY);
321 }
322 return 0;
323 }
324
325 static int
meson_rtc_serial_read(struct meson_rtc_softc * sc,uint32_t addr,uint32_t * sec)326 meson_rtc_serial_read(struct meson_rtc_softc *sc, uint32_t addr,
327 uint32_t *sec)
328 {
329
330 if (meson_rtc_serial_init(sc) == -1)
331 return EIO;
332
333 meson_rtc_send_data(sc, SERIAL_TYPE_ADDR, addr);
334 meson_rtc_set_mode(sc, SERIAL_MODE_READ);
335 *sec = meson_rtc_get_data(sc);
336 return 0;
337 }
338
339 static int
meson_rtc_serial_write(struct meson_rtc_softc * sc,uint32_t addr,uint32_t data)340 meson_rtc_serial_write(struct meson_rtc_softc *sc, uint32_t addr,
341 uint32_t data)
342 {
343
344 if (meson_rtc_serial_init(sc) == -1)
345 return EIO;
346
347 meson_rtc_send_data(sc, SERIAL_TYPE_DATA, data);
348 meson_rtc_send_data(sc, SERIAL_TYPE_ADDR, addr);
349 meson_rtc_set_mode(sc, SERIAL_MODE_WRITE);
350 return 0;
351 }
352
353 static int
meson_rtc_todr_gettime(todr_chip_handle_t ch,struct timeval * tv)354 meson_rtc_todr_gettime(todr_chip_handle_t ch, struct timeval *tv)
355 {
356 struct meson_rtc_softc * const sc = ch->cookie;
357 uint32_t sec;
358 int rv;
359
360 if (atomic_swap_uint(&sc->sc_busy, 1))
361 return EBUSY; /* XXX: EAGAIN? */
362
363 rv = meson_rtc_serial_read(sc, RTC_COUNTER_ADDR, &sec);
364 sc->sc_busy = 0;
365
366 if (rv == 0) {
367 tv->tv_sec = sec;
368 tv->tv_usec = 0;
369 }
370 return rv;
371 }
372
373 static int
meson_rtc_todr_settime(todr_chip_handle_t ch,struct timeval * tv)374 meson_rtc_todr_settime(todr_chip_handle_t ch, struct timeval *tv)
375 {
376 struct meson_rtc_softc * const sc = ch->cookie;
377 int rv;
378
379 if (atomic_swap_uint(&sc->sc_busy, 1))
380 return EBUSY; /* XXX: EAGAIN? */
381
382 rv = meson_rtc_serial_write(sc, RTC_COUNTER_ADDR, tv->tv_sec);
383 sc->sc_busy = 0;
384
385 return rv;
386 }
387