1/* rtc-ds3234.c 2 * 3 * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal 4 * and SRAM. 5 * 6 * Copyright (C) 2008 MIMOMax Wireless Ltd. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13 14#include <linux/init.h> 15#include <linux/module.h> 16#include <linux/device.h> 17#include <linux/platform_device.h> 18#include <linux/rtc.h> 19#include <linux/spi/spi.h> 20#include <linux/bcd.h> 21 22#define DS3234_REG_SECONDS 0x00 23#define DS3234_REG_MINUTES 0x01 24#define DS3234_REG_HOURS 0x02 25#define DS3234_REG_DAY 0x03 26#define DS3234_REG_DATE 0x04 27#define DS3234_REG_MONTH 0x05 28#define DS3234_REG_YEAR 0x06 29#define DS3234_REG_CENTURY (1 << 7) /* Bit 7 of the Month register */ 30 31#define DS3234_REG_CONTROL 0x0E 32#define DS3234_REG_CONT_STAT 0x0F 33 34static int ds3234_set_reg(struct device *dev, unsigned char address, 35 unsigned char data) 36{ 37 struct spi_device *spi = to_spi_device(dev); 38 unsigned char buf[2]; 39 40 /* MSB must be '1' to indicate write */ 41 buf[0] = address | 0x80; 42 buf[1] = data; 43 44 return spi_write_then_read(spi, buf, 2, NULL, 0); 45} 46 47static int ds3234_get_reg(struct device *dev, unsigned char address, 48 unsigned char *data) 49{ 50 struct spi_device *spi = to_spi_device(dev); 51 52 *data = address & 0x7f; 53 54 return spi_write_then_read(spi, data, 1, data, 1); 55} 56 57static int ds3234_read_time(struct device *dev, struct rtc_time *dt) 58{ 59 int err; 60 unsigned char buf[8]; 61 struct spi_device *spi = to_spi_device(dev); 62 63 buf[0] = 0x00; /* Start address */ 64 65 err = spi_write_then_read(spi, buf, 1, buf, 8); 66 if (err != 0) 67 return err; 68 69 /* Seconds, Minutes, Hours, Day, Date, Month, Year */ 70 dt->tm_sec = bcd2bin(buf[0]); 71 dt->tm_min = bcd2bin(buf[1]); 72 dt->tm_hour = bcd2bin(buf[2] & 0x3f); 73 dt->tm_wday = bcd2bin(buf[3]) - 1; /* 0 = Sun */ 74 dt->tm_mday = bcd2bin(buf[4]); 75 dt->tm_mon = bcd2bin(buf[5] & 0x1f) - 1; /* 0 = Jan */ 76 dt->tm_year = bcd2bin(buf[6] & 0xff) + 100; /* Assume 20YY */ 77 78 return rtc_valid_tm(dt); 79} 80 81static int ds3234_set_time(struct device *dev, struct rtc_time *dt) 82{ 83 ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec)); 84 ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min)); 85 ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f); 86 87 /* 0 = Sun */ 88 ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1)); 89 ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday)); 90 91 /* 0 = Jan */ 92 ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1)); 93 94 /* Assume 20YY although we just want to make sure not to go negative. */ 95 if (dt->tm_year > 100) 96 dt->tm_year -= 100; 97 98 ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year)); 99 100 return 0; 101} 102 103static const struct rtc_class_ops ds3234_rtc_ops = { 104 .read_time = ds3234_read_time, 105 .set_time = ds3234_set_time, 106}; 107 108static int ds3234_probe(struct spi_device *spi) 109{ 110 struct rtc_device *rtc; 111 unsigned char tmp; 112 int res; 113 114 spi->mode = SPI_MODE_3; 115 spi->bits_per_word = 8; 116 spi_setup(spi); 117 118 res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp); 119 if (res != 0) 120 return res; 121 122 /* Control settings 123 * 124 * CONTROL_REG 125 * BIT 7 6 5 4 3 2 1 0 126 * EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE 127 * 128 * 0 0 0 1 1 1 0 0 129 * 130 * CONTROL_STAT_REG 131 * BIT 7 6 5 4 3 2 1 0 132 * OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F 133 * 134 * 1 0 0 0 1 0 0 0 135 */ 136 ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); 137 ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c); 138 139 ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); 140 ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88); 141 142 /* Print our settings */ 143 ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); 144 dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp); 145 146 ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); 147 dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp); 148 149 rtc = devm_rtc_device_register(&spi->dev, "ds3234", 150 &ds3234_rtc_ops, THIS_MODULE); 151 if (IS_ERR(rtc)) 152 return PTR_ERR(rtc); 153 154 spi_set_drvdata(spi, rtc); 155 156 return 0; 157} 158 159static struct spi_driver ds3234_driver = { 160 .driver = { 161 .name = "ds3234", 162 .owner = THIS_MODULE, 163 }, 164 .probe = ds3234_probe, 165}; 166 167module_spi_driver(ds3234_driver); 168 169MODULE_DESCRIPTION("DS3234 SPI RTC driver"); 170MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>"); 171MODULE_LICENSE("GPL"); 172MODULE_ALIAS("spi:ds3234"); 173