0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/bcd.h>
0013 #include <linux/kernel.h>
0014 #include <linux/gfp.h>
0015 #include <linux/delay.h>
0016 #include <linux/jiffies.h>
0017 #include <linux/rtc.h>
0018 #include <linux/of.h>
0019 #include <linux/of_device.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/io.h>
0022 #include <linux/module.h>
0023
0024 #define RTC_SIZE 8
0025
0026 #define RTC_CONTROL 0
0027 #define RTC_CENTURY 0
0028 #define RTC_SECONDS 1
0029 #define RTC_MINUTES 2
0030 #define RTC_HOURS 3
0031 #define RTC_DAY 4
0032 #define RTC_DATE 5
0033 #define RTC_MONTH 6
0034 #define RTC_YEAR 7
0035
0036 #define RTC_CENTURY_MASK 0x3f
0037 #define RTC_SECONDS_MASK 0x7f
0038 #define RTC_DAY_MASK 0x07
0039
0040
0041 #define RTC_WRITE 0x80
0042 #define RTC_READ 0x40
0043
0044
0045 #define RTC_STOP 0x80
0046
0047
0048 #define RTC_BATT_FLAG 0x80
0049
0050 struct rtc_plat_data {
0051 void __iomem *ioaddr_nvram;
0052 void __iomem *ioaddr_rtc;
0053 unsigned long last_jiffies;
0054 };
0055
0056 static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
0057 {
0058 struct rtc_plat_data *pdata = dev_get_drvdata(dev);
0059 void __iomem *ioaddr = pdata->ioaddr_rtc;
0060 u8 century;
0061
0062 century = bin2bcd((tm->tm_year + 1900) / 100);
0063
0064 writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
0065
0066 writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
0067 writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
0068 writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
0069 writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
0070 writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
0071 writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
0072 writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
0073
0074
0075 writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
0076 writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
0077 return 0;
0078 }
0079
0080 static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
0081 {
0082 struct rtc_plat_data *pdata = dev_get_drvdata(dev);
0083 void __iomem *ioaddr = pdata->ioaddr_rtc;
0084 unsigned int year, month, day, hour, minute, second, week;
0085 unsigned int century;
0086
0087
0088 if (pdata->last_jiffies == jiffies)
0089 msleep(1);
0090 pdata->last_jiffies = jiffies;
0091 writeb(RTC_READ, ioaddr + RTC_CONTROL);
0092 second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
0093 minute = readb(ioaddr + RTC_MINUTES);
0094 hour = readb(ioaddr + RTC_HOURS);
0095 day = readb(ioaddr + RTC_DATE);
0096 week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
0097 month = readb(ioaddr + RTC_MONTH);
0098 year = readb(ioaddr + RTC_YEAR);
0099 century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
0100 writeb(0, ioaddr + RTC_CONTROL);
0101 tm->tm_sec = bcd2bin(second);
0102 tm->tm_min = bcd2bin(minute);
0103 tm->tm_hour = bcd2bin(hour);
0104 tm->tm_mday = bcd2bin(day);
0105 tm->tm_wday = bcd2bin(week);
0106 tm->tm_mon = bcd2bin(month) - 1;
0107
0108 tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
0109
0110 return 0;
0111 }
0112
0113 static const struct rtc_class_ops ds1742_rtc_ops = {
0114 .read_time = ds1742_rtc_read_time,
0115 .set_time = ds1742_rtc_set_time,
0116 };
0117
0118 static int ds1742_nvram_read(void *priv, unsigned int pos, void *val,
0119 size_t bytes)
0120 {
0121 struct rtc_plat_data *pdata = priv;
0122 void __iomem *ioaddr = pdata->ioaddr_nvram;
0123 u8 *buf = val;
0124
0125 for (; bytes; bytes--)
0126 *buf++ = readb(ioaddr + pos++);
0127 return 0;
0128 }
0129
0130 static int ds1742_nvram_write(void *priv, unsigned int pos, void *val,
0131 size_t bytes)
0132 {
0133 struct rtc_plat_data *pdata = priv;
0134 void __iomem *ioaddr = pdata->ioaddr_nvram;
0135 u8 *buf = val;
0136
0137 for (; bytes; bytes--)
0138 writeb(*buf++, ioaddr + pos++);
0139 return 0;
0140 }
0141
0142 static int ds1742_rtc_probe(struct platform_device *pdev)
0143 {
0144 struct rtc_device *rtc;
0145 struct resource *res;
0146 unsigned int cen, sec;
0147 struct rtc_plat_data *pdata;
0148 void __iomem *ioaddr;
0149 int ret = 0;
0150 struct nvmem_config nvmem_cfg = {
0151 .name = "ds1742_nvram",
0152 .reg_read = ds1742_nvram_read,
0153 .reg_write = ds1742_nvram_write,
0154 };
0155
0156
0157 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
0158 if (!pdata)
0159 return -ENOMEM;
0160
0161 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0162 ioaddr = devm_ioremap_resource(&pdev->dev, res);
0163 if (IS_ERR(ioaddr))
0164 return PTR_ERR(ioaddr);
0165
0166 pdata->ioaddr_nvram = ioaddr;
0167 pdata->ioaddr_rtc = ioaddr + resource_size(res) - RTC_SIZE;
0168
0169 nvmem_cfg.size = resource_size(res) - RTC_SIZE;
0170 nvmem_cfg.priv = pdata;
0171
0172
0173 ioaddr = pdata->ioaddr_rtc;
0174 sec = readb(ioaddr + RTC_SECONDS);
0175 if (sec & RTC_STOP) {
0176 sec &= RTC_SECONDS_MASK;
0177 cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
0178 writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
0179 writeb(sec, ioaddr + RTC_SECONDS);
0180 writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
0181 }
0182 if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG))
0183 dev_warn(&pdev->dev, "voltage-low detected.\n");
0184
0185 pdata->last_jiffies = jiffies;
0186 platform_set_drvdata(pdev, pdata);
0187
0188 rtc = devm_rtc_allocate_device(&pdev->dev);
0189 if (IS_ERR(rtc))
0190 return PTR_ERR(rtc);
0191
0192 rtc->ops = &ds1742_rtc_ops;
0193
0194 ret = devm_rtc_register_device(rtc);
0195 if (ret)
0196 return ret;
0197
0198 devm_rtc_nvmem_register(rtc, &nvmem_cfg);
0199
0200 return 0;
0201 }
0202
0203 static const struct of_device_id __maybe_unused ds1742_rtc_of_match[] = {
0204 { .compatible = "maxim,ds1742", },
0205 { }
0206 };
0207 MODULE_DEVICE_TABLE(of, ds1742_rtc_of_match);
0208
0209 static struct platform_driver ds1742_rtc_driver = {
0210 .probe = ds1742_rtc_probe,
0211 .driver = {
0212 .name = "rtc-ds1742",
0213 .of_match_table = of_match_ptr(ds1742_rtc_of_match),
0214 },
0215 };
0216
0217 module_platform_driver(ds1742_rtc_driver);
0218
0219 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
0220 MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
0221 MODULE_LICENSE("GPL");
0222 MODULE_ALIAS("platform:rtc-ds1742");