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