]>
Commit | Line | Data |
---|---|---|
97fb5e8d | 1 | // SPDX-License-Identifier: GPL-2.0-only |
9a9a54ad | 2 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. |
9a9a54ad | 3 | */ |
5a418558 | 4 | #include <linux/of.h> |
9a9a54ad AG |
5 | #include <linux/module.h> |
6 | #include <linux/init.h> | |
7 | #include <linux/rtc.h> | |
5d7dc4cf | 8 | #include <linux/platform_device.h> |
9a9a54ad | 9 | #include <linux/pm.h> |
5d7dc4cf | 10 | #include <linux/regmap.h> |
9a9a54ad AG |
11 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | |
13 | ||
9a9a54ad AG |
14 | /* RTC Register offsets from RTC CTRL REG */ |
15 | #define PM8XXX_ALARM_CTRL_OFFSET 0x01 | |
16 | #define PM8XXX_RTC_WRITE_OFFSET 0x02 | |
17 | #define PM8XXX_RTC_READ_OFFSET 0x06 | |
18 | #define PM8XXX_ALARM_RW_OFFSET 0x0A | |
19 | ||
20 | /* RTC_CTRL register bit fields */ | |
21 | #define PM8xxx_RTC_ENABLE BIT(7) | |
9a9a54ad | 22 | #define PM8xxx_RTC_ALARM_CLEAR BIT(0) |
121f54ef | 23 | #define PM8xxx_RTC_ALARM_ENABLE BIT(7) |
9a9a54ad AG |
24 | |
25 | #define NUM_8_BIT_RTC_REGS 0x4 | |
26 | ||
c8d523a4 SV |
27 | /** |
28 | * struct pm8xxx_rtc_regs - describe RTC registers per PMIC versions | |
29 | * @ctrl: base address of control register | |
30 | * @write: base address of write register | |
31 | * @read: base address of read register | |
32 | * @alarm_ctrl: base address of alarm control register | |
33 | * @alarm_ctrl2: base address of alarm control2 register | |
34 | * @alarm_rw: base address of alarm read-write register | |
35 | * @alarm_en: alarm enable mask | |
36 | */ | |
37 | struct pm8xxx_rtc_regs { | |
38 | unsigned int ctrl; | |
39 | unsigned int write; | |
40 | unsigned int read; | |
41 | unsigned int alarm_ctrl; | |
42 | unsigned int alarm_ctrl2; | |
43 | unsigned int alarm_rw; | |
44 | unsigned int alarm_en; | |
45 | }; | |
46 | ||
9a9a54ad AG |
47 | /** |
48 | * struct pm8xxx_rtc - rtc driver internal structure | |
49 | * @rtc: rtc device for this driver. | |
5d7dc4cf | 50 | * @regmap: regmap used to access RTC registers |
5a418558 | 51 | * @allow_set_time: indicates whether writing to the RTC is allowed |
9a9a54ad | 52 | * @rtc_alarm_irq: rtc alarm irq number. |
863d7b18 | 53 | * @regs: rtc registers description. |
9a9a54ad AG |
54 | * @rtc_dev: device structure. |
55 | * @ctrl_reg_lock: spinlock protecting access to ctrl_reg. | |
56 | */ | |
57 | struct pm8xxx_rtc { | |
58 | struct rtc_device *rtc; | |
5d7dc4cf | 59 | struct regmap *regmap; |
5a418558 | 60 | bool allow_set_time; |
9a9a54ad | 61 | int rtc_alarm_irq; |
c8d523a4 | 62 | const struct pm8xxx_rtc_regs *regs; |
9a9a54ad AG |
63 | struct device *rtc_dev; |
64 | spinlock_t ctrl_reg_lock; | |
65 | }; | |
66 | ||
9a9a54ad AG |
67 | /* |
68 | * Steps to write the RTC registers. | |
69 | * 1. Disable alarm if enabled. | |
83220bf3 MA |
70 | * 2. Disable rtc if enabled. |
71 | * 3. Write 0x00 to LSB. | |
72 | * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0]. | |
73 | * 5. Enable rtc if disabled in step 2. | |
74 | * 6. Enable alarm if disabled in step 1. | |
9a9a54ad AG |
75 | */ |
76 | static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) | |
77 | { | |
78 | int rc, i; | |
79 | unsigned long secs, irq_flags; | |
83220bf3 MA |
80 | u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, rtc_disabled = 0; |
81 | unsigned int ctrl_reg, rtc_ctrl_reg; | |
9a9a54ad | 82 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); |
c8d523a4 | 83 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
9a9a54ad | 84 | |
5a418558 JC |
85 | if (!rtc_dd->allow_set_time) |
86 | return -EACCES; | |
87 | ||
4c470b2f | 88 | secs = rtc_tm_to_time64(tm); |
9a9a54ad | 89 | |
83220bf3 MA |
90 | dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); |
91 | ||
9a9a54ad AG |
92 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { |
93 | value[i] = secs & 0xFF; | |
94 | secs >>= 8; | |
95 | } | |
96 | ||
9a9a54ad | 97 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); |
9a9a54ad | 98 | |
83220bf3 | 99 | rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); |
c8d523a4 SV |
100 | if (rc) |
101 | goto rtc_rw_fail; | |
102 | ||
103 | if (ctrl_reg & regs->alarm_en) { | |
9a9a54ad | 104 | alarm_enabled = 1; |
c8d523a4 | 105 | ctrl_reg &= ~regs->alarm_en; |
83220bf3 MA |
106 | rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); |
107 | if (rc) { | |
108 | dev_err(dev, "Write to RTC Alarm control register failed\n"); | |
109 | goto rtc_rw_fail; | |
110 | } | |
111 | } | |
112 | ||
113 | /* Disable RTC H/w before writing on RTC register */ | |
114 | rc = regmap_read(rtc_dd->regmap, regs->ctrl, &rtc_ctrl_reg); | |
115 | if (rc) | |
116 | goto rtc_rw_fail; | |
117 | ||
118 | if (rtc_ctrl_reg & PM8xxx_RTC_ENABLE) { | |
119 | rtc_disabled = 1; | |
120 | rtc_ctrl_reg &= ~PM8xxx_RTC_ENABLE; | |
121 | rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg); | |
5d7dc4cf | 122 | if (rc) { |
5bed811d | 123 | dev_err(dev, "Write to RTC control register failed\n"); |
9a9a54ad AG |
124 | goto rtc_rw_fail; |
125 | } | |
5bed811d | 126 | } |
9a9a54ad AG |
127 | |
128 | /* Write 0 to Byte[0] */ | |
c8d523a4 | 129 | rc = regmap_write(rtc_dd->regmap, regs->write, 0); |
5d7dc4cf | 130 | if (rc) { |
9a9a54ad AG |
131 | dev_err(dev, "Write to RTC write data register failed\n"); |
132 | goto rtc_rw_fail; | |
133 | } | |
134 | ||
135 | /* Write Byte[1], Byte[2], Byte[3] */ | |
c8d523a4 | 136 | rc = regmap_bulk_write(rtc_dd->regmap, regs->write + 1, |
5d7dc4cf JC |
137 | &value[1], sizeof(value) - 1); |
138 | if (rc) { | |
9a9a54ad AG |
139 | dev_err(dev, "Write to RTC write data register failed\n"); |
140 | goto rtc_rw_fail; | |
141 | } | |
142 | ||
143 | /* Write Byte[0] */ | |
c8d523a4 | 144 | rc = regmap_write(rtc_dd->regmap, regs->write, value[0]); |
5d7dc4cf | 145 | if (rc) { |
9a9a54ad AG |
146 | dev_err(dev, "Write to RTC write data register failed\n"); |
147 | goto rtc_rw_fail; | |
148 | } | |
149 | ||
83220bf3 MA |
150 | /* Enable RTC H/w after writing on RTC register */ |
151 | if (rtc_disabled) { | |
152 | rtc_ctrl_reg |= PM8xxx_RTC_ENABLE; | |
153 | rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg); | |
154 | if (rc) { | |
155 | dev_err(dev, "Write to RTC control register failed\n"); | |
156 | goto rtc_rw_fail; | |
157 | } | |
158 | } | |
159 | ||
9a9a54ad | 160 | if (alarm_enabled) { |
c8d523a4 | 161 | ctrl_reg |= regs->alarm_en; |
83220bf3 | 162 | rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); |
5d7dc4cf | 163 | if (rc) { |
83220bf3 | 164 | dev_err(dev, "Write to RTC Alarm control register failed\n"); |
9a9a54ad AG |
165 | goto rtc_rw_fail; |
166 | } | |
9a9a54ad AG |
167 | } |
168 | ||
169 | rtc_rw_fail: | |
c8d523a4 | 170 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); |
9a9a54ad AG |
171 | |
172 | return rc; | |
173 | } | |
174 | ||
175 | static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | |
176 | { | |
177 | int rc; | |
5d7dc4cf | 178 | u8 value[NUM_8_BIT_RTC_REGS]; |
9a9a54ad | 179 | unsigned long secs; |
5d7dc4cf | 180 | unsigned int reg; |
9a9a54ad | 181 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); |
c8d523a4 | 182 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
9a9a54ad | 183 | |
c8d523a4 | 184 | rc = regmap_bulk_read(rtc_dd->regmap, regs->read, value, sizeof(value)); |
5d7dc4cf | 185 | if (rc) { |
9a9a54ad AG |
186 | dev_err(dev, "RTC read data register failed\n"); |
187 | return rc; | |
188 | } | |
189 | ||
190 | /* | |
191 | * Read the LSB again and check if there has been a carry over. | |
192 | * If there is, redo the read operation. | |
193 | */ | |
c8d523a4 | 194 | rc = regmap_read(rtc_dd->regmap, regs->read, ®); |
9a9a54ad AG |
195 | if (rc < 0) { |
196 | dev_err(dev, "RTC read data register failed\n"); | |
197 | return rc; | |
198 | } | |
199 | ||
200 | if (unlikely(reg < value[0])) { | |
c8d523a4 | 201 | rc = regmap_bulk_read(rtc_dd->regmap, regs->read, |
5d7dc4cf JC |
202 | value, sizeof(value)); |
203 | if (rc) { | |
9a9a54ad AG |
204 | dev_err(dev, "RTC read data register failed\n"); |
205 | return rc; | |
206 | } | |
207 | } | |
208 | ||
e4228088 CIK |
209 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | |
210 | ((unsigned long)value[3] << 24); | |
9a9a54ad | 211 | |
4c470b2f | 212 | rtc_time64_to_tm(secs, tm); |
9a9a54ad | 213 | |
4f5ef6ee | 214 | dev_dbg(dev, "secs = %lu, h:m:s == %ptRt, y-m-d = %ptRdr\n", secs, tm, tm); |
9a9a54ad AG |
215 | |
216 | return 0; | |
217 | } | |
218 | ||
219 | static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |
220 | { | |
221 | int rc, i; | |
c8d523a4 SV |
222 | u8 value[NUM_8_BIT_RTC_REGS]; |
223 | unsigned int ctrl_reg; | |
9a9a54ad AG |
224 | unsigned long secs, irq_flags; |
225 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | |
c8d523a4 | 226 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
9a9a54ad | 227 | |
4c470b2f | 228 | secs = rtc_tm_to_time64(&alarm->time); |
9a9a54ad AG |
229 | |
230 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { | |
231 | value[i] = secs & 0xFF; | |
232 | secs >>= 8; | |
233 | } | |
234 | ||
235 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | |
236 | ||
c8d523a4 | 237 | rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value, |
5d7dc4cf JC |
238 | sizeof(value)); |
239 | if (rc) { | |
9a9a54ad AG |
240 | dev_err(dev, "Write to RTC ALARM register failed\n"); |
241 | goto rtc_rw_fail; | |
242 | } | |
243 | ||
c8d523a4 SV |
244 | rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); |
245 | if (rc) | |
246 | goto rtc_rw_fail; | |
5bed811d JC |
247 | |
248 | if (alarm->enabled) | |
c8d523a4 | 249 | ctrl_reg |= regs->alarm_en; |
5bed811d | 250 | else |
c8d523a4 | 251 | ctrl_reg &= ~regs->alarm_en; |
9a9a54ad | 252 | |
c8d523a4 | 253 | rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); |
5d7dc4cf | 254 | if (rc) { |
c8d523a4 | 255 | dev_err(dev, "Write to RTC alarm control register failed\n"); |
9a9a54ad AG |
256 | goto rtc_rw_fail; |
257 | } | |
258 | ||
4f5ef6ee AS |
259 | dev_dbg(dev, "Alarm Set for h:m:s=%ptRt, y-m-d=%ptRdr\n", |
260 | &alarm->time, &alarm->time); | |
9a9a54ad AG |
261 | rtc_rw_fail: |
262 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | |
263 | return rc; | |
264 | } | |
265 | ||
266 | static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |
267 | { | |
268 | int rc; | |
121f54ef | 269 | unsigned int ctrl_reg; |
9a9a54ad AG |
270 | u8 value[NUM_8_BIT_RTC_REGS]; |
271 | unsigned long secs; | |
272 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | |
c8d523a4 | 273 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
9a9a54ad | 274 | |
c8d523a4 | 275 | rc = regmap_bulk_read(rtc_dd->regmap, regs->alarm_rw, value, |
5d7dc4cf JC |
276 | sizeof(value)); |
277 | if (rc) { | |
9a9a54ad AG |
278 | dev_err(dev, "RTC alarm time read failed\n"); |
279 | return rc; | |
280 | } | |
281 | ||
e4228088 CIK |
282 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | |
283 | ((unsigned long)value[3] << 24); | |
9a9a54ad | 284 | |
4c470b2f | 285 | rtc_time64_to_tm(secs, &alarm->time); |
9a9a54ad | 286 | |
121f54ef GW |
287 | rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); |
288 | if (rc) { | |
289 | dev_err(dev, "Read from RTC alarm control register failed\n"); | |
290 | return rc; | |
291 | } | |
292 | alarm->enabled = !!(ctrl_reg & PM8xxx_RTC_ALARM_ENABLE); | |
293 | ||
4f5ef6ee AS |
294 | dev_dbg(dev, "Alarm set for - h:m:s=%ptRt, y-m-d=%ptRdr\n", |
295 | &alarm->time, &alarm->time); | |
9a9a54ad AG |
296 | |
297 | return 0; | |
298 | } | |
299 | ||
300 | static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | |
301 | { | |
302 | int rc; | |
303 | unsigned long irq_flags; | |
304 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | |
c8d523a4 SV |
305 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
306 | unsigned int ctrl_reg; | |
34ce2977 | 307 | u8 value[NUM_8_BIT_RTC_REGS] = {0}; |
9a9a54ad AG |
308 | |
309 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | |
5bed811d | 310 | |
c8d523a4 SV |
311 | rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); |
312 | if (rc) | |
313 | goto rtc_rw_fail; | |
5bed811d JC |
314 | |
315 | if (enable) | |
c8d523a4 | 316 | ctrl_reg |= regs->alarm_en; |
5bed811d | 317 | else |
c8d523a4 | 318 | ctrl_reg &= ~regs->alarm_en; |
9a9a54ad | 319 | |
c8d523a4 | 320 | rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); |
5d7dc4cf | 321 | if (rc) { |
9a9a54ad AG |
322 | dev_err(dev, "Write to RTC control register failed\n"); |
323 | goto rtc_rw_fail; | |
324 | } | |
325 | ||
34ce2977 | 326 | /* Clear Alarm register */ |
327 | if (!enable) { | |
328 | rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value, | |
329 | sizeof(value)); | |
330 | if (rc) { | |
331 | dev_err(dev, "Clear RTC ALARM register failed\n"); | |
332 | goto rtc_rw_fail; | |
333 | } | |
334 | } | |
335 | ||
9a9a54ad AG |
336 | rtc_rw_fail: |
337 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | |
338 | return rc; | |
339 | } | |
340 | ||
5a418558 | 341 | static const struct rtc_class_ops pm8xxx_rtc_ops = { |
9a9a54ad | 342 | .read_time = pm8xxx_rtc_read_time, |
5a418558 | 343 | .set_time = pm8xxx_rtc_set_time, |
9a9a54ad AG |
344 | .set_alarm = pm8xxx_rtc_set_alarm, |
345 | .read_alarm = pm8xxx_rtc_read_alarm, | |
346 | .alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable, | |
347 | }; | |
348 | ||
349 | static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) | |
350 | { | |
351 | struct pm8xxx_rtc *rtc_dd = dev_id; | |
c8d523a4 | 352 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
5d7dc4cf | 353 | unsigned int ctrl_reg; |
9a9a54ad | 354 | int rc; |
9a9a54ad AG |
355 | |
356 | rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF); | |
357 | ||
51317975 | 358 | spin_lock(&rtc_dd->ctrl_reg_lock); |
9a9a54ad AG |
359 | |
360 | /* Clear the alarm enable bit */ | |
c8d523a4 SV |
361 | rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg); |
362 | if (rc) { | |
51317975 | 363 | spin_unlock(&rtc_dd->ctrl_reg_lock); |
c8d523a4 SV |
364 | goto rtc_alarm_handled; |
365 | } | |
366 | ||
367 | ctrl_reg &= ~regs->alarm_en; | |
9a9a54ad | 368 | |
c8d523a4 | 369 | rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg); |
5d7dc4cf | 370 | if (rc) { |
51317975 | 371 | spin_unlock(&rtc_dd->ctrl_reg_lock); |
5bed811d | 372 | dev_err(rtc_dd->rtc_dev, |
c8d523a4 | 373 | "Write to alarm control register failed\n"); |
9a9a54ad AG |
374 | goto rtc_alarm_handled; |
375 | } | |
376 | ||
51317975 | 377 | spin_unlock(&rtc_dd->ctrl_reg_lock); |
9a9a54ad AG |
378 | |
379 | /* Clear RTC alarm register */ | |
c8d523a4 | 380 | rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl2, &ctrl_reg); |
5d7dc4cf | 381 | if (rc) { |
5bed811d | 382 | dev_err(rtc_dd->rtc_dev, |
c8d523a4 | 383 | "RTC Alarm control2 register read failed\n"); |
9a9a54ad AG |
384 | goto rtc_alarm_handled; |
385 | } | |
386 | ||
c8d523a4 SV |
387 | ctrl_reg |= PM8xxx_RTC_ALARM_CLEAR; |
388 | rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl2, ctrl_reg); | |
5d7dc4cf | 389 | if (rc) |
5bed811d | 390 | dev_err(rtc_dd->rtc_dev, |
c8d523a4 | 391 | "Write to RTC Alarm control2 register failed\n"); |
9a9a54ad AG |
392 | |
393 | rtc_alarm_handled: | |
394 | return IRQ_HANDLED; | |
395 | } | |
396 | ||
c8d523a4 SV |
397 | static int pm8xxx_rtc_enable(struct pm8xxx_rtc *rtc_dd) |
398 | { | |
399 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; | |
400 | unsigned int ctrl_reg; | |
401 | int rc; | |
402 | ||
403 | /* Check if the RTC is on, else turn it on */ | |
404 | rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg); | |
405 | if (rc) | |
406 | return rc; | |
407 | ||
408 | if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) { | |
409 | ctrl_reg |= PM8xxx_RTC_ENABLE; | |
410 | rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg); | |
411 | if (rc) | |
412 | return rc; | |
413 | } | |
414 | ||
415 | return 0; | |
416 | } | |
417 | ||
418 | static const struct pm8xxx_rtc_regs pm8921_regs = { | |
419 | .ctrl = 0x11d, | |
420 | .write = 0x11f, | |
421 | .read = 0x123, | |
422 | .alarm_rw = 0x127, | |
423 | .alarm_ctrl = 0x11d, | |
424 | .alarm_ctrl2 = 0x11e, | |
425 | .alarm_en = BIT(1), | |
426 | }; | |
427 | ||
428 | static const struct pm8xxx_rtc_regs pm8058_regs = { | |
429 | .ctrl = 0x1e8, | |
430 | .write = 0x1ea, | |
431 | .read = 0x1ee, | |
432 | .alarm_rw = 0x1f2, | |
433 | .alarm_ctrl = 0x1e8, | |
434 | .alarm_ctrl2 = 0x1e9, | |
435 | .alarm_en = BIT(1), | |
436 | }; | |
437 | ||
438 | static const struct pm8xxx_rtc_regs pm8941_regs = { | |
439 | .ctrl = 0x6046, | |
440 | .write = 0x6040, | |
441 | .read = 0x6048, | |
442 | .alarm_rw = 0x6140, | |
443 | .alarm_ctrl = 0x6146, | |
444 | .alarm_ctrl2 = 0x6148, | |
445 | .alarm_en = BIT(7), | |
446 | }; | |
447 | ||
c8f0ca8b | 448 | static const struct pm8xxx_rtc_regs pmk8350_regs = { |
449 | .ctrl = 0x6146, | |
450 | .write = 0x6140, | |
451 | .read = 0x6148, | |
452 | .alarm_rw = 0x6240, | |
453 | .alarm_ctrl = 0x6246, | |
454 | .alarm_ctrl2 = 0x6248, | |
455 | .alarm_en = BIT(7), | |
456 | }; | |
457 | ||
5a418558 JC |
458 | /* |
459 | * Hardcoded RTC bases until IORESOURCE_REG mapping is figured out | |
460 | */ | |
461 | static const struct of_device_id pm8xxx_id_table[] = { | |
c8d523a4 | 462 | { .compatible = "qcom,pm8921-rtc", .data = &pm8921_regs }, |
08655bca | 463 | { .compatible = "qcom,pm8018-rtc", .data = &pm8921_regs }, |
c8d523a4 SV |
464 | { .compatible = "qcom,pm8058-rtc", .data = &pm8058_regs }, |
465 | { .compatible = "qcom,pm8941-rtc", .data = &pm8941_regs }, | |
c8f0ca8b | 466 | { .compatible = "qcom,pmk8350-rtc", .data = &pmk8350_regs }, |
5a418558 JC |
467 | { }, |
468 | }; | |
469 | MODULE_DEVICE_TABLE(of, pm8xxx_id_table); | |
470 | ||
5a167f45 | 471 | static int pm8xxx_rtc_probe(struct platform_device *pdev) |
9a9a54ad AG |
472 | { |
473 | int rc; | |
9a9a54ad | 474 | struct pm8xxx_rtc *rtc_dd; |
5a418558 | 475 | const struct of_device_id *match; |
9a9a54ad | 476 | |
5a418558 JC |
477 | match = of_match_node(pm8xxx_id_table, pdev->dev.of_node); |
478 | if (!match) | |
479 | return -ENXIO; | |
9a9a54ad | 480 | |
c417299c | 481 | rtc_dd = devm_kzalloc(&pdev->dev, sizeof(*rtc_dd), GFP_KERNEL); |
49ae425b | 482 | if (rtc_dd == NULL) |
9a9a54ad | 483 | return -ENOMEM; |
9a9a54ad AG |
484 | |
485 | /* Initialise spinlock to protect RTC control register */ | |
486 | spin_lock_init(&rtc_dd->ctrl_reg_lock); | |
487 | ||
5d7dc4cf JC |
488 | rtc_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL); |
489 | if (!rtc_dd->regmap) { | |
490 | dev_err(&pdev->dev, "Parent regmap unavailable.\n"); | |
491 | return -ENXIO; | |
492 | } | |
493 | ||
9a9a54ad | 494 | rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0); |
faac9102 | 495 | if (rtc_dd->rtc_alarm_irq < 0) |
c417299c | 496 | return -ENXIO; |
9a9a54ad | 497 | |
5a418558 JC |
498 | rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node, |
499 | "allow-set-time"); | |
9a9a54ad | 500 | |
c8d523a4 | 501 | rtc_dd->regs = match->data; |
9a9a54ad AG |
502 | rtc_dd->rtc_dev = &pdev->dev; |
503 | ||
c8d523a4 SV |
504 | rc = pm8xxx_rtc_enable(rtc_dd); |
505 | if (rc) | |
c417299c | 506 | return rc; |
9a9a54ad AG |
507 | |
508 | platform_set_drvdata(pdev, rtc_dd); | |
509 | ||
fda9909d JC |
510 | device_init_wakeup(&pdev->dev, 1); |
511 | ||
9a9a54ad | 512 | /* Register the RTC device */ |
d5d55b70 AB |
513 | rtc_dd->rtc = devm_rtc_allocate_device(&pdev->dev); |
514 | if (IS_ERR(rtc_dd->rtc)) | |
c417299c | 515 | return PTR_ERR(rtc_dd->rtc); |
d5d55b70 AB |
516 | |
517 | rtc_dd->rtc->ops = &pm8xxx_rtc_ops; | |
3cfe5260 | 518 | rtc_dd->rtc->range_max = U32_MAX; |
9a9a54ad AG |
519 | |
520 | /* Request the alarm IRQ */ | |
bffcbc08 JC |
521 | rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->rtc_alarm_irq, |
522 | pm8xxx_alarm_trigger, | |
523 | IRQF_TRIGGER_RISING, | |
524 | "pm8xxx_rtc_alarm", rtc_dd); | |
9a9a54ad AG |
525 | if (rc < 0) { |
526 | dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc); | |
c417299c | 527 | return rc; |
9a9a54ad AG |
528 | } |
529 | ||
fdcfd854 | 530 | return devm_rtc_register_device(rtc_dd->rtc); |
9a9a54ad AG |
531 | } |
532 | ||
9a9a54ad AG |
533 | #ifdef CONFIG_PM_SLEEP |
534 | static int pm8xxx_rtc_resume(struct device *dev) | |
535 | { | |
536 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | |
537 | ||
538 | if (device_may_wakeup(dev)) | |
539 | disable_irq_wake(rtc_dd->rtc_alarm_irq); | |
540 | ||
541 | return 0; | |
542 | } | |
543 | ||
544 | static int pm8xxx_rtc_suspend(struct device *dev) | |
545 | { | |
546 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | |
547 | ||
548 | if (device_may_wakeup(dev)) | |
549 | enable_irq_wake(rtc_dd->rtc_alarm_irq); | |
550 | ||
551 | return 0; | |
552 | } | |
553 | #endif | |
554 | ||
5bed811d JC |
555 | static SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, |
556 | pm8xxx_rtc_suspend, | |
557 | pm8xxx_rtc_resume); | |
9a9a54ad AG |
558 | |
559 | static struct platform_driver pm8xxx_rtc_driver = { | |
560 | .probe = pm8xxx_rtc_probe, | |
9a9a54ad | 561 | .driver = { |
5a418558 | 562 | .name = "rtc-pm8xxx", |
5a418558 JC |
563 | .pm = &pm8xxx_rtc_pm_ops, |
564 | .of_match_table = pm8xxx_id_table, | |
9a9a54ad AG |
565 | }, |
566 | }; | |
567 | ||
0c4eae66 | 568 | module_platform_driver(pm8xxx_rtc_driver); |
9a9a54ad AG |
569 | |
570 | MODULE_ALIAS("platform:rtc-pm8xxx"); | |
571 | MODULE_DESCRIPTION("PMIC8xxx RTC driver"); | |
572 | MODULE_LICENSE("GPL v2"); | |
573 | MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>"); |