// SPDX-License-Identifier: GPL-2.0-or-later
/*
* RTC class driver for "CMOS RTC": PCs, ACPI, etc
*
* Copyright (C) 1996 Paul Gortmaker (drivers/char/rtc.c)
* Copyright (C) 2006 David Brownell (convert to new framework)
*/
/*
* The original "cmos clock" chip was an MC146818 chip, now obsolete.
* That defined the register interface now provided by all PCs, some
* non-PC systems, and incorporated into ACPI. Modern PC chipsets
* integrate an MC146818 clone in their southbridge, and boards use
* that instead of discrete clones like the DS12887 or M48T86. There
* are also clones that connect using the LPC bus.
*
* That register API is also used directly by various other drivers
* (notably for integrated NVRAM), infrastructure (x86 has code to
* bypass the RTC framework, directly reading the RTC during boot
* and updating minutes/seconds for systems using NTP synch) and
* utilities (like userspace 'hwclock', if no /dev node exists).
*
* So **ALL** calls to CMOS_READ and CMOS_WRITE must be done with
* interrupts disabled, holding the global rtc_lock, to exclude those
* other drivers and utilities on correctly configured systems.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/log2.h>
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#ifdef CONFIG_X86
#include <asm/i8259.h>
#include <asm/processor.h>
#include <linux/dmi.h>
#endif
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <linux/mc146818rtc.h>
#ifdef CONFIG_ACPI
/*
* Use ACPI SCI to replace HPET interrupt for RTC Alarm event
*
* If cleared, ACPI SCI is only used to wake up the system from suspend
*
* If set, ACPI SCI is used to handle UIE/AIE and system wakeup
*/
static bool use_acpi_alarm;
module_param(use_acpi_alarm, bool, 0444);
static inline int cmos_use_acpi_alarm(void)
{
return use_acpi_alarm;
}
#else /* !CONFIG_ACPI */
static inline int cmos_use_acpi_alarm(void)
{
return 0;
}
#endif
struct cmos_rtc {
struct rtc_device *rtc;
struct device *dev;
int irq;
struct resource *iomem;
time64_t alarm_expires;
void (*wake_on)(struct device *);
void (*wake_off)(struct device *);
u8 enabled_wake;
u8 suspend_ctrl;
/* newer hardware extends the original register set */
u8 day_alrm;
u8 mon_alrm;
u8 century;
struct rtc_wkalrm saved_wkalrm;
};
/* both platform and pnp busses use negative numbers for invalid irqs */
#define is_valid_irq(n) ((n) > 0)
static const char driver_name[] = "rtc_cmos";
/* The RTC_INTR register may have e.g. RTC_PF set even if RTC_PIE is clear;
* always mask it against the irq enable bits in RTC_CONTROL. Bit values
* are the same: PF==PIE, AF=AIE, UF=UIE; so RTC_IRQMASK works with both.
*/
#define RTC_IRQMASK (RTC_PF | RTC_AF | RTC_UF)
static inline int is_intr(u8 rtc_intr)
{
if (!(rtc_intr & RTC_IRQF))
return 0;
return rtc_intr & RTC_IRQMASK;
}
/*----------------------------------------------------------------*/
/* Much modern x86 hardware has HPETs (10+ MHz timers) which, because
* many BIOS programmers don't set up "sane mode" IRQ routing, are mostly
* used in a broken "legacy replacement" mode. The breakage includes
* HPET #1 hijacking the IRQ for this RTC, and being unavailable for
* other (better) use.
*
* When that broken mode is in use, platform glue provides a partial
* emulation of hardware RTC IRQ facilities using HPET #1. We don't
* want to use HPET for anything except those IRQs though...
*/
#ifdef CONFIG_HPET_EMULATE_RTC
#include <asm/hpet.h>
#else
static inline int is_hpet_enabled(void)
{
return 0;
}
static inline int hpet_mask_rtc_irq_bit(unsigned long mask)
{
return 0;
}
static inline int hpet_set_rtc_irq_bit(unsigned long mask)
{
return 0;
}
static inline int
hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
{
return 0;
}
static inline int hpet_set_periodic_freq(unsigned long freq)
{
return 0;
}
static inline int hpet_rtc_timer_init(void)
{
return 0;
}
extern irq_handler_t hpet_rtc_interrupt;
static inline int hpet_register_irq_handler(irq_handler_t handler)
{
return 0;
}
static inline int hpet_unregister_irq_handler(irq_handler_t handler)
{
return 0;
}
#endif
/* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */
static inline int use_hpet_alarm(void)
{
return is_hpet_enabled() && !cmos_use_acpi_alarm();
}
/*----------------------------------------------------------------*/
#ifdef RTC_PORT
/* Most newer x86 systems have two register banks, the first used
* for RTC and NVRAM and the second only for NVRAM. Caller must
* own rtc_lock ... and we won't worry about access during NMI.
*/
#define can_bank2 true
static inline unsigned char cmos_read_bank2(unsigned char addr)
{
outb(addr, RTC_PORT(2));
return inb(RTC_PORT(3));
}
static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
{
outb(addr, RTC_PORT(2));
outb(val, RTC_PORT(3));
}
#else
#define can_bank2 false
static inline unsigned char cmos_read_bank2(unsigned char addr)
{
return 0;
}
static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
{
}
#endif
/*----------------------------------------------------------------*/
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
int ret;
/*
* If pm_trace abused the RTC for storage, set the timespec to 0,
* which tells the caller that this RTC value is unusable.
*/
if (!pm_trace_rtc_valid())
return -EIO;
ret = mc146818_get_time(t, 1000);
if (ret < 0) {
dev_err_ratelimited(dev, "unable to read current time\n");
return ret;
}
return 0;
}
static int cmos_set_time(struct device *dev, struct rtc_time *t)
{
/* NOTE: this ignores the issue whereby updating the seconds
* takes effect exactly 500ms after we write the register.
* (Also queueing and other delays before we get this far.)
*/
return
|