rtc: basic implementation of Epson RX-8581 I2C Real Time Clock

Provide the basic "get" and "set" functionality for the Epson RX-8581 I2C
RTC. It currently does not support the RTC's Alarm or Fixed-cycle timer.

[akpm@linux-foundation.org: need log2.h for ilog2(), remove unneeded initialisation]
Signed-off-by: Martyn Welch <martyn.welch@gefanuc.com>
Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Cc: David Brownell <david-b@pacbell.net>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Martyn Welch and committed by
Linus Torvalds
a7fa9851 077eaf5b

+290
+8
drivers/rtc/Kconfig
··· 277 277 This driver can also be built as a module. If so the module 278 278 will be called rtc-fm3130. 279 279 280 + config RTC_DRV_RX8581 281 + tristate "Epson RX-8581" 282 + help 283 + If you say yes here you will get support for the Epson RX-8581. 284 + 285 + This driver can also be built as a module. If so the module 286 + will be called rtc-rx8581. 287 + 280 288 endif # I2C 281 289 282 290 comment "SPI RTC drivers"
+1
drivers/rtc/Makefile
··· 57 57 obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o 58 58 obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o 59 59 obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o 60 + obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o 60 61 obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o 61 62 obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o 62 63 obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
+281
drivers/rtc/rtc-rx8581.c
··· 1 + /* 2 + * An I2C driver for the Epson RX8581 RTC 3 + * 4 + * Author: Martyn Welch <martyn.welch@gefanuc.com> 5 + * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) 12 + * Copyright 2005-06 Tower Technologies 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/i2c.h> 17 + #include <linux/bcd.h> 18 + #include <linux/rtc.h> 19 + #include <linux/log2.h> 20 + 21 + #define DRV_VERSION "0.1" 22 + 23 + #define RX8581_REG_SC 0x00 /* Second in BCD */ 24 + #define RX8581_REG_MN 0x01 /* Minute in BCD */ 25 + #define RX8581_REG_HR 0x02 /* Hour in BCD */ 26 + #define RX8581_REG_DW 0x03 /* Day of Week */ 27 + #define RX8581_REG_DM 0x04 /* Day of Month in BCD */ 28 + #define RX8581_REG_MO 0x05 /* Month in BCD */ 29 + #define RX8581_REG_YR 0x06 /* Year in BCD */ 30 + #define RX8581_REG_RAM 0x07 /* RAM */ 31 + #define RX8581_REG_AMN 0x08 /* Alarm Min in BCD*/ 32 + #define RX8581_REG_AHR 0x09 /* Alarm Hour in BCD */ 33 + #define RX8581_REG_ADM 0x0A 34 + #define RX8581_REG_ADW 0x0A 35 + #define RX8581_REG_TMR0 0x0B 36 + #define RX8581_REG_TMR1 0x0C 37 + #define RX8581_REG_EXT 0x0D /* Extension Register */ 38 + #define RX8581_REG_FLAG 0x0E /* Flag Register */ 39 + #define RX8581_REG_CTRL 0x0F /* Control Register */ 40 + 41 + 42 + /* Flag Register bit definitions */ 43 + #define RX8581_FLAG_UF 0x20 /* Update */ 44 + #define RX8581_FLAG_TF 0x10 /* Timer */ 45 + #define RX8581_FLAG_AF 0x08 /* Alarm */ 46 + #define RX8581_FLAG_VLF 0x02 /* Voltage Low */ 47 + 48 + /* Control Register bit definitions */ 49 + #define RX8581_CTRL_UIE 0x20 /* Update Interrupt Enable */ 50 + #define RX8581_CTRL_TIE 0x10 /* Timer Interrupt Enable */ 51 + #define RX8581_CTRL_AIE 0x08 /* Alarm Interrupt Enable */ 52 + #define RX8581_CTRL_STOP 0x02 /* STOP bit */ 53 + #define RX8581_CTRL_RESET 0x01 /* RESET bit */ 54 + 55 + static struct i2c_driver rx8581_driver; 56 + 57 + /* 58 + * In the routines that deal directly with the rx8581 hardware, we use 59 + * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. 60 + */ 61 + static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) 62 + { 63 + unsigned char date[7]; 64 + int data, err; 65 + 66 + /* First we ensure that the "update flag" is not set, we read the 67 + * time and date then re-read the "update flag". If the update flag 68 + * has been set, we know that the time has changed during the read so 69 + * we repeat the whole process again. 70 + */ 71 + data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); 72 + if (data < 0) { 73 + dev_err(&client->dev, "Unable to read device flags\n"); 74 + return -EIO; 75 + } 76 + 77 + do { 78 + /* If update flag set, clear it */ 79 + if (data & RX8581_FLAG_UF) { 80 + err = i2c_smbus_write_byte_data(client, 81 + RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); 82 + if (err != 0) { 83 + dev_err(&client->dev, "Unable to write device " 84 + "flags\n"); 85 + return -EIO; 86 + } 87 + } 88 + 89 + /* Now read time and date */ 90 + err = i2c_smbus_read_i2c_block_data(client, RX8581_REG_SC, 91 + 7, date); 92 + if (err < 0) { 93 + dev_err(&client->dev, "Unable to read date\n"); 94 + return -EIO; 95 + } 96 + 97 + /* Check flag register */ 98 + data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); 99 + if (data < 0) { 100 + dev_err(&client->dev, "Unable to read device flags\n"); 101 + return -EIO; 102 + } 103 + } while (data & RX8581_FLAG_UF); 104 + 105 + if (data & RX8581_FLAG_VLF) 106 + dev_info(&client->dev, 107 + "low voltage detected, date/time is not reliable.\n"); 108 + 109 + dev_dbg(&client->dev, 110 + "%s: raw data is sec=%02x, min=%02x, hr=%02x, " 111 + "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", 112 + __func__, 113 + date[0], date[1], date[2], date[3], date[4], date[5], date[6]); 114 + 115 + tm->tm_sec = bcd2bin(date[RX8581_REG_SC] & 0x7F); 116 + tm->tm_min = bcd2bin(date[RX8581_REG_MN] & 0x7F); 117 + tm->tm_hour = bcd2bin(date[RX8581_REG_HR] & 0x3F); /* rtc hr 0-23 */ 118 + tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F); 119 + tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F); 120 + tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ 121 + tm->tm_year = bcd2bin(date[RX8581_REG_YR]); 122 + if (tm->tm_year < 70) 123 + tm->tm_year += 100; /* assume we are in 1970...2069 */ 124 + 125 + 126 + dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " 127 + "mday=%d, mon=%d, year=%d, wday=%d\n", 128 + __func__, 129 + tm->tm_sec, tm->tm_min, tm->tm_hour, 130 + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 131 + 132 + err = rtc_valid_tm(tm); 133 + if (err < 0) 134 + dev_err(&client->dev, "retrieved date/time is not valid.\n"); 135 + 136 + return err; 137 + } 138 + 139 + static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) 140 + { 141 + int data, err; 142 + unsigned char buf[7]; 143 + 144 + dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " 145 + "mday=%d, mon=%d, year=%d, wday=%d\n", 146 + __func__, 147 + tm->tm_sec, tm->tm_min, tm->tm_hour, 148 + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 149 + 150 + /* hours, minutes and seconds */ 151 + buf[RX8581_REG_SC] = bin2bcd(tm->tm_sec); 152 + buf[RX8581_REG_MN] = bin2bcd(tm->tm_min); 153 + buf[RX8581_REG_HR] = bin2bcd(tm->tm_hour); 154 + 155 + buf[RX8581_REG_DM] = bin2bcd(tm->tm_mday); 156 + 157 + /* month, 1 - 12 */ 158 + buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1); 159 + 160 + /* year and century */ 161 + buf[RX8581_REG_YR] = bin2bcd(tm->tm_year % 100); 162 + buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); 163 + 164 + /* Stop the clock */ 165 + data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); 166 + if (data < 0) { 167 + dev_err(&client->dev, "Unable to read control register\n"); 168 + return -EIO; 169 + } 170 + 171 + err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, 172 + (data | RX8581_CTRL_STOP)); 173 + if (err < 0) { 174 + dev_err(&client->dev, "Unable to write control register\n"); 175 + return -EIO; 176 + } 177 + 178 + /* write register's data */ 179 + err = i2c_smbus_write_i2c_block_data(client, RX8581_REG_SC, 7, buf); 180 + if (err < 0) { 181 + dev_err(&client->dev, "Unable to write to date registers\n"); 182 + return -EIO; 183 + } 184 + 185 + /* Restart the clock */ 186 + data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); 187 + if (data < 0) { 188 + dev_err(&client->dev, "Unable to read control register\n"); 189 + return -EIO; 190 + } 191 + 192 + err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, 193 + (data | ~(RX8581_CTRL_STOP))); 194 + if (err != 0) { 195 + dev_err(&client->dev, "Unable to write control register\n"); 196 + return -EIO; 197 + } 198 + 199 + return 0; 200 + } 201 + 202 + static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) 203 + { 204 + return rx8581_get_datetime(to_i2c_client(dev), tm); 205 + } 206 + 207 + static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) 208 + { 209 + return rx8581_set_datetime(to_i2c_client(dev), tm); 210 + } 211 + 212 + static const struct rtc_class_ops rx8581_rtc_ops = { 213 + .read_time = rx8581_rtc_read_time, 214 + .set_time = rx8581_rtc_set_time, 215 + }; 216 + 217 + static int __devinit rx8581_probe(struct i2c_client *client, 218 + const struct i2c_device_id *id) 219 + { 220 + struct rtc_device *rtc; 221 + 222 + dev_dbg(&client->dev, "%s\n", __func__); 223 + 224 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 225 + return -ENODEV; 226 + 227 + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); 228 + 229 + rtc = rtc_device_register(rx8581_driver.driver.name, 230 + &client->dev, &rx8581_rtc_ops, THIS_MODULE); 231 + 232 + if (IS_ERR(rtc)) 233 + return PTR_ERR(rtc); 234 + 235 + i2c_set_clientdata(client, rtc); 236 + 237 + return 0; 238 + } 239 + 240 + static int __devexit rx8581_remove(struct i2c_client *client) 241 + { 242 + struct rtc_device *rtc = i2c_get_clientdata(client); 243 + 244 + rtc_device_unregister(rtc); 245 + 246 + return 0; 247 + } 248 + 249 + static const struct i2c_device_id rx8581_id[] = { 250 + { "rx8581", 0 }, 251 + { } 252 + }; 253 + MODULE_DEVICE_TABLE(i2c, rx8581_id); 254 + 255 + static struct i2c_driver rx8581_driver = { 256 + .driver = { 257 + .name = "rtc-rx8581", 258 + .owner = THIS_MODULE, 259 + }, 260 + .probe = rx8581_probe, 261 + .remove = __devexit_p(rx8581_remove), 262 + .id_table = rx8581_id, 263 + }; 264 + 265 + static int __init rx8581_init(void) 266 + { 267 + return i2c_add_driver(&rx8581_driver); 268 + } 269 + 270 + static void __exit rx8581_exit(void) 271 + { 272 + i2c_del_driver(&rx8581_driver); 273 + } 274 + 275 + MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>"); 276 + MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); 277 + MODULE_LICENSE("GPL"); 278 + MODULE_VERSION(DRV_VERSION); 279 + 280 + module_init(rx8581_init); 281 + module_exit(rx8581_exit);