rk3188:pmu-ricoh619:updata the drivers,modify some rtc and fg bug

This commit is contained in:
张晴
2013-08-09 11:46:18 +08:00
parent 706a2c6f26
commit f28bf8262b
6 changed files with 1420 additions and 362 deletions

View File

@@ -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, &reg_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

View File

@@ -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
View 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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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,&reg_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,&reg_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,&reg_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,&reg_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,&reg_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, &reg);
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, &reg_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);
reg_data &= ~0x81;
err = ricoh619_write_regs(dev, rtc_ctrl2, 1, &reg_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, &reg);
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, &reg);
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, &reg);
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, &reg);
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
View 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
/**************************/

View File

@@ -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