aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Bjornstedt <johan.bjornstedt@stericsson.com>2012-01-18 06:44:55 -0500
committerLee Jones <lee.jones@linaro.org>2012-12-11 03:43:51 -0500
commitf8e96dff240982c1433d447bae533acc36b5cf8f (patch)
tree59c364b5fd5873bea4bd0c8fc36d9cd10a632ebb
parentf5695a39833a2946479f6215f3afc4f672333713 (diff)
ab8500_charger: Charger current step-up/down
There is no state machine in the AB to step up/down the charger current to avoid dips and spikes on VBUS and VBAT when charging is started. Instead this is implemented in SW. Signed-off-by: Johan Bjornstedt <johan.bjornstedt@stericsson.com> Signed-off-by: Mattias Wallin <mattias.wallin@stericsson.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Reviewed-by: Karl KOMIEROWSKI <karl.komierowski@stericsson.com>
-rw-r--r--drivers/power/ab8500_charger.c175
1 files changed, 135 insertions, 40 deletions
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index dddc9473f72a..d27dd7fec163 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -79,6 +79,9 @@
79/* Lowest charger voltage is 3.39V -> 0x4E */ 79/* Lowest charger voltage is 3.39V -> 0x4E */
80#define LOW_VOLT_REG 0x4E 80#define LOW_VOLT_REG 0x4E
81 81
82/* Step up/down delay in us */
83#define STEP_UDELAY 1000
84
82/* UsbLineStatus register - usb types */ 85/* UsbLineStatus register - usb types */
83enum ab8500_charger_link_status { 86enum ab8500_charger_link_status {
84 USB_STAT_NOT_CONFIGURED, 87 USB_STAT_NOT_CONFIGURED,
@@ -936,6 +939,88 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
936} 939}
937 940
938/** 941/**
942 * ab8500_charger_set_current() - set charger current
943 * @di: pointer to the ab8500_charger structure
944 * @ich: charger current, in mA
945 * @reg: select what charger register to set
946 *
947 * Set charger current.
948 * There is no state machine in the AB to step up/down the charger
949 * current to avoid dips and spikes on MAIN, VBUS and VBAT when
950 * charging is started. Instead we need to implement
951 * this charger current step-up/down here.
952 * Returns error code in case of failure else 0(on success)
953 */
954static int ab8500_charger_set_current(struct ab8500_charger *di,
955 int ich, int reg)
956{
957 int ret, i;
958 int curr_index, prev_curr_index, shift_value;
959 u8 reg_value;
960
961 switch (reg) {
962 case AB8500_MCH_IPT_CURLVL_REG:
963 shift_value = MAIN_CH_INPUT_CURR_SHIFT;
964 curr_index = ab8500_current_to_regval(ich);
965 break;
966 case AB8500_USBCH_IPT_CRNTLVL_REG:
967 shift_value = VBUS_IN_CURR_LIM_SHIFT;
968 curr_index = ab8500_vbus_in_curr_to_regval(ich);
969 break;
970 case AB8500_CH_OPT_CRNTLVL_REG:
971 shift_value = 0;
972 curr_index = ab8500_current_to_regval(ich);
973 break;
974 default:
975 dev_err(di->dev, "%s current register not valid\n", __func__);
976 return -ENXIO;
977 }
978
979 if (curr_index < 0) {
980 dev_err(di->dev, "requested current limit out-of-range\n");
981 return -ENXIO;
982 }
983
984 ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
985 reg, &reg_value);
986 if (ret < 0) {
987 dev_err(di->dev, "%s read failed\n", __func__);
988 return ret;
989 }
990 prev_curr_index = (reg_value >> shift_value);
991
992 /* only update current if it's been changed */
993 if (prev_curr_index == curr_index)
994 return 0;
995
996 dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n",
997 __func__, ich, reg);
998
999 if (prev_curr_index > curr_index) {
1000 for (i = prev_curr_index - 1; i >= curr_index; i--) {
1001 ret = abx500_set_register_interruptible(di->dev,
1002 AB8500_CHARGER, reg, (u8) i << shift_value);
1003 if (ret) {
1004 dev_err(di->dev, "%s write failed\n", __func__);
1005 return ret;
1006 }
1007 usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
1008 }
1009 } else {
1010 for (i = prev_curr_index + 1; i <= curr_index; i++) {
1011 ret = abx500_set_register_interruptible(di->dev,
1012 AB8500_CHARGER, reg, (u8) i << shift_value);
1013 if (ret) {
1014 dev_err(di->dev, "%s write failed\n", __func__);
1015 return ret;
1016 }
1017 usleep_range(STEP_UDELAY, STEP_UDELAY * 2);
1018 }
1019 }
1020 return ret;
1021}
1022
1023/**
939 * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit 1024 * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit
940 * @di: pointer to the ab8500_charger structure 1025 * @di: pointer to the ab8500_charger structure
941 * @ich_in: charger input current limit 1026 * @ich_in: charger input current limit
@@ -946,8 +1031,6 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
946static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, 1031static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
947 int ich_in) 1032 int ich_in)
948{ 1033{
949 int ret;
950 int input_curr_index;
951 int min_value; 1034 int min_value;
952 1035
953 /* We should always use to lowest current limit */ 1036 /* We should always use to lowest current limit */
@@ -966,19 +1049,38 @@ static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
966 break; 1049 break;
967 } 1050 }
968 1051
969 input_curr_index = ab8500_vbus_in_curr_to_regval(min_value); 1052 return ab8500_charger_set_current(di, min_value,
970 if (input_curr_index < 0) { 1053 AB8500_USBCH_IPT_CRNTLVL_REG);
971 dev_err(di->dev, "VBUS input current limit too high\n"); 1054}
972 return -ENXIO;
973 }
974 1055
975 ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1056/**
976 AB8500_USBCH_IPT_CRNTLVL_REG, 1057 * ab8500_charger_set_main_in_curr() - set main charger input current
977 input_curr_index << VBUS_IN_CURR_LIM_SHIFT); 1058 * @di: pointer to the ab8500_charger structure
978 if (ret) 1059 * @ich_in: input charger current, in mA
979 dev_err(di->dev, "%s write failed\n", __func__); 1060 *
1061 * Set main charger input current.
1062 * Returns error code in case of failure else 0(on success)
1063 */
1064static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di,
1065 int ich_in)
1066{
1067 return ab8500_charger_set_current(di, ich_in,
1068 AB8500_MCH_IPT_CURLVL_REG);
1069}
980 1070
981 return ret; 1071/**
1072 * ab8500_charger_set_output_curr() - set charger output current
1073 * @di: pointer to the ab8500_charger structure
1074 * @ich_out: output charger current, in mA
1075 *
1076 * Set charger output current.
1077 * Returns error code in case of failure else 0(on success)
1078 */
1079static int ab8500_charger_set_output_curr(struct ab8500_charger *di,
1080 int ich_out)
1081{
1082 return ab8500_charger_set_current(di, ich_out,
1083 AB8500_CH_OPT_CRNTLVL_REG);
982} 1084}
983 1085
984/** 1086/**
@@ -1090,18 +1192,19 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
1090 return ret; 1192 return ret;
1091 } 1193 }
1092 /* MainChInputCurr: current that can be drawn from the charger*/ 1194 /* MainChInputCurr: current that can be drawn from the charger*/
1093 ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1195 ret = ab8500_charger_set_main_in_curr(di,
1094 AB8500_MCH_IPT_CURLVL_REG, 1196 di->bat->chg_params->ac_curr_max);
1095 input_curr_index << MAIN_CH_INPUT_CURR_SHIFT);
1096 if (ret) { 1197 if (ret) {
1097 dev_err(di->dev, "%s write failed\n", __func__); 1198 dev_err(di->dev, "%s Failed to set MainChInputCurr\n",
1199 __func__);
1098 return ret; 1200 return ret;
1099 } 1201 }
1100 /* ChOutputCurentLevel: protected output current */ 1202 /* ChOutputCurentLevel: protected output current */
1101 ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1203 ret = ab8500_charger_set_output_curr(di, iset);
1102 AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
1103 if (ret) { 1204 if (ret) {
1104 dev_err(di->dev, "%s write failed\n", __func__); 1205 dev_err(di->dev, "%s "
1206 "Failed to set ChOutputCurentLevel\n",
1207 __func__);
1105 return ret; 1208 return ret;
1106 } 1209 }
1107 1210
@@ -1158,12 +1261,11 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
1158 return ret; 1261 return ret;
1159 } 1262 }
1160 1263
1161 ret = abx500_set_register_interruptible(di->dev, 1264 ret = ab8500_charger_set_output_curr(di, 0);
1162 AB8500_CHARGER,
1163 AB8500_CH_OPT_CRNTLVL_REG, CH_OP_CUR_LVL_0P1);
1164 if (ret) { 1265 if (ret) {
1165 dev_err(di->dev, 1266 dev_err(di->dev, "%s "
1166 "%s write failed\n", __func__); 1267 "Failed to set ChOutputCurentLevel\n",
1268 __func__);
1167 return ret; 1269 return ret;
1168 } 1270 }
1169 } else { 1271 } else {
@@ -1266,10 +1368,11 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
1266 return ret; 1368 return ret;
1267 } 1369 }
1268 /* ChOutputCurentLevel: protected output current */ 1370 /* ChOutputCurentLevel: protected output current */
1269 ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1371 ret = ab8500_charger_set_output_curr(di, ich_out);
1270 AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
1271 if (ret) { 1372 if (ret) {
1272 dev_err(di->dev, "%s write failed\n", __func__); 1373 dev_err(di->dev, "%s "
1374 "Failed to set ChOutputCurentLevel\n",
1375 __func__);
1273 return ret; 1376 return ret;
1274 } 1377 }
1275 /* Check if VBAT overshoot control should be enabled */ 1378 /* Check if VBAT overshoot control should be enabled */
@@ -1366,7 +1469,6 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
1366 int ich_out) 1469 int ich_out)
1367{ 1470{
1368 int ret; 1471 int ret;
1369 int curr_index;
1370 struct ab8500_charger *di; 1472 struct ab8500_charger *di;
1371 1473
1372 if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) 1474 if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
@@ -1376,18 +1478,11 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
1376 else 1478 else
1377 return -ENXIO; 1479 return -ENXIO;
1378 1480
1379 curr_index = ab8500_current_to_regval(ich_out); 1481 ret = ab8500_charger_set_output_curr(di, ich_out);
1380 if (curr_index < 0) {
1381 dev_err(di->dev,
1382 "Charger current too high, "
1383 "charging not started\n");
1384 return -ENXIO;
1385 }
1386
1387 ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
1388 AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index);
1389 if (ret) { 1482 if (ret) {
1390 dev_err(di->dev, "%s write failed\n", __func__); 1483 dev_err(di->dev, "%s "
1484 "Failed to set ChOutputCurentLevel\n",
1485 __func__);
1391 return ret; 1486 return ret;
1392 } 1487 }
1393 1488