1 /* $NetBSD: r2025.c,v 1.5 2008/05/04 15:26:29 xtraeme Exp $ */
4 * Copyright (c) 2006 Shigeyuki Fukushima.
7 * Written by Shigeyuki Fukushima.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * 3. The name of the author may not be used to endorse or promote
19 * products derived from this software without specific prior
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: r2025.c,v 1.5 2008/05/04 15:26:29 xtraeme Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 #include <sys/kernel.h>
42 #include <sys/fcntl.h>
45 #include <sys/event.h>
47 #include <dev/clock_subr.h>
49 #include <dev/i2c/i2cvar.h>
50 #include <dev/i2c/r2025reg.h>
52 struct r2025rtc_softc
{
57 struct todr_chip_handle sc_todr
;
60 static void r2025rtc_attach(device_t
, device_t
, void *);
61 static int r2025rtc_match(device_t
, cfdata_t
, void *);
63 CFATTACH_DECL_NEW(r2025rtc
, sizeof(struct r2025rtc_softc
),
64 r2025rtc_match
, r2025rtc_attach
, NULL
, NULL
);
66 static int r2025rtc_gettime(struct todr_chip_handle
*, struct timeval
*);
67 static int r2025rtc_settime(struct todr_chip_handle
*, struct timeval
*);
68 static int r2025rtc_reg_write(struct r2025rtc_softc
*, int, uint8_t*, int);
69 static int r2025rtc_reg_read(struct r2025rtc_softc
*, int, uint8_t*, int);
73 r2025rtc_match(device_t parent
, cfdata_t cf
, void *arg
)
75 struct i2c_attach_args
*ia
= arg
;
77 /* match only R2025 RTC devices */
78 if (ia
->ia_addr
== R2025_ADDR
)
85 r2025rtc_attach(device_t parent
, device_t self
, void *arg
)
87 struct r2025rtc_softc
*sc
= device_private(self
);
88 struct i2c_attach_args
*ia
= arg
;
90 aprint_normal(": RICOH R2025S/D Real-time Clock\n");
92 sc
->sc_tag
= ia
->ia_tag
;
93 sc
->sc_address
= ia
->ia_addr
;
96 sc
->sc_todr
.cookie
= sc
;
97 sc
->sc_todr
.todr_gettime
= r2025rtc_gettime
;
98 sc
->sc_todr
.todr_settime
= r2025rtc_settime
;
99 sc
->sc_todr
.todr_setwen
= NULL
;
101 todr_attach(&sc
->sc_todr
);
105 r2025rtc_gettime(struct todr_chip_handle
*ch
, struct timeval
*tv
)
107 struct r2025rtc_softc
*sc
= ch
->cookie
;
108 struct clock_ymdhms dt
;
110 uint8_t bcd
[R2025_CLK_SIZE
];
113 memset(&dt
, 0, sizeof(dt
));
115 if (r2025rtc_reg_read(sc
, R2025_REG_CTRL1
, &rctrl
, 1) != 0) {
116 aprint_error_dev(sc
->sc_dev
,
117 "r2025rtc_gettime: failed to read registers.\n");
121 if (r2025rtc_reg_read(sc
, R2025_REG_SEC
, &bcd
[0], R2025_CLK_SIZE
)
123 aprint_error_dev(sc
->sc_dev
,
124 "r2025rtc_gettime: failed to read registers.\n");
128 dt
.dt_sec
= FROMBCD(bcd
[R2025_REG_SEC
] & R2025_REG_SEC_MASK
);
129 dt
.dt_min
= FROMBCD(bcd
[R2025_REG_MIN
] & R2025_REG_MIN_MASK
);
130 hour
= FROMBCD(bcd
[R2025_REG_HOUR
] & R2025_REG_HOUR_MASK
);
131 if (rctrl
& R2025_REG_CTRL1_H1224
) {
136 } else if (hour
== 32) {
138 } else if (hour
> 13) {
139 dt
.dt_hour
= (hour
- 8);
140 } else { /* (hour < 12) */
144 dt
.dt_wday
= FROMBCD(bcd
[R2025_REG_WDAY
] & R2025_REG_WDAY_MASK
);
145 dt
.dt_day
= FROMBCD(bcd
[R2025_REG_DAY
] & R2025_REG_DAY_MASK
);
146 dt
.dt_mon
= FROMBCD(bcd
[R2025_REG_MON
] & R2025_REG_MON_MASK
);
147 dt
.dt_year
= FROMBCD(bcd
[R2025_REG_YEAR
] & R2025_REG_YEAR_MASK
)
148 + ((bcd
[R2025_REG_MON
] & R2025_REG_MON_Y1920
) ? 2000 : 1900);
150 tv
->tv_sec
= clock_ymdhms_to_secs(&dt
);
157 r2025rtc_settime(struct todr_chip_handle
*ch
, struct timeval
*tv
)
159 struct r2025rtc_softc
*sc
= ch
->cookie
;
160 struct clock_ymdhms dt
;
162 uint8_t bcd
[R2025_CLK_SIZE
];
164 clock_secs_to_ymdhms(tv
->tv_sec
, &dt
);
167 if (dt
.dt_year
>= 3000) {
168 aprint_error_dev(sc
->sc_dev
,
170 "RTC does not support year 3000 or over.\n");
174 if (r2025rtc_reg_read(sc
, R2025_REG_CTRL1
, &rctrl
, 1) != 0) {
175 aprint_error_dev(sc
->sc_dev
,
176 "r2025rtc_settime: failed to read register.\n");
179 rctrl
|= R2025_REG_CTRL1_H1224
;
181 /* setup registers 0x00-0x06 (7 byte) */
182 bcd
[R2025_REG_SEC
] = TOBCD(dt
.dt_sec
) & R2025_REG_SEC_MASK
;
183 bcd
[R2025_REG_MIN
] = TOBCD(dt
.dt_min
) & R2025_REG_MIN_MASK
;
184 bcd
[R2025_REG_HOUR
] = TOBCD(dt
.dt_hour
) & R2025_REG_HOUR_MASK
;
185 bcd
[R2025_REG_WDAY
] = TOBCD(dt
.dt_wday
) & R2025_REG_WDAY_MASK
;
186 bcd
[R2025_REG_DAY
] = TOBCD(dt
.dt_day
) & R2025_REG_DAY_MASK
;
187 bcd
[R2025_REG_MON
] = (TOBCD(dt
.dt_mon
) & R2025_REG_MON_MASK
)
188 | ((dt
.dt_year
>= 2000) ? R2025_REG_MON_Y1920
: 0);
189 bcd
[R2025_REG_YEAR
] = TOBCD(dt
.dt_year
% 100) & R2025_REG_YEAR_MASK
;
191 /* Write RTC register */
192 if (r2025rtc_reg_write(sc
, R2025_REG_CTRL1
, &rctrl
, 1) != 0) {
193 aprint_error_dev(sc
->sc_dev
,
194 "r2025rtc_settime: failed to write registers.\n");
197 if (r2025rtc_reg_write(sc
, R2025_REG_SEC
, bcd
, R2025_CLK_SIZE
) != 0) {
198 aprint_error_dev(sc
->sc_dev
,
199 "r2025rtc_settime: failed to write registers.\n");
207 r2025rtc_reg_write(struct r2025rtc_softc
*sc
, int reg
, uint8_t *val
, int len
)
213 if (iic_acquire_bus(sc
->sc_tag
, I2C_F_POLL
)) {
214 aprint_error_dev(sc
->sc_dev
,
215 "r2025rtc_clock_write: failed to acquire I2C bus\n");
219 for (i
= 0 ; i
< len
; i
++) {
220 cmdbuf
[0] = (((reg
+ i
) << 4) & 0xf0);
222 if (iic_exec(sc
->sc_tag
, I2C_OP_WRITE_WITH_STOP
, sc
->sc_address
,
223 cmdbuf
, 1, buf
, 1, I2C_F_POLL
)) {
224 iic_release_bus(sc
->sc_tag
, I2C_F_POLL
);
225 aprint_error_dev(sc
->sc_dev
, "r2025rtc_reg_write: "
226 "failed to write registers\n");
231 iic_release_bus(sc
->sc_tag
, I2C_F_POLL
);
237 r2025rtc_reg_read(struct r2025rtc_softc
*sc
, int reg
, uint8_t *val
, int len
)
243 if (iic_acquire_bus(sc
->sc_tag
, I2C_F_POLL
)) {
244 aprint_error_dev(sc
->sc_dev
,
245 "r2025rtc_clock_read: failed to acquire I2C bus\n");
249 for (i
= 0 ; i
< len
; i
++) {
250 cmdbuf
[0] = (((reg
+ i
) << 4) & 0xf0);
252 if (iic_exec(sc
->sc_tag
, I2C_OP_READ_WITH_STOP
, sc
->sc_address
,
253 cmdbuf
, 1, buf
, 1, I2C_F_POLL
)) {
254 iic_release_bus(sc
->sc_tag
, I2C_F_POLL
);
255 aprint_error_dev(sc
->sc_dev
, "r2025rtc_reg_read: "
256 "failed to write registers\n");
263 iic_release_bus(sc
->sc_tag
, I2C_F_POLL
);