1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * rtc-tps6586x.c: RTC driver for TI PMIC TPS6586X |
4 | * |
5 | * Copyright (c) 2012, NVIDIA Corporation. |
6 | * |
7 | * Author: Laxman Dewangan <ldewangan@nvidia.com> |
8 | */ |
9 | |
10 | #include <linux/device.h> |
11 | #include <linux/err.h> |
12 | #include <linux/init.h> |
13 | #include <linux/irq.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/mfd/tps6586x.h> |
16 | #include <linux/module.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/rtc.h> |
20 | #include <linux/slab.h> |
21 | |
22 | #define RTC_CTRL 0xc0 |
23 | #define POR_RESET_N BIT(7) |
24 | #define OSC_SRC_SEL BIT(6) |
25 | #define RTC_ENABLE BIT(5) /* enables alarm */ |
26 | #define RTC_BUF_ENABLE BIT(4) /* 32 KHz buffer enable */ |
27 | #define PRE_BYPASS BIT(3) /* 0=1KHz or 1=32KHz updates */ |
28 | #define CL_SEL_MASK (BIT(2)|BIT(1)) |
29 | #define CL_SEL_POS 1 |
30 | #define RTC_ALARM1_HI 0xc1 |
31 | #define RTC_COUNT4 0xc6 |
32 | |
33 | /* start a PMU RTC access by reading the register prior to the RTC_COUNT4 */ |
34 | #define RTC_COUNT4_DUMMYREAD 0xc5 |
35 | |
36 | /*only 14-bits width in second*/ |
37 | #define ALM1_VALID_RANGE_IN_SEC 0x3FFF |
38 | |
39 | #define TPS6586X_RTC_CL_SEL_1_5PF 0x0 |
40 | #define TPS6586X_RTC_CL_SEL_6_5PF 0x1 |
41 | #define TPS6586X_RTC_CL_SEL_7_5PF 0x2 |
42 | #define TPS6586X_RTC_CL_SEL_12_5PF 0x3 |
43 | |
44 | struct tps6586x_rtc { |
45 | struct device *dev; |
46 | struct rtc_device *rtc; |
47 | int irq; |
48 | bool irq_en; |
49 | }; |
50 | |
51 | static inline struct device *to_tps6586x_dev(struct device *dev) |
52 | { |
53 | return dev->parent; |
54 | } |
55 | |
56 | static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm) |
57 | { |
58 | struct device *tps_dev = to_tps6586x_dev(dev); |
59 | unsigned long long ticks = 0; |
60 | time64_t seconds; |
61 | u8 buff[6]; |
62 | int ret; |
63 | int i; |
64 | |
65 | ret = tps6586x_reads(dev: tps_dev, RTC_COUNT4_DUMMYREAD, len: sizeof(buff), val: buff); |
66 | if (ret < 0) { |
67 | dev_err(dev, "read counter failed with err %d\n" , ret); |
68 | return ret; |
69 | } |
70 | |
71 | for (i = 1; i < sizeof(buff); i++) { |
72 | ticks <<= 8; |
73 | ticks |= buff[i]; |
74 | } |
75 | |
76 | seconds = ticks >> 10; |
77 | rtc_time64_to_tm(time: seconds, tm); |
78 | |
79 | return 0; |
80 | } |
81 | |
82 | static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm) |
83 | { |
84 | struct device *tps_dev = to_tps6586x_dev(dev); |
85 | unsigned long long ticks; |
86 | time64_t seconds; |
87 | u8 buff[5]; |
88 | int ret; |
89 | |
90 | seconds = rtc_tm_to_time64(tm); |
91 | |
92 | ticks = (unsigned long long)seconds << 10; |
93 | buff[0] = (ticks >> 32) & 0xff; |
94 | buff[1] = (ticks >> 24) & 0xff; |
95 | buff[2] = (ticks >> 16) & 0xff; |
96 | buff[3] = (ticks >> 8) & 0xff; |
97 | buff[4] = ticks & 0xff; |
98 | |
99 | /* Disable RTC before changing time */ |
100 | ret = tps6586x_clr_bits(dev: tps_dev, RTC_CTRL, RTC_ENABLE); |
101 | if (ret < 0) { |
102 | dev_err(dev, "failed to clear RTC_ENABLE\n" ); |
103 | return ret; |
104 | } |
105 | |
106 | ret = tps6586x_writes(dev: tps_dev, RTC_COUNT4, len: sizeof(buff), val: buff); |
107 | if (ret < 0) { |
108 | dev_err(dev, "failed to program new time\n" ); |
109 | return ret; |
110 | } |
111 | |
112 | /* Enable RTC */ |
113 | ret = tps6586x_set_bits(dev: tps_dev, RTC_CTRL, RTC_ENABLE); |
114 | if (ret < 0) { |
115 | dev_err(dev, "failed to set RTC_ENABLE\n" ); |
116 | return ret; |
117 | } |
118 | return 0; |
119 | } |
120 | |
121 | static int tps6586x_rtc_alarm_irq_enable(struct device *dev, |
122 | unsigned int enabled) |
123 | { |
124 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); |
125 | |
126 | if (enabled && !rtc->irq_en) { |
127 | enable_irq(irq: rtc->irq); |
128 | rtc->irq_en = true; |
129 | } else if (!enabled && rtc->irq_en) { |
130 | disable_irq(irq: rtc->irq); |
131 | rtc->irq_en = false; |
132 | } |
133 | return 0; |
134 | } |
135 | |
136 | static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
137 | { |
138 | struct device *tps_dev = to_tps6586x_dev(dev); |
139 | time64_t seconds; |
140 | unsigned long ticks; |
141 | unsigned long rtc_current_time; |
142 | unsigned long long rticks = 0; |
143 | u8 buff[3]; |
144 | u8 rbuff[6]; |
145 | int ret; |
146 | int i; |
147 | |
148 | seconds = rtc_tm_to_time64(tm: &alrm->time); |
149 | |
150 | ret = tps6586x_rtc_alarm_irq_enable(dev, enabled: alrm->enabled); |
151 | if (ret < 0) { |
152 | dev_err(dev, "can't set alarm irq, err %d\n" , ret); |
153 | return ret; |
154 | } |
155 | |
156 | ret = tps6586x_reads(dev: tps_dev, RTC_COUNT4_DUMMYREAD, |
157 | len: sizeof(rbuff), val: rbuff); |
158 | if (ret < 0) { |
159 | dev_err(dev, "read counter failed with err %d\n" , ret); |
160 | return ret; |
161 | } |
162 | |
163 | for (i = 1; i < sizeof(rbuff); i++) { |
164 | rticks <<= 8; |
165 | rticks |= rbuff[i]; |
166 | } |
167 | |
168 | rtc_current_time = rticks >> 10; |
169 | if ((seconds - rtc_current_time) > ALM1_VALID_RANGE_IN_SEC) |
170 | seconds = rtc_current_time - 1; |
171 | |
172 | ticks = (unsigned long long)seconds << 10; |
173 | buff[0] = (ticks >> 16) & 0xff; |
174 | buff[1] = (ticks >> 8) & 0xff; |
175 | buff[2] = ticks & 0xff; |
176 | |
177 | ret = tps6586x_writes(dev: tps_dev, RTC_ALARM1_HI, len: sizeof(buff), val: buff); |
178 | if (ret) |
179 | dev_err(dev, "programming alarm failed with err %d\n" , ret); |
180 | |
181 | return ret; |
182 | } |
183 | |
184 | static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
185 | { |
186 | struct device *tps_dev = to_tps6586x_dev(dev); |
187 | unsigned long ticks; |
188 | time64_t seconds; |
189 | u8 buff[3]; |
190 | int ret; |
191 | |
192 | ret = tps6586x_reads(dev: tps_dev, RTC_ALARM1_HI, len: sizeof(buff), val: buff); |
193 | if (ret) { |
194 | dev_err(dev, "read RTC_ALARM1_HI failed with err %d\n" , ret); |
195 | return ret; |
196 | } |
197 | |
198 | ticks = (buff[0] << 16) | (buff[1] << 8) | buff[2]; |
199 | seconds = ticks >> 10; |
200 | |
201 | rtc_time64_to_tm(time: seconds, tm: &alrm->time); |
202 | return 0; |
203 | } |
204 | |
205 | static const struct rtc_class_ops tps6586x_rtc_ops = { |
206 | .read_time = tps6586x_rtc_read_time, |
207 | .set_time = tps6586x_rtc_set_time, |
208 | .set_alarm = tps6586x_rtc_set_alarm, |
209 | .read_alarm = tps6586x_rtc_read_alarm, |
210 | .alarm_irq_enable = tps6586x_rtc_alarm_irq_enable, |
211 | }; |
212 | |
213 | static irqreturn_t tps6586x_rtc_irq(int irq, void *data) |
214 | { |
215 | struct tps6586x_rtc *rtc = data; |
216 | |
217 | rtc_update_irq(rtc: rtc->rtc, num: 1, RTC_IRQF | RTC_AF); |
218 | return IRQ_HANDLED; |
219 | } |
220 | |
221 | static int tps6586x_rtc_probe(struct platform_device *pdev) |
222 | { |
223 | struct device *tps_dev = to_tps6586x_dev(dev: &pdev->dev); |
224 | struct tps6586x_rtc *rtc; |
225 | int ret; |
226 | |
227 | rtc = devm_kzalloc(dev: &pdev->dev, size: sizeof(*rtc), GFP_KERNEL); |
228 | if (!rtc) |
229 | return -ENOMEM; |
230 | |
231 | rtc->dev = &pdev->dev; |
232 | rtc->irq = platform_get_irq(pdev, 0); |
233 | |
234 | /* 1 kHz tick mode, enable tick counting */ |
235 | ret = tps6586x_update(dev: tps_dev, RTC_CTRL, |
236 | RTC_ENABLE | OSC_SRC_SEL | |
237 | ((TPS6586X_RTC_CL_SEL_1_5PF << CL_SEL_POS) & CL_SEL_MASK), |
238 | RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); |
239 | if (ret < 0) { |
240 | dev_err(&pdev->dev, "unable to start counter\n" ); |
241 | return ret; |
242 | } |
243 | |
244 | device_init_wakeup(dev: &pdev->dev, enable: 1); |
245 | |
246 | platform_set_drvdata(pdev, data: rtc); |
247 | rtc->rtc = devm_rtc_allocate_device(dev: &pdev->dev); |
248 | if (IS_ERR(ptr: rtc->rtc)) { |
249 | ret = PTR_ERR(ptr: rtc->rtc); |
250 | goto fail_rtc_register; |
251 | } |
252 | |
253 | rtc->rtc->ops = &tps6586x_rtc_ops; |
254 | rtc->rtc->range_max = (1ULL << 30) - 1; /* 30-bit seconds */ |
255 | rtc->rtc->alarm_offset_max = ALM1_VALID_RANGE_IN_SEC; |
256 | rtc->rtc->start_secs = mktime64(year: 2009, mon: 1, day: 1, hour: 0, min: 0, sec: 0); |
257 | rtc->rtc->set_start_time = true; |
258 | |
259 | irq_set_status_flags(irq: rtc->irq, set: IRQ_NOAUTOEN); |
260 | |
261 | ret = devm_request_threaded_irq(dev: &pdev->dev, irq: rtc->irq, NULL, |
262 | thread_fn: tps6586x_rtc_irq, |
263 | IRQF_ONESHOT, |
264 | devname: dev_name(dev: &pdev->dev), dev_id: rtc); |
265 | if (ret < 0) { |
266 | dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n" , |
267 | rtc->irq, ret); |
268 | goto fail_rtc_register; |
269 | } |
270 | |
271 | ret = devm_rtc_register_device(rtc->rtc); |
272 | if (ret) |
273 | goto fail_rtc_register; |
274 | |
275 | return 0; |
276 | |
277 | fail_rtc_register: |
278 | tps6586x_update(dev: tps_dev, RTC_CTRL, val: 0, |
279 | RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); |
280 | return ret; |
281 | }; |
282 | |
283 | static void tps6586x_rtc_remove(struct platform_device *pdev) |
284 | { |
285 | struct device *tps_dev = to_tps6586x_dev(dev: &pdev->dev); |
286 | |
287 | tps6586x_update(dev: tps_dev, RTC_CTRL, val: 0, |
288 | RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); |
289 | } |
290 | |
291 | #ifdef CONFIG_PM_SLEEP |
292 | static int tps6586x_rtc_suspend(struct device *dev) |
293 | { |
294 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); |
295 | |
296 | if (device_may_wakeup(dev)) |
297 | enable_irq_wake(irq: rtc->irq); |
298 | return 0; |
299 | } |
300 | |
301 | static int tps6586x_rtc_resume(struct device *dev) |
302 | { |
303 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); |
304 | |
305 | if (device_may_wakeup(dev)) |
306 | disable_irq_wake(irq: rtc->irq); |
307 | return 0; |
308 | } |
309 | #endif |
310 | |
311 | static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_rtc_suspend, |
312 | tps6586x_rtc_resume); |
313 | |
314 | static struct platform_driver tps6586x_rtc_driver = { |
315 | .driver = { |
316 | .name = "tps6586x-rtc" , |
317 | .pm = &tps6586x_pm_ops, |
318 | }, |
319 | .probe = tps6586x_rtc_probe, |
320 | .remove_new = tps6586x_rtc_remove, |
321 | }; |
322 | module_platform_driver(tps6586x_rtc_driver); |
323 | |
324 | MODULE_ALIAS("platform:tps6586x-rtc" ); |
325 | MODULE_DESCRIPTION("TI TPS6586x RTC driver" ); |
326 | MODULE_AUTHOR("Laxman dewangan <ldewangan@nvidia.com>" ); |
327 | MODULE_LICENSE("GPL v2" ); |
328 | |