[PATCH 38/40] abx500-chargalg: Add charging current step interface

2013-02-15 Thread Lee Jones
To prevent overheating, provide differnt steps of charging current
interface to allow thermal mitigation. This will provide possibility
to reduce gradually the charging current.

Signed-off-by: Lee Jones 
---
 drivers/power/abx500_chargalg.c |  231 ++-
 1 file changed, 155 insertions(+), 76 deletions(-)

diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 7e4bc01..9863e42 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -47,6 +47,9 @@
 /* Plus margin for the low battery threshold */
 #define BAT_PLUS_MARGIN(100)
 
+#define CHARGALG_CURR_STEP_LOW 0
+#define CHARGALG_CURR_STEP_HIGH100
+
 #define to_abx500_chargalg_device_info(x) container_of((x), \
struct abx500_chargalg, chargalg_psy);
 
@@ -80,6 +83,11 @@ struct abx500_chargalg_suspension_status {
bool usb_suspended;
 };
 
+struct abx500_chargalg_current_step_status {
+   bool curr_step_change;
+   int curr_step;
+};
+
 struct abx500_chargalg_battery_data {
int temp;
int volt;
@@ -220,6 +228,7 @@ enum maxim_ret {
  * @batt_data: data of the battery
  * @susp_status:   current charger suspension status
  * @bm:Platform specific battery management information
+ * @curr_status:   Current step status for over-current protection
  * @parent:pointer to the struct abx500
  * @chargalg_psy:  structure that holds the battery properties exposed by
  * the charging algorithm
@@ -245,6 +254,7 @@ struct abx500_chargalg {
struct abx500_chargalg_battery_data batt_data;
struct abx500_chargalg_suspension_status susp_status;
struct ab8500 *parent;
+   struct abx500_chargalg_current_step_status curr_status;
struct abx500_bm_data *bm;
struct power_supply chargalg_psy;
struct ux500_charger *ac_chg;
@@ -268,6 +278,12 @@ static enum power_supply_property abx500_chargalg_props[] 
= {
POWER_SUPPLY_PROP_HEALTH,
 };
 
+struct abx500_chargalg_sysfs_entry {
+   struct attribute attr;
+   ssize_t (*show)(struct abx500_chargalg *, char *);
+   ssize_t (*store)(struct abx500_chargalg *, const char *, size_t);
+};
+
 /**
  * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
  * @timer: pointer to the hrtimer structure
@@ -402,6 +418,22 @@ static int abx500_chargalg_check_charger_connection(struct 
abx500_chargalg *di)
 }
 
 /**
+ * abx500_chargalg_check_current_step_status() - Check charging current
+ * step status.
+ * @di:pointer to the abx500_chargalg structure
+ *
+ * This function will check if there is a change in the charging current step
+ * and change charge state accordingly.
+ */
+static void abx500_chargalg_check_current_step_status
+   (struct abx500_chargalg *di)
+{
+   if (di->curr_status.curr_step_change)
+   abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
+   di->curr_status.curr_step_change = false;
+}
+
+/**
  * abx500_chargalg_start_safety_timer() - Start charging safety timer
  * @di:pointer to the abx500_chargalg structure
  *
@@ -1300,6 +1332,7 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di)
 {
int charger_status;
int ret;
+   int curr_step_lvl;
 
/* Collect data from all power_supply class devices */
class_for_each_device(power_supply_class, NULL,
@@ -1310,6 +1343,7 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di)
abx500_chargalg_check_charger_voltage(di);
 
charger_status = abx500_chargalg_check_charger_connection(di);
+   abx500_chargalg_check_current_step_status(di);
 
if (is_ab8500(di->parent)) {
ret = abx500_chargalg_check_charger_enable(di);
@@ -1523,9 +1557,18 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di)
}
}
 
-   abx500_chargalg_start_charging(di,
-   di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
-   di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
+   if (di->curr_status.curr_step == CHARGALG_CURR_STEP_LOW)
+   abx500_chargalg_stop_charging(di);
+   else {
+   curr_step_lvl = di->bm->bat_type[
+   di->bm->batt_id].normal_cur_lvl
+   * di->curr_status.curr_step
+   / CHARGALG_CURR_STEP_HIGH;
+   abx500_chargalg_start_charging(di,
+   di->bm->bat_type[di->bm->batt_id]
+   .normal_vol_lvl, curr_step_lvl);
+   }
+
abx500_chargalg_state_to(di, STATE_NORMAL);
abx500_chargalg_start_safety_timer(di);
abx500_chargalg_stop_maintenance_timer(di);
@@ 

[PATCH 38/40] abx500-chargalg: Add charging current step interface

2013-02-15 Thread Lee Jones
To prevent overheating, provide differnt steps of charging current
interface to allow thermal mitigation. This will provide possibility
to reduce gradually the charging current.

Signed-off-by: Lee Jones lee.jo...@linaro.org
---
 drivers/power/abx500_chargalg.c |  231 ++-
 1 file changed, 155 insertions(+), 76 deletions(-)

diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 7e4bc01..9863e42 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -47,6 +47,9 @@
 /* Plus margin for the low battery threshold */
 #define BAT_PLUS_MARGIN(100)
 
+#define CHARGALG_CURR_STEP_LOW 0
+#define CHARGALG_CURR_STEP_HIGH100
+
 #define to_abx500_chargalg_device_info(x) container_of((x), \
struct abx500_chargalg, chargalg_psy);
 
@@ -80,6 +83,11 @@ struct abx500_chargalg_suspension_status {
bool usb_suspended;
 };
 
+struct abx500_chargalg_current_step_status {
+   bool curr_step_change;
+   int curr_step;
+};
+
 struct abx500_chargalg_battery_data {
int temp;
int volt;
@@ -220,6 +228,7 @@ enum maxim_ret {
  * @batt_data: data of the battery
  * @susp_status:   current charger suspension status
  * @bm:Platform specific battery management information
+ * @curr_status:   Current step status for over-current protection
  * @parent:pointer to the struct abx500
  * @chargalg_psy:  structure that holds the battery properties exposed by
  * the charging algorithm
@@ -245,6 +254,7 @@ struct abx500_chargalg {
struct abx500_chargalg_battery_data batt_data;
struct abx500_chargalg_suspension_status susp_status;
struct ab8500 *parent;
+   struct abx500_chargalg_current_step_status curr_status;
struct abx500_bm_data *bm;
struct power_supply chargalg_psy;
struct ux500_charger *ac_chg;
@@ -268,6 +278,12 @@ static enum power_supply_property abx500_chargalg_props[] 
= {
POWER_SUPPLY_PROP_HEALTH,
 };
 
+struct abx500_chargalg_sysfs_entry {
+   struct attribute attr;
+   ssize_t (*show)(struct abx500_chargalg *, char *);
+   ssize_t (*store)(struct abx500_chargalg *, const char *, size_t);
+};
+
 /**
  * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
  * @timer: pointer to the hrtimer structure
@@ -402,6 +418,22 @@ static int abx500_chargalg_check_charger_connection(struct 
abx500_chargalg *di)
 }
 
 /**
+ * abx500_chargalg_check_current_step_status() - Check charging current
+ * step status.
+ * @di:pointer to the abx500_chargalg structure
+ *
+ * This function will check if there is a change in the charging current step
+ * and change charge state accordingly.
+ */
+static void abx500_chargalg_check_current_step_status
+   (struct abx500_chargalg *di)
+{
+   if (di-curr_status.curr_step_change)
+   abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
+   di-curr_status.curr_step_change = false;
+}
+
+/**
  * abx500_chargalg_start_safety_timer() - Start charging safety timer
  * @di:pointer to the abx500_chargalg structure
  *
@@ -1300,6 +1332,7 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di)
 {
int charger_status;
int ret;
+   int curr_step_lvl;
 
/* Collect data from all power_supply class devices */
class_for_each_device(power_supply_class, NULL,
@@ -1310,6 +1343,7 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di)
abx500_chargalg_check_charger_voltage(di);
 
charger_status = abx500_chargalg_check_charger_connection(di);
+   abx500_chargalg_check_current_step_status(di);
 
if (is_ab8500(di-parent)) {
ret = abx500_chargalg_check_charger_enable(di);
@@ -1523,9 +1557,18 @@ static void abx500_chargalg_algorithm(struct 
abx500_chargalg *di)
}
}
 
-   abx500_chargalg_start_charging(di,
-   di-bm-bat_type[di-bm-batt_id].normal_vol_lvl,
-   di-bm-bat_type[di-bm-batt_id].normal_cur_lvl);
+   if (di-curr_status.curr_step == CHARGALG_CURR_STEP_LOW)
+   abx500_chargalg_stop_charging(di);
+   else {
+   curr_step_lvl = di-bm-bat_type[
+   di-bm-batt_id].normal_cur_lvl
+   * di-curr_status.curr_step
+   / CHARGALG_CURR_STEP_HIGH;
+   abx500_chargalg_start_charging(di,
+   di-bm-bat_type[di-bm-batt_id]
+   .normal_vol_lvl, curr_step_lvl);
+   }
+
abx500_chargalg_state_to(di, STATE_NORMAL);
abx500_chargalg_start_safety_timer(di);
abx500_chargalg_stop_maintenance_timer(di);
@@