blob: 3e12f57ce0b7ba819f5ce1bb8edd635ee282ba4c [file] [log] [blame]
Patrick Delaunay1f99eaf2019-07-22 11:02:34 +02001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2/*
3 * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
4 */
5#include <common.h>
6#include <clk.h>
7#include <dm.h>
Simon Glass336d4612020-02-03 07:36:16 -07008#include <malloc.h>
Patrick Delaunay1f99eaf2019-07-22 11:02:34 +02009#include <rtc.h>
10#include <asm/io.h>
Simon Glass336d4612020-02-03 07:36:16 -070011#include <dm/device_compat.h>
Patrick Delaunay1f99eaf2019-07-22 11:02:34 +020012#include <linux/iopoll.h>
13
14#define STM32_RTC_TR 0x00
15#define STM32_RTC_DR 0x04
16#define STM32_RTC_ISR 0x0C
17#define STM32_RTC_PRER 0x10
18#define STM32_RTC_CR 0x18
19#define STM32_RTC_WPR 0x24
20
21/* STM32_RTC_TR bit fields */
22#define STM32_RTC_SEC_SHIFT 0
23#define STM32_RTC_SEC GENMASK(6, 0)
24#define STM32_RTC_MIN_SHIFT 8
25#define STM32_RTC_MIN GENMASK(14, 8)
26#define STM32_RTC_HOUR_SHIFT 16
27#define STM32_RTC_HOUR GENMASK(21, 16)
28
29/* STM32_RTC_DR bit fields */
30#define STM32_RTC_DATE_SHIFT 0
31#define STM32_RTC_DATE GENMASK(5, 0)
32#define STM32_RTC_MONTH_SHIFT 8
33#define STM32_RTC_MONTH GENMASK(12, 8)
34#define STM32_RTC_WDAY_SHIFT 13
35#define STM32_RTC_WDAY GENMASK(15, 13)
36#define STM32_RTC_YEAR_SHIFT 16
37#define STM32_RTC_YEAR GENMASK(23, 16)
38
39/* STM32_RTC_CR bit fields */
40#define STM32_RTC_CR_FMT BIT(6)
41
42/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
43#define STM32_RTC_ISR_INITS BIT(4)
44#define STM32_RTC_ISR_RSF BIT(5)
45#define STM32_RTC_ISR_INITF BIT(6)
46#define STM32_RTC_ISR_INIT BIT(7)
47
48/* STM32_RTC_PRER bit fields */
49#define STM32_RTC_PRER_PRED_S_SHIFT 0
50#define STM32_RTC_PRER_PRED_S GENMASK(14, 0)
51#define STM32_RTC_PRER_PRED_A_SHIFT 16
52#define STM32_RTC_PRER_PRED_A GENMASK(22, 16)
53
54/* STM32_RTC_WPR key constants */
55#define RTC_WPR_1ST_KEY 0xCA
56#define RTC_WPR_2ND_KEY 0x53
57#define RTC_WPR_WRONG_KEY 0xFF
58
59struct stm32_rtc_priv {
60 fdt_addr_t base;
61};
62
63static int stm32_rtc_get(struct udevice *dev, struct rtc_time *tm)
64{
65 struct stm32_rtc_priv *priv = dev_get_priv(dev);
66 u32 tr, dr;
67
68 tr = readl(priv->base + STM32_RTC_TR);
69 dr = readl(priv->base + STM32_RTC_DR);
70
71 tm->tm_sec = bcd2bin((tr & STM32_RTC_SEC) >> STM32_RTC_SEC_SHIFT);
72 tm->tm_min = bcd2bin((tr & STM32_RTC_MIN) >> STM32_RTC_MIN_SHIFT);
73 tm->tm_hour = bcd2bin((tr & STM32_RTC_HOUR) >> STM32_RTC_HOUR_SHIFT);
74
75 tm->tm_mday = bcd2bin((dr & STM32_RTC_DATE) >> STM32_RTC_DATE_SHIFT);
76 tm->tm_mon = bcd2bin((dr & STM32_RTC_MONTH) >> STM32_RTC_MONTH_SHIFT);
Patrick Delaunayfed51572019-07-22 14:50:21 +020077 tm->tm_year = 2000 +
78 bcd2bin((dr & STM32_RTC_YEAR) >> STM32_RTC_YEAR_SHIFT);
Patrick Delaunay1f99eaf2019-07-22 11:02:34 +020079 tm->tm_wday = bcd2bin((dr & STM32_RTC_WDAY) >> STM32_RTC_WDAY_SHIFT);
80 tm->tm_yday = 0;
81 tm->tm_isdst = 0;
82
83 dev_dbg(dev, "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
84 tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
85 tm->tm_hour, tm->tm_min, tm->tm_sec);
86
87 return 0;
88}
89
90static void stm32_rtc_unlock(struct udevice *dev)
91{
92 struct stm32_rtc_priv *priv = dev_get_priv(dev);
93
94 writel(RTC_WPR_1ST_KEY, priv->base + STM32_RTC_WPR);
95 writel(RTC_WPR_2ND_KEY, priv->base + STM32_RTC_WPR);
96}
97
98static void stm32_rtc_lock(struct udevice *dev)
99{
100 struct stm32_rtc_priv *priv = dev_get_priv(dev);
101
102 writel(RTC_WPR_WRONG_KEY, priv->base + STM32_RTC_WPR);
103}
104
105static int stm32_rtc_enter_init_mode(struct udevice *dev)
106{
107 struct stm32_rtc_priv *priv = dev_get_priv(dev);
108 u32 isr = readl(priv->base + STM32_RTC_ISR);
109
110 if (!(isr & STM32_RTC_ISR_INITF)) {
111 isr |= STM32_RTC_ISR_INIT;
112 writel(isr, priv->base + STM32_RTC_ISR);
113
114 return readl_poll_timeout(priv->base + STM32_RTC_ISR,
115 isr,
116 (isr & STM32_RTC_ISR_INITF),
117 100000);
118 }
119
120 return 0;
121}
122
123static int stm32_rtc_wait_sync(struct udevice *dev)
124{
125 struct stm32_rtc_priv *priv = dev_get_priv(dev);
126 u32 isr = readl(priv->base + STM32_RTC_ISR);
127
128 isr &= ~STM32_RTC_ISR_RSF;
129 writel(isr, priv->base + STM32_RTC_ISR);
130
131 /*
132 * Wait for RSF to be set to ensure the calendar registers are
133 * synchronised, it takes around 2 rtc_ck clock cycles
134 */
135 return readl_poll_timeout(priv->base + STM32_RTC_ISR,
136 isr, (isr & STM32_RTC_ISR_RSF),
137 100000);
138}
139
140static void stm32_rtc_exit_init_mode(struct udevice *dev)
141{
142 struct stm32_rtc_priv *priv = dev_get_priv(dev);
143 u32 isr = readl(priv->base + STM32_RTC_ISR);
144
145 isr &= ~STM32_RTC_ISR_INIT;
146 writel(isr, priv->base + STM32_RTC_ISR);
147}
148
149static int stm32_rtc_set_time(struct udevice *dev, u32 time, u32 date)
150{
151 struct stm32_rtc_priv *priv = dev_get_priv(dev);
152 int ret;
153
154 stm32_rtc_unlock(dev);
155
156 ret = stm32_rtc_enter_init_mode(dev);
157 if (ret)
158 goto lock;
159
160 writel(time, priv->base + STM32_RTC_TR);
161 writel(date, priv->base + STM32_RTC_DR);
162
163 stm32_rtc_exit_init_mode(dev);
164
165 ret = stm32_rtc_wait_sync(dev);
166
167lock:
168 stm32_rtc_lock(dev);
169 return ret;
170}
171
172static int stm32_rtc_set(struct udevice *dev, const struct rtc_time *tm)
173{
174 u32 t, d;
175
176 dev_dbg(dev, "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
177 tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
178 tm->tm_hour, tm->tm_min, tm->tm_sec);
179
Patrick Delaunayfed51572019-07-22 14:50:21 +0200180 if (tm->tm_year < 2000 || tm->tm_year > 2099)
181 return -EINVAL;
182
Patrick Delaunay1f99eaf2019-07-22 11:02:34 +0200183 /* Time in BCD format */
184 t = (bin2bcd(tm->tm_sec) << STM32_RTC_SEC_SHIFT) & STM32_RTC_SEC;
185 t |= (bin2bcd(tm->tm_min) << STM32_RTC_MIN_SHIFT) & STM32_RTC_MIN;
186 t |= (bin2bcd(tm->tm_hour) << STM32_RTC_HOUR_SHIFT) & STM32_RTC_HOUR;
187
188 /* Date in BCD format */
189 d = (bin2bcd(tm->tm_mday) << STM32_RTC_DATE_SHIFT) & STM32_RTC_DATE;
190 d |= (bin2bcd(tm->tm_mon) << STM32_RTC_MONTH_SHIFT) & STM32_RTC_MONTH;
Patrick Delaunayfed51572019-07-22 14:50:21 +0200191 d |= (bin2bcd(tm->tm_year - 2000) << STM32_RTC_YEAR_SHIFT) &
192 STM32_RTC_YEAR;
Patrick Delaunay1f99eaf2019-07-22 11:02:34 +0200193 d |= (bin2bcd(tm->tm_wday) << STM32_RTC_WDAY_SHIFT) & STM32_RTC_WDAY;
194
195 return stm32_rtc_set_time(dev, t, d);
196}
197
198static int stm32_rtc_reset(struct udevice *dev)
199{
200 dev_dbg(dev, "Reset DATE\n");
201
202 return stm32_rtc_set_time(dev, 0, 0);
203}
204
205static int stm32_rtc_init(struct udevice *dev)
206{
207 struct stm32_rtc_priv *priv = dev_get_priv(dev);
208 unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
209 unsigned int rate;
210 struct clk clk;
211 int ret;
212 u32 isr = readl(priv->base + STM32_RTC_ISR);
213
214 if (isr & STM32_RTC_ISR_INITS)
215 return 0;
216
217 ret = clk_get_by_index(dev, 1, &clk);
218 if (ret)
219 return ret;
220
221 ret = clk_enable(&clk);
222 if (ret) {
223 clk_free(&clk);
224 return ret;
225 }
226
227 rate = clk_get_rate(&clk);
228
229 /* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
230 pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
231 pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
232
233 for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
234 pred_s = (rate / (pred_a + 1)) - 1;
235
236 if (((pred_s + 1) * (pred_a + 1)) == rate)
237 break;
238 }
239
240 /*
241 * Can't find a 1Hz, so give priority to RTC power consumption
242 * by choosing the higher possible value for prediv_a
243 */
244 if (pred_s > pred_s_max || pred_a > pred_a_max) {
245 pred_a = pred_a_max;
246 pred_s = (rate / (pred_a + 1)) - 1;
247 }
248
249 stm32_rtc_unlock(dev);
250
251 ret = stm32_rtc_enter_init_mode(dev);
252 if (ret) {
253 dev_err(dev,
254 "Can't enter in init mode. Prescaler config failed.\n");
255 goto unlock;
256 }
257
258 prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
259 prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
260 writel(prer, priv->base + STM32_RTC_PRER);
261
262 /* Force 24h time format */
263 cr = readl(priv->base + STM32_RTC_CR);
264 cr &= ~STM32_RTC_CR_FMT;
265 writel(cr, priv->base + STM32_RTC_CR);
266
267 stm32_rtc_exit_init_mode(dev);
268
269 ret = stm32_rtc_wait_sync(dev);
270
271unlock:
272 stm32_rtc_lock(dev);
273
274 if (ret) {
275 clk_disable(&clk);
276 clk_free(&clk);
277 }
278
279 return ret;
280}
281
282static int stm32_rtc_probe(struct udevice *dev)
283{
284 struct stm32_rtc_priv *priv = dev_get_priv(dev);
285 struct clk clk;
286 int ret;
287
288 priv->base = dev_read_addr(dev);
289 if (priv->base == FDT_ADDR_T_NONE)
290 return -EINVAL;
291
292 ret = clk_get_by_index(dev, 0, &clk);
293 if (ret)
294 return ret;
295
296 ret = clk_enable(&clk);
297 if (ret) {
298 clk_free(&clk);
299 return ret;
300 }
301
302 ret = stm32_rtc_init(dev);
303
304 if (ret) {
305 clk_disable(&clk);
306 clk_free(&clk);
307 }
308
309 return ret;
310}
311
312static const struct rtc_ops stm32_rtc_ops = {
313 .get = stm32_rtc_get,
314 .set = stm32_rtc_set,
315 .reset = stm32_rtc_reset,
316};
317
318static const struct udevice_id stm32_rtc_ids[] = {
319 { .compatible = "st,stm32mp1-rtc" },
320 { }
321};
322
323U_BOOT_DRIVER(rtc_stm32) = {
324 .name = "rtc-stm32",
325 .id = UCLASS_RTC,
326 .probe = stm32_rtc_probe,
327 .of_match = stm32_rtc_ids,
328 .ops = &stm32_rtc_ops,
329 .priv_auto_alloc_size = sizeof(struct stm32_rtc_priv),
330};