cregit-Linux how code gets into the kernel

Release 4.18 arch/x86/kernel/rtc.c

Directory: arch/x86/kernel
// SPDX-License-Identifier: GPL-2.0
/*
 * RTC related functions
 */
#include <linux/platform_device.h>
#include <linux/mc146818rtc.h>
#include <linux/acpi.h>
#include <linux/bcd.h>
#include <linux/export.h>
#include <linux/pnp.h>
#include <linux/of.h>

#include <asm/vsyscall.h>
#include <asm/x86_init.h>
#include <asm/time.h>
#include <asm/intel-mid.h>
#include <asm/setup.h>

#ifdef CONFIG_X86_32
/*
 * This is a special lock that is owned by the CPU and holds the index
 * register we are working with.  It is required for NMI access to the
 * CMOS/RTC registers.  See include/asm-i386/mc146818rtc.h for details.
 */

volatile unsigned long cmos_lock;
EXPORT_SYMBOL(cmos_lock);
#endif /* CONFIG_X86_32 */

/* For two digit years assume time is always after that */

#define CMOS_YEARS_OFFS 2000

DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);

/*
 * In order to set the CMOS clock precisely, set_rtc_mmss has to be
 * called 500 ms after the second nowtime has started, because when
 * nowtime is written into the registers of the CMOS clock, it will
 * jump to the next second precisely 500 ms later. Check the Motorola
 * MC146818A or Dallas DS12887 data sheet for details.
 */

int mach_set_rtc_mmss(const struct timespec64 *now) { unsigned long long nowtime = now->tv_sec; struct rtc_time tm; int retval = 0; rtc_time64_to_tm(nowtime, &tm); if (!rtc_valid_tm(&tm)) { retval = mc146818_set_time(&tm); if (retval) printk(KERN_ERR "%s: RTC write failed with error %d\n", __func__, retval); } else { printk(KERN_ERR "%s: Invalid RTC value: write of %llx to RTC failed\n", __func__, nowtime); retval = -EINVAL; } return retval; }

Contributors

PersonTokensPropCommitsCommitProp
Alan Cox4347.25%110.00%
Prarit Bhargava2325.27%110.00%
David Vrabel1112.09%110.00%
Jaswinder Singh Rajput55.49%110.00%
Benjamin Gaignard33.30%110.00%
Rasmus Villemoes22.20%110.00%
Arnd Bergmann22.20%220.00%
Adrian Bunk11.10%110.00%
Matt Fleming11.10%110.00%
Total91100.00%10100.00%


void mach_get_cmos_time(struct timespec64 *now) { unsigned int status, year, mon, day, hour, min, sec, century = 0; unsigned long flags; /* * If pm_trace abused the RTC as storage, set the timespec to 0, * which tells the caller that this RTC value is unusable. */ if (!pm_trace_rtc_valid()) { now->tv_sec = now->tv_nsec = 0; return; } spin_lock_irqsave(&rtc_lock, flags); /* * If UIP is clear, then we have >= 244 microseconds before * RTC registers will be updated. Spec sheet says that this * is the reliable way to read RTC - registers. If UIP is set * then the register access might be invalid. */ while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) cpu_relax(); sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); hour = CMOS_READ(RTC_HOURS); day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); #ifdef CONFIG_ACPI if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && acpi_gbl_FADT.century) century = CMOS_READ(acpi_gbl_FADT.century); #endif status = CMOS_READ(RTC_CONTROL); WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY)); spin_unlock_irqrestore(&rtc_lock, flags); if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) { sec = bcd2bin(sec); min = bcd2bin(min); hour = bcd2bin(hour); day = bcd2bin(day); mon = bcd2bin(mon); year = bcd2bin(year); } if (century) { century = bcd2bin(century); year += century * 100; } else year += CMOS_YEARS_OFFS; now->tv_sec = mktime64(year, mon, day, hour, min, sec); now->tv_nsec = 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen8731.41%222.22%
Alan Cox6924.91%111.11%
Thomas Gleixner4315.52%111.11%
Adrian Bunk217.58%111.11%
Matt Fleming207.22%111.11%
Chen Yu207.22%111.11%
David Vrabel155.42%111.11%
Arnd Bergmann20.72%111.11%
Total277100.00%9100.00%

/* Routines for accessing the CMOS RAM/RTC. */
unsigned char rtc_cmos_read(unsigned char addr) { unsigned char val; lock_cmos_prefix(addr); outb(addr, RTC_PORT(0)); val = inb(RTC_PORT(1)); lock_cmos_suffix(addr); return val; }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen4391.49%133.33%
Thomas Gleixner24.26%133.33%
David P. Reed24.26%133.33%
Total47100.00%3100.00%

EXPORT_SYMBOL(rtc_cmos_read);
void rtc_cmos_write(unsigned char val, unsigned char addr) { lock_cmos_prefix(addr); outb(addr, RTC_PORT(0)); outb(val, RTC_PORT(1)); lock_cmos_suffix(addr); }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen3990.70%133.33%
David P. Reed24.65%133.33%
Thomas Gleixner24.65%133.33%
Total43100.00%3100.00%

EXPORT_SYMBOL(rtc_cmos_write);
int update_persistent_clock64(struct timespec64 now) { return x86_platform.set_wallclock(&now); }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen950.00%120.00%
Feng Tang527.78%120.00%
Arnd Bergmann211.11%120.00%
David Vrabel15.56%120.00%
Matt Fleming15.56%120.00%
Total18100.00%5100.00%

/* not static: needed by APM */
void read_persistent_clock64(struct timespec64 *ts) { x86_platform.get_wallclock(ts); }

Contributors

PersonTokensPropCommitsCommitProp
Martin Schwidefsky635.29%120.00%
Andi Kleen529.41%120.00%
Arnd Bergmann211.76%120.00%
Feng Tang211.76%120.00%
David Vrabel211.76%120.00%
Total17100.00%5100.00%

static struct resource rtc_resources[] = { [0] = { .start = RTC_PORT(0), .end = RTC_PORT(1), .flags = IORESOURCE_IO, }, [1] = { .start = RTC_IRQ, .end = RTC_IRQ, .flags = IORESOURCE_IRQ, } }; static struct platform_device rtc_device = { .name = "rtc_cmos", .id = -1, .resource = rtc_resources, .num_resources = ARRAY_SIZE(rtc_resources), };
static __init int add_rtc_cmos(void) { #ifdef CONFIG_PNP static const char * const ids[] __initconst = { "PNP0b00", "PNP0b01", "PNP0b02", }; struct pnp_dev *dev; struct pnp_id *id; int i; pnp_for_each_dev(dev) { for (id = dev->id; id; id = id->next) { for (i = 0; i < ARRAY_SIZE(ids); i++) { if (compare_pnp_id(id, ids[i]) != 0) return 0; } } } #endif if (!x86_platform.legacy.rtc) return -ENODEV; platform_device_register(&rtc_device); dev_info(&rtc_device.dev, "registered platform RTC device (no PNP device found)\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Helgaas9268.15%116.67%
Stas Sergeev2921.48%116.67%
David Vrabel64.44%116.67%
Luis R. Rodriguez53.70%116.67%
Sebastian Andrzej Siewior21.48%116.67%
Andi Kleen10.74%116.67%
Total135100.00%6100.00%

device_initcall(add_rtc_cmos);

Overall Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen19724.53%413.33%
Stas Sergeev12615.69%13.33%
Alan Cox11414.20%13.33%
Björn Helgaas9211.46%13.33%
Thomas Gleixner8410.46%26.67%
David Vrabel354.36%26.67%
Prarit Bhargava263.24%13.33%
Adrian Bunk222.74%13.33%
Matt Fleming222.74%13.33%
Chen Yu202.49%13.33%
Jaswinder Singh Rajput121.49%13.33%
Feng Tang101.25%13.33%
Arnd Bergmann81.00%26.67%
Luis R. Rodriguez60.75%13.33%
Martin Schwidefsky60.75%13.33%
Sebastian Andrzej Siewior50.62%13.33%
David P. Reed40.50%13.33%
Paul Gortmaker30.37%13.33%
Benjamin Gaignard30.37%13.33%
Rasmus Villemoes20.25%13.33%
Ingo Molnar20.25%13.33%
Mathias Nyman20.25%13.33%
Greg Kroah-Hartman10.12%13.33%
Kuppuswamy Sathyanarayanan10.12%13.33%
Total803100.00%30100.00%
Directory: arch/x86/kernel
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.