1216390Sjchandra/*- 2216390Sjchandra * Copyright (c) 2003-2009 RMI Corporation 3216390Sjchandra * All rights reserved. 4216390Sjchandra * 5216390Sjchandra * Redistribution and use in source and binary forms, with or without 6216390Sjchandra * modification, are permitted provided that the following conditions 7216390Sjchandra * are met: 8216390Sjchandra * 1. Redistributions of source code must retain the above copyright 9216390Sjchandra * notice, this list of conditions and the following disclaimer. 10216390Sjchandra * 2. Redistributions in binary form must reproduce the above copyright 11216390Sjchandra * notice, this list of conditions and the following disclaimer in the 12216390Sjchandra * documentation and/or other materials provided with the distribution. 13216390Sjchandra * 3. Neither the name of RMI Corporation, nor the names of its contributors, 14216390Sjchandra * may be used to endorse or promote products derived from this software 15216390Sjchandra * without specific prior written permission. 16216390Sjchandra * 17216390Sjchandra * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18216390Sjchandra * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19216390Sjchandra * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20216390Sjchandra * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21216390Sjchandra * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22216390Sjchandra * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23216390Sjchandra * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24216390Sjchandra * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25216390Sjchandra * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26216390Sjchandra * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27216390Sjchandra * SUCH DAMAGE. 28216390Sjchandra * 29216390Sjchandra * RMI_BSD */ 30216390Sjchandra 31216390Sjchandra#include <sys/cdefs.h> 32216390Sjchandra__FBSDID("$FreeBSD: releng/10.2/sys/mips/rmi/dev/iic/ds1374u.c 216410 2010-12-13 17:53:38Z jchandra $"); 33216390Sjchandra/* 34216390Sjchandra * RTC chip sitting on the I2C bus. 35216390Sjchandra */ 36216390Sjchandra#include <sys/param.h> 37216390Sjchandra#include <sys/systm.h> 38216390Sjchandra#include <sys/kernel.h> 39216390Sjchandra#include <sys/module.h> 40216390Sjchandra#include <sys/bus.h> 41216390Sjchandra#include <sys/clock.h> 42216390Sjchandra#include <sys/time.h> 43216390Sjchandra#include <sys/resource.h> 44216390Sjchandra#include <sys/rman.h> 45216390Sjchandra 46216390Sjchandra#include <mips/include/bus.h> 47216390Sjchandra#include <mips/include/cpu.h> 48216390Sjchandra#include <mips/include/cpufunc.h> 49216390Sjchandra#include <mips/include/frame.h> 50216390Sjchandra#include <mips/include/resource.h> 51216390Sjchandra 52216390Sjchandra#include <dev/iicbus/iiconf.h> 53216390Sjchandra#include <dev/iicbus/iicbus.h> 54216390Sjchandra 55216390Sjchandra#include "iicbus_if.h" 56216390Sjchandra#include "clock_if.h" 57216390Sjchandra 58216390Sjchandra#define DS1374_RTC_COUNTER 0 /* counter (bytes 0-3) */ 59216390Sjchandra 60216390Sjchandrastruct ds1374u_softc { 61216390Sjchandra uint32_t sc_addr; 62216390Sjchandra device_t sc_dev; 63216390Sjchandra}; 64216390Sjchandra 65216390Sjchandrastatic int 66216390Sjchandrads1374u_probe(device_t dev) 67216390Sjchandra{ 68216390Sjchandra device_set_desc(dev, "DS1374U-33 RTC"); 69216390Sjchandra return (0); 70216390Sjchandra} 71216390Sjchandra 72216390Sjchandrastatic int 73216390Sjchandrads1374u_attach(device_t dev) 74216390Sjchandra{ 75216390Sjchandra struct ds1374u_softc *sc = device_get_softc(dev); 76216390Sjchandra 77216390Sjchandra if(sc==NULL) { 78216390Sjchandra printf("ds1374u_attach device_get_softc failed\n"); 79216390Sjchandra return (0); 80216390Sjchandra } 81216390Sjchandra sc->sc_dev = dev; 82216390Sjchandra sc->sc_addr = iicbus_get_addr(dev); 83216390Sjchandra 84216390Sjchandra clock_register(dev, 1000); 85216390Sjchandra return (0); 86216390Sjchandra} 87216390Sjchandra 88216410Sjchandrastatic int 89216410Sjchandrads1374u_settime(device_t dev, struct timespec *ts) 90216390Sjchandra{ 91216410Sjchandra /* NB: register pointer precedes actual data */ 92216410Sjchandra uint8_t data[5] = { DS1374_RTC_COUNTER }; 93216390Sjchandra struct ds1374u_softc *sc = device_get_softc(dev); 94216390Sjchandra struct iic_msg msgs[1] = { 95216410Sjchandra { sc->sc_addr, IIC_M_WR, 5, data }, 96216390Sjchandra }; 97216390Sjchandra 98216410Sjchandra data[1] = (ts->tv_sec >> 0) & 0xff; 99216410Sjchandra data[2] = (ts->tv_sec >> 8) & 0xff; 100216410Sjchandra data[3] = (ts->tv_sec >> 16) & 0xff; 101216410Sjchandra data[4] = (ts->tv_sec >> 24) & 0xff; 102216390Sjchandra 103216410Sjchandra return iicbus_transfer(dev, msgs, 1); 104216390Sjchandra} 105216390Sjchandra 106216390Sjchandrastatic int 107216390Sjchandrads1374u_gettime(device_t dev, struct timespec *ts) 108216390Sjchandra{ 109216390Sjchandra struct ds1374u_softc *sc = device_get_softc(dev); 110216390Sjchandra uint8_t addr[1] = { DS1374_RTC_COUNTER }; 111216390Sjchandra uint8_t secs[4]; 112216390Sjchandra struct iic_msg msgs[2] = { 113216390Sjchandra { sc->sc_addr, IIC_M_WR, 1, addr }, 114216390Sjchandra { sc->sc_addr, IIC_M_RD, 4, secs }, 115216390Sjchandra }; 116216390Sjchandra int error; 117216390Sjchandra 118216390Sjchandra error = iicbus_transfer(dev, msgs, 2); 119216390Sjchandra if (error == 0) { 120216390Sjchandra /* counter has seconds since epoch */ 121216390Sjchandra ts->tv_sec = (secs[3] << 24) | (secs[2] << 16) 122216390Sjchandra | (secs[1] << 8) | (secs[0] << 0); 123216390Sjchandra ts->tv_nsec = 0; 124216390Sjchandra } 125216390Sjchandra return error; 126216390Sjchandra} 127216390Sjchandra 128216390Sjchandrastatic device_method_t ds1374u_methods[] = { 129216390Sjchandra DEVMETHOD(device_probe, ds1374u_probe), 130216390Sjchandra DEVMETHOD(device_attach, ds1374u_attach), 131216390Sjchandra 132216390Sjchandra DEVMETHOD(clock_gettime, ds1374u_gettime), 133216390Sjchandra DEVMETHOD(clock_settime, ds1374u_settime), 134216390Sjchandra 135216390Sjchandra {0, 0}, 136216390Sjchandra}; 137216390Sjchandra 138216390Sjchandrastatic driver_t ds1374u_driver = { 139216390Sjchandra "ds1374u", 140216390Sjchandra ds1374u_methods, 141216390Sjchandra sizeof(struct ds1374u_softc), 142216390Sjchandra}; 143216390Sjchandrastatic devclass_t ds1374u_devclass; 144216390Sjchandra 145216390SjchandraDRIVER_MODULE(ds1374u, iicbus, ds1374u_driver, ds1374u_devclass, 0, 0); 146216390SjchandraMODULE_VERSION(ds1374u, 1); 147216390SjchandraMODULE_DEPEND(ds1374u, iicbus, 1, 1, 1); 148