forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/drivers/rtc/rtc-cmos.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * RTC class driver for "CMOS RTC": PCs, ACPI, etc
34 *
45 * Copyright (C) 1996 Paul Gortmaker (drivers/char/rtc.c)
56 * Copyright (C) 2006 David Brownell (convert to new framework)
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License
9
- * as published by the Free Software Foundation; either version
10
- * 2 of the License, or (at your option) any later version.
117 */
128
139 /*
....@@ -226,6 +222,8 @@
226222
227223 static int cmos_read_time(struct device *dev, struct rtc_time *t)
228224 {
225
+ int ret;
226
+
229227 /*
230228 * If pm_trace abused the RTC for storage, set the timespec to 0,
231229 * which tells the caller that this RTC value is unusable.
....@@ -233,29 +231,64 @@
233231 if (!pm_trace_rtc_valid())
234232 return -EIO;
235233
236
- /* REVISIT: if the clock has a "century" register, use
237
- * that instead of the heuristic in mc146818_get_time().
238
- * That'll make Y3K compatility (year > 2070) easy!
239
- */
240
- mc146818_get_time(t);
234
+ ret = mc146818_get_time(t);
235
+ if (ret < 0) {
236
+ dev_err_ratelimited(dev, "unable to read current time\n");
237
+ return ret;
238
+ }
239
+
241240 return 0;
242241 }
243242
244243 static int cmos_set_time(struct device *dev, struct rtc_time *t)
245244 {
246
- /* REVISIT: set the "century" register if available
247
- *
248
- * NOTE: this ignores the issue whereby updating the seconds
245
+ /* NOTE: this ignores the issue whereby updating the seconds
249246 * takes effect exactly 500ms after we write the register.
250247 * (Also queueing and other delays before we get this far.)
251248 */
252249 return mc146818_set_time(t);
253250 }
254251
252
+struct cmos_read_alarm_callback_param {
253
+ struct cmos_rtc *cmos;
254
+ struct rtc_time *time;
255
+ unsigned char rtc_control;
256
+};
257
+
258
+static void cmos_read_alarm_callback(unsigned char __always_unused seconds,
259
+ void *param_in)
260
+{
261
+ struct cmos_read_alarm_callback_param *p =
262
+ (struct cmos_read_alarm_callback_param *)param_in;
263
+ struct rtc_time *time = p->time;
264
+
265
+ time->tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
266
+ time->tm_min = CMOS_READ(RTC_MINUTES_ALARM);
267
+ time->tm_hour = CMOS_READ(RTC_HOURS_ALARM);
268
+
269
+ if (p->cmos->day_alrm) {
270
+ /* ignore upper bits on readback per ACPI spec */
271
+ time->tm_mday = CMOS_READ(p->cmos->day_alrm) & 0x3f;
272
+ if (!time->tm_mday)
273
+ time->tm_mday = -1;
274
+
275
+ if (p->cmos->mon_alrm) {
276
+ time->tm_mon = CMOS_READ(p->cmos->mon_alrm);
277
+ if (!time->tm_mon)
278
+ time->tm_mon = -1;
279
+ }
280
+ }
281
+
282
+ p->rtc_control = CMOS_READ(RTC_CONTROL);
283
+}
284
+
255285 static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
256286 {
257287 struct cmos_rtc *cmos = dev_get_drvdata(dev);
258
- unsigned char rtc_control;
288
+ struct cmos_read_alarm_callback_param p = {
289
+ .cmos = cmos,
290
+ .time = &t->time,
291
+ };
259292
260293 /* This not only a rtc_op, but also called directly */
261294 if (!is_valid_irq(cmos->irq))
....@@ -266,28 +299,18 @@
266299 * the future.
267300 */
268301
269
- spin_lock_irq(&rtc_lock);
270
- t->time.tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
271
- t->time.tm_min = CMOS_READ(RTC_MINUTES_ALARM);
272
- t->time.tm_hour = CMOS_READ(RTC_HOURS_ALARM);
302
+ /* Some Intel chipsets disconnect the alarm registers when the clock
303
+ * update is in progress - during this time reads return bogus values
304
+ * and writes may fail silently. See for example "7th Generation IntelĀ®
305
+ * Processor Family I/O for U/Y Platforms [...] Datasheet", section
306
+ * 27.7.1
307
+ *
308
+ * Use the mc146818_avoid_UIP() function to avoid this.
309
+ */
310
+ if (!mc146818_avoid_UIP(cmos_read_alarm_callback, &p))
311
+ return -EIO;
273312
274
- if (cmos->day_alrm) {
275
- /* ignore upper bits on readback per ACPI spec */
276
- t->time.tm_mday = CMOS_READ(cmos->day_alrm) & 0x3f;
277
- if (!t->time.tm_mday)
278
- t->time.tm_mday = -1;
279
-
280
- if (cmos->mon_alrm) {
281
- t->time.tm_mon = CMOS_READ(cmos->mon_alrm);
282
- if (!t->time.tm_mon)
283
- t->time.tm_mon = -1;
284
- }
285
- }
286
-
287
- rtc_control = CMOS_READ(RTC_CONTROL);
288
- spin_unlock_irq(&rtc_lock);
289
-
290
- if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
313
+ if (!(p.rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
291314 if (((unsigned)t->time.tm_sec) < 0x60)
292315 t->time.tm_sec = bcd2bin(t->time.tm_sec);
293316 else
....@@ -316,7 +339,7 @@
316339 }
317340 }
318341
319
- t->enabled = !!(rtc_control & RTC_AIE);
342
+ t->enabled = !!(p.rtc_control & RTC_AIE);
320343 t->pending = 0;
321344
322345 return 0;
....@@ -447,10 +470,57 @@
447470 return 0;
448471 }
449472
473
+struct cmos_set_alarm_callback_param {
474
+ struct cmos_rtc *cmos;
475
+ unsigned char mon, mday, hrs, min, sec;
476
+ struct rtc_wkalrm *t;
477
+};
478
+
479
+/* Note: this function may be executed by mc146818_avoid_UIP() more then
480
+ * once
481
+ */
482
+static void cmos_set_alarm_callback(unsigned char __always_unused seconds,
483
+ void *param_in)
484
+{
485
+ struct cmos_set_alarm_callback_param *p =
486
+ (struct cmos_set_alarm_callback_param *)param_in;
487
+
488
+ /* next rtc irq must not be from previous alarm setting */
489
+ cmos_irq_disable(p->cmos, RTC_AIE);
490
+
491
+ /* update alarm */
492
+ CMOS_WRITE(p->hrs, RTC_HOURS_ALARM);
493
+ CMOS_WRITE(p->min, RTC_MINUTES_ALARM);
494
+ CMOS_WRITE(p->sec, RTC_SECONDS_ALARM);
495
+
496
+ /* the system may support an "enhanced" alarm */
497
+ if (p->cmos->day_alrm) {
498
+ CMOS_WRITE(p->mday, p->cmos->day_alrm);
499
+ if (p->cmos->mon_alrm)
500
+ CMOS_WRITE(p->mon, p->cmos->mon_alrm);
501
+ }
502
+
503
+ if (use_hpet_alarm()) {
504
+ /*
505
+ * FIXME the HPET alarm glue currently ignores day_alrm
506
+ * and mon_alrm ...
507
+ */
508
+ hpet_set_alarm_time(p->t->time.tm_hour, p->t->time.tm_min,
509
+ p->t->time.tm_sec);
510
+ }
511
+
512
+ if (p->t->enabled)
513
+ cmos_irq_enable(p->cmos, RTC_AIE);
514
+}
515
+
450516 static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
451517 {
452518 struct cmos_rtc *cmos = dev_get_drvdata(dev);
453
- unsigned char mon, mday, hrs, min, sec, rtc_control;
519
+ struct cmos_set_alarm_callback_param p = {
520
+ .cmos = cmos,
521
+ .t = t
522
+ };
523
+ unsigned char rtc_control;
454524 int ret;
455525
456526 /* This not only a rtc_op, but also called directly */
....@@ -461,11 +531,11 @@
461531 if (ret < 0)
462532 return ret;
463533
464
- mon = t->time.tm_mon + 1;
465
- mday = t->time.tm_mday;
466
- hrs = t->time.tm_hour;
467
- min = t->time.tm_min;
468
- sec = t->time.tm_sec;
534
+ p.mon = t->time.tm_mon + 1;
535
+ p.mday = t->time.tm_mday;
536
+ p.hrs = t->time.tm_hour;
537
+ p.min = t->time.tm_min;
538
+ p.sec = t->time.tm_sec;
469539
470540 spin_lock_irq(&rtc_lock);
471541 rtc_control = CMOS_READ(RTC_CONTROL);
....@@ -473,43 +543,21 @@
473543
474544 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
475545 /* Writing 0xff means "don't care" or "match all". */
476
- mon = (mon <= 12) ? bin2bcd(mon) : 0xff;
477
- mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
478
- hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff;
479
- min = (min < 60) ? bin2bcd(min) : 0xff;
480
- sec = (sec < 60) ? bin2bcd(sec) : 0xff;
546
+ p.mon = (p.mon <= 12) ? bin2bcd(p.mon) : 0xff;
547
+ p.mday = (p.mday >= 1 && p.mday <= 31) ? bin2bcd(p.mday) : 0xff;
548
+ p.hrs = (p.hrs < 24) ? bin2bcd(p.hrs) : 0xff;
549
+ p.min = (p.min < 60) ? bin2bcd(p.min) : 0xff;
550
+ p.sec = (p.sec < 60) ? bin2bcd(p.sec) : 0xff;
481551 }
482552
483
- spin_lock_irq(&rtc_lock);
484
-
485
- /* next rtc irq must not be from previous alarm setting */
486
- cmos_irq_disable(cmos, RTC_AIE);
487
-
488
- /* update alarm */
489
- CMOS_WRITE(hrs, RTC_HOURS_ALARM);
490
- CMOS_WRITE(min, RTC_MINUTES_ALARM);
491
- CMOS_WRITE(sec, RTC_SECONDS_ALARM);
492
-
493
- /* the system may support an "enhanced" alarm */
494
- if (cmos->day_alrm) {
495
- CMOS_WRITE(mday, cmos->day_alrm);
496
- if (cmos->mon_alrm)
497
- CMOS_WRITE(mon, cmos->mon_alrm);
498
- }
499
-
500
- if (use_hpet_alarm()) {
501
- /*
502
- * FIXME the HPET alarm glue currently ignores day_alrm
503
- * and mon_alrm ...
504
- */
505
- hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min,
506
- t->time.tm_sec);
507
- }
508
-
509
- if (t->enabled)
510
- cmos_irq_enable(cmos, RTC_AIE);
511
-
512
- spin_unlock_irq(&rtc_lock);
553
+ /*
554
+ * Some Intel chipsets disconnect the alarm registers when the clock
555
+ * update is in progress - during this time writes fail silently.
556
+ *
557
+ * Use mc146818_avoid_UIP() to avoid this.
558
+ */
559
+ if (!mc146818_avoid_UIP(cmos_set_alarm_callback, &p))
560
+ return -EIO;
513561
514562 cmos->alarm_expires = rtc_tm_to_time64(&t->time);
515563
....@@ -809,6 +857,12 @@
809857
810858 rename_region(ports, dev_name(&cmos_rtc.rtc->dev));
811859
860
+ if (!mc146818_does_rtc_work()) {
861
+ dev_warn(dev, "broken or not accessible\n");
862
+ retval = -ENXIO;
863
+ goto cleanup1;
864
+ }
865
+
812866 spin_lock_irq(&rtc_lock);
813867
814868 if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) {
....@@ -1012,6 +1066,7 @@
10121066 enable_irq_wake(cmos->irq);
10131067 }
10141068
1069
+ memset(&cmos->saved_wkalrm, 0, sizeof(struct rtc_wkalrm));
10151070 cmos_read_alarm(dev, &cmos->saved_wkalrm);
10161071
10171072 dev_dbg(dev, "suspend%s, ctrl %02x\n",
....@@ -1056,10 +1111,13 @@
10561111 * ACK the rtc irq here
10571112 */
10581113 if (t_now >= cmos->alarm_expires && cmos_use_acpi_alarm()) {
1114
+ local_irq_disable();
10591115 cmos_interrupt(0, (void *)cmos->rtc);
1116
+ local_irq_enable();
10601117 return;
10611118 }
10621119
1120
+ memset(&current_alarm, 0, sizeof(struct rtc_wkalrm));
10631121 cmos_read_alarm(dev, &current_alarm);
10641122 t_current_expires = rtc_tm_to_time64(&current_alarm.time);
10651123 t_saved_expires = rtc_tm_to_time64(&cmos->saved_wkalrm.time);
....@@ -1204,8 +1262,6 @@
12041262 /* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */
12051263 static void use_acpi_alarm_quirks(void)
12061264 {
1207
- int year;
1208
-
12091265 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
12101266 return;
12111267
....@@ -1215,8 +1271,10 @@
12151271 if (!is_hpet_enabled())
12161272 return;
12171273
1218
- if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2015)
1219
- use_acpi_alarm = true;
1274
+ if (dmi_get_bios_year() < 2015)
1275
+ return;
1276
+
1277
+ use_acpi_alarm = true;
12201278 }
12211279 #else
12221280 static inline void use_acpi_alarm_quirks(void) { }
....@@ -1312,7 +1370,7 @@
13121370 * hardcode it on systems with a legacy PIC.
13131371 */
13141372 if (nr_legacy_irqs())
1315
- irq = 8;
1373
+ irq = RTC_IRQ;
13161374 #endif
13171375 return cmos_do_probe(&pnp->dev,
13181376 pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
....@@ -1352,7 +1410,7 @@
13521410 MODULE_DEVICE_TABLE(pnp, rtc_ids);
13531411
13541412 static struct pnp_driver cmos_pnp_driver = {
1355
- .name = (char *) driver_name,
1413
+ .name = driver_name,
13561414 .id_table = rtc_ids,
13571415 .probe = cmos_pnp_probe,
13581416 .remove = cmos_pnp_remove,