aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorAnurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>2016-04-12 08:15:45 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-05-20 06:33:51 -0400
commit58c4ed3ba2e0c97e33affd237dc05738fa55a725 (patch)
tree652d1d2f2c20fb3e67f88d9af9aaa3722d8ef6f5 /drivers/rtc
parent9092984f1a8440ea52bf53c2d53bf8f5953a5126 (diff)
rtc: zynqmp: Write Calibration value before setting time
It is suggested to program CALIB_WRITE register with the calibration value before updating the SET_TIME_WRITE register, doing so will clear the Tick Counter and force the next second to be signaled exactly in 1 second. Signed-off-by: Anurag Kumar Vulisha <anuragku@xilinx.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-zynqmp.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index 6adb603f29bc..f87f971a72c2 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -56,6 +56,7 @@ struct xlnx_rtc_dev {
56 void __iomem *reg_base; 56 void __iomem *reg_base;
57 int alarm_irq; 57 int alarm_irq;
58 int sec_irq; 58 int sec_irq;
59 int calibval;
59}; 60};
60 61
61static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm) 62static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -68,6 +69,13 @@ static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
68 if (new_time > RTC_SEC_MAX_VAL) 69 if (new_time > RTC_SEC_MAX_VAL)
69 return -EINVAL; 70 return -EINVAL;
70 71
72 /*
73 * Writing into calibration register will clear the Tick Counter and
74 * force the next second to be signaled exactly in 1 second period
75 */
76 xrtcdev->calibval &= RTC_CALIB_MASK;
77 writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
78
71 writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR); 79 writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR);
72 80
73 return 0; 81 return 0;
@@ -121,7 +129,7 @@ static int xlnx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
121 return 0; 129 return 0;
122} 130}
123 131
124static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev, u32 calibval) 132static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)
125{ 133{
126 u32 rtc_ctrl; 134 u32 rtc_ctrl;
127 135
@@ -136,8 +144,8 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev, u32 calibval)
136 * to default value suggested as per design spec 144 * to default value suggested as per design spec
137 * to correct RTC delay in frequency over period of time. 145 * to correct RTC delay in frequency over period of time.
138 */ 146 */
139 calibval &= RTC_CALIB_MASK; 147 xrtcdev->calibval &= RTC_CALIB_MASK;
140 writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR)); 148 writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
141} 149}
142 150
143static const struct rtc_class_ops xlnx_rtc_ops = { 151static const struct rtc_class_ops xlnx_rtc_ops = {
@@ -174,7 +182,6 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
174 struct xlnx_rtc_dev *xrtcdev; 182 struct xlnx_rtc_dev *xrtcdev;
175 struct resource *res; 183 struct resource *res;
176 int ret; 184 int ret;
177 unsigned int calibvalue;
178 185
179 xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL); 186 xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL);
180 if (!xrtcdev) 187 if (!xrtcdev)
@@ -215,11 +222,11 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
215 } 222 }
216 223
217 ret = of_property_read_u32(pdev->dev.of_node, "calibration", 224 ret = of_property_read_u32(pdev->dev.of_node, "calibration",
218 &calibvalue); 225 &xrtcdev->calibval);
219 if (ret) 226 if (ret)
220 calibvalue = RTC_CALIB_DEF; 227 xrtcdev->calibval = RTC_CALIB_DEF;
221 228
222 xlnx_init_rtc(xrtcdev, calibvalue); 229 xlnx_init_rtc(xrtcdev);
223 230
224 device_init_wakeup(&pdev->dev, 1); 231 device_init_wakeup(&pdev->dev, 1);
225 232