1 /* $NetBSD: dsclock.c,v 1.1 2009/02/12 06:33:57 rumble Exp $ */
4 * Copyright (c) 2001 Rafal K. Boni
5 * Copyright (c) 2001 Christopher Sekiya
6 * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
9 * Portions of this code are derived from software contributed to The
10 * NetBSD Foundation by Jason R. Thorpe of the Numerical Aerospace
11 * Simulation Facility, NASA Ames Research Center.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: dsclock.c,v 1.1 2009/02/12 06:33:57 rumble Exp $");
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
44 #include <machine/bus.h>
45 #include <machine/autoconf.h>
46 #include <machine/sysconf.h>
47 #include <machine/machtype.h>
49 #include <dev/clock_subr.h>
50 #include <dev/ic/ds1286reg.h>
52 #include <sgimips/sgimips/clockvar.h>
54 struct dsclock_softc
{
57 struct todr_chip_handle sc_todrch
;
60 bus_space_tag_t sc_rtct
;
61 bus_space_handle_t sc_rtch
;
64 static int dsclock_match(struct device
*, struct cfdata
*, void *);
65 static void dsclock_attach(struct device
*, struct device
*, void *);
66 static int dsclock_gettime(struct todr_chip_handle
*, struct timeval
*);
67 static int dsclock_settime(struct todr_chip_handle
*, struct timeval
*);
69 CFATTACH_DECL(dsclock
, sizeof(struct dsclock_softc
),
70 dsclock_match
, dsclock_attach
, NULL
, NULL
);
72 #define ds1286_write(dev, reg, datum) \
73 bus_space_write_1(dev->sc_rtct, dev->sc_rtch, reg, datum)
74 #define ds1286_read(dev, reg) \
75 (bus_space_read_1(dev->sc_rtct, dev->sc_rtch, reg))
78 dsclock_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
80 struct mainbus_attach_args
*ma
= aux
;
82 if (mach_type
== MACH_SGI_IP22
&& ma
->ma_addr
== 0x1fbe0000)
89 dsclock_attach(struct device
*parent
, struct device
*self
, void *aux
)
91 struct dsclock_softc
*sc
= (void *)self
;
92 struct mainbus_attach_args
*ma
= aux
;
97 sc
->sc_rtct
= SGIMIPS_BUS_SPACE_HPC
;
98 if ((err
= bus_space_map(sc
->sc_rtct
, ma
->ma_addr
, 0x1ffff,
99 BUS_SPACE_MAP_LINEAR
, &sc
->sc_rtch
)) != 0) {
100 printf(": unable to map RTC registers, error = %d\n", err
);
104 sc
->sc_todrch
.cookie
= sc
;
105 sc
->sc_todrch
.todr_gettime
= dsclock_gettime
;
106 sc
->sc_todrch
.todr_settime
= dsclock_settime
;
107 sc
->sc_todrch
.todr_setwen
= NULL
;
109 todr_attach(&sc
->sc_todrch
);
113 * Get the time of day, based on the clock's value and/or the base value.
116 dsclock_gettime(struct todr_chip_handle
*todrch
, struct timeval
*tv
)
118 struct dsclock_softc
*sc
= (struct dsclock_softc
*)todrch
->cookie
;
119 struct clock_ymdhms dt
;
124 DS1286_GETTOD(sc
, ®s
)
127 dt
.dt_sec
= FROMBCD(regs
[DS1286_SEC
]);
128 dt
.dt_min
= FROMBCD(regs
[DS1286_MIN
]);
130 if (regs
[DS1286_HOUR
] & DS1286_HOUR_12MODE
) {
131 dt
.dt_hour
= FROMBCD(regs
[DS1286_HOUR
] & DS1286_HOUR_12HR_MASK
)
132 + ((regs
[DS1286_HOUR
] & DS1286_HOUR_12HR_PM
) ? 12 : 0);
135 * In AM/PM mode, hour range is 01-12, so adding in 12 hours
136 * for PM gives us 01-24, whereas we want 00-23, so map hour
139 if (dt
.dt_hour
== 24)
142 dt
.dt_hour
= FROMBCD(regs
[DS1286_HOUR
] & DS1286_HOUR_24HR_MASK
);
145 dt
.dt_wday
= FROMBCD(regs
[DS1286_DOW
]);
146 dt
.dt_day
= FROMBCD(regs
[DS1286_DOM
]);
147 dt
.dt_mon
= FROMBCD(regs
[DS1286_MONTH
] & DS1286_MONTH_MASK
);
148 dt
.dt_year
= FROM_IRIX_YEAR(FROMBCD(regs
[DS1286_YEAR
]));
150 /* simple sanity checks */
151 if (dt
.dt_mon
> 12 || dt
.dt_day
> 31 ||
152 dt
.dt_hour
>= 24 || dt
.dt_min
>= 60 || dt
.dt_sec
>= 60)
155 tv
->tv_sec
= (long)clock_ymdhms_to_secs(&dt
);
156 if (tv
->tv_sec
== -1)
164 * Reset the TODR based on the time value.
167 dsclock_settime(struct todr_chip_handle
*todrch
, struct timeval
*tv
)
169 struct dsclock_softc
*sc
= (struct dsclock_softc
*)todrch
->cookie
;
170 struct clock_ymdhms dt
;
174 clock_secs_to_ymdhms((time_t)(tv
->tv_sec
+ (tv
->tv_usec
> 500000)),&dt
);
177 DS1286_GETTOD(sc
, ®s
);
180 regs
[DS1286_SUBSEC
] = 0;
181 regs
[DS1286_SEC
] = TOBCD(dt
.dt_sec
);
182 regs
[DS1286_MIN
] = TOBCD(dt
.dt_min
);
183 regs
[DS1286_HOUR
] = TOBCD(dt
.dt_hour
) & DS1286_HOUR_24HR_MASK
;
184 regs
[DS1286_DOW
] = TOBCD(dt
.dt_wday
);
185 regs
[DS1286_DOM
] = TOBCD(dt
.dt_day
);
187 /* Leave wave-generator bits as set originally */
188 regs
[DS1286_MONTH
] &= ~DS1286_MONTH_MASK
;
189 regs
[DS1286_MONTH
] |= TOBCD(dt
.dt_mon
) & DS1286_MONTH_MASK
;
191 regs
[DS1286_YEAR
] = TOBCD(TO_IRIX_YEAR(dt
.dt_year
));
194 DS1286_PUTTOD(sc
, ®s
);