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#define S35390A_CMD_TIME2 3 23#define S35390A_CMD_INT2_REG1 5 24 25#define S35390A_BYTE_YEAR 0 26#define S35390A_BYTE_MONTH 1 27#define S35390A_BYTE_DAY 2 28#define S35390A_BYTE_WDAY 3 29#define S35390A_BYTE_HOURS 4 30#define S35390A_BYTE_MINS 5 31#define S35390A_BYTE_SECS 6 32 33#define S35390A_ALRM_BYTE_WDAY 0 34#define S35390A_ALRM_BYTE_HOURS 1 35#define S35390A_ALRM_BYTE_MINS 2 36 37#define S35390A_FLAG_POC 0x01 38#define S35390A_FLAG_BLD 0x02 39#define S35390A_FLAG_24H 0x40 40#define S35390A_FLAG_RESET 0x80 41#define S35390A_FLAG_TEST 0x01 42 43#define S35390A_INT2_MODE_MASK 0xF0 44 45#define S35390A_INT2_MODE_NOINTR 0x00 46#define S35390A_INT2_MODE_FREQ 0x10 47#define S35390A_INT2_MODE_ALARM 0x40 48#define S35390A_INT2_MODE_PMIN_EDG 0x20 49 50static const struct i2c_device_id s35390a_id[] = { 51 { "s35390a", 0 }, 52 { } 53}; 54MODULE_DEVICE_TABLE(i2c, s35390a_id); 55 56struct s35390a { 57 struct i2c_client *client[8]; 58 struct rtc_device *rtc; 59 int twentyfourhour; 60}; 61 62static int s35390a_set_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 { 67 .addr = client->addr, 68 .len = len, 69 .buf = buf 70 }, 71 }; 72 73 if ((i2c_transfer(client->adapter, msg, 1)) != 1) 74 return -EIO; 75 76 return 0; 77} 78 79static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) 80{ 81 struct i2c_client *client = s35390a->client[reg]; 82 struct i2c_msg msg[] = { 83 { 84 .addr = client->addr, 85 .flags = I2C_M_RD, 86 .len = len, 87 .buf = buf 88 }, 89 }; 90 91 if ((i2c_transfer(client->adapter, msg, 1)) != 1) 92 return -EIO; 93 94 return 0; 95} 96 97static int s35390a_reset(struct s35390a *s35390a) 98{ 99 char buf[1]; 100 101 if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0) 102 return -EIO; 103 104 if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD))) 105 return 0; 106 107 buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H); 108 buf[0] &= 0xf0; 109 return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); 110} 111 112static int s35390a_disable_test_mode(struct s35390a *s35390a) 113{ 114 char buf[1]; 115 116 if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0) 117 return -EIO; 118 119 if (!(buf[0] & S35390A_FLAG_TEST)) 120 return 0; 121 122 buf[0] &= ~S35390A_FLAG_TEST; 123 return s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)); 124} 125 126static char s35390a_hr2reg(struct s35390a *s35390a, int hour) 127{ 128 if (s35390a->twentyfourhour) 129 return bin2bcd(hour); 130 131 if (hour < 12) 132 return bin2bcd(hour); 133 134 return 0x40 | bin2bcd(hour - 12); 135} 136 137static int s35390a_reg2hr(struct s35390a *s35390a, char reg) 138{ 139 unsigned hour; 140 141 if (s35390a->twentyfourhour) 142 return bcd2bin(reg & 0x3f); 143 144 hour = bcd2bin(reg & 0x3f); 145 if (reg & 0x40) 146 hour += 12; 147 148 return hour; 149} 150 151static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) 152{ 153 struct s35390a *s35390a = i2c_get_clientdata(client); 154 int i, err; 155 char buf[7]; 156 157 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, " 158 "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, 159 tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, 160 tm->tm_wday); 161 162 buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100); 163 buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1); 164 buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday); 165 buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday); 166 buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour); 167 buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min); 168 buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec); 169 170 /* This chip expects the bits of each byte to be in reverse order */ 171 for (i = 0; i < 7; ++i) 172 buf[i] = bitrev8(buf[i]); 173 174 err = s35390a_set_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); 175 176 return err; 177} 178 179static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) 180{ 181 struct s35390a *s35390a = i2c_get_clientdata(client); 182 char buf[7]; 183 int i, err; 184 185 err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); 186 if (err < 0) 187 return err; 188 189 /* This chip returns the bits of each byte in reverse order */ 190 for (i = 0; i < 7; ++i) 191 buf[i] = bitrev8(buf[i]); 192 193 tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]); 194 tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]); 195 tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]); 196 tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]); 197 tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]); 198 tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1; 199 tm->tm_year = bcd2bin(buf[S35390A_BYTE_YEAR]) + 100; 200 201 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, " 202 "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, 203 tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, 204 tm->tm_wday); 205 206 return rtc_valid_tm(tm); 207} 208 209static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) 210{ 211 struct s35390a *s35390a = i2c_get_clientdata(client); 212 char buf[3], sts = 0; 213 int err, i; 214 215 dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\ 216 "mon=%d, year=%d, wday=%d\n", __func__, alm->time.tm_sec, 217 alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, 218 alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); 219 220 /* disable interrupt */ 221 err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); 222 if (err < 0) 223 return err; 224 225 /* clear pending interrupt, if any */ 226 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); 227 if (err < 0) 228 return err; 229 230 if (alm->enabled) 231 sts = S35390A_INT2_MODE_ALARM; 232 else 233 sts = S35390A_INT2_MODE_NOINTR; 234 235 /* This chip expects the bits of each byte to be in reverse order */ 236 sts = bitrev8(sts); 237 238 /* set interupt mode*/ 239 err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); 240 if (err < 0) 241 return err; 242 243 if (alm->time.tm_wday != -1) 244 buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; 245 246 buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, 247 alm->time.tm_hour) | 0x80; 248 buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80; 249 250 if (alm->time.tm_hour >= 12) 251 buf[S35390A_ALRM_BYTE_HOURS] |= 0x40; 252 253 for (i = 0; i < 3; ++i) 254 buf[i] = bitrev8(buf[i]); 255 256 err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf, 257 sizeof(buf)); 258 259 return err; 260} 261 262static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) 263{ 264 struct s35390a *s35390a = i2c_get_clientdata(client); 265 char buf[3], sts; 266 int i, err; 267 268 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); 269 if (err < 0) 270 return err; 271 272 if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) 273 return -EINVAL; 274 275 err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); 276 if (err < 0) 277 return err; 278 279 /* This chip returns the bits of each byte in reverse order */ 280 for (i = 0; i < 3; ++i) { 281 buf[i] = bitrev8(buf[i]); 282 buf[i] &= ~0x80; 283 } 284 285 alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); 286 alm->time.tm_hour = s35390a_reg2hr(s35390a, 287 buf[S35390A_ALRM_BYTE_HOURS]); 288 alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); 289 290 dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", 291 __func__, alm->time.tm_min, alm->time.tm_hour, 292 alm->time.tm_wday); 293 294 return 0; 295} 296 297static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 298{ 299 return s35390a_read_alarm(to_i2c_client(dev), alm); 300} 301 302static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 303{ 304 return s35390a_set_alarm(to_i2c_client(dev), alm); 305} 306 307static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) 308{ 309 return s35390a_get_datetime(to_i2c_client(dev), tm); 310} 311 312static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) 313{ 314 return s35390a_set_datetime(to_i2c_client(dev), tm); 315} 316 317static const struct rtc_class_ops s35390a_rtc_ops = { 318 .read_time = s35390a_rtc_read_time, 319 .set_time = s35390a_rtc_set_time, 320 .set_alarm = s35390a_rtc_set_alarm, 321 .read_alarm = s35390a_rtc_read_alarm, 322 323}; 324 325static struct i2c_driver s35390a_driver; 326 327static int s35390a_probe(struct i2c_client *client, 328 const struct i2c_device_id *id) 329{ 330 int err; 331 unsigned int i; 332 struct s35390a *s35390a; 333 struct rtc_time tm; 334 char buf[1]; 335 336 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 337 err = -ENODEV; 338 goto exit; 339 } 340 341 s35390a = devm_kzalloc(&client->dev, sizeof(struct s35390a), 342 GFP_KERNEL); 343 if (!s35390a) { 344 err = -ENOMEM; 345 goto exit; 346 } 347 348 s35390a->client[0] = client; 349 i2c_set_clientdata(client, s35390a); 350 351 /* This chip uses multiple addresses, use dummy devices for them */ 352 for (i = 1; i < 8; ++i) { 353 s35390a->client[i] = i2c_new_dummy(client->adapter, 354 client->addr + i); 355 if (!s35390a->client[i]) { 356 dev_err(&client->dev, "Address %02x unavailable\n", 357 client->addr + i); 358 err = -EBUSY; 359 goto exit_dummy; 360 } 361 } 362 363 err = s35390a_reset(s35390a); 364 if (err < 0) { 365 dev_err(&client->dev, "error resetting chip\n"); 366 goto exit_dummy; 367 } 368 369 err = s35390a_disable_test_mode(s35390a); 370 if (err < 0) { 371 dev_err(&client->dev, "error disabling test mode\n"); 372 goto exit_dummy; 373 } 374 375 err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)); 376 if (err < 0) { 377 dev_err(&client->dev, "error checking 12/24 hour mode\n"); 378 goto exit_dummy; 379 } 380 if (buf[0] & S35390A_FLAG_24H) 381 s35390a->twentyfourhour = 1; 382 else 383 s35390a->twentyfourhour = 0; 384 385 if (s35390a_get_datetime(client, &tm) < 0) 386 dev_warn(&client->dev, "clock needs to be set\n"); 387 388 device_set_wakeup_capable(&client->dev, 1); 389 390 s35390a->rtc = devm_rtc_device_register(&client->dev, 391 s35390a_driver.driver.name, 392 &s35390a_rtc_ops, THIS_MODULE); 393 394 if (IS_ERR(s35390a->rtc)) { 395 err = PTR_ERR(s35390a->rtc); 396 goto exit_dummy; 397 } 398 return 0; 399 400exit_dummy: 401 for (i = 1; i < 8; ++i) 402 if (s35390a->client[i]) 403 i2c_unregister_device(s35390a->client[i]); 404 405exit: 406 return err; 407} 408 409static int s35390a_remove(struct i2c_client *client) 410{ 411 unsigned int i; 412 struct s35390a *s35390a = i2c_get_clientdata(client); 413 414 for (i = 1; i < 8; ++i) 415 if (s35390a->client[i]) 416 i2c_unregister_device(s35390a->client[i]); 417 418 return 0; 419} 420 421static struct i2c_driver s35390a_driver = { 422 .driver = { 423 .name = "rtc-s35390a", 424 }, 425 .probe = s35390a_probe, 426 .remove = s35390a_remove, 427 .id_table = s35390a_id, 428}; 429 430module_i2c_driver(s35390a_driver); 431 432MODULE_AUTHOR("Byron Bradley <byron.bbradley@gmail.com>"); 433MODULE_DESCRIPTION("S35390A RTC driver"); 434MODULE_LICENSE("GPL"); 435