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