// SPDX-License-Identifier: GPL-2.0-only /* * rtc-ds1305.c -- driver for DS1305 and DS1306 SPI RTC chips * * Copyright (C) 2008 David Brownell */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/bcd.h> #include <linux/slab.h> #include <linux/rtc.h> #include <linux/workqueue.h> #include <linux/spi/spi.h> #include <linux/spi/ds1305.h> #include <linux/module.h> /* * Registers ... mask DS1305_WRITE into register address to write, * otherwise you're reading it. All non-bitmask values are BCD. */ #define DS1305_WRITE … /* RTC date/time ... the main special cases are that we: * - Need fancy "hours" encoding in 12hour mode * - Don't rely on the "day-of-week" field (or tm_wday) * - Are a 21st-century clock (2000 <= year < 2100) */ #define DS1305_RTC_LEN … #define DS1305_SEC … #define DS1305_MIN … #define DS1305_HOUR … #define DS1305_HR_12 … #define DS1305_HR_PM … #define DS1305_WDAY … #define DS1305_MDAY … #define DS1305_MON … #define DS1305_YEAR … /* The two alarms have only sec/min/hour/wday fields (ALM_LEN). * DS1305_ALM_DISABLE disables a match field (some combos are bad). * * NOTE that since we don't use WDAY, we limit ourselves to alarms * only one day into the future (vs potentially up to a week). * * NOTE ALSO that while we could generate once-a-second IRQs (UIE), we * don't currently support them. We'd either need to do it only when * no alarm is pending (not the standard model), or to use the second * alarm (implying that this is a DS1305 not DS1306, *and* that either * it's wired up a second IRQ we know, or that INTCN is set) */ #define DS1305_ALM_LEN … #define DS1305_ALM_DISABLE … #define DS1305_ALM0(r) … #define DS1305_ALM1(r) … /* three control registers */ #define DS1305_CONTROL_LEN … #define DS1305_CONTROL … #define DS1305_nEOSC … #define DS1305_WP … #define DS1305_INTCN … #define DS1306_1HZ … #define DS1305_AEI1 … #define DS1305_AEI0 … #define DS1305_STATUS … /* status has just AEIx bits, mirrored as IRQFx */ #define DS1305_TRICKLE … /* trickle bits are defined in <linux/spi/ds1305.h> */ /* a bunch of NVRAM */ #define DS1305_NVRAM_LEN … #define DS1305_NVRAM … struct ds1305 { … }; /*----------------------------------------------------------------------*/ /* * Utilities ... tolerate 12-hour AM/PM notation in case of non-Linux * software (like a bootloader) which may require it. */ static unsigned bcd2hour(u8 bcd) { … } static u8 hour2bcd(bool hr12, int hour) { … } /*----------------------------------------------------------------------*/ /* * Interface to RTC framework */ static int ds1305_alarm_irq_enable(struct device *dev, unsigned int enabled) { … } /* * Get/set of date and time is pretty normal. */ static int ds1305_get_time(struct device *dev, struct rtc_time *time) { … } static int ds1305_set_time(struct device *dev, struct rtc_time *time) { … } /* * Get/set of alarm is a bit funky: * * - First there's the inherent raciness of getting the (partitioned) * status of an alarm that could trigger while we're reading parts * of that status. * * - Second there's its limited range (we could increase it a bit by * relying on WDAY), which means it will easily roll over. * * - Third there's the choice of two alarms and alarm signals. * Here we use ALM0 and expect that nINT0 (open drain) is used; * that's the only real option for DS1306 runtime alarms, and is * natural on DS1305. * * - Fourth, there's also ALM1, and a second interrupt signal: * + On DS1305 ALM1 uses nINT1 (when INTCN=1) else nINT0; * + On DS1306 ALM1 only uses INT1 (an active high pulse) * and it won't work when VCC1 is active. * * So to be most general, we should probably set both alarms to the * same value, letting ALM1 be the wakeup event source on DS1306 * and handling several wiring options on DS1305. * * - Fifth, we support the polled mode (as well as possible; why not?) * even when no interrupt line is wired to an IRQ. */ /* * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) */ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm) { … } /* * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) */ static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { … } #ifdef CONFIG_PROC_FS static int ds1305_proc(struct device *dev, struct seq_file *seq) { … } #else #define ds1305_proc … #endif static const struct rtc_class_ops ds1305_ops = …; static void ds1305_work(struct work_struct *work) { … } /* * This "real" IRQ handler hands off to a workqueue mostly to allow * mutex locking for ds1305->ctrl ... unlike I2C, we could issue async * I/O requests in IRQ context (to clear the IRQ status). */ static irqreturn_t ds1305_irq(int irq, void *p) { … } /*----------------------------------------------------------------------*/ /* * Interface for NVRAM */ static void msg_init(struct spi_message *m, struct spi_transfer *x, u8 *addr, size_t count, char *tx, char *rx) { … } static int ds1305_nvram_read(void *priv, unsigned int off, void *buf, size_t count) { … } static int ds1305_nvram_write(void *priv, unsigned int off, void *buf, size_t count) { … } /*----------------------------------------------------------------------*/ /* * Interface to SPI stack */ static int ds1305_probe(struct spi_device *spi) { … } static void ds1305_remove(struct spi_device *spi) { … } static struct spi_driver ds1305_driver = …; module_spi_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_ALIAS(…) …;