Annotation of sys/dev/i2c/rs5c372.c, Revision 1.1.1.1
1.1 nbrk 1: /* $NetBSD: rs5c372.c,v 1.5 2006/03/29 06:41:24 thorpej Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Kimihiro Nonaka
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 WASABI SYSTEMS, INC. ``AS IS'' AND
17: * 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 WASABI SYSTEMS, INC
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/param.h>
30: #include <sys/systm.h>
31: #include <sys/device.h>
32: #include <sys/kernel.h>
33: #include <sys/fcntl.h>
34: #include <sys/uio.h>
35: #include <sys/conf.h>
36: #include <sys/event.h>
37:
38: #include <dev/clock_subr.h>
39:
40: #include <dev/i2c/i2cvar.h>
41:
42: /*
43: * RS5C372[AB] Real-Time Clock
44: */
45:
46: #define RICOHRTC_ADDR 0x32 /* Fixed I2C Slave Address */
47:
48: #define RICOHRTC_SECONDS 0
49: #define RICOHRTC_MINUTES 1
50: #define RICOHRTC_HOURS 2
51: #define RICOHRTC_DAY 3
52: #define RICOHRTC_DATE 4
53: #define RICOHRTC_MONTH 5
54: #define RICOHRTC_YEAR 6
55: #define RICOHRTC_CLOCK_CORRECT 7
56: #define RICOHRTC_ALARMA_MIN 8
57: #define RICOHRTC_ALARMA_HOUR 9
58: #define RICOHRTC_ALARMA_DATE 10
59: #define RICOHRTC_ALARMB_MIN 11
60: #define RICOHRTC_ALARMB_HOUR 12
61: #define RICOHRTC_ALARMB_DATE 13
62: #define RICOHRTC_CONTROL1 14
63: #define RICOHRTC_CONTROL2 15
64: #define RICOHRTC_NREGS 16
65: #define RICOHRTC_NRTC_REGS 7
66:
67: /*
68: * Bit definitions.
69: */
70: #define RICOHRTC_SECONDS_MASK 0x7f
71: #define RICOHRTC_MINUTES_MASK 0x7f
72: #define RICOHRTC_HOURS_12HRS_PM (1u << 5) /* If 12 hr mode, set = PM */
73: #define RICOHRTC_HOURS_12MASK 0x1f
74: #define RICOHRTC_HOURS_24MASK 0x3f
75: #define RICOHRTC_DAY_MASK 0x07
76: #define RICOHRTC_DATE_MASK 0x3f
77: #define RICOHRTC_MONTH_MASK 0x1f
78: #define RICOHRTC_CONTROL2_24HRS (1u << 5)
79: #define RICOHRTC_CONTROL2_XSTP (1u << 4) /* read */
80: #define RICOHRTC_CONTROL2_ADJ (1u << 4) /* write */
81: #define RICOHRTC_CONTROL2_NCLEN (1u << 3)
82: #define RICOHRTC_CONTROL2_CTFG (1u << 2)
83: #define RICOHRTC_CONTROL2_AAFG (1u << 1)
84: #define RICOHRTC_CONTROL2_BAFG (1u << 0)
85:
86: struct ricohrtc_softc {
87: struct device sc_dev;
88: i2c_tag_t sc_tag;
89: int sc_address;
90: struct todr_chip_handle sc_todr;
91: };
92:
93: int ricohrtc_match(struct device *, void *, void *);
94: void ricohrtc_attach(struct device *, struct device *, void *);
95:
96: struct cfattach ricohrtc_ca = {
97: sizeof(struct ricohrtc_softc), ricohrtc_match, ricohrtc_attach
98: };
99:
100: struct cfdriver ricohrtc_cd = {
101: NULL, "ricohrtc", DV_DULL
102: };
103:
104: void ricohrtc_reg_write(struct ricohrtc_softc *, int, uint8_t);
105: int ricohrtc_clock_read(struct ricohrtc_softc *, struct clock_ymdhms *);
106: int ricohrtc_clock_write(struct ricohrtc_softc *, struct clock_ymdhms *);
107: int ricohrtc_gettime(struct todr_chip_handle *, struct timeval *);
108: int ricohrtc_settime(struct todr_chip_handle *, struct timeval *);
109: int ricohrtc_getcal(struct todr_chip_handle *, int *);
110: int ricohrtc_setcal(struct todr_chip_handle *, int);
111:
112: int
113: ricohrtc_match(struct device *parent, void *v, void *arg)
114: {
115: struct i2c_attach_args *ia = arg;
116: #ifdef PARANOID_CHECKS
117: u_int8_t data, cmd;
118: #endif
119:
120: if (ia->ia_addr != RICOHRTC_ADDR)
121: return (0);
122:
123: #ifdef PARANOID_CHECKS
124: /* Verify that the 'reserved bits in a few registers read 0 */
125: if (iic_acquire_bus(ia->ia_tag, I2C_F_POLL)) {
126: printf("ricohrtc acquire fail\n");
127: return (0);
128: }
129:
130: cmd = RICOHRTC_SECONDS;
131: if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
132: &cmd, 1, &data, 1, I2C_F_POLL)) {
133: iic_release_bus(ia->ia_tag, I2C_F_POLL);
134: printf("ricohrtc read %d fail\n", cmd);
135: return (0);
136: }
137: if ((data & ~RICOHRTC_SECONDS_MASK) != 0) {
138: printf("ricohrtc second %d\n",data);
139: return (0);
140: }
141:
142: cmd = RICOHRTC_MINUTES;
143: if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
144: &cmd, 1, &data, 1, I2C_F_POLL)) {
145: iic_release_bus(ia->ia_tag, I2C_F_POLL);
146: printf("ricohrtc read %d fail\n", cmd);
147: return (0);
148: }
149:
150: if ((data & ~RICOHRTC_MINUTES_MASK) != 0) {
151: printf("ricohrtc minute %d\n",data);
152: return (0);
153: }
154:
155: cmd = RICOHRTC_HOURS;
156: if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
157: &cmd, 1, &data, 1, I2C_F_POLL)) {
158: iic_release_bus(ia->ia_tag, I2C_F_POLL);
159: printf("ricohrtc read %d fail\n", cmd);
160: return (0);
161: }
162: if ((data & ~RICOHRTC_HOURS_24MASK) != 0) {
163: printf("ricohrtc hour %d\n",data);
164: return (0);
165: }
166: #endif
167:
168: iic_release_bus(ia->ia_tag, I2C_F_POLL);
169: return (1);
170: }
171:
172: void
173: ricohrtc_attach(struct device *parent, struct device *self, void *arg)
174: {
175: struct ricohrtc_softc *sc = (struct ricohrtc_softc *)self;
176: struct i2c_attach_args *ia = arg;
177:
178: printf(": RICOH RS5C372[AB] Real-time Clock\n");
179:
180: sc->sc_tag = ia->ia_tag;
181: sc->sc_address = ia->ia_addr;
182: sc->sc_todr.cookie = sc;
183: sc->sc_todr.todr_gettime = ricohrtc_gettime;
184: sc->sc_todr.todr_settime = ricohrtc_settime;
185: sc->sc_todr.todr_getcal = ricohrtc_getcal;
186: sc->sc_todr.todr_setcal = ricohrtc_setcal;
187: sc->sc_todr.todr_setwen = NULL;
188:
189: #if 0
190: todr_attach(&sc->sc_todr);
191: #else
192: /* XXX */
193: {
194: extern todr_chip_handle_t todr_handle;
195: todr_handle = &sc->sc_todr;
196: }
197: #endif
198:
199: /* Initialize RTC */
200: ricohrtc_reg_write(sc, RICOHRTC_CONTROL2, RICOHRTC_CONTROL2_24HRS);
201: ricohrtc_reg_write(sc, RICOHRTC_CONTROL1, 0);
202: }
203:
204: int
205: ricohrtc_gettime(struct todr_chip_handle *ch, struct timeval *tv)
206: {
207: struct ricohrtc_softc *sc = ch->cookie;
208: struct clock_ymdhms dt;
209:
210: memset(&dt, 0, sizeof(dt));
211: if (ricohrtc_clock_read(sc, &dt) == 0)
212: return (-1);
213:
214: tv->tv_sec = clock_ymdhms_to_secs(&dt);
215: tv->tv_usec = 0;
216: return (0);
217: }
218:
219: int
220: ricohrtc_settime(struct todr_chip_handle *ch, struct timeval *tv)
221: {
222: struct ricohrtc_softc *sc = ch->cookie;
223: struct clock_ymdhms dt;
224:
225: clock_secs_to_ymdhms(tv->tv_sec, &dt);
226:
227: if (ricohrtc_clock_write(sc, &dt) == 0)
228: return (-1);
229: return (0);
230: }
231:
232: int
233: ricohrtc_setcal(struct todr_chip_handle *ch, int cal)
234: {
235:
236: return (EOPNOTSUPP);
237: }
238:
239: int
240: ricohrtc_getcal(struct todr_chip_handle *ch, int *cal)
241: {
242:
243: return (EOPNOTSUPP);
244: }
245:
246: void
247: ricohrtc_reg_write(struct ricohrtc_softc *sc, int reg, uint8_t val)
248: {
249: uint8_t cmd;
250:
251: iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
252: reg &= 0xf;
253: cmd = (reg << 4);
254: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
255: &cmd, 1, &val, 1, I2C_F_POLL)) {
256: iic_release_bus(sc->sc_tag, I2C_F_POLL);
257: printf("%s: ricohrtc_reg_write: failed to write reg%d\n",
258: sc->sc_dev.dv_xname, reg);
259: return;
260: }
261: iic_release_bus(sc->sc_tag, I2C_F_POLL);
262: }
263:
264: int
265: ricohrtc_clock_read(struct ricohrtc_softc *sc, struct clock_ymdhms *dt)
266: {
267: uint8_t bcd[RICOHRTC_NRTC_REGS];
268: uint8_t cmd;
269:
270: iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
271: cmd = (RICOHRTC_SECONDS << 4);
272: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address,
273: &cmd, 1, bcd, RICOHRTC_NRTC_REGS, I2C_F_POLL)) {
274: iic_release_bus(sc->sc_tag, I2C_F_POLL);
275: printf("%s: ricohrtc_clock_read: failed to read rtc\n",
276: sc->sc_dev.dv_xname);
277: return (0);
278: }
279: iic_release_bus(sc->sc_tag, I2C_F_POLL);
280:
281: /*
282: * Convert the RICOHRTC's register values into something useable
283: */
284: dt->dt_sec = FROMBCD(bcd[RICOHRTC_SECONDS] & RICOHRTC_SECONDS_MASK);
285: dt->dt_min = FROMBCD(bcd[RICOHRTC_MINUTES] & RICOHRTC_MINUTES_MASK);
286: dt->dt_hour = FROMBCD(bcd[RICOHRTC_HOURS] & RICOHRTC_HOURS_24MASK);
287: dt->dt_day = FROMBCD(bcd[RICOHRTC_DATE] & RICOHRTC_DATE_MASK);
288: dt->dt_mon = FROMBCD(bcd[RICOHRTC_MONTH] & RICOHRTC_MONTH_MASK);
289: dt->dt_year = FROMBCD(bcd[RICOHRTC_YEAR]) + POSIX_BASE_YEAR;
290: return (1);
291: }
292:
293: int
294: ricohrtc_clock_write(struct ricohrtc_softc *sc, struct clock_ymdhms *dt)
295: {
296: uint8_t bcd[RICOHRTC_NRTC_REGS];
297: uint8_t cmd;
298:
299: /*
300: * Convert our time representation into something the RICOHRTC
301: * can understand.
302: */
303: bcd[RICOHRTC_SECONDS] = TOBCD(dt->dt_sec);
304: bcd[RICOHRTC_MINUTES] = TOBCD(dt->dt_min);
305: bcd[RICOHRTC_HOURS] = TOBCD(dt->dt_hour);
306: bcd[RICOHRTC_DATE] = TOBCD(dt->dt_day);
307: bcd[RICOHRTC_DAY] = TOBCD(dt->dt_wday);
308: bcd[RICOHRTC_MONTH] = TOBCD(dt->dt_mon);
309: bcd[RICOHRTC_YEAR] = TOBCD(dt->dt_year - POSIX_BASE_YEAR);
310:
311: iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
312: cmd = (RICOHRTC_SECONDS << 4);
313: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
314: &cmd, 1, bcd, RICOHRTC_NRTC_REGS, I2C_F_POLL)) {
315: iic_release_bus(sc->sc_tag, I2C_F_POLL);
316: printf("%s: ricohrtc_clock_write: failed to write rtc\n",
317: sc->sc_dev.dv_xname);
318: return (0);
319: }
320: iic_release_bus(sc->sc_tag, I2C_F_POLL);
321: return (1);
322: }
CVSweb