aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorHenrik Sölver <henrik.solver@stericsson.com>2012-04-17 09:51:01 -0400
committerLee Jones <lee.jones@linaro.org>2013-01-23 06:33:03 -0500
commitff38090aa2e1423e130cc72e790145bad7de8215 (patch)
tree3ab24aed90dd12a9a323a8c0eee95680f1473421 /drivers/power
parent01ec8c5423901c4fe8d97f786ed9a0c31215b53a (diff)
ab8500-charger: AB workaround for invalid charger
AB8500 refuses to start charging when some types of non standard chargers are connected. This change force the AB to start charging. Signed-off-by: Henrik Sölver <henrik.solver@stericsson.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Reviewed-by: Yvan FILLION <yvan.fillion@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Tested-by: Yvan FILLION <yvan.fillion@stericsson.com>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/ab8500_charger.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 43ec82ba4275..4c66172aaa64 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -207,6 +207,7 @@ struct ab8500_charger_usb_state {
207 * @usb_device_is_unrecognised USB device is unrecognised by the hardware 207 * @usb_device_is_unrecognised USB device is unrecognised by the hardware
208 * @autopower Indicate if we should have automatic pwron after pwrloss 208 * @autopower Indicate if we should have automatic pwron after pwrloss
209 * @autopower_cfg platform specific power config support for "pwron after pwrloss" 209 * @autopower_cfg platform specific power config support for "pwron after pwrloss"
210 * @invalid_charger_detect_state State when forcing AB to use invalid charger
210 * @parent: Pointer to the struct ab8500 211 * @parent: Pointer to the struct ab8500
211 * @gpadc: Pointer to the struct gpadc 212 * @gpadc: Pointer to the struct gpadc
212 * @bm: Platform specific battery management information 213 * @bm: Platform specific battery management information
@@ -251,6 +252,7 @@ struct ab8500_charger {
251 bool usb_device_is_unrecognised; 252 bool usb_device_is_unrecognised;
252 bool autopower; 253 bool autopower;
253 bool autopower_cfg; 254 bool autopower_cfg;
255 int invalid_charger_detect_state;
254 struct ab8500 *parent; 256 struct ab8500 *parent;
255 struct ab8500_gpadc *gpadc; 257 struct ab8500_gpadc *gpadc;
256 struct abx500_bm_data *bm; 258 struct abx500_bm_data *bm;
@@ -659,7 +661,6 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
659 break; 661 break;
660 } 662 }
661 case USB_STAT_HM_IDGND: 663 case USB_STAT_HM_IDGND:
662 case USB_STAT_NOT_VALID_LINK:
663 dev_err(di->dev, "USB Type - Charging not allowed\n"); 664 dev_err(di->dev, "USB Type - Charging not allowed\n");
664 di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; 665 di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05;
665 ret = -ENXIO; 666 ret = -ENXIO;
@@ -688,6 +689,9 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
688 di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; 689 di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
689 dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, 690 dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
690 di->max_usb_in_curr); 691 di->max_usb_in_curr);
692 case USB_STAT_NOT_VALID_LINK:
693 dev_err(di->dev, "USB Type invalid - try charging anyway\n");
694 di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5;
691 break; 695 break;
692 696
693 default: 697 default:
@@ -1957,7 +1961,9 @@ static void ab8500_charger_usb_link_attach_work(struct work_struct *work)
1957 */ 1961 */
1958static void ab8500_charger_usb_link_status_work(struct work_struct *work) 1962static void ab8500_charger_usb_link_status_work(struct work_struct *work)
1959{ 1963{
1964 int detected_chargers;
1960 int ret; 1965 int ret;
1966 u8 val;
1961 1967
1962 struct ab8500_charger *di = container_of(work, 1968 struct ab8500_charger *di = container_of(work,
1963 struct ab8500_charger, usb_link_status_work); 1969 struct ab8500_charger, usb_link_status_work);
@@ -1967,11 +1973,55 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work)
1967 * synchronously, we have the check if is 1973 * synchronously, we have the check if is
1968 * connected by reading the status register 1974 * connected by reading the status register
1969 */ 1975 */
1970 ret = ab8500_charger_detect_chargers(di); 1976 detected_chargers = ab8500_charger_detect_chargers(di);
1971 if (ret < 0) 1977 if (detected_chargers < 0)
1972 return; 1978 return;
1973 1979
1974 if (!(ret & USB_PW_CONN)) { 1980 /*
1981 * Some chargers that breaks the USB spec is
1982 * identified as invalid by AB8500 and it refuse
1983 * to start the charging process. but by jumping
1984 * thru a few hoops it can be forced to start.
1985 */
1986 ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
1987 AB8500_USB_LINE_STAT_REG, &val);
1988 if (ret >= 0)
1989 dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val);
1990 else
1991 dev_dbg(di->dev, "Error reading USB link status\n");
1992
1993 if (detected_chargers & USB_PW_CONN) {
1994 if (((val & AB8500_USB_LINK_STATUS) >> 3) == USB_STAT_NOT_VALID_LINK &&
1995 di->invalid_charger_detect_state == 0) {
1996 dev_dbg(di->dev, "Invalid charger detected, state= 0\n");
1997 /*Enable charger*/
1998 abx500_mask_and_set_register_interruptible(di->dev,
1999 AB8500_CHARGER, AB8500_USBCH_CTRL1_REG, 0x01, 0x01);
2000 /*Enable charger detection*/
2001 abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB,
2002 AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x01);
2003 di->invalid_charger_detect_state = 1;
2004 /*exit and wait for new link status interrupt.*/
2005 return;
2006
2007 }
2008 if (di->invalid_charger_detect_state == 1) {
2009 dev_dbg(di->dev, "Invalid charger detected, state= 1\n");
2010 /*Stop charger detection*/
2011 abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB,
2012 AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x00);
2013 /*Check link status*/
2014 ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
2015 AB8500_USB_LINE_STAT_REG, &val);
2016 dev_dbg(di->dev, "USB link status= 0x%02x\n",
2017 (val & AB8500_USB_LINK_STATUS) >> 3);
2018 di->invalid_charger_detect_state = 2;
2019 }
2020 } else {
2021 di->invalid_charger_detect_state = 0;
2022 }
2023
2024 if (!(detected_chargers & USB_PW_CONN)) {
1975 di->vbus_detected = 0; 2025 di->vbus_detected = 0;
1976 ab8500_charger_set_usb_connected(di, false); 2026 ab8500_charger_set_usb_connected(di, false);
1977 ab8500_power_supply_changed(di, &di->usb_chg.psy); 2027 ab8500_power_supply_changed(di, &di->usb_chg.psy);
@@ -2884,6 +2934,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
2884 spin_lock_init(&di->usb_state.usb_lock); 2934 spin_lock_init(&di->usb_state.usb_lock);
2885 2935
2886 di->autopower = false; 2936 di->autopower = false;
2937 di->invalid_charger_detect_state = 0;
2887 2938
2888 /* AC supply */ 2939 /* AC supply */
2889 /* power_supply base class */ 2940 /* power_supply base class */