1
2
3
4
5
6
7
8
9
10#include <linux/delay.h>
11#include <linux/io.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/platform_device.h>
16#include <linux/rtc.h>
17
18#define RTC_STATUS 0x0
19#define RTC_STATUS_ALARM1 BIT(0)
20#define RTC_STATUS_ALARM2 BIT(1)
21#define RTC_IRQ1_CONF 0x4
22#define RTC_IRQ2_CONF 0x8
23#define RTC_IRQ_AL_EN BIT(0)
24#define RTC_IRQ_FREQ_EN BIT(1)
25#define RTC_IRQ_FREQ_1HZ BIT(2)
26#define RTC_CCR 0x18
27#define RTC_CCR_MODE BIT(15)
28#define RTC_CONF_TEST 0x1C
29#define RTC_NOMINAL_TIMING BIT(13)
30
31#define RTC_TIME 0xC
32#define RTC_ALARM1 0x10
33#define RTC_ALARM2 0x14
34
35
36#define RTC_38X_BRIDGE_TIMING_CTL 0x0
37#define RTC_38X_PERIOD_OFFS 0
38#define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS)
39#define RTC_38X_READ_DELAY_OFFS 26
40#define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS)
41
42
43#define RTC_8K_BRIDGE_TIMING_CTL0 0x0
44#define RTC_8K_WRCLK_PERIOD_OFFS 0
45#define RTC_8K_WRCLK_PERIOD_MASK (0xFFFF << RTC_8K_WRCLK_PERIOD_OFFS)
46#define RTC_8K_WRCLK_SETUP_OFFS 16
47#define RTC_8K_WRCLK_SETUP_MASK (0xFFFF << RTC_8K_WRCLK_SETUP_OFFS)
48#define RTC_8K_BRIDGE_TIMING_CTL1 0x4
49#define RTC_8K_READ_DELAY_OFFS 0
50#define RTC_8K_READ_DELAY_MASK (0xFFFF << RTC_8K_READ_DELAY_OFFS)
51
52#define RTC_8K_ISR 0x10
53#define RTC_8K_IMR 0x14
54#define RTC_8K_ALARM2 BIT(0)
55
56#define SOC_RTC_INTERRUPT 0x8
57#define SOC_RTC_ALARM1 BIT(0)
58#define SOC_RTC_ALARM2 BIT(1)
59#define SOC_RTC_ALARM1_MASK BIT(2)
60#define SOC_RTC_ALARM2_MASK BIT(3)
61
62#define SAMPLE_NR 100
63
64struct value_to_freq {
65 u32 value;
66 u8 freq;
67};
68
69struct armada38x_rtc {
70 struct rtc_device *rtc_dev;
71 void __iomem *regs;
72 void __iomem *regs_soc;
73 spinlock_t lock;
74 int irq;
75 bool initialized;
76 struct value_to_freq *val_to_freq;
77 const struct armada38x_rtc_data *data;
78};
79
80#define ALARM1 0
81#define ALARM2 1
82
83#define ALARM_REG(base, alarm) ((base) + (alarm) * sizeof(u32))
84
85struct armada38x_rtc_data {
86
87 void (*update_mbus_timing)(struct armada38x_rtc *rtc);
88 u32 (*read_rtc_reg)(struct armada38x_rtc *rtc, u8 rtc_reg);
89 void (*clear_isr)(struct armada38x_rtc *rtc);
90 void (*unmask_interrupt)(struct armada38x_rtc *rtc);
91 u32 alarm;
92};
93
94
95
96
97
98
99
100
101
102
103
104static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
105{
106 writel(0, rtc->regs + RTC_STATUS);
107 writel(0, rtc->regs + RTC_STATUS);
108 writel(val, rtc->regs + offset);
109 udelay(5);
110}
111
112
113static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
114{
115 u32 reg;
116
117 reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
118 reg &= ~RTC_38X_PERIOD_MASK;
119 reg |= 0x3FF << RTC_38X_PERIOD_OFFS;
120 reg &= ~RTC_38X_READ_DELAY_MASK;
121 reg |= 0x1F << RTC_38X_READ_DELAY_OFFS;
122 writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
123}
124
125static void rtc_update_8k_mbus_timing_params(struct armada38x_rtc *rtc)
126{
127 u32 reg;
128
129 reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
130 reg &= ~RTC_8K_WRCLK_PERIOD_MASK;
131 reg |= 0x3FF << RTC_8K_WRCLK_PERIOD_OFFS;
132 reg &= ~RTC_8K_WRCLK_SETUP_MASK;
133 reg |= 0x29 << RTC_8K_WRCLK_SETUP_OFFS;
134 writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
135
136 reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
137 reg &= ~RTC_8K_READ_DELAY_MASK;
138 reg |= 0x3F << RTC_8K_READ_DELAY_OFFS;
139 writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
140}
141
142static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg)
143{
144 return readl(rtc->regs + rtc_reg);
145}
146
147static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg)
148{
149 int i, index_max = 0, max = 0;
150
151 for (i = 0; i < SAMPLE_NR; i++) {
152 rtc->val_to_freq[i].value = readl(rtc->regs + rtc_reg);
153 rtc->val_to_freq[i].freq = 0;
154 }
155
156 for (i = 0; i < SAMPLE_NR; i++) {
157 int j = 0;
158 u32 value = rtc->val_to_freq[i].value;
159
160 while (rtc->val_to_freq[j].freq) {
161 if (rtc->val_to_freq[j].value == value) {
162 rtc->val_to_freq[j].freq++;
163 break;
164 }
165 j++;
166 }
167
168 if (!rtc->val_to_freq[j].freq) {
169 rtc->val_to_freq[j].value = value;
170 rtc->val_to_freq[j].freq = 1;
171 }
172
173 if (rtc->val_to_freq[j].freq > max) {
174 index_max = j;
175 max = rtc->val_to_freq[j].freq;
176 }
177
178
179
180
181
182 if (max > SAMPLE_NR / 2)
183 break;
184 }
185
186 return rtc->val_to_freq[index_max].value;
187}
188
189static void armada38x_clear_isr(struct armada38x_rtc *rtc)
190{
191 u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
192
193 writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT);
194}
195
196static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc)
197{
198 u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
199
200 writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT);
201}
202
203static void armada8k_clear_isr(struct armada38x_rtc *rtc)
204{
205 writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR);
206}
207
208static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc)
209{
210 writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_IMR);
211}
212
213static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
214{
215 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
216 unsigned long time, flags;
217
218 spin_lock_irqsave(&rtc->lock, flags);
219 time = rtc->data->read_rtc_reg(rtc, RTC_TIME);
220 spin_unlock_irqrestore(&rtc->lock, flags);
221
222 rtc_time64_to_tm(time, tm);
223
224 return 0;
225}
226
227static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
228{
229 u32 reg;
230
231 reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST);
232
233 if (reg & 0xff) {
234 rtc_delayed_write(0, rtc, RTC_CONF_TEST);
235 msleep(500);
236 rtc_delayed_write(0, rtc, RTC_TIME);
237 rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc,
238 RTC_STATUS);
239 rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR);
240 }
241 rtc->initialized = true;
242}
243
244static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
245{
246 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
247 unsigned long time, flags;
248
249 time = rtc_tm_to_time64(tm);
250
251 if (!rtc->initialized)
252 armada38x_rtc_reset(rtc);
253
254 spin_lock_irqsave(&rtc->lock, flags);
255 rtc_delayed_write(time, rtc, RTC_TIME);
256 spin_unlock_irqrestore(&rtc->lock, flags);
257
258 return 0;
259}
260
261static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
262{
263 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
264 unsigned long time, flags;
265 u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm);
266 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
267 u32 val;
268
269 spin_lock_irqsave(&rtc->lock, flags);
270
271 time = rtc->data->read_rtc_reg(rtc, reg);
272 val = rtc->data->read_rtc_reg(rtc, reg_irq) & RTC_IRQ_AL_EN;
273
274 spin_unlock_irqrestore(&rtc->lock, flags);
275
276 alrm->enabled = val ? 1 : 0;
277 rtc_time64_to_tm(time, &alrm->time);
278
279 return 0;
280}
281
282static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
283{
284 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
285 u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm);
286 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
287 unsigned long time, flags;
288
289 time = rtc_tm_to_time64(&alrm->time);
290
291 spin_lock_irqsave(&rtc->lock, flags);
292
293 rtc_delayed_write(time, rtc, reg);
294
295 if (alrm->enabled) {
296 rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq);
297 rtc->data->unmask_interrupt(rtc);
298 }
299
300 spin_unlock_irqrestore(&rtc->lock, flags);
301
302 return 0;
303}
304
305static int armada38x_rtc_alarm_irq_enable(struct device *dev,
306 unsigned int enabled)
307{
308 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
309 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
310 unsigned long flags;
311
312 spin_lock_irqsave(&rtc->lock, flags);
313
314 if (enabled)
315 rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq);
316 else
317 rtc_delayed_write(0, rtc, reg_irq);
318
319 spin_unlock_irqrestore(&rtc->lock, flags);
320
321 return 0;
322}
323
324static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
325{
326 struct armada38x_rtc *rtc = data;
327 u32 val;
328 int event = RTC_IRQF | RTC_AF;
329 u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
330
331 dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq);
332
333 spin_lock(&rtc->lock);
334
335 rtc->data->clear_isr(rtc);
336 val = rtc->data->read_rtc_reg(rtc, reg_irq);
337
338 rtc_delayed_write(0, rtc, reg_irq);
339
340 rtc_delayed_write(1 << rtc->data->alarm, rtc, RTC_STATUS);
341
342 spin_unlock(&rtc->lock);
343
344 if (val & RTC_IRQ_FREQ_EN) {
345 if (val & RTC_IRQ_FREQ_1HZ)
346 event |= RTC_UF;
347 else
348 event |= RTC_PF;
349 }
350
351 rtc_update_irq(rtc->rtc_dev, 1, event);
352
353 return IRQ_HANDLED;
354}
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391static long armada38x_ppb_convert(long ppb)
392{
393 long div = ppb + 1000000000L;
394
395 return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L;
396}
397
398static int armada38x_rtc_read_offset(struct device *dev, long *offset)
399{
400 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
401 unsigned long ccr, flags;
402 long ppb_cor;
403
404 spin_lock_irqsave(&rtc->lock, flags);
405 ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR);
406 spin_unlock_irqrestore(&rtc->lock, flags);
407
408 ppb_cor = (ccr & RTC_CCR_MODE ? 3815 : 954) * (s8)ccr;
409
410 *offset = armada38x_ppb_convert(ppb_cor);
411
412 return 0;
413}
414
415static int armada38x_rtc_set_offset(struct device *dev, long offset)
416{
417 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
418 unsigned long ccr = 0;
419 long ppb_cor, off;
420
421
422
423
424
425
426
427 offset = clamp(offset, -484270L, 488558L);
428
429 ppb_cor = armada38x_ppb_convert(offset);
430
431
432
433
434
435 off = DIV_ROUND_CLOSEST(ppb_cor, 954);
436 if (off > 127 || off < -128) {
437 ccr = RTC_CCR_MODE;
438 off = DIV_ROUND_CLOSEST(ppb_cor, 3815);
439 }
440
441
442
443
444
445 ccr |= (off & 0x3fff) ^ 0x2000;
446 rtc_delayed_write(ccr, rtc, RTC_CCR);
447
448 return 0;
449}
450
451static const struct rtc_class_ops armada38x_rtc_ops = {
452 .read_time = armada38x_rtc_read_time,
453 .set_time = armada38x_rtc_set_time,
454 .read_alarm = armada38x_rtc_read_alarm,
455 .set_alarm = armada38x_rtc_set_alarm,
456 .alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
457 .read_offset = armada38x_rtc_read_offset,
458 .set_offset = armada38x_rtc_set_offset,
459};
460
461static const struct armada38x_rtc_data armada38x_data = {
462 .update_mbus_timing = rtc_update_38x_mbus_timing_params,
463 .read_rtc_reg = read_rtc_register_38x_wa,
464 .clear_isr = armada38x_clear_isr,
465 .unmask_interrupt = armada38x_unmask_interrupt,
466 .alarm = ALARM1,
467};
468
469static const struct armada38x_rtc_data armada8k_data = {
470 .update_mbus_timing = rtc_update_8k_mbus_timing_params,
471 .read_rtc_reg = read_rtc_register,
472 .clear_isr = armada8k_clear_isr,
473 .unmask_interrupt = armada8k_unmask_interrupt,
474 .alarm = ALARM2,
475};
476
477#ifdef CONFIG_OF
478static const struct of_device_id armada38x_rtc_of_match_table[] = {
479 {
480 .compatible = "marvell,armada-380-rtc",
481 .data = &armada38x_data,
482 },
483 {
484 .compatible = "marvell,armada-8k-rtc",
485 .data = &armada8k_data,
486 },
487 {}
488};
489MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
490#endif
491
492static __init int armada38x_rtc_probe(struct platform_device *pdev)
493{
494 struct resource *res;
495 struct armada38x_rtc *rtc;
496
497 rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc),
498 GFP_KERNEL);
499 if (!rtc)
500 return -ENOMEM;
501
502 rtc->data = of_device_get_match_data(&pdev->dev);
503
504 rtc->val_to_freq = devm_kcalloc(&pdev->dev, SAMPLE_NR,
505 sizeof(struct value_to_freq), GFP_KERNEL);
506 if (!rtc->val_to_freq)
507 return -ENOMEM;
508
509 spin_lock_init(&rtc->lock);
510
511 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
512 rtc->regs = devm_ioremap_resource(&pdev->dev, res);
513 if (IS_ERR(rtc->regs))
514 return PTR_ERR(rtc->regs);
515 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc");
516 rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res);
517 if (IS_ERR(rtc->regs_soc))
518 return PTR_ERR(rtc->regs_soc);
519
520 rtc->irq = platform_get_irq(pdev, 0);
521 if (rtc->irq < 0)
522 return rtc->irq;
523
524 rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
525 if (IS_ERR(rtc->rtc_dev))
526 return PTR_ERR(rtc->rtc_dev);
527
528 if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq,
529 0, pdev->name, rtc) < 0) {
530 dev_warn(&pdev->dev, "Interrupt not available.\n");
531 rtc->irq = -1;
532 }
533 platform_set_drvdata(pdev, rtc);
534
535 if (rtc->irq != -1)
536 device_init_wakeup(&pdev->dev, 1);
537 else
538 clear_bit(RTC_FEATURE_ALARM, rtc->rtc_dev->features);
539
540
541 rtc->data->update_mbus_timing(rtc);
542
543 rtc->rtc_dev->ops = &armada38x_rtc_ops;
544 rtc->rtc_dev->range_max = U32_MAX;
545
546 return devm_rtc_register_device(rtc->rtc_dev);
547}
548
549#ifdef CONFIG_PM_SLEEP
550static int armada38x_rtc_suspend(struct device *dev)
551{
552 if (device_may_wakeup(dev)) {
553 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
554
555 return enable_irq_wake(rtc->irq);
556 }
557
558 return 0;
559}
560
561static int armada38x_rtc_resume(struct device *dev)
562{
563 if (device_may_wakeup(dev)) {
564 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
565
566
567 rtc->data->update_mbus_timing(rtc);
568
569 return disable_irq_wake(rtc->irq);
570 }
571
572 return 0;
573}
574#endif
575
576static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
577 armada38x_rtc_suspend, armada38x_rtc_resume);
578
579static struct platform_driver armada38x_rtc_driver = {
580 .driver = {
581 .name = "armada38x-rtc",
582 .pm = &armada38x_rtc_pm_ops,
583 .of_match_table = of_match_ptr(armada38x_rtc_of_match_table),
584 },
585};
586
587module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe);
588
589MODULE_DESCRIPTION("Marvell Armada 38x RTC driver");
590MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
591MODULE_LICENSE("GPL");
592