0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
0026 #define M48T86_DOM 0x07
0027 #define M48T86_MONTH 0x08
0028 #define M48T86_YEAR 0x09
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
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
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
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
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
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
0110 reg |= M48T86_B_SET | M48T86_B_H24;
0111 m48t86_writeb(dev, reg, M48T86_B);
0112
0113 if (reg & M48T86_B_DM) {
0114
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
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
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
0189
0190
0191
0192
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
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");