1*b59f66e1Schristos /* $NetBSD: tsrtc.c,v 1.8 2014/11/20 16:34:25 christos Exp $ */
2cff4f008Sjoff
3cff4f008Sjoff /*
4cff4f008Sjoff * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5cff4f008Sjoff * All rights reserved.
6cff4f008Sjoff *
7cff4f008Sjoff * Author: Chris G. Demetriou
8cff4f008Sjoff *
9cff4f008Sjoff * Permission to use, copy, modify and distribute this software and
10cff4f008Sjoff * its documentation is hereby granted, provided that both the copyright
11cff4f008Sjoff * notice and this permission notice appear in all copies of the
12cff4f008Sjoff * software, derivative works or modified versions, and any portions
13cff4f008Sjoff * thereof, and that both notices appear in supporting documentation.
14cff4f008Sjoff *
15cff4f008Sjoff * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16cff4f008Sjoff * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17cff4f008Sjoff * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18cff4f008Sjoff *
19cff4f008Sjoff * Carnegie Mellon requests users of this software to return to
20cff4f008Sjoff *
21cff4f008Sjoff * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22cff4f008Sjoff * School of Computer Science
23cff4f008Sjoff * Carnegie Mellon University
24cff4f008Sjoff * Pittsburgh PA 15213-3890
25cff4f008Sjoff *
26cff4f008Sjoff * any improvements or extensions that they make and grant Carnegie the
27cff4f008Sjoff * rights to redistribute these changes.
28cff4f008Sjoff */
29cff4f008Sjoff
30cff4f008Sjoff #include <sys/cdefs.h>
31*b59f66e1Schristos __KERNEL_RCSID(0, "$NetBSD: tsrtc.c,v 1.8 2014/11/20 16:34:25 christos Exp $");
32cff4f008Sjoff
33cff4f008Sjoff #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34cff4f008Sjoff
35cff4f008Sjoff #include <sys/param.h>
36cff4f008Sjoff #include <sys/kernel.h>
37cff4f008Sjoff #include <sys/systm.h>
38cff4f008Sjoff #include <sys/device.h>
39cff4f008Sjoff
40cf10107dSdyoung #include <sys/bus.h>
41cff4f008Sjoff
42cff4f008Sjoff #include <dev/clock_subr.h>
43cff4f008Sjoff #include <dev/ic/mc146818reg.h>
44cff4f008Sjoff #include <dev/ic/mc146818var.h>
45cff4f008Sjoff
46cff4f008Sjoff #include <evbarm/tsarm/tspldvar.h>
47cff4f008Sjoff #include <evbarm/tsarm/tsarmreg.h>
48cff4f008Sjoff
49048fb884Stsutsui int tsrtc_match(device_t, cfdata_t, void *);
50048fb884Stsutsui void tsrtc_attach(device_t, device_t, void *);
51cff4f008Sjoff
52cff4f008Sjoff struct tsrtc_softc {
53cff4f008Sjoff struct mc146818_softc sc_mc;
54cff4f008Sjoff bus_space_tag_t sc_iot;
55cff4f008Sjoff bus_space_handle_t sc_dath;
56cff4f008Sjoff bus_space_handle_t sc_idxh;
57cff4f008Sjoff };
58cff4f008Sjoff
59048fb884Stsutsui CFATTACH_DECL_NEW(tsrtc, sizeof (struct tsrtc_softc),
60cff4f008Sjoff tsrtc_match, tsrtc_attach, NULL, NULL);
61cff4f008Sjoff
62048fb884Stsutsui void tsrtc_write(struct mc146818_softc *, u_int, u_int);
63048fb884Stsutsui u_int tsrtc_read(struct mc146818_softc *, u_int);
64cff4f008Sjoff
65cff4f008Sjoff
66cff4f008Sjoff int
tsrtc_match(device_t parent,cfdata_t cf,void * aux)67048fb884Stsutsui tsrtc_match(device_t parent, cfdata_t cf, void *aux)
68cff4f008Sjoff {
69cff4f008Sjoff struct tspld_attach_args *aa = aux;
70703736dfStsutsui struct tsrtc_softc tsrtc, *tsc;
71703736dfStsutsui struct mc146818_softc *sc;
72cff4f008Sjoff unsigned int t1, t2;
73cff4f008Sjoff static int found = -1;
74cff4f008Sjoff
75048fb884Stsutsui if (found != -1)
76048fb884Stsutsui return found;
77cff4f008Sjoff
78703736dfStsutsui tsc = &tsrtc;
79703736dfStsutsui sc = &tsc->sc_mc;
80703736dfStsutsui tsc->sc_iot = aa->ta_iot;
81703736dfStsutsui if (bus_space_map(tsc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_RTCIDX, 1, 0,
82703736dfStsutsui &tsc->sc_idxh))
83cff4f008Sjoff return (0);
84703736dfStsutsui if (bus_space_map(tsc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_RTCDAT, 1, 0,
85703736dfStsutsui &tsc->sc_dath))
86cff4f008Sjoff return (0);
87cff4f008Sjoff
88cff4f008Sjoff /* Read from the seconds counter. */
89*b59f66e1Schristos t1 = bcdtobin(tsrtc_read(sc, MC_SEC));
90cff4f008Sjoff if (t1 > 59)
91cff4f008Sjoff goto unmap;
92cff4f008Sjoff
93cff4f008Sjoff /* Wait, then look again. */
94cff4f008Sjoff DELAY(1100000);
95*b59f66e1Schristos t2 = bcdtobin(tsrtc_read(sc, MC_SEC));
96cff4f008Sjoff if (t2 > 59)
97cff4f008Sjoff goto unmap;
98cff4f008Sjoff
99cff4f008Sjoff /* If [1,2) seconds have passed since, call it a clock. */
100cff4f008Sjoff if ((t1 + 1) % 60 == t2 || (t1 + 2) % 60 == t2)
101cff4f008Sjoff found = 1;
102cff4f008Sjoff
103cff4f008Sjoff unmap:
104703736dfStsutsui bus_space_unmap(tsc->sc_iot, tsc->sc_idxh, 1);
105703736dfStsutsui bus_space_unmap(tsc->sc_iot, tsc->sc_dath, 1);
106cff4f008Sjoff
107cff4f008Sjoff return (found);
108cff4f008Sjoff }
109cff4f008Sjoff
110cff4f008Sjoff void
tsrtc_attach(device_t parent,device_t self,void * aux)111048fb884Stsutsui tsrtc_attach(device_t parent, device_t self, void *aux)
112cff4f008Sjoff {
113703736dfStsutsui struct tsrtc_softc *tsc = device_private(self);
114703736dfStsutsui struct mc146818_softc *sc = &tsc->sc_mc;
115cff4f008Sjoff struct tspld_attach_args *aa = aux;
116cff4f008Sjoff
1174090172bStsutsui sc->sc_dev = self;
118703736dfStsutsui tsc->sc_iot = aa->ta_iot;
119703736dfStsutsui if (bus_space_map(tsc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_RTCIDX,
120703736dfStsutsui 1, 0, &tsc->sc_idxh))
121cff4f008Sjoff panic("tsrtc_attach: couldn't map clock I/O space");
122703736dfStsutsui if (bus_space_map(tsc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_RTCDAT,
123703736dfStsutsui 1, 0, &tsc->sc_dath))
124cff4f008Sjoff panic("tsrtc_attach: couldn't map clock I/O space");
125cff4f008Sjoff
126703736dfStsutsui sc->sc_year0 = 2000;
127703736dfStsutsui sc->sc_mcread = tsrtc_read;
128703736dfStsutsui sc->sc_mcwrite = tsrtc_write;
129703736dfStsutsui sc->sc_flag = MC146818_BCD;
130703736dfStsutsui mc146818_attach(sc);
131cff4f008Sjoff
132703736dfStsutsui aprint_normal("\n");
133cff4f008Sjoff
134703736dfStsutsui (*sc->sc_mcwrite)(sc, MC_REGB, MC_REGB_24HR);
135cff4f008Sjoff }
136cff4f008Sjoff
137cff4f008Sjoff void
tsrtc_write(struct mc146818_softc * mc_sc,u_int reg,u_int datum)138048fb884Stsutsui tsrtc_write(struct mc146818_softc *mc_sc, u_int reg, u_int datum)
139cff4f008Sjoff {
140cff4f008Sjoff struct tsrtc_softc *sc = (struct tsrtc_softc *)mc_sc;
141cff4f008Sjoff
142cff4f008Sjoff bus_space_write_1(sc->sc_iot, sc->sc_idxh, 0, reg);
143cff4f008Sjoff bus_space_write_1(sc->sc_iot, sc->sc_dath, 0, datum);
144cff4f008Sjoff }
145cff4f008Sjoff
146cff4f008Sjoff u_int
tsrtc_read(struct mc146818_softc * mc_sc,u_int reg)147048fb884Stsutsui tsrtc_read(struct mc146818_softc *mc_sc, u_int reg)
148cff4f008Sjoff {
149cff4f008Sjoff struct tsrtc_softc *sc = (struct tsrtc_softc *)mc_sc;
150cff4f008Sjoff u_int datum;
151cff4f008Sjoff
152cff4f008Sjoff bus_space_write_1(sc->sc_iot, sc->sc_idxh, 0, reg);
153cff4f008Sjoff datum = bus_space_read_1(sc->sc_iot, sc->sc_dath, 0);
154cff4f008Sjoff
155cff4f008Sjoff return (datum);
156cff4f008Sjoff }
157