#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/watchdog.h>
#define PCF2127_REG_CTRL1 …
#define PCF2127_BIT_CTRL1_POR_OVRD …
#define PCF2127_BIT_CTRL1_TSF1 …
#define PCF2127_BIT_CTRL1_STOP …
#define PCF2127_REG_CTRL2 …
#define PCF2127_BIT_CTRL2_AIE …
#define PCF2127_BIT_CTRL2_TSIE …
#define PCF2127_BIT_CTRL2_AF …
#define PCF2127_BIT_CTRL2_TSF2 …
#define PCF2127_BIT_CTRL2_WDTF …
#define PCF2127_REG_CTRL3 …
#define PCF2127_BIT_CTRL3_BLIE …
#define PCF2127_BIT_CTRL3_BIE …
#define PCF2127_BIT_CTRL3_BLF …
#define PCF2127_BIT_CTRL3_BF …
#define PCF2127_BIT_CTRL3_BTSE …
#define PCF2127_REG_TIME_BASE …
#define PCF2127_BIT_SC_OSF …
#define PCF2127_REG_ALARM_BASE …
#define PCF2127_BIT_ALARM_AE …
#define PCF2127_REG_CLKOUT …
#define PCF2127_BIT_CLKOUT_OTPR …
#define PCF2127_REG_WD_CTL …
#define PCF2127_BIT_WD_CTL_TF0 …
#define PCF2127_BIT_WD_CTL_TF1 …
#define PCF2127_BIT_WD_CTL_CD0 …
#define PCF2127_BIT_WD_CTL_CD1 …
#define PCF2127_REG_WD_VAL …
#define PCF2127_REG_TS1_BASE …
#define PCF2127_BIT_TS_CTRL_TSOFF …
#define PCF2127_BIT_TS_CTRL_TSM …
#define PCF2127_REG_RAM_ADDR_MSB …
#define PCF2127_REG_RAM_WRT_CMD …
#define PCF2127_REG_RAM_RD_CMD …
#define PCF2127_WD_VAL_STOP …
#define PCF2127_WD_CLOCK_HZ_X1000 …
#define PCF2127_WD_MIN_HW_HEARTBEAT_MS …
#define PCF2131_WD_CLOCK_HZ_X1000 …
#define PCF2131_WD_MIN_HW_HEARTBEAT_MS …
#define PCF2127_WD_DEFAULT_TIMEOUT_S …
#define PCF2127_CTRL1_IRQ_MASK …
#define PCF2127_CTRL2_IRQ_MASK …
#define PCF2127_MAX_TS_SUPPORTED …
#define PCF2131_REG_CTRL4 …
#define PCF2131_BIT_CTRL4_TSF4 …
#define PCF2131_BIT_CTRL4_TSF3 …
#define PCF2131_BIT_CTRL4_TSF2 …
#define PCF2131_BIT_CTRL4_TSF1 …
#define PCF2131_REG_CTRL5 …
#define PCF2131_BIT_CTRL5_TSIE4 …
#define PCF2131_BIT_CTRL5_TSIE3 …
#define PCF2131_BIT_CTRL5_TSIE2 …
#define PCF2131_BIT_CTRL5_TSIE1 …
#define PCF2131_REG_SR_RESET …
#define PCF2131_SR_RESET_READ_PATTERN …
#define PCF2131_SR_RESET_CPR_CMD …
#define PCF2131_REG_TIME_BASE …
#define PCF2131_REG_ALARM_BASE …
#define PCF2131_REG_CLKOUT …
#define PCF2131_REG_WD_CTL …
#define PCF2131_REG_WD_VAL …
#define PCF2131_REG_TS1_BASE …
#define PCF2131_REG_TS2_BASE …
#define PCF2131_REG_TS3_BASE …
#define PCF2131_REG_TS4_BASE …
#define PCF2131_REG_INT_A_MASK1 …
#define PCF2131_REG_INT_A_MASK2 …
#define PCF2131_REG_INT_B_MASK1 …
#define PCF2131_REG_INT_B_MASK2 …
#define PCF2131_BIT_INT_BLIE …
#define PCF2131_BIT_INT_BIE …
#define PCF2131_BIT_INT_AIE …
#define PCF2131_BIT_INT_WD_CD …
#define PCF2131_BIT_INT_SI …
#define PCF2131_BIT_INT_MI …
#define PCF2131_CTRL2_IRQ_MASK …
#define PCF2131_CTRL4_IRQ_MASK …
enum pcf21xx_type { … };
struct pcf21xx_ts_config { … };
struct pcf21xx_config { … };
struct pcf2127 { … };
static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ … }
static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ … }
static int pcf2127_rtc_ioctl(struct device *dev,
unsigned int cmd, unsigned long arg)
{ … }
static int pcf2127_nvmem_read(void *priv, unsigned int offset,
void *val, size_t bytes)
{ … }
static int pcf2127_nvmem_write(void *priv, unsigned int offset,
void *val, size_t bytes)
{ … }
static int pcf2127_wdt_ping(struct watchdog_device *wdd)
{ … }
static int pcf2127_wdt_active_ping(struct watchdog_device *wdd)
{ … }
static int pcf2127_wdt_start(struct watchdog_device *wdd)
{ … }
static int pcf2127_wdt_stop(struct watchdog_device *wdd)
{ … }
static int pcf2127_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int new_timeout)
{ … }
static const struct watchdog_info pcf2127_wdt_info = …;
static const struct watchdog_ops pcf2127_watchdog_ops = …;
static int pcf2127_watchdog_get_period(int n, int f1000)
{ … }
static int pcf2127_watchdog_init(struct device *dev, struct pcf2127 *pcf2127)
{ … }
static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ … }
static int pcf2127_rtc_alarm_irq_enable(struct device *dev, u32 enable)
{ … }
static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ … }
static int pcf2127_rtc_ts_read(struct device *dev, time64_t *ts,
int ts_id)
{
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
struct rtc_time tm;
int ret;
unsigned char data[7];
ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->ts[ts_id].reg_base,
data, sizeof(data));
if (ret) {
dev_err(dev, "%s: read error ret=%d\n", __func__, ret);
return ret;
}
dev_dbg(dev,
"%s: raw data is ts_sc=%02x, ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n",
__func__, data[1], data[2], data[3], data[4], data[5], data[6]);
tm.tm_sec = bcd2bin(data[1] & 0x7F);
tm.tm_min = bcd2bin(data[2] & 0x7F);
tm.tm_hour = bcd2bin(data[3] & 0x3F);
tm.tm_mday = bcd2bin(data[4] & 0x3F);
tm.tm_mon = bcd2bin(data[5] & 0x1F) - 1;
tm.tm_year = bcd2bin(data[6]);
if (tm.tm_year < 70)
tm.tm_year += 100;
ret = rtc_valid_tm(&tm);
if (ret) {
dev_err(dev, "Invalid timestamp. ret=%d\n", ret);
return ret;
}
*ts = rtc_tm_to_time64(&tm);
return 0;
};
static void pcf2127_rtc_ts_snapshot(struct device *dev, int ts_id)
{ … }
static irqreturn_t pcf2127_rtc_irq(int irq, void *dev)
{ … }
static const struct rtc_class_ops pcf2127_rtc_ops = …;
static ssize_t timestamp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count, int ts_id)
{ … }
static ssize_t timestamp0_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return timestamp_store(dev, attr, buf, count, 0);
};
static ssize_t timestamp1_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return timestamp_store(dev, attr, buf, count, 1);
};
static ssize_t timestamp2_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return timestamp_store(dev, attr, buf, count, 2);
};
static ssize_t timestamp3_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return timestamp_store(dev, attr, buf, count, 3);
};
static ssize_t timestamp_show(struct device *dev,
struct device_attribute *attr, char *buf,
int ts_id)
{ … }
static ssize_t timestamp0_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return timestamp_show(dev, attr, buf, 0);
};
static ssize_t timestamp1_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return timestamp_show(dev, attr, buf, 1);
};
static ssize_t timestamp2_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return timestamp_show(dev, attr, buf, 2);
};
static ssize_t timestamp3_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return timestamp_show(dev, attr, buf, 3);
};
static DEVICE_ATTR_RW(timestamp0);
static DEVICE_ATTR_RW(timestamp1);
static DEVICE_ATTR_RW(timestamp2);
static DEVICE_ATTR_RW(timestamp3);
static struct attribute *pcf2127_attrs[] = …;
static struct attribute *pcf2131_attrs[] = …;
static struct pcf21xx_config pcf21xx_cfg[] = …;
static int pcf2127_enable_ts(struct device *dev, int ts_id)
{ … }
static int pcf2127_configure_interrupt_pins(struct device *dev)
{ … }
static int pcf2127_probe(struct device *dev, struct regmap *regmap,
int alarm_irq, const struct pcf21xx_config *config)
{ … }
#ifdef CONFIG_OF
static const struct of_device_id pcf2127_of_match[] = …;
MODULE_DEVICE_TABLE(of, pcf2127_of_match);
#endif
#if IS_ENABLED(CONFIG_I2C)
static int pcf2127_i2c_write(void *context, const void *data, size_t count)
{ … }
static int pcf2127_i2c_gather_write(void *context,
const void *reg, size_t reg_size,
const void *val, size_t val_size)
{ … }
static int pcf2127_i2c_read(void *context, const void *reg, size_t reg_size,
void *val, size_t val_size)
{ … }
static const struct regmap_bus pcf2127_i2c_regmap = …;
static struct i2c_driver pcf2127_i2c_driver;
static const struct i2c_device_id pcf2127_i2c_id[] = …;
MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
static int pcf2127_i2c_probe(struct i2c_client *client)
{ … }
static struct i2c_driver pcf2127_i2c_driver = …;
static int pcf2127_i2c_register_driver(void)
{ … }
static void pcf2127_i2c_unregister_driver(void)
{ … }
#else
static int pcf2127_i2c_register_driver(void)
{
return 0;
}
static void pcf2127_i2c_unregister_driver(void)
{
}
#endif
#if IS_ENABLED(CONFIG_SPI_MASTER)
static struct spi_driver pcf2127_spi_driver;
static const struct spi_device_id pcf2127_spi_id[];
static int pcf2127_spi_probe(struct spi_device *spi)
{ … }
static const struct spi_device_id pcf2127_spi_id[] = …;
MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
static struct spi_driver pcf2127_spi_driver = …;
static int pcf2127_spi_register_driver(void)
{ … }
static void pcf2127_spi_unregister_driver(void)
{ … }
#else
static int pcf2127_spi_register_driver(void)
{
return 0;
}
static void pcf2127_spi_unregister_driver(void)
{
}
#endif
static int __init pcf2127_init(void)
{ … }
module_init(…) …
static void __exit pcf2127_exit(void)
{ … }
module_exit(…)
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;