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