1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Real time clocks driver for MStar/SigmaStar SSD202D SoCs.
4 *
5 * (C) 2021 Daniel Palmer
6 * (C) 2023 Romain Perier
7 */
8
9 #include <linux/clk.h>
10 #include <linux/delay.h>
11 #include <linux/module.h>
12 #include <linux/mod_devicetable.h>
13 #include <linux/platform_device.h>
14 #include <linux/rtc.h>
15 #include <linux/regmap.h>
16 #include <linux/pm.h>
17
18 #define REG_CTRL 0x0
19 #define REG_CTRL1 0x4
20 #define REG_ISO_CTRL 0xc
21 #define REG_WRDATA_L 0x10
22 #define REG_WRDATA_H 0x14
23 #define REG_ISOACK 0x20
24 #define REG_RDDATA_L 0x24
25 #define REG_RDDATA_H 0x28
26 #define REG_RDCNT_L 0x30
27 #define REG_RDCNT_H 0x34
28 #define REG_CNT_TRIG 0x38
29 #define REG_PWRCTRL 0x3c
30 #define REG_RTC_TEST 0x54
31
32 #define CNT_RD_TRIG_BIT BIT(0)
33 #define CNT_RD_BIT BIT(0)
34 #define BASE_WR_BIT BIT(1)
35 #define BASE_RD_BIT BIT(2)
36 #define CNT_RST_BIT BIT(3)
37 #define ISO_CTRL_ACK_MASK BIT(3)
38 #define ISO_CTRL_ACK_SHIFT 3
39 #define SW0_WR_BIT BIT(5)
40 #define SW1_WR_BIT BIT(6)
41 #define SW0_RD_BIT BIT(7)
42 #define SW1_RD_BIT BIT(8)
43
44 #define ISO_CTRL_MASK GENMASK(2, 0)
45
46 struct ssd202d_rtc {
47 struct rtc_device *rtc_dev;
48 void __iomem *base;
49 };
50
read_iso_en(void __iomem * base)51 static u8 read_iso_en(void __iomem *base)
52 {
53 return readb(base + REG_RTC_TEST) & 0x1;
54 }
55
read_iso_ctrl_ack(void __iomem * base)56 static u8 read_iso_ctrl_ack(void __iomem *base)
57 {
58 return (readb(base + REG_ISOACK) & ISO_CTRL_ACK_MASK) >> ISO_CTRL_ACK_SHIFT;
59 }
60
ssd202d_rtc_isoctrl(struct ssd202d_rtc * priv)61 static int ssd202d_rtc_isoctrl(struct ssd202d_rtc *priv)
62 {
63 static const unsigned int sequence[] = { 0x0, 0x1, 0x3, 0x7, 0x5, 0x1, 0x0 };
64 unsigned int val;
65 struct device *dev = &priv->rtc_dev->dev;
66 int i, ret;
67
68 /*
69 * This gates iso_en by writing a special sequence of bytes to iso_ctrl
70 * and ensuring that it has been correctly applied by reading iso_ctrl_ack
71 */
72 for (i = 0; i < ARRAY_SIZE(sequence); i++) {
73 writeb(sequence[i] & ISO_CTRL_MASK, priv->base + REG_ISO_CTRL);
74
75 ret = read_poll_timeout(read_iso_ctrl_ack, val, val == (i % 2), 100,
76 20 * 100, true, priv->base);
77 if (ret) {
78 dev_dbg(dev, "Timeout waiting for ack byte %i (%x) of sequence\n", i,
79 sequence[i]);
80 return ret;
81 }
82 }
83
84 /*
85 * At this point iso_en should be raised for 1ms
86 */
87 ret = read_poll_timeout(read_iso_en, val, val, 100, 22 * 100, true, priv->base);
88 if (ret)
89 dev_dbg(dev, "Timeout waiting for iso_en\n");
90 mdelay(2);
91 return 0;
92 }
93
ssd202d_rtc_read_reg(struct ssd202d_rtc * priv,unsigned int reg,unsigned int field,unsigned int * base)94 static void ssd202d_rtc_read_reg(struct ssd202d_rtc *priv, unsigned int reg,
95 unsigned int field, unsigned int *base)
96 {
97 unsigned int l, h;
98 u16 val;
99
100 /* Ask for the content of an RTC value into RDDATA by gating iso_en,
101 * then iso_en is gated and the content of RDDATA can be read
102 */
103 val = readw(priv->base + reg);
104 writew(val | field, priv->base + reg);
105 ssd202d_rtc_isoctrl(priv);
106 writew(val & ~field, priv->base + reg);
107
108 l = readw(priv->base + REG_RDDATA_L);
109 h = readw(priv->base + REG_RDDATA_H);
110
111 *base = (h << 16) | l;
112 }
113
ssd202d_rtc_write_reg(struct ssd202d_rtc * priv,unsigned int reg,unsigned int field,u32 base)114 static void ssd202d_rtc_write_reg(struct ssd202d_rtc *priv, unsigned int reg,
115 unsigned int field, u32 base)
116 {
117 u16 val;
118
119 /* Set the content of an RTC value from WRDATA by gating iso_en */
120 val = readw(priv->base + reg);
121 writew(val | field, priv->base + reg);
122 writew(base, priv->base + REG_WRDATA_L);
123 writew(base >> 16, priv->base + REG_WRDATA_H);
124 ssd202d_rtc_isoctrl(priv);
125 writew(val & ~field, priv->base + reg);
126 }
127
ssd202d_rtc_read_counter(struct ssd202d_rtc * priv,unsigned int * counter)128 static int ssd202d_rtc_read_counter(struct ssd202d_rtc *priv, unsigned int *counter)
129 {
130 unsigned int l, h;
131 u16 val;
132
133 val = readw(priv->base + REG_CTRL1);
134 writew(val | CNT_RD_BIT, priv->base + REG_CTRL1);
135 ssd202d_rtc_isoctrl(priv);
136 writew(val & ~CNT_RD_BIT, priv->base + REG_CTRL1);
137
138 val = readw(priv->base + REG_CTRL1);
139 writew(val | CNT_RD_TRIG_BIT, priv->base + REG_CNT_TRIG);
140 writew(val & ~CNT_RD_TRIG_BIT, priv->base + REG_CNT_TRIG);
141
142 l = readw(priv->base + REG_RDCNT_L);
143 h = readw(priv->base + REG_RDCNT_H);
144
145 *counter = (h << 16) | l;
146
147 return 0;
148 }
149
ssd202d_rtc_read_time(struct device * dev,struct rtc_time * tm)150 static int ssd202d_rtc_read_time(struct device *dev, struct rtc_time *tm)
151 {
152 struct ssd202d_rtc *priv = dev_get_drvdata(dev);
153 unsigned int sw0, base, counter;
154 u32 seconds;
155 int ret;
156
157 /* Check that RTC is enabled by SW */
158 ssd202d_rtc_read_reg(priv, REG_CTRL, SW0_RD_BIT, &sw0);
159 if (sw0 != 1)
160 return -EINVAL;
161
162 /* Get RTC base value from RDDATA */
163 ssd202d_rtc_read_reg(priv, REG_CTRL, BASE_RD_BIT, &base);
164 /* Get RTC counter value from RDDATA */
165 ret = ssd202d_rtc_read_counter(priv, &counter);
166 if (ret)
167 return ret;
168
169 seconds = base + counter;
170
171 rtc_time64_to_tm(seconds, tm);
172
173 return 0;
174 }
175
ssd202d_rtc_reset_counter(struct ssd202d_rtc * priv)176 static int ssd202d_rtc_reset_counter(struct ssd202d_rtc *priv)
177 {
178 u16 val;
179
180 val = readw(priv->base + REG_CTRL);
181 writew(val | CNT_RST_BIT, priv->base + REG_CTRL);
182 ssd202d_rtc_isoctrl(priv);
183 writew(val & ~CNT_RST_BIT, priv->base + REG_CTRL);
184 ssd202d_rtc_isoctrl(priv);
185
186 return 0;
187 }
188
ssd202d_rtc_set_time(struct device * dev,struct rtc_time * tm)189 static int ssd202d_rtc_set_time(struct device *dev, struct rtc_time *tm)
190 {
191 struct ssd202d_rtc *priv = dev_get_drvdata(dev);
192 unsigned long seconds = rtc_tm_to_time64(tm);
193
194 ssd202d_rtc_write_reg(priv, REG_CTRL, BASE_WR_BIT, seconds);
195 ssd202d_rtc_reset_counter(priv);
196 ssd202d_rtc_write_reg(priv, REG_CTRL, SW0_WR_BIT, 1);
197
198 return 0;
199 }
200
201 static const struct rtc_class_ops ssd202d_rtc_ops = {
202 .read_time = ssd202d_rtc_read_time,
203 .set_time = ssd202d_rtc_set_time,
204 };
205
ssd202d_rtc_probe(struct platform_device * pdev)206 static int ssd202d_rtc_probe(struct platform_device *pdev)
207 {
208 struct device *dev = &pdev->dev;
209 struct ssd202d_rtc *priv;
210
211 priv = devm_kzalloc(&pdev->dev, sizeof(struct ssd202d_rtc), GFP_KERNEL);
212 if (!priv)
213 return -ENOMEM;
214
215 priv->base = devm_platform_ioremap_resource(pdev, 0);
216 if (IS_ERR(priv->base))
217 return PTR_ERR(priv->base);
218
219 priv->rtc_dev = devm_rtc_allocate_device(dev);
220 if (IS_ERR(priv->rtc_dev))
221 return PTR_ERR(priv->rtc_dev);
222
223 priv->rtc_dev->ops = &ssd202d_rtc_ops;
224 priv->rtc_dev->range_max = U32_MAX;
225
226 platform_set_drvdata(pdev, priv);
227
228 return devm_rtc_register_device(priv->rtc_dev);
229 }
230
231 static const struct of_device_id ssd202d_rtc_of_match_table[] = {
232 { .compatible = "mstar,ssd202d-rtc" },
233 { }
234 };
235 MODULE_DEVICE_TABLE(of, ssd202d_rtc_of_match_table);
236
237 static struct platform_driver ssd202d_rtc_driver = {
238 .probe = ssd202d_rtc_probe,
239 .driver = {
240 .name = "ssd202d-rtc",
241 .of_match_table = ssd202d_rtc_of_match_table,
242 },
243 };
244 module_platform_driver(ssd202d_rtc_driver);
245
246 MODULE_AUTHOR("Daniel Palmer <daniel@thingy.jp>");
247 MODULE_AUTHOR("Romain Perier <romain.perier@gmail.com>");
248 MODULE_DESCRIPTION("MStar SSD202D RTC Driver");
249 MODULE_LICENSE("GPL");
250