common/drivers/rtc/rtc-rv8803.c
/*
* RTC driver for the Micro Crystal RV8803
*
* Copyright (C) 2015 Micro Crystal SA
*
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
*/
#include <linux/bcd.h>
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/rtc.h>
#define RV8803_SEC 0x00
#define RV8803_MIN 0x01
#define RV8803_HOUR 0x02
#define RV8803_WEEK 0x03
#define RV8803_DAY 0x04
#define RV8803_MONTH 0x05
#define RV8803_YEAR 0x06
#define RV8803_RAM 0x07
#define RV8803_ALARM_MIN 0x08
#define RV8803_ALARM_HOUR 0x09
#define RV8803_ALARM_WEEK_OR_DAY 0x0A
#define RV8803_TIMER_CNT_0 0x0B
#define RV8803_TIMER_CNT_1 0x0C
#define RV8803_EXT 0x0D
#define RV8803_FLAG 0x0E
#define RV8803_CTRL 0x0F
#define RV8803_EX2_OSC_OFFSET 0x2C
#define RV8803_EX2_EVENT_CTRL 0x2F
#define RV8803_EXT_TSEL0 BIT(0)
#define RV8803_EXT_TSEL1 BIT(1)
#define RV8803_EXT_FSEL0 BIT(2)
#define RV8803_EXT_FSEL1 BIT(3)
#define RV8803_EXT_TE BIT(4)
#define RV8803_EXT_USEL BIT(5)
#define RV8803_EXT_WADA BIT(6)
#define RV8803_EXT_TEST BIT(7)
#define RV8803_FLAG_V1F BIT(0)
#define RV8803_FLAG_V2F BIT(1)
#define RV8803_FLAG_EVF BIT(2)
#define RV8803_FLAG_AF BIT(3)
#define RV8803_FLAG_TF BIT(4)
#define RV8803_FLAG_UF BIT(5)
#define RV8803_CTRL_RESET BIT(0)
#define RV8803_CTRL_EIE BIT(2)
#define RV8803_CTRL_AIE BIT(3)
#define RV8803_CTRL_TIE BIT(4)
#define RV8803_CTRL_UIE BIT(5)
struct rv8803_data {
struct i2c_client *client;
struct rtc_device *rtc;
u8 ctrl;
};
/*
static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
struct rv8803_data *rv8803 = i2c_get_clientdata(client);
unsigned long events = 0;
u8 flags;
flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
if (flags <= 0)
return IRQ_HANDLED;
if (flags & RV8803_FLAG_V1F)
dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
if (flags & RV8803_FLAG_V2F)
dev_warn(&client->dev, "Voltage low, data loss detected.\n");
if (flags & RV8803_FLAG_TF) {
flags &= ~RV8803_FLAG_TF;
rv8803->ctrl &= ~RV8803_CTRL_TIE;
events |= RTC_PF;
}
if (flags & RV8803_FLAG_AF) {
flags &= ~RV8803_FLAG_AF;
rv8803->ctrl &= ~RV8803_CTRL_AIE;
events |= RTC_AF;
}
if (flags & RV8803_FLAG_UF) {
flags &= ~RV8803_FLAG_UF;
rv8803->ctrl &= ~RV8803_CTRL_UIE;
events |= RTC_UF;
}
if (events) {
rtc_update_irq(rv8803->rtc, 1, events);
i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
rv8803->ctrl);
}
return IRQ_HANDLED;
}
*/
static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
{
struct rv8803_data *rv8803 = dev_get_drvdata(dev);
u8 date1[7];
u8 *date = date1;
int ret, flags;
flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
if (flags < 0)
return flags;
if (flags & RV8803_FLAG_V2F) {
dev_warn(dev, "Voltage low, data is invalid.\n");
return -EINVAL;
}
ret = i2c_smbus_read_i2c_block_data(rv880