1 // SPDX-License-Identifier: GPL-2.0-only
3 * ST M48T86 / Dallas DS12887 RTC driver
4 * Copyright (c) 2006 Tower Technologies
6 * Author: Alessandro Zummo <a.zummo@towertech.it>
8 * This drivers only supports the clock running in BCD and 24H mode.
9 * If it will be ever adapted to binary and 12H mode, care must be taken
10 * to not introduce bugs.
13 #include <linux/module.h>
14 #include <linux/rtc.h>
15 #include <linux/platform_device.h>
16 #include <linux/bcd.h>
19 #define M48T86_SEC 0x00
20 #define M48T86_SECALRM 0x01
21 #define M48T86_MIN 0x02
22 #define M48T86_MINALRM 0x03
23 #define M48T86_HOUR 0x04
24 #define M48T86_HOURALRM 0x05
25 #define M48T86_DOW 0x06 /* 1 = sunday */
26 #define M48T86_DOM 0x07
27 #define M48T86_MONTH 0x08 /* 1 - 12 */
28 #define M48T86_YEAR 0x09 /* 0 - 99 */
31 #define M48T86_B_SET BIT(7)
32 #define M48T86_B_DM BIT(2)
33 #define M48T86_B_H24 BIT(1)
36 #define M48T86_D_VRT BIT(7)
37 #define M48T86_NVRAM(x) (0x0e + (x))
38 #define M48T86_NVRAM_LEN 114
40 struct m48t86_rtc_info
{
41 void __iomem
*index_reg
;
42 void __iomem
*data_reg
;
43 struct rtc_device
*rtc
;
46 static unsigned char m48t86_readb(struct device
*dev
, unsigned long addr
)
48 struct m48t86_rtc_info
*info
= dev_get_drvdata(dev
);
51 writeb(addr
, info
->index_reg
);
52 value
= readb(info
->data_reg
);
57 static void m48t86_writeb(struct device
*dev
,
58 unsigned char value
, unsigned long addr
)
60 struct m48t86_rtc_info
*info
= dev_get_drvdata(dev
);
62 writeb(addr
, info
->index_reg
);
63 writeb(value
, info
->data_reg
);
66 static int m48t86_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
70 reg
= m48t86_readb(dev
, M48T86_B
);
72 if (reg
& M48T86_B_DM
) {
73 /* data (binary) mode */
74 tm
->tm_sec
= m48t86_readb(dev
, M48T86_SEC
);
75 tm
->tm_min
= m48t86_readb(dev
, M48T86_MIN
);
76 tm
->tm_hour
= m48t86_readb(dev
, M48T86_HOUR
) & 0x3f;
77 tm
->tm_mday
= m48t86_readb(dev
, M48T86_DOM
);
79 tm
->tm_mon
= m48t86_readb(dev
, M48T86_MONTH
) - 1;
80 tm
->tm_year
= m48t86_readb(dev
, M48T86_YEAR
) + 100;
81 tm
->tm_wday
= m48t86_readb(dev
, M48T86_DOW
);
84 tm
->tm_sec
= bcd2bin(m48t86_readb(dev
, M48T86_SEC
));
85 tm
->tm_min
= bcd2bin(m48t86_readb(dev
, M48T86_MIN
));
86 tm
->tm_hour
= bcd2bin(m48t86_readb(dev
, M48T86_HOUR
) &
88 tm
->tm_mday
= bcd2bin(m48t86_readb(dev
, M48T86_DOM
));
90 tm
->tm_mon
= bcd2bin(m48t86_readb(dev
, M48T86_MONTH
)) - 1;
91 tm
->tm_year
= bcd2bin(m48t86_readb(dev
, M48T86_YEAR
)) + 100;
92 tm
->tm_wday
= bcd2bin(m48t86_readb(dev
, M48T86_DOW
));
95 /* correct the hour if the clock is in 12h mode */
96 if (!(reg
& M48T86_B_H24
))
97 if (m48t86_readb(dev
, M48T86_HOUR
) & 0x80)
103 static int m48t86_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
107 reg
= m48t86_readb(dev
, M48T86_B
);
109 /* update flag and 24h mode */
110 reg
|= M48T86_B_SET
| M48T86_B_H24
;
111 m48t86_writeb(dev
, reg
, M48T86_B
);
113 if (reg
& M48T86_B_DM
) {
114 /* data (binary) mode */
115 m48t86_writeb(dev
, tm
->tm_sec
, M48T86_SEC
);
116 m48t86_writeb(dev
, tm
->tm_min
, M48T86_MIN
);
117 m48t86_writeb(dev
, tm
->tm_hour
, M48T86_HOUR
);
118 m48t86_writeb(dev
, tm
->tm_mday
, M48T86_DOM
);
119 m48t86_writeb(dev
, tm
->tm_mon
+ 1, M48T86_MONTH
);
120 m48t86_writeb(dev
, tm
->tm_year
% 100, M48T86_YEAR
);
121 m48t86_writeb(dev
, tm
->tm_wday
, M48T86_DOW
);
124 m48t86_writeb(dev
, bin2bcd(tm
->tm_sec
), M48T86_SEC
);
125 m48t86_writeb(dev
, bin2bcd(tm
->tm_min
), M48T86_MIN
);
126 m48t86_writeb(dev
, bin2bcd(tm
->tm_hour
), M48T86_HOUR
);
127 m48t86_writeb(dev
, bin2bcd(tm
->tm_mday
), M48T86_DOM
);
128 m48t86_writeb(dev
, bin2bcd(tm
->tm_mon
+ 1), M48T86_MONTH
);
129 m48t86_writeb(dev
, bin2bcd(tm
->tm_year
% 100), M48T86_YEAR
);
130 m48t86_writeb(dev
, bin2bcd(tm
->tm_wday
), M48T86_DOW
);
134 reg
&= ~M48T86_B_SET
;
135 m48t86_writeb(dev
, reg
, M48T86_B
);
140 static int m48t86_rtc_proc(struct device
*dev
, struct seq_file
*seq
)
144 reg
= m48t86_readb(dev
, M48T86_B
);
146 seq_printf(seq
, "mode\t\t: %s\n",
147 (reg
& M48T86_B_DM
) ? "binary" : "bcd");
149 reg
= m48t86_readb(dev
, M48T86_D
);
151 seq_printf(seq
, "battery\t\t: %s\n",
152 (reg
& M48T86_D_VRT
) ? "ok" : "exhausted");
157 static const struct rtc_class_ops m48t86_rtc_ops
= {
158 .read_time
= m48t86_rtc_read_time
,
159 .set_time
= m48t86_rtc_set_time
,
160 .proc
= m48t86_rtc_proc
,
163 static int m48t86_nvram_read(void *priv
, unsigned int off
, void *buf
,
166 struct device
*dev
= priv
;
169 for (i
= 0; i
< count
; i
++)
170 ((u8
*)buf
)[i
] = m48t86_readb(dev
, M48T86_NVRAM(off
+ i
));
175 static int m48t86_nvram_write(void *priv
, unsigned int off
, void *buf
,
178 struct device
*dev
= priv
;
181 for (i
= 0; i
< count
; i
++)
182 m48t86_writeb(dev
, ((u8
*)buf
)[i
], M48T86_NVRAM(off
+ i
));
188 * The RTC is an optional feature at purchase time on some Technologic Systems
189 * boards. Verify that it actually exists by checking if the last two bytes
190 * of the NVRAM can be changed.
192 * This is based on the method used in their rtc7800.c example.
194 static bool m48t86_verify_chip(struct platform_device
*pdev
)
196 unsigned int offset0
= M48T86_NVRAM(M48T86_NVRAM_LEN
- 2);
197 unsigned int offset1
= M48T86_NVRAM(M48T86_NVRAM_LEN
- 1);
198 unsigned char tmp0
, tmp1
;
200 tmp0
= m48t86_readb(&pdev
->dev
, offset0
);
201 tmp1
= m48t86_readb(&pdev
->dev
, offset1
);
203 m48t86_writeb(&pdev
->dev
, 0x00, offset0
);
204 m48t86_writeb(&pdev
->dev
, 0x55, offset1
);
205 if (m48t86_readb(&pdev
->dev
, offset1
) == 0x55) {
206 m48t86_writeb(&pdev
->dev
, 0xaa, offset1
);
207 if (m48t86_readb(&pdev
->dev
, offset1
) == 0xaa &&
208 m48t86_readb(&pdev
->dev
, offset0
) == 0x00) {
209 m48t86_writeb(&pdev
->dev
, tmp0
, offset0
);
210 m48t86_writeb(&pdev
->dev
, tmp1
, offset1
);
218 static int m48t86_rtc_probe(struct platform_device
*pdev
)
220 struct m48t86_rtc_info
*info
;
223 struct nvmem_config m48t86_nvmem_cfg
= {
224 .name
= "m48t86_nvram",
227 .size
= M48T86_NVRAM_LEN
,
228 .reg_read
= m48t86_nvram_read
,
229 .reg_write
= m48t86_nvram_write
,
233 info
= devm_kzalloc(&pdev
->dev
, sizeof(*info
), GFP_KERNEL
);
237 info
->index_reg
= devm_platform_ioremap_resource(pdev
, 0);
238 if (IS_ERR(info
->index_reg
))
239 return PTR_ERR(info
->index_reg
);
241 info
->data_reg
= devm_platform_ioremap_resource(pdev
, 1);
242 if (IS_ERR(info
->data_reg
))
243 return PTR_ERR(info
->data_reg
);
245 dev_set_drvdata(&pdev
->dev
, info
);
247 if (!m48t86_verify_chip(pdev
)) {
248 dev_info(&pdev
->dev
, "RTC not present\n");
252 info
->rtc
= devm_rtc_allocate_device(&pdev
->dev
);
253 if (IS_ERR(info
->rtc
))
254 return PTR_ERR(info
->rtc
);
256 info
->rtc
->ops
= &m48t86_rtc_ops
;
257 info
->rtc
->nvram_old_abi
= true;
259 err
= rtc_register_device(info
->rtc
);
263 rtc_nvmem_register(info
->rtc
, &m48t86_nvmem_cfg
);
265 /* read battery status */
266 reg
= m48t86_readb(&pdev
->dev
, M48T86_D
);
267 dev_info(&pdev
->dev
, "battery %s\n",
268 (reg
& M48T86_D_VRT
) ? "ok" : "exhausted");
273 static struct platform_driver m48t86_rtc_platform_driver
= {
275 .name
= "rtc-m48t86",
277 .probe
= m48t86_rtc_probe
,
280 module_platform_driver(m48t86_rtc_platform_driver
);
282 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
283 MODULE_DESCRIPTION("M48T86 RTC driver");
284 MODULE_LICENSE("GPL");
285 MODULE_ALIAS("platform:rtc-m48t86");