LCOV - code coverage report
Current view: top level - arch/x86/kernel - rtc.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 20 62 32.3 %
Date: 2021-04-22 12:43:58 Functions: 4 7 57.1 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * RTC related functions
       4             :  */
       5             : #include <linux/platform_device.h>
       6             : #include <linux/mc146818rtc.h>
       7             : #include <linux/acpi.h>
       8             : #include <linux/bcd.h>
       9             : #include <linux/export.h>
      10             : #include <linux/pnp.h>
      11             : #include <linux/of.h>
      12             : 
      13             : #include <asm/vsyscall.h>
      14             : #include <asm/x86_init.h>
      15             : #include <asm/time.h>
      16             : #include <asm/intel-mid.h>
      17             : #include <asm/setup.h>
      18             : 
      19             : #ifdef CONFIG_X86_32
      20             : /*
      21             :  * This is a special lock that is owned by the CPU and holds the index
      22             :  * register we are working with.  It is required for NMI access to the
      23             :  * CMOS/RTC registers.  See include/asm-i386/mc146818rtc.h for details.
      24             :  */
      25             : volatile unsigned long cmos_lock;
      26             : EXPORT_SYMBOL(cmos_lock);
      27             : #endif /* CONFIG_X86_32 */
      28             : 
      29             : /* For two digit years assume time is always after that */
      30             : #define CMOS_YEARS_OFFS 2000
      31             : 
      32             : DEFINE_SPINLOCK(rtc_lock);
      33             : EXPORT_SYMBOL(rtc_lock);
      34             : 
      35             : /*
      36             :  * In order to set the CMOS clock precisely, set_rtc_mmss has to be
      37             :  * called 500 ms after the second nowtime has started, because when
      38             :  * nowtime is written into the registers of the CMOS clock, it will
      39             :  * jump to the next second precisely 500 ms later. Check the Motorola
      40             :  * MC146818A or Dallas DS12887 data sheet for details.
      41             :  */
      42           0 : int mach_set_rtc_mmss(const struct timespec64 *now)
      43             : {
      44           0 :         unsigned long long nowtime = now->tv_sec;
      45           0 :         struct rtc_time tm;
      46           0 :         int retval = 0;
      47             : 
      48           0 :         rtc_time64_to_tm(nowtime, &tm);
      49           0 :         if (!rtc_valid_tm(&tm)) {
      50           0 :                 retval = mc146818_set_time(&tm);
      51           0 :                 if (retval)
      52           0 :                         printk(KERN_ERR "%s: RTC write failed with error %d\n",
      53             :                                __func__, retval);
      54             :         } else {
      55           0 :                 printk(KERN_ERR
      56             :                        "%s: Invalid RTC value: write of %llx to RTC failed\n",
      57             :                         __func__, nowtime);
      58           0 :                 retval = -EINVAL;
      59             :         }
      60           0 :         return retval;
      61             : }
      62             : 
      63           0 : void mach_get_cmos_time(struct timespec64 *now)
      64             : {
      65           0 :         unsigned int status, year, mon, day, hour, min, sec, century = 0;
      66           0 :         unsigned long flags;
      67             : 
      68             :         /*
      69             :          * If pm_trace abused the RTC as storage, set the timespec to 0,
      70             :          * which tells the caller that this RTC value is unusable.
      71             :          */
      72           0 :         if (!pm_trace_rtc_valid()) {
      73             :                 now->tv_sec = now->tv_nsec = 0;
      74             :                 return;
      75             :         }
      76             : 
      77           0 :         spin_lock_irqsave(&rtc_lock, flags);
      78             : 
      79             :         /*
      80             :          * If UIP is clear, then we have >= 244 microseconds before
      81             :          * RTC registers will be updated.  Spec sheet says that this
      82             :          * is the reliable way to read RTC - registers. If UIP is set
      83             :          * then the register access might be invalid.
      84             :          */
      85           0 :         while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
      86           0 :                 cpu_relax();
      87             : 
      88           0 :         sec = CMOS_READ(RTC_SECONDS);
      89           0 :         min = CMOS_READ(RTC_MINUTES);
      90           0 :         hour = CMOS_READ(RTC_HOURS);
      91           0 :         day = CMOS_READ(RTC_DAY_OF_MONTH);
      92           0 :         mon = CMOS_READ(RTC_MONTH);
      93           0 :         year = CMOS_READ(RTC_YEAR);
      94             : 
      95             : #ifdef CONFIG_ACPI
      96             :         if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
      97             :             acpi_gbl_FADT.century)
      98             :                 century = CMOS_READ(acpi_gbl_FADT.century);
      99             : #endif
     100             : 
     101           0 :         status = CMOS_READ(RTC_CONTROL);
     102           0 :         WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY));
     103             : 
     104           0 :         spin_unlock_irqrestore(&rtc_lock, flags);
     105             : 
     106           0 :         if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) {
     107           0 :                 sec = bcd2bin(sec);
     108           0 :                 min = bcd2bin(min);
     109           0 :                 hour = bcd2bin(hour);
     110           0 :                 day = bcd2bin(day);
     111           0 :                 mon = bcd2bin(mon);
     112           0 :                 year = bcd2bin(year);
     113             :         }
     114             : 
     115           0 :         if (century) {
     116             :                 century = bcd2bin(century);
     117             :                 year += century * 100;
     118             :         } else
     119           0 :                 year += CMOS_YEARS_OFFS;
     120             : 
     121           0 :         now->tv_sec = mktime64(year, mon, day, hour, min, sec);
     122           0 :         now->tv_nsec = 0;
     123             : }
     124             : 
     125             : /* Routines for accessing the CMOS RAM/RTC. */
     126           1 : unsigned char rtc_cmos_read(unsigned char addr)
     127             : {
     128           1 :         unsigned char val;
     129             : 
     130           1 :         lock_cmos_prefix(addr);
     131           1 :         outb(addr, RTC_PORT(0));
     132           1 :         val = inb(RTC_PORT(1));
     133           1 :         lock_cmos_suffix(addr);
     134             : 
     135           0 :         return val;
     136             : }
     137             : EXPORT_SYMBOL(rtc_cmos_read);
     138             : 
     139           6 : void rtc_cmos_write(unsigned char val, unsigned char addr)
     140             : {
     141           6 :         lock_cmos_prefix(addr);
     142           6 :         outb(addr, RTC_PORT(0));
     143           6 :         outb(val, RTC_PORT(1));
     144           6 :         lock_cmos_suffix(addr);
     145           6 : }
     146             : EXPORT_SYMBOL(rtc_cmos_write);
     147             : 
     148           0 : int update_persistent_clock64(struct timespec64 now)
     149             : {
     150           0 :         return x86_platform.set_wallclock(&now);
     151             : }
     152             : 
     153             : /* not static: needed by APM */
     154           1 : void read_persistent_clock64(struct timespec64 *ts)
     155             : {
     156           1 :         x86_platform.get_wallclock(ts);
     157           1 : }
     158             : 
     159             : 
     160             : static struct resource rtc_resources[] = {
     161             :         [0] = {
     162             :                 .start  = RTC_PORT(0),
     163             :                 .end    = RTC_PORT(1),
     164             :                 .flags  = IORESOURCE_IO,
     165             :         },
     166             :         [1] = {
     167             :                 .start  = RTC_IRQ,
     168             :                 .end    = RTC_IRQ,
     169             :                 .flags  = IORESOURCE_IRQ,
     170             :         }
     171             : };
     172             : 
     173             : static struct platform_device rtc_device = {
     174             :         .name           = "rtc_cmos",
     175             :         .id             = -1,
     176             :         .resource       = rtc_resources,
     177             :         .num_resources  = ARRAY_SIZE(rtc_resources),
     178             : };
     179             : 
     180           1 : static __init int add_rtc_cmos(void)
     181             : {
     182             : #ifdef CONFIG_PNP
     183             :         static const char * const ids[] __initconst =
     184             :             { "PNP0b00", "PNP0b01", "PNP0b02", };
     185             :         struct pnp_dev *dev;
     186             :         struct pnp_id *id;
     187             :         int i;
     188             : 
     189             :         pnp_for_each_dev(dev) {
     190             :                 for (id = dev->id; id; id = id->next) {
     191             :                         for (i = 0; i < ARRAY_SIZE(ids); i++) {
     192             :                                 if (compare_pnp_id(id, ids[i]) != 0)
     193             :                                         return 0;
     194             :                         }
     195             :                 }
     196             :         }
     197             : #endif
     198           1 :         if (!x86_platform.legacy.rtc)
     199             :                 return -ENODEV;
     200             : 
     201           1 :         platform_device_register(&rtc_device);
     202           1 :         dev_info(&rtc_device.dev,
     203             :                  "registered platform RTC device (no PNP device found)\n");
     204             : 
     205           1 :         return 0;
     206             : }
     207             : device_initcall(add_rtc_cmos);

Generated by: LCOV version 1.14