1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * RTC driver for the Armada 38x Marvell SoCs
4 *
5 * Copyright (C) 2021 Marek Behun <marek.behun@nic.cz>
6 *
7 * Based on Linux' driver by Gregory Clement and Marvell
8 */
9
10 #include <asm/io.h>
11 #include <dm.h>
12 #include <linux/delay.h>
13 #include <rtc.h>
14
15 #define RTC_STATUS 0x0
16 #define RTC_TIME 0xC
17 #define RTC_CONF_TEST 0x1C
18
19 /* Armada38x SoC registers */
20 #define RTC_38X_BRIDGE_TIMING_CTL 0x0
21 #define RTC_38X_PERIOD_OFFS 0
22 #define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS)
23 #define RTC_38X_READ_DELAY_OFFS 26
24 #define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS)
25
26 #define SAMPLE_NR 100
27
28 struct armada38x_rtc {
29 void __iomem *regs;
30 void __iomem *regs_soc;
31 };
32
33 /*
34 * According to Erratum RES-3124064 we have to do some configuration in MBUS.
35 * To read an RTC register we need to read it 100 times and return the most
36 * frequent value.
37 * To write an RTC register we need to write 2x zero into STATUS register,
38 * followed by the proper write. Linux adds an 5 us delay after this, so we do
39 * it here as well.
40 */
update_38x_mbus_timing_params(struct armada38x_rtc * rtc)41 static void update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
42 {
43 u32 reg;
44
45 reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
46 reg &= ~RTC_38X_PERIOD_MASK;
47 reg |= 0x3FF << RTC_38X_PERIOD_OFFS; /* Maximum value */
48 reg &= ~RTC_38X_READ_DELAY_MASK;
49 reg |= 0x1F << RTC_38X_READ_DELAY_OFFS; /* Maximum value */
50 writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
51 }
52
armada38x_rtc_write(u32 val,struct armada38x_rtc * rtc,u8 reg)53 static void armada38x_rtc_write(u32 val, struct armada38x_rtc *rtc, u8 reg)
54 {
55 writel(0, rtc->regs + RTC_STATUS);
56 writel(0, rtc->regs + RTC_STATUS);
57 writel(val, rtc->regs + reg);
58 udelay(5);
59 }
60
armada38x_rtc_read(struct armada38x_rtc * rtc,u8 reg)61 static u32 armada38x_rtc_read(struct armada38x_rtc *rtc, u8 reg)
62 {
63 u8 counts[SAMPLE_NR], max_idx;
64 u32 samples[SAMPLE_NR], max;
65 int i, j, last;
66
67 for (i = 0, last = 0; i < SAMPLE_NR; ++i) {
68 u32 sample = readl(rtc->regs + reg);
69
70 /* find if this value was already read */
71 for (j = 0; j < last; ++j) {
72 if (samples[j] == sample)
73 break;
74 }
75
76 if (j < last) {
77 /* if yes, increment count */
78 ++counts[j];
79 } else {
80 /* if not, add */
81 samples[last] = sample;
82 counts[last] = 1;
83 ++last;
84 }
85 }
86
87 /* finally find the sample that was read the most */
88 max = 0;
89 max_idx = 0;
90
91 for (i = 0; i < last; ++i) {
92 if (counts[i] > max) {
93 max = counts[i];
94 max_idx = i;
95 }
96 }
97
98 return samples[max_idx];
99 }
100
armada38x_rtc_get(struct udevice * dev,struct rtc_time * tm)101 static int armada38x_rtc_get(struct udevice *dev, struct rtc_time *tm)
102 {
103 struct armada38x_rtc *rtc = dev_get_priv(dev);
104 u32 time;
105
106 time = armada38x_rtc_read(rtc, RTC_TIME);
107
108 rtc_to_tm(time, tm);
109
110 return 0;
111 }
112
armada38x_rtc_reset(struct udevice * dev)113 static int armada38x_rtc_reset(struct udevice *dev)
114 {
115 struct armada38x_rtc *rtc = dev_get_priv(dev);
116 u32 reg;
117
118 reg = armada38x_rtc_read(rtc, RTC_CONF_TEST);
119
120 if (reg & 0xff) {
121 armada38x_rtc_write(0, rtc, RTC_CONF_TEST);
122 mdelay(500);
123 armada38x_rtc_write(0, rtc, RTC_TIME);
124 armada38x_rtc_write(BIT(0) | BIT(1), 0, RTC_STATUS);
125 }
126
127 return 0;
128 }
129
armada38x_rtc_set(struct udevice * dev,const struct rtc_time * tm)130 static int armada38x_rtc_set(struct udevice *dev, const struct rtc_time *tm)
131 {
132 struct armada38x_rtc *rtc = dev_get_priv(dev);
133 unsigned long time;
134
135 time = rtc_mktime(tm);
136
137 if (time > U32_MAX)
138 printf("%s: requested time to set will overflow\n", dev->name);
139
140 armada38x_rtc_reset(dev);
141 armada38x_rtc_write(time, rtc, RTC_TIME);
142
143 return 0;
144 }
145
armada38x_probe(struct udevice * dev)146 static int armada38x_probe(struct udevice *dev)
147 {
148 struct armada38x_rtc *rtc = dev_get_priv(dev);
149
150 rtc->regs = dev_remap_addr_name(dev, "rtc");
151 if (!rtc->regs)
152 goto err;
153
154 rtc->regs_soc = dev_remap_addr_name(dev, "rtc-soc");
155 if (!rtc->regs_soc)
156 goto err;
157
158 update_38x_mbus_timing_params(rtc);
159
160 return 0;
161 err:
162 printf("%s: io address missing\n", dev->name);
163 return -ENODEV;
164 }
165
166 static const struct rtc_ops armada38x_rtc_ops = {
167 .get = armada38x_rtc_get,
168 .set = armada38x_rtc_set,
169 .reset = armada38x_rtc_reset,
170 };
171
172 static const struct udevice_id armada38x_rtc_ids[] = {
173 { .compatible = "marvell,armada-380-rtc", .data = 0 },
174 { }
175 };
176
177 U_BOOT_DRIVER(rtc_armada38x) = {
178 .name = "rtc-armada38x",
179 .id = UCLASS_RTC,
180 .of_match = armada38x_rtc_ids,
181 .probe = armada38x_probe,
182 .priv_auto = sizeof(struct armada38x_rtc),
183 .ops = &armada38x_rtc_ops,
184 };
185