mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
rk3188:pmu-ricoh619:updata the drivers,modify some rtc and fg bug
This commit is contained in:
@@ -372,9 +372,9 @@ static irqreturn_t ricoh619_irq(int irq, void *data)
|
||||
}
|
||||
if (i != 2) {
|
||||
ret = ricoh619_write(ricoh619->dev,
|
||||
irq_clr_add[i], ~int_sts[i]);
|
||||
irq_clr_add[i], ~int_sts[i]);
|
||||
if (ret < 0) {
|
||||
dev_err(ricoh619->dev, "Error in reading reg 0x%02x "
|
||||
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
|
||||
"error: %d\n", irq_clr_add[i], ret);
|
||||
}
|
||||
}
|
||||
@@ -438,6 +438,7 @@ int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq,
|
||||
int irq_base)
|
||||
{
|
||||
int i, ret;
|
||||
u8 reg_data = 0;
|
||||
|
||||
if (!irq_base) {
|
||||
dev_warn(ricoh619->dev, "No interrupt support on IRQ base\n");
|
||||
@@ -447,10 +448,21 @@ int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq,
|
||||
mutex_init(&ricoh619->irq_lock);
|
||||
|
||||
/* Initialize all locals to 0 */
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
ricoh619->irq_en_cache[i] = 0;
|
||||
ricoh619->irq_en_reg[i] = 0;
|
||||
}
|
||||
|
||||
/* Initialize rtc */
|
||||
ricoh619->irq_en_cache[2] = 0x20;
|
||||
ricoh619->irq_en_reg[2] = 0x20;
|
||||
|
||||
/* Initialize all locals to 0 */
|
||||
for (i = 3; i < 8; i++) {
|
||||
ricoh619->irq_en_cache[i] = 0;
|
||||
ricoh619->irq_en_reg[i] = 0;
|
||||
}
|
||||
|
||||
// Charger Mask register must be set to 1 for masking Int output.
|
||||
for (i = 8; i < MAX_INTERRUPT_MASKS; i++) {
|
||||
ricoh619->irq_en_cache[i] = 0xff;
|
||||
@@ -490,11 +502,29 @@ int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq,
|
||||
|
||||
/* Clear all interrupts in case they woke up active. */
|
||||
for (i = 0; i < MAX_INTERRUPT_MASKS; i++) {
|
||||
ret = ricoh619_write(ricoh619->dev,
|
||||
if(irq_clr_add[i] != RICOH619_INT_IR_RTC)
|
||||
{
|
||||
ret = ricoh619_write(ricoh619->dev,
|
||||
irq_clr_add[i], 0);
|
||||
if (ret < 0)
|
||||
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
|
||||
"error: %d\n", irq_clr_add[i], ret);
|
||||
if (ret < 0)
|
||||
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
|
||||
"error: %d\n", irq_clr_add[i], ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ricoh619_read(ricoh619->dev,
|
||||
RICOH619_INT_IR_RTC, ®_data);
|
||||
if (ret < 0)
|
||||
dev_err(ricoh619->dev, "Error in reading reg 0x%02x "
|
||||
"error: %d\n", RICOH619_INT_IR_RTC, ret);
|
||||
reg_data &= 0xf0;
|
||||
ret = ricoh619_write(ricoh619->dev,
|
||||
RICOH619_INT_IR_RTC, reg_data);
|
||||
if (ret < 0)
|
||||
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
|
||||
"error: %d\n", RICOH619_INT_IR_RTC, ret);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ricoh619->irq_base = irq_base;
|
||||
@@ -512,7 +542,7 @@ int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq,
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(irq, NULL, ricoh619_irq,
|
||||
IRQ_TYPE_EDGE_FALLING|IRQF_DISABLED|IRQF_ONESHOT,
|
||||
IRQ_TYPE_LEVEL_LOW|IRQF_DISABLED|IRQF_ONESHOT,
|
||||
"ricoh619", ricoh619);
|
||||
if (ret < 0)
|
||||
dev_err(ricoh619->dev, "Error in registering interrupt "
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -285,7 +285,7 @@ static unsigned int ricoh619_dcdc_get_mode(struct regulator_dev *rdev)
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case 2:
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
case 4:
|
||||
case 3:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
default:
|
||||
return -1;
|
||||
|
||||
700
drivers/rtc/rtc-ricoh619.c
Normal file → Executable file
700
drivers/rtc/rtc-ricoh619.c
Normal file → Executable file
@@ -6,7 +6,7 @@
|
||||
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
|
||||
*
|
||||
* Based on code
|
||||
* Copyright (C) 2011 NVIDIA Corporation
|
||||
* Copyright (C) 2011 NVIDIA Corporation
|
||||
*
|
||||
* 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
|
||||
@@ -19,7 +19,7 @@
|
||||
* more details.
|
||||
*
|
||||
* you should have received a copy of the gnu general public license
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -37,10 +37,9 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct ricoh619_rtc {
|
||||
unsigned long epoch_start;
|
||||
int irq;
|
||||
struct rtc_device *rtc;
|
||||
bool irq_en;
|
||||
bool irq_en;
|
||||
};
|
||||
|
||||
static int ricoh619_read_regs(struct device *dev, int reg, int len,
|
||||
@@ -70,21 +69,24 @@ static int ricoh619_write_regs(struct device *dev, int reg, int len,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 0=OK, -EINVAL= FAIL
|
||||
static int ricoh619_rtc_valid_tm(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
if (tm->tm_year >= (rtc_year_offset + 99)
|
||||
|| tm->tm_mon > 12
|
||||
if (tm->tm_year > 199 || tm->tm_year < 70
|
||||
|| tm->tm_mon > 11 || tm->tm_mon < 0
|
||||
|| tm->tm_mday < 1
|
||||
|| tm->tm_mday > rtc_month_days(tm->tm_mon,
|
||||
tm->tm_year + os_ref_year)
|
||||
|| tm->tm_hour >= 24
|
||||
|| tm->tm_min >= 60
|
||||
|| tm->tm_sec >= 60) {
|
||||
dev_err(dev->parent, "\n returning error due to time"
|
||||
"%d/%d/%d %d:%d:%d", tm->tm_mon, tm->tm_mday,
|
||||
tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|| tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + os_ref_year)
|
||||
|| tm->tm_hour >= 24 || tm->tm_hour <0
|
||||
|| tm->tm_min < 0 || tm->tm_min >= 60
|
||||
|| tm->tm_sec < 0 || tm->tm_sec >= 60
|
||||
)
|
||||
{
|
||||
dev_err(dev->parent, "PMU: %s *** Returning error due to time, %d/%d/%d %d:%d:%d *****\n",
|
||||
__func__, tm->tm_mon, tm->tm_mday, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -114,47 +116,199 @@ static void convert_decimal_to_bcd(u8 *buf, u8 len)
|
||||
|
||||
static void print_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
dev_info(dev, "rtc-time : %d/%d/%d %d:%d\n",
|
||||
(tm->tm_mon + 1), tm->tm_mday, (tm->tm_year + os_ref_year),
|
||||
tm->tm_hour, tm->tm_min);
|
||||
dev_info(dev, "PMU: %s *** rtc-time : %d/%d/%d %d:%d:%d *****\n",
|
||||
__func__, (tm->tm_mon), tm->tm_mday, (tm->tm_year + os_ref_year), tm->tm_hour, tm->tm_min,tm->tm_sec);
|
||||
}
|
||||
|
||||
static int ricoh619_rtc_periodic_disable(struct device *dev)
|
||||
{
|
||||
int err;
|
||||
uint8_t reg_data;
|
||||
|
||||
// disable function
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl1, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error=0x%x\n", err);
|
||||
return err;
|
||||
}
|
||||
reg_data &= 0xf8;
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl1, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error=0x%x\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// clear alarm flag and CTFG
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error=0x%x\n", err);
|
||||
return err;
|
||||
}
|
||||
reg_data &= ~0x85;// 1000-0101
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl2, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error=0x%x\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ricoh619_rtc_clk_adjust(struct device *dev, uint8_t clk)
|
||||
{
|
||||
return ricoh619_write_regs(dev, rtc_adjust, 1, &clk);
|
||||
}
|
||||
|
||||
static int ricoh619_rtc_Pon_get_clr(struct device *dev, uint8_t *Pon_f)
|
||||
{
|
||||
int err;
|
||||
uint8_t reg_data;
|
||||
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "rtc_ctrl1 read err=0x%x\n", err);
|
||||
return err;
|
||||
}
|
||||
// printk("%s,PON=1 -- CTRL2=0x%x\n", __func__, reg_data);
|
||||
|
||||
if(reg_data & 0x10)
|
||||
{
|
||||
*Pon_f = 1;
|
||||
//clear VDET PON
|
||||
reg_data &= ~0x5b;// 0101-1011
|
||||
reg_data |= 0x20; // 0010-0000
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl2, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "rtc_ctrl1 write err=0x%x\n", err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*Pon_f = 0;
|
||||
}
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// 0-12hour, 1-24hour
|
||||
static int ricoh619_rtc_hour_mode_get(struct device *dev, int *mode)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl1, 1, mode);
|
||||
if(err < 0)
|
||||
dev_err(dev->parent, "read rtc ctrl1 error\n");
|
||||
|
||||
if(*mode & 0x20)
|
||||
*mode = 1;
|
||||
else
|
||||
*mode = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// 0-12hour, 1-24hour
|
||||
static int ricoh619_rtc_hour_mode_set(struct device *dev, int mode)
|
||||
{
|
||||
uint8_t reg_data;
|
||||
int err;
|
||||
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl1, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error\n");
|
||||
return err;
|
||||
}
|
||||
if(mode == 0)
|
||||
reg_data &= 0xDF;
|
||||
else
|
||||
reg_data |= 0x20;
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl1, 1, ®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "write rtc_ctrl1 error\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int ricoh619_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
u8 buff[7];
|
||||
int err;
|
||||
int cent_flag;
|
||||
int i;
|
||||
|
||||
// printk(KERN_INFO "PMU: %s\n", __func__);
|
||||
err = ricoh619_read_regs(dev, rtc_seconds_reg, sizeof(buff), buff);
|
||||
|
||||
if (err < 0) {
|
||||
dev_err(dev, "\n %s :: failed to read time\n", __FILE__);
|
||||
dev_err(dev->parent, "PMU: %s *** failed to read time *****\n", __func__);
|
||||
return err;
|
||||
}
|
||||
convert_bcd_to_decimal(buff, sizeof(buff));
|
||||
|
||||
if (buff[5] & 0x80)
|
||||
cent_flag = 1;
|
||||
else
|
||||
cent_flag = 0;
|
||||
|
||||
buff[5] = buff[5]&0x1f; //bit5 19_20
|
||||
convert_bcd_to_decimal(buff, sizeof(buff));
|
||||
|
||||
tm->tm_sec = buff[0];
|
||||
tm->tm_min = buff[1];
|
||||
tm->tm_hour = buff[2];
|
||||
tm->tm_hour = buff[2]; //bit5 PA_H20
|
||||
tm->tm_wday = buff[3];
|
||||
tm->tm_mday = buff[4];
|
||||
tm->tm_mon = buff[5] - 1;
|
||||
tm->tm_year = buff[6] + rtc_year_offset;
|
||||
// print_time(dev, tm);
|
||||
return ricoh619_rtc_valid_tm(dev, tm);
|
||||
tm->tm_mon = buff[5]; //for print
|
||||
tm->tm_year = buff[6] + 100 * cent_flag;
|
||||
print_time(dev, tm); //for print
|
||||
tm->tm_mon = buff[5] - 1; //back to system 0-11
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ricoh619_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
u8 buff[7];
|
||||
int err;
|
||||
int cent_flag;
|
||||
|
||||
// print_time(dev, tm);
|
||||
// printk(KERN_INFO "PMU: %s\n", __func__);
|
||||
|
||||
if(ricoh619_rtc_valid_tm(dev, tm) != 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tm->tm_year >= 100)
|
||||
cent_flag = 1;
|
||||
else
|
||||
cent_flag = 0;
|
||||
|
||||
tm->tm_mon = tm->tm_mon + 1;
|
||||
buff[0] = tm->tm_sec;
|
||||
buff[1] = tm->tm_min;
|
||||
buff[2] = tm->tm_hour;
|
||||
buff[3] = tm->tm_wday;
|
||||
buff[4] = tm->tm_mday;
|
||||
buff[5] = tm->tm_mon + 1;
|
||||
buff[6] = tm->tm_year - rtc_year_offset;
|
||||
buff[5] = tm->tm_mon; //system set 0-11
|
||||
buff[6] = tm->tm_year - 100 * cent_flag;
|
||||
print_time(dev, tm); // RTC_TEST
|
||||
|
||||
convert_decimal_to_bcd(buff, sizeof(buff));
|
||||
|
||||
if (1 == cent_flag)
|
||||
buff[5] |= 0x80;
|
||||
|
||||
err = ricoh619_write_regs(dev, rtc_seconds_reg, sizeof(buff), buff);
|
||||
if (err < 0) {
|
||||
dev_err(dev->parent, "\n failed to program new time\n");
|
||||
@@ -163,118 +317,221 @@ static int ricoh619_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int ricoh619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm);
|
||||
|
||||
static int ricoh619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
static int ricoh619_rtc_alarm_is_enabled(struct device *dev, uint8_t *enabled)
|
||||
{
|
||||
struct ricoh619_rtc *rtc = dev_get_drvdata(dev);
|
||||
unsigned long seconds;
|
||||
u8 buff[6];
|
||||
int err;
|
||||
struct rtc_time tm;
|
||||
uint8_t reg_data;
|
||||
|
||||
if (rtc->irq == -1)
|
||||
return -EIO;
|
||||
|
||||
rtc_tm_to_time(&alrm->time, &seconds);
|
||||
err = ricoh619_rtc_read_time(dev, &tm);
|
||||
if (err) {
|
||||
dev_err(dev, "\n failed to read time\n");
|
||||
return err;
|
||||
err = 0;
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl1, 1,®_data);
|
||||
if(err)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error 0x%lx\n", err);
|
||||
*enabled = 0;
|
||||
}
|
||||
rtc_tm_to_time(&tm, &rtc->epoch_start);
|
||||
else
|
||||
{
|
||||
if(reg_data & 0x40)
|
||||
*enabled = 1;
|
||||
else
|
||||
*enabled = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_info(dev->parent, "\n setting alarm to requested time::\n");
|
||||
// print_time(dev->parent, &alrm->time);
|
||||
// 0-disable, 1-enable
|
||||
static int ricoh619_rtc_alarm_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
struct ricoh619_rtc *rtc = dev_get_drvdata(dev);
|
||||
int err;
|
||||
uint8_t reg_data;
|
||||
|
||||
if (WARN_ON(alrm->enabled && (seconds < rtc->epoch_start))) {
|
||||
dev_err(dev->parent, "\n can't set alarm to requested time\n");
|
||||
return -EINVAL;
|
||||
// printk(KERN_INFO "PMU: %s :%d\n", __func__,enabled);
|
||||
|
||||
err = 0;
|
||||
if(enabled)
|
||||
{
|
||||
rtc->irq_en = 1;
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl1, 1,®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error 0x%lx\n", err);
|
||||
goto ERR;
|
||||
}
|
||||
reg_data |= 0x40;// set DALE
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl1, 1,®_data);
|
||||
if(dev < 0)
|
||||
dev_err(dev->parent, "write rtc_ctrl1 error 0x%lx\n", err);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtc->irq_en = 0;
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl1, 1,®_data);
|
||||
if(err < 0)
|
||||
{
|
||||
dev_err(dev->parent, "read rtc_ctrl1 error 0x%lx\n", err);
|
||||
goto ERR;
|
||||
}
|
||||
reg_data &= 0xbf;// clear DALE
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl1, 1,®_data);
|
||||
if(dev < 0)
|
||||
dev_err(dev->parent, "write rtc_ctrl1 error 0x%lx\n", err);
|
||||
}
|
||||
|
||||
if (alrm->enabled && !rtc->irq_en)
|
||||
rtc->irq_en = true;
|
||||
else if (!alrm->enabled && rtc->irq_en)
|
||||
rtc->irq_en = false;
|
||||
|
||||
buff[0] = alrm->time.tm_sec;
|
||||
buff[1] = alrm->time.tm_min;
|
||||
buff[2] = alrm->time.tm_hour;
|
||||
buff[3] = alrm->time.tm_mday;
|
||||
buff[4] = alrm->time.tm_mon + 1;
|
||||
buff[5] = alrm->time.tm_year - rtc_year_offset;
|
||||
convert_decimal_to_bcd(buff, sizeof(buff));
|
||||
buff[3] |= 0x80; /* set DAL_EXT */
|
||||
err = ricoh619_write_regs(dev, rtc_alarm_y_sec, sizeof(buff), buff);
|
||||
if (err) {
|
||||
dev_err(dev->parent, "\n unable to set alarm\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, buff);
|
||||
if (err) {
|
||||
dev_err(dev->parent, "unable to read rtc_ctrl2 reg\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
buff[1] = buff[0] & ~0x81; /* to clear alarm-D flag, and set adjustment parameter */
|
||||
buff[0] = 0x60; /* to enable alarm_d and 24-hour format */
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl1, 2, buff);
|
||||
if (err) {
|
||||
dev_err(dev, "failed programming rtc ctrl regs\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
return err;
|
||||
ERR:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ricoh619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
u8 buff[6];
|
||||
u8 buff_cent;
|
||||
int err;
|
||||
int cent_flag;
|
||||
unsigned char enabled_flag;
|
||||
|
||||
// printk(KERN_INFO "PMU: %s\n", __func__);
|
||||
|
||||
err = 0;
|
||||
|
||||
alrm->time.tm_sec = 0;
|
||||
alrm->time.tm_min = 0;
|
||||
alrm->time.tm_hour = 0;
|
||||
alrm->time.tm_mday = 0;
|
||||
alrm->time.tm_mon = 0;
|
||||
alrm->time.tm_year = 0;
|
||||
alrm->enabled = 0;
|
||||
|
||||
err = ricoh619_read_regs(dev, rtc_month_reg, 1, &buff_cent);
|
||||
if (err < 0) {
|
||||
dev_err(dev->parent, "PMU: %s *** failed to read time *****\n", __func__);
|
||||
return err;
|
||||
}
|
||||
if (buff_cent & 0x80)
|
||||
cent_flag = 1;
|
||||
else
|
||||
cent_flag = 0;
|
||||
|
||||
err = ricoh619_read_regs(dev, rtc_alarm_y_sec, sizeof(buff), buff);
|
||||
if (err)
|
||||
if(err)
|
||||
{
|
||||
dev_err(dev->parent, "RTC: %s *** read rtc_alarm timer error 0x%lx\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl1, 1,&enabled_flag);
|
||||
if(err)
|
||||
{
|
||||
dev_err(dev->parent, "RTC: %s *** read rtc_enable flag error 0x%lx\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
if(enabled_flag & 0x40)
|
||||
enabled_flag = 1;
|
||||
else
|
||||
enabled_flag = 0;
|
||||
|
||||
buff[3] &= ~0x80; /* clear DAL_EXT */
|
||||
convert_bcd_to_decimal(buff, sizeof(buff));
|
||||
|
||||
buff[3] = buff[3]&0x3f;
|
||||
convert_bcd_to_decimal(buff, sizeof(buff));
|
||||
|
||||
alrm->time.tm_sec = buff[0];
|
||||
alrm->time.tm_min = buff[1];
|
||||
alrm->time.tm_hour = buff[2];
|
||||
alrm->time.tm_mday = buff[3];
|
||||
alrm->time.tm_mon = buff[4];// for print
|
||||
alrm->time.tm_year = buff[5] + 100 * cent_flag;
|
||||
dev_info(dev, "PMU: read alarm: %d/%d/%d %d:%d:%d *****\n",
|
||||
(alrm->time.tm_mon), alrm->time.tm_mday, (alrm->time.tm_year + os_ref_year), alrm->time.tm_hour, alrm->time.tm_min,alrm->time.tm_sec);
|
||||
alrm->time.tm_mon = buff[4] - 1;
|
||||
alrm->time.tm_year = buff[5] + rtc_year_offset;
|
||||
|
||||
// dev_info(dev->parent, "\n getting alarm time::\n");
|
||||
// print_time(dev, &alrm->time);
|
||||
alrm->enabled = enabled_flag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ricoh619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct ricoh619_rtc *rtc = dev_get_drvdata(dev);
|
||||
u8 buff[6];
|
||||
int err;
|
||||
int cent_flag;
|
||||
|
||||
// printk(KERN_INFO "PMU: %s\n", __func__);
|
||||
err = 0;
|
||||
ricoh619_rtc_alarm_enable(dev, 0);
|
||||
if (rtc->irq == -1)
|
||||
{
|
||||
err = -EIO;
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
if(alrm->enabled== 0)
|
||||
return 0;
|
||||
|
||||
if (alrm->time.tm_year >= 100)
|
||||
cent_flag = 1;
|
||||
else
|
||||
cent_flag = 0;
|
||||
|
||||
alrm->time.tm_mon += 1;
|
||||
print_time(dev->parent, &alrm->time);
|
||||
buff[0] = alrm->time.tm_sec;
|
||||
buff[1] = alrm->time.tm_min;
|
||||
buff[2] = alrm->time.tm_hour;
|
||||
buff[3] = alrm->time.tm_mday;
|
||||
buff[4] = alrm->time.tm_mon;
|
||||
// buff[5] = alrm->time.tm_year - rtc_year_offset;
|
||||
buff[5] = alrm->time.tm_year - 100 * cent_flag;
|
||||
convert_decimal_to_bcd(buff, sizeof(buff));
|
||||
buff[3] |= 0x80; /* set DAL_EXT */
|
||||
err = ricoh619_write_regs(dev, rtc_alarm_y_sec, sizeof(buff), buff);
|
||||
if (err) {
|
||||
dev_err(dev->parent, "\n unable to set alarm\n");
|
||||
err = -EBUSY;
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
ricoh619_rtc_alarm_enable(dev, alrm->enabled);
|
||||
|
||||
ERR:
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops ricoh619_rtc_ops = {
|
||||
.read_time = ricoh619_rtc_read_time,
|
||||
.set_time = ricoh619_rtc_set_time,
|
||||
.set_alarm = ricoh619_rtc_set_alarm,
|
||||
.read_alarm = ricoh619_rtc_read_alarm,
|
||||
.alarm_irq_enable = ricoh619_rtc_alarm_enable,
|
||||
};
|
||||
|
||||
static irqreturn_t ricoh619_rtc_irq(int irq, void *data)
|
||||
static int ricoh619_rtc_alarm_flag_clr(struct device *dev)
|
||||
{
|
||||
struct device *dev = data;
|
||||
struct ricoh619_rtc *rtc = dev_get_drvdata(dev);
|
||||
u8 reg;
|
||||
int err;
|
||||
uint8_t reg_data;
|
||||
|
||||
/* clear alarm-D status bits.*/
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, ®);
|
||||
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, ®_data);
|
||||
if (err)
|
||||
dev_err(dev->parent, "unable to read rtc_ctrl2 reg\n");
|
||||
|
||||
/* to clear alarm-D flag, and set adjustment parameter */
|
||||
reg &= ~0x81;
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl2, 1, ®);
|
||||
reg_data &= ~0x81;
|
||||
err = ricoh619_write_regs(dev, rtc_ctrl2, 1, ®_data);
|
||||
if (err)
|
||||
dev_err(dev->parent, "unable to program rtc_status reg\n");
|
||||
return err;
|
||||
}
|
||||
static irqreturn_t ricoh619_rtc_irq(int irq, void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
struct ricoh619_rtc *rtc = dev_get_drvdata(dev);
|
||||
|
||||
// printk(KERN_INFO "PMU: %s\n", __func__);
|
||||
|
||||
ricoh619_rtc_alarm_flag_clr(dev);
|
||||
|
||||
rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
|
||||
return IRQ_HANDLED;
|
||||
@@ -285,103 +542,224 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev)
|
||||
struct ricoh619_rtc_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct ricoh619_rtc *rtc;
|
||||
struct rtc_time tm;
|
||||
uint8_t Pon_flag,Alarm_flag;
|
||||
int err;
|
||||
u8 reg;
|
||||
rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
|
||||
// printk("%s,line=%d\n", __func__,__LINE__);
|
||||
uint8_t buff[6];
|
||||
|
||||
if (!rtc)
|
||||
return -ENOMEM;
|
||||
// printk(KERN_INFO "******PMU RTC: Version 2013-08-01 REDS!******\n");
|
||||
// printk(KERN_INFO "PMU RTC: %s, ricoh619 driver run at 24H-mode\n", __func__);
|
||||
// printk(KERN_INFO "PMU RTC: we never using periodic function and interrupt\n");
|
||||
|
||||
rtc->irq = -1;
|
||||
|
||||
if (!pdata) {
|
||||
if(!pdata)
|
||||
{
|
||||
dev_err(&pdev->dev, "no platform_data specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdata->irq < 0)
|
||||
dev_err(&pdev->dev, "\n no irq specified, wakeup is disabled\n");
|
||||
|
||||
rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
|
||||
if(IS_ERR(rtc))
|
||||
{
|
||||
err = PTR_ERR(rtc);
|
||||
dev_err(&pdev->dev, "no enough memory for ricoh619_rtc using\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, rtc);
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
|
||||
&ricoh619_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rtc->rtc)) {
|
||||
if(IS_ERR(rtc->rtc))
|
||||
{
|
||||
err = PTR_ERR(rtc->rtc);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
reg = 0x60; /* to enable alarm_d and 24-hour format */
|
||||
err = ricoh619_write_regs(&pdev->dev, rtc_ctrl1, 1, ®);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed rtc setup\n");
|
||||
return -EBUSY;
|
||||
if(pdata->irq < 0)
|
||||
{
|
||||
dev_err(&pdev->dev, "\n no irq specified, wakeup is disabled\n");
|
||||
rtc->irq = -1;
|
||||
rtc->irq_en = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtc->irq = pdata->irq;
|
||||
rtc->irq_en = 1;
|
||||
}
|
||||
|
||||
reg = 0; /* clearing RTC Adjust register */
|
||||
err = ricoh619_write_regs(&pdev->dev, rtc_adjust, 1, ®);
|
||||
if (err) {
|
||||
//get interrupt flag
|
||||
err = ricoh619_rtc_alarm_is_enabled(&pdev->dev, &Alarm_flag);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: Disable alarm interrupt error\n");
|
||||
goto fail;
|
||||
|
||||
}
|
||||
|
||||
// get PON flag
|
||||
err = ricoh619_rtc_Pon_get_clr(&pdev->dev, &Pon_flag);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: get PON flag error\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// disable rtc periodic function
|
||||
err = ricoh619_rtc_periodic_disable(&pdev->dev);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: disable rtc periodic int error\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// clearing RTC Adjust register
|
||||
err = ricoh619_rtc_clk_adjust(&pdev->dev, 0);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "unable to program rtc_adjust reg\n");
|
||||
return -EBUSY;
|
||||
err = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
/* Set default time-1970.1.1-0h:0m:0s if PON is on */
|
||||
err = ricoh619_read_regs(&pdev->dev, rtc_ctrl2, 1, ®);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "\n failed to read rtc ctl2 reg\n");
|
||||
return -EBUSY;
|
||||
|
||||
//disable interrupt
|
||||
err = ricoh619_rtc_alarm_enable(&pdev->dev, 0);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: Disable alarm interrupt error\n");
|
||||
goto fail;
|
||||
}
|
||||
if (reg&0x10) {
|
||||
printk("%s,PON=1 -- CTRL2=%x\n", __func__, reg);
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_hour = 0;
|
||||
tm.tm_wday = 4;
|
||||
tm.tm_mday = 1;
|
||||
tm.tm_mon = 0;
|
||||
tm.tm_year = 0x70;
|
||||
/* VDET & PON = 0, others are not changed */
|
||||
reg &= ~0x50;
|
||||
err = ricoh619_write_regs(&pdev->dev, rtc_ctrl2, 1, ®);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "\n failed to write rtc ctl2 reg\n");
|
||||
return -EBUSY;
|
||||
|
||||
// PON=1
|
||||
if(Pon_flag)
|
||||
{
|
||||
Alarm_flag = 0;
|
||||
// clear int flag
|
||||
err = ricoh619_rtc_alarm_flag_clr(&pdev->dev);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: Pon=1 clear alarm flag error\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// using 24h-mode
|
||||
err = ricoh619_rtc_hour_mode_set(&pdev->dev,1);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: Pon=1 set 24h-mode error\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else {
|
||||
err = ricoh619_rtc_read_time(&pdev->dev, &tm);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "\n failed to read time\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (ricoh619_rtc_valid_tm(&pdev->dev, &tm)) {
|
||||
if (pdata->time.tm_year < 2000 || pdata->time.tm_year > 2100) {
|
||||
memset(&pdata->time, 0, sizeof(pdata->time));
|
||||
pdata->time.tm_year = rtc_year_offset;
|
||||
pdata->time.tm_mday = 1;
|
||||
} else
|
||||
// setting the default year
|
||||
// printk(KERN_INFO "PMU: %s Set default time\n", __func__);
|
||||
|
||||
pdata->time.tm_sec=0;
|
||||
pdata->time.tm_min=0;
|
||||
pdata->time.tm_hour=0;
|
||||
pdata->time.tm_wday=6;
|
||||
pdata->time.tm_mday=1;
|
||||
pdata->time.tm_mon=1;
|
||||
pdata->time.tm_year=2012;
|
||||
pdata->time.tm_year -= os_ref_year;
|
||||
err = ricoh619_rtc_set_time(&pdev->dev, &pdata->time);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "\n failed to set time\n");
|
||||
return err;
|
||||
if(ricoh619_rtc_valid_tm(&pdev->dev, &(pdata->time)) == 0)
|
||||
{
|
||||
tm.tm_sec = pdata->time.tm_sec;
|
||||
tm.tm_min = pdata->time.tm_min;
|
||||
tm.tm_hour = pdata->time.tm_hour;
|
||||
tm.tm_wday= pdata->time.tm_wday;
|
||||
tm.tm_mday= pdata->time.tm_mday;
|
||||
tm.tm_mon = pdata->time.tm_mon-1;
|
||||
tm.tm_year = pdata->time.tm_year;
|
||||
}
|
||||
else
|
||||
{
|
||||
// using the ricoh default time instead of board default time
|
||||
dev_err(&pdev->dev, "board rtc default is erro\n");
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_hour = 0;
|
||||
tm.tm_wday = 4;
|
||||
tm.tm_mday = 1;
|
||||
tm.tm_mon = 0;
|
||||
tm.tm_year = 70;
|
||||
}
|
||||
|
||||
// set default alarm time
|
||||
if (tm.tm_year >= 100)
|
||||
buff[5] = tm.tm_year-100-1;
|
||||
else
|
||||
buff[5] = tm.tm_year-1;
|
||||
buff[0] = tm.tm_sec;
|
||||
buff[1] = tm.tm_min;
|
||||
buff[2] = tm.tm_hour;
|
||||
buff[3] = tm.tm_mday;
|
||||
buff[4] = tm.tm_mon +1;
|
||||
|
||||
err = ricoh619_rtc_set_time(&pdev->dev, &tm);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5t619 RTC:\n failed to set time\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
convert_decimal_to_bcd(buff, sizeof(buff));
|
||||
buff[3] |= 0x80; /* set DAL_EXT */
|
||||
|
||||
err = ricoh619_write_regs(&pdev->dev, rtc_alarm_y_sec, sizeof(buff), buff);
|
||||
if (err)
|
||||
printk( "\n unable to set alarm\n");
|
||||
|
||||
}
|
||||
if (pdata && (pdata->irq >= 0)) {
|
||||
rtc->irq = pdata->irq + RICOH619_IRQ_DALE;
|
||||
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
// printk(KERN_INFO "PMU: %s register rtc device \n", __func__);
|
||||
rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
|
||||
&ricoh619_rtc_ops, THIS_MODULE);
|
||||
|
||||
// set interrupt and enable it
|
||||
if(rtc->irq != -1)
|
||||
{
|
||||
rtc->irq = rtc->irq + RICOH619_IRQ_DALE;
|
||||
err = request_threaded_irq(rtc->irq, NULL, ricoh619_rtc_irq,
|
||||
IRQF_ONESHOT, "rtc_ricoh619",
|
||||
&pdev->dev);
|
||||
if (err) {
|
||||
IRQF_ONESHOT, "rtc_ricoh619", &pdev->dev);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq);
|
||||
rtc->irq = -1;
|
||||
} else {
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
err = ricoh619_rtc_alarm_enable(&pdev->dev, 0);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: enable rtc alarm error\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// enable wake
|
||||
enable_irq_wake(rtc->irq);
|
||||
// enable alarm_d
|
||||
err = ricoh619_rtc_alarm_enable(&pdev->dev, Alarm_flag);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "failed rtc setup\n");
|
||||
err = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// system don't want to using alarm interrupt, so close it
|
||||
err = ricoh619_rtc_alarm_enable(&pdev->dev, 0);
|
||||
if(err)
|
||||
{
|
||||
dev_err(&pdev->dev, "5T619 RTC: Disable rtc alarm error\n");
|
||||
goto fail;
|
||||
}
|
||||
dev_err(&pdev->dev, "ricoh619 interrupt is disabled\n");
|
||||
}
|
||||
|
||||
printk(KERN_INFO "RICOH619 RTC Register Success\n");
|
||||
|
||||
ricoh619_read_regs(&pdev->dev, rtc_ctrl1, 1,&buff[0]);
|
||||
ricoh619_read_regs(&pdev->dev, rtc_ctrl2, 1,&buff[1]);
|
||||
// printk(KERN_INFO "0xAE:%x 0xAF:%x\n",buff[0],buff[1]);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
5
include/linux/power/ricoh619_battery.h
Executable file → Normal file
5
include/linux/power/ricoh619_battery.h
Executable file → Normal file
@@ -35,6 +35,8 @@
|
||||
#define ADC_VDD_MV 2800
|
||||
#define MIN_VOLTAGE 3100
|
||||
#define MAX_VOLTAGE 4200
|
||||
#define B_VALUE 3435
|
||||
|
||||
|
||||
/* 619 Register information */
|
||||
/* bank 0 */
|
||||
@@ -54,6 +56,7 @@
|
||||
#define REGISET1_REG 0xB6
|
||||
#define REGISET2_REG 0xB7
|
||||
#define CHGISET_REG 0xB8
|
||||
#define TIMSET_REG 0xB9
|
||||
#define BATSET1_REG 0xBA
|
||||
#define BATSET2_REG 0xBB
|
||||
|
||||
@@ -85,6 +88,8 @@
|
||||
/* bank 1 */
|
||||
/* Top address for battery initial setting */
|
||||
#define BAT_INIT_TOP_REG 0xBC
|
||||
#define TEMP_GAIN_H_REG 0xD6
|
||||
#define TEMP_OFF_H_REG 0xB8
|
||||
#define BAT_REL_SEL_REG 0xDA
|
||||
#define BAT_TA_SEL_REG 0xDB
|
||||
/**************************/
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* include/linux/rtc/rtc-ricoh619.h
|
||||
*
|
||||
* Real time clock driver for RICOH RC5T619 power management chip.
|
||||
* Real time clock driver for RICOH R5T619 power management chip.
|
||||
*
|
||||
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
|
||||
*
|
||||
* Based on code
|
||||
* Copyright (C) 2011 NVIDIA Corporation
|
||||
* Copyright (C) 2011 NVIDIA Corporation
|
||||
*
|
||||
* 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
|
||||
@@ -19,7 +19,7 @@
|
||||
* more details.
|
||||
*
|
||||
* you should have received a copy of the gnu general public license
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef __LINUX_RTC_RICOH619_H_
|
||||
@@ -32,6 +32,9 @@
|
||||
#define rtc_seconds_reg 0xA0
|
||||
#define rtc_alarm_y_sec 0xA8
|
||||
#define rtc_adjust 0xA7
|
||||
#define rtc_month_reg 0xA5
|
||||
#define rtc_mday_reg 0xA4
|
||||
#define rtc_dal_month_reg 0xAC
|
||||
|
||||
|
||||
/*
|
||||
@@ -44,7 +47,6 @@ linux rtc driver refers 1900 as base year in many calculations.
|
||||
pmu rtc have only 2 nibbles to store year information, so using an
|
||||
offset of 100 to set the base year as 2000 for our driver.
|
||||
*/
|
||||
#define rtc_year_offset 100
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user