linux/drivers/rtc/rtc-ds1305.c

// 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();