#define ENABLE_FACTORY_MODE
#define DISABLE_CHARGER_TIMER
/* #define ENABLE_FG_KEEP_ON_MODE */
+#define ENABLE_OCV_TABLE_CALIB
#define RICOH619_CHARGE_RESUME_TIME 1
#define RICOH619_CHARGE_CALC_TIME 1
#define RICOH619_JEITA_UPDATE_TIME 60
+#define RICOH619_DELAY_TIME 60
/* define for FG parameter */
#define RICOH619_MAX_RESET_SOC_DIFF 5
#define RICOH619_GET_CHARGE_NUM 10
#define RICOH619_UPDATE_COUNT_DISP 4
#define RICOH619_UPDATE_COUNT_FULL 4
#define RICOH619_CHARGE_UPDATE_TIME 3
+#define RICOH619_FULL_WAIT_TIME 2
#define RE_CAP_GO_DOWN 10 /* 40 */
#define RICOH619_ENTER_LOW_VOL 70
#define RICOH619_TAH_SEL2 5
struct ricoh619_soca_info {
int Rbat;
int n_cap;
+ int ocv_table_def[11];
int ocv_table[11];
int soc; /* Latest FG SOC value */
int displayed_soc;
int reset_flg_90;
int reset_flg_95;
int f_chg_margin;
+ int chg_cmp_times;
int dischg_state;
int Vbat[RICOH619_GET_CHARGE_NUM];
int Vsys[RICOH619_GET_CHARGE_NUM];
int target_vsys;
int target_ibat;
int jt_limit;
+ int OCV100_min;
+ int OCV100_max;
};
struct ricoh619_battery_info {
extern int dwc_vbus_status(void);
/*This is for full state*/
int g_full_flag;
-static int BatteryTableFlageDef=0;
+static int BatteryTableFlagDef=0;
static int BatteryTypeDef=0;
+static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int cutoff_vol, int full_vol, int *start_per, int *end_per);
static int Battery_Type(void)
{
return BatteryTypeDef;
static int Battery_Table(void)
{
- return BatteryTableFlageDef;
+ return BatteryTableFlagDef;
}
static void ricoh619_battery_work(struct work_struct *work)
static int measure_vbatt_FG(struct ricoh619_battery_info *info, int *data);
static int measure_Ibatt_FG(struct ricoh619_battery_info *info, int *data);
static int calc_capacity(struct ricoh619_battery_info *info);
+static int calc_capacity_2(struct ricoh619_battery_info *info);
static int get_OCV_init_Data(struct ricoh619_battery_info *info, int index);
static int get_OCV_voltage(struct ricoh619_battery_info *info, int index);
static int get_check_fuel_gauge_reg(struct ricoh619_battery_info *info,
int Reg_h, int Reg_l, int enable_bit);
static int calc_capacity_in_period(struct ricoh619_battery_info *info,
- int *cc_cap, bool *is_charging);
+ int *cc_cap, bool *is_charging, bool cc_rst);
static int get_charge_priority(struct ricoh619_battery_info *info, bool *data);
static int set_charge_priority(struct ricoh619_battery_info *info, bool *data);
static int get_power_supply_status(struct ricoh619_battery_info *info);
static int measure_vsys_ADC(struct ricoh619_battery_info *info, int *data);
static int Calc_Linear_Interpolation(int x0, int y0, int x1, int y1, int y);
static int get_battery_temp(struct ricoh619_battery_info *info);
+static int get_battery_temp_2(struct ricoh619_battery_info *info);
static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita_updated);
static int calc_ocv(struct ricoh619_battery_info *info)
}
if (info->soca->Ibat_ave < 0) {
if (g_full_flag == 1) {
- if ((calc_ocv(info) < (get_OCV_voltage(info, 10) - info->soca->f_chg_margin) )
+ if ((calc_ocv(info) < (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*3/10) )
&& (info->soca->soc/100 <= 98) ) {
g_full_flag = 0;
info->soca->displayed_soc = 100*100;
* @is_charging: Flag of charging current direction
* TRUE : charging (plus)
* FALSE: discharging (minus)
+* @cc_rst: reset CC_SUM or not
+* TRUE : reset
+* FALSE: not reset
**/
static int calc_capacity_in_period(struct ricoh619_battery_info *info,
- int *cc_cap, bool *is_charging)
+ int *cc_cap, bool *is_charging, bool cc_rst)
{
int err;
uint8_t cc_sum_reg[4];
if (err < 0)
goto out;
- /* CC_SUM <- 0 */
- err = ricoh619_bulk_writes(info->dev->parent,
- CC_SUMREG3_REG, 4, cc_clr);
- if (err < 0)
- goto out;
+ if (cc_rst == true) {
+ /* CC_SUM <- 0 */
+ err = ricoh619_bulk_writes(info->dev->parent,
+ CC_SUMREG3_REG, 4, cc_clr);
+ if (err < 0)
+ goto out;
+ }
/* CC_pause exist */
err = ricoh619_write(info->dev->parent, CC_CTRL_REG, 0);
return 0;
}
+#ifdef ENABLE_OCV_TABLE_CALIB
+/**
+* Calibration OCV Table
+* - Update the value of VBAT on 100% in OCV table
+* if battery is Full charged.
+* - int vbat_ocv <- unit is uV
+**/
+static int calib_ocvTable(struct ricoh619_battery_info *info, int vbat_ocv)
+{
+ int ret;
+ int cutoff_ocv;
+ int i;
+ int ocv100_new;
+ int start_per,end_per;
+
+ RICOH_FG_DBG("PMU: %s\n", __func__);
+
+ if (info->soca->Ibat_ave > RICOH619_REL1_SEL_VALUE) {
+ RICOH_FG_DBG("PMU: %s IBAT > 64mA -- Not Calibration --\n", __func__);
+ return 0;
+ }
+
+ if (vbat_ocv < info->soca->OCV100_max) {
+ if (vbat_ocv < info->soca->OCV100_min)
+ ocv100_new = info->soca->OCV100_min;
+ else
+ ocv100_new = vbat_ocv;
+ } else {
+ ocv100_new = info->soca->OCV100_max;
+ }
+ RICOH_FG_DBG("PMU : %s :max %d min %d current %d\n",__func__,info->soca->OCV100_max,info->soca->OCV100_min,vbat_ocv);
+ RICOH_FG_DBG("PMU : %s : New OCV 100% = 0x%x\n",__func__,ocv100_new);
+
+ /* FG_En Off */
+ ret = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01);
+ if (ret < 0) {
+ dev_err("PMU: %s Error in FG_En OFF\n", __func__);
+ goto err;
+ }
+
+ info->soca->ready_fg = 0;
+
+ //cutoff_ocv = (battery_init_para[info->num][0]<<8) | (battery_init_para[info->num][1]);
+ cutoff_ocv = get_OCV_voltage(info, 0);
+
+ info->soca->ocv_table_def[10] = info->soca->OCV100_max;
+
+ ricoh619_scaling_OCV_table(info, cutoff_ocv/1000, ocv100_new/1000, &start_per, &end_per);
+
+ ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+ BAT_INIT_TOP_REG, 22, battery_init_para[info->num]);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+
+ for (i = 0; i <= 10; i = i+1) {
+ info->soca->ocv_table[i] = get_OCV_voltage(info, i);
+ RICOH_FG_DBG("PMU: %s : * %d0%% voltage = %d uV\n",
+ __func__, i, info->soca->ocv_table[i]);
+ }
+
+ /* FG_En on & Reset*/
+ ret = ricoh619_write(info->dev->parent, FG_CTRL_REG, 0x51);
+ if (ret < 0) {
+ dev_err("PMU: %s Error in FG_En On & Reset\n", __func__);
+ goto err;
+ }
+
+ RICOH_FG_DBG("PMU: %s Exit \n", __func__);
+ return 0;
+err:
+ return ret;
+
+}
+#endif
static void ricoh619_displayed_work(struct work_struct *work)
{
int last_soc_round;
int last_disp_round;
int displayed_soc_temp;
+ int disp_dec;
int cc_cap = 0;
bool is_charging = true;
int i;
int re_cap,fa_cap,use_cap;
bool is_jeita_updated;
+ uint8_t reg_val;
+ int delay_flag = 0;
+ int Vbat = 0;
+ int Ibat = 0;
+ int ret;
+ int ocv;
+ int temp_ocv;
struct ricoh619_battery_info *info = container_of(work,
struct ricoh619_battery_info, displayed_work.work);
is_jeita_updated = false;
if ((RICOH619_SOCA_START == info->soca->status)
- || (RICOH619_SOCA_STABLE == info->soca->status))
+ || (RICOH619_SOCA_STABLE == info->soca->status)
+ || (RICOH619_SOCA_FULL == info->soca->status))
info->soca->ready_fg = 1;
/* judege Full state or Moni Vsys state */
if ((RICOH619_SOCA_DISP == info->soca->status)
|| (RICOH619_SOCA_STABLE == info->soca->status))
{
+ /* caluc 95% ocv */
+ temp_ocv = get_OCV_voltage(info, 10) -
+ (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))/2;
+
+ if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status)
+ && (calc_ocv(info) > temp_ocv)) {
+ info->soca->status = RICOH619_SOCA_FULL;
+ info->soca->update_count = 0;
+ }
/* for issue 1 solution start*/
if(g_full_flag == 1){
info->soca->status = RICOH619_SOCA_FULL;
}
/* for issue1 solution end */
/* check Full state or not*/
- if (info->soca->Ibat_ave >= 0) {
- if ((calc_ocv(info) > (get_OCV_voltage(info, 10) - info->soca->f_chg_margin))
+ if (info->soca->Ibat_ave >= -20) {
+ if ((calc_ocv(info) > (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10))
|| (info->soca->displayed_soc/100 >= 99))
{
g_full_flag = 0;
info->soca->status = RICOH619_SOCA_FULL;
info->soca->update_count = 0;
+ } else if ((calc_ocv(info) > (get_OCV_voltage(info, 9)))
+ && (info->soca->Ibat_ave < 300))
+ {
+ g_full_flag = 0;
+ info->soca->status = RICOH619_SOCA_FULL;
+ info->soca->update_count = 0;
}
} else { /* dis-charging */
if (info->soca->displayed_soc/100 < RICOH619_ENTER_LOW_VOL) {
+ info->soca->target_use_cap = 0;
info->soca->status = RICOH619_SOCA_LOW_VOL;
}
}
}
if (RICOH619_SOCA_STABLE == info->soca->status) {
- info->soca->soc = calc_capacity(info) * 100;
+ info->soca->soc = calc_capacity_2(info);
soc_round = info->soca->soc / 100;
last_soc_round = info->soca->last_soc / 100;
- info->soca->soc_delta = soc_round - last_soc_round;
+ info->soca->soc_delta = info->soca->soc - info->soca->last_soc;
//get charge status
if (info->soca->chg_status == POWER_SUPPLY_STATUS_CHARGING) {
}
}
- if (info->soca->soc_delta >= -1 && info->soca->soc_delta <= 1) {
+ if (info->soca->soc_delta >= -100 && info->soca->soc_delta <= 100) {
info->soca->displayed_soc = info->soca->soc;
} else {
info->soca->status = RICOH619_SOCA_DISP;
}
info->soca->last_soc = info->soca->soc;
info->soca->soc_delta = 0;
- info->soca->update_count = 0;
} else if (RICOH619_SOCA_FULL == info->soca->status) {
err = check_jeita_status(info, &is_jeita_updated);
if (err < 0) {
goto end_flow;
}
info->soca->soc = calc_capacity(info) * 100;
- if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) {
- if (0 == info->soca->jt_limit) {
- g_full_flag = 1;
- info->soca->displayed_soc = 100*100;
- info->soca->update_count = 0;
- } else {
- info->soca->update_count = 0;
- }
- }
- if (info->soca->Ibat_ave >= 0) { /* for issue 3 */
+ info->soca->last_soc = calc_capacity_2(info); /* for DISP */
+
+ if (info->soca->Ibat_ave >= -20) { /* charging */
if (0 == info->soca->jt_limit) {
if (g_full_flag == 1) {
- info->soca->displayed_soc = 100*100;
- info->soca->update_count = 0;
+ /* caluc 95% ocv */
+ //temp_ocv = get_OCV_voltage(info, 10) -
+ // (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))/2;
+ temp_ocv = get_OCV_voltage(info, 9);
+ info->soca->update_count++;
+ info->soca->chg_cmp_times = 0;
+ if (info->soca->update_count >= RICOH619_UPDATE_COUNT_FULL) {
+ if (calc_ocv(info) < temp_ocv) {
+ if(info->soca->displayed_soc > info->soca->soc) {
+ info->soca->displayed_soc = info->soca->displayed_soc - 1;
+ } else {
+ info->soca->displayed_soc = info->soca->soc;
+ }
+ } else {
+ info->soca->displayed_soc = 100*100;
+ }
+ info->soca->update_count = 0;
+ }
} else {
- if (info->soca->displayed_soc/100 < 99) {
- info->soca->update_count++;
- if (info->soca->update_count
- >= RICOH619_UPDATE_COUNT_FULL) {
- info->soca->displayed_soc = info->soca->displayed_soc + 100;
+ if (calc_ocv(info) < (get_OCV_voltage(info, 8))) { /* fail safe*/
+ g_full_flag = 0;
+ info->soca->status = RICOH619_SOCA_DISP;
+ info->soca->soc_delta = 0;
+ } else if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) {
+ if(info->soca->chg_cmp_times >= RICOH619_FULL_WAIT_TIME) {
+ info->soca->displayed_soc = 100*100;
info->soca->update_count = 0;
+ g_full_flag = 1;
+#ifdef ENABLE_OCV_TABLE_CALIB
+ err = calib_ocvTable(info,calc_ocv(info));
+ if (err < 0)
+ dev_err(info->dev, "Calibration OCV Error !!\n");
+#endif
+ } else {
+ info->soca->chg_cmp_times++;
}
} else {
- info->soca->displayed_soc = 99 * 100;
- info->soca->update_count = 0;
+ info->soca->chg_cmp_times = 0;
+ if (info->soca->displayed_soc/100 < 99) {
+ info->soca->update_count++;
+ if (info->soca->update_count
+ >= RICOH619_UPDATE_COUNT_FULL) {
+ info->soca->displayed_soc = info->soca->displayed_soc + 100;
+ info->soca->update_count = 0;
+ }
+ } else {
+ info->soca->displayed_soc = 99 * 100;
+ info->soca->update_count = 0;
+ }
}
}
} else {
info->soca->update_count = 0;
}
- }
- if (info->soca->Ibat_ave < 0) { /* for issue 3 */
- info->soca->update_count = 0;
+ } else { /* discharging */
if (g_full_flag == 1) {
- if ((calc_ocv(info) < (get_OCV_voltage(info, 10) - info->soca->f_chg_margin))
- && (info->soca->soc/100 <= 98)) { /* for issue 2 */
- g_full_flag = 0;
- info->soca->displayed_soc = 100*100;
- info->soca->status = RICOH619_SOCA_DISP;
- info->soca->last_soc = info->soca->soc;
- info->soca->soc_delta = 0;
- } else {
- info->soca->displayed_soc = 100*100;
+ if (info->soca->Ibat_ave <= -1 * RICOH619_REL1_SEL_VALUE) {
+ if ((calc_ocv(info) < (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*3/10))
+ && (info->soca->soc/100 <= 98)) {
+ g_full_flag = 0;
+ info->soca->displayed_soc = 100 * 100;
+ info->soca->status = RICOH619_SOCA_DISP;
+ info->soca->soc_delta = 0;
+ } else {
+ info->soca->displayed_soc = 100 * 100;
+ }
+ } else { /* into relaxation state */
+ ricoh619_read(info->dev->parent, CHGSTATE_REG, ®_val);
+ if (reg_val & 0xc0) {
+ info->soca->displayed_soc = 100 * 100;
+ } else {
+ g_full_flag = 0;
+ info->soca->displayed_soc = 100 * 100;
+ info->soca->status = RICOH619_SOCA_DISP;
+ info->soca->soc_delta = 0;
+ }
}
} else {
g_full_flag = 0;
info->soca->status = RICOH619_SOCA_DISP;
- info->soca->last_soc = info->soca->soc;
info->soca->soc_delta = 0;
}
}
info->soca->status = RICOH619_SOCA_DISP;
info->soca->last_soc = info->soca->soc;
info->soca->soc_delta = 0;
- info->soca->update_count = 0;
} else {
re_cap = get_check_fuel_gauge_reg(info, RE_CAP_H_REG, RE_CAP_L_REG,
0x7fff);
0x7fff);
use_cap = fa_cap - re_cap;
- if ((info->soca->target_use_cap == 0)
- && (info->soca->hurry_up_flg == 0)) {
+ if (info->soca->target_use_cap == 0) {
info->soca->re_cap_old = re_cap;
get_target_use_cap(info);
}
-
- if((use_cap >= info->soca->target_use_cap)
- || (info->soca->hurry_up_flg == 1)) {
+
+ if(use_cap >= info->soca->target_use_cap) {
+ info->soca->displayed_soc = info->soca->displayed_soc - 100;
+ info->soca->displayed_soc = max(0, info->soca->displayed_soc);
+ info->soca->re_cap_old = re_cap;
+ } else if (info->soca->hurry_up_flg == 1) {
info->soca->displayed_soc = info->soca->displayed_soc - 100;
info->soca->displayed_soc = max(0, info->soca->displayed_soc);
info->soca->re_cap_old = re_cap;
}
if (RICOH619_SOCA_DISP == info->soca->status) {
- info->soca->soc = calc_capacity(info) * 100;
+ info->soca->soc = calc_capacity_2(info);
soc_round = info->soca->soc / 100;
last_soc_round = info->soca->last_soc / 100;
last_disp_round = (info->soca->displayed_soc + 50) / 100;
info->soca->soc_delta =
- info->soca->soc_delta + (soc_round - last_soc_round);
+ info->soca->soc_delta + (info->soca->soc - info->soca->last_soc);
info->soca->last_soc = info->soca->soc;
/* six case */
/* if SOC == DISPLAY move to stable */
info->soca->displayed_soc = info->soca->soc ;
info->soca->status = RICOH619_SOCA_STABLE;
+ delay_flag = 1;
} else if (info->soca->Ibat_ave > 0) {
if ((0 == info->soca->jt_limit) ||
- (POWER_SUPPLY_STATUS_FULL != info->soca->chg_status)) {
+ (POWER_SUPPLY_STATUS_FULL != info->soca->chg_status)) {
/* Charge */
if (last_disp_round < soc_round) {
/* Case 1 : Charge, Display < SOC */
- info->soca->update_count++;
- if ((info->soca->update_count
- >= RICOH619_UPDATE_COUNT_DISP)
- || (info->soca->soc_delta == 1)) {
+ if (info->soca->soc_delta >= 100) {
info->soca->displayed_soc
- = (last_disp_round + 1)*100;
- info->soca->update_count = 0;
- info->soca->soc_delta = 0;
+ = last_disp_round * 100 + 50;
+ info->soca->soc_delta -= 100;
+ if (info->soca->soc_delta >= 100)
+ delay_flag = 1;
+ } else {
+ info->soca->displayed_soc += 25;
+ disp_dec = info->soca->displayed_soc % 100;
+ if ((50 <= disp_dec) && (disp_dec <= 74))
+ info->soca->soc_delta = 0;
}
if (info->soca->displayed_soc/100
>= soc_round) {
= info->soca->soc ;
info->soca->status
= RICOH619_SOCA_STABLE;
+ delay_flag = 1;
}
} else if (last_disp_round > soc_round) {
/* Case 2 : Charge, Display > SOC */
- info->soca->update_count = 0;
- if (info->soca->soc_delta >= 3) {
- info->soca->displayed_soc =
- (last_disp_round + 1)*100;
- info->soca->soc_delta -= 3;
+ if (info->soca->soc_delta >= 300) {
+ info->soca->displayed_soc += 100;
+ info->soca->soc_delta -= 300;
}
if (info->soca->displayed_soc/100
<= soc_round) {
= info->soca->soc ;
info->soca->status
= RICOH619_SOCA_STABLE;
+ delay_flag = 1;
}
}
} else {
- info->soca->update_count = 0;
info->soca->soc_delta = 0;
}
} else {
/* Dis-Charge */
if (last_disp_round > soc_round) {
/* Case 3 : Dis-Charge, Display > SOC */
- info->soca->update_count++;
- if ((info->soca->update_count
- >= RICOH619_UPDATE_COUNT_DISP)
- || (info->soca->soc_delta == -1)) {
+ if (info->soca->soc_delta <= -100) {
info->soca->displayed_soc
- = (last_disp_round - 1)*100;
- info->soca->update_count = 0;
- info->soca->soc_delta = 0;
+ = last_disp_round * 100 - 75;
+ info->soca->soc_delta += 100;
+ if (info->soca->soc_delta <= -100)
+ delay_flag = 1;
+ } else {
+ info->soca->displayed_soc -= 25;
+ disp_dec = info->soca->displayed_soc % 100;
+ if ((25 <= disp_dec) && (disp_dec <= 49))
+ info->soca->soc_delta = 0;
}
if (info->soca->displayed_soc/100
<= soc_round) {
= info->soca->soc ;
info->soca->status
= RICOH619_SOCA_STABLE;
+ delay_flag = 1;
}
} else if (last_disp_round < soc_round) {
/* Case 4 : Dis-Charge, Display < SOC */
- info->soca->update_count = 0;
- if (info->soca->soc_delta <= -3) {
- info->soca->displayed_soc
- = (last_disp_round - 1)*100;
- info->soca->soc_delta += 3;
+ if (info->soca->soc_delta <= -300) {
+ info->soca->displayed_soc -= 100;
+ info->soca->soc_delta += 300;
}
if (info->soca->displayed_soc/100
>= soc_round) {
= info->soca->soc ;
info->soca->status
= RICOH619_SOCA_STABLE;
+ delay_flag = 1;
}
}
}
} else if (RICOH619_SOCA_UNSTABLE == info->soca->status) {
+ err = ricoh619_read(info->dev->parent, PSWR_REG, &val);
+ val &= 0x7f;
+ info->soca->soc = val * 100;
+ if (err < 0) {
+ dev_err(info->dev,
+ "Error in reading PSWR_REG %d\n", err);
+ info->soca->soc
+ = calc_capacity(info) * 100;
+ }
+
+ err = calc_capacity_in_period(info, &cc_cap,
+ &is_charging, false);
+ if (err < 0)
+ dev_err(info->dev, "Read cc_sum Error !!-----\n");
+
+ info->soca->cc_delta
+ = (is_charging == true) ? cc_cap : -cc_cap;
+
+ displayed_soc_temp
+ = info->soca->soc + info->soca->cc_delta;
+ if (displayed_soc_temp < 0)
+ displayed_soc_temp = 0;
+ displayed_soc_temp
+ = min(10000, displayed_soc_temp);
+ displayed_soc_temp = max(0, displayed_soc_temp);
+
if (0 == info->soca->jt_limit) {
- check_charge_status_2(info, info->soca->displayed_soc);
+ check_charge_status_2(info, displayed_soc_temp);
+ } else {
+ info->soca->displayed_soc = displayed_soc_temp;
}
} else if (RICOH619_SOCA_FG_RESET == info->soca->status) {
/* No update */
}
err = ricoh619_read(info->dev->parent, PSWR_REG, &val);
val &= 0x7f;
+ ////debug for Zero state///
+ ret = measure_vbatt_FG(info, &Vbat);
+ ret = measure_Ibatt_FG(info, &Ibat);
+ ocv = Vbat - Ibat * info->soca->Rbat;
+ RICOH_FG_DBG("Check ZERO state : Vbat %d, Ibat %d, ocv %d Rbat %d %d\n",Vbat,Ibat,ocv,info->soca->Rbat);
+ info->soca->soc = calc_capacity(info) * 100;
+ RICOH_FG_DBG("Check ZERO state : first_pwon %d, RSOC is %d OCV is %d\n",info->first_pwon,info->soca->soc/100,calc_ocv(info));
+ RICOH_FG_DBG("Check ZERO state : g_fg_on_mode %d, get ocv voltage %d\n",g_fg_on_mode,get_OCV_voltage(info, 0));
+ ///////////////////////////
if (info->first_pwon) {
info->soca->soc = calc_capacity(info) * 100;
+ val = (info->soca->soc + 50)/100;
+ val &= 0x7f;
+ err = ricoh619_write(info->dev->parent, PSWR_REG, val);
+ if (err < 0)
+ dev_err(info->dev, "Error in writing PSWR_REG\n");
+ g_soc = val;
+
if ((info->soca->soc == 0) && (calc_ocv(info)
< get_OCV_voltage(info, 0))) {
info->soca->displayed_soc = 0;
} else {
info->soca->displayed_soc = info->soca->soc;
}
+ info->soca->last_soc = info->soca->soc;
info->soca->status = RICOH619_SOCA_STABLE;
}
} else {
}
err = calc_capacity_in_period(info, &cc_cap,
- &is_charging);
+ &is_charging, false);
if (err < 0)
dev_err(info->dev, "Read cc_sum Error !!-----\n");
} else {
info->soca->displayed_soc = displayed_soc_temp;
}
+ info->soca->last_soc = calc_capacity(info) * 100;
info->soca->status = RICOH619_SOCA_UNSTABLE;
}
}
FG_CTRL_REG, 0x51);
if (err < 0)
dev_err(info->dev, "Error in writing the control register\n");
+ info->soca->last_soc = calc_capacity_2(info);
info->soca->status = RICOH619_SOCA_STABLE;
info->soca->ready_fg = 0;
}
if (err < 0)
dev_err(info->dev, "Error in writing PSWR_REG\n");
g_soc = 0x7F;
- } else {
- if (info->soca->displayed_soc < 0) {
- val = 0;
+ } else if (RICOH619_SOCA_UNSTABLE != info->soca->status) {
+ if (info->soca->displayed_soc <= 0) {
+ val = 1;
} else {
val = (info->soca->displayed_soc + 50)/100;
val &= 0x7f;
g_soc = val;
- err = calc_capacity_in_period(info, &cc_cap, &is_charging);
+ err = calc_capacity_in_period(info, &cc_cap,
+ &is_charging, true);
if (err < 0)
dev_err(info->dev, "Read cc_sum Error !!-----\n");
}
if (0 == info->soca->ready_fg)
queue_delayed_work(info->monitor_wqueue, &info->displayed_work,
RICOH619_FG_RESET_TIME * HZ);
+ else if (delay_flag == 1)
+ queue_delayed_work(info->monitor_wqueue, &info->displayed_work,
+ RICOH619_DELAY_TIME * HZ);
else if (RICOH619_SOCA_DISP == info->soca->status)
queue_delayed_work(info->monitor_wqueue, &info->displayed_work,
RICOH619_DISPLAY_UPDATE_TIME * HZ);
info->soca->last_soc = info->soca->soc;
info->soca->status = RICOH619_SOCA_DISP;
info->soca->soc_delta = 0;
- info->soca->update_count = 0;
}
mutex_unlock(&info->lock);
info->soca->n_cap = get_OCV_init_Data(info, 11);
info->soca->f_chg_margin = (get_OCV_voltage(info, 10) -
- get_OCV_voltage(info, 9)) / 10 * 3;
+ get_OCV_voltage(info, 9)) / 10;
info->soca->displayed_soc = 0;
info->soca->suspend_soc = 0;
info->soca->status = RICOH619_SOCA_START;
/* stable count down 11->2, 1: reset; 0: Finished; */
info->soca->stable_count = 11;
+ info->soca->chg_cmp_times = 0;
info->soca->dischg_state = 0;
info->soca->Vbat_ave = 0;
info->soca->Vsys_ave = 0;
info->soca->Ibat[i] = 0;
}
+ g_full_flag = 0;
+
#ifdef ENABLE_FG_KEEP_ON_MODE
g_fg_on_mode = 1;
#else
/* Check FG Reset */
if (info->soca->ready_fg) {
- temp = get_battery_temp(info) / 10;
+ temp = get_battery_temp_2(info) / 10;
} else {
RICOH_FG_DBG(KERN_INFO "JEITA: %s *** cannot update by resetting FG ******\n", __func__);
goto out;
return x;
}
+static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int cutoff_vol, int full_vol, int *start_per, int *end_per)
+{
+ int ret = 0;
+ int i, j;
+ int temp;
+ int percent_step;
+ int OCV_percent_new[11];
+
+ /* get ocv table. this table is calculated by Apprication */
+ //RICOH_FG_DBG("PMU : %s : original table\n",__func__);
+ for (i = 0; i <= 10; i = i+1) {
+ RICOH_FG_DBG(KERN_INFO "PMU: %s : %d0%% voltage = %d uV\n",
+ __func__, i, info->soca->ocv_table_def[i]);
+ }
+ //RICOH_FG_DBG("PMU: %s : cutoff_vol %d full_vol %d\n",
+ // __func__, cutoff_vol,full_vol);
+
+ /* Check Start % */
+ for (i = 1; i < 11; i++) {
+ if (info->soca->ocv_table_def[i] >= cutoff_vol * 1000) {
+ /* unit is 0.001% */
+ *start_per = Calc_Linear_Interpolation(
+ (i-1)*1000, info->soca->ocv_table_def[i-1], i*1000,
+ info->soca->ocv_table_def[i], (cutoff_vol * 1000));
+ i = 11;
+ }
+ }
+
+ /* Check End % */
+ for (i = 1; i < 11; i++) {
+ if (info->soca->ocv_table_def[i] >= full_vol * 1000) {
+ /* unit is 0.001% */
+ *end_per = Calc_Linear_Interpolation(
+ (i-1)*1000, info->soca->ocv_table_def[i-1], i*1000,
+ info->soca->ocv_table_def[i], (full_vol * 1000));
+ i = 11;
+ }
+ }
+
+ /* calc new ocv percent */
+ percent_step = ( *end_per - *start_per) / 10;
+ //RICOH_FG_DBG("PMU : %s : percent_step is %d end per is %d start per is %d\n",__func__, percent_step, *end_per, *start_per);
+
+ for (i = 0; i < 11; i++) {
+ OCV_percent_new[i]
+ = *start_per + percent_step*(i - 0);
+ }
+
+ /* calc new ocv voltage */
+ for (i = 0; i < 11; i++) {
+ for (j = 1; j < 11; j++) {
+ if (1000*j >= OCV_percent_new[i]) {
+ temp = Calc_Linear_Interpolation(
+ info->soca->ocv_table_def[j-1], (j-1)*1000,
+ info->soca->ocv_table_def[j] , j*1000,
+ OCV_percent_new[i]);
+
+ temp = ( (temp/1000) * 4095 ) / 5000;
+
+ battery_init_para[info->num][i*2 + 1] = temp;
+ battery_init_para[info->num][i*2] = temp >> 8;
+
+ j = 11;
+ }
+ }
+ }
+ RICOH_FG_DBG("PMU : %s : new table\n",__func__);
+ for (i = 0; i <= 10; i = i+1) {
+ temp = (battery_init_para[info->num][i*2]<<8)
+ | (battery_init_para[info->num][i*2+1]);
+ /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
+ temp = ((temp * 50000 * 10 / 4095) + 5) / 10;
+ RICOH_FG_DBG("PMU : %s : ocv_table %d is %d v\n",__func__, i, temp);
+ }
+
+}
+
static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info)
{
int ret = 0;
- int ocv_table[11];
+ int OCV_set_table[11];
int i, j;
+ int full_ocv;
int available_cap;
+ int available_cap_ori;
+ int OCV_100_def;
+ int OCV_0_def;
+ int OCV_100_diff;
+ int OCV_0_diff;
int temp;
- int start_par;
+ int start_per;
+ int end_per;
int percent_step;
int OCV_percent_new[11];
int Rbat;
int Ibat_min;
+ uint8_t val;
+ uint8_t val2;
+ uint8_t val_temp;
+
+
+ //get ocv table
+ for (i = 0; i <= 10; i = i+1) {
+ info->soca->ocv_table_def[i] = get_OCV_voltage(info, i);
+ RICOH_FG_DBG(KERN_INFO "PMU: %s : %d0%% voltage = %d uV\n",
+ __func__, i, info->soca->ocv_table_def[i]);
+ }
info->soca->target_vsys = info->fg_target_vsys;
info->soca->target_ibat = info->fg_target_ibat;
//for debug
- RICOH_FG_DBG("PMU : %s : target_vsys is %d target_ibat is %d",__func__,info->soca->target_vsys,info->soca->target_ibat);
+ RICOH_FG_DBG("PMU : %s : target_vsys is %d target_ibat is %d\n",__func__,info->soca->target_vsys,info->soca->target_ibat);
if ((info->soca->target_ibat == 0) || (info->soca->target_vsys == 0)) { /* normal version */
} else { /*Slice cutoff voltage version. */
- /* get ocv table. this table is calculated by Apprication */
- for (i = 0; i <= 10; i = i+1) {
- temp = (battery_init_para[info->num][i*2]<<8)
- | (battery_init_para[info->num][i*2+1]);
- /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
- temp = ((temp * 50000 * 10 / 4095) + 5) / 10;
- ocv_table[i] = temp;
-
- }
-
- /* get internal impedence */
temp = (battery_init_para[info->num][24]<<8) | (battery_init_para[info->num][25]);
Rbat = temp * 1000 / 512 * 5000 / 4095;
Ibat_min = -1 * info->soca->target_ibat;
info->soca->Rsys = Rbat + 55;
info->soca->cutoff_ocv = info->soca->target_vsys - Ibat_min * info->soca->Rsys / 1000;
+
+ full_ocv = (battery_init_para[info->num][20]<<8) | (battery_init_para[info->num][21]);
+ full_ocv = full_ocv * 5000 / 4095;
-
- RICOH_FG_DBG("PMU: ------- Rbat= %d: Rsys= %d: cutoff_ocv= %d: =======\n",
- Rbat, info->soca->Rsys, info->soca->cutoff_ocv);
-
- /* Check Start % */
- for (i = 1; i < 11; i++) {
- if (ocv_table[i] >= info->soca->cutoff_ocv * 10) {
- /* unit is 0.001% */
- start_par = Calc_Linear_Interpolation(
- (i-1)*1000, ocv_table[i-1], i*1000,
- ocv_table[i], (info->soca->cutoff_ocv * 10));
- i = 11;
- }
- }
- /* calc new ocv percent */
- percent_step = (10000 - start_par) / 10;
-
- for (i = 0; i < 11; i++) {
- OCV_percent_new[i]
- = start_par + percent_step*(i - 0);
- }
-
- /* calc new ocv voltage */
- for (i = 0; i < 11; i++) {
- for (j = 1; j < 11; j++) {
- if (1000*j >= OCV_percent_new[i]) {
- temp = Calc_Linear_Interpolation(
- ocv_table[j-1], (j-1)*1000,
- ocv_table[j] , j*1000,
- OCV_percent_new[i]);
-
- temp = temp * 4095 / 50000;
-
- battery_init_para[info->num][i*2 + 1] = temp;
- battery_init_para[info->num][i*2] = temp >> 8;
-
- j = 11;
- }
- }
- }
-
- for (i = 0; i <= 10; i = i+1) {
- temp = (battery_init_para[info->num][i*2]<<8)
- | (battery_init_para[info->num][i*2+1]);
- /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
- temp = ((temp * 50000 * 10 / 4095) + 5) / 10;
- RICOH_FG_DBG("PMU: ------- ocv_table[%d]= %d: =======\n",
- i, temp);
- }
-
+ ricoh619_scaling_OCV_table(info, info->soca->cutoff_ocv, full_ocv, &start_per, &end_per);
/* calc available capacity */
/* get avilable capacity */
| (battery_init_para[info->num][23]);
available_cap = available_cap
- * ((10000 - start_par) / 100) / 100 ;
+ * ((10000 - start_per) / 100) / 100 ;
battery_init_para[info->num][23] = available_cap;
battery_init_para[info->num][22] = available_cap >> 8;
}
- ret = ricoh619_bulk_writes_bank1(info->dev->parent,
- BAT_INIT_TOP_REG, 32, battery_init_para[info->num]);
+ ret = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01);
if (ret < 0) {
+ dev_err(info->dev, "error in FG_En off\n");
+ goto err;
+ }
+ ////////////////////////////////
+ ////////////////////////////////
+ //check OCV calibration or not
+ /* get ocv table from setting */
+ for (i = 0; i < 11; i++){
+ ret = ricoh619_read_bank1(info->dev->parent, (0xBC + i*2), &val);
+ if (ret < 0) {
dev_err(info->dev, "batterry initialize error\n");
return ret;
+ }
+ ret = ricoh619_read_bank1(info->dev->parent, (0xBD + i*2), &val2);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ return ret;
+ }
+ val &= 0x0F;
+ OCV_set_table[i] = val2 + (val << 8);
+ RICOH_FG_DBG("PMU : %s : no %d OCV_set_table %x\n", __func__, i, OCV_set_table[i]);
+
}
- return 1;
+ OCV_100_def = (battery_init_para[info->num][20]<<8)
+ | (battery_init_para[info->num][21]);
+
+ OCV_0_def = (battery_init_para[info->num][0]<<8)
+ | (battery_init_para[info->num][1]);
+
+ if(OCV_100_def < OCV_set_table[10]) {
+ OCV_100_diff = OCV_set_table[10] - OCV_100_def;
+ } else {
+ OCV_100_diff = OCV_100_def - OCV_set_table[10];
+ }
+
+ if(OCV_0_def < OCV_set_table[0]) {
+ OCV_0_diff = OCV_set_table[0] - OCV_0_def;
+ } else {
+ OCV_0_diff = OCV_0_def - OCV_set_table[0];
+ }
+ RICOH_FG_DBG("PMU : %s : def OCV 100 %x OCV 0 %x \n", __func__, OCV_100_def, OCV_0_def);
+ RICOH_FG_DBG("PMU : %s : OCV 100 %x OCV 0 %x \n", __func__, OCV_set_table[10], OCV_set_table[0]);
+ RICOH_FG_DBG("PMU : %s : diff OCV 100 %x OCV 0 %x \n", __func__, OCV_100_diff, OCV_0_diff);
+
+ if ( (OCV_100_diff > 5)
+ &&(OCV_0_diff < 5))
+ {/* keep setting OCV table */
+ for (i = 0; i < 11; i++) {
+ RICOH_FG_DBG("PMU : 1\n");
+ battery_init_para[info->num][i*2+1] = OCV_set_table[i];
+ battery_init_para[info->num][i*2] = OCV_set_table[i] >> 8;
+ }
+ }
+
+ /////////////////////////////////
+ ret = ricoh619_read_bank1(info->dev->parent, 0xDC, &val);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+
+ val_temp = val;
+ val &= 0x0F; //clear bit 4-7
+ val |= 0x10; //set bit 4
+
+ ret = ricoh619_write_bank1(info->dev->parent, 0xDC, val);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+
+ ret = ricoh619_read_bank1(info->dev->parent, 0xDC, &val2);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+
+ ret = ricoh619_write_bank1(info->dev->parent, 0xDC, val_temp);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+
+ RICOH_FG_DBG("PMU : %s : original 0x%x, before 0x%x, after 0x%x\n",__func__, val_temp, val, val2);
+
+ if (val != val2) {
+ ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+ BAT_INIT_TOP_REG, 30, battery_init_para[info->num]);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+ } else {
+ ret = ricoh619_read_bank1(info->dev->parent, 0xD2, &val);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+
+ ret = ricoh619_read_bank1(info->dev->parent, 0xD3, &val2);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+
+ available_cap_ori = val2 + (val << 8);
+ available_cap = battery_init_para[info->num][23]
+ + (battery_init_para[info->num][22] << 8);
+
+ if (available_cap_ori == available_cap) {
+ ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+ BAT_INIT_TOP_REG, 22, battery_init_para[info->num]);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ return ret;
+ }
+
+ for (i = 0; i < 6; i++) {
+ ret = ricoh619_write_bank1(info->dev->parent, 0xD4+i, battery_init_para[info->num][23+i]);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ return ret;
+ }
+ }
+ } else {
+ ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+ BAT_INIT_TOP_REG, 30, battery_init_para[info->num]);
+ if (ret < 0) {
+ dev_err(info->dev, "batterry initialize error\n");
+ goto err;
+ }
+ }
+ }
+
+ ////////////////////////////////
+
+ return 0;
+err:
+ return ret;
}
/* Initial setting of battery */
return ret;
}
- ret = ricoh619_read(info->dev->parent, FG_CTRL_REG, &val);
+// ret = ricoh619_read(info->dev->parent, FG_CTRL_REG, &val);
+// if (ret < 0) {
+// dev_err(info->dev, "Error in reading the control register\n");
+// return ret;
+// }
+
+// val = (val & 0x10) >> 4;
+// info->first_pwon = (val == 0) ? 1 : 0;
+ ret = ricoh619_read(info->dev->parent, PSWR_REG, &val);
if (ret < 0) {
- dev_err(info->dev, "Error in reading the control register\n");
+ dev_err(info->dev,"Error in reading PSWR_REG %d\n", ret);
return ret;
}
-
- val = (val & 0x10) >> 4;
info->first_pwon = (val == 0) ? 1 : 0;
-
+ g_soc = val & 0x7f;
+
ret = ricoh619_set_OCV_table(info);
if (ret < 0) {
dev_err(info->dev, "Error in writing the OCV Tabler\n");
static int ricoh619_init_charger(struct ricoh619_battery_info *info)
{
int err;
+ int i;
uint8_t val;
uint8_t val2;
uint8_t val3;
int charge_status;
+ int vfchg_val;
+ int icchg_val;
+ int rbat;
+ int temp;
info->chg_ctr = 0;
info->chg_stat1 = 0;
goto free_device;
}
}
+ /* get OCV100_min, OCV100_min*/
+ temp = (battery_init_para[info->num][24]<<8) | (battery_init_para[info->num][25]);
+ rbat = temp * 1000 / 512 * 5000 / 4095;
+
+ /* get vfchg value */
+ err = ricoh619_read(info->dev->parent, BATSET2_REG, &val);
+ if (err < 0) {
+ dev_err(info->dev, "Error in reading the batset2reg\n");
+ goto free_device;
+ }
+ val &= 0x70;
+ val2 = val >> 4;
+ if (val2 <= 3) {
+ vfchg_val = 4050 + val2 * 50;
+ } else {
+ vfchg_val = 4350;
+ }
+ RICOH_FG_DBG("PMU : %s : test test val %d, val2 %d vfchg %d\n", __func__, val, val2, vfchg_val);
+
+ /* get value */
+ err = ricoh619_read(info->dev->parent, CHGISET_REG, &val);
+ if (err < 0) {
+ dev_err(info->dev, "Error in reading the chgisetreg\n");
+ goto free_device;
+ }
+ val &= 0xC0;
+ val2 = val >> 6;
+ icchg_val = 50 + val2 * 50;
+ RICOH_FG_DBG("PMU : %s : test test val %d, val2 %d icchg %d\n", __func__, val, val2, icchg_val);
+
+ info->soca->OCV100_min = ( vfchg_val * 99 / 100 - (icchg_val * (rbat +20))/1000 - 20 ) * 1000;
+ info->soca->OCV100_max = ( vfchg_val * 101 / 100 - (icchg_val * (rbat +20))/1000 + 20 ) * 1000;
+
+ RICOH_FG_DBG("PMU : %s : 100 min %d, 100 max %d vfchg %d icchg %d rbat %d\n",__func__,
+ info->soca->OCV100_min,info->soca->OCV100_max,vfchg_val,icchg_val,rbat);
#ifdef ENABLE_LOW_BATTERY_DETECTION
/* Set ADRQ=00 to stop ADC */
ricoh619_write(info->dev->parent, RICOH619_ADC_CNT2, 0x0);
/* Enable VSYS pin conversion in auto-ADC */
ricoh619_write(info->dev->parent, RICOH619_ADC_CNT1, 0x10);
- /* Set VSYS threshold low voltage = 3.50v */
- ricoh619_write(info->dev->parent, RICOH619_ADC_VSYS_THL, 0x77);
+ /* Set VSYS threshold low voltage value = (voltage(V)*255)/(3*2.5) */
+ val = info->alarm_vol_mv * 255 / 7500;
+ ricoh619_write(info->dev->parent, RICOH619_ADC_VSYS_THL, val);
/* Start auto-mode & average 4-time conversion mode for ADC */
ricoh619_write(info->dev->parent, RICOH619_ADC_CNT3, 0x28);
/* Enable master ADC INT */
int nt;
int temperature;
- temperature = get_battery_temp(info) / 10; /* unit 0.1 degree -> 1 degree */
+ temperature = get_battery_temp_2(info) / 10; /* unit 0.1 degree -> 1 degree */
if (temperature >= 25) {
nt = 0;
return temp; /* Unit is 1% */
}
+static int calc_capacity_2(struct ricoh619_battery_info *info)
+{
+ uint8_t val;
+ long capacity;
+ int re_cap, fa_cap;
+ int temp;
+ int ret = 0;
+ int nt;
+ int temperature;
+
+ temperature = get_battery_temp_2(info) / 10; /* unit 0.1 degree -> 1 degree */
+
+ if (temperature >= 25) {
+ nt = 0;
+ } else if (temperature >= 5) {
+ nt = (25 - temperature) * RICOH619_TAH_SEL2 * 625 / 100;
+ } else {
+ nt = (625 + (5 - temperature) * RICOH619_TAL_SEL2 * 625 / 100);
+ }
+
+ re_cap = get_check_fuel_gauge_reg(info, RE_CAP_H_REG, RE_CAP_L_REG,
+ 0x7fff);
+ fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG,
+ 0x7fff);
+
+ if (fa_cap != 0) {
+ capacity = ((long)re_cap * 100 * 100 / fa_cap) + 50;
+ capacity = min(10000, capacity);
+ capacity = max(0, capacity);
+ } else {
+ ret = ricoh619_read(info->dev->parent, SOC_REG, &val);
+ if (ret < 0) {
+ dev_err(info->dev, "Error in reading the control register\n");
+ return ret;
+ }
+ capacity = (long)val * 100;
+ }
+
+
+ temp = (int)(capacity * 100 * 100 / (10000 - nt));
+
+ return temp; /* Unit is 0.01% */
+}
+
static int get_battery_temp(struct ricoh619_battery_info *info)
{
int ret = 0;
return ret;
}
+static int get_battery_temp_2(struct ricoh619_battery_info *info)
+{
+ uint8_t reg_buff[2];
+ long temp, temp_off, temp_gain;
+ bool temp_sign, temp_off_sign, temp_gain_sign;
+ int Vsns = 0;
+ int Iout = 0;
+ int Vthm, Rthm;
+ int reg_val = 0;
+ int new_temp;
+ long R_ln1, R_ln2;
+ int ret = 0;
+
+ /* Calculate TEMP */
+ ret = get_check_fuel_gauge_reg(info, TEMP_1_REG, TEMP_2_REG, 0x0fff);
+ if (ret < 0) {
+ dev_err(info->dev, "Error in reading the fuel gauge register\n");
+ goto out;
+ }
+
+ reg_val = ret;
+ temp_sign = (reg_val & 0x0800) >> 11;
+ reg_val = (reg_val & 0x07ff);
+
+ if (temp_sign == 0) /* positive value part */
+ /* the unit is 0.0001 degree */
+ temp = (long)reg_val * 625;
+ else { /*negative value part */
+ reg_val = (~reg_val + 1) & 0x7ff;
+ temp = -1 * (long)reg_val * 625;
+ }
+
+ /* Calculate TEMP_OFF */
+ ret = ricoh619_bulk_reads_bank1(info->dev->parent,
+ TEMP_OFF_H_REG, 2, reg_buff);
+ if (ret < 0) {
+ dev_err(info->dev, "Error in reading the fuel gauge register\n");
+ goto out;
+ }
+
+ reg_val = reg_buff[0] << 8 | reg_buff[1];
+ temp_off_sign = (reg_val & 0x0800) >> 11;
+ reg_val = (reg_val & 0x07ff);
+
+ if (temp_off_sign == 0) /* positive value part */
+ /* the unit is 0.0001 degree */
+ temp_off = (long)reg_val * 625;
+ else { /*negative value part */
+ reg_val = (~reg_val + 1) & 0x7ff;
+ temp_off = -1 * (long)reg_val * 625;
+ }
+
+ /* Calculate TEMP_GAIN */
+ ret = ricoh619_bulk_reads_bank1(info->dev->parent,
+ TEMP_GAIN_H_REG, 2, reg_buff);
+ if (ret < 0) {
+ dev_err(info->dev, "Error in reading the fuel gauge register\n");
+ goto out;
+ }
+
+ reg_val = reg_buff[0] << 8 | reg_buff[1];
+ temp_gain_sign = (reg_val & 0x0800) >> 11;
+ reg_val = (reg_val & 0x07ff);
+
+ if (temp_gain_sign == 0) /* positive value part */
+ /* 1 unit is 0.000488281. the result is 0.01 */
+ temp_gain = (long)reg_val * 488281 / 100000;
+ else { /*negative value part */
+ reg_val = (~reg_val + 1) & 0x7ff;
+ temp_gain = -1 * (long)reg_val * 488281 / 100000;
+ }
+
+ /* Calculate VTHM */
+ if (0 != temp_gain)
+ Vthm = (int)((temp - temp_off) / 4095 * 2500 / temp_gain);
+ else {
+ RICOH_FG_DBG("PMU %s Skip to compensate temperature\n", __func__);
+ goto out;
+ }
+
+ ret = measure_Ibatt_FG(info, &Iout);
+ Vsns = Iout * 2 / 100;
+
+ if (temp < -120000) {
+ /* Low Temperature */
+ if (0 != (2500 - Vthm)) {
+ Rthm = 10 * 10 * (Vthm - Vsns) / (2500 - Vthm);
+ } else {
+ RICOH_FG_DBG("PMU %s Skip to compensate temperature\n", __func__);
+ goto out;
+ }
+
+ R_ln1 = Rthm / 10;
+ R_ln2 = (R_ln1 * R_ln1 * R_ln1 * R_ln1 * R_ln1 / 100000
+ - R_ln1 * R_ln1 * R_ln1 * R_ln1 * 2 / 100
+ + R_ln1 * R_ln1 * R_ln1 * 11
+ - R_ln1 * R_ln1 * 2980
+ + R_ln1 * 449800
+ - 784000) / 10000;
+
+ /* the unit of new_temp is 0.1 degree */
+ new_temp = (int)((100 * 1000 * B_VALUE / (R_ln2 + B_VALUE * 100 * 1000 / 29815) - 27315) / 10);
+ RICOH_FG_DBG("PMU %s low temperature %d\n", __func__, new_temp/10);
+ } else if (temp > 520000) {
+ /* High Temperature */
+ if (0 != (2500 - Vthm)) {
+ Rthm = 100 * 10 * (Vthm - Vsns) / (2500 - Vthm);
+ } else {
+ RICOH_FG_DBG("PMU %s Skip to compensate temperature\n", __func__);
+ goto out;
+ }
+ RICOH_FG_DBG("PMU %s [Rthm] Rthm %d[ohm]\n", __func__, Rthm);
+
+ R_ln1 = Rthm / 10;
+ R_ln2 = (R_ln1 * R_ln1 * R_ln1 * R_ln1 * R_ln1 / 100000 * 15652 / 100
+ - R_ln1 * R_ln1 * R_ln1 * R_ln1 / 1000 * 23103 / 100
+ + R_ln1 * R_ln1 * R_ln1 * 1298 / 100
+ - R_ln1 * R_ln1 * 35089 / 100
+ + R_ln1 * 50334 / 10
+ - 48569) / 100;
+ /* the unit of new_temp is 0.1 degree */
+ new_temp = (int)((100 * 100 * B_VALUE / (R_ln2 + B_VALUE * 100 * 100 / 29815) - 27315) / 10);
+ RICOH_FG_DBG("PMU %s high temperature %d\n", __func__, new_temp/10);
+ } else {
+ /* the unit of new_temp is 0.1 degree */
+ new_temp = temp / 1000;
+ }
+
+ return new_temp;
+
+out:
+ new_temp = get_battery_temp(info);
+ return new_temp;
+}
+
static int get_time_to_empty(struct ricoh619_battery_info *info)
{
int ret = 0;
mutex_lock(&info->lock);
switch (psp) {
+#if 0
case POWER_SUPPLY_PROP_ONLINE:
ret = ricoh619_read(info->dev->parent, CHGSTATE_REG, &status);
if (ret < 0) {
else if (psy->type == POWER_SUPPLY_TYPE_USB)
val->intval = (status & 0x80 ? 1 : 0);
break;
+#endif
/* this setting is same as battery driver of 584 */
case POWER_SUPPLY_PROP_STATUS:
ret = get_power_supply_status(info);
case POWER_SUPPLY_PROP_TEMP:
if (info->soca->ready_fg) {
ret = 0;
- val->intval = get_battery_temp(info);
+ val->intval = get_battery_temp_2(info);
info->battery_temp = val->intval/10;
RICOH_FG_DBG( "battery temperature is %d degree\n", info->battery_temp);
} else {
int type_n;
int ret, temp;
- RICOH_FG_DBG("PMU: %s\n", __func__);
-
+ RICOH_FG_DBG("PMU:2013.8.3 %s\n", __func__);
+
info = kzalloc(sizeof(struct ricoh619_battery_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if (err < 0)
dev_err(info->dev, "Error in writing PSWR_REG\n");
g_soc = 0x7f;
- } else {
- if (info->soca->displayed_soc < 0) {
- val = 0;
+ } else if (info->soca->status != RICOH619_SOCA_START
+ && info->soca->status != RICOH619_SOCA_UNSTABLE) {
+ if (info->soca->displayed_soc <= 0) {
+ val = 1;
} else {
val = (info->soca->displayed_soc + 50)/100;
val &= 0x7f;
g_soc = val;
- ret = calc_capacity_in_period(info, &cc_cap, &is_charging);
+ ret = calc_capacity_in_period(info, &cc_cap,
+ &is_charging, true);
if (ret < 0)
dev_err(info->dev, "Read cc_sum Error !!-----\n");
}
if (err < 0)
dev_err(info->dev, "Error in writing PSWR_REG\n");
g_soc = 0x7F;
- info->soca->suspend_soc = (info->soca->displayed_soc + 50)/100;
- } else {
- if (info->soca->displayed_soc < 0) {
- val = 0;
+ info->soca->suspend_soc = info->soca->displayed_soc;
+ } else if (info->soca->status != RICOH619_SOCA_START
+ && info->soca->status != RICOH619_SOCA_UNSTABLE) {
+ if (info->soca->displayed_soc <= 0) {
+ val = 1;
} else {
val = (info->soca->displayed_soc + 50)/100;
val &= 0x7f;
g_soc = val;
- info->soca->suspend_soc = (info->soca->displayed_soc + 50)/100;
+ info->soca->suspend_soc = info->soca->displayed_soc;
- ret = calc_capacity_in_period(info, &cc_cap, &is_charging);
+ ret = calc_capacity_in_period(info, &cc_cap,
+ &is_charging, true);
if (ret < 0)
dev_err(info->dev, "Read cc_sum Error !!-----\n");
+ } else if (info->soca->status == RICOH619_SOCA_START
+ || info->soca->status == RICOH619_SOCA_UNSTABLE) {
+
+ ret = ricoh619_read(info->dev->parent, PSWR_REG, &val);
+ if (ret < 0)
+ dev_err(info->dev, "Error in reading the pswr register\n");
+ val &= 0x7f;
+
+ info->soca->suspend_soc = val * 100;
+ }
+
+ if (info->soca->status == RICOH619_SOCA_DISP
+ || info->soca->status == RICOH619_SOCA_STABLE
+ || info->soca->status == RICOH619_SOCA_FULL) {
+ info->soca->soc = calc_capacity_2(info);
+ info->soca->soc_delta =
+ info->soca->soc_delta + (info->soca->soc - info->soca->last_soc);
+
+ } else {
+ info->soca->soc_delta = 0;
}
if (info->soca->status == RICOH619_SOCA_STABLE
|| info->soca->status == RICOH619_SOCA_FULL)
info->soca->status = RICOH619_SOCA_DISP;
-
/* set rapid timer 300 min */
err = ricoh619_set_bits(info->dev->parent, TIMSET_REG, 0x03);
if (err < 0) {
}
ret = calc_capacity_in_period(info, &cc_cap,
- &is_charging);
+ &is_charging, true);
if (ret < 0)
dev_err(info->dev, "Read cc_sum Error !!-----\n");
} else
info->soca->displayed_soc = 0;
} else {
- info->soca->soc = info->soca->suspend_soc * 100;
+ info->soca->soc = info->soca->suspend_soc;
+
+ if (RICOH619_SOCA_START == info->soca->status
+ || RICOH619_SOCA_UNSTABLE == info->soca->status) {
+ ret = calc_capacity_in_period(info, &cc_cap,
+ &is_charging, false);
+ } else {
+ ret = calc_capacity_in_period(info, &cc_cap,
+ &is_charging, true);
+ }
- ret = calc_capacity_in_period(info, &cc_cap, &is_charging);
if (ret < 0)
dev_err(info->dev, "Read cc_sum Error !!-----\n");
}
if (RICOH619_SOCA_DISP == info->soca->status) {
- info->soca->last_soc = calc_capacity(info) * 100;
- info->soca->soc_delta = 0;
+ info->soca->last_soc = calc_capacity_2(info);
}
}
info->soca->update_count = 0;
RICOH619_JEITA_UPDATE_TIME * HZ);
}
}
- ricoh619_write(info->dev->parent, 0x9d, 0x00);
+// ricoh619_write(info->dev->parent, 0x9d, 0x00);
// enable_irq(charger_irq + RICOH619_IRQ_FONCHGINT);
// enable_irq(charger_irq + RICOH619_IRQ_FCHGCMPINT);
// enable_irq(charger_irq + RICOH619_IRQ_FVUSBDETSINT);
* 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
* 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/>.
*
*/
#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,
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;
}
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;
+
+// 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;
-// print_time(dev, tm);
+ 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");
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;
-
- 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;
+ uint8_t reg_data;
+
+ 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);
-
- dev_info(dev->parent, "\n setting alarm to requested time::\n");
-// print_time(dev->parent, &alrm->time);
-
- if (WARN_ON(alrm->enabled && (seconds < rtc->epoch_start))) {
- dev_err(dev->parent, "\n can't set alarm to requested time\n");
- return -EINVAL;
+ else
+ {
+ if(reg_data & 0x40)
+ *enabled = 1;
+ else
+ *enabled = 0;
}
+ return 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;
+// 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;
+
+// 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);
}
-
- err = ricoh619_read_regs(dev, rtc_ctrl2, 1, buff);
- if (err) {
- dev_err(dev->parent, "unable to read rtc_ctrl2 reg\n");
- return -EBUSY;
+ 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);
}
- 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;
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__);
-
- if (!rtc)
- return -ENOMEM;
+ uint8_t buff[6];
- rtc->irq = -1;
+// 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");
- if (!pdata) {
+ if(!pdata)
+ {
dev_err(&pdev->dev, "no platform_data specified\n");
return -EINVAL;
}
- if (pdata->irq < 0)
+ 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);
+ if(IS_ERR(rtc->rtc))
+ {
+ err = PTR_ERR(rtc->rtc);
+ goto fail;
+ }
+
+ 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;
+ }
- 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);
+ //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;
- if (IS_ERR(rtc->rtc)) {
- err = PTR_ERR(rtc->rtc);
+ }
+
+ // 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;
}
- 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;
+ // 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;
}
- reg = 0; /* clearing RTC Adjust register */
- err = ricoh619_write_regs(&pdev->dev, rtc_adjust, 1, ®);
- if (err) {
+ // 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;
+ }
+
+ //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;
}
- /* 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;
- }
- 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;
- }
- } else {
- err = ricoh619_rtc_read_time(&pdev->dev, &tm);
- if (err) {
- dev_err(&pdev->dev, "\n failed to read time\n");
- return err;
+ // 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;
}
- }
- 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
+
+ // 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;
+ }
+
+ // 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: