1b09d6335SNishanth Menon // SPDX-License-Identifier: GPL-2.0
2b09d6335SNishanth Menon /*
3b09d6335SNishanth Menon * Texas Instruments K3 RTC driver
4b09d6335SNishanth Menon *
5b09d6335SNishanth Menon * Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/
6b09d6335SNishanth Menon */
7b09d6335SNishanth Menon
8b09d6335SNishanth Menon #include <linux/clk.h>
9b09d6335SNishanth Menon #include <linux/delay.h>
10b09d6335SNishanth Menon #include <linux/mod_devicetable.h>
11b09d6335SNishanth Menon #include <linux/module.h>
12*48144c28SRob Herring #include <linux/of.h>
13b09d6335SNishanth Menon #include <linux/platform_device.h>
141e2585b4SBryan Brattlof #include <linux/sys_soc.h>
15b09d6335SNishanth Menon #include <linux/property.h>
16b09d6335SNishanth Menon #include <linux/regmap.h>
17b09d6335SNishanth Menon #include <linux/rtc.h>
18b09d6335SNishanth Menon
19b09d6335SNishanth Menon /* Registers */
20b09d6335SNishanth Menon #define REG_K3RTC_S_CNT_LSW 0x08
21b09d6335SNishanth Menon #define REG_K3RTC_S_CNT_MSW 0x0c
22b09d6335SNishanth Menon #define REG_K3RTC_COMP 0x10
23b09d6335SNishanth Menon #define REG_K3RTC_ON_OFF_S_CNT_LSW 0x20
24b09d6335SNishanth Menon #define REG_K3RTC_ON_OFF_S_CNT_MSW 0x24
25b09d6335SNishanth Menon #define REG_K3RTC_SCRATCH0 0x30
26b09d6335SNishanth Menon #define REG_K3RTC_SCRATCH7 0x4c
27b09d6335SNishanth Menon #define REG_K3RTC_GENERAL_CTL 0x50
28b09d6335SNishanth Menon #define REG_K3RTC_IRQSTATUS_RAW_SYS 0x54
29b09d6335SNishanth Menon #define REG_K3RTC_IRQSTATUS_SYS 0x58
30b09d6335SNishanth Menon #define REG_K3RTC_IRQENABLE_SET_SYS 0x5c
31b09d6335SNishanth Menon #define REG_K3RTC_IRQENABLE_CLR_SYS 0x60
32b09d6335SNishanth Menon #define REG_K3RTC_SYNCPEND 0x68
33b09d6335SNishanth Menon #define REG_K3RTC_KICK0 0x70
34b09d6335SNishanth Menon #define REG_K3RTC_KICK1 0x74
35b09d6335SNishanth Menon
36b09d6335SNishanth Menon /* Freeze when lsw is read and unfreeze when msw is read */
37b09d6335SNishanth Menon #define K3RTC_CNT_FMODE_S_CNT_VALUE (0x2 << 24)
38b09d6335SNishanth Menon
39b09d6335SNishanth Menon /* Magic values for lock/unlock */
40b09d6335SNishanth Menon #define K3RTC_KICK0_UNLOCK_VALUE 0x83e70b13
41b09d6335SNishanth Menon #define K3RTC_KICK1_UNLOCK_VALUE 0x95a4f1e0
42b09d6335SNishanth Menon
43b09d6335SNishanth Menon /* Multiplier for ppb conversions */
44b09d6335SNishanth Menon #define K3RTC_PPB_MULT (1000000000LL)
45b09d6335SNishanth Menon /* Min and max values supported with 'offset' interface (swapped sign) */
46b09d6335SNishanth Menon #define K3RTC_MIN_OFFSET (-277761)
47b09d6335SNishanth Menon #define K3RTC_MAX_OFFSET (277778)
48b09d6335SNishanth Menon
49b09d6335SNishanth Menon static const struct regmap_config ti_k3_rtc_regmap_config = {
50b09d6335SNishanth Menon .name = "peripheral-registers",
51b09d6335SNishanth Menon .reg_bits = 32,
52b09d6335SNishanth Menon .val_bits = 32,
53b09d6335SNishanth Menon .reg_stride = 4,
54b09d6335SNishanth Menon .max_register = REG_K3RTC_KICK1,
55b09d6335SNishanth Menon };
56b09d6335SNishanth Menon
57b09d6335SNishanth Menon enum ti_k3_rtc_fields {
58b09d6335SNishanth Menon K3RTC_KICK0,
59b09d6335SNishanth Menon K3RTC_KICK1,
60b09d6335SNishanth Menon K3RTC_S_CNT_LSW,
61b09d6335SNishanth Menon K3RTC_S_CNT_MSW,
62b09d6335SNishanth Menon K3RTC_O32K_OSC_DEP_EN,
63b09d6335SNishanth Menon K3RTC_UNLOCK,
64b09d6335SNishanth Menon K3RTC_CNT_FMODE,
65b09d6335SNishanth Menon K3RTC_PEND,
66b09d6335SNishanth Menon K3RTC_RELOAD_FROM_BBD,
67b09d6335SNishanth Menon K3RTC_COMP,
68b09d6335SNishanth Menon
69b09d6335SNishanth Menon K3RTC_ALM_S_CNT_LSW,
70b09d6335SNishanth Menon K3RTC_ALM_S_CNT_MSW,
71b09d6335SNishanth Menon K3RTC_IRQ_STATUS_RAW,
72b09d6335SNishanth Menon K3RTC_IRQ_STATUS,
73b09d6335SNishanth Menon K3RTC_IRQ_ENABLE_SET,
74b09d6335SNishanth Menon K3RTC_IRQ_ENABLE_CLR,
75b09d6335SNishanth Menon
76b09d6335SNishanth Menon K3RTC_IRQ_STATUS_ALT,
77b09d6335SNishanth Menon K3RTC_IRQ_ENABLE_CLR_ALT,
78b09d6335SNishanth Menon
79b09d6335SNishanth Menon K3_RTC_MAX_FIELDS
80b09d6335SNishanth Menon };
81b09d6335SNishanth Menon
82b09d6335SNishanth Menon static const struct reg_field ti_rtc_reg_fields[] = {
83b09d6335SNishanth Menon [K3RTC_KICK0] = REG_FIELD(REG_K3RTC_KICK0, 0, 31),
84b09d6335SNishanth Menon [K3RTC_KICK1] = REG_FIELD(REG_K3RTC_KICK1, 0, 31),
85b09d6335SNishanth Menon [K3RTC_S_CNT_LSW] = REG_FIELD(REG_K3RTC_S_CNT_LSW, 0, 31),
86b09d6335SNishanth Menon [K3RTC_S_CNT_MSW] = REG_FIELD(REG_K3RTC_S_CNT_MSW, 0, 15),
87b09d6335SNishanth Menon [K3RTC_O32K_OSC_DEP_EN] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 21, 21),
88b09d6335SNishanth Menon [K3RTC_UNLOCK] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 23, 23),
89b09d6335SNishanth Menon [K3RTC_CNT_FMODE] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 24, 25),
90b09d6335SNishanth Menon [K3RTC_PEND] = REG_FIELD(REG_K3RTC_SYNCPEND, 0, 1),
91b09d6335SNishanth Menon [K3RTC_RELOAD_FROM_BBD] = REG_FIELD(REG_K3RTC_SYNCPEND, 31, 31),
92b09d6335SNishanth Menon [K3RTC_COMP] = REG_FIELD(REG_K3RTC_COMP, 0, 31),
93b09d6335SNishanth Menon
94b09d6335SNishanth Menon /* We use on to off as alarm trigger */
95b09d6335SNishanth Menon [K3RTC_ALM_S_CNT_LSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_LSW, 0, 31),
96b09d6335SNishanth Menon [K3RTC_ALM_S_CNT_MSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_MSW, 0, 15),
97b09d6335SNishanth Menon [K3RTC_IRQ_STATUS_RAW] = REG_FIELD(REG_K3RTC_IRQSTATUS_RAW_SYS, 0, 0),
98b09d6335SNishanth Menon [K3RTC_IRQ_STATUS] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 0, 0),
99b09d6335SNishanth Menon [K3RTC_IRQ_ENABLE_SET] = REG_FIELD(REG_K3RTC_IRQENABLE_SET_SYS, 0, 0),
100b09d6335SNishanth Menon [K3RTC_IRQ_ENABLE_CLR] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 0, 0),
101b09d6335SNishanth Menon /* Off to on is alternate */
102b09d6335SNishanth Menon [K3RTC_IRQ_STATUS_ALT] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 1, 1),
103b09d6335SNishanth Menon [K3RTC_IRQ_ENABLE_CLR_ALT] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 1, 1),
104b09d6335SNishanth Menon };
105b09d6335SNishanth Menon
106b09d6335SNishanth Menon /**
107b09d6335SNishanth Menon * struct ti_k3_rtc - Private data for ti-k3-rtc
108b09d6335SNishanth Menon * @irq: IRQ
109b09d6335SNishanth Menon * @sync_timeout_us: data sync timeout period in uSec
110b09d6335SNishanth Menon * @rate_32k: 32k clock rate in Hz
111b09d6335SNishanth Menon * @rtc_dev: rtc device
112b09d6335SNishanth Menon * @regmap: rtc mmio regmap
113b09d6335SNishanth Menon * @r_fields: rtc register fields
114b09d6335SNishanth Menon */
115b09d6335SNishanth Menon struct ti_k3_rtc {
116b09d6335SNishanth Menon unsigned int irq;
117b09d6335SNishanth Menon u32 sync_timeout_us;
118b09d6335SNishanth Menon unsigned long rate_32k;
119b09d6335SNishanth Menon struct rtc_device *rtc_dev;
120b09d6335SNishanth Menon struct regmap *regmap;
121b09d6335SNishanth Menon struct regmap_field *r_fields[K3_RTC_MAX_FIELDS];
122b09d6335SNishanth Menon };
123b09d6335SNishanth Menon
k3rtc_field_read(struct ti_k3_rtc * priv,enum ti_k3_rtc_fields f)124b09d6335SNishanth Menon static int k3rtc_field_read(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f)
125b09d6335SNishanth Menon {
126b09d6335SNishanth Menon int ret;
127b09d6335SNishanth Menon int val;
128b09d6335SNishanth Menon
129b09d6335SNishanth Menon ret = regmap_field_read(priv->r_fields[f], &val);
130b09d6335SNishanth Menon /*
131b09d6335SNishanth Menon * We shouldn't be seeing regmap fail on us for mmio reads
132b09d6335SNishanth Menon * This is possible if clock context fails, but that isn't the case for us
133b09d6335SNishanth Menon */
134b09d6335SNishanth Menon if (WARN_ON_ONCE(ret))
135b09d6335SNishanth Menon return ret;
136b09d6335SNishanth Menon return val;
137b09d6335SNishanth Menon }
138b09d6335SNishanth Menon
k3rtc_field_write(struct ti_k3_rtc * priv,enum ti_k3_rtc_fields f,u32 val)139b09d6335SNishanth Menon static void k3rtc_field_write(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f, u32 val)
140b09d6335SNishanth Menon {
141b09d6335SNishanth Menon regmap_field_write(priv->r_fields[f], val);
142b09d6335SNishanth Menon }
143b09d6335SNishanth Menon
144b09d6335SNishanth Menon /**
145b09d6335SNishanth Menon * k3rtc_fence - Ensure a register sync took place between the two domains
146b09d6335SNishanth Menon * @priv: pointer to priv data
147b09d6335SNishanth Menon *
148b09d6335SNishanth Menon * Return: 0 if the sync took place, else returns -ETIMEDOUT
149b09d6335SNishanth Menon */
k3rtc_fence(struct ti_k3_rtc * priv)150b09d6335SNishanth Menon static int k3rtc_fence(struct ti_k3_rtc *priv)
151b09d6335SNishanth Menon {
152b09d6335SNishanth Menon int ret;
153b09d6335SNishanth Menon
154b09d6335SNishanth Menon ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_PEND], ret,
155b09d6335SNishanth Menon !ret, 2, priv->sync_timeout_us);
156b09d6335SNishanth Menon
157b09d6335SNishanth Menon return ret;
158b09d6335SNishanth Menon }
159b09d6335SNishanth Menon
k3rtc_check_unlocked(struct ti_k3_rtc * priv)160b09d6335SNishanth Menon static inline int k3rtc_check_unlocked(struct ti_k3_rtc *priv)
161b09d6335SNishanth Menon {
162b09d6335SNishanth Menon int ret;
163b09d6335SNishanth Menon
164b09d6335SNishanth Menon ret = k3rtc_field_read(priv, K3RTC_UNLOCK);
165b09d6335SNishanth Menon if (ret < 0)
166b09d6335SNishanth Menon return ret;
167b09d6335SNishanth Menon
168b09d6335SNishanth Menon return (ret) ? 0 : 1;
169b09d6335SNishanth Menon }
170b09d6335SNishanth Menon
k3rtc_unlock_rtc(struct ti_k3_rtc * priv)171b09d6335SNishanth Menon static int k3rtc_unlock_rtc(struct ti_k3_rtc *priv)
172b09d6335SNishanth Menon {
173b09d6335SNishanth Menon int ret;
174b09d6335SNishanth Menon
175b09d6335SNishanth Menon ret = k3rtc_check_unlocked(priv);
176b09d6335SNishanth Menon if (!ret)
177b09d6335SNishanth Menon return ret;
178b09d6335SNishanth Menon
179b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_KICK0, K3RTC_KICK0_UNLOCK_VALUE);
180b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_KICK1, K3RTC_KICK1_UNLOCK_VALUE);
181b09d6335SNishanth Menon
182b09d6335SNishanth Menon /* Skip fence since we are going to check the unlock bit as fence */
183b09d6335SNishanth Menon ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_UNLOCK], ret,
184f2c5671aSBryan Brattlof ret, 2, priv->sync_timeout_us);
185b09d6335SNishanth Menon
186b09d6335SNishanth Menon return ret;
187b09d6335SNishanth Menon }
188b09d6335SNishanth Menon
1891e2585b4SBryan Brattlof /*
1901e2585b4SBryan Brattlof * This is the list of SoCs affected by TI's i2327 errata causing the RTC
1911e2585b4SBryan Brattlof * state-machine to break if not unlocked fast enough during boot. These
1921e2585b4SBryan Brattlof * SoCs must have the bootloader unlock this device very early in the
1931e2585b4SBryan Brattlof * boot-flow before we (Linux) can use this device.
1941e2585b4SBryan Brattlof */
1951e2585b4SBryan Brattlof static const struct soc_device_attribute has_erratum_i2327[] = {
1961e2585b4SBryan Brattlof { .family = "AM62X", .revision = "SR1.0" },
1971e2585b4SBryan Brattlof { /* sentinel */ }
1981e2585b4SBryan Brattlof };
1991e2585b4SBryan Brattlof
k3rtc_configure(struct device * dev)200b09d6335SNishanth Menon static int k3rtc_configure(struct device *dev)
201b09d6335SNishanth Menon {
202b09d6335SNishanth Menon int ret;
203b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
204b09d6335SNishanth Menon
205b09d6335SNishanth Menon /*
206b09d6335SNishanth Menon * HWBUG: The compare state machine is broken if the RTC module
207b09d6335SNishanth Menon * is NOT unlocked in under one second of boot - which is pretty long
208b09d6335SNishanth Menon * time from the perspective of Linux driver (module load, u-boot
209b09d6335SNishanth Menon * shell all can take much longer than this.
210b09d6335SNishanth Menon *
211b09d6335SNishanth Menon * In such occurrence, it is assumed that the RTC module is unusable
212b09d6335SNishanth Menon */
2131e2585b4SBryan Brattlof if (soc_device_match(has_erratum_i2327)) {
214b09d6335SNishanth Menon ret = k3rtc_check_unlocked(priv);
215b09d6335SNishanth Menon /* If there is an error OR if we are locked, return error */
216b09d6335SNishanth Menon if (ret) {
217b09d6335SNishanth Menon dev_err(dev,
218b09d6335SNishanth Menon HW_ERR "Erratum i2327 unlock QUIRK! Cannot operate!!\n");
219b09d6335SNishanth Menon return -EFAULT;
220b09d6335SNishanth Menon }
221b09d6335SNishanth Menon } else {
222b09d6335SNishanth Menon /* May need to explicitly unlock first time */
223b09d6335SNishanth Menon ret = k3rtc_unlock_rtc(priv);
224b09d6335SNishanth Menon if (ret) {
225b09d6335SNishanth Menon dev_err(dev, "Failed to unlock(%d)!\n", ret);
226b09d6335SNishanth Menon return ret;
227b09d6335SNishanth Menon }
228b09d6335SNishanth Menon }
229b09d6335SNishanth Menon
230b09d6335SNishanth Menon /* Enable Shadow register sync on 32k clock boundary */
231b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_O32K_OSC_DEP_EN, 0x1);
232b09d6335SNishanth Menon
233b09d6335SNishanth Menon /*
234b09d6335SNishanth Menon * Wait at least clock sync time before proceeding further programming.
235b09d6335SNishanth Menon * This ensures that the 32k based sync is active.
236b09d6335SNishanth Menon */
237b09d6335SNishanth Menon usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 5);
238b09d6335SNishanth Menon
239b09d6335SNishanth Menon /* We need to ensure fence here to make sure sync here */
240b09d6335SNishanth Menon ret = k3rtc_fence(priv);
241b09d6335SNishanth Menon if (ret) {
242b09d6335SNishanth Menon dev_err(dev,
243b09d6335SNishanth Menon "Failed fence osc_dep enable(%d) - is 32k clk working?!\n", ret);
244b09d6335SNishanth Menon return ret;
245b09d6335SNishanth Menon }
246b09d6335SNishanth Menon
247b09d6335SNishanth Menon /*
248b09d6335SNishanth Menon * FMODE setting: Reading lower seconds will freeze value on higher
249b09d6335SNishanth Menon * seconds. This also implies that we must *ALWAYS* read lower seconds
250b09d6335SNishanth Menon * prior to reading higher seconds
251b09d6335SNishanth Menon */
252b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_CNT_FMODE, K3RTC_CNT_FMODE_S_CNT_VALUE);
253b09d6335SNishanth Menon
254b09d6335SNishanth Menon /* Clear any spurious IRQ sources if any */
255b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_IRQ_STATUS_ALT, 0x1);
256b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_IRQ_STATUS, 0x1);
257b09d6335SNishanth Menon /* Disable all IRQs */
258b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR_ALT, 0x1);
259b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR, 0x1);
260b09d6335SNishanth Menon
261b09d6335SNishanth Menon /* And.. Let us Sync the writes in */
262b09d6335SNishanth Menon return k3rtc_fence(priv);
263b09d6335SNishanth Menon }
264b09d6335SNishanth Menon
ti_k3_rtc_read_time(struct device * dev,struct rtc_time * tm)265b09d6335SNishanth Menon static int ti_k3_rtc_read_time(struct device *dev, struct rtc_time *tm)
266b09d6335SNishanth Menon {
267b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
268b09d6335SNishanth Menon u32 seconds_lo, seconds_hi;
269b09d6335SNishanth Menon
270b09d6335SNishanth Menon seconds_lo = k3rtc_field_read(priv, K3RTC_S_CNT_LSW);
271b09d6335SNishanth Menon seconds_hi = k3rtc_field_read(priv, K3RTC_S_CNT_MSW);
272b09d6335SNishanth Menon
273b09d6335SNishanth Menon rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, tm);
274b09d6335SNishanth Menon
275b09d6335SNishanth Menon return 0;
276b09d6335SNishanth Menon }
277b09d6335SNishanth Menon
ti_k3_rtc_set_time(struct device * dev,struct rtc_time * tm)278b09d6335SNishanth Menon static int ti_k3_rtc_set_time(struct device *dev, struct rtc_time *tm)
279b09d6335SNishanth Menon {
280b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
281b09d6335SNishanth Menon time64_t seconds;
282b09d6335SNishanth Menon
283b09d6335SNishanth Menon seconds = rtc_tm_to_time64(tm);
284b09d6335SNishanth Menon
285b09d6335SNishanth Menon /*
286b09d6335SNishanth Menon * Read operation on LSW will freeze the RTC, so to update
287b09d6335SNishanth Menon * the time, we cannot use field operations. Just write since the
288b09d6335SNishanth Menon * reserved bits are ignored.
289b09d6335SNishanth Menon */
290b09d6335SNishanth Menon regmap_write(priv->regmap, REG_K3RTC_S_CNT_LSW, seconds);
291b09d6335SNishanth Menon regmap_write(priv->regmap, REG_K3RTC_S_CNT_MSW, seconds >> 32);
292b09d6335SNishanth Menon
293b09d6335SNishanth Menon return k3rtc_fence(priv);
294b09d6335SNishanth Menon }
295b09d6335SNishanth Menon
ti_k3_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)296b09d6335SNishanth Menon static int ti_k3_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
297b09d6335SNishanth Menon {
298b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
299b09d6335SNishanth Menon u32 reg;
300b09d6335SNishanth Menon u32 offset = enabled ? K3RTC_IRQ_ENABLE_SET : K3RTC_IRQ_ENABLE_CLR;
301b09d6335SNishanth Menon
302b09d6335SNishanth Menon reg = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET);
303b09d6335SNishanth Menon if ((enabled && reg) || (!enabled && !reg))
304b09d6335SNishanth Menon return 0;
305b09d6335SNishanth Menon
306b09d6335SNishanth Menon k3rtc_field_write(priv, offset, 0x1);
307b09d6335SNishanth Menon
308b09d6335SNishanth Menon /*
309b09d6335SNishanth Menon * Ensure the write sync is through - NOTE: it should be OK to have
310b09d6335SNishanth Menon * ISR to fire as we are checking sync (which should be done in a 32k
311b09d6335SNishanth Menon * cycle or so).
312b09d6335SNishanth Menon */
313b09d6335SNishanth Menon return k3rtc_fence(priv);
314b09d6335SNishanth Menon }
315b09d6335SNishanth Menon
ti_k3_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alarm)316b09d6335SNishanth Menon static int ti_k3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
317b09d6335SNishanth Menon {
318b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
319b09d6335SNishanth Menon u32 seconds_lo, seconds_hi;
320b09d6335SNishanth Menon
321b09d6335SNishanth Menon seconds_lo = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_LSW);
322b09d6335SNishanth Menon seconds_hi = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_MSW);
323b09d6335SNishanth Menon
324b09d6335SNishanth Menon rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, &alarm->time);
325b09d6335SNishanth Menon
326b09d6335SNishanth Menon alarm->enabled = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET);
327b09d6335SNishanth Menon
328b09d6335SNishanth Menon return 0;
329b09d6335SNishanth Menon }
330b09d6335SNishanth Menon
ti_k3_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alarm)331b09d6335SNishanth Menon static int ti_k3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
332b09d6335SNishanth Menon {
333b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
334b09d6335SNishanth Menon time64_t seconds;
335b09d6335SNishanth Menon int ret;
336b09d6335SNishanth Menon
337b09d6335SNishanth Menon seconds = rtc_tm_to_time64(&alarm->time);
338b09d6335SNishanth Menon
339b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_ALM_S_CNT_LSW, seconds);
340b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_ALM_S_CNT_MSW, (seconds >> 32));
341b09d6335SNishanth Menon
342b09d6335SNishanth Menon /* Make sure the alarm time is synced in */
343b09d6335SNishanth Menon ret = k3rtc_fence(priv);
344b09d6335SNishanth Menon if (ret) {
345b09d6335SNishanth Menon dev_err(dev, "Failed to fence(%d)! Potential config issue?\n", ret);
346b09d6335SNishanth Menon return ret;
347b09d6335SNishanth Menon }
348b09d6335SNishanth Menon
349b09d6335SNishanth Menon /* Alarm IRQ enable will do a sync */
350b09d6335SNishanth Menon return ti_k3_rtc_alarm_irq_enable(dev, alarm->enabled);
351b09d6335SNishanth Menon }
352b09d6335SNishanth Menon
ti_k3_rtc_read_offset(struct device * dev,long * offset)353b09d6335SNishanth Menon static int ti_k3_rtc_read_offset(struct device *dev, long *offset)
354b09d6335SNishanth Menon {
355b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
356b09d6335SNishanth Menon u32 ticks_per_hr = priv->rate_32k * 3600;
357b09d6335SNishanth Menon int comp;
358b09d6335SNishanth Menon s64 tmp;
359b09d6335SNishanth Menon
360b09d6335SNishanth Menon comp = k3rtc_field_read(priv, K3RTC_COMP);
361b09d6335SNishanth Menon
362b09d6335SNishanth Menon /* Convert from RTC calibration register format to ppb format */
363b09d6335SNishanth Menon tmp = comp * (s64)K3RTC_PPB_MULT;
364b09d6335SNishanth Menon if (tmp < 0)
365b09d6335SNishanth Menon tmp -= ticks_per_hr / 2LL;
366b09d6335SNishanth Menon else
367b09d6335SNishanth Menon tmp += ticks_per_hr / 2LL;
368b09d6335SNishanth Menon tmp = div_s64(tmp, ticks_per_hr);
369b09d6335SNishanth Menon
370b09d6335SNishanth Menon /* Offset value operates in negative way, so swap sign */
371b09d6335SNishanth Menon *offset = (long)-tmp;
372b09d6335SNishanth Menon
373b09d6335SNishanth Menon return 0;
374b09d6335SNishanth Menon }
375b09d6335SNishanth Menon
ti_k3_rtc_set_offset(struct device * dev,long offset)376b09d6335SNishanth Menon static int ti_k3_rtc_set_offset(struct device *dev, long offset)
377b09d6335SNishanth Menon {
378b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
379b09d6335SNishanth Menon u32 ticks_per_hr = priv->rate_32k * 3600;
380b09d6335SNishanth Menon int comp;
381b09d6335SNishanth Menon s64 tmp;
382b09d6335SNishanth Menon
383b09d6335SNishanth Menon /* Make sure offset value is within supported range */
384b09d6335SNishanth Menon if (offset < K3RTC_MIN_OFFSET || offset > K3RTC_MAX_OFFSET)
385b09d6335SNishanth Menon return -ERANGE;
386b09d6335SNishanth Menon
387b09d6335SNishanth Menon /* Convert from ppb format to RTC calibration register format */
388b09d6335SNishanth Menon tmp = offset * (s64)ticks_per_hr;
389b09d6335SNishanth Menon if (tmp < 0)
390b09d6335SNishanth Menon tmp -= K3RTC_PPB_MULT / 2LL;
391b09d6335SNishanth Menon else
392b09d6335SNishanth Menon tmp += K3RTC_PPB_MULT / 2LL;
393b09d6335SNishanth Menon tmp = div_s64(tmp, K3RTC_PPB_MULT);
394b09d6335SNishanth Menon
395b09d6335SNishanth Menon /* Offset value operates in negative way, so swap sign */
396b09d6335SNishanth Menon comp = (int)-tmp;
397b09d6335SNishanth Menon
398b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_COMP, comp);
399b09d6335SNishanth Menon
400b09d6335SNishanth Menon return k3rtc_fence(priv);
401b09d6335SNishanth Menon }
402b09d6335SNishanth Menon
ti_k3_rtc_interrupt(s32 irq,void * dev_id)403b09d6335SNishanth Menon static irqreturn_t ti_k3_rtc_interrupt(s32 irq, void *dev_id)
404b09d6335SNishanth Menon {
405b09d6335SNishanth Menon struct device *dev = dev_id;
406b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
407b09d6335SNishanth Menon u32 reg;
408b09d6335SNishanth Menon int ret;
409b09d6335SNishanth Menon
410b09d6335SNishanth Menon /*
411b09d6335SNishanth Menon * IRQ assertion can be very fast, however, the IRQ Status clear
412b09d6335SNishanth Menon * de-assert depends on 32k clock edge in the 32k domain
413b09d6335SNishanth Menon * If we clear the status prior to the first 32k clock edge,
414b09d6335SNishanth Menon * the status bit is cleared, but the IRQ stays re-asserted.
415b09d6335SNishanth Menon *
416b09d6335SNishanth Menon * To prevent this condition, we need to wait for clock sync time.
417b09d6335SNishanth Menon * We can either do that by polling the 32k observability signal for
418b09d6335SNishanth Menon * a toggle OR we could just sleep and let the processor do other
419b09d6335SNishanth Menon * stuff.
420b09d6335SNishanth Menon */
421b09d6335SNishanth Menon usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 2);
422b09d6335SNishanth Menon
423b09d6335SNishanth Menon /* Lets make sure that this is a valid interrupt */
424b09d6335SNishanth Menon reg = k3rtc_field_read(priv, K3RTC_IRQ_STATUS);
425b09d6335SNishanth Menon
426b09d6335SNishanth Menon if (!reg) {
427b09d6335SNishanth Menon u32 raw = k3rtc_field_read(priv, K3RTC_IRQ_STATUS_RAW);
428b09d6335SNishanth Menon
429b09d6335SNishanth Menon dev_err(dev,
430b09d6335SNishanth Menon HW_ERR
431b09d6335SNishanth Menon "Erratum i2327/IRQ trig: status: 0x%08x / 0x%08x\n", reg, raw);
432b09d6335SNishanth Menon return IRQ_NONE;
433b09d6335SNishanth Menon }
434b09d6335SNishanth Menon
435b09d6335SNishanth Menon /*
436b09d6335SNishanth Menon * Write 1 to clear status reg
437b09d6335SNishanth Menon * We cannot use a field operation here due to a potential race between
438b09d6335SNishanth Menon * 32k domain and vbus domain.
439b09d6335SNishanth Menon */
440b09d6335SNishanth Menon regmap_write(priv->regmap, REG_K3RTC_IRQSTATUS_SYS, 0x1);
441b09d6335SNishanth Menon
442b09d6335SNishanth Menon /* Sync the write in */
443b09d6335SNishanth Menon ret = k3rtc_fence(priv);
444b09d6335SNishanth Menon if (ret) {
445b09d6335SNishanth Menon dev_err(dev, "Failed to fence irq status clr(%d)!\n", ret);
446b09d6335SNishanth Menon return IRQ_NONE;
447b09d6335SNishanth Menon }
448b09d6335SNishanth Menon
449b09d6335SNishanth Menon /*
450b09d6335SNishanth Menon * Force the 32k status to be reloaded back in to ensure status is
451b09d6335SNishanth Menon * reflected back correctly.
452b09d6335SNishanth Menon */
453b09d6335SNishanth Menon k3rtc_field_write(priv, K3RTC_RELOAD_FROM_BBD, 0x1);
454b09d6335SNishanth Menon
455b09d6335SNishanth Menon /* Ensure the write sync is through */
456b09d6335SNishanth Menon ret = k3rtc_fence(priv);
457b09d6335SNishanth Menon if (ret) {
458b09d6335SNishanth Menon dev_err(dev, "Failed to fence reload from bbd(%d)!\n", ret);
459b09d6335SNishanth Menon return IRQ_NONE;
460b09d6335SNishanth Menon }
461b09d6335SNishanth Menon
462b09d6335SNishanth Menon /* Now we ensure that the status bit is cleared */
463b09d6335SNishanth Menon ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_IRQ_STATUS],
464b09d6335SNishanth Menon ret, !ret, 2, priv->sync_timeout_us);
465b09d6335SNishanth Menon if (ret) {
466b09d6335SNishanth Menon dev_err(dev, "Time out waiting for status clear\n");
467b09d6335SNishanth Menon return IRQ_NONE;
468b09d6335SNishanth Menon }
469b09d6335SNishanth Menon
470b09d6335SNishanth Menon /* Notify RTC core on event */
471b09d6335SNishanth Menon rtc_update_irq(priv->rtc_dev, 1, RTC_IRQF | RTC_AF);
472b09d6335SNishanth Menon
473b09d6335SNishanth Menon return IRQ_HANDLED;
474b09d6335SNishanth Menon }
475b09d6335SNishanth Menon
476b09d6335SNishanth Menon static const struct rtc_class_ops ti_k3_rtc_ops = {
477b09d6335SNishanth Menon .read_time = ti_k3_rtc_read_time,
478b09d6335SNishanth Menon .set_time = ti_k3_rtc_set_time,
479b09d6335SNishanth Menon .read_alarm = ti_k3_rtc_read_alarm,
480b09d6335SNishanth Menon .set_alarm = ti_k3_rtc_set_alarm,
481b09d6335SNishanth Menon .read_offset = ti_k3_rtc_read_offset,
482b09d6335SNishanth Menon .set_offset = ti_k3_rtc_set_offset,
483b09d6335SNishanth Menon .alarm_irq_enable = ti_k3_rtc_alarm_irq_enable,
484b09d6335SNishanth Menon };
485b09d6335SNishanth Menon
ti_k3_rtc_scratch_read(void * priv_data,unsigned int offset,void * val,size_t bytes)486b09d6335SNishanth Menon static int ti_k3_rtc_scratch_read(void *priv_data, unsigned int offset,
487b09d6335SNishanth Menon void *val, size_t bytes)
488b09d6335SNishanth Menon {
489b09d6335SNishanth Menon struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data;
490b09d6335SNishanth Menon
491b09d6335SNishanth Menon return regmap_bulk_read(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4);
492b09d6335SNishanth Menon }
493b09d6335SNishanth Menon
ti_k3_rtc_scratch_write(void * priv_data,unsigned int offset,void * val,size_t bytes)494b09d6335SNishanth Menon static int ti_k3_rtc_scratch_write(void *priv_data, unsigned int offset,
495b09d6335SNishanth Menon void *val, size_t bytes)
496b09d6335SNishanth Menon {
497b09d6335SNishanth Menon struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data;
498b09d6335SNishanth Menon int ret;
499b09d6335SNishanth Menon
500b09d6335SNishanth Menon ret = regmap_bulk_write(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4);
501b09d6335SNishanth Menon if (ret)
502b09d6335SNishanth Menon return ret;
503b09d6335SNishanth Menon
504b09d6335SNishanth Menon return k3rtc_fence(priv);
505b09d6335SNishanth Menon }
506b09d6335SNishanth Menon
507b09d6335SNishanth Menon static struct nvmem_config ti_k3_rtc_nvmem_config = {
508b09d6335SNishanth Menon .name = "ti_k3_rtc_scratch",
509b09d6335SNishanth Menon .word_size = 4,
510b09d6335SNishanth Menon .stride = 4,
511b09d6335SNishanth Menon .size = REG_K3RTC_SCRATCH7 - REG_K3RTC_SCRATCH0 + 4,
512b09d6335SNishanth Menon .reg_read = ti_k3_rtc_scratch_read,
513b09d6335SNishanth Menon .reg_write = ti_k3_rtc_scratch_write,
514b09d6335SNishanth Menon };
515b09d6335SNishanth Menon
k3rtc_get_32kclk(struct device * dev,struct ti_k3_rtc * priv)516b09d6335SNishanth Menon static int k3rtc_get_32kclk(struct device *dev, struct ti_k3_rtc *priv)
517b09d6335SNishanth Menon {
518b09d6335SNishanth Menon struct clk *clk;
519b09d6335SNishanth Menon
5208f08553eSChristophe JAILLET clk = devm_clk_get_enabled(dev, "osc32k");
521b09d6335SNishanth Menon if (IS_ERR(clk))
522b09d6335SNishanth Menon return PTR_ERR(clk);
523b09d6335SNishanth Menon
524b09d6335SNishanth Menon priv->rate_32k = clk_get_rate(clk);
525b09d6335SNishanth Menon
526b09d6335SNishanth Menon /* Make sure we are exact 32k clock. Else, try to compensate delay */
527b09d6335SNishanth Menon if (priv->rate_32k != 32768)
528b09d6335SNishanth Menon dev_warn(dev, "Clock rate %ld is not 32768! Could misbehave!\n",
529b09d6335SNishanth Menon priv->rate_32k);
530b09d6335SNishanth Menon
531b09d6335SNishanth Menon /*
532b09d6335SNishanth Menon * Sync timeout should be two 32k clk sync cycles = ~61uS. We double
533b09d6335SNishanth Menon * it to comprehend intermediate bus segment and cpu frequency
534b09d6335SNishanth Menon * deltas
535b09d6335SNishanth Menon */
536b09d6335SNishanth Menon priv->sync_timeout_us = (u32)(DIV_ROUND_UP_ULL(1000000, priv->rate_32k) * 4);
537b09d6335SNishanth Menon
5388f08553eSChristophe JAILLET return 0;
539b09d6335SNishanth Menon }
540b09d6335SNishanth Menon
k3rtc_get_vbusclk(struct device * dev,struct ti_k3_rtc * priv)541b09d6335SNishanth Menon static int k3rtc_get_vbusclk(struct device *dev, struct ti_k3_rtc *priv)
542b09d6335SNishanth Menon {
543b09d6335SNishanth Menon struct clk *clk;
544b09d6335SNishanth Menon
545b09d6335SNishanth Menon /* Note: VBUS isn't a context clock, it is needed for hardware operation */
5468f08553eSChristophe JAILLET clk = devm_clk_get_enabled(dev, "vbus");
547b09d6335SNishanth Menon if (IS_ERR(clk))
548b09d6335SNishanth Menon return PTR_ERR(clk);
549b09d6335SNishanth Menon
5508f08553eSChristophe JAILLET return 0;
551b09d6335SNishanth Menon }
552b09d6335SNishanth Menon
ti_k3_rtc_probe(struct platform_device * pdev)553b09d6335SNishanth Menon static int ti_k3_rtc_probe(struct platform_device *pdev)
554b09d6335SNishanth Menon {
555b09d6335SNishanth Menon struct device *dev = &pdev->dev;
556b09d6335SNishanth Menon struct ti_k3_rtc *priv;
557b09d6335SNishanth Menon void __iomem *rtc_base;
558b09d6335SNishanth Menon int ret;
559b09d6335SNishanth Menon
560b09d6335SNishanth Menon priv = devm_kzalloc(dev, sizeof(struct ti_k3_rtc), GFP_KERNEL);
561b09d6335SNishanth Menon if (!priv)
562b09d6335SNishanth Menon return -ENOMEM;
563b09d6335SNishanth Menon
564b09d6335SNishanth Menon rtc_base = devm_platform_ioremap_resource(pdev, 0);
565b09d6335SNishanth Menon if (IS_ERR(rtc_base))
566b09d6335SNishanth Menon return PTR_ERR(rtc_base);
567b09d6335SNishanth Menon
568b09d6335SNishanth Menon priv->regmap = devm_regmap_init_mmio(dev, rtc_base, &ti_k3_rtc_regmap_config);
569b09d6335SNishanth Menon if (IS_ERR(priv->regmap))
570b09d6335SNishanth Menon return PTR_ERR(priv->regmap);
571b09d6335SNishanth Menon
572b09d6335SNishanth Menon ret = devm_regmap_field_bulk_alloc(dev, priv->regmap, priv->r_fields,
573b09d6335SNishanth Menon ti_rtc_reg_fields, K3_RTC_MAX_FIELDS);
574b09d6335SNishanth Menon if (ret)
575b09d6335SNishanth Menon return ret;
576b09d6335SNishanth Menon
577b09d6335SNishanth Menon ret = k3rtc_get_32kclk(dev, priv);
578b09d6335SNishanth Menon if (ret)
579b09d6335SNishanth Menon return ret;
580b09d6335SNishanth Menon ret = k3rtc_get_vbusclk(dev, priv);
581b09d6335SNishanth Menon if (ret)
582b09d6335SNishanth Menon return ret;
583b09d6335SNishanth Menon
584b09d6335SNishanth Menon ret = platform_get_irq(pdev, 0);
585b09d6335SNishanth Menon if (ret < 0)
586b09d6335SNishanth Menon return ret;
587b09d6335SNishanth Menon priv->irq = (unsigned int)ret;
588b09d6335SNishanth Menon
589b09d6335SNishanth Menon priv->rtc_dev = devm_rtc_allocate_device(dev);
590b09d6335SNishanth Menon if (IS_ERR(priv->rtc_dev))
591b09d6335SNishanth Menon return PTR_ERR(priv->rtc_dev);
592b09d6335SNishanth Menon
593b09d6335SNishanth Menon priv->rtc_dev->ops = &ti_k3_rtc_ops;
594b09d6335SNishanth Menon priv->rtc_dev->range_max = (1ULL << 48) - 1; /* 48Bit seconds */
595b09d6335SNishanth Menon ti_k3_rtc_nvmem_config.priv = priv;
596b09d6335SNishanth Menon
597b09d6335SNishanth Menon ret = devm_request_threaded_irq(dev, priv->irq, NULL,
598b09d6335SNishanth Menon ti_k3_rtc_interrupt,
599b09d6335SNishanth Menon IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
600b09d6335SNishanth Menon dev_name(dev), dev);
601b09d6335SNishanth Menon if (ret) {
602b09d6335SNishanth Menon dev_err(dev, "Could not request IRQ: %d\n", ret);
603b09d6335SNishanth Menon return ret;
604b09d6335SNishanth Menon }
605b09d6335SNishanth Menon
606b09d6335SNishanth Menon platform_set_drvdata(pdev, priv);
607b09d6335SNishanth Menon
608b09d6335SNishanth Menon ret = k3rtc_configure(dev);
609b09d6335SNishanth Menon if (ret)
610b09d6335SNishanth Menon return ret;
611b09d6335SNishanth Menon
612b09d6335SNishanth Menon if (device_property_present(dev, "wakeup-source"))
613b09d6335SNishanth Menon device_init_wakeup(dev, true);
614b09d6335SNishanth Menon else
615b09d6335SNishanth Menon device_set_wakeup_capable(dev, true);
616b09d6335SNishanth Menon
617b09d6335SNishanth Menon ret = devm_rtc_register_device(priv->rtc_dev);
618b09d6335SNishanth Menon if (ret)
619b09d6335SNishanth Menon return ret;
620b09d6335SNishanth Menon
621b09d6335SNishanth Menon return devm_rtc_nvmem_register(priv->rtc_dev, &ti_k3_rtc_nvmem_config);
622b09d6335SNishanth Menon }
623b09d6335SNishanth Menon
624b09d6335SNishanth Menon static const struct of_device_id ti_k3_rtc_of_match_table[] = {
6251e2585b4SBryan Brattlof {.compatible = "ti,am62-rtc" },
626b09d6335SNishanth Menon {}
627b09d6335SNishanth Menon };
628b09d6335SNishanth Menon MODULE_DEVICE_TABLE(of, ti_k3_rtc_of_match_table);
629b09d6335SNishanth Menon
ti_k3_rtc_suspend(struct device * dev)630b09d6335SNishanth Menon static int __maybe_unused ti_k3_rtc_suspend(struct device *dev)
631b09d6335SNishanth Menon {
632b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
633b09d6335SNishanth Menon
634b09d6335SNishanth Menon if (device_may_wakeup(dev))
635d31d7300SDhruva Gole return enable_irq_wake(priv->irq);
636d31d7300SDhruva Gole
637b09d6335SNishanth Menon return 0;
638b09d6335SNishanth Menon }
639b09d6335SNishanth Menon
ti_k3_rtc_resume(struct device * dev)640b09d6335SNishanth Menon static int __maybe_unused ti_k3_rtc_resume(struct device *dev)
641b09d6335SNishanth Menon {
642b09d6335SNishanth Menon struct ti_k3_rtc *priv = dev_get_drvdata(dev);
643b09d6335SNishanth Menon
644b09d6335SNishanth Menon if (device_may_wakeup(dev))
645b09d6335SNishanth Menon disable_irq_wake(priv->irq);
646b09d6335SNishanth Menon return 0;
647b09d6335SNishanth Menon }
648b09d6335SNishanth Menon
649b09d6335SNishanth Menon static SIMPLE_DEV_PM_OPS(ti_k3_rtc_pm_ops, ti_k3_rtc_suspend, ti_k3_rtc_resume);
650b09d6335SNishanth Menon
651b09d6335SNishanth Menon static struct platform_driver ti_k3_rtc_driver = {
652b09d6335SNishanth Menon .probe = ti_k3_rtc_probe,
653b09d6335SNishanth Menon .driver = {
654b09d6335SNishanth Menon .name = "rtc-ti-k3",
655b09d6335SNishanth Menon .of_match_table = ti_k3_rtc_of_match_table,
656b09d6335SNishanth Menon .pm = &ti_k3_rtc_pm_ops,
657b09d6335SNishanth Menon },
658b09d6335SNishanth Menon };
659b09d6335SNishanth Menon module_platform_driver(ti_k3_rtc_driver);
660b09d6335SNishanth Menon
661b09d6335SNishanth Menon MODULE_LICENSE("GPL");
662b09d6335SNishanth Menon MODULE_DESCRIPTION("TI K3 RTC driver");
663b09d6335SNishanth Menon MODULE_AUTHOR("Nishanth Menon");
664