1 /* 2 * Seiko Instruments S-35390A RTC Driver 3 * 4 * Copyright (c) 2007 Byron Bradley 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/rtc.h> 14 #include <linux/i2c.h> 15 #include <linux/bitrev.h> 16 #include <linux/bcd.h> 17 #include <linux/slab.h> 18 19 #define S35390A_CMD_STATUS1 0 20 #define S35390A_CMD_STATUS2 1 21 #define S35390A_CMD_TIME1 2 22 23 #define S35390A_BYTE_YEAR 0 24 #define S35390A_BYTE_MONTH 1 25 #define S35390A_BYTE_DAY 2 26 #define S35390A_BYTE_WDAY 3 27 #define S35390A_BYTE_HOURS 4 28 #define S35390A_BYTE_MINS 5 29 #define S35390A_BYTE_SECS 6 30 31 #define S35390A_FLAG_POC 0x01 32 #define S35390A_FLAG_BLD 0x02 33 #define S35390A_FLAG_24H 0x40 34 #define S35390A_FLAG_RESET 0x80 35 #define S35390A_FLAG_TEST 0x01 36 37 struct s35390a { 38 struct i2c_client *client[8]; 39 struct rtc_device *rtc; 40 int twentyfourhour; 41 }; 42 43 static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len) 44 { 45 struct i2c_client *client = s35390a->client[reg]; 46 struct i2c_msg msg[] = { 47 { client->addr, 0, len, buf }, 48 }; 49 50 if ((i2c_transfer(client->adapter, msg, 1)) != 1) 51 return -EIO; 52 53 return 0; 54 } 55 56 static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) 57 { 58 struct i2c_client *client = s35390a->client[reg]; 59 struct i2c_msg msg[] = { 60 { client->addr, I2C_M_RD, len, buf }, 61 }; 62 63 if ((i2c_transfer(client->adapter, msg, 1)) != 1) 64 return -EIO; 65 66 return 0; 67 } 68 69 static int s35390a_reset(struct s35390a *s35390a) 70 { 71 char buf[1]; 72 73 if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0) 74 return -EIO; 75 76 if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD))) 77 return 0; 78 79 buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H); 80 buf[0] &= 0xf0; 81 return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); 82 } 83 84 static int s35390a_disable_test_mode(struct s35390a *s35390a) 85 { 86 char buf[1]; 87 88 if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0) 89 return -EIO; 90 91 if (!(buf[0] & S35390A_FLAG_TEST)) 92 return 0; 93 94 buf[0] &= ~S35390A_FLAG_TEST; 95 return s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)); 96 } 97 98 static char s35390a_hr2reg(struct s35390a *s35390a, int hour) 99 { 100 if (s35390a->twentyfourhour) 101 return BIN2BCD(hour); 102 103 if (hour < 12) 104 return BIN2BCD(hour); 105 106 return 0x40 | BIN2BCD(hour - 12); 107 } 108 109 static int s35390a_reg2hr(struct s35390a *s35390a, char reg) 110 { 111 unsigned hour; 112 113 if (s35390a->twentyfourhour) 114 return BCD2BIN(reg & 0x3f); 115 116 hour = BCD2BIN(reg & 0x3f); 117 if (reg & 0x40) 118 hour += 12; 119 120 return hour; 121 } 122 123 static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) 124 { 125 struct s35390a *s35390a = i2c_get_clientdata(client); 126 int i, err; 127 char buf[7]; 128 129 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, " 130 "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, 131 tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, 132 tm->tm_wday); 133 134 buf[S35390A_BYTE_YEAR] = BIN2BCD(tm->tm_year - 100); 135 buf[S35390A_BYTE_MONTH] = BIN2BCD(tm->tm_mon + 1); 136 buf[S35390A_BYTE_DAY] = BIN2BCD(tm->tm_mday); 137 buf[S35390A_BYTE_WDAY] = BIN2BCD(tm->tm_wday); 138 buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour); 139 buf[S35390A_BYTE_MINS] = BIN2BCD(tm->tm_min); 140 buf[S35390A_BYTE_SECS] = BIN2BCD(tm->tm_sec); 141 142 /* This chip expects the bits of each byte to be in reverse order */ 143 for (i = 0; i < 7; ++i) 144 buf[i] = bitrev8(buf[i]); 145 146 err = s35390a_set_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); 147 148 return err; 149 } 150 151 static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) 152 { 153 struct s35390a *s35390a = i2c_get_clientdata(client); 154 char buf[7]; 155 int i, err; 156 157 err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); 158 if (err < 0) 159 return err; 160 161 /* This chip returns the bits of each byte in reverse order */ 162 for (i = 0; i < 7; ++i) 163 buf[i] = bitrev8(buf[i]); 164 165 tm->tm_sec = BCD2BIN(buf[S35390A_BYTE_SECS]); 166 tm->tm_min = BCD2BIN(buf[S35390A_BYTE_MINS]); 167 tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]); 168 tm->tm_wday = BCD2BIN(buf[S35390A_BYTE_WDAY]); 169 tm->tm_mday = BCD2BIN(buf[S35390A_BYTE_DAY]); 170 tm->tm_mon = BCD2BIN(buf[S35390A_BYTE_MONTH]) - 1; 171 tm->tm_year = BCD2BIN(buf[S35390A_BYTE_YEAR]) + 100; 172 173 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, " 174 "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, 175 tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, 176 tm->tm_wday); 177 178 return rtc_valid_tm(tm); 179 } 180 181 static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) 182 { 183 return s35390a_get_datetime(to_i2c_client(dev), tm); 184 } 185 186 static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) 187 { 188 return s35390a_set_datetime(to_i2c_client(dev), tm); 189 } 190 191 static const struct rtc_class_ops s35390a_rtc_ops = { 192 .read_time = s35390a_rtc_read_time, 193 .set_time = s35390a_rtc_set_time, 194 }; 195 196 static struct i2c_driver s35390a_driver; 197 198 static int s35390a_probe(struct i2c_client *client) 199 { 200 int err; 201 unsigned int i; 202 struct s35390a *s35390a; 203 struct rtc_time tm; 204 char buf[1]; 205 206 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 207 err = -ENODEV; 208 goto exit; 209 } 210 211 s35390a = kzalloc(sizeof(struct s35390a), GFP_KERNEL); 212 if (!s35390a) { 213 err = -ENOMEM; 214 goto exit; 215 } 216 217 s35390a->client[0] = client; 218 i2c_set_clientdata(client, s35390a); 219 220 /* This chip uses multiple addresses, use dummy devices for them */ 221 for (i = 1; i < 8; ++i) { 222 s35390a->client[i] = i2c_new_dummy(client->adapter, 223 client->addr + i, "rtc-s35390a"); 224 if (!s35390a->client[i]) { 225 dev_err(&client->dev, "Address %02x unavailable\n", 226 client->addr + i); 227 err = -EBUSY; 228 goto exit_dummy; 229 } 230 } 231 232 err = s35390a_reset(s35390a); 233 if (err < 0) { 234 dev_err(&client->dev, "error resetting chip\n"); 235 goto exit_dummy; 236 } 237 238 err = s35390a_disable_test_mode(s35390a); 239 if (err < 0) { 240 dev_err(&client->dev, "error disabling test mode\n"); 241 goto exit_dummy; 242 } 243 244 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); 245 if (err < 0) { 246 dev_err(&client->dev, "error checking 12/24 hour mode\n"); 247 goto exit_dummy; 248 } 249 if (buf[0] & S35390A_FLAG_24H) 250 s35390a->twentyfourhour = 1; 251 else 252 s35390a->twentyfourhour = 0; 253 254 if (s35390a_get_datetime(client, &tm) < 0) 255 dev_warn(&client->dev, "clock needs to be set\n"); 256 257 s35390a->rtc = rtc_device_register(s35390a_driver.driver.name, 258 &client->dev, &s35390a_rtc_ops, THIS_MODULE); 259 260 if (IS_ERR(s35390a->rtc)) { 261 err = PTR_ERR(s35390a->rtc); 262 goto exit_dummy; 263 } 264 return 0; 265 266 exit_dummy: 267 for (i = 1; i < 8; ++i) 268 if (s35390a->client[i]) 269 i2c_unregister_device(s35390a->client[i]); 270 kfree(s35390a); 271 i2c_set_clientdata(client, NULL); 272 273 exit: 274 return err; 275 } 276 277 static int s35390a_remove(struct i2c_client *client) 278 { 279 unsigned int i; 280 281 struct s35390a *s35390a = i2c_get_clientdata(client); 282 for (i = 1; i < 8; ++i) 283 if (s35390a->client[i]) 284 i2c_unregister_device(s35390a->client[i]); 285 286 rtc_device_unregister(s35390a->rtc); 287 kfree(s35390a); 288 i2c_set_clientdata(client, NULL); 289 290 return 0; 291 } 292 293 static struct i2c_driver s35390a_driver = { 294 .driver = { 295 .name = "rtc-s35390a", 296 }, 297 .probe = s35390a_probe, 298 .remove = s35390a_remove, 299 }; 300 301 static int __init s35390a_rtc_init(void) 302 { 303 return i2c_add_driver(&s35390a_driver); 304 } 305 306 static void __exit s35390a_rtc_exit(void) 307 { 308 i2c_del_driver(&s35390a_driver); 309 } 310 311 MODULE_AUTHOR("Byron Bradley <byron.bbradley@gmail.com>"); 312 MODULE_DESCRIPTION("S35390A RTC driver"); 313 MODULE_LICENSE("GPL"); 314 315 module_init(s35390a_rtc_init); 316 module_exit(s35390a_rtc_exit); 317