ds1374.c revision 235652
1/*-
2 * Copyright (c) 2003-2012 Broadcom Corporation
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 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
20 * 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
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/dev/iicbus/ds1374.c 235652 2012-05-19 17:42:11Z marcel $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/module.h>
36#include <sys/bus.h>
37#include <sys/clock.h>
38#include <sys/time.h>
39#include <sys/resource.h>
40#include <sys/rman.h>
41
42#include <dev/iicbus/iiconf.h>
43#include <dev/iicbus/iicbus.h>
44
45#include "iicbus_if.h"
46#include "clock_if.h"
47
48#define	DS1374_RTC_COUNTER	0	/* counter (bytes 0-3) */
49
50struct ds1374_softc {
51	uint32_t	sc_addr;
52	device_t	sc_dev;
53};
54
55static int
56ds1374_probe(device_t dev)
57{
58	device_set_desc(dev, "DS1374 RTC");
59	return (0);
60}
61
62static int
63ds1374_attach(device_t dev)
64{
65	struct ds1374_softc *sc = device_get_softc(dev);
66
67	if(sc==NULL) {
68		printf("ds1374_attach device_get_softc failed\n");
69		return (0);
70	}
71	sc->sc_dev = dev;
72	sc->sc_addr = iicbus_get_addr(dev);
73
74	clock_register(dev, 1000);
75	return (0);
76}
77
78static int
79ds1374_settime(device_t dev, struct timespec *ts)
80{
81	/* NB: register pointer precedes actual data */
82	uint8_t data[5] = { DS1374_RTC_COUNTER };
83	struct ds1374_softc *sc = device_get_softc(dev);
84	struct iic_msg msgs[1] = {
85	     { sc->sc_addr, IIC_M_WR, 5, data },
86	};
87
88	data[1] = (ts->tv_sec >> 0) & 0xff;
89	data[2] = (ts->tv_sec >> 8) & 0xff;
90	data[3] = (ts->tv_sec >> 16) & 0xff;
91	data[4] = (ts->tv_sec >> 24) & 0xff;
92
93	return iicbus_transfer(dev, msgs, 1);
94}
95
96static int
97ds1374_gettime(device_t dev, struct timespec *ts)
98{
99	struct ds1374_softc *sc = device_get_softc(dev);
100	uint8_t addr[1] = { DS1374_RTC_COUNTER };
101	uint8_t secs[4];
102	struct iic_msg msgs[2] = {
103	     { sc->sc_addr, IIC_M_WR, 1, addr },
104	     { sc->sc_addr, IIC_M_RD, 4, secs },
105	};
106	int error;
107
108	error = iicbus_transfer(dev, msgs, 2);
109	if (error == 0) {
110		/* counter has seconds since epoch */
111		ts->tv_sec = (secs[3] << 24) | (secs[2] << 16)
112			   | (secs[1] <<  8) | (secs[0] <<  0);
113		ts->tv_nsec = 0;
114	}
115	return error;
116}
117
118static device_method_t ds1374_methods[] = {
119	DEVMETHOD(device_probe,		ds1374_probe),
120	DEVMETHOD(device_attach,	ds1374_attach),
121
122	DEVMETHOD(clock_gettime,	ds1374_gettime),
123	DEVMETHOD(clock_settime,	ds1374_settime),
124
125	DEVMETHOD_END
126};
127
128static driver_t ds1374_driver = {
129	"ds1374_rtc",
130	ds1374_methods,
131	sizeof(struct ds1374_softc),
132};
133static devclass_t ds1374_devclass;
134
135DRIVER_MODULE(ds1374, iicbus, ds1374_driver, ds1374_devclass, 0, 0);
136MODULE_VERSION(ds1374, 1);
137MODULE_DEPEND(ds1374, iicbus, 1, 1, 1);
138