2 * Real Time Clock driver for Conexant Digicolor
4 * Copyright (C) 2015 Paradox Innovation Ltd.
6 * Author: Baruch Siach <baruch@tkos.co.il>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
15 #include <linux/iopoll.h>
16 #include <linux/delay.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/rtc.h>
22 #define DC_RTC_CONTROL 0x0
23 #define DC_RTC_TIME 0x8
24 #define DC_RTC_REFERENCE 0xc
25 #define DC_RTC_ALARM 0x10
26 #define DC_RTC_INTFLAG_CLEAR 0x14
27 #define DC_RTC_INTENABLE 0x16
29 #define DC_RTC_CMD_MASK 0xf
30 #define DC_RTC_GO_BUSY BIT(7)
37 #define CMD_DELAY_US (10*1000)
38 #define CMD_TIMEOUT_US (500*CMD_DELAY_US)
41 struct rtc_device
*rtc_dev
;
45 static int dc_rtc_cmds(struct dc_rtc
*rtc
, const u8
*cmds
, int len
)
50 for (i
= 0; i
< len
; i
++) {
51 writeb_relaxed((cmds
[i
] & DC_RTC_CMD_MASK
) | DC_RTC_GO_BUSY
,
52 rtc
->regs
+ DC_RTC_CONTROL
);
53 ret
= readb_relaxed_poll_timeout(
54 rtc
->regs
+ DC_RTC_CONTROL
, val
,
55 !(val
& DC_RTC_GO_BUSY
), CMD_DELAY_US
, CMD_TIMEOUT_US
);
63 static int dc_rtc_read(struct dc_rtc
*rtc
, unsigned long *val
)
65 static const u8 read_cmds
[] = {CMD_READ
, CMD_NOP
};
66 u32 reference
, time1
, time2
;
69 ret
= dc_rtc_cmds(rtc
, read_cmds
, ARRAY_SIZE(read_cmds
));
73 reference
= readl_relaxed(rtc
->regs
+ DC_RTC_REFERENCE
);
74 time1
= readl_relaxed(rtc
->regs
+ DC_RTC_TIME
);
75 /* Read twice to ensure consistency */
77 time2
= readl_relaxed(rtc
->regs
+ DC_RTC_TIME
);
83 *val
= reference
+ time1
;
87 static int dc_rtc_write(struct dc_rtc
*rtc
, u32 val
)
89 static const u8 write_cmds
[] = {CMD_WRITE
, CMD_NOP
, CMD_RESET
, CMD_NOP
};
91 writel_relaxed(val
, rtc
->regs
+ DC_RTC_REFERENCE
);
92 return dc_rtc_cmds(rtc
, write_cmds
, ARRAY_SIZE(write_cmds
));
95 static int dc_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
97 struct dc_rtc
*rtc
= dev_get_drvdata(dev
);
101 ret
= dc_rtc_read(rtc
, &now
);
104 rtc_time64_to_tm(now
, tm
);
109 static int dc_rtc_set_mmss(struct device
*dev
, unsigned long secs
)
111 struct dc_rtc
*rtc
= dev_get_drvdata(dev
);
113 return dc_rtc_write(rtc
, secs
);
116 static int dc_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alarm
)
118 struct dc_rtc
*rtc
= dev_get_drvdata(dev
);
119 u32 alarm_reg
, reference
;
123 alarm_reg
= readl_relaxed(rtc
->regs
+ DC_RTC_ALARM
);
124 reference
= readl_relaxed(rtc
->regs
+ DC_RTC_REFERENCE
);
125 rtc_time64_to_tm(reference
+ alarm_reg
, &alarm
->time
);
127 ret
= dc_rtc_read(rtc
, &now
);
131 alarm
->pending
= alarm_reg
+ reference
> now
;
132 alarm
->enabled
= readl_relaxed(rtc
->regs
+ DC_RTC_INTENABLE
);
137 static int dc_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alarm
)
139 struct dc_rtc
*rtc
= dev_get_drvdata(dev
);
143 alarm_time
= rtc_tm_to_time64(&alarm
->time
);
145 reference
= readl_relaxed(rtc
->regs
+ DC_RTC_REFERENCE
);
146 writel_relaxed(alarm_time
- reference
, rtc
->regs
+ DC_RTC_ALARM
);
148 writeb_relaxed(!!alarm
->enabled
, rtc
->regs
+ DC_RTC_INTENABLE
);
153 static int dc_rtc_alarm_irq_enable(struct device
*dev
, unsigned int enabled
)
155 struct dc_rtc
*rtc
= dev_get_drvdata(dev
);
157 writeb_relaxed(!!enabled
, rtc
->regs
+ DC_RTC_INTENABLE
);
162 static struct rtc_class_ops dc_rtc_ops
= {
163 .read_time
= dc_rtc_read_time
,
164 .set_mmss
= dc_rtc_set_mmss
,
165 .read_alarm
= dc_rtc_read_alarm
,
166 .set_alarm
= dc_rtc_set_alarm
,
167 .alarm_irq_enable
= dc_rtc_alarm_irq_enable
,
170 static irqreturn_t
dc_rtc_irq(int irq
, void *dev_id
)
172 struct dc_rtc
*rtc
= dev_id
;
174 writeb_relaxed(1, rtc
->regs
+ DC_RTC_INTFLAG_CLEAR
);
175 rtc_update_irq(rtc
->rtc_dev
, 1, RTC_AF
| RTC_IRQF
);
180 static int __init
dc_rtc_probe(struct platform_device
*pdev
)
182 struct resource
*res
;
186 rtc
= devm_kzalloc(&pdev
->dev
, sizeof(*rtc
), GFP_KERNEL
);
190 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
191 rtc
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
192 if (IS_ERR(rtc
->regs
))
193 return PTR_ERR(rtc
->regs
);
195 irq
= platform_get_irq(pdev
, 0);
198 ret
= devm_request_irq(&pdev
->dev
, irq
, dc_rtc_irq
, 0, pdev
->name
, rtc
);
202 platform_set_drvdata(pdev
, rtc
);
203 rtc
->rtc_dev
= devm_rtc_device_register(&pdev
->dev
, pdev
->name
,
204 &dc_rtc_ops
, THIS_MODULE
);
205 if (IS_ERR(rtc
->rtc_dev
))
206 return PTR_ERR(rtc
->rtc_dev
);
211 static const struct of_device_id dc_dt_ids
[] = {
212 { .compatible
= "cnxt,cx92755-rtc" },
215 MODULE_DEVICE_TABLE(of
, dc_dt_ids
);
217 static struct platform_driver dc_rtc_driver
= {
219 .name
= "digicolor_rtc",
220 .of_match_table
= of_match_ptr(dc_dt_ids
),
223 module_platform_driver_probe(dc_rtc_driver
, dc_rtc_probe
);
225 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
226 MODULE_DESCRIPTION("Conexant Digicolor Realtime Clock Driver (RTC)");
227 MODULE_LICENSE("GPL");