Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ST M48T86 / Dallas DS12887 RTC driver
0004  * Copyright (c) 2006 Tower Technologies
0005  *
0006  * Author: Alessandro Zummo <a.zummo@towertech.it>
0007  *
0008  * This drivers only supports the clock running in BCD and 24H mode.
0009  * If it will be ever adapted to binary and 12H mode, care must be taken
0010  * to not introduce bugs.
0011  */
0012 
0013 #include <linux/module.h>
0014 #include <linux/rtc.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/bcd.h>
0017 #include <linux/io.h>
0018 
0019 #define M48T86_SEC      0x00
0020 #define M48T86_SECALRM      0x01
0021 #define M48T86_MIN      0x02
0022 #define M48T86_MINALRM      0x03
0023 #define M48T86_HOUR     0x04
0024 #define M48T86_HOURALRM     0x05
0025 #define M48T86_DOW      0x06 /* 1 = sunday */
0026 #define M48T86_DOM      0x07
0027 #define M48T86_MONTH        0x08 /* 1 - 12 */
0028 #define M48T86_YEAR     0x09 /* 0 - 99 */
0029 #define M48T86_A        0x0a
0030 #define M48T86_B        0x0b
0031 #define M48T86_B_SET        BIT(7)
0032 #define M48T86_B_DM     BIT(2)
0033 #define M48T86_B_H24        BIT(1)
0034 #define M48T86_C        0x0c
0035 #define M48T86_D        0x0d
0036 #define M48T86_D_VRT        BIT(7)
0037 #define M48T86_NVRAM(x)     (0x0e + (x))
0038 #define M48T86_NVRAM_LEN    114
0039 
0040 struct m48t86_rtc_info {
0041     void __iomem *index_reg;
0042     void __iomem *data_reg;
0043     struct rtc_device *rtc;
0044 };
0045 
0046 static unsigned char m48t86_readb(struct device *dev, unsigned long addr)
0047 {
0048     struct m48t86_rtc_info *info = dev_get_drvdata(dev);
0049     unsigned char value;
0050 
0051     writeb(addr, info->index_reg);
0052     value = readb(info->data_reg);
0053 
0054     return value;
0055 }
0056 
0057 static void m48t86_writeb(struct device *dev,
0058               unsigned char value, unsigned long addr)
0059 {
0060     struct m48t86_rtc_info *info = dev_get_drvdata(dev);
0061 
0062     writeb(addr, info->index_reg);
0063     writeb(value, info->data_reg);
0064 }
0065 
0066 static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
0067 {
0068     unsigned char reg;
0069 
0070     reg = m48t86_readb(dev, M48T86_B);
0071 
0072     if (reg & M48T86_B_DM) {
0073         /* data (binary) mode */
0074         tm->tm_sec  = m48t86_readb(dev, M48T86_SEC);
0075         tm->tm_min  = m48t86_readb(dev, M48T86_MIN);
0076         tm->tm_hour = m48t86_readb(dev, M48T86_HOUR) & 0x3f;
0077         tm->tm_mday = m48t86_readb(dev, M48T86_DOM);
0078         /* tm_mon is 0-11 */
0079         tm->tm_mon  = m48t86_readb(dev, M48T86_MONTH) - 1;
0080         tm->tm_year = m48t86_readb(dev, M48T86_YEAR) + 100;
0081         tm->tm_wday = m48t86_readb(dev, M48T86_DOW);
0082     } else {
0083         /* bcd mode */
0084         tm->tm_sec  = bcd2bin(m48t86_readb(dev, M48T86_SEC));
0085         tm->tm_min  = bcd2bin(m48t86_readb(dev, M48T86_MIN));
0086         tm->tm_hour = bcd2bin(m48t86_readb(dev, M48T86_HOUR) &
0087                       0x3f);
0088         tm->tm_mday = bcd2bin(m48t86_readb(dev, M48T86_DOM));
0089         /* tm_mon is 0-11 */
0090         tm->tm_mon  = bcd2bin(m48t86_readb(dev, M48T86_MONTH)) - 1;
0091         tm->tm_year = bcd2bin(m48t86_readb(dev, M48T86_YEAR)) + 100;
0092         tm->tm_wday = bcd2bin(m48t86_readb(dev, M48T86_DOW));
0093     }
0094 
0095     /* correct the hour if the clock is in 12h mode */
0096     if (!(reg & M48T86_B_H24))
0097         if (m48t86_readb(dev, M48T86_HOUR) & 0x80)
0098             tm->tm_hour += 12;
0099 
0100     return 0;
0101 }
0102 
0103 static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
0104 {
0105     unsigned char reg;
0106 
0107     reg = m48t86_readb(dev, M48T86_B);
0108 
0109     /* update flag and 24h mode */
0110     reg |= M48T86_B_SET | M48T86_B_H24;
0111     m48t86_writeb(dev, reg, M48T86_B);
0112 
0113     if (reg & M48T86_B_DM) {
0114         /* data (binary) mode */
0115         m48t86_writeb(dev, tm->tm_sec, M48T86_SEC);
0116         m48t86_writeb(dev, tm->tm_min, M48T86_MIN);
0117         m48t86_writeb(dev, tm->tm_hour, M48T86_HOUR);
0118         m48t86_writeb(dev, tm->tm_mday, M48T86_DOM);
0119         m48t86_writeb(dev, tm->tm_mon + 1, M48T86_MONTH);
0120         m48t86_writeb(dev, tm->tm_year % 100, M48T86_YEAR);
0121         m48t86_writeb(dev, tm->tm_wday, M48T86_DOW);
0122     } else {
0123         /* bcd mode */
0124         m48t86_writeb(dev, bin2bcd(tm->tm_sec), M48T86_SEC);
0125         m48t86_writeb(dev, bin2bcd(tm->tm_min), M48T86_MIN);
0126         m48t86_writeb(dev, bin2bcd(tm->tm_hour), M48T86_HOUR);
0127         m48t86_writeb(dev, bin2bcd(tm->tm_mday), M48T86_DOM);
0128         m48t86_writeb(dev, bin2bcd(tm->tm_mon + 1), M48T86_MONTH);
0129         m48t86_writeb(dev, bin2bcd(tm->tm_year % 100), M48T86_YEAR);
0130         m48t86_writeb(dev, bin2bcd(tm->tm_wday), M48T86_DOW);
0131     }
0132 
0133     /* update ended */
0134     reg &= ~M48T86_B_SET;
0135     m48t86_writeb(dev, reg, M48T86_B);
0136 
0137     return 0;
0138 }
0139 
0140 static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
0141 {
0142     unsigned char reg;
0143 
0144     reg = m48t86_readb(dev, M48T86_B);
0145 
0146     seq_printf(seq, "mode\t\t: %s\n",
0147            (reg & M48T86_B_DM) ? "binary" : "bcd");
0148 
0149     reg = m48t86_readb(dev, M48T86_D);
0150 
0151     seq_printf(seq, "battery\t\t: %s\n",
0152            (reg & M48T86_D_VRT) ? "ok" : "exhausted");
0153 
0154     return 0;
0155 }
0156 
0157 static const struct rtc_class_ops m48t86_rtc_ops = {
0158     .read_time  = m48t86_rtc_read_time,
0159     .set_time   = m48t86_rtc_set_time,
0160     .proc       = m48t86_rtc_proc,
0161 };
0162 
0163 static int m48t86_nvram_read(void *priv, unsigned int off, void *buf,
0164                  size_t count)
0165 {
0166     struct device *dev = priv;
0167     unsigned int i;
0168 
0169     for (i = 0; i < count; i++)
0170         ((u8 *)buf)[i] = m48t86_readb(dev, M48T86_NVRAM(off + i));
0171 
0172     return 0;
0173 }
0174 
0175 static int m48t86_nvram_write(void *priv, unsigned int off, void *buf,
0176                   size_t count)
0177 {
0178     struct device *dev = priv;
0179     unsigned int i;
0180 
0181     for (i = 0; i < count; i++)
0182         m48t86_writeb(dev, ((u8 *)buf)[i], M48T86_NVRAM(off + i));
0183 
0184     return 0;
0185 }
0186 
0187 /*
0188  * The RTC is an optional feature at purchase time on some Technologic Systems
0189  * boards. Verify that it actually exists by checking if the last two bytes
0190  * of the NVRAM can be changed.
0191  *
0192  * This is based on the method used in their rtc7800.c example.
0193  */
0194 static bool m48t86_verify_chip(struct platform_device *pdev)
0195 {
0196     unsigned int offset0 = M48T86_NVRAM(M48T86_NVRAM_LEN - 2);
0197     unsigned int offset1 = M48T86_NVRAM(M48T86_NVRAM_LEN - 1);
0198     unsigned char tmp0, tmp1;
0199 
0200     tmp0 = m48t86_readb(&pdev->dev, offset0);
0201     tmp1 = m48t86_readb(&pdev->dev, offset1);
0202 
0203     m48t86_writeb(&pdev->dev, 0x00, offset0);
0204     m48t86_writeb(&pdev->dev, 0x55, offset1);
0205     if (m48t86_readb(&pdev->dev, offset1) == 0x55) {
0206         m48t86_writeb(&pdev->dev, 0xaa, offset1);
0207         if (m48t86_readb(&pdev->dev, offset1) == 0xaa &&
0208             m48t86_readb(&pdev->dev, offset0) == 0x00) {
0209             m48t86_writeb(&pdev->dev, tmp0, offset0);
0210             m48t86_writeb(&pdev->dev, tmp1, offset1);
0211 
0212             return true;
0213         }
0214     }
0215     return false;
0216 }
0217 
0218 static int m48t86_rtc_probe(struct platform_device *pdev)
0219 {
0220     struct m48t86_rtc_info *info;
0221     unsigned char reg;
0222     int err;
0223     struct nvmem_config m48t86_nvmem_cfg = {
0224         .name = "m48t86_nvram",
0225         .word_size = 1,
0226         .stride = 1,
0227         .size = M48T86_NVRAM_LEN,
0228         .reg_read = m48t86_nvram_read,
0229         .reg_write = m48t86_nvram_write,
0230         .priv = &pdev->dev,
0231     };
0232 
0233     info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0234     if (!info)
0235         return -ENOMEM;
0236 
0237     info->index_reg = devm_platform_ioremap_resource(pdev, 0);
0238     if (IS_ERR(info->index_reg))
0239         return PTR_ERR(info->index_reg);
0240 
0241     info->data_reg = devm_platform_ioremap_resource(pdev, 1);
0242     if (IS_ERR(info->data_reg))
0243         return PTR_ERR(info->data_reg);
0244 
0245     dev_set_drvdata(&pdev->dev, info);
0246 
0247     if (!m48t86_verify_chip(pdev)) {
0248         dev_info(&pdev->dev, "RTC not present\n");
0249         return -ENODEV;
0250     }
0251 
0252     info->rtc = devm_rtc_allocate_device(&pdev->dev);
0253     if (IS_ERR(info->rtc))
0254         return PTR_ERR(info->rtc);
0255 
0256     info->rtc->ops = &m48t86_rtc_ops;
0257 
0258     err = devm_rtc_register_device(info->rtc);
0259     if (err)
0260         return err;
0261 
0262     devm_rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg);
0263 
0264     /* read battery status */
0265     reg = m48t86_readb(&pdev->dev, M48T86_D);
0266     dev_info(&pdev->dev, "battery %s\n",
0267          (reg & M48T86_D_VRT) ? "ok" : "exhausted");
0268 
0269     return 0;
0270 }
0271 
0272 static struct platform_driver m48t86_rtc_platform_driver = {
0273     .driver     = {
0274         .name   = "rtc-m48t86",
0275     },
0276     .probe      = m48t86_rtc_probe,
0277 };
0278 
0279 module_platform_driver(m48t86_rtc_platform_driver);
0280 
0281 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
0282 MODULE_DESCRIPTION("M48T86 RTC driver");
0283 MODULE_LICENSE("GPL");
0284 MODULE_ALIAS("platform:rtc-m48t86");