]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/amlogic/aml8726/aml8726_rtc.c
Upgrade Unbound to 1.8.0. More to follow.
[FreeBSD/FreeBSD.git] / sys / arm / amlogic / aml8726 / aml8726_rtc.c
1 /*-
2  * Copyright 2013-2015 John Wehle <john@feith.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 /*
28  * Amlogic aml8726 RTC driver.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/clock.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
40 #include <sys/lock.h>
41 #include <sys/mutex.h>
42 #include <sys/resource.h>
43 #include <sys/rman.h>
44
45 #include <sys/time.h>
46
47 #include <machine/bus.h>
48 #include <machine/cpu.h>
49
50 #include <dev/ofw/ofw_bus.h>
51 #include <dev/ofw/ofw_bus_subr.h>
52
53 #include <arm/amlogic/aml8726/aml8726_soc.h>
54
55 #include "clock_if.h"
56
57 /*
58  * The RTC initialization various slightly between the different chips.
59  *
60  *                 aml8726-m1     aml8726-m3     aml8726-m6 (and later)
61  *  init-always    true           true           false
62  *  xo-init        0x0004         0x3c0a         0x180a
63  *  gpo-init       0x100000       0x100000       0x500000
64  */
65
66 struct aml8726_rtc_init {
67         boolean_t       always;
68         uint16_t        xo;
69         uint32_t        gpo;
70 };
71
72 struct aml8726_rtc_softc {
73         device_t                dev;
74         struct aml8726_rtc_init init;
75         struct resource *       res[2];
76         struct mtx              mtx;
77 };
78
79 static struct resource_spec aml8726_rtc_spec[] = {
80         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
81         { SYS_RES_IRQ,          0,      RF_ACTIVE },
82         { -1, 0 }
83 };
84
85 #define AML_RTC_LOCK(sc)                mtx_lock_spin(&(sc)->mtx)
86 #define AML_RTC_UNLOCK(sc)              mtx_unlock_spin(&(sc)->mtx)
87 #define AML_RTC_LOCK_INIT(sc)           \
88     mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),        \
89     "rtc", MTX_SPIN)
90 #define AML_RTC_LOCK_DESTROY(sc)        mtx_destroy(&(sc)->mtx);
91
92 #define AML_RTC_0_REG                   0
93 #define AML_RTC_SCLK                    (1 << 0)
94 #define AML_RTC_SDI                     (1 << 2)
95 #define AML_RTC_SEN                     (1 << 1)
96 #define AML_RTC_AS                      (1 << 17)
97 #define AML_RTC_ABSY                    (1 << 22)
98 #define AML_RTC_IRQ_DIS                 (1 << 12)
99 #define AML_RTC_1_REG                   4
100 #define AML_RTC_SDO                     (1 << 0)
101 #define AML_RTC_SRDY                    (1 << 1)
102 #define AML_RTC_2_REG                   8
103 #define AML_RTC_3_REG                   12
104 #define AML_RTC_MSR_BUSY                (1 << 20)
105 #define AML_RTC_MSR_CA                  (1 << 17)
106 #define AML_RTC_MSR_DURATION_EN         (1 << 16)
107 #define AML_RTC_MSR_DURATION_MASK       0xffff
108 #define AML_RTC_MSR_DURATION_SHIFT      0
109 #define AML_RTC_4_REG                   16
110
111 #define AML_RTC_TIME_SREG               0
112 #define AML_RTC_GPO_SREG                1
113 #define AML_RTC_GPO_LEVEL               (1 << 24)
114 #define AML_RTC_GPO_BUSY                (1 << 23)
115 #define AML_RTC_GPO_ACTIVE_HIGH         (1 << 22)
116 #define AML_RTC_GPO_CMD_MASK            (3 << 20)
117 #define AML_RTC_GPO_CMD_SHIFT           20
118 #define AML_RTC_GPO_CMD_NOW             (1 << 20)
119 #define AML_RTC_GPO_CMD_COUNT           (2 << 20)
120 #define AML_RTC_GPO_CMD_PULSE           (3 << 20)
121 #define AML_RTC_GPO_CNT_MASK            0xfffff
122 #define AML_RTC_GPO_CNT_SHIFT           0
123
124 #define CSR_WRITE_4(sc, reg, val)       bus_write_4((sc)->res[0], reg, (val))
125 #define CSR_READ_4(sc, reg)             bus_read_4((sc)->res[0], reg)
126 #define CSR_BARRIER(sc, reg)            bus_barrier((sc)->res[0], reg, 4, \
127     (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE))
128
129 static int
130 aml8726_rtc_start_transfer(struct aml8726_rtc_softc *sc)
131 {
132         unsigned i;
133
134         /* idle the serial interface */
135         CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) &
136             ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI)));
137
138         CSR_BARRIER(sc, AML_RTC_0_REG);
139
140         /* see if it is ready for a new cycle */
141         for (i = 40; i; i--) {
142                 DELAY(5);
143                 if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) )
144                         break;
145         }
146
147         if (i == 0)
148                 return (EIO);
149
150         /* start the cycle */
151         CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) |
152             AML_RTC_SEN));
153
154         return (0);
155 }
156
157 static inline void
158 aml8726_rtc_sclk_pulse(struct aml8726_rtc_softc *sc)
159 {
160
161         DELAY(5);
162
163         CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) |
164             AML_RTC_SCLK));
165
166         CSR_BARRIER(sc, AML_RTC_0_REG);
167
168         DELAY(5);
169
170         CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) &
171             ~AML_RTC_SCLK));
172
173         CSR_BARRIER(sc, AML_RTC_0_REG);
174 }
175
176 static inline void
177 aml8726_rtc_send_bit(struct aml8726_rtc_softc *sc, unsigned bit)
178 {
179
180         if (bit) {
181                 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) |
182                     AML_RTC_SDI));
183         } else {
184                 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) &
185                     ~AML_RTC_SDI));
186         }
187
188         aml8726_rtc_sclk_pulse(sc);
189 }
190
191 static inline void
192 aml8726_rtc_send_addr(struct aml8726_rtc_softc *sc, u_char addr)
193 {
194         unsigned mask;
195
196         for (mask = 1 << 3; mask; mask >>= 1) {
197                 if (mask == 1) {
198                         /* final bit indicates read / write mode */
199                         CSR_WRITE_4(sc, AML_RTC_0_REG,
200                             (CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SEN));
201                 }
202                 aml8726_rtc_send_bit(sc, (addr & mask));
203         }
204 }
205
206 static inline void
207 aml8726_rtc_send_data(struct aml8726_rtc_softc *sc, uint32_t data)
208 {
209         unsigned mask;
210
211         for (mask = 1U << 31; mask; mask >>= 1)
212                 aml8726_rtc_send_bit(sc, (data & mask));
213 }
214
215 static inline void
216 aml8726_rtc_recv_data(struct aml8726_rtc_softc *sc, uint32_t *dp)
217 {
218         uint32_t data;
219         unsigned i;
220
221         data = 0;
222
223         for (i = 0; i < 32; i++) {
224                 aml8726_rtc_sclk_pulse(sc);
225                 data <<= 1;
226                 data |= (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SDO) ? 1 : 0;
227         }
228
229         *dp = data;
230 }
231
232 static int
233 aml8726_rtc_sreg_read(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t *val)
234 {
235         u_char addr;
236         int error;
237
238         /* read is indicated by lsb = 0 */
239         addr = (sreg << 1) | 0;
240
241         error = aml8726_rtc_start_transfer(sc);
242
243         if (error)
244                 return (error);
245
246         aml8726_rtc_send_addr(sc, addr);
247         aml8726_rtc_recv_data(sc, val);
248
249         return (0);
250 }
251
252 static int
253 aml8726_rtc_sreg_write(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t val)
254 {
255         u_char addr;
256         int error;
257
258         /* write is indicated by lsb = 1 */
259         addr = (sreg << 1) | 1;
260
261         error = aml8726_rtc_start_transfer(sc);
262
263         if (error)
264                 return (error);
265
266         aml8726_rtc_send_data(sc, val);
267         aml8726_rtc_send_addr(sc, addr);
268
269         return (0);
270 }
271
272 static int
273 aml8726_rtc_initialize(struct aml8726_rtc_softc *sc)
274 {
275         int error;
276         unsigned i;
277
278         /* idle the serial interface */
279         CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) &
280             ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI)));
281
282         CSR_BARRIER(sc, AML_RTC_0_REG);
283
284         /* see if it is ready for a new cycle */
285         for (i = 40; i; i--) {
286                 DELAY(5);
287                 if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) )
288                         break;
289         }
290
291         if (sc->init.always == TRUE || (CSR_READ_4(sc, AML_RTC_1_REG) &
292             AML_RTC_SRDY) == 0) {
293
294                 /*
295                  * The RTC has a 16 bit initialization register.  The upper
296                  * bits can be written directly.  The lower bits are written
297                  * through a shift register.
298                  */
299
300                 CSR_WRITE_4(sc, AML_RTC_4_REG, ((sc->init.xo >> 8) & 0xff));
301
302                 CSR_WRITE_4(sc, AML_RTC_0_REG,
303                     ((CSR_READ_4(sc, AML_RTC_0_REG) & 0xffffff) |
304                     ((uint32_t)(sc->init.xo & 0xff) << 24) | AML_RTC_AS |
305                     AML_RTC_IRQ_DIS));
306
307                 while ((CSR_READ_4(sc, AML_RTC_0_REG) & AML_RTC_ABSY) != 0)
308                         cpu_spinwait();
309
310                 DELAY(2);
311
312                 error = aml8726_rtc_sreg_write(sc, AML_RTC_GPO_SREG,
313                     sc->init.gpo);
314
315                 if (error)
316                         return (error);
317         }
318
319         return (0);
320 }
321
322 static int
323 aml8726_rtc_check_xo(struct aml8726_rtc_softc *sc)
324 {
325         uint32_t now, previous;
326         int i;
327
328         /*
329          * The RTC is driven by a 32.768khz clock meaning it's period
330          * is roughly 30.5 us.  Check that it's working (implying the
331          * RTC could contain a valid value) by enabling count always
332          * and seeing if the value changes after 200 us (per RTC User
333          * Guide ... presumably the extra time is to cover XO startup).
334          */
335
336         CSR_WRITE_4(sc, AML_RTC_3_REG, (CSR_READ_4(sc, AML_RTC_3_REG) |
337             AML_RTC_MSR_CA));
338
339         previous = CSR_READ_4(sc, AML_RTC_2_REG);
340
341         for (i = 0; i < 4; i++) {
342                 DELAY(50);
343                 now = CSR_READ_4(sc, AML_RTC_2_REG);
344                 if (now != previous)
345                         break;
346         }
347
348         CSR_WRITE_4(sc, AML_RTC_3_REG, (CSR_READ_4(sc, AML_RTC_3_REG) &
349             ~AML_RTC_MSR_CA));
350
351         if (now == previous)
352                 return (EINVAL);
353
354         return (0);
355 }
356
357 static int
358 aml8726_rtc_probe(device_t dev)
359 {
360
361         if (!ofw_bus_status_okay(dev))
362                 return (ENXIO);
363
364         if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rtc"))
365                 return (ENXIO);
366
367         device_set_desc(dev, "Amlogic aml8726 RTC");
368
369         return (BUS_PROBE_DEFAULT);
370 }
371
372 static int
373 aml8726_rtc_attach(device_t dev)
374 {
375         struct aml8726_rtc_softc *sc = device_get_softc(dev);
376
377         sc->dev = dev;
378
379         switch (aml8726_soc_hw_rev) {
380         case AML_SOC_HW_REV_M3:
381                 sc->init.always = true;
382                 sc->init.xo = 0x3c0a;
383                 sc->init.gpo = 0x100000;
384                 break;
385         case AML_SOC_HW_REV_M6:
386         case AML_SOC_HW_REV_M8:
387         case AML_SOC_HW_REV_M8B:
388                 sc->init.always = false;
389                 sc->init.xo = 0x180a;
390                 sc->init.gpo = 0x500000;
391                 break;
392         default:
393                 device_printf(dev, "unsupported SoC\n");
394                 return (ENXIO);
395                 /* NOTREACHED */
396         }
397
398         if (bus_alloc_resources(dev, aml8726_rtc_spec, sc->res)) {
399                 device_printf(dev, "can not allocate resources for device\n");
400                 return (ENXIO);
401         }
402
403         aml8726_rtc_initialize(sc);
404
405         if (aml8726_rtc_check_xo(sc) != 0) {
406                 device_printf(dev, "crystal oscillator check failed\n");
407
408                 bus_release_resources(dev, aml8726_rtc_spec, sc->res);
409
410                 return (ENXIO);
411         }
412
413         AML_RTC_LOCK_INIT(sc);
414
415         clock_register(dev, 1000000);
416
417         return (0);
418 }
419
420 static int
421 aml8726_rtc_detach(device_t dev)
422 {
423
424         return (EBUSY);
425 }
426
427 static int
428 aml8726_rtc_gettime(device_t dev, struct timespec *ts)
429 {
430         struct aml8726_rtc_softc *sc = device_get_softc(dev);
431         uint32_t sec;
432         int error;
433
434         AML_RTC_LOCK(sc);
435
436         error = aml8726_rtc_sreg_read(sc, AML_RTC_TIME_SREG, &sec);
437
438         AML_RTC_UNLOCK(sc);
439
440         ts->tv_sec = sec;
441         ts->tv_nsec = 0;
442
443         return (error);
444 }
445
446 static int
447 aml8726_rtc_settime(device_t dev, struct timespec *ts)
448 {
449         struct aml8726_rtc_softc *sc = device_get_softc(dev);
450         uint32_t sec;
451         int error;
452
453         sec = ts->tv_sec;
454
455         /* Accuracy is only one second. */
456         if (ts->tv_nsec >= 500000000)
457                 sec++;
458
459         AML_RTC_LOCK(sc);
460
461         error = aml8726_rtc_sreg_write(sc, AML_RTC_TIME_SREG, sec);
462
463         AML_RTC_UNLOCK(sc);
464
465         return (error); 
466 }
467
468 static device_method_t aml8726_rtc_methods[] = {
469         /* Device interface */
470         DEVMETHOD(device_probe,         aml8726_rtc_probe),
471         DEVMETHOD(device_attach,        aml8726_rtc_attach),
472         DEVMETHOD(device_detach,        aml8726_rtc_detach),
473
474         /* Clock interface */
475         DEVMETHOD(clock_gettime,        aml8726_rtc_gettime),
476         DEVMETHOD(clock_settime,        aml8726_rtc_settime),
477
478         DEVMETHOD_END
479 };
480
481 static driver_t aml8726_rtc_driver = {
482         "rtc",
483         aml8726_rtc_methods,
484         sizeof(struct aml8726_rtc_softc),
485 };
486
487 static devclass_t aml8726_rtc_devclass;
488
489 DRIVER_MODULE(rtc, simplebus, aml8726_rtc_driver, aml8726_rtc_devclass, 0, 0);