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