0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/init.h>
0009 #include <linux/bcd.h>
0010 #include <linux/slab.h>
0011 #include <linux/rtc.h>
0012 #include <linux/workqueue.h>
0013
0014 #include <linux/spi/spi.h>
0015 #include <linux/spi/ds1305.h>
0016 #include <linux/module.h>
0017
0018
0019
0020
0021
0022
0023 #define DS1305_WRITE 0x80
0024
0025
0026
0027
0028
0029
0030
0031 #define DS1305_RTC_LEN 7
0032
0033 #define DS1305_SEC 0x00
0034 #define DS1305_MIN 0x01
0035 #define DS1305_HOUR 0x02
0036 # define DS1305_HR_12 0x40
0037 # define DS1305_HR_PM 0x20
0038 #define DS1305_WDAY 0x03
0039 #define DS1305_MDAY 0x04
0040 #define DS1305_MON 0x05
0041 #define DS1305_YEAR 0x06
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 #define DS1305_ALM_LEN 4
0057 #define DS1305_ALM_DISABLE 0x80
0058
0059 #define DS1305_ALM0(r) (0x07 + (r))
0060 #define DS1305_ALM1(r) (0x0b + (r))
0061
0062
0063
0064 #define DS1305_CONTROL_LEN 3
0065
0066 #define DS1305_CONTROL 0x0f
0067 # define DS1305_nEOSC 0x80
0068 # define DS1305_WP 0x40
0069 # define DS1305_INTCN 0x04
0070 # define DS1306_1HZ 0x04
0071 # define DS1305_AEI1 0x02
0072 # define DS1305_AEI0 0x01
0073 #define DS1305_STATUS 0x10
0074
0075 #define DS1305_TRICKLE 0x11
0076
0077
0078
0079 #define DS1305_NVRAM_LEN 96
0080
0081 #define DS1305_NVRAM 0x20
0082
0083
0084 struct ds1305 {
0085 struct spi_device *spi;
0086 struct rtc_device *rtc;
0087
0088 struct work_struct work;
0089
0090 unsigned long flags;
0091 #define FLAG_EXITING 0
0092
0093 bool hr12;
0094 u8 ctrl[DS1305_CONTROL_LEN];
0095 };
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 static unsigned bcd2hour(u8 bcd)
0106 {
0107 if (bcd & DS1305_HR_12) {
0108 unsigned hour = 0;
0109
0110 bcd &= ~DS1305_HR_12;
0111 if (bcd & DS1305_HR_PM) {
0112 hour = 12;
0113 bcd &= ~DS1305_HR_PM;
0114 }
0115 hour += bcd2bin(bcd);
0116 return hour - 1;
0117 }
0118 return bcd2bin(bcd);
0119 }
0120
0121 static u8 hour2bcd(bool hr12, int hour)
0122 {
0123 if (hr12) {
0124 hour++;
0125 if (hour <= 12)
0126 return DS1305_HR_12 | bin2bcd(hour);
0127 hour -= 12;
0128 return DS1305_HR_12 | DS1305_HR_PM | bin2bcd(hour);
0129 }
0130 return bin2bcd(hour);
0131 }
0132
0133
0134
0135
0136
0137
0138
0139 static int ds1305_alarm_irq_enable(struct device *dev, unsigned int enabled)
0140 {
0141 struct ds1305 *ds1305 = dev_get_drvdata(dev);
0142 u8 buf[2];
0143 long err = -EINVAL;
0144
0145 buf[0] = DS1305_WRITE | DS1305_CONTROL;
0146 buf[1] = ds1305->ctrl[0];
0147
0148 if (enabled) {
0149 if (ds1305->ctrl[0] & DS1305_AEI0)
0150 goto done;
0151 buf[1] |= DS1305_AEI0;
0152 } else {
0153 if (!(buf[1] & DS1305_AEI0))
0154 goto done;
0155 buf[1] &= ~DS1305_AEI0;
0156 }
0157 err = spi_write_then_read(ds1305->spi, buf, sizeof(buf), NULL, 0);
0158 if (err >= 0)
0159 ds1305->ctrl[0] = buf[1];
0160 done:
0161 return err;
0162
0163 }
0164
0165
0166
0167
0168
0169
0170 static int ds1305_get_time(struct device *dev, struct rtc_time *time)
0171 {
0172 struct ds1305 *ds1305 = dev_get_drvdata(dev);
0173 u8 addr = DS1305_SEC;
0174 u8 buf[DS1305_RTC_LEN];
0175 int status;
0176
0177
0178
0179
0180 status = spi_write_then_read(ds1305->spi, &addr, sizeof(addr),
0181 buf, sizeof(buf));
0182 if (status < 0)
0183 return status;
0184
0185 dev_vdbg(dev, "%s: %3ph, %4ph\n", "read", &buf[0], &buf[3]);
0186
0187
0188 time->tm_sec = bcd2bin(buf[DS1305_SEC]);
0189 time->tm_min = bcd2bin(buf[DS1305_MIN]);
0190 time->tm_hour = bcd2hour(buf[DS1305_HOUR]);
0191 time->tm_wday = buf[DS1305_WDAY] - 1;
0192 time->tm_mday = bcd2bin(buf[DS1305_MDAY]);
0193 time->tm_mon = bcd2bin(buf[DS1305_MON]) - 1;
0194 time->tm_year = bcd2bin(buf[DS1305_YEAR]) + 100;
0195
0196 dev_vdbg(dev, "%s secs=%d, mins=%d, "
0197 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
0198 "read", time->tm_sec, time->tm_min,
0199 time->tm_hour, time->tm_mday,
0200 time->tm_mon, time->tm_year, time->tm_wday);
0201
0202 return 0;
0203 }
0204
0205 static int ds1305_set_time(struct device *dev, struct rtc_time *time)
0206 {
0207 struct ds1305 *ds1305 = dev_get_drvdata(dev);
0208 u8 buf[1 + DS1305_RTC_LEN];
0209 u8 *bp = buf;
0210
0211 dev_vdbg(dev, "%s secs=%d, mins=%d, "
0212 "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
0213 "write", time->tm_sec, time->tm_min,
0214 time->tm_hour, time->tm_mday,
0215 time->tm_mon, time->tm_year, time->tm_wday);
0216
0217
0218 *bp++ = DS1305_WRITE | DS1305_SEC;
0219
0220 *bp++ = bin2bcd(time->tm_sec);
0221 *bp++ = bin2bcd(time->tm_min);
0222 *bp++ = hour2bcd(ds1305->hr12, time->tm_hour);
0223 *bp++ = (time->tm_wday < 7) ? (time->tm_wday + 1) : 1;
0224 *bp++ = bin2bcd(time->tm_mday);
0225 *bp++ = bin2bcd(time->tm_mon + 1);
0226 *bp++ = bin2bcd(time->tm_year - 100);
0227
0228 dev_dbg(dev, "%s: %3ph, %4ph\n", "write", &buf[1], &buf[4]);
0229
0230
0231 return spi_write_then_read(ds1305->spi, buf, sizeof(buf),
0232 NULL, 0);
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266 static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
0267 {
0268 struct ds1305 *ds1305 = dev_get_drvdata(dev);
0269 struct spi_device *spi = ds1305->spi;
0270 u8 addr;
0271 int status;
0272 u8 buf[DS1305_ALM_LEN];
0273
0274
0275
0276
0277
0278
0279 addr = DS1305_CONTROL;
0280 status = spi_write_then_read(spi, &addr, sizeof(addr),
0281 ds1305->ctrl, sizeof(ds1305->ctrl));
0282 if (status < 0)
0283 return status;
0284
0285 alm->enabled = !!(ds1305->ctrl[0] & DS1305_AEI0);
0286 alm->pending = !!(ds1305->ctrl[1] & DS1305_AEI0);
0287
0288
0289 addr = DS1305_ALM0(DS1305_SEC);
0290 status = spi_write_then_read(spi, &addr, sizeof(addr),
0291 buf, sizeof(buf));
0292 if (status < 0)
0293 return status;
0294
0295 dev_vdbg(dev, "%s: %02x %02x %02x %02x\n",
0296 "alm0 read", buf[DS1305_SEC], buf[DS1305_MIN],
0297 buf[DS1305_HOUR], buf[DS1305_WDAY]);
0298
0299 if ((DS1305_ALM_DISABLE & buf[DS1305_SEC])
0300 || (DS1305_ALM_DISABLE & buf[DS1305_MIN])
0301 || (DS1305_ALM_DISABLE & buf[DS1305_HOUR]))
0302 return -EIO;
0303
0304
0305
0306
0307
0308 alm->time.tm_sec = bcd2bin(buf[DS1305_SEC]);
0309 alm->time.tm_min = bcd2bin(buf[DS1305_MIN]);
0310 alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
0311
0312 return 0;
0313 }
0314
0315
0316
0317
0318 static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
0319 {
0320 struct ds1305 *ds1305 = dev_get_drvdata(dev);
0321 struct spi_device *spi = ds1305->spi;
0322 unsigned long now, later;
0323 struct rtc_time tm;
0324 int status;
0325 u8 buf[1 + DS1305_ALM_LEN];
0326
0327
0328 later = rtc_tm_to_time64(&alm->time);
0329
0330
0331 status = ds1305_get_time(dev, &tm);
0332 if (status < 0)
0333 return status;
0334 now = rtc_tm_to_time64(&tm);
0335
0336
0337 if (later <= now)
0338 return -EINVAL;
0339 if ((later - now) > 24 * 60 * 60)
0340 return -EDOM;
0341
0342
0343 if (ds1305->ctrl[0] & DS1305_AEI0) {
0344 ds1305->ctrl[0] &= ~DS1305_AEI0;
0345
0346 buf[0] = DS1305_WRITE | DS1305_CONTROL;
0347 buf[1] = ds1305->ctrl[0];
0348 status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
0349 if (status < 0)
0350 return status;
0351 }
0352
0353
0354 buf[0] = DS1305_WRITE | DS1305_ALM0(DS1305_SEC);
0355 buf[1 + DS1305_SEC] = bin2bcd(alm->time.tm_sec);
0356 buf[1 + DS1305_MIN] = bin2bcd(alm->time.tm_min);
0357 buf[1 + DS1305_HOUR] = hour2bcd(ds1305->hr12, alm->time.tm_hour);
0358 buf[1 + DS1305_WDAY] = DS1305_ALM_DISABLE;
0359
0360 dev_dbg(dev, "%s: %02x %02x %02x %02x\n",
0361 "alm0 write", buf[1 + DS1305_SEC], buf[1 + DS1305_MIN],
0362 buf[1 + DS1305_HOUR], buf[1 + DS1305_WDAY]);
0363
0364 status = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
0365 if (status < 0)
0366 return status;
0367
0368
0369 if (alm->enabled) {
0370 ds1305->ctrl[0] |= DS1305_AEI0;
0371
0372 buf[0] = DS1305_WRITE | DS1305_CONTROL;
0373 buf[1] = ds1305->ctrl[0];
0374 status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
0375 }
0376
0377 return status;
0378 }
0379
0380 #ifdef CONFIG_PROC_FS
0381
0382 static int ds1305_proc(struct device *dev, struct seq_file *seq)
0383 {
0384 struct ds1305 *ds1305 = dev_get_drvdata(dev);
0385 char *diodes = "no";
0386 char *resistors = "";
0387
0388
0389 if ((ds1305->ctrl[2] & 0xf0) == DS1305_TRICKLE_MAGIC) {
0390 switch (ds1305->ctrl[2] & 0x0c) {
0391 case DS1305_TRICKLE_DS2:
0392 diodes = "2 diodes, ";
0393 break;
0394 case DS1305_TRICKLE_DS1:
0395 diodes = "1 diode, ";
0396 break;
0397 default:
0398 goto done;
0399 }
0400 switch (ds1305->ctrl[2] & 0x03) {
0401 case DS1305_TRICKLE_2K:
0402 resistors = "2k Ohm";
0403 break;
0404 case DS1305_TRICKLE_4K:
0405 resistors = "4k Ohm";
0406 break;
0407 case DS1305_TRICKLE_8K:
0408 resistors = "8k Ohm";
0409 break;
0410 default:
0411 diodes = "no";
0412 break;
0413 }
0414 }
0415
0416 done:
0417 seq_printf(seq, "trickle_charge\t: %s%s\n", diodes, resistors);
0418
0419 return 0;
0420 }
0421
0422 #else
0423 #define ds1305_proc NULL
0424 #endif
0425
0426 static const struct rtc_class_ops ds1305_ops = {
0427 .read_time = ds1305_get_time,
0428 .set_time = ds1305_set_time,
0429 .read_alarm = ds1305_get_alarm,
0430 .set_alarm = ds1305_set_alarm,
0431 .proc = ds1305_proc,
0432 .alarm_irq_enable = ds1305_alarm_irq_enable,
0433 };
0434
0435 static void ds1305_work(struct work_struct *work)
0436 {
0437 struct ds1305 *ds1305 = container_of(work, struct ds1305, work);
0438 struct spi_device *spi = ds1305->spi;
0439 u8 buf[3];
0440 int status;
0441
0442
0443 rtc_lock(ds1305->rtc);
0444
0445
0446
0447
0448
0449 ds1305->ctrl[0] &= ~(DS1305_AEI1 | DS1305_AEI0);
0450 ds1305->ctrl[1] = 0;
0451
0452 buf[0] = DS1305_WRITE | DS1305_CONTROL;
0453 buf[1] = ds1305->ctrl[0];
0454 buf[2] = 0;
0455
0456 status = spi_write_then_read(spi, buf, sizeof(buf),
0457 NULL, 0);
0458 if (status < 0)
0459 dev_dbg(&spi->dev, "clear irq --> %d\n", status);
0460
0461 rtc_unlock(ds1305->rtc);
0462
0463 if (!test_bit(FLAG_EXITING, &ds1305->flags))
0464 enable_irq(spi->irq);
0465
0466 rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF);
0467 }
0468
0469
0470
0471
0472
0473
0474 static irqreturn_t ds1305_irq(int irq, void *p)
0475 {
0476 struct ds1305 *ds1305 = p;
0477
0478 disable_irq(irq);
0479 schedule_work(&ds1305->work);
0480 return IRQ_HANDLED;
0481 }
0482
0483
0484
0485
0486
0487
0488
0489 static void msg_init(struct spi_message *m, struct spi_transfer *x,
0490 u8 *addr, size_t count, char *tx, char *rx)
0491 {
0492 spi_message_init(m);
0493 memset(x, 0, 2 * sizeof(*x));
0494
0495 x->tx_buf = addr;
0496 x->len = 1;
0497 spi_message_add_tail(x, m);
0498
0499 x++;
0500
0501 x->tx_buf = tx;
0502 x->rx_buf = rx;
0503 x->len = count;
0504 spi_message_add_tail(x, m);
0505 }
0506
0507 static int ds1305_nvram_read(void *priv, unsigned int off, void *buf,
0508 size_t count)
0509 {
0510 struct ds1305 *ds1305 = priv;
0511 struct spi_device *spi = ds1305->spi;
0512 u8 addr;
0513 struct spi_message m;
0514 struct spi_transfer x[2];
0515
0516 addr = DS1305_NVRAM + off;
0517 msg_init(&m, x, &addr, count, NULL, buf);
0518
0519 return spi_sync(spi, &m);
0520 }
0521
0522 static int ds1305_nvram_write(void *priv, unsigned int off, void *buf,
0523 size_t count)
0524 {
0525 struct ds1305 *ds1305 = priv;
0526 struct spi_device *spi = ds1305->spi;
0527 u8 addr;
0528 struct spi_message m;
0529 struct spi_transfer x[2];
0530
0531 addr = (DS1305_WRITE | DS1305_NVRAM) + off;
0532 msg_init(&m, x, &addr, count, buf, NULL);
0533
0534 return spi_sync(spi, &m);
0535 }
0536
0537
0538
0539
0540
0541
0542
0543 static int ds1305_probe(struct spi_device *spi)
0544 {
0545 struct ds1305 *ds1305;
0546 int status;
0547 u8 addr, value;
0548 struct ds1305_platform_data *pdata = dev_get_platdata(&spi->dev);
0549 bool write_ctrl = false;
0550 struct nvmem_config ds1305_nvmem_cfg = {
0551 .name = "ds1305_nvram",
0552 .word_size = 1,
0553 .stride = 1,
0554 .size = DS1305_NVRAM_LEN,
0555 .reg_read = ds1305_nvram_read,
0556 .reg_write = ds1305_nvram_write,
0557 };
0558
0559
0560
0561
0562
0563 if ((spi->bits_per_word && spi->bits_per_word != 8)
0564 || (spi->max_speed_hz > 2000000)
0565 || !(spi->mode & SPI_CPHA))
0566 return -EINVAL;
0567
0568
0569 ds1305 = devm_kzalloc(&spi->dev, sizeof(*ds1305), GFP_KERNEL);
0570 if (!ds1305)
0571 return -ENOMEM;
0572 ds1305->spi = spi;
0573 spi_set_drvdata(spi, ds1305);
0574
0575
0576 addr = DS1305_CONTROL;
0577 status = spi_write_then_read(spi, &addr, sizeof(addr),
0578 ds1305->ctrl, sizeof(ds1305->ctrl));
0579 if (status < 0) {
0580 dev_dbg(&spi->dev, "can't %s, %d\n",
0581 "read", status);
0582 return status;
0583 }
0584
0585 dev_dbg(&spi->dev, "ctrl %s: %3ph\n", "read", ds1305->ctrl);
0586
0587
0588
0589
0590
0591
0592 if ((ds1305->ctrl[0] & 0x38) != 0 || (ds1305->ctrl[1] & 0xfc) != 0) {
0593 dev_dbg(&spi->dev, "RTC chip is not present\n");
0594 return -ENODEV;
0595 }
0596 if (ds1305->ctrl[2] == 0)
0597 dev_dbg(&spi->dev, "chip may not be present\n");
0598
0599
0600
0601
0602 if (ds1305->ctrl[0] & DS1305_WP) {
0603 u8 buf[2];
0604
0605 ds1305->ctrl[0] &= ~DS1305_WP;
0606
0607 buf[0] = DS1305_WRITE | DS1305_CONTROL;
0608 buf[1] = ds1305->ctrl[0];
0609 status = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
0610
0611 dev_dbg(&spi->dev, "clear WP --> %d\n", status);
0612 if (status < 0)
0613 return status;
0614 }
0615
0616
0617
0618
0619 if (ds1305->ctrl[0] & DS1305_nEOSC) {
0620 ds1305->ctrl[0] &= ~DS1305_nEOSC;
0621 write_ctrl = true;
0622 dev_warn(&spi->dev, "SET TIME!\n");
0623 }
0624
0625
0626 if (ds1305->ctrl[1]) {
0627 ds1305->ctrl[1] = 0;
0628 write_ctrl = true;
0629 }
0630
0631
0632 if (pdata) {
0633
0634 if (((ds1305->ctrl[2] & 0xf0) != DS1305_TRICKLE_MAGIC)) {
0635 ds1305->ctrl[2] = DS1305_TRICKLE_MAGIC
0636 | pdata->trickle;
0637 write_ctrl = true;
0638 }
0639
0640
0641 if (pdata->is_ds1306) {
0642 if (pdata->en_1hz) {
0643 if (!(ds1305->ctrl[0] & DS1306_1HZ)) {
0644 ds1305->ctrl[0] |= DS1306_1HZ;
0645 write_ctrl = true;
0646 }
0647 } else {
0648 if (ds1305->ctrl[0] & DS1306_1HZ) {
0649 ds1305->ctrl[0] &= ~DS1306_1HZ;
0650 write_ctrl = true;
0651 }
0652 }
0653 }
0654 }
0655
0656 if (write_ctrl) {
0657 u8 buf[4];
0658
0659 buf[0] = DS1305_WRITE | DS1305_CONTROL;
0660 buf[1] = ds1305->ctrl[0];
0661 buf[2] = ds1305->ctrl[1];
0662 buf[3] = ds1305->ctrl[2];
0663 status = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
0664 if (status < 0) {
0665 dev_dbg(&spi->dev, "can't %s, %d\n",
0666 "write", status);
0667 return status;
0668 }
0669
0670 dev_dbg(&spi->dev, "ctrl %s: %3ph\n", "write", ds1305->ctrl);
0671 }
0672
0673
0674 addr = DS1305_HOUR;
0675 status = spi_write_then_read(spi, &addr, sizeof(addr),
0676 &value, sizeof(value));
0677 if (status < 0) {
0678 dev_dbg(&spi->dev, "read HOUR --> %d\n", status);
0679 return status;
0680 }
0681
0682 ds1305->hr12 = (DS1305_HR_12 & value) != 0;
0683 if (ds1305->hr12)
0684 dev_dbg(&spi->dev, "AM/PM\n");
0685
0686
0687 ds1305->rtc = devm_rtc_allocate_device(&spi->dev);
0688 if (IS_ERR(ds1305->rtc))
0689 return PTR_ERR(ds1305->rtc);
0690
0691 ds1305->rtc->ops = &ds1305_ops;
0692 ds1305->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
0693 ds1305->rtc->range_max = RTC_TIMESTAMP_END_2099;
0694
0695 ds1305_nvmem_cfg.priv = ds1305;
0696 status = devm_rtc_register_device(ds1305->rtc);
0697 if (status)
0698 return status;
0699
0700 devm_rtc_nvmem_register(ds1305->rtc, &ds1305_nvmem_cfg);
0701
0702
0703
0704
0705
0706
0707
0708 if (spi->irq) {
0709 INIT_WORK(&ds1305->work, ds1305_work);
0710 status = devm_request_irq(&spi->dev, spi->irq, ds1305_irq,
0711 0, dev_name(&ds1305->rtc->dev), ds1305);
0712 if (status < 0) {
0713 dev_err(&spi->dev, "request_irq %d --> %d\n",
0714 spi->irq, status);
0715 } else {
0716 device_set_wakeup_capable(&spi->dev, 1);
0717 }
0718 }
0719
0720 return 0;
0721 }
0722
0723 static void ds1305_remove(struct spi_device *spi)
0724 {
0725 struct ds1305 *ds1305 = spi_get_drvdata(spi);
0726
0727
0728 if (spi->irq) {
0729 set_bit(FLAG_EXITING, &ds1305->flags);
0730 devm_free_irq(&spi->dev, spi->irq, ds1305);
0731 cancel_work_sync(&ds1305->work);
0732 }
0733 }
0734
0735 static struct spi_driver ds1305_driver = {
0736 .driver.name = "rtc-ds1305",
0737 .probe = ds1305_probe,
0738 .remove = ds1305_remove,
0739
0740 };
0741
0742 module_spi_driver(ds1305_driver);
0743
0744 MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips");
0745 MODULE_LICENSE("GPL");
0746 MODULE_ALIAS("spi:rtc-ds1305");