diff options
Diffstat (limited to 'drivers/mfd/ab8500-core.c')
-rw-r--r-- | drivers/mfd/ab8500-core.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 7c84ced2e01b..50e6f1e29727 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -111,6 +111,13 @@ | |||
111 | 111 | ||
112 | #define AB8500_TURN_ON_STATUS 0x00 | 112 | #define AB8500_TURN_ON_STATUS 0x00 |
113 | 113 | ||
114 | #define AB8500_CH_USBCH_STAT1_REG 0x02 | ||
115 | #define VBUS_DET_DBNC100 0x02 | ||
116 | #define VBUS_DET_DBNC1 0x01 | ||
117 | |||
118 | static DEFINE_SPINLOCK(on_stat_lock); | ||
119 | static u8 turn_on_stat_mask = 0xFF; | ||
120 | static u8 turn_on_stat_set; | ||
114 | static bool no_bm; /* No battery management */ | 121 | static bool no_bm; /* No battery management */ |
115 | module_param(no_bm, bool, S_IRUGO); | 122 | module_param(no_bm, bool, S_IRUGO); |
116 | 123 | ||
@@ -1171,6 +1178,15 @@ static ssize_t show_switch_off_status(struct device *dev, | |||
1171 | return sprintf(buf, "%#x\n", value); | 1178 | return sprintf(buf, "%#x\n", value); |
1172 | } | 1179 | } |
1173 | 1180 | ||
1181 | /* use mask and set to override the register turn_on_stat value */ | ||
1182 | void ab8500_override_turn_on_stat(u8 mask, u8 set) | ||
1183 | { | ||
1184 | spin_lock(&on_stat_lock); | ||
1185 | turn_on_stat_mask = mask; | ||
1186 | turn_on_stat_set = set; | ||
1187 | spin_unlock(&on_stat_lock); | ||
1188 | } | ||
1189 | |||
1174 | /* | 1190 | /* |
1175 | * ab8500 has turned on due to (TURN_ON_STATUS): | 1191 | * ab8500 has turned on due to (TURN_ON_STATUS): |
1176 | * 0x01 PORnVbat | 1192 | * 0x01 PORnVbat |
@@ -1194,6 +1210,20 @@ static ssize_t show_turn_on_status(struct device *dev, | |||
1194 | AB8500_TURN_ON_STATUS, &value); | 1210 | AB8500_TURN_ON_STATUS, &value); |
1195 | if (ret < 0) | 1211 | if (ret < 0) |
1196 | return ret; | 1212 | return ret; |
1213 | |||
1214 | /* | ||
1215 | * In L9540, turn_on_status register is not updated correctly if | ||
1216 | * the device is rebooted with AC/USB charger connected. Due to | ||
1217 | * this, the device boots android instead of entering into charge | ||
1218 | * only mode. Read the AC/USB status register to detect the charger | ||
1219 | * presence and update the turn on status manually. | ||
1220 | */ | ||
1221 | if (is_ab9540(ab8500)) { | ||
1222 | spin_lock(&on_stat_lock); | ||
1223 | value = (value & turn_on_stat_mask) | turn_on_stat_set; | ||
1224 | spin_unlock(&on_stat_lock); | ||
1225 | } | ||
1226 | |||
1197 | return sprintf(buf, "%#x\n", value); | 1227 | return sprintf(buf, "%#x\n", value); |
1198 | } | 1228 | } |
1199 | 1229 | ||
@@ -1399,6 +1429,15 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1399 | 1429 | ||
1400 | if (plat && plat->init) | 1430 | if (plat && plat->init) |
1401 | plat->init(ab8500); | 1431 | plat->init(ab8500); |
1432 | if (is_ab9540(ab8500)) { | ||
1433 | ret = get_register_interruptible(ab8500, AB8500_CHARGER, | ||
1434 | AB8500_CH_USBCH_STAT1_REG, &value); | ||
1435 | if (ret < 0) | ||
1436 | return ret; | ||
1437 | if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) | ||
1438 | ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, | ||
1439 | AB8500_VBUS_DET); | ||
1440 | } | ||
1402 | 1441 | ||
1403 | /* Clear and mask all interrupts */ | 1442 | /* Clear and mask all interrupts */ |
1404 | for (i = 0; i < ab8500->mask_size; i++) { | 1443 | for (i = 0; i < ab8500->mask_size; i++) { |