ds1374u.c revision 216390
1169691Skan/*-
2132720Skan * Copyright (c) 2003-2009 RMI Corporation
3132720Skan * All rights reserved.
4132720Skan *
5132720Skan * Redistribution and use in source and binary forms, with or without
6132720Skan * modification, are permitted provided that the following conditions
7132720Skan * are met:
8132720Skan * 1. Redistributions of source code must retain the above copyright
9132720Skan *    notice, this list of conditions and the following disclaimer.
10132720Skan * 2. Redistributions in binary form must reproduce the above copyright
11132720Skan *    notice, this list of conditions and the following disclaimer in the
12132720Skan *    documentation and/or other materials provided with the distribution.
13132720Skan * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14132720Skan *    may be used to endorse or promote products derived from this software
15132720Skan *    without specific prior written permission.
16132720Skan *
17169691Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18132720Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19132720Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20132720Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21132720Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22132720Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23132720Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24132720Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25132720Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26132720Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27132720Skan * SUCH DAMAGE.
28132720Skan *
29132720Skan * RMI_BSD */
30132720Skan
31169691Skan#include <sys/cdefs.h>
32169691Skan__FBSDID("$FreeBSD: head/sys/mips/rmi/dev/iic/ds1374u.c 216390 2010-12-12 06:00:26Z jchandra $");
33132720Skan/*
34132720Skan *  RTC chip sitting on the I2C bus.
35132720Skan */
36132720Skan#include <sys/param.h>
37132720Skan#include <sys/systm.h>
38132720Skan#include <sys/kernel.h>
39132720Skan#include <sys/module.h>
40132720Skan#include <sys/bus.h>
41132720Skan#include <sys/clock.h>
42132720Skan#include <sys/time.h>
43132720Skan#include <sys/resource.h>
44132720Skan#include <sys/rman.h>
45132720Skan
46132720Skan#include <mips/include/bus.h>
47132720Skan#include <mips/include/cpu.h>
48132720Skan#include <mips/include/cpufunc.h>
49132720Skan#include <mips/include/frame.h>
50132720Skan#include <mips/include/resource.h>
51132720Skan
52132720Skan#include <dev/iicbus/iiconf.h>
53132720Skan#include <dev/iicbus/iicbus.h>
54132720Skan
55132720Skan#include "iicbus_if.h"
56132720Skan#include "clock_if.h"
57132720Skan
58132720Skan#define	DS1374_RTC_COUNTER	0	/* counter (bytes 0-3) */
59132720Skan
60132720Skanstruct ds1374u_softc {
61132720Skan	uint32_t	sc_addr;
62132720Skan	device_t	sc_dev;
63132720Skan};
64132720Skan
65132720Skanstatic int
66132720Skands1374u_probe(device_t dev)
67132720Skan{
68132720Skan	device_set_desc(dev, "DS1374U-33 RTC");
69132720Skan	return (0);
70132720Skan}
71132720Skan
72132720Skanstatic int
73132720Skands1374u_attach(device_t dev)
74132720Skan{
75132720Skan	struct ds1374u_softc *sc = device_get_softc(dev);
76132720Skan
77132720Skan	if(sc==NULL) {
78132720Skan		printf("ds1374u_attach device_get_softc failed\n");
79132720Skan		return (0);
80132720Skan	}
81132720Skan	sc->sc_dev = dev;
82132720Skan	sc->sc_addr = iicbus_get_addr(dev);
83132720Skan
84132720Skan	clock_register(dev, 1000);
85132720Skan	return (0);
86132720Skan}
87132720Skan
88132720Skan
89132720Skanstatic int
90132720Skands1374u_write(device_t dev, int reg, uint8_t val)
91132720Skan{
92132720Skan	uint8_t data[2];
93169691Skan	struct ds1374u_softc *sc = device_get_softc(dev);
94169691Skan	struct iic_msg msgs[1] = {
95	     { sc->sc_addr, IIC_M_WR, 2, data },
96	};
97
98	data[0] = reg;
99	data[1] = val;
100	if (iicbus_transfer(dev, msgs, 1) == 0)
101		return (0);
102	else
103		return (-1);
104}
105
106static int
107ds1374u_settime(device_t dev, struct timespec *ts)
108{
109	int i;
110	int temp = 0;
111
112	for (i = 0; i < 4; i++) {
113		temp = (ts->tv_sec >> (8*i)) & 0xff;
114		if (ds1374u_write(dev, DS1374_RTC_COUNTER+i, temp)!=0)
115			return (-1);
116	}
117	return 0;
118}
119
120static int
121ds1374u_gettime(device_t dev, struct timespec *ts)
122{
123	struct ds1374u_softc *sc = device_get_softc(dev);
124	uint8_t addr[1] = { DS1374_RTC_COUNTER };
125	uint8_t secs[4];
126	struct iic_msg msgs[2] = {
127	     { sc->sc_addr, IIC_M_WR, 1, addr },
128	     { sc->sc_addr, IIC_M_RD, 4, secs },
129	};
130	int error;
131
132	error = iicbus_transfer(dev, msgs, 2);
133	if (error == 0) {
134		/* counter has seconds since epoch */
135		ts->tv_sec = (secs[3] << 24) | (secs[2] << 16)
136			   | (secs[1] <<  8) | (secs[0] <<  0);
137		ts->tv_nsec = 0;
138	}
139	return error;
140	return 0;
141}
142
143static device_method_t ds1374u_methods[] = {
144	DEVMETHOD(device_probe,		ds1374u_probe),
145	DEVMETHOD(device_attach,	ds1374u_attach),
146
147	DEVMETHOD(clock_gettime,	ds1374u_gettime),
148	DEVMETHOD(clock_settime,	ds1374u_settime),
149
150	{0, 0},
151};
152
153static driver_t ds1374u_driver = {
154	"ds1374u",
155	ds1374u_methods,
156	sizeof(struct ds1374u_softc),
157};
158static devclass_t ds1374u_devclass;
159
160DRIVER_MODULE(ds1374u, iicbus, ds1374u_driver, ds1374u_devclass, 0, 0);
161MODULE_VERSION(ds1374u, 1);
162MODULE_DEPEND(ds1374u, iicbus, 1, 1, 1);
163