1617b26a0SRaghavendra Ganiga /* rtc-ds1347.c 2617b26a0SRaghavendra Ganiga * 3617b26a0SRaghavendra Ganiga * Driver for Dallas Semiconductor DS1347 Low Current, SPI Compatible 4617b26a0SRaghavendra Ganiga * Real Time Clock 5617b26a0SRaghavendra Ganiga * 6617b26a0SRaghavendra Ganiga * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> 7617b26a0SRaghavendra Ganiga * 8617b26a0SRaghavendra Ganiga * This program is free software; you can redistribute it and/or modify 9617b26a0SRaghavendra Ganiga * it under the terms of the GNU General Public License version 2 as 10617b26a0SRaghavendra Ganiga * published by the Free Software Foundation. 11617b26a0SRaghavendra Ganiga * 12617b26a0SRaghavendra Ganiga */ 13617b26a0SRaghavendra Ganiga 14617b26a0SRaghavendra Ganiga #include <linux/init.h> 15617b26a0SRaghavendra Ganiga #include <linux/module.h> 16617b26a0SRaghavendra Ganiga #include <linux/device.h> 17617b26a0SRaghavendra Ganiga #include <linux/platform_device.h> 18617b26a0SRaghavendra Ganiga #include <linux/rtc.h> 19617b26a0SRaghavendra Ganiga #include <linux/spi/spi.h> 20617b26a0SRaghavendra Ganiga #include <linux/bcd.h> 21617b26a0SRaghavendra Ganiga 22617b26a0SRaghavendra Ganiga /* Registers in ds1347 rtc */ 23617b26a0SRaghavendra Ganiga 24617b26a0SRaghavendra Ganiga #define DS1347_SECONDS_REG 0x01 25617b26a0SRaghavendra Ganiga #define DS1347_MINUTES_REG 0x03 26617b26a0SRaghavendra Ganiga #define DS1347_HOURS_REG 0x05 27617b26a0SRaghavendra Ganiga #define DS1347_DATE_REG 0x07 28617b26a0SRaghavendra Ganiga #define DS1347_MONTH_REG 0x09 29617b26a0SRaghavendra Ganiga #define DS1347_DAY_REG 0x0B 30617b26a0SRaghavendra Ganiga #define DS1347_YEAR_REG 0x0D 31617b26a0SRaghavendra Ganiga #define DS1347_CONTROL_REG 0x0F 32617b26a0SRaghavendra Ganiga #define DS1347_STATUS_REG 0x17 33617b26a0SRaghavendra Ganiga #define DS1347_CLOCK_BURST 0x3F 34617b26a0SRaghavendra Ganiga 35617b26a0SRaghavendra Ganiga static int ds1347_read_reg(struct device *dev, unsigned char address, 36617b26a0SRaghavendra Ganiga unsigned char *data) 37617b26a0SRaghavendra Ganiga { 38617b26a0SRaghavendra Ganiga struct spi_device *spi = to_spi_device(dev); 39617b26a0SRaghavendra Ganiga 40617b26a0SRaghavendra Ganiga *data = address | 0x80; 41617b26a0SRaghavendra Ganiga 42617b26a0SRaghavendra Ganiga return spi_write_then_read(spi, data, 1, data, 1); 43617b26a0SRaghavendra Ganiga } 44617b26a0SRaghavendra Ganiga 45617b26a0SRaghavendra Ganiga static int ds1347_write_reg(struct device *dev, unsigned char address, 46617b26a0SRaghavendra Ganiga unsigned char data) 47617b26a0SRaghavendra Ganiga { 48617b26a0SRaghavendra Ganiga struct spi_device *spi = to_spi_device(dev); 49617b26a0SRaghavendra Ganiga unsigned char buf[2]; 50617b26a0SRaghavendra Ganiga 51617b26a0SRaghavendra Ganiga buf[0] = address & 0x7F; 52617b26a0SRaghavendra Ganiga buf[1] = data; 53617b26a0SRaghavendra Ganiga 54617b26a0SRaghavendra Ganiga return spi_write_then_read(spi, buf, 2, NULL, 0); 55617b26a0SRaghavendra Ganiga } 56617b26a0SRaghavendra Ganiga 57617b26a0SRaghavendra Ganiga static int ds1347_read_time(struct device *dev, struct rtc_time *dt) 58617b26a0SRaghavendra Ganiga { 59617b26a0SRaghavendra Ganiga struct spi_device *spi = to_spi_device(dev); 60617b26a0SRaghavendra Ganiga int err; 61617b26a0SRaghavendra Ganiga unsigned char buf[8]; 62617b26a0SRaghavendra Ganiga 63617b26a0SRaghavendra Ganiga buf[0] = DS1347_CLOCK_BURST | 0x80; 64617b26a0SRaghavendra Ganiga 65617b26a0SRaghavendra Ganiga err = spi_write_then_read(spi, buf, 1, buf, 8); 66617b26a0SRaghavendra Ganiga if (err) 67617b26a0SRaghavendra Ganiga return err; 68617b26a0SRaghavendra Ganiga 69617b26a0SRaghavendra Ganiga dt->tm_sec = bcd2bin(buf[0]); 70617b26a0SRaghavendra Ganiga dt->tm_min = bcd2bin(buf[1]); 71617b26a0SRaghavendra Ganiga dt->tm_hour = bcd2bin(buf[2] & 0x3F); 72617b26a0SRaghavendra Ganiga dt->tm_mday = bcd2bin(buf[3]); 73617b26a0SRaghavendra Ganiga dt->tm_mon = bcd2bin(buf[4]) - 1; 74617b26a0SRaghavendra Ganiga dt->tm_wday = bcd2bin(buf[5]) - 1; 75617b26a0SRaghavendra Ganiga dt->tm_year = bcd2bin(buf[6]) + 100; 76617b26a0SRaghavendra Ganiga 77617b26a0SRaghavendra Ganiga return rtc_valid_tm(dt); 78617b26a0SRaghavendra Ganiga } 79617b26a0SRaghavendra Ganiga 80617b26a0SRaghavendra Ganiga static int ds1347_set_time(struct device *dev, struct rtc_time *dt) 81617b26a0SRaghavendra Ganiga { 82617b26a0SRaghavendra Ganiga struct spi_device *spi = to_spi_device(dev); 83617b26a0SRaghavendra Ganiga unsigned char buf[9]; 84617b26a0SRaghavendra Ganiga 85617b26a0SRaghavendra Ganiga buf[0] = DS1347_CLOCK_BURST & 0x7F; 86617b26a0SRaghavendra Ganiga buf[1] = bin2bcd(dt->tm_sec); 87617b26a0SRaghavendra Ganiga buf[2] = bin2bcd(dt->tm_min); 88617b26a0SRaghavendra Ganiga buf[3] = (bin2bcd(dt->tm_hour) & 0x3F); 89617b26a0SRaghavendra Ganiga buf[4] = bin2bcd(dt->tm_mday); 90617b26a0SRaghavendra Ganiga buf[5] = bin2bcd(dt->tm_mon + 1); 91617b26a0SRaghavendra Ganiga buf[6] = bin2bcd(dt->tm_wday + 1); 92617b26a0SRaghavendra Ganiga 93617b26a0SRaghavendra Ganiga /* year in linux is from 1900 i.e in range of 100 94617b26a0SRaghavendra Ganiga in rtc it is from 00 to 99 */ 95617b26a0SRaghavendra Ganiga dt->tm_year = dt->tm_year % 100; 96617b26a0SRaghavendra Ganiga 97617b26a0SRaghavendra Ganiga buf[7] = bin2bcd(dt->tm_year); 98617b26a0SRaghavendra Ganiga buf[8] = bin2bcd(0x00); 99617b26a0SRaghavendra Ganiga 100617b26a0SRaghavendra Ganiga /* write the rtc settings */ 101617b26a0SRaghavendra Ganiga return spi_write_then_read(spi, buf, 9, NULL, 0); 102617b26a0SRaghavendra Ganiga } 103617b26a0SRaghavendra Ganiga 104617b26a0SRaghavendra Ganiga static const struct rtc_class_ops ds1347_rtc_ops = { 105617b26a0SRaghavendra Ganiga .read_time = ds1347_read_time, 106617b26a0SRaghavendra Ganiga .set_time = ds1347_set_time, 107617b26a0SRaghavendra Ganiga }; 108617b26a0SRaghavendra Ganiga 109617b26a0SRaghavendra Ganiga static int ds1347_probe(struct spi_device *spi) 110617b26a0SRaghavendra Ganiga { 111617b26a0SRaghavendra Ganiga struct rtc_device *rtc; 112617b26a0SRaghavendra Ganiga unsigned char data; 113617b26a0SRaghavendra Ganiga int res; 114617b26a0SRaghavendra Ganiga 115617b26a0SRaghavendra Ganiga /* spi setup with ds1347 in mode 3 and bits per word as 8 */ 116617b26a0SRaghavendra Ganiga spi->mode = SPI_MODE_3; 117617b26a0SRaghavendra Ganiga spi->bits_per_word = 8; 118617b26a0SRaghavendra Ganiga spi_setup(spi); 119617b26a0SRaghavendra Ganiga 120617b26a0SRaghavendra Ganiga /* RTC Settings */ 121617b26a0SRaghavendra Ganiga res = ds1347_read_reg(&spi->dev, DS1347_SECONDS_REG, &data); 122617b26a0SRaghavendra Ganiga if (res) 123617b26a0SRaghavendra Ganiga return res; 124617b26a0SRaghavendra Ganiga 125617b26a0SRaghavendra Ganiga /* Disable the write protect of rtc */ 126617b26a0SRaghavendra Ganiga ds1347_read_reg(&spi->dev, DS1347_CONTROL_REG, &data); 127617b26a0SRaghavendra Ganiga data = data & ~(1<<7); 128617b26a0SRaghavendra Ganiga ds1347_write_reg(&spi->dev, DS1347_CONTROL_REG, data); 129617b26a0SRaghavendra Ganiga 130617b26a0SRaghavendra Ganiga /* Enable the oscillator , disable the oscillator stop flag, 131617b26a0SRaghavendra Ganiga and glitch filter to reduce current consumption */ 132617b26a0SRaghavendra Ganiga ds1347_read_reg(&spi->dev, DS1347_STATUS_REG, &data); 133617b26a0SRaghavendra Ganiga data = data & 0x1B; 134617b26a0SRaghavendra Ganiga ds1347_write_reg(&spi->dev, DS1347_STATUS_REG, data); 135617b26a0SRaghavendra Ganiga 136617b26a0SRaghavendra Ganiga /* display the settings */ 137617b26a0SRaghavendra Ganiga ds1347_read_reg(&spi->dev, DS1347_CONTROL_REG, &data); 138617b26a0SRaghavendra Ganiga dev_info(&spi->dev, "DS1347 RTC CTRL Reg = 0x%02x\n", data); 139617b26a0SRaghavendra Ganiga 140617b26a0SRaghavendra Ganiga ds1347_read_reg(&spi->dev, DS1347_STATUS_REG, &data); 141617b26a0SRaghavendra Ganiga dev_info(&spi->dev, "DS1347 RTC Status Reg = 0x%02x\n", data); 142617b26a0SRaghavendra Ganiga 143617b26a0SRaghavendra Ganiga rtc = devm_rtc_device_register(&spi->dev, "ds1347", 144617b26a0SRaghavendra Ganiga &ds1347_rtc_ops, THIS_MODULE); 145617b26a0SRaghavendra Ganiga 146617b26a0SRaghavendra Ganiga if (IS_ERR(rtc)) 147617b26a0SRaghavendra Ganiga return PTR_ERR(rtc); 148617b26a0SRaghavendra Ganiga 149617b26a0SRaghavendra Ganiga spi_set_drvdata(spi, rtc); 150617b26a0SRaghavendra Ganiga 151617b26a0SRaghavendra Ganiga return 0; 152617b26a0SRaghavendra Ganiga } 153617b26a0SRaghavendra Ganiga 154617b26a0SRaghavendra Ganiga static struct spi_driver ds1347_driver = { 155617b26a0SRaghavendra Ganiga .driver = { 156617b26a0SRaghavendra Ganiga .name = "ds1347", 157617b26a0SRaghavendra Ganiga .owner = THIS_MODULE, 158617b26a0SRaghavendra Ganiga }, 159617b26a0SRaghavendra Ganiga .probe = ds1347_probe, 160617b26a0SRaghavendra Ganiga }; 161617b26a0SRaghavendra Ganiga 162617b26a0SRaghavendra Ganiga module_spi_driver(ds1347_driver); 163617b26a0SRaghavendra Ganiga 164617b26a0SRaghavendra Ganiga MODULE_DESCRIPTION("DS1347 SPI RTC DRIVER"); 165617b26a0SRaghavendra Ganiga MODULE_AUTHOR("Raghavendra C Ganiga <ravi23ganiga@gmail.com>"); 166617b26a0SRaghavendra Ganiga MODULE_LICENSE("GPL v2"); 167