Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* rtc-ds1347.c
0003  *
0004  * Driver for Dallas Semiconductor DS1347 Low Current, SPI Compatible
0005  * Real Time Clock
0006  *
0007  * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>
0008  */
0009 
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 #include <linux/device.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/rtc.h>
0015 #include <linux/spi/spi.h>
0016 #include <linux/bcd.h>
0017 #include <linux/regmap.h>
0018 
0019 /* Registers in ds1347 rtc */
0020 
0021 #define DS1347_SECONDS_REG  0x01
0022 #define DS1347_MINUTES_REG  0x03
0023 #define DS1347_HOURS_REG    0x05
0024 #define DS1347_DATE_REG     0x07
0025 #define DS1347_MONTH_REG    0x09
0026 #define DS1347_DAY_REG      0x0B
0027 #define DS1347_YEAR_REG     0x0D
0028 #define DS1347_CONTROL_REG  0x0F
0029 #define DS1347_CENTURY_REG  0x13
0030 #define DS1347_STATUS_REG   0x17
0031 #define DS1347_CLOCK_BURST  0x3F
0032 
0033 #define DS1347_WP_BIT       BIT(7)
0034 
0035 #define DS1347_NEOSC_BIT    BIT(7)
0036 #define DS1347_OSF_BIT      BIT(2)
0037 
0038 static const struct regmap_range ds1347_ranges[] = {
0039     {
0040         .range_min = DS1347_SECONDS_REG,
0041         .range_max = DS1347_STATUS_REG,
0042     },
0043 };
0044 
0045 static const struct regmap_access_table ds1347_access_table = {
0046     .yes_ranges = ds1347_ranges,
0047     .n_yes_ranges = ARRAY_SIZE(ds1347_ranges),
0048 };
0049 
0050 static int ds1347_read_time(struct device *dev, struct rtc_time *dt)
0051 {
0052     struct regmap *map = dev_get_drvdata(dev);
0053     unsigned int status, century, secs;
0054     unsigned char buf[8];
0055     int err;
0056 
0057     err = regmap_read(map, DS1347_STATUS_REG, &status);
0058     if (err)
0059         return err;
0060 
0061     if (status & DS1347_OSF_BIT)
0062         return -EINVAL;
0063 
0064     do {
0065         err = regmap_bulk_read(map, DS1347_CLOCK_BURST, buf, 8);
0066         if (err)
0067             return err;
0068 
0069         err = regmap_read(map, DS1347_CENTURY_REG, &century);
0070         if (err)
0071             return err;
0072 
0073         err = regmap_read(map, DS1347_SECONDS_REG, &secs);
0074         if (err)
0075             return err;
0076     } while (buf[0] != secs);
0077 
0078     dt->tm_sec = bcd2bin(buf[0]);
0079     dt->tm_min = bcd2bin(buf[1] & 0x7f);
0080     dt->tm_hour = bcd2bin(buf[2] & 0x3F);
0081     dt->tm_mday = bcd2bin(buf[3]);
0082     dt->tm_mon = bcd2bin(buf[4]) - 1;
0083     dt->tm_wday = bcd2bin(buf[5]) - 1;
0084     dt->tm_year = (bcd2bin(century) * 100) + bcd2bin(buf[6]) - 1900;
0085 
0086     return 0;
0087 }
0088 
0089 static int ds1347_set_time(struct device *dev, struct rtc_time *dt)
0090 {
0091     struct regmap *map = dev_get_drvdata(dev);
0092     unsigned int century;
0093     unsigned char buf[8];
0094     int err;
0095 
0096     err = regmap_update_bits(map, DS1347_STATUS_REG,
0097                  DS1347_NEOSC_BIT, DS1347_NEOSC_BIT);
0098     if (err)
0099         return err;
0100 
0101     buf[0] = bin2bcd(dt->tm_sec);
0102     buf[1] = bin2bcd(dt->tm_min);
0103     buf[2] = (bin2bcd(dt->tm_hour) & 0x3F);
0104     buf[3] = bin2bcd(dt->tm_mday);
0105     buf[4] = bin2bcd(dt->tm_mon + 1);
0106     buf[5] = bin2bcd(dt->tm_wday + 1);
0107     buf[6] = bin2bcd(dt->tm_year % 100);
0108     buf[7] = bin2bcd(0x00);
0109 
0110     err = regmap_bulk_write(map, DS1347_CLOCK_BURST, buf, 8);
0111     if (err)
0112         return err;
0113 
0114     century = (dt->tm_year / 100) + 19;
0115     err = regmap_write(map, DS1347_CENTURY_REG, century);
0116     if (err)
0117         return err;
0118 
0119     return regmap_update_bits(map, DS1347_STATUS_REG,
0120                   DS1347_NEOSC_BIT | DS1347_OSF_BIT, 0);
0121 }
0122 
0123 static const struct rtc_class_ops ds1347_rtc_ops = {
0124     .read_time = ds1347_read_time,
0125     .set_time = ds1347_set_time,
0126 };
0127 
0128 static int ds1347_probe(struct spi_device *spi)
0129 {
0130     struct rtc_device *rtc;
0131     struct regmap_config config;
0132     struct regmap *map;
0133     int err;
0134 
0135     memset(&config, 0, sizeof(config));
0136     config.reg_bits = 8;
0137     config.val_bits = 8;
0138     config.read_flag_mask = 0x80;
0139     config.max_register = 0x3F;
0140     config.wr_table = &ds1347_access_table;
0141 
0142     /* spi setup with ds1347 in mode 3 and bits per word as 8 */
0143     spi->mode = SPI_MODE_3;
0144     spi->bits_per_word = 8;
0145     spi_setup(spi);
0146 
0147     map = devm_regmap_init_spi(spi, &config);
0148 
0149     if (IS_ERR(map)) {
0150         dev_err(&spi->dev, "ds1347 regmap init spi failed\n");
0151         return PTR_ERR(map);
0152     }
0153 
0154     spi_set_drvdata(spi, map);
0155 
0156     /* Disable the write protect of rtc */
0157     err = regmap_update_bits(map, DS1347_CONTROL_REG, DS1347_WP_BIT, 0);
0158     if (err)
0159         return err;
0160 
0161     rtc = devm_rtc_allocate_device(&spi->dev);
0162     if (IS_ERR(rtc))
0163         return PTR_ERR(rtc);
0164 
0165     rtc->ops = &ds1347_rtc_ops;
0166     rtc->range_min = RTC_TIMESTAMP_BEGIN_0000;
0167     rtc->range_max = RTC_TIMESTAMP_END_9999;
0168 
0169     return devm_rtc_register_device(rtc);
0170 }
0171 
0172 static struct spi_driver ds1347_driver = {
0173     .driver = {
0174         .name = "ds1347",
0175     },
0176     .probe = ds1347_probe,
0177 };
0178 
0179 module_spi_driver(ds1347_driver);
0180 
0181 MODULE_DESCRIPTION("DS1347 SPI RTC DRIVER");
0182 MODULE_AUTHOR("Raghavendra C Ganiga <ravi23ganiga@gmail.com>");
0183 MODULE_LICENSE("GPL v2");