1*8c0984e5SSebastian Reichel /* 2*8c0984e5SSebastian Reichel * Copyright (C) ST-Ericsson SA 2012 3*8c0984e5SSebastian Reichel * 4*8c0984e5SSebastian Reichel * Charger driver for AB8500 5*8c0984e5SSebastian Reichel * 6*8c0984e5SSebastian Reichel * License Terms: GNU General Public License v2 7*8c0984e5SSebastian Reichel * Author: 8*8c0984e5SSebastian Reichel * Johan Palsson <johan.palsson@stericsson.com> 9*8c0984e5SSebastian Reichel * Karl Komierowski <karl.komierowski@stericsson.com> 10*8c0984e5SSebastian Reichel * Arun R Murthy <arun.murthy@stericsson.com> 11*8c0984e5SSebastian Reichel */ 12*8c0984e5SSebastian Reichel 13*8c0984e5SSebastian Reichel #include <linux/init.h> 14*8c0984e5SSebastian Reichel #include <linux/module.h> 15*8c0984e5SSebastian Reichel #include <linux/device.h> 16*8c0984e5SSebastian Reichel #include <linux/interrupt.h> 17*8c0984e5SSebastian Reichel #include <linux/delay.h> 18*8c0984e5SSebastian Reichel #include <linux/notifier.h> 19*8c0984e5SSebastian Reichel #include <linux/slab.h> 20*8c0984e5SSebastian Reichel #include <linux/platform_device.h> 21*8c0984e5SSebastian Reichel #include <linux/power_supply.h> 22*8c0984e5SSebastian Reichel #include <linux/completion.h> 23*8c0984e5SSebastian Reichel #include <linux/regulator/consumer.h> 24*8c0984e5SSebastian Reichel #include <linux/err.h> 25*8c0984e5SSebastian Reichel #include <linux/workqueue.h> 26*8c0984e5SSebastian Reichel #include <linux/kobject.h> 27*8c0984e5SSebastian Reichel #include <linux/of.h> 28*8c0984e5SSebastian Reichel #include <linux/mfd/core.h> 29*8c0984e5SSebastian Reichel #include <linux/mfd/abx500/ab8500.h> 30*8c0984e5SSebastian Reichel #include <linux/mfd/abx500.h> 31*8c0984e5SSebastian Reichel #include <linux/mfd/abx500/ab8500-bm.h> 32*8c0984e5SSebastian Reichel #include <linux/mfd/abx500/ab8500-gpadc.h> 33*8c0984e5SSebastian Reichel #include <linux/mfd/abx500/ux500_chargalg.h> 34*8c0984e5SSebastian Reichel #include <linux/usb/otg.h> 35*8c0984e5SSebastian Reichel #include <linux/mutex.h> 36*8c0984e5SSebastian Reichel 37*8c0984e5SSebastian Reichel /* Charger constants */ 38*8c0984e5SSebastian Reichel #define NO_PW_CONN 0 39*8c0984e5SSebastian Reichel #define AC_PW_CONN 1 40*8c0984e5SSebastian Reichel #define USB_PW_CONN 2 41*8c0984e5SSebastian Reichel 42*8c0984e5SSebastian Reichel #define MAIN_WDOG_ENA 0x01 43*8c0984e5SSebastian Reichel #define MAIN_WDOG_KICK 0x02 44*8c0984e5SSebastian Reichel #define MAIN_WDOG_DIS 0x00 45*8c0984e5SSebastian Reichel #define CHARG_WD_KICK 0x01 46*8c0984e5SSebastian Reichel #define MAIN_CH_ENA 0x01 47*8c0984e5SSebastian Reichel #define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02 48*8c0984e5SSebastian Reichel #define USB_CH_ENA 0x01 49*8c0984e5SSebastian Reichel #define USB_CHG_NO_OVERSHOOT_ENA_N 0x02 50*8c0984e5SSebastian Reichel #define MAIN_CH_DET 0x01 51*8c0984e5SSebastian Reichel #define MAIN_CH_CV_ON 0x04 52*8c0984e5SSebastian Reichel #define USB_CH_CV_ON 0x08 53*8c0984e5SSebastian Reichel #define VBUS_DET_DBNC100 0x02 54*8c0984e5SSebastian Reichel #define VBUS_DET_DBNC1 0x01 55*8c0984e5SSebastian Reichel #define OTP_ENABLE_WD 0x01 56*8c0984e5SSebastian Reichel #define DROP_COUNT_RESET 0x01 57*8c0984e5SSebastian Reichel #define USB_CH_DET 0x01 58*8c0984e5SSebastian Reichel 59*8c0984e5SSebastian Reichel #define MAIN_CH_INPUT_CURR_SHIFT 4 60*8c0984e5SSebastian Reichel #define VBUS_IN_CURR_LIM_SHIFT 4 61*8c0984e5SSebastian Reichel #define AB8540_VBUS_IN_CURR_LIM_SHIFT 2 62*8c0984e5SSebastian Reichel #define AUTO_VBUS_IN_CURR_LIM_SHIFT 4 63*8c0984e5SSebastian Reichel #define AB8540_AUTO_VBUS_IN_CURR_MASK 0x3F 64*8c0984e5SSebastian Reichel #define VBUS_IN_CURR_LIM_RETRY_SET_TIME 30 /* seconds */ 65*8c0984e5SSebastian Reichel 66*8c0984e5SSebastian Reichel #define LED_INDICATOR_PWM_ENA 0x01 67*8c0984e5SSebastian Reichel #define LED_INDICATOR_PWM_DIS 0x00 68*8c0984e5SSebastian Reichel #define LED_IND_CUR_5MA 0x04 69*8c0984e5SSebastian Reichel #define LED_INDICATOR_PWM_DUTY_252_256 0xBF 70*8c0984e5SSebastian Reichel 71*8c0984e5SSebastian Reichel /* HW failure constants */ 72*8c0984e5SSebastian Reichel #define MAIN_CH_TH_PROT 0x02 73*8c0984e5SSebastian Reichel #define VBUS_CH_NOK 0x08 74*8c0984e5SSebastian Reichel #define USB_CH_TH_PROT 0x02 75*8c0984e5SSebastian Reichel #define VBUS_OVV_TH 0x01 76*8c0984e5SSebastian Reichel #define MAIN_CH_NOK 0x01 77*8c0984e5SSebastian Reichel #define VBUS_DET 0x80 78*8c0984e5SSebastian Reichel 79*8c0984e5SSebastian Reichel #define MAIN_CH_STATUS2_MAINCHGDROP 0x80 80*8c0984e5SSebastian Reichel #define MAIN_CH_STATUS2_MAINCHARGERDETDBNC 0x40 81*8c0984e5SSebastian Reichel #define USB_CH_VBUSDROP 0x40 82*8c0984e5SSebastian Reichel #define USB_CH_VBUSDETDBNC 0x01 83*8c0984e5SSebastian Reichel 84*8c0984e5SSebastian Reichel /* UsbLineStatus register bit masks */ 85*8c0984e5SSebastian Reichel #define AB8500_USB_LINK_STATUS 0x78 86*8c0984e5SSebastian Reichel #define AB8505_USB_LINK_STATUS 0xF8 87*8c0984e5SSebastian Reichel #define AB8500_STD_HOST_SUSP 0x18 88*8c0984e5SSebastian Reichel #define USB_LINK_STATUS_SHIFT 3 89*8c0984e5SSebastian Reichel 90*8c0984e5SSebastian Reichel /* Watchdog timeout constant */ 91*8c0984e5SSebastian Reichel #define WD_TIMER 0x30 /* 4min */ 92*8c0984e5SSebastian Reichel #define WD_KICK_INTERVAL (60 * HZ) 93*8c0984e5SSebastian Reichel 94*8c0984e5SSebastian Reichel /* Lowest charger voltage is 3.39V -> 0x4E */ 95*8c0984e5SSebastian Reichel #define LOW_VOLT_REG 0x4E 96*8c0984e5SSebastian Reichel 97*8c0984e5SSebastian Reichel /* Step up/down delay in us */ 98*8c0984e5SSebastian Reichel #define STEP_UDELAY 1000 99*8c0984e5SSebastian Reichel 100*8c0984e5SSebastian Reichel #define CHARGER_STATUS_POLL 10 /* in ms */ 101*8c0984e5SSebastian Reichel 102*8c0984e5SSebastian Reichel #define CHG_WD_INTERVAL (60 * HZ) 103*8c0984e5SSebastian Reichel 104*8c0984e5SSebastian Reichel #define AB8500_SW_CONTROL_FALLBACK 0x03 105*8c0984e5SSebastian Reichel /* Wait for enumeration before charing in us */ 106*8c0984e5SSebastian Reichel #define WAIT_ACA_RID_ENUMERATION (5 * 1000) 107*8c0984e5SSebastian Reichel /*External charger control*/ 108*8c0984e5SSebastian Reichel #define AB8500_SYS_CHARGER_CONTROL_REG 0x52 109*8c0984e5SSebastian Reichel #define EXTERNAL_CHARGER_DISABLE_REG_VAL 0x03 110*8c0984e5SSebastian Reichel #define EXTERNAL_CHARGER_ENABLE_REG_VAL 0x07 111*8c0984e5SSebastian Reichel 112*8c0984e5SSebastian Reichel /* UsbLineStatus register - usb types */ 113*8c0984e5SSebastian Reichel enum ab8500_charger_link_status { 114*8c0984e5SSebastian Reichel USB_STAT_NOT_CONFIGURED, 115*8c0984e5SSebastian Reichel USB_STAT_STD_HOST_NC, 116*8c0984e5SSebastian Reichel USB_STAT_STD_HOST_C_NS, 117*8c0984e5SSebastian Reichel USB_STAT_STD_HOST_C_S, 118*8c0984e5SSebastian Reichel USB_STAT_HOST_CHG_NM, 119*8c0984e5SSebastian Reichel USB_STAT_HOST_CHG_HS, 120*8c0984e5SSebastian Reichel USB_STAT_HOST_CHG_HS_CHIRP, 121*8c0984e5SSebastian Reichel USB_STAT_DEDICATED_CHG, 122*8c0984e5SSebastian Reichel USB_STAT_ACA_RID_A, 123*8c0984e5SSebastian Reichel USB_STAT_ACA_RID_B, 124*8c0984e5SSebastian Reichel USB_STAT_ACA_RID_C_NM, 125*8c0984e5SSebastian Reichel USB_STAT_ACA_RID_C_HS, 126*8c0984e5SSebastian Reichel USB_STAT_ACA_RID_C_HS_CHIRP, 127*8c0984e5SSebastian Reichel USB_STAT_HM_IDGND, 128*8c0984e5SSebastian Reichel USB_STAT_RESERVED, 129*8c0984e5SSebastian Reichel USB_STAT_NOT_VALID_LINK, 130*8c0984e5SSebastian Reichel USB_STAT_PHY_EN, 131*8c0984e5SSebastian Reichel USB_STAT_SUP_NO_IDGND_VBUS, 132*8c0984e5SSebastian Reichel USB_STAT_SUP_IDGND_VBUS, 133*8c0984e5SSebastian Reichel USB_STAT_CHARGER_LINE_1, 134*8c0984e5SSebastian Reichel USB_STAT_CARKIT_1, 135*8c0984e5SSebastian Reichel USB_STAT_CARKIT_2, 136*8c0984e5SSebastian Reichel USB_STAT_ACA_DOCK_CHARGER, 137*8c0984e5SSebastian Reichel }; 138*8c0984e5SSebastian Reichel 139*8c0984e5SSebastian Reichel enum ab8500_usb_state { 140*8c0984e5SSebastian Reichel AB8500_BM_USB_STATE_RESET_HS, /* HighSpeed Reset */ 141*8c0984e5SSebastian Reichel AB8500_BM_USB_STATE_RESET_FS, /* FullSpeed/LowSpeed Reset */ 142*8c0984e5SSebastian Reichel AB8500_BM_USB_STATE_CONFIGURED, 143*8c0984e5SSebastian Reichel AB8500_BM_USB_STATE_SUSPEND, 144*8c0984e5SSebastian Reichel AB8500_BM_USB_STATE_RESUME, 145*8c0984e5SSebastian Reichel AB8500_BM_USB_STATE_MAX, 146*8c0984e5SSebastian Reichel }; 147*8c0984e5SSebastian Reichel 148*8c0984e5SSebastian Reichel /* VBUS input current limits supported in AB8500 in mA */ 149*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P05 50 150*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P09 98 151*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P19 193 152*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P29 290 153*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P38 380 154*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P45 450 155*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P5 500 156*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P6 600 157*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P7 700 158*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P8 800 159*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_0P9 900 160*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_1P0 1000 161*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_1P1 1100 162*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_1P3 1300 163*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_1P4 1400 164*8c0984e5SSebastian Reichel #define USB_CH_IP_CUR_LVL_1P5 1500 165*8c0984e5SSebastian Reichel 166*8c0984e5SSebastian Reichel #define VBAT_TRESH_IP_CUR_RED 3800 167*8c0984e5SSebastian Reichel 168*8c0984e5SSebastian Reichel #define to_ab8500_charger_usb_device_info(x) container_of((x), \ 169*8c0984e5SSebastian Reichel struct ab8500_charger, usb_chg) 170*8c0984e5SSebastian Reichel #define to_ab8500_charger_ac_device_info(x) container_of((x), \ 171*8c0984e5SSebastian Reichel struct ab8500_charger, ac_chg) 172*8c0984e5SSebastian Reichel 173*8c0984e5SSebastian Reichel /** 174*8c0984e5SSebastian Reichel * struct ab8500_charger_interrupts - ab8500 interupts 175*8c0984e5SSebastian Reichel * @name: name of the interrupt 176*8c0984e5SSebastian Reichel * @isr function pointer to the isr 177*8c0984e5SSebastian Reichel */ 178*8c0984e5SSebastian Reichel struct ab8500_charger_interrupts { 179*8c0984e5SSebastian Reichel char *name; 180*8c0984e5SSebastian Reichel irqreturn_t (*isr)(int irq, void *data); 181*8c0984e5SSebastian Reichel }; 182*8c0984e5SSebastian Reichel 183*8c0984e5SSebastian Reichel struct ab8500_charger_info { 184*8c0984e5SSebastian Reichel int charger_connected; 185*8c0984e5SSebastian Reichel int charger_online; 186*8c0984e5SSebastian Reichel int charger_voltage; 187*8c0984e5SSebastian Reichel int cv_active; 188*8c0984e5SSebastian Reichel bool wd_expired; 189*8c0984e5SSebastian Reichel int charger_current; 190*8c0984e5SSebastian Reichel }; 191*8c0984e5SSebastian Reichel 192*8c0984e5SSebastian Reichel struct ab8500_charger_event_flags { 193*8c0984e5SSebastian Reichel bool mainextchnotok; 194*8c0984e5SSebastian Reichel bool main_thermal_prot; 195*8c0984e5SSebastian Reichel bool usb_thermal_prot; 196*8c0984e5SSebastian Reichel bool vbus_ovv; 197*8c0984e5SSebastian Reichel bool usbchargernotok; 198*8c0984e5SSebastian Reichel bool chgwdexp; 199*8c0984e5SSebastian Reichel bool vbus_collapse; 200*8c0984e5SSebastian Reichel bool vbus_drop_end; 201*8c0984e5SSebastian Reichel }; 202*8c0984e5SSebastian Reichel 203*8c0984e5SSebastian Reichel struct ab8500_charger_usb_state { 204*8c0984e5SSebastian Reichel int usb_current; 205*8c0984e5SSebastian Reichel int usb_current_tmp; 206*8c0984e5SSebastian Reichel enum ab8500_usb_state state; 207*8c0984e5SSebastian Reichel enum ab8500_usb_state state_tmp; 208*8c0984e5SSebastian Reichel spinlock_t usb_lock; 209*8c0984e5SSebastian Reichel }; 210*8c0984e5SSebastian Reichel 211*8c0984e5SSebastian Reichel struct ab8500_charger_max_usb_in_curr { 212*8c0984e5SSebastian Reichel int usb_type_max; 213*8c0984e5SSebastian Reichel int set_max; 214*8c0984e5SSebastian Reichel int calculated_max; 215*8c0984e5SSebastian Reichel }; 216*8c0984e5SSebastian Reichel 217*8c0984e5SSebastian Reichel /** 218*8c0984e5SSebastian Reichel * struct ab8500_charger - ab8500 Charger device information 219*8c0984e5SSebastian Reichel * @dev: Pointer to the structure device 220*8c0984e5SSebastian Reichel * @vbus_detected: VBUS detected 221*8c0984e5SSebastian Reichel * @vbus_detected_start: 222*8c0984e5SSebastian Reichel * VBUS detected during startup 223*8c0984e5SSebastian Reichel * @ac_conn: This will be true when the AC charger has been plugged 224*8c0984e5SSebastian Reichel * @vddadc_en_ac: Indicate if VDD ADC supply is enabled because AC 225*8c0984e5SSebastian Reichel * charger is enabled 226*8c0984e5SSebastian Reichel * @vddadc_en_usb: Indicate if VDD ADC supply is enabled because USB 227*8c0984e5SSebastian Reichel * charger is enabled 228*8c0984e5SSebastian Reichel * @vbat Battery voltage 229*8c0984e5SSebastian Reichel * @old_vbat Previously measured battery voltage 230*8c0984e5SSebastian Reichel * @usb_device_is_unrecognised USB device is unrecognised by the hardware 231*8c0984e5SSebastian Reichel * @autopower Indicate if we should have automatic pwron after pwrloss 232*8c0984e5SSebastian Reichel * @autopower_cfg platform specific power config support for "pwron after pwrloss" 233*8c0984e5SSebastian Reichel * @invalid_charger_detect_state State when forcing AB to use invalid charger 234*8c0984e5SSebastian Reichel * @is_aca_rid: Incicate if accessory is ACA type 235*8c0984e5SSebastian Reichel * @current_stepping_sessions: 236*8c0984e5SSebastian Reichel * Counter for current stepping sessions 237*8c0984e5SSebastian Reichel * @parent: Pointer to the struct ab8500 238*8c0984e5SSebastian Reichel * @gpadc: Pointer to the struct gpadc 239*8c0984e5SSebastian Reichel * @bm: Platform specific battery management information 240*8c0984e5SSebastian Reichel * @flags: Structure for information about events triggered 241*8c0984e5SSebastian Reichel * @usb_state: Structure for usb stack information 242*8c0984e5SSebastian Reichel * @max_usb_in_curr: Max USB charger input current 243*8c0984e5SSebastian Reichel * @ac_chg: AC charger power supply 244*8c0984e5SSebastian Reichel * @usb_chg: USB charger power supply 245*8c0984e5SSebastian Reichel * @ac: Structure that holds the AC charger properties 246*8c0984e5SSebastian Reichel * @usb: Structure that holds the USB charger properties 247*8c0984e5SSebastian Reichel * @regu: Pointer to the struct regulator 248*8c0984e5SSebastian Reichel * @charger_wq: Work queue for the IRQs and checking HW state 249*8c0984e5SSebastian Reichel * @usb_ipt_crnt_lock: Lock to protect VBUS input current setting from mutuals 250*8c0984e5SSebastian Reichel * @pm_lock: Lock to prevent system to suspend 251*8c0984e5SSebastian Reichel * @check_vbat_work Work for checking vbat threshold to adjust vbus current 252*8c0984e5SSebastian Reichel * @check_hw_failure_work: Work for checking HW state 253*8c0984e5SSebastian Reichel * @check_usbchgnotok_work: Work for checking USB charger not ok status 254*8c0984e5SSebastian Reichel * @kick_wd_work: Work for kicking the charger watchdog in case 255*8c0984e5SSebastian Reichel * of ABB rev 1.* due to the watchog logic bug 256*8c0984e5SSebastian Reichel * @ac_charger_attached_work: Work for checking if AC charger is still 257*8c0984e5SSebastian Reichel * connected 258*8c0984e5SSebastian Reichel * @usb_charger_attached_work: Work for checking if USB charger is still 259*8c0984e5SSebastian Reichel * connected 260*8c0984e5SSebastian Reichel * @ac_work: Work for checking AC charger connection 261*8c0984e5SSebastian Reichel * @detect_usb_type_work: Work for detecting the USB type connected 262*8c0984e5SSebastian Reichel * @usb_link_status_work: Work for checking the new USB link status 263*8c0984e5SSebastian Reichel * @usb_state_changed_work: Work for checking USB state 264*8c0984e5SSebastian Reichel * @attach_work: Work for detecting USB type 265*8c0984e5SSebastian Reichel * @vbus_drop_end_work: Work for detecting VBUS drop end 266*8c0984e5SSebastian Reichel * @check_main_thermal_prot_work: 267*8c0984e5SSebastian Reichel * Work for checking Main thermal status 268*8c0984e5SSebastian Reichel * @check_usb_thermal_prot_work: 269*8c0984e5SSebastian Reichel * Work for checking USB thermal status 270*8c0984e5SSebastian Reichel * @charger_attached_mutex: For controlling the wakelock 271*8c0984e5SSebastian Reichel */ 272*8c0984e5SSebastian Reichel struct ab8500_charger { 273*8c0984e5SSebastian Reichel struct device *dev; 274*8c0984e5SSebastian Reichel bool vbus_detected; 275*8c0984e5SSebastian Reichel bool vbus_detected_start; 276*8c0984e5SSebastian Reichel bool ac_conn; 277*8c0984e5SSebastian Reichel bool vddadc_en_ac; 278*8c0984e5SSebastian Reichel bool vddadc_en_usb; 279*8c0984e5SSebastian Reichel int vbat; 280*8c0984e5SSebastian Reichel int old_vbat; 281*8c0984e5SSebastian Reichel bool usb_device_is_unrecognised; 282*8c0984e5SSebastian Reichel bool autopower; 283*8c0984e5SSebastian Reichel bool autopower_cfg; 284*8c0984e5SSebastian Reichel int invalid_charger_detect_state; 285*8c0984e5SSebastian Reichel int is_aca_rid; 286*8c0984e5SSebastian Reichel atomic_t current_stepping_sessions; 287*8c0984e5SSebastian Reichel struct ab8500 *parent; 288*8c0984e5SSebastian Reichel struct ab8500_gpadc *gpadc; 289*8c0984e5SSebastian Reichel struct abx500_bm_data *bm; 290*8c0984e5SSebastian Reichel struct ab8500_charger_event_flags flags; 291*8c0984e5SSebastian Reichel struct ab8500_charger_usb_state usb_state; 292*8c0984e5SSebastian Reichel struct ab8500_charger_max_usb_in_curr max_usb_in_curr; 293*8c0984e5SSebastian Reichel struct ux500_charger ac_chg; 294*8c0984e5SSebastian Reichel struct ux500_charger usb_chg; 295*8c0984e5SSebastian Reichel struct ab8500_charger_info ac; 296*8c0984e5SSebastian Reichel struct ab8500_charger_info usb; 297*8c0984e5SSebastian Reichel struct regulator *regu; 298*8c0984e5SSebastian Reichel struct workqueue_struct *charger_wq; 299*8c0984e5SSebastian Reichel struct mutex usb_ipt_crnt_lock; 300*8c0984e5SSebastian Reichel struct delayed_work check_vbat_work; 301*8c0984e5SSebastian Reichel struct delayed_work check_hw_failure_work; 302*8c0984e5SSebastian Reichel struct delayed_work check_usbchgnotok_work; 303*8c0984e5SSebastian Reichel struct delayed_work kick_wd_work; 304*8c0984e5SSebastian Reichel struct delayed_work usb_state_changed_work; 305*8c0984e5SSebastian Reichel struct delayed_work attach_work; 306*8c0984e5SSebastian Reichel struct delayed_work ac_charger_attached_work; 307*8c0984e5SSebastian Reichel struct delayed_work usb_charger_attached_work; 308*8c0984e5SSebastian Reichel struct delayed_work vbus_drop_end_work; 309*8c0984e5SSebastian Reichel struct work_struct ac_work; 310*8c0984e5SSebastian Reichel struct work_struct detect_usb_type_work; 311*8c0984e5SSebastian Reichel struct work_struct usb_link_status_work; 312*8c0984e5SSebastian Reichel struct work_struct check_main_thermal_prot_work; 313*8c0984e5SSebastian Reichel struct work_struct check_usb_thermal_prot_work; 314*8c0984e5SSebastian Reichel struct usb_phy *usb_phy; 315*8c0984e5SSebastian Reichel struct notifier_block nb; 316*8c0984e5SSebastian Reichel struct mutex charger_attached_mutex; 317*8c0984e5SSebastian Reichel }; 318*8c0984e5SSebastian Reichel 319*8c0984e5SSebastian Reichel /* AC properties */ 320*8c0984e5SSebastian Reichel static enum power_supply_property ab8500_charger_ac_props[] = { 321*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_HEALTH, 322*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_PRESENT, 323*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_ONLINE, 324*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_NOW, 325*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_AVG, 326*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CURRENT_NOW, 327*8c0984e5SSebastian Reichel }; 328*8c0984e5SSebastian Reichel 329*8c0984e5SSebastian Reichel /* USB properties */ 330*8c0984e5SSebastian Reichel static enum power_supply_property ab8500_charger_usb_props[] = { 331*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_HEALTH, 332*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CURRENT_AVG, 333*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_PRESENT, 334*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_ONLINE, 335*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_NOW, 336*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_VOLTAGE_AVG, 337*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CURRENT_NOW, 338*8c0984e5SSebastian Reichel }; 339*8c0984e5SSebastian Reichel 340*8c0984e5SSebastian Reichel /* 341*8c0984e5SSebastian Reichel * Function for enabling and disabling sw fallback mode 342*8c0984e5SSebastian Reichel * should always be disabled when no charger is connected. 343*8c0984e5SSebastian Reichel */ 344*8c0984e5SSebastian Reichel static void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di, 345*8c0984e5SSebastian Reichel bool fallback) 346*8c0984e5SSebastian Reichel { 347*8c0984e5SSebastian Reichel u8 val; 348*8c0984e5SSebastian Reichel u8 reg; 349*8c0984e5SSebastian Reichel u8 bank; 350*8c0984e5SSebastian Reichel u8 bit; 351*8c0984e5SSebastian Reichel int ret; 352*8c0984e5SSebastian Reichel 353*8c0984e5SSebastian Reichel dev_dbg(di->dev, "SW Fallback: %d\n", fallback); 354*8c0984e5SSebastian Reichel 355*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) { 356*8c0984e5SSebastian Reichel bank = 0x15; 357*8c0984e5SSebastian Reichel reg = 0x0; 358*8c0984e5SSebastian Reichel bit = 3; 359*8c0984e5SSebastian Reichel } else { 360*8c0984e5SSebastian Reichel bank = AB8500_SYS_CTRL1_BLOCK; 361*8c0984e5SSebastian Reichel reg = AB8500_SW_CONTROL_FALLBACK; 362*8c0984e5SSebastian Reichel bit = 0; 363*8c0984e5SSebastian Reichel } 364*8c0984e5SSebastian Reichel 365*8c0984e5SSebastian Reichel /* read the register containing fallback bit */ 366*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, bank, reg, &val); 367*8c0984e5SSebastian Reichel if (ret < 0) { 368*8c0984e5SSebastian Reichel dev_err(di->dev, "%d read failed\n", __LINE__); 369*8c0984e5SSebastian Reichel return; 370*8c0984e5SSebastian Reichel } 371*8c0984e5SSebastian Reichel 372*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) { 373*8c0984e5SSebastian Reichel /* enable the OPT emulation registers */ 374*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2); 375*8c0984e5SSebastian Reichel if (ret) { 376*8c0984e5SSebastian Reichel dev_err(di->dev, "%d write failed\n", __LINE__); 377*8c0984e5SSebastian Reichel goto disable_otp; 378*8c0984e5SSebastian Reichel } 379*8c0984e5SSebastian Reichel } 380*8c0984e5SSebastian Reichel 381*8c0984e5SSebastian Reichel if (fallback) 382*8c0984e5SSebastian Reichel val |= (1 << bit); 383*8c0984e5SSebastian Reichel else 384*8c0984e5SSebastian Reichel val &= ~(1 << bit); 385*8c0984e5SSebastian Reichel 386*8c0984e5SSebastian Reichel /* write back the changed fallback bit value to register */ 387*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, bank, reg, val); 388*8c0984e5SSebastian Reichel if (ret) { 389*8c0984e5SSebastian Reichel dev_err(di->dev, "%d write failed\n", __LINE__); 390*8c0984e5SSebastian Reichel } 391*8c0984e5SSebastian Reichel 392*8c0984e5SSebastian Reichel disable_otp: 393*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) { 394*8c0984e5SSebastian Reichel /* disable the set OTP registers again */ 395*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0); 396*8c0984e5SSebastian Reichel if (ret) { 397*8c0984e5SSebastian Reichel dev_err(di->dev, "%d write failed\n", __LINE__); 398*8c0984e5SSebastian Reichel } 399*8c0984e5SSebastian Reichel } 400*8c0984e5SSebastian Reichel } 401*8c0984e5SSebastian Reichel 402*8c0984e5SSebastian Reichel /** 403*8c0984e5SSebastian Reichel * ab8500_power_supply_changed - a wrapper with local extentions for 404*8c0984e5SSebastian Reichel * power_supply_changed 405*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 406*8c0984e5SSebastian Reichel * @psy: pointer to power_supply_that have changed. 407*8c0984e5SSebastian Reichel * 408*8c0984e5SSebastian Reichel */ 409*8c0984e5SSebastian Reichel static void ab8500_power_supply_changed(struct ab8500_charger *di, 410*8c0984e5SSebastian Reichel struct power_supply *psy) 411*8c0984e5SSebastian Reichel { 412*8c0984e5SSebastian Reichel if (di->autopower_cfg) { 413*8c0984e5SSebastian Reichel if (!di->usb.charger_connected && 414*8c0984e5SSebastian Reichel !di->ac.charger_connected && 415*8c0984e5SSebastian Reichel di->autopower) { 416*8c0984e5SSebastian Reichel di->autopower = false; 417*8c0984e5SSebastian Reichel ab8500_enable_disable_sw_fallback(di, false); 418*8c0984e5SSebastian Reichel } else if (!di->autopower && 419*8c0984e5SSebastian Reichel (di->ac.charger_connected || 420*8c0984e5SSebastian Reichel di->usb.charger_connected)) { 421*8c0984e5SSebastian Reichel di->autopower = true; 422*8c0984e5SSebastian Reichel ab8500_enable_disable_sw_fallback(di, true); 423*8c0984e5SSebastian Reichel } 424*8c0984e5SSebastian Reichel } 425*8c0984e5SSebastian Reichel power_supply_changed(psy); 426*8c0984e5SSebastian Reichel } 427*8c0984e5SSebastian Reichel 428*8c0984e5SSebastian Reichel static void ab8500_charger_set_usb_connected(struct ab8500_charger *di, 429*8c0984e5SSebastian Reichel bool connected) 430*8c0984e5SSebastian Reichel { 431*8c0984e5SSebastian Reichel if (connected != di->usb.charger_connected) { 432*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB connected:%i\n", connected); 433*8c0984e5SSebastian Reichel di->usb.charger_connected = connected; 434*8c0984e5SSebastian Reichel 435*8c0984e5SSebastian Reichel if (!connected) 436*8c0984e5SSebastian Reichel di->flags.vbus_drop_end = false; 437*8c0984e5SSebastian Reichel 438*8c0984e5SSebastian Reichel sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL, "present"); 439*8c0984e5SSebastian Reichel 440*8c0984e5SSebastian Reichel if (connected) { 441*8c0984e5SSebastian Reichel mutex_lock(&di->charger_attached_mutex); 442*8c0984e5SSebastian Reichel mutex_unlock(&di->charger_attached_mutex); 443*8c0984e5SSebastian Reichel 444*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 445*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 446*8c0984e5SSebastian Reichel &di->usb_charger_attached_work, 447*8c0984e5SSebastian Reichel HZ); 448*8c0984e5SSebastian Reichel } else { 449*8c0984e5SSebastian Reichel cancel_delayed_work_sync(&di->usb_charger_attached_work); 450*8c0984e5SSebastian Reichel mutex_lock(&di->charger_attached_mutex); 451*8c0984e5SSebastian Reichel mutex_unlock(&di->charger_attached_mutex); 452*8c0984e5SSebastian Reichel } 453*8c0984e5SSebastian Reichel } 454*8c0984e5SSebastian Reichel } 455*8c0984e5SSebastian Reichel 456*8c0984e5SSebastian Reichel /** 457*8c0984e5SSebastian Reichel * ab8500_charger_get_ac_voltage() - get ac charger voltage 458*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 459*8c0984e5SSebastian Reichel * 460*8c0984e5SSebastian Reichel * Returns ac charger voltage (on success) 461*8c0984e5SSebastian Reichel */ 462*8c0984e5SSebastian Reichel static int ab8500_charger_get_ac_voltage(struct ab8500_charger *di) 463*8c0984e5SSebastian Reichel { 464*8c0984e5SSebastian Reichel int vch; 465*8c0984e5SSebastian Reichel 466*8c0984e5SSebastian Reichel /* Only measure voltage if the charger is connected */ 467*8c0984e5SSebastian Reichel if (di->ac.charger_connected) { 468*8c0984e5SSebastian Reichel vch = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_V); 469*8c0984e5SSebastian Reichel if (vch < 0) 470*8c0984e5SSebastian Reichel dev_err(di->dev, "%s gpadc conv failed,\n", __func__); 471*8c0984e5SSebastian Reichel } else { 472*8c0984e5SSebastian Reichel vch = 0; 473*8c0984e5SSebastian Reichel } 474*8c0984e5SSebastian Reichel return vch; 475*8c0984e5SSebastian Reichel } 476*8c0984e5SSebastian Reichel 477*8c0984e5SSebastian Reichel /** 478*8c0984e5SSebastian Reichel * ab8500_charger_ac_cv() - check if the main charger is in CV mode 479*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 480*8c0984e5SSebastian Reichel * 481*8c0984e5SSebastian Reichel * Returns ac charger CV mode (on success) else error code 482*8c0984e5SSebastian Reichel */ 483*8c0984e5SSebastian Reichel static int ab8500_charger_ac_cv(struct ab8500_charger *di) 484*8c0984e5SSebastian Reichel { 485*8c0984e5SSebastian Reichel u8 val; 486*8c0984e5SSebastian Reichel int ret = 0; 487*8c0984e5SSebastian Reichel 488*8c0984e5SSebastian Reichel /* Only check CV mode if the charger is online */ 489*8c0984e5SSebastian Reichel if (di->ac.charger_online) { 490*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 491*8c0984e5SSebastian Reichel AB8500_CH_STATUS1_REG, &val); 492*8c0984e5SSebastian Reichel if (ret < 0) { 493*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 494*8c0984e5SSebastian Reichel return 0; 495*8c0984e5SSebastian Reichel } 496*8c0984e5SSebastian Reichel 497*8c0984e5SSebastian Reichel if (val & MAIN_CH_CV_ON) 498*8c0984e5SSebastian Reichel ret = 1; 499*8c0984e5SSebastian Reichel else 500*8c0984e5SSebastian Reichel ret = 0; 501*8c0984e5SSebastian Reichel } 502*8c0984e5SSebastian Reichel 503*8c0984e5SSebastian Reichel return ret; 504*8c0984e5SSebastian Reichel } 505*8c0984e5SSebastian Reichel 506*8c0984e5SSebastian Reichel /** 507*8c0984e5SSebastian Reichel * ab8500_charger_get_vbus_voltage() - get vbus voltage 508*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 509*8c0984e5SSebastian Reichel * 510*8c0984e5SSebastian Reichel * This function returns the vbus voltage. 511*8c0984e5SSebastian Reichel * Returns vbus voltage (on success) 512*8c0984e5SSebastian Reichel */ 513*8c0984e5SSebastian Reichel static int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di) 514*8c0984e5SSebastian Reichel { 515*8c0984e5SSebastian Reichel int vch; 516*8c0984e5SSebastian Reichel 517*8c0984e5SSebastian Reichel /* Only measure voltage if the charger is connected */ 518*8c0984e5SSebastian Reichel if (di->usb.charger_connected) { 519*8c0984e5SSebastian Reichel vch = ab8500_gpadc_convert(di->gpadc, VBUS_V); 520*8c0984e5SSebastian Reichel if (vch < 0) 521*8c0984e5SSebastian Reichel dev_err(di->dev, "%s gpadc conv failed\n", __func__); 522*8c0984e5SSebastian Reichel } else { 523*8c0984e5SSebastian Reichel vch = 0; 524*8c0984e5SSebastian Reichel } 525*8c0984e5SSebastian Reichel return vch; 526*8c0984e5SSebastian Reichel } 527*8c0984e5SSebastian Reichel 528*8c0984e5SSebastian Reichel /** 529*8c0984e5SSebastian Reichel * ab8500_charger_get_usb_current() - get usb charger current 530*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 531*8c0984e5SSebastian Reichel * 532*8c0984e5SSebastian Reichel * This function returns the usb charger current. 533*8c0984e5SSebastian Reichel * Returns usb current (on success) and error code on failure 534*8c0984e5SSebastian Reichel */ 535*8c0984e5SSebastian Reichel static int ab8500_charger_get_usb_current(struct ab8500_charger *di) 536*8c0984e5SSebastian Reichel { 537*8c0984e5SSebastian Reichel int ich; 538*8c0984e5SSebastian Reichel 539*8c0984e5SSebastian Reichel /* Only measure current if the charger is online */ 540*8c0984e5SSebastian Reichel if (di->usb.charger_online) { 541*8c0984e5SSebastian Reichel ich = ab8500_gpadc_convert(di->gpadc, USB_CHARGER_C); 542*8c0984e5SSebastian Reichel if (ich < 0) 543*8c0984e5SSebastian Reichel dev_err(di->dev, "%s gpadc conv failed\n", __func__); 544*8c0984e5SSebastian Reichel } else { 545*8c0984e5SSebastian Reichel ich = 0; 546*8c0984e5SSebastian Reichel } 547*8c0984e5SSebastian Reichel return ich; 548*8c0984e5SSebastian Reichel } 549*8c0984e5SSebastian Reichel 550*8c0984e5SSebastian Reichel /** 551*8c0984e5SSebastian Reichel * ab8500_charger_get_ac_current() - get ac charger current 552*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 553*8c0984e5SSebastian Reichel * 554*8c0984e5SSebastian Reichel * This function returns the ac charger current. 555*8c0984e5SSebastian Reichel * Returns ac current (on success) and error code on failure. 556*8c0984e5SSebastian Reichel */ 557*8c0984e5SSebastian Reichel static int ab8500_charger_get_ac_current(struct ab8500_charger *di) 558*8c0984e5SSebastian Reichel { 559*8c0984e5SSebastian Reichel int ich; 560*8c0984e5SSebastian Reichel 561*8c0984e5SSebastian Reichel /* Only measure current if the charger is online */ 562*8c0984e5SSebastian Reichel if (di->ac.charger_online) { 563*8c0984e5SSebastian Reichel ich = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_C); 564*8c0984e5SSebastian Reichel if (ich < 0) 565*8c0984e5SSebastian Reichel dev_err(di->dev, "%s gpadc conv failed\n", __func__); 566*8c0984e5SSebastian Reichel } else { 567*8c0984e5SSebastian Reichel ich = 0; 568*8c0984e5SSebastian Reichel } 569*8c0984e5SSebastian Reichel return ich; 570*8c0984e5SSebastian Reichel } 571*8c0984e5SSebastian Reichel 572*8c0984e5SSebastian Reichel /** 573*8c0984e5SSebastian Reichel * ab8500_charger_usb_cv() - check if the usb charger is in CV mode 574*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 575*8c0984e5SSebastian Reichel * 576*8c0984e5SSebastian Reichel * Returns ac charger CV mode (on success) else error code 577*8c0984e5SSebastian Reichel */ 578*8c0984e5SSebastian Reichel static int ab8500_charger_usb_cv(struct ab8500_charger *di) 579*8c0984e5SSebastian Reichel { 580*8c0984e5SSebastian Reichel int ret; 581*8c0984e5SSebastian Reichel u8 val; 582*8c0984e5SSebastian Reichel 583*8c0984e5SSebastian Reichel /* Only check CV mode if the charger is online */ 584*8c0984e5SSebastian Reichel if (di->usb.charger_online) { 585*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 586*8c0984e5SSebastian Reichel AB8500_CH_USBCH_STAT1_REG, &val); 587*8c0984e5SSebastian Reichel if (ret < 0) { 588*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 589*8c0984e5SSebastian Reichel return 0; 590*8c0984e5SSebastian Reichel } 591*8c0984e5SSebastian Reichel 592*8c0984e5SSebastian Reichel if (val & USB_CH_CV_ON) 593*8c0984e5SSebastian Reichel ret = 1; 594*8c0984e5SSebastian Reichel else 595*8c0984e5SSebastian Reichel ret = 0; 596*8c0984e5SSebastian Reichel } else { 597*8c0984e5SSebastian Reichel ret = 0; 598*8c0984e5SSebastian Reichel } 599*8c0984e5SSebastian Reichel 600*8c0984e5SSebastian Reichel return ret; 601*8c0984e5SSebastian Reichel } 602*8c0984e5SSebastian Reichel 603*8c0984e5SSebastian Reichel /** 604*8c0984e5SSebastian Reichel * ab8500_charger_detect_chargers() - Detect the connected chargers 605*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 606*8c0984e5SSebastian Reichel * @probe: if probe, don't delay and wait for HW 607*8c0984e5SSebastian Reichel * 608*8c0984e5SSebastian Reichel * Returns the type of charger connected. 609*8c0984e5SSebastian Reichel * For USB it will not mean we can actually charge from it 610*8c0984e5SSebastian Reichel * but that there is a USB cable connected that we have to 611*8c0984e5SSebastian Reichel * identify. This is used during startup when we don't get 612*8c0984e5SSebastian Reichel * interrupts of the charger detection 613*8c0984e5SSebastian Reichel * 614*8c0984e5SSebastian Reichel * Returns an integer value, that means, 615*8c0984e5SSebastian Reichel * NO_PW_CONN no power supply is connected 616*8c0984e5SSebastian Reichel * AC_PW_CONN if the AC power supply is connected 617*8c0984e5SSebastian Reichel * USB_PW_CONN if the USB power supply is connected 618*8c0984e5SSebastian Reichel * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected 619*8c0984e5SSebastian Reichel */ 620*8c0984e5SSebastian Reichel static int ab8500_charger_detect_chargers(struct ab8500_charger *di, bool probe) 621*8c0984e5SSebastian Reichel { 622*8c0984e5SSebastian Reichel int result = NO_PW_CONN; 623*8c0984e5SSebastian Reichel int ret; 624*8c0984e5SSebastian Reichel u8 val; 625*8c0984e5SSebastian Reichel 626*8c0984e5SSebastian Reichel /* Check for AC charger */ 627*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 628*8c0984e5SSebastian Reichel AB8500_CH_STATUS1_REG, &val); 629*8c0984e5SSebastian Reichel if (ret < 0) { 630*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 631*8c0984e5SSebastian Reichel return ret; 632*8c0984e5SSebastian Reichel } 633*8c0984e5SSebastian Reichel 634*8c0984e5SSebastian Reichel if (val & MAIN_CH_DET) 635*8c0984e5SSebastian Reichel result = AC_PW_CONN; 636*8c0984e5SSebastian Reichel 637*8c0984e5SSebastian Reichel /* Check for USB charger */ 638*8c0984e5SSebastian Reichel 639*8c0984e5SSebastian Reichel if (!probe) { 640*8c0984e5SSebastian Reichel /* 641*8c0984e5SSebastian Reichel * AB8500 says VBUS_DET_DBNC1 & VBUS_DET_DBNC100 642*8c0984e5SSebastian Reichel * when disconnecting ACA even though no 643*8c0984e5SSebastian Reichel * charger was connected. Try waiting a little 644*8c0984e5SSebastian Reichel * longer than the 100 ms of VBUS_DET_DBNC100... 645*8c0984e5SSebastian Reichel */ 646*8c0984e5SSebastian Reichel msleep(110); 647*8c0984e5SSebastian Reichel } 648*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 649*8c0984e5SSebastian Reichel AB8500_CH_USBCH_STAT1_REG, &val); 650*8c0984e5SSebastian Reichel if (ret < 0) { 651*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 652*8c0984e5SSebastian Reichel return ret; 653*8c0984e5SSebastian Reichel } 654*8c0984e5SSebastian Reichel dev_dbg(di->dev, 655*8c0984e5SSebastian Reichel "%s AB8500_CH_USBCH_STAT1_REG %x\n", __func__, 656*8c0984e5SSebastian Reichel val); 657*8c0984e5SSebastian Reichel if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100)) 658*8c0984e5SSebastian Reichel result |= USB_PW_CONN; 659*8c0984e5SSebastian Reichel 660*8c0984e5SSebastian Reichel return result; 661*8c0984e5SSebastian Reichel } 662*8c0984e5SSebastian Reichel 663*8c0984e5SSebastian Reichel /** 664*8c0984e5SSebastian Reichel * ab8500_charger_max_usb_curr() - get the max curr for the USB type 665*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 666*8c0984e5SSebastian Reichel * @link_status: the identified USB type 667*8c0984e5SSebastian Reichel * 668*8c0984e5SSebastian Reichel * Get the maximum current that is allowed to be drawn from the host 669*8c0984e5SSebastian Reichel * based on the USB type. 670*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0 on success 671*8c0984e5SSebastian Reichel */ 672*8c0984e5SSebastian Reichel static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, 673*8c0984e5SSebastian Reichel enum ab8500_charger_link_status link_status) 674*8c0984e5SSebastian Reichel { 675*8c0984e5SSebastian Reichel int ret = 0; 676*8c0984e5SSebastian Reichel 677*8c0984e5SSebastian Reichel di->usb_device_is_unrecognised = false; 678*8c0984e5SSebastian Reichel 679*8c0984e5SSebastian Reichel /* 680*8c0984e5SSebastian Reichel * Platform only supports USB 2.0. 681*8c0984e5SSebastian Reichel * This means that charging current from USB source 682*8c0984e5SSebastian Reichel * is maximum 500 mA. Every occurence of USB_STAT_*_HOST_* 683*8c0984e5SSebastian Reichel * should set USB_CH_IP_CUR_LVL_0P5. 684*8c0984e5SSebastian Reichel */ 685*8c0984e5SSebastian Reichel 686*8c0984e5SSebastian Reichel switch (link_status) { 687*8c0984e5SSebastian Reichel case USB_STAT_STD_HOST_NC: 688*8c0984e5SSebastian Reichel case USB_STAT_STD_HOST_C_NS: 689*8c0984e5SSebastian Reichel case USB_STAT_STD_HOST_C_S: 690*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB Type - Standard host is " 691*8c0984e5SSebastian Reichel "detected through USB driver\n"); 692*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 693*8c0984e5SSebastian Reichel di->is_aca_rid = 0; 694*8c0984e5SSebastian Reichel break; 695*8c0984e5SSebastian Reichel case USB_STAT_HOST_CHG_HS_CHIRP: 696*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 697*8c0984e5SSebastian Reichel di->is_aca_rid = 0; 698*8c0984e5SSebastian Reichel break; 699*8c0984e5SSebastian Reichel case USB_STAT_HOST_CHG_HS: 700*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 701*8c0984e5SSebastian Reichel di->is_aca_rid = 0; 702*8c0984e5SSebastian Reichel break; 703*8c0984e5SSebastian Reichel case USB_STAT_ACA_RID_C_HS: 704*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P9; 705*8c0984e5SSebastian Reichel di->is_aca_rid = 0; 706*8c0984e5SSebastian Reichel break; 707*8c0984e5SSebastian Reichel case USB_STAT_ACA_RID_A: 708*8c0984e5SSebastian Reichel /* 709*8c0984e5SSebastian Reichel * Dedicated charger level minus maximum current accessory 710*8c0984e5SSebastian Reichel * can consume (900mA). Closest level is 500mA 711*8c0984e5SSebastian Reichel */ 712*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n"); 713*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 714*8c0984e5SSebastian Reichel di->is_aca_rid = 1; 715*8c0984e5SSebastian Reichel break; 716*8c0984e5SSebastian Reichel case USB_STAT_ACA_RID_B: 717*8c0984e5SSebastian Reichel /* 718*8c0984e5SSebastian Reichel * Dedicated charger level minus 120mA (20mA for ACA and 719*8c0984e5SSebastian Reichel * 100mA for potential accessory). Closest level is 1300mA 720*8c0984e5SSebastian Reichel */ 721*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P3; 722*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, 723*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 724*8c0984e5SSebastian Reichel di->is_aca_rid = 1; 725*8c0984e5SSebastian Reichel break; 726*8c0984e5SSebastian Reichel case USB_STAT_HOST_CHG_NM: 727*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 728*8c0984e5SSebastian Reichel di->is_aca_rid = 0; 729*8c0984e5SSebastian Reichel break; 730*8c0984e5SSebastian Reichel case USB_STAT_DEDICATED_CHG: 731*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5; 732*8c0984e5SSebastian Reichel di->is_aca_rid = 0; 733*8c0984e5SSebastian Reichel break; 734*8c0984e5SSebastian Reichel case USB_STAT_ACA_RID_C_HS_CHIRP: 735*8c0984e5SSebastian Reichel case USB_STAT_ACA_RID_C_NM: 736*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5; 737*8c0984e5SSebastian Reichel di->is_aca_rid = 1; 738*8c0984e5SSebastian Reichel break; 739*8c0984e5SSebastian Reichel case USB_STAT_NOT_CONFIGURED: 740*8c0984e5SSebastian Reichel if (di->vbus_detected) { 741*8c0984e5SSebastian Reichel di->usb_device_is_unrecognised = true; 742*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB Type - Legacy charger.\n"); 743*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = 744*8c0984e5SSebastian Reichel USB_CH_IP_CUR_LVL_1P5; 745*8c0984e5SSebastian Reichel break; 746*8c0984e5SSebastian Reichel } 747*8c0984e5SSebastian Reichel case USB_STAT_HM_IDGND: 748*8c0984e5SSebastian Reichel dev_err(di->dev, "USB Type - Charging not allowed\n"); 749*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; 750*8c0984e5SSebastian Reichel ret = -ENXIO; 751*8c0984e5SSebastian Reichel break; 752*8c0984e5SSebastian Reichel case USB_STAT_RESERVED: 753*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) { 754*8c0984e5SSebastian Reichel di->flags.vbus_collapse = true; 755*8c0984e5SSebastian Reichel dev_err(di->dev, "USB Type - USB_STAT_RESERVED " 756*8c0984e5SSebastian Reichel "VBUS has collapsed\n"); 757*8c0984e5SSebastian Reichel ret = -ENXIO; 758*8c0984e5SSebastian Reichel break; 759*8c0984e5SSebastian Reichel } else { 760*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB Type - Charging not allowed\n"); 761*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = 762*8c0984e5SSebastian Reichel USB_CH_IP_CUR_LVL_0P05; 763*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", 764*8c0984e5SSebastian Reichel link_status, 765*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 766*8c0984e5SSebastian Reichel ret = -ENXIO; 767*8c0984e5SSebastian Reichel break; 768*8c0984e5SSebastian Reichel } 769*8c0984e5SSebastian Reichel case USB_STAT_CARKIT_1: 770*8c0984e5SSebastian Reichel case USB_STAT_CARKIT_2: 771*8c0984e5SSebastian Reichel case USB_STAT_ACA_DOCK_CHARGER: 772*8c0984e5SSebastian Reichel case USB_STAT_CHARGER_LINE_1: 773*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 774*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, 775*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 776*8c0984e5SSebastian Reichel break; 777*8c0984e5SSebastian Reichel case USB_STAT_NOT_VALID_LINK: 778*8c0984e5SSebastian Reichel dev_err(di->dev, "USB Type invalid - try charging anyway\n"); 779*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 780*8c0984e5SSebastian Reichel break; 781*8c0984e5SSebastian Reichel 782*8c0984e5SSebastian Reichel default: 783*8c0984e5SSebastian Reichel dev_err(di->dev, "USB Type - Unknown\n"); 784*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; 785*8c0984e5SSebastian Reichel ret = -ENXIO; 786*8c0984e5SSebastian Reichel break; 787*8c0984e5SSebastian Reichel }; 788*8c0984e5SSebastian Reichel 789*8c0984e5SSebastian Reichel di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max; 790*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", 791*8c0984e5SSebastian Reichel link_status, di->max_usb_in_curr.set_max); 792*8c0984e5SSebastian Reichel 793*8c0984e5SSebastian Reichel return ret; 794*8c0984e5SSebastian Reichel } 795*8c0984e5SSebastian Reichel 796*8c0984e5SSebastian Reichel /** 797*8c0984e5SSebastian Reichel * ab8500_charger_read_usb_type() - read the type of usb connected 798*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 799*8c0984e5SSebastian Reichel * 800*8c0984e5SSebastian Reichel * Detect the type of the plugged USB 801*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0 on success 802*8c0984e5SSebastian Reichel */ 803*8c0984e5SSebastian Reichel static int ab8500_charger_read_usb_type(struct ab8500_charger *di) 804*8c0984e5SSebastian Reichel { 805*8c0984e5SSebastian Reichel int ret; 806*8c0984e5SSebastian Reichel u8 val; 807*8c0984e5SSebastian Reichel 808*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 809*8c0984e5SSebastian Reichel AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val); 810*8c0984e5SSebastian Reichel if (ret < 0) { 811*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 812*8c0984e5SSebastian Reichel return ret; 813*8c0984e5SSebastian Reichel } 814*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 815*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 816*8c0984e5SSebastian Reichel AB8500_USB_LINE_STAT_REG, &val); 817*8c0984e5SSebastian Reichel else 818*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 819*8c0984e5SSebastian Reichel AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); 820*8c0984e5SSebastian Reichel if (ret < 0) { 821*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 822*8c0984e5SSebastian Reichel return ret; 823*8c0984e5SSebastian Reichel } 824*8c0984e5SSebastian Reichel 825*8c0984e5SSebastian Reichel /* get the USB type */ 826*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 827*8c0984e5SSebastian Reichel val = (val & AB8500_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT; 828*8c0984e5SSebastian Reichel else 829*8c0984e5SSebastian Reichel val = (val & AB8505_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT; 830*8c0984e5SSebastian Reichel ret = ab8500_charger_max_usb_curr(di, 831*8c0984e5SSebastian Reichel (enum ab8500_charger_link_status) val); 832*8c0984e5SSebastian Reichel 833*8c0984e5SSebastian Reichel return ret; 834*8c0984e5SSebastian Reichel } 835*8c0984e5SSebastian Reichel 836*8c0984e5SSebastian Reichel /** 837*8c0984e5SSebastian Reichel * ab8500_charger_detect_usb_type() - get the type of usb connected 838*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 839*8c0984e5SSebastian Reichel * 840*8c0984e5SSebastian Reichel * Detect the type of the plugged USB 841*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0 on success 842*8c0984e5SSebastian Reichel */ 843*8c0984e5SSebastian Reichel static int ab8500_charger_detect_usb_type(struct ab8500_charger *di) 844*8c0984e5SSebastian Reichel { 845*8c0984e5SSebastian Reichel int i, ret; 846*8c0984e5SSebastian Reichel u8 val; 847*8c0984e5SSebastian Reichel 848*8c0984e5SSebastian Reichel /* 849*8c0984e5SSebastian Reichel * On getting the VBUS rising edge detect interrupt there 850*8c0984e5SSebastian Reichel * is a 250ms delay after which the register UsbLineStatus 851*8c0984e5SSebastian Reichel * is filled with valid data. 852*8c0984e5SSebastian Reichel */ 853*8c0984e5SSebastian Reichel for (i = 0; i < 10; i++) { 854*8c0984e5SSebastian Reichel msleep(250); 855*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 856*8c0984e5SSebastian Reichel AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, 857*8c0984e5SSebastian Reichel &val); 858*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s AB8500_IT_SOURCE21_REG %x\n", 859*8c0984e5SSebastian Reichel __func__, val); 860*8c0984e5SSebastian Reichel if (ret < 0) { 861*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 862*8c0984e5SSebastian Reichel return ret; 863*8c0984e5SSebastian Reichel } 864*8c0984e5SSebastian Reichel 865*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 866*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 867*8c0984e5SSebastian Reichel AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); 868*8c0984e5SSebastian Reichel else 869*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 870*8c0984e5SSebastian Reichel AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); 871*8c0984e5SSebastian Reichel if (ret < 0) { 872*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 873*8c0984e5SSebastian Reichel return ret; 874*8c0984e5SSebastian Reichel } 875*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s AB8500_USB_LINE_STAT_REG %x\n", __func__, 876*8c0984e5SSebastian Reichel val); 877*8c0984e5SSebastian Reichel /* 878*8c0984e5SSebastian Reichel * Until the IT source register is read the UsbLineStatus 879*8c0984e5SSebastian Reichel * register is not updated, hence doing the same 880*8c0984e5SSebastian Reichel * Revisit this: 881*8c0984e5SSebastian Reichel */ 882*8c0984e5SSebastian Reichel 883*8c0984e5SSebastian Reichel /* get the USB type */ 884*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 885*8c0984e5SSebastian Reichel val = (val & AB8500_USB_LINK_STATUS) >> 886*8c0984e5SSebastian Reichel USB_LINK_STATUS_SHIFT; 887*8c0984e5SSebastian Reichel else 888*8c0984e5SSebastian Reichel val = (val & AB8505_USB_LINK_STATUS) >> 889*8c0984e5SSebastian Reichel USB_LINK_STATUS_SHIFT; 890*8c0984e5SSebastian Reichel if (val) 891*8c0984e5SSebastian Reichel break; 892*8c0984e5SSebastian Reichel } 893*8c0984e5SSebastian Reichel ret = ab8500_charger_max_usb_curr(di, 894*8c0984e5SSebastian Reichel (enum ab8500_charger_link_status) val); 895*8c0984e5SSebastian Reichel 896*8c0984e5SSebastian Reichel return ret; 897*8c0984e5SSebastian Reichel } 898*8c0984e5SSebastian Reichel 899*8c0984e5SSebastian Reichel /* 900*8c0984e5SSebastian Reichel * This array maps the raw hex value to charger voltage used by the AB8500 901*8c0984e5SSebastian Reichel * Values taken from the UM0836 902*8c0984e5SSebastian Reichel */ 903*8c0984e5SSebastian Reichel static int ab8500_charger_voltage_map[] = { 904*8c0984e5SSebastian Reichel 3500 , 905*8c0984e5SSebastian Reichel 3525 , 906*8c0984e5SSebastian Reichel 3550 , 907*8c0984e5SSebastian Reichel 3575 , 908*8c0984e5SSebastian Reichel 3600 , 909*8c0984e5SSebastian Reichel 3625 , 910*8c0984e5SSebastian Reichel 3650 , 911*8c0984e5SSebastian Reichel 3675 , 912*8c0984e5SSebastian Reichel 3700 , 913*8c0984e5SSebastian Reichel 3725 , 914*8c0984e5SSebastian Reichel 3750 , 915*8c0984e5SSebastian Reichel 3775 , 916*8c0984e5SSebastian Reichel 3800 , 917*8c0984e5SSebastian Reichel 3825 , 918*8c0984e5SSebastian Reichel 3850 , 919*8c0984e5SSebastian Reichel 3875 , 920*8c0984e5SSebastian Reichel 3900 , 921*8c0984e5SSebastian Reichel 3925 , 922*8c0984e5SSebastian Reichel 3950 , 923*8c0984e5SSebastian Reichel 3975 , 924*8c0984e5SSebastian Reichel 4000 , 925*8c0984e5SSebastian Reichel 4025 , 926*8c0984e5SSebastian Reichel 4050 , 927*8c0984e5SSebastian Reichel 4060 , 928*8c0984e5SSebastian Reichel 4070 , 929*8c0984e5SSebastian Reichel 4080 , 930*8c0984e5SSebastian Reichel 4090 , 931*8c0984e5SSebastian Reichel 4100 , 932*8c0984e5SSebastian Reichel 4110 , 933*8c0984e5SSebastian Reichel 4120 , 934*8c0984e5SSebastian Reichel 4130 , 935*8c0984e5SSebastian Reichel 4140 , 936*8c0984e5SSebastian Reichel 4150 , 937*8c0984e5SSebastian Reichel 4160 , 938*8c0984e5SSebastian Reichel 4170 , 939*8c0984e5SSebastian Reichel 4180 , 940*8c0984e5SSebastian Reichel 4190 , 941*8c0984e5SSebastian Reichel 4200 , 942*8c0984e5SSebastian Reichel 4210 , 943*8c0984e5SSebastian Reichel 4220 , 944*8c0984e5SSebastian Reichel 4230 , 945*8c0984e5SSebastian Reichel 4240 , 946*8c0984e5SSebastian Reichel 4250 , 947*8c0984e5SSebastian Reichel 4260 , 948*8c0984e5SSebastian Reichel 4270 , 949*8c0984e5SSebastian Reichel 4280 , 950*8c0984e5SSebastian Reichel 4290 , 951*8c0984e5SSebastian Reichel 4300 , 952*8c0984e5SSebastian Reichel 4310 , 953*8c0984e5SSebastian Reichel 4320 , 954*8c0984e5SSebastian Reichel 4330 , 955*8c0984e5SSebastian Reichel 4340 , 956*8c0984e5SSebastian Reichel 4350 , 957*8c0984e5SSebastian Reichel 4360 , 958*8c0984e5SSebastian Reichel 4370 , 959*8c0984e5SSebastian Reichel 4380 , 960*8c0984e5SSebastian Reichel 4390 , 961*8c0984e5SSebastian Reichel 4400 , 962*8c0984e5SSebastian Reichel 4410 , 963*8c0984e5SSebastian Reichel 4420 , 964*8c0984e5SSebastian Reichel 4430 , 965*8c0984e5SSebastian Reichel 4440 , 966*8c0984e5SSebastian Reichel 4450 , 967*8c0984e5SSebastian Reichel 4460 , 968*8c0984e5SSebastian Reichel 4470 , 969*8c0984e5SSebastian Reichel 4480 , 970*8c0984e5SSebastian Reichel 4490 , 971*8c0984e5SSebastian Reichel 4500 , 972*8c0984e5SSebastian Reichel 4510 , 973*8c0984e5SSebastian Reichel 4520 , 974*8c0984e5SSebastian Reichel 4530 , 975*8c0984e5SSebastian Reichel 4540 , 976*8c0984e5SSebastian Reichel 4550 , 977*8c0984e5SSebastian Reichel 4560 , 978*8c0984e5SSebastian Reichel 4570 , 979*8c0984e5SSebastian Reichel 4580 , 980*8c0984e5SSebastian Reichel 4590 , 981*8c0984e5SSebastian Reichel 4600 , 982*8c0984e5SSebastian Reichel }; 983*8c0984e5SSebastian Reichel 984*8c0984e5SSebastian Reichel static int ab8500_voltage_to_regval(int voltage) 985*8c0984e5SSebastian Reichel { 986*8c0984e5SSebastian Reichel int i; 987*8c0984e5SSebastian Reichel 988*8c0984e5SSebastian Reichel /* Special case for voltage below 3.5V */ 989*8c0984e5SSebastian Reichel if (voltage < ab8500_charger_voltage_map[0]) 990*8c0984e5SSebastian Reichel return LOW_VOLT_REG; 991*8c0984e5SSebastian Reichel 992*8c0984e5SSebastian Reichel for (i = 1; i < ARRAY_SIZE(ab8500_charger_voltage_map); i++) { 993*8c0984e5SSebastian Reichel if (voltage < ab8500_charger_voltage_map[i]) 994*8c0984e5SSebastian Reichel return i - 1; 995*8c0984e5SSebastian Reichel } 996*8c0984e5SSebastian Reichel 997*8c0984e5SSebastian Reichel /* If not last element, return error */ 998*8c0984e5SSebastian Reichel i = ARRAY_SIZE(ab8500_charger_voltage_map) - 1; 999*8c0984e5SSebastian Reichel if (voltage == ab8500_charger_voltage_map[i]) 1000*8c0984e5SSebastian Reichel return i; 1001*8c0984e5SSebastian Reichel else 1002*8c0984e5SSebastian Reichel return -1; 1003*8c0984e5SSebastian Reichel } 1004*8c0984e5SSebastian Reichel 1005*8c0984e5SSebastian Reichel static int ab8500_current_to_regval(struct ab8500_charger *di, int curr) 1006*8c0984e5SSebastian Reichel { 1007*8c0984e5SSebastian Reichel int i; 1008*8c0984e5SSebastian Reichel 1009*8c0984e5SSebastian Reichel if (curr < di->bm->chg_output_curr[0]) 1010*8c0984e5SSebastian Reichel return 0; 1011*8c0984e5SSebastian Reichel 1012*8c0984e5SSebastian Reichel for (i = 0; i < di->bm->n_chg_out_curr; i++) { 1013*8c0984e5SSebastian Reichel if (curr < di->bm->chg_output_curr[i]) 1014*8c0984e5SSebastian Reichel return i - 1; 1015*8c0984e5SSebastian Reichel } 1016*8c0984e5SSebastian Reichel 1017*8c0984e5SSebastian Reichel /* If not last element, return error */ 1018*8c0984e5SSebastian Reichel i = di->bm->n_chg_out_curr - 1; 1019*8c0984e5SSebastian Reichel if (curr == di->bm->chg_output_curr[i]) 1020*8c0984e5SSebastian Reichel return i; 1021*8c0984e5SSebastian Reichel else 1022*8c0984e5SSebastian Reichel return -1; 1023*8c0984e5SSebastian Reichel } 1024*8c0984e5SSebastian Reichel 1025*8c0984e5SSebastian Reichel static int ab8500_vbus_in_curr_to_regval(struct ab8500_charger *di, int curr) 1026*8c0984e5SSebastian Reichel { 1027*8c0984e5SSebastian Reichel int i; 1028*8c0984e5SSebastian Reichel 1029*8c0984e5SSebastian Reichel if (curr < di->bm->chg_input_curr[0]) 1030*8c0984e5SSebastian Reichel return 0; 1031*8c0984e5SSebastian Reichel 1032*8c0984e5SSebastian Reichel for (i = 0; i < di->bm->n_chg_in_curr; i++) { 1033*8c0984e5SSebastian Reichel if (curr < di->bm->chg_input_curr[i]) 1034*8c0984e5SSebastian Reichel return i - 1; 1035*8c0984e5SSebastian Reichel } 1036*8c0984e5SSebastian Reichel 1037*8c0984e5SSebastian Reichel /* If not last element, return error */ 1038*8c0984e5SSebastian Reichel i = di->bm->n_chg_in_curr - 1; 1039*8c0984e5SSebastian Reichel if (curr == di->bm->chg_input_curr[i]) 1040*8c0984e5SSebastian Reichel return i; 1041*8c0984e5SSebastian Reichel else 1042*8c0984e5SSebastian Reichel return -1; 1043*8c0984e5SSebastian Reichel } 1044*8c0984e5SSebastian Reichel 1045*8c0984e5SSebastian Reichel /** 1046*8c0984e5SSebastian Reichel * ab8500_charger_get_usb_cur() - get usb current 1047*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structre 1048*8c0984e5SSebastian Reichel * 1049*8c0984e5SSebastian Reichel * The usb stack provides the maximum current that can be drawn from 1050*8c0984e5SSebastian Reichel * the standard usb host. This will be in mA. 1051*8c0984e5SSebastian Reichel * This function converts current in mA to a value that can be written 1052*8c0984e5SSebastian Reichel * to the register. Returns -1 if charging is not allowed 1053*8c0984e5SSebastian Reichel */ 1054*8c0984e5SSebastian Reichel static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) 1055*8c0984e5SSebastian Reichel { 1056*8c0984e5SSebastian Reichel int ret = 0; 1057*8c0984e5SSebastian Reichel switch (di->usb_state.usb_current) { 1058*8c0984e5SSebastian Reichel case 100: 1059*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P09; 1060*8c0984e5SSebastian Reichel break; 1061*8c0984e5SSebastian Reichel case 200: 1062*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P19; 1063*8c0984e5SSebastian Reichel break; 1064*8c0984e5SSebastian Reichel case 300: 1065*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P29; 1066*8c0984e5SSebastian Reichel break; 1067*8c0984e5SSebastian Reichel case 400: 1068*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P38; 1069*8c0984e5SSebastian Reichel break; 1070*8c0984e5SSebastian Reichel case 500: 1071*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 1072*8c0984e5SSebastian Reichel break; 1073*8c0984e5SSebastian Reichel default: 1074*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; 1075*8c0984e5SSebastian Reichel ret = -EPERM; 1076*8c0984e5SSebastian Reichel break; 1077*8c0984e5SSebastian Reichel }; 1078*8c0984e5SSebastian Reichel di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max; 1079*8c0984e5SSebastian Reichel return ret; 1080*8c0984e5SSebastian Reichel } 1081*8c0984e5SSebastian Reichel 1082*8c0984e5SSebastian Reichel /** 1083*8c0984e5SSebastian Reichel * ab8500_charger_check_continue_stepping() - Check to allow stepping 1084*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1085*8c0984e5SSebastian Reichel * @reg: select what charger register to check 1086*8c0984e5SSebastian Reichel * 1087*8c0984e5SSebastian Reichel * Check if current stepping should be allowed to continue. 1088*8c0984e5SSebastian Reichel * Checks if charger source has not collapsed. If it has, further stepping 1089*8c0984e5SSebastian Reichel * is not allowed. 1090*8c0984e5SSebastian Reichel */ 1091*8c0984e5SSebastian Reichel static bool ab8500_charger_check_continue_stepping(struct ab8500_charger *di, 1092*8c0984e5SSebastian Reichel int reg) 1093*8c0984e5SSebastian Reichel { 1094*8c0984e5SSebastian Reichel if (reg == AB8500_USBCH_IPT_CRNTLVL_REG) 1095*8c0984e5SSebastian Reichel return !di->flags.vbus_drop_end; 1096*8c0984e5SSebastian Reichel else 1097*8c0984e5SSebastian Reichel return true; 1098*8c0984e5SSebastian Reichel } 1099*8c0984e5SSebastian Reichel 1100*8c0984e5SSebastian Reichel /** 1101*8c0984e5SSebastian Reichel * ab8500_charger_set_current() - set charger current 1102*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1103*8c0984e5SSebastian Reichel * @ich: charger current, in mA 1104*8c0984e5SSebastian Reichel * @reg: select what charger register to set 1105*8c0984e5SSebastian Reichel * 1106*8c0984e5SSebastian Reichel * Set charger current. 1107*8c0984e5SSebastian Reichel * There is no state machine in the AB to step up/down the charger 1108*8c0984e5SSebastian Reichel * current to avoid dips and spikes on MAIN, VBUS and VBAT when 1109*8c0984e5SSebastian Reichel * charging is started. Instead we need to implement 1110*8c0984e5SSebastian Reichel * this charger current step-up/down here. 1111*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1112*8c0984e5SSebastian Reichel */ 1113*8c0984e5SSebastian Reichel static int ab8500_charger_set_current(struct ab8500_charger *di, 1114*8c0984e5SSebastian Reichel int ich, int reg) 1115*8c0984e5SSebastian Reichel { 1116*8c0984e5SSebastian Reichel int ret = 0; 1117*8c0984e5SSebastian Reichel int curr_index, prev_curr_index, shift_value, i; 1118*8c0984e5SSebastian Reichel u8 reg_value; 1119*8c0984e5SSebastian Reichel u32 step_udelay; 1120*8c0984e5SSebastian Reichel bool no_stepping = false; 1121*8c0984e5SSebastian Reichel 1122*8c0984e5SSebastian Reichel atomic_inc(&di->current_stepping_sessions); 1123*8c0984e5SSebastian Reichel 1124*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 1125*8c0984e5SSebastian Reichel reg, ®_value); 1126*8c0984e5SSebastian Reichel if (ret < 0) { 1127*8c0984e5SSebastian Reichel dev_err(di->dev, "%s read failed\n", __func__); 1128*8c0984e5SSebastian Reichel goto exit_set_current; 1129*8c0984e5SSebastian Reichel } 1130*8c0984e5SSebastian Reichel 1131*8c0984e5SSebastian Reichel switch (reg) { 1132*8c0984e5SSebastian Reichel case AB8500_MCH_IPT_CURLVL_REG: 1133*8c0984e5SSebastian Reichel shift_value = MAIN_CH_INPUT_CURR_SHIFT; 1134*8c0984e5SSebastian Reichel prev_curr_index = (reg_value >> shift_value); 1135*8c0984e5SSebastian Reichel curr_index = ab8500_current_to_regval(di, ich); 1136*8c0984e5SSebastian Reichel step_udelay = STEP_UDELAY; 1137*8c0984e5SSebastian Reichel if (!di->ac.charger_connected) 1138*8c0984e5SSebastian Reichel no_stepping = true; 1139*8c0984e5SSebastian Reichel break; 1140*8c0984e5SSebastian Reichel case AB8500_USBCH_IPT_CRNTLVL_REG: 1141*8c0984e5SSebastian Reichel if (is_ab8540(di->parent)) 1142*8c0984e5SSebastian Reichel shift_value = AB8540_VBUS_IN_CURR_LIM_SHIFT; 1143*8c0984e5SSebastian Reichel else 1144*8c0984e5SSebastian Reichel shift_value = VBUS_IN_CURR_LIM_SHIFT; 1145*8c0984e5SSebastian Reichel prev_curr_index = (reg_value >> shift_value); 1146*8c0984e5SSebastian Reichel curr_index = ab8500_vbus_in_curr_to_regval(di, ich); 1147*8c0984e5SSebastian Reichel step_udelay = STEP_UDELAY * 100; 1148*8c0984e5SSebastian Reichel 1149*8c0984e5SSebastian Reichel if (!di->usb.charger_connected) 1150*8c0984e5SSebastian Reichel no_stepping = true; 1151*8c0984e5SSebastian Reichel break; 1152*8c0984e5SSebastian Reichel case AB8500_CH_OPT_CRNTLVL_REG: 1153*8c0984e5SSebastian Reichel shift_value = 0; 1154*8c0984e5SSebastian Reichel prev_curr_index = (reg_value >> shift_value); 1155*8c0984e5SSebastian Reichel curr_index = ab8500_current_to_regval(di, ich); 1156*8c0984e5SSebastian Reichel step_udelay = STEP_UDELAY; 1157*8c0984e5SSebastian Reichel if (curr_index && (curr_index - prev_curr_index) > 1) 1158*8c0984e5SSebastian Reichel step_udelay *= 100; 1159*8c0984e5SSebastian Reichel 1160*8c0984e5SSebastian Reichel if (!di->usb.charger_connected && !di->ac.charger_connected) 1161*8c0984e5SSebastian Reichel no_stepping = true; 1162*8c0984e5SSebastian Reichel 1163*8c0984e5SSebastian Reichel break; 1164*8c0984e5SSebastian Reichel default: 1165*8c0984e5SSebastian Reichel dev_err(di->dev, "%s current register not valid\n", __func__); 1166*8c0984e5SSebastian Reichel ret = -ENXIO; 1167*8c0984e5SSebastian Reichel goto exit_set_current; 1168*8c0984e5SSebastian Reichel } 1169*8c0984e5SSebastian Reichel 1170*8c0984e5SSebastian Reichel if (curr_index < 0) { 1171*8c0984e5SSebastian Reichel dev_err(di->dev, "requested current limit out-of-range\n"); 1172*8c0984e5SSebastian Reichel ret = -ENXIO; 1173*8c0984e5SSebastian Reichel goto exit_set_current; 1174*8c0984e5SSebastian Reichel } 1175*8c0984e5SSebastian Reichel 1176*8c0984e5SSebastian Reichel /* only update current if it's been changed */ 1177*8c0984e5SSebastian Reichel if (prev_curr_index == curr_index) { 1178*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s current not changed for reg: 0x%02x\n", 1179*8c0984e5SSebastian Reichel __func__, reg); 1180*8c0984e5SSebastian Reichel ret = 0; 1181*8c0984e5SSebastian Reichel goto exit_set_current; 1182*8c0984e5SSebastian Reichel } 1183*8c0984e5SSebastian Reichel 1184*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n", 1185*8c0984e5SSebastian Reichel __func__, ich, reg); 1186*8c0984e5SSebastian Reichel 1187*8c0984e5SSebastian Reichel if (no_stepping) { 1188*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1189*8c0984e5SSebastian Reichel reg, (u8)curr_index << shift_value); 1190*8c0984e5SSebastian Reichel if (ret) 1191*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1192*8c0984e5SSebastian Reichel } else if (prev_curr_index > curr_index) { 1193*8c0984e5SSebastian Reichel for (i = prev_curr_index - 1; i >= curr_index; i--) { 1194*8c0984e5SSebastian Reichel dev_dbg(di->dev, "curr change_1 to: %x for 0x%02x\n", 1195*8c0984e5SSebastian Reichel (u8) i << shift_value, reg); 1196*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 1197*8c0984e5SSebastian Reichel AB8500_CHARGER, reg, (u8)i << shift_value); 1198*8c0984e5SSebastian Reichel if (ret) { 1199*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1200*8c0984e5SSebastian Reichel goto exit_set_current; 1201*8c0984e5SSebastian Reichel } 1202*8c0984e5SSebastian Reichel if (i != curr_index) 1203*8c0984e5SSebastian Reichel usleep_range(step_udelay, step_udelay * 2); 1204*8c0984e5SSebastian Reichel } 1205*8c0984e5SSebastian Reichel } else { 1206*8c0984e5SSebastian Reichel bool allow = true; 1207*8c0984e5SSebastian Reichel for (i = prev_curr_index + 1; i <= curr_index && allow; i++) { 1208*8c0984e5SSebastian Reichel dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n", 1209*8c0984e5SSebastian Reichel (u8)i << shift_value, reg); 1210*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 1211*8c0984e5SSebastian Reichel AB8500_CHARGER, reg, (u8)i << shift_value); 1212*8c0984e5SSebastian Reichel if (ret) { 1213*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1214*8c0984e5SSebastian Reichel goto exit_set_current; 1215*8c0984e5SSebastian Reichel } 1216*8c0984e5SSebastian Reichel if (i != curr_index) 1217*8c0984e5SSebastian Reichel usleep_range(step_udelay, step_udelay * 2); 1218*8c0984e5SSebastian Reichel 1219*8c0984e5SSebastian Reichel allow = ab8500_charger_check_continue_stepping(di, reg); 1220*8c0984e5SSebastian Reichel } 1221*8c0984e5SSebastian Reichel } 1222*8c0984e5SSebastian Reichel 1223*8c0984e5SSebastian Reichel exit_set_current: 1224*8c0984e5SSebastian Reichel atomic_dec(&di->current_stepping_sessions); 1225*8c0984e5SSebastian Reichel 1226*8c0984e5SSebastian Reichel return ret; 1227*8c0984e5SSebastian Reichel } 1228*8c0984e5SSebastian Reichel 1229*8c0984e5SSebastian Reichel /** 1230*8c0984e5SSebastian Reichel * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit 1231*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1232*8c0984e5SSebastian Reichel * @ich_in: charger input current limit 1233*8c0984e5SSebastian Reichel * 1234*8c0984e5SSebastian Reichel * Sets the current that can be drawn from the USB host 1235*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1236*8c0984e5SSebastian Reichel */ 1237*8c0984e5SSebastian Reichel static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, 1238*8c0984e5SSebastian Reichel int ich_in) 1239*8c0984e5SSebastian Reichel { 1240*8c0984e5SSebastian Reichel int min_value; 1241*8c0984e5SSebastian Reichel int ret; 1242*8c0984e5SSebastian Reichel 1243*8c0984e5SSebastian Reichel /* We should always use to lowest current limit */ 1244*8c0984e5SSebastian Reichel min_value = min(di->bm->chg_params->usb_curr_max, ich_in); 1245*8c0984e5SSebastian Reichel if (di->max_usb_in_curr.set_max > 0) 1246*8c0984e5SSebastian Reichel min_value = min(di->max_usb_in_curr.set_max, min_value); 1247*8c0984e5SSebastian Reichel 1248*8c0984e5SSebastian Reichel if (di->usb_state.usb_current >= 0) 1249*8c0984e5SSebastian Reichel min_value = min(di->usb_state.usb_current, min_value); 1250*8c0984e5SSebastian Reichel 1251*8c0984e5SSebastian Reichel switch (min_value) { 1252*8c0984e5SSebastian Reichel case 100: 1253*8c0984e5SSebastian Reichel if (di->vbat < VBAT_TRESH_IP_CUR_RED) 1254*8c0984e5SSebastian Reichel min_value = USB_CH_IP_CUR_LVL_0P05; 1255*8c0984e5SSebastian Reichel break; 1256*8c0984e5SSebastian Reichel case 500: 1257*8c0984e5SSebastian Reichel if (di->vbat < VBAT_TRESH_IP_CUR_RED) 1258*8c0984e5SSebastian Reichel min_value = USB_CH_IP_CUR_LVL_0P45; 1259*8c0984e5SSebastian Reichel break; 1260*8c0984e5SSebastian Reichel default: 1261*8c0984e5SSebastian Reichel break; 1262*8c0984e5SSebastian Reichel } 1263*8c0984e5SSebastian Reichel 1264*8c0984e5SSebastian Reichel dev_info(di->dev, "VBUS input current limit set to %d mA\n", min_value); 1265*8c0984e5SSebastian Reichel 1266*8c0984e5SSebastian Reichel mutex_lock(&di->usb_ipt_crnt_lock); 1267*8c0984e5SSebastian Reichel ret = ab8500_charger_set_current(di, min_value, 1268*8c0984e5SSebastian Reichel AB8500_USBCH_IPT_CRNTLVL_REG); 1269*8c0984e5SSebastian Reichel mutex_unlock(&di->usb_ipt_crnt_lock); 1270*8c0984e5SSebastian Reichel 1271*8c0984e5SSebastian Reichel return ret; 1272*8c0984e5SSebastian Reichel } 1273*8c0984e5SSebastian Reichel 1274*8c0984e5SSebastian Reichel /** 1275*8c0984e5SSebastian Reichel * ab8500_charger_set_main_in_curr() - set main charger input current 1276*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1277*8c0984e5SSebastian Reichel * @ich_in: input charger current, in mA 1278*8c0984e5SSebastian Reichel * 1279*8c0984e5SSebastian Reichel * Set main charger input current. 1280*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1281*8c0984e5SSebastian Reichel */ 1282*8c0984e5SSebastian Reichel static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di, 1283*8c0984e5SSebastian Reichel int ich_in) 1284*8c0984e5SSebastian Reichel { 1285*8c0984e5SSebastian Reichel return ab8500_charger_set_current(di, ich_in, 1286*8c0984e5SSebastian Reichel AB8500_MCH_IPT_CURLVL_REG); 1287*8c0984e5SSebastian Reichel } 1288*8c0984e5SSebastian Reichel 1289*8c0984e5SSebastian Reichel /** 1290*8c0984e5SSebastian Reichel * ab8500_charger_set_output_curr() - set charger output current 1291*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1292*8c0984e5SSebastian Reichel * @ich_out: output charger current, in mA 1293*8c0984e5SSebastian Reichel * 1294*8c0984e5SSebastian Reichel * Set charger output current. 1295*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1296*8c0984e5SSebastian Reichel */ 1297*8c0984e5SSebastian Reichel static int ab8500_charger_set_output_curr(struct ab8500_charger *di, 1298*8c0984e5SSebastian Reichel int ich_out) 1299*8c0984e5SSebastian Reichel { 1300*8c0984e5SSebastian Reichel return ab8500_charger_set_current(di, ich_out, 1301*8c0984e5SSebastian Reichel AB8500_CH_OPT_CRNTLVL_REG); 1302*8c0984e5SSebastian Reichel } 1303*8c0984e5SSebastian Reichel 1304*8c0984e5SSebastian Reichel /** 1305*8c0984e5SSebastian Reichel * ab8500_charger_led_en() - turn on/off chargign led 1306*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1307*8c0984e5SSebastian Reichel * @on: flag to turn on/off the chargign led 1308*8c0984e5SSebastian Reichel * 1309*8c0984e5SSebastian Reichel * Power ON/OFF charging LED indication 1310*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1311*8c0984e5SSebastian Reichel */ 1312*8c0984e5SSebastian Reichel static int ab8500_charger_led_en(struct ab8500_charger *di, int on) 1313*8c0984e5SSebastian Reichel { 1314*8c0984e5SSebastian Reichel int ret; 1315*8c0984e5SSebastian Reichel 1316*8c0984e5SSebastian Reichel if (on) { 1317*8c0984e5SSebastian Reichel /* Power ON charging LED indicator, set LED current to 5mA */ 1318*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1319*8c0984e5SSebastian Reichel AB8500_LED_INDICATOR_PWM_CTRL, 1320*8c0984e5SSebastian Reichel (LED_IND_CUR_5MA | LED_INDICATOR_PWM_ENA)); 1321*8c0984e5SSebastian Reichel if (ret) { 1322*8c0984e5SSebastian Reichel dev_err(di->dev, "Power ON LED failed\n"); 1323*8c0984e5SSebastian Reichel return ret; 1324*8c0984e5SSebastian Reichel } 1325*8c0984e5SSebastian Reichel /* LED indicator PWM duty cycle 252/256 */ 1326*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1327*8c0984e5SSebastian Reichel AB8500_LED_INDICATOR_PWM_DUTY, 1328*8c0984e5SSebastian Reichel LED_INDICATOR_PWM_DUTY_252_256); 1329*8c0984e5SSebastian Reichel if (ret) { 1330*8c0984e5SSebastian Reichel dev_err(di->dev, "Set LED PWM duty cycle failed\n"); 1331*8c0984e5SSebastian Reichel return ret; 1332*8c0984e5SSebastian Reichel } 1333*8c0984e5SSebastian Reichel } else { 1334*8c0984e5SSebastian Reichel /* Power off charging LED indicator */ 1335*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1336*8c0984e5SSebastian Reichel AB8500_LED_INDICATOR_PWM_CTRL, 1337*8c0984e5SSebastian Reichel LED_INDICATOR_PWM_DIS); 1338*8c0984e5SSebastian Reichel if (ret) { 1339*8c0984e5SSebastian Reichel dev_err(di->dev, "Power-off LED failed\n"); 1340*8c0984e5SSebastian Reichel return ret; 1341*8c0984e5SSebastian Reichel } 1342*8c0984e5SSebastian Reichel } 1343*8c0984e5SSebastian Reichel 1344*8c0984e5SSebastian Reichel return ret; 1345*8c0984e5SSebastian Reichel } 1346*8c0984e5SSebastian Reichel 1347*8c0984e5SSebastian Reichel /** 1348*8c0984e5SSebastian Reichel * ab8500_charger_ac_en() - enable or disable ac charging 1349*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1350*8c0984e5SSebastian Reichel * @enable: enable/disable flag 1351*8c0984e5SSebastian Reichel * @vset: charging voltage 1352*8c0984e5SSebastian Reichel * @iset: charging current 1353*8c0984e5SSebastian Reichel * 1354*8c0984e5SSebastian Reichel * Enable/Disable AC/Mains charging and turns on/off the charging led 1355*8c0984e5SSebastian Reichel * respectively. 1356*8c0984e5SSebastian Reichel **/ 1357*8c0984e5SSebastian Reichel static int ab8500_charger_ac_en(struct ux500_charger *charger, 1358*8c0984e5SSebastian Reichel int enable, int vset, int iset) 1359*8c0984e5SSebastian Reichel { 1360*8c0984e5SSebastian Reichel int ret; 1361*8c0984e5SSebastian Reichel int volt_index; 1362*8c0984e5SSebastian Reichel int curr_index; 1363*8c0984e5SSebastian Reichel int input_curr_index; 1364*8c0984e5SSebastian Reichel u8 overshoot = 0; 1365*8c0984e5SSebastian Reichel 1366*8c0984e5SSebastian Reichel struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); 1367*8c0984e5SSebastian Reichel 1368*8c0984e5SSebastian Reichel if (enable) { 1369*8c0984e5SSebastian Reichel /* Check if AC is connected */ 1370*8c0984e5SSebastian Reichel if (!di->ac.charger_connected) { 1371*8c0984e5SSebastian Reichel dev_err(di->dev, "AC charger not connected\n"); 1372*8c0984e5SSebastian Reichel return -ENXIO; 1373*8c0984e5SSebastian Reichel } 1374*8c0984e5SSebastian Reichel 1375*8c0984e5SSebastian Reichel /* Enable AC charging */ 1376*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Enable AC: %dmV %dmA\n", vset, iset); 1377*8c0984e5SSebastian Reichel 1378*8c0984e5SSebastian Reichel /* 1379*8c0984e5SSebastian Reichel * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts 1380*8c0984e5SSebastian Reichel * will be triggered everytime we enable the VDD ADC supply. 1381*8c0984e5SSebastian Reichel * This will turn off charging for a short while. 1382*8c0984e5SSebastian Reichel * It can be avoided by having the supply on when 1383*8c0984e5SSebastian Reichel * there is a charger enabled. Normally the VDD ADC supply 1384*8c0984e5SSebastian Reichel * is enabled everytime a GPADC conversion is triggered. We will 1385*8c0984e5SSebastian Reichel * force it to be enabled from this driver to have 1386*8c0984e5SSebastian Reichel * the GPADC module independant of the AB8500 chargers 1387*8c0984e5SSebastian Reichel */ 1388*8c0984e5SSebastian Reichel if (!di->vddadc_en_ac) { 1389*8c0984e5SSebastian Reichel ret = regulator_enable(di->regu); 1390*8c0984e5SSebastian Reichel if (ret) 1391*8c0984e5SSebastian Reichel dev_warn(di->dev, 1392*8c0984e5SSebastian Reichel "Failed to enable regulator\n"); 1393*8c0984e5SSebastian Reichel else 1394*8c0984e5SSebastian Reichel di->vddadc_en_ac = true; 1395*8c0984e5SSebastian Reichel } 1396*8c0984e5SSebastian Reichel 1397*8c0984e5SSebastian Reichel /* Check if the requested voltage or current is valid */ 1398*8c0984e5SSebastian Reichel volt_index = ab8500_voltage_to_regval(vset); 1399*8c0984e5SSebastian Reichel curr_index = ab8500_current_to_regval(di, iset); 1400*8c0984e5SSebastian Reichel input_curr_index = ab8500_current_to_regval(di, 1401*8c0984e5SSebastian Reichel di->bm->chg_params->ac_curr_max); 1402*8c0984e5SSebastian Reichel if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { 1403*8c0984e5SSebastian Reichel dev_err(di->dev, 1404*8c0984e5SSebastian Reichel "Charger voltage or current too high, " 1405*8c0984e5SSebastian Reichel "charging not started\n"); 1406*8c0984e5SSebastian Reichel return -ENXIO; 1407*8c0984e5SSebastian Reichel } 1408*8c0984e5SSebastian Reichel 1409*8c0984e5SSebastian Reichel /* ChVoltLevel: maximum battery charging voltage */ 1410*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1411*8c0984e5SSebastian Reichel AB8500_CH_VOLT_LVL_REG, (u8) volt_index); 1412*8c0984e5SSebastian Reichel if (ret) { 1413*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1414*8c0984e5SSebastian Reichel return ret; 1415*8c0984e5SSebastian Reichel } 1416*8c0984e5SSebastian Reichel /* MainChInputCurr: current that can be drawn from the charger*/ 1417*8c0984e5SSebastian Reichel ret = ab8500_charger_set_main_in_curr(di, 1418*8c0984e5SSebastian Reichel di->bm->chg_params->ac_curr_max); 1419*8c0984e5SSebastian Reichel if (ret) { 1420*8c0984e5SSebastian Reichel dev_err(di->dev, "%s Failed to set MainChInputCurr\n", 1421*8c0984e5SSebastian Reichel __func__); 1422*8c0984e5SSebastian Reichel return ret; 1423*8c0984e5SSebastian Reichel } 1424*8c0984e5SSebastian Reichel /* ChOutputCurentLevel: protected output current */ 1425*8c0984e5SSebastian Reichel ret = ab8500_charger_set_output_curr(di, iset); 1426*8c0984e5SSebastian Reichel if (ret) { 1427*8c0984e5SSebastian Reichel dev_err(di->dev, "%s " 1428*8c0984e5SSebastian Reichel "Failed to set ChOutputCurentLevel\n", 1429*8c0984e5SSebastian Reichel __func__); 1430*8c0984e5SSebastian Reichel return ret; 1431*8c0984e5SSebastian Reichel } 1432*8c0984e5SSebastian Reichel 1433*8c0984e5SSebastian Reichel /* Check if VBAT overshoot control should be enabled */ 1434*8c0984e5SSebastian Reichel if (!di->bm->enable_overshoot) 1435*8c0984e5SSebastian Reichel overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N; 1436*8c0984e5SSebastian Reichel 1437*8c0984e5SSebastian Reichel /* Enable Main Charger */ 1438*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1439*8c0984e5SSebastian Reichel AB8500_MCH_CTRL1, MAIN_CH_ENA | overshoot); 1440*8c0984e5SSebastian Reichel if (ret) { 1441*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1442*8c0984e5SSebastian Reichel return ret; 1443*8c0984e5SSebastian Reichel } 1444*8c0984e5SSebastian Reichel 1445*8c0984e5SSebastian Reichel /* Power on charging LED indication */ 1446*8c0984e5SSebastian Reichel ret = ab8500_charger_led_en(di, true); 1447*8c0984e5SSebastian Reichel if (ret < 0) 1448*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to enable LED\n"); 1449*8c0984e5SSebastian Reichel 1450*8c0984e5SSebastian Reichel di->ac.charger_online = 1; 1451*8c0984e5SSebastian Reichel } else { 1452*8c0984e5SSebastian Reichel /* Disable AC charging */ 1453*8c0984e5SSebastian Reichel if (is_ab8500_1p1_or_earlier(di->parent)) { 1454*8c0984e5SSebastian Reichel /* 1455*8c0984e5SSebastian Reichel * For ABB revision 1.0 and 1.1 there is a bug in the 1456*8c0984e5SSebastian Reichel * watchdog logic. That means we have to continously 1457*8c0984e5SSebastian Reichel * kick the charger watchdog even when no charger is 1458*8c0984e5SSebastian Reichel * connected. This is only valid once the AC charger 1459*8c0984e5SSebastian Reichel * has been enabled. This is a bug that is not handled 1460*8c0984e5SSebastian Reichel * by the algorithm and the watchdog have to be kicked 1461*8c0984e5SSebastian Reichel * by the charger driver when the AC charger 1462*8c0984e5SSebastian Reichel * is disabled 1463*8c0984e5SSebastian Reichel */ 1464*8c0984e5SSebastian Reichel if (di->ac_conn) { 1465*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 1466*8c0984e5SSebastian Reichel &di->kick_wd_work, 1467*8c0984e5SSebastian Reichel round_jiffies(WD_KICK_INTERVAL)); 1468*8c0984e5SSebastian Reichel } 1469*8c0984e5SSebastian Reichel 1470*8c0984e5SSebastian Reichel /* 1471*8c0984e5SSebastian Reichel * We can't turn off charging completely 1472*8c0984e5SSebastian Reichel * due to a bug in AB8500 cut1. 1473*8c0984e5SSebastian Reichel * If we do, charging will not start again. 1474*8c0984e5SSebastian Reichel * That is why we set the lowest voltage 1475*8c0984e5SSebastian Reichel * and current possible 1476*8c0984e5SSebastian Reichel */ 1477*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 1478*8c0984e5SSebastian Reichel AB8500_CHARGER, 1479*8c0984e5SSebastian Reichel AB8500_CH_VOLT_LVL_REG, CH_VOL_LVL_3P5); 1480*8c0984e5SSebastian Reichel if (ret) { 1481*8c0984e5SSebastian Reichel dev_err(di->dev, 1482*8c0984e5SSebastian Reichel "%s write failed\n", __func__); 1483*8c0984e5SSebastian Reichel return ret; 1484*8c0984e5SSebastian Reichel } 1485*8c0984e5SSebastian Reichel 1486*8c0984e5SSebastian Reichel ret = ab8500_charger_set_output_curr(di, 0); 1487*8c0984e5SSebastian Reichel if (ret) { 1488*8c0984e5SSebastian Reichel dev_err(di->dev, "%s " 1489*8c0984e5SSebastian Reichel "Failed to set ChOutputCurentLevel\n", 1490*8c0984e5SSebastian Reichel __func__); 1491*8c0984e5SSebastian Reichel return ret; 1492*8c0984e5SSebastian Reichel } 1493*8c0984e5SSebastian Reichel } else { 1494*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 1495*8c0984e5SSebastian Reichel AB8500_CHARGER, 1496*8c0984e5SSebastian Reichel AB8500_MCH_CTRL1, 0); 1497*8c0984e5SSebastian Reichel if (ret) { 1498*8c0984e5SSebastian Reichel dev_err(di->dev, 1499*8c0984e5SSebastian Reichel "%s write failed\n", __func__); 1500*8c0984e5SSebastian Reichel return ret; 1501*8c0984e5SSebastian Reichel } 1502*8c0984e5SSebastian Reichel } 1503*8c0984e5SSebastian Reichel 1504*8c0984e5SSebastian Reichel ret = ab8500_charger_led_en(di, false); 1505*8c0984e5SSebastian Reichel if (ret < 0) 1506*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to disable LED\n"); 1507*8c0984e5SSebastian Reichel 1508*8c0984e5SSebastian Reichel di->ac.charger_online = 0; 1509*8c0984e5SSebastian Reichel di->ac.wd_expired = false; 1510*8c0984e5SSebastian Reichel 1511*8c0984e5SSebastian Reichel /* Disable regulator if enabled */ 1512*8c0984e5SSebastian Reichel if (di->vddadc_en_ac) { 1513*8c0984e5SSebastian Reichel regulator_disable(di->regu); 1514*8c0984e5SSebastian Reichel di->vddadc_en_ac = false; 1515*8c0984e5SSebastian Reichel } 1516*8c0984e5SSebastian Reichel 1517*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s Disabled AC charging\n", __func__); 1518*8c0984e5SSebastian Reichel } 1519*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->ac_chg.psy); 1520*8c0984e5SSebastian Reichel 1521*8c0984e5SSebastian Reichel return ret; 1522*8c0984e5SSebastian Reichel } 1523*8c0984e5SSebastian Reichel 1524*8c0984e5SSebastian Reichel /** 1525*8c0984e5SSebastian Reichel * ab8500_charger_usb_en() - enable usb charging 1526*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1527*8c0984e5SSebastian Reichel * @enable: enable/disable flag 1528*8c0984e5SSebastian Reichel * @vset: charging voltage 1529*8c0984e5SSebastian Reichel * @ich_out: charger output current 1530*8c0984e5SSebastian Reichel * 1531*8c0984e5SSebastian Reichel * Enable/Disable USB charging and turns on/off the charging led respectively. 1532*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1533*8c0984e5SSebastian Reichel */ 1534*8c0984e5SSebastian Reichel static int ab8500_charger_usb_en(struct ux500_charger *charger, 1535*8c0984e5SSebastian Reichel int enable, int vset, int ich_out) 1536*8c0984e5SSebastian Reichel { 1537*8c0984e5SSebastian Reichel int ret; 1538*8c0984e5SSebastian Reichel int volt_index; 1539*8c0984e5SSebastian Reichel int curr_index; 1540*8c0984e5SSebastian Reichel u8 overshoot = 0; 1541*8c0984e5SSebastian Reichel 1542*8c0984e5SSebastian Reichel struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); 1543*8c0984e5SSebastian Reichel 1544*8c0984e5SSebastian Reichel if (enable) { 1545*8c0984e5SSebastian Reichel /* Check if USB is connected */ 1546*8c0984e5SSebastian Reichel if (!di->usb.charger_connected) { 1547*8c0984e5SSebastian Reichel dev_err(di->dev, "USB charger not connected\n"); 1548*8c0984e5SSebastian Reichel return -ENXIO; 1549*8c0984e5SSebastian Reichel } 1550*8c0984e5SSebastian Reichel 1551*8c0984e5SSebastian Reichel /* 1552*8c0984e5SSebastian Reichel * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts 1553*8c0984e5SSebastian Reichel * will be triggered everytime we enable the VDD ADC supply. 1554*8c0984e5SSebastian Reichel * This will turn off charging for a short while. 1555*8c0984e5SSebastian Reichel * It can be avoided by having the supply on when 1556*8c0984e5SSebastian Reichel * there is a charger enabled. Normally the VDD ADC supply 1557*8c0984e5SSebastian Reichel * is enabled everytime a GPADC conversion is triggered. We will 1558*8c0984e5SSebastian Reichel * force it to be enabled from this driver to have 1559*8c0984e5SSebastian Reichel * the GPADC module independant of the AB8500 chargers 1560*8c0984e5SSebastian Reichel */ 1561*8c0984e5SSebastian Reichel if (!di->vddadc_en_usb) { 1562*8c0984e5SSebastian Reichel ret = regulator_enable(di->regu); 1563*8c0984e5SSebastian Reichel if (ret) 1564*8c0984e5SSebastian Reichel dev_warn(di->dev, 1565*8c0984e5SSebastian Reichel "Failed to enable regulator\n"); 1566*8c0984e5SSebastian Reichel else 1567*8c0984e5SSebastian Reichel di->vddadc_en_usb = true; 1568*8c0984e5SSebastian Reichel } 1569*8c0984e5SSebastian Reichel 1570*8c0984e5SSebastian Reichel /* Enable USB charging */ 1571*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Enable USB: %dmV %dmA\n", vset, ich_out); 1572*8c0984e5SSebastian Reichel 1573*8c0984e5SSebastian Reichel /* Check if the requested voltage or current is valid */ 1574*8c0984e5SSebastian Reichel volt_index = ab8500_voltage_to_regval(vset); 1575*8c0984e5SSebastian Reichel curr_index = ab8500_current_to_regval(di, ich_out); 1576*8c0984e5SSebastian Reichel if (volt_index < 0 || curr_index < 0) { 1577*8c0984e5SSebastian Reichel dev_err(di->dev, 1578*8c0984e5SSebastian Reichel "Charger voltage or current too high, " 1579*8c0984e5SSebastian Reichel "charging not started\n"); 1580*8c0984e5SSebastian Reichel return -ENXIO; 1581*8c0984e5SSebastian Reichel } 1582*8c0984e5SSebastian Reichel 1583*8c0984e5SSebastian Reichel /* ChVoltLevel: max voltage upto which battery can be charged */ 1584*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1585*8c0984e5SSebastian Reichel AB8500_CH_VOLT_LVL_REG, (u8) volt_index); 1586*8c0984e5SSebastian Reichel if (ret) { 1587*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1588*8c0984e5SSebastian Reichel return ret; 1589*8c0984e5SSebastian Reichel } 1590*8c0984e5SSebastian Reichel /* Check if VBAT overshoot control should be enabled */ 1591*8c0984e5SSebastian Reichel if (!di->bm->enable_overshoot) 1592*8c0984e5SSebastian Reichel overshoot = USB_CHG_NO_OVERSHOOT_ENA_N; 1593*8c0984e5SSebastian Reichel 1594*8c0984e5SSebastian Reichel /* Enable USB Charger */ 1595*8c0984e5SSebastian Reichel dev_dbg(di->dev, 1596*8c0984e5SSebastian Reichel "Enabling USB with write to AB8500_USBCH_CTRL1_REG\n"); 1597*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1598*8c0984e5SSebastian Reichel AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot); 1599*8c0984e5SSebastian Reichel if (ret) { 1600*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1601*8c0984e5SSebastian Reichel return ret; 1602*8c0984e5SSebastian Reichel } 1603*8c0984e5SSebastian Reichel 1604*8c0984e5SSebastian Reichel /* If success power on charging LED indication */ 1605*8c0984e5SSebastian Reichel ret = ab8500_charger_led_en(di, true); 1606*8c0984e5SSebastian Reichel if (ret < 0) 1607*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to enable LED\n"); 1608*8c0984e5SSebastian Reichel 1609*8c0984e5SSebastian Reichel di->usb.charger_online = 1; 1610*8c0984e5SSebastian Reichel 1611*8c0984e5SSebastian Reichel /* USBChInputCurr: current that can be drawn from the usb */ 1612*8c0984e5SSebastian Reichel ret = ab8500_charger_set_vbus_in_curr(di, 1613*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 1614*8c0984e5SSebastian Reichel if (ret) { 1615*8c0984e5SSebastian Reichel dev_err(di->dev, "setting USBChInputCurr failed\n"); 1616*8c0984e5SSebastian Reichel return ret; 1617*8c0984e5SSebastian Reichel } 1618*8c0984e5SSebastian Reichel 1619*8c0984e5SSebastian Reichel /* ChOutputCurentLevel: protected output current */ 1620*8c0984e5SSebastian Reichel ret = ab8500_charger_set_output_curr(di, ich_out); 1621*8c0984e5SSebastian Reichel if (ret) { 1622*8c0984e5SSebastian Reichel dev_err(di->dev, "%s " 1623*8c0984e5SSebastian Reichel "Failed to set ChOutputCurentLevel\n", 1624*8c0984e5SSebastian Reichel __func__); 1625*8c0984e5SSebastian Reichel return ret; 1626*8c0984e5SSebastian Reichel } 1627*8c0984e5SSebastian Reichel 1628*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ); 1629*8c0984e5SSebastian Reichel 1630*8c0984e5SSebastian Reichel } else { 1631*8c0984e5SSebastian Reichel /* Disable USB charging */ 1632*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); 1633*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 1634*8c0984e5SSebastian Reichel AB8500_CHARGER, 1635*8c0984e5SSebastian Reichel AB8500_USBCH_CTRL1_REG, 0); 1636*8c0984e5SSebastian Reichel if (ret) { 1637*8c0984e5SSebastian Reichel dev_err(di->dev, 1638*8c0984e5SSebastian Reichel "%s write failed\n", __func__); 1639*8c0984e5SSebastian Reichel return ret; 1640*8c0984e5SSebastian Reichel } 1641*8c0984e5SSebastian Reichel 1642*8c0984e5SSebastian Reichel ret = ab8500_charger_led_en(di, false); 1643*8c0984e5SSebastian Reichel if (ret < 0) 1644*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to disable LED\n"); 1645*8c0984e5SSebastian Reichel /* USBChInputCurr: current that can be drawn from the usb */ 1646*8c0984e5SSebastian Reichel ret = ab8500_charger_set_vbus_in_curr(di, 0); 1647*8c0984e5SSebastian Reichel if (ret) { 1648*8c0984e5SSebastian Reichel dev_err(di->dev, "setting USBChInputCurr failed\n"); 1649*8c0984e5SSebastian Reichel return ret; 1650*8c0984e5SSebastian Reichel } 1651*8c0984e5SSebastian Reichel 1652*8c0984e5SSebastian Reichel /* ChOutputCurentLevel: protected output current */ 1653*8c0984e5SSebastian Reichel ret = ab8500_charger_set_output_curr(di, 0); 1654*8c0984e5SSebastian Reichel if (ret) { 1655*8c0984e5SSebastian Reichel dev_err(di->dev, "%s " 1656*8c0984e5SSebastian Reichel "Failed to reset ChOutputCurentLevel\n", 1657*8c0984e5SSebastian Reichel __func__); 1658*8c0984e5SSebastian Reichel return ret; 1659*8c0984e5SSebastian Reichel } 1660*8c0984e5SSebastian Reichel di->usb.charger_online = 0; 1661*8c0984e5SSebastian Reichel di->usb.wd_expired = false; 1662*8c0984e5SSebastian Reichel 1663*8c0984e5SSebastian Reichel /* Disable regulator if enabled */ 1664*8c0984e5SSebastian Reichel if (di->vddadc_en_usb) { 1665*8c0984e5SSebastian Reichel regulator_disable(di->regu); 1666*8c0984e5SSebastian Reichel di->vddadc_en_usb = false; 1667*8c0984e5SSebastian Reichel } 1668*8c0984e5SSebastian Reichel 1669*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); 1670*8c0984e5SSebastian Reichel 1671*8c0984e5SSebastian Reichel /* Cancel any pending Vbat check work */ 1672*8c0984e5SSebastian Reichel cancel_delayed_work(&di->check_vbat_work); 1673*8c0984e5SSebastian Reichel 1674*8c0984e5SSebastian Reichel } 1675*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 1676*8c0984e5SSebastian Reichel 1677*8c0984e5SSebastian Reichel return ret; 1678*8c0984e5SSebastian Reichel } 1679*8c0984e5SSebastian Reichel 1680*8c0984e5SSebastian Reichel static int ab8500_external_charger_prepare(struct notifier_block *charger_nb, 1681*8c0984e5SSebastian Reichel unsigned long event, void *data) 1682*8c0984e5SSebastian Reichel { 1683*8c0984e5SSebastian Reichel int ret; 1684*8c0984e5SSebastian Reichel struct device *dev = data; 1685*8c0984e5SSebastian Reichel /*Toggle External charger control pin*/ 1686*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, 1687*8c0984e5SSebastian Reichel AB8500_SYS_CHARGER_CONTROL_REG, 1688*8c0984e5SSebastian Reichel EXTERNAL_CHARGER_DISABLE_REG_VAL); 1689*8c0984e5SSebastian Reichel if (ret < 0) { 1690*8c0984e5SSebastian Reichel dev_err(dev, "write reg failed %d\n", ret); 1691*8c0984e5SSebastian Reichel goto out; 1692*8c0984e5SSebastian Reichel } 1693*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, 1694*8c0984e5SSebastian Reichel AB8500_SYS_CHARGER_CONTROL_REG, 1695*8c0984e5SSebastian Reichel EXTERNAL_CHARGER_ENABLE_REG_VAL); 1696*8c0984e5SSebastian Reichel if (ret < 0) 1697*8c0984e5SSebastian Reichel dev_err(dev, "Write reg failed %d\n", ret); 1698*8c0984e5SSebastian Reichel 1699*8c0984e5SSebastian Reichel out: 1700*8c0984e5SSebastian Reichel return ret; 1701*8c0984e5SSebastian Reichel } 1702*8c0984e5SSebastian Reichel 1703*8c0984e5SSebastian Reichel /** 1704*8c0984e5SSebastian Reichel * ab8500_charger_usb_check_enable() - enable usb charging 1705*8c0984e5SSebastian Reichel * @charger: pointer to the ux500_charger structure 1706*8c0984e5SSebastian Reichel * @vset: charging voltage 1707*8c0984e5SSebastian Reichel * @iset: charger output current 1708*8c0984e5SSebastian Reichel * 1709*8c0984e5SSebastian Reichel * Check if the VBUS charger has been disconnected and reconnected without 1710*8c0984e5SSebastian Reichel * AB8500 rising an interrupt. Returns 0 on success. 1711*8c0984e5SSebastian Reichel */ 1712*8c0984e5SSebastian Reichel static int ab8500_charger_usb_check_enable(struct ux500_charger *charger, 1713*8c0984e5SSebastian Reichel int vset, int iset) 1714*8c0984e5SSebastian Reichel { 1715*8c0984e5SSebastian Reichel u8 usbch_ctrl1 = 0; 1716*8c0984e5SSebastian Reichel int ret = 0; 1717*8c0984e5SSebastian Reichel 1718*8c0984e5SSebastian Reichel struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); 1719*8c0984e5SSebastian Reichel 1720*8c0984e5SSebastian Reichel if (!di->usb.charger_connected) 1721*8c0984e5SSebastian Reichel return ret; 1722*8c0984e5SSebastian Reichel 1723*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 1724*8c0984e5SSebastian Reichel AB8500_USBCH_CTRL1_REG, &usbch_ctrl1); 1725*8c0984e5SSebastian Reichel if (ret < 0) { 1726*8c0984e5SSebastian Reichel dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 1727*8c0984e5SSebastian Reichel return ret; 1728*8c0984e5SSebastian Reichel } 1729*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1); 1730*8c0984e5SSebastian Reichel 1731*8c0984e5SSebastian Reichel if (!(usbch_ctrl1 & USB_CH_ENA)) { 1732*8c0984e5SSebastian Reichel dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); 1733*8c0984e5SSebastian Reichel 1734*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 1735*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CHARGER_CTRL, 1736*8c0984e5SSebastian Reichel DROP_COUNT_RESET, DROP_COUNT_RESET); 1737*8c0984e5SSebastian Reichel if (ret < 0) { 1738*8c0984e5SSebastian Reichel dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); 1739*8c0984e5SSebastian Reichel return ret; 1740*8c0984e5SSebastian Reichel } 1741*8c0984e5SSebastian Reichel 1742*8c0984e5SSebastian Reichel ret = ab8500_charger_usb_en(&di->usb_chg, true, vset, iset); 1743*8c0984e5SSebastian Reichel if (ret < 0) { 1744*8c0984e5SSebastian Reichel dev_err(di->dev, "Failed to enable VBUS charger %d\n", 1745*8c0984e5SSebastian Reichel __LINE__); 1746*8c0984e5SSebastian Reichel return ret; 1747*8c0984e5SSebastian Reichel } 1748*8c0984e5SSebastian Reichel } 1749*8c0984e5SSebastian Reichel return ret; 1750*8c0984e5SSebastian Reichel } 1751*8c0984e5SSebastian Reichel 1752*8c0984e5SSebastian Reichel /** 1753*8c0984e5SSebastian Reichel * ab8500_charger_ac_check_enable() - enable usb charging 1754*8c0984e5SSebastian Reichel * @charger: pointer to the ux500_charger structure 1755*8c0984e5SSebastian Reichel * @vset: charging voltage 1756*8c0984e5SSebastian Reichel * @iset: charger output current 1757*8c0984e5SSebastian Reichel * 1758*8c0984e5SSebastian Reichel * Check if the AC charger has been disconnected and reconnected without 1759*8c0984e5SSebastian Reichel * AB8500 rising an interrupt. Returns 0 on success. 1760*8c0984e5SSebastian Reichel */ 1761*8c0984e5SSebastian Reichel static int ab8500_charger_ac_check_enable(struct ux500_charger *charger, 1762*8c0984e5SSebastian Reichel int vset, int iset) 1763*8c0984e5SSebastian Reichel { 1764*8c0984e5SSebastian Reichel u8 mainch_ctrl1 = 0; 1765*8c0984e5SSebastian Reichel int ret = 0; 1766*8c0984e5SSebastian Reichel 1767*8c0984e5SSebastian Reichel struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); 1768*8c0984e5SSebastian Reichel 1769*8c0984e5SSebastian Reichel if (!di->ac.charger_connected) 1770*8c0984e5SSebastian Reichel return ret; 1771*8c0984e5SSebastian Reichel 1772*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 1773*8c0984e5SSebastian Reichel AB8500_MCH_CTRL1, &mainch_ctrl1); 1774*8c0984e5SSebastian Reichel if (ret < 0) { 1775*8c0984e5SSebastian Reichel dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 1776*8c0984e5SSebastian Reichel return ret; 1777*8c0984e5SSebastian Reichel } 1778*8c0984e5SSebastian Reichel dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1); 1779*8c0984e5SSebastian Reichel 1780*8c0984e5SSebastian Reichel if (!(mainch_ctrl1 & MAIN_CH_ENA)) { 1781*8c0984e5SSebastian Reichel dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); 1782*8c0984e5SSebastian Reichel 1783*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 1784*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CHARGER_CTRL, 1785*8c0984e5SSebastian Reichel DROP_COUNT_RESET, DROP_COUNT_RESET); 1786*8c0984e5SSebastian Reichel 1787*8c0984e5SSebastian Reichel if (ret < 0) { 1788*8c0984e5SSebastian Reichel dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); 1789*8c0984e5SSebastian Reichel return ret; 1790*8c0984e5SSebastian Reichel } 1791*8c0984e5SSebastian Reichel 1792*8c0984e5SSebastian Reichel ret = ab8500_charger_ac_en(&di->usb_chg, true, vset, iset); 1793*8c0984e5SSebastian Reichel if (ret < 0) { 1794*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to enable AC charger %d\n", 1795*8c0984e5SSebastian Reichel __LINE__); 1796*8c0984e5SSebastian Reichel return ret; 1797*8c0984e5SSebastian Reichel } 1798*8c0984e5SSebastian Reichel } 1799*8c0984e5SSebastian Reichel return ret; 1800*8c0984e5SSebastian Reichel } 1801*8c0984e5SSebastian Reichel 1802*8c0984e5SSebastian Reichel /** 1803*8c0984e5SSebastian Reichel * ab8500_charger_watchdog_kick() - kick charger watchdog 1804*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1805*8c0984e5SSebastian Reichel * 1806*8c0984e5SSebastian Reichel * Kick charger watchdog 1807*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1808*8c0984e5SSebastian Reichel */ 1809*8c0984e5SSebastian Reichel static int ab8500_charger_watchdog_kick(struct ux500_charger *charger) 1810*8c0984e5SSebastian Reichel { 1811*8c0984e5SSebastian Reichel int ret; 1812*8c0984e5SSebastian Reichel struct ab8500_charger *di; 1813*8c0984e5SSebastian Reichel 1814*8c0984e5SSebastian Reichel if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS) 1815*8c0984e5SSebastian Reichel di = to_ab8500_charger_ac_device_info(charger); 1816*8c0984e5SSebastian Reichel else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB) 1817*8c0984e5SSebastian Reichel di = to_ab8500_charger_usb_device_info(charger); 1818*8c0984e5SSebastian Reichel else 1819*8c0984e5SSebastian Reichel return -ENXIO; 1820*8c0984e5SSebastian Reichel 1821*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1822*8c0984e5SSebastian Reichel AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 1823*8c0984e5SSebastian Reichel if (ret) 1824*8c0984e5SSebastian Reichel dev_err(di->dev, "Failed to kick WD!\n"); 1825*8c0984e5SSebastian Reichel 1826*8c0984e5SSebastian Reichel return ret; 1827*8c0984e5SSebastian Reichel } 1828*8c0984e5SSebastian Reichel 1829*8c0984e5SSebastian Reichel /** 1830*8c0984e5SSebastian Reichel * ab8500_charger_update_charger_current() - update charger current 1831*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 1832*8c0984e5SSebastian Reichel * 1833*8c0984e5SSebastian Reichel * Update the charger output current for the specified charger 1834*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1835*8c0984e5SSebastian Reichel */ 1836*8c0984e5SSebastian Reichel static int ab8500_charger_update_charger_current(struct ux500_charger *charger, 1837*8c0984e5SSebastian Reichel int ich_out) 1838*8c0984e5SSebastian Reichel { 1839*8c0984e5SSebastian Reichel int ret; 1840*8c0984e5SSebastian Reichel struct ab8500_charger *di; 1841*8c0984e5SSebastian Reichel 1842*8c0984e5SSebastian Reichel if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS) 1843*8c0984e5SSebastian Reichel di = to_ab8500_charger_ac_device_info(charger); 1844*8c0984e5SSebastian Reichel else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB) 1845*8c0984e5SSebastian Reichel di = to_ab8500_charger_usb_device_info(charger); 1846*8c0984e5SSebastian Reichel else 1847*8c0984e5SSebastian Reichel return -ENXIO; 1848*8c0984e5SSebastian Reichel 1849*8c0984e5SSebastian Reichel ret = ab8500_charger_set_output_curr(di, ich_out); 1850*8c0984e5SSebastian Reichel if (ret) { 1851*8c0984e5SSebastian Reichel dev_err(di->dev, "%s " 1852*8c0984e5SSebastian Reichel "Failed to set ChOutputCurentLevel\n", 1853*8c0984e5SSebastian Reichel __func__); 1854*8c0984e5SSebastian Reichel return ret; 1855*8c0984e5SSebastian Reichel } 1856*8c0984e5SSebastian Reichel 1857*8c0984e5SSebastian Reichel /* Reset the main and usb drop input current measurement counter */ 1858*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 1859*8c0984e5SSebastian Reichel AB8500_CHARGER_CTRL, DROP_COUNT_RESET); 1860*8c0984e5SSebastian Reichel if (ret) { 1861*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1862*8c0984e5SSebastian Reichel return ret; 1863*8c0984e5SSebastian Reichel } 1864*8c0984e5SSebastian Reichel 1865*8c0984e5SSebastian Reichel return ret; 1866*8c0984e5SSebastian Reichel } 1867*8c0984e5SSebastian Reichel 1868*8c0984e5SSebastian Reichel /** 1869*8c0984e5SSebastian Reichel * ab8540_charger_power_path_enable() - enable usb power path mode 1870*8c0984e5SSebastian Reichel * @charger: pointer to the ux500_charger structure 1871*8c0984e5SSebastian Reichel * @enable: enable/disable flag 1872*8c0984e5SSebastian Reichel * 1873*8c0984e5SSebastian Reichel * Enable or disable the power path for usb mode 1874*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1875*8c0984e5SSebastian Reichel */ 1876*8c0984e5SSebastian Reichel static int ab8540_charger_power_path_enable(struct ux500_charger *charger, 1877*8c0984e5SSebastian Reichel bool enable) 1878*8c0984e5SSebastian Reichel { 1879*8c0984e5SSebastian Reichel int ret; 1880*8c0984e5SSebastian Reichel struct ab8500_charger *di; 1881*8c0984e5SSebastian Reichel 1882*8c0984e5SSebastian Reichel if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB) 1883*8c0984e5SSebastian Reichel di = to_ab8500_charger_usb_device_info(charger); 1884*8c0984e5SSebastian Reichel else 1885*8c0984e5SSebastian Reichel return -ENXIO; 1886*8c0984e5SSebastian Reichel 1887*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 1888*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8540_USB_PP_MODE_REG, 1889*8c0984e5SSebastian Reichel BUS_POWER_PATH_MODE_ENA, enable); 1890*8c0984e5SSebastian Reichel if (ret) { 1891*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1892*8c0984e5SSebastian Reichel return ret; 1893*8c0984e5SSebastian Reichel } 1894*8c0984e5SSebastian Reichel 1895*8c0984e5SSebastian Reichel return ret; 1896*8c0984e5SSebastian Reichel } 1897*8c0984e5SSebastian Reichel 1898*8c0984e5SSebastian Reichel 1899*8c0984e5SSebastian Reichel /** 1900*8c0984e5SSebastian Reichel * ab8540_charger_usb_pre_chg_enable() - enable usb pre change 1901*8c0984e5SSebastian Reichel * @charger: pointer to the ux500_charger structure 1902*8c0984e5SSebastian Reichel * @enable: enable/disable flag 1903*8c0984e5SSebastian Reichel * 1904*8c0984e5SSebastian Reichel * Enable or disable the pre-chage for usb mode 1905*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 1906*8c0984e5SSebastian Reichel */ 1907*8c0984e5SSebastian Reichel static int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger, 1908*8c0984e5SSebastian Reichel bool enable) 1909*8c0984e5SSebastian Reichel { 1910*8c0984e5SSebastian Reichel int ret; 1911*8c0984e5SSebastian Reichel struct ab8500_charger *di; 1912*8c0984e5SSebastian Reichel 1913*8c0984e5SSebastian Reichel if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB) 1914*8c0984e5SSebastian Reichel di = to_ab8500_charger_usb_device_info(charger); 1915*8c0984e5SSebastian Reichel else 1916*8c0984e5SSebastian Reichel return -ENXIO; 1917*8c0984e5SSebastian Reichel 1918*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 1919*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8540_USB_PP_CHR_REG, 1920*8c0984e5SSebastian Reichel BUS_POWER_PATH_PRECHG_ENA, enable); 1921*8c0984e5SSebastian Reichel if (ret) { 1922*8c0984e5SSebastian Reichel dev_err(di->dev, "%s write failed\n", __func__); 1923*8c0984e5SSebastian Reichel return ret; 1924*8c0984e5SSebastian Reichel } 1925*8c0984e5SSebastian Reichel 1926*8c0984e5SSebastian Reichel return ret; 1927*8c0984e5SSebastian Reichel } 1928*8c0984e5SSebastian Reichel 1929*8c0984e5SSebastian Reichel static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data) 1930*8c0984e5SSebastian Reichel { 1931*8c0984e5SSebastian Reichel struct power_supply *psy; 1932*8c0984e5SSebastian Reichel struct power_supply *ext = dev_get_drvdata(dev); 1933*8c0984e5SSebastian Reichel const char **supplicants = (const char **)ext->supplied_to; 1934*8c0984e5SSebastian Reichel struct ab8500_charger *di; 1935*8c0984e5SSebastian Reichel union power_supply_propval ret; 1936*8c0984e5SSebastian Reichel int j; 1937*8c0984e5SSebastian Reichel struct ux500_charger *usb_chg; 1938*8c0984e5SSebastian Reichel 1939*8c0984e5SSebastian Reichel usb_chg = (struct ux500_charger *)data; 1940*8c0984e5SSebastian Reichel psy = usb_chg->psy; 1941*8c0984e5SSebastian Reichel 1942*8c0984e5SSebastian Reichel di = to_ab8500_charger_usb_device_info(usb_chg); 1943*8c0984e5SSebastian Reichel 1944*8c0984e5SSebastian Reichel /* For all psy where the driver name appears in any supplied_to */ 1945*8c0984e5SSebastian Reichel j = match_string(supplicants, ext->num_supplicants, psy->desc->name); 1946*8c0984e5SSebastian Reichel if (j < 0) 1947*8c0984e5SSebastian Reichel return 0; 1948*8c0984e5SSebastian Reichel 1949*8c0984e5SSebastian Reichel /* Go through all properties for the psy */ 1950*8c0984e5SSebastian Reichel for (j = 0; j < ext->desc->num_properties; j++) { 1951*8c0984e5SSebastian Reichel enum power_supply_property prop; 1952*8c0984e5SSebastian Reichel prop = ext->desc->properties[j]; 1953*8c0984e5SSebastian Reichel 1954*8c0984e5SSebastian Reichel if (power_supply_get_property(ext, prop, &ret)) 1955*8c0984e5SSebastian Reichel continue; 1956*8c0984e5SSebastian Reichel 1957*8c0984e5SSebastian Reichel switch (prop) { 1958*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_NOW: 1959*8c0984e5SSebastian Reichel switch (ext->desc->type) { 1960*8c0984e5SSebastian Reichel case POWER_SUPPLY_TYPE_BATTERY: 1961*8c0984e5SSebastian Reichel di->vbat = ret.intval / 1000; 1962*8c0984e5SSebastian Reichel break; 1963*8c0984e5SSebastian Reichel default: 1964*8c0984e5SSebastian Reichel break; 1965*8c0984e5SSebastian Reichel } 1966*8c0984e5SSebastian Reichel break; 1967*8c0984e5SSebastian Reichel default: 1968*8c0984e5SSebastian Reichel break; 1969*8c0984e5SSebastian Reichel } 1970*8c0984e5SSebastian Reichel } 1971*8c0984e5SSebastian Reichel return 0; 1972*8c0984e5SSebastian Reichel } 1973*8c0984e5SSebastian Reichel 1974*8c0984e5SSebastian Reichel /** 1975*8c0984e5SSebastian Reichel * ab8500_charger_check_vbat_work() - keep vbus current within spec 1976*8c0984e5SSebastian Reichel * @work pointer to the work_struct structure 1977*8c0984e5SSebastian Reichel * 1978*8c0984e5SSebastian Reichel * Due to a asic bug it is necessary to lower the input current to the vbus 1979*8c0984e5SSebastian Reichel * charger when charging with at some specific levels. This issue is only valid 1980*8c0984e5SSebastian Reichel * for below a certain battery voltage. This function makes sure that the 1981*8c0984e5SSebastian Reichel * the allowed current limit isn't exceeded. 1982*8c0984e5SSebastian Reichel */ 1983*8c0984e5SSebastian Reichel static void ab8500_charger_check_vbat_work(struct work_struct *work) 1984*8c0984e5SSebastian Reichel { 1985*8c0984e5SSebastian Reichel int t = 10; 1986*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 1987*8c0984e5SSebastian Reichel struct ab8500_charger, check_vbat_work.work); 1988*8c0984e5SSebastian Reichel 1989*8c0984e5SSebastian Reichel class_for_each_device(power_supply_class, NULL, 1990*8c0984e5SSebastian Reichel di->usb_chg.psy, ab8500_charger_get_ext_psy_data); 1991*8c0984e5SSebastian Reichel 1992*8c0984e5SSebastian Reichel /* First run old_vbat is 0. */ 1993*8c0984e5SSebastian Reichel if (di->old_vbat == 0) 1994*8c0984e5SSebastian Reichel di->old_vbat = di->vbat; 1995*8c0984e5SSebastian Reichel 1996*8c0984e5SSebastian Reichel if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED && 1997*8c0984e5SSebastian Reichel di->vbat <= VBAT_TRESH_IP_CUR_RED) || 1998*8c0984e5SSebastian Reichel (di->old_vbat > VBAT_TRESH_IP_CUR_RED && 1999*8c0984e5SSebastian Reichel di->vbat > VBAT_TRESH_IP_CUR_RED))) { 2000*8c0984e5SSebastian Reichel 2001*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d," 2002*8c0984e5SSebastian Reichel " old: %d\n", di->max_usb_in_curr.usb_type_max, 2003*8c0984e5SSebastian Reichel di->vbat, di->old_vbat); 2004*8c0984e5SSebastian Reichel ab8500_charger_set_vbus_in_curr(di, 2005*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 2006*8c0984e5SSebastian Reichel power_supply_changed(di->usb_chg.psy); 2007*8c0984e5SSebastian Reichel } 2008*8c0984e5SSebastian Reichel 2009*8c0984e5SSebastian Reichel di->old_vbat = di->vbat; 2010*8c0984e5SSebastian Reichel 2011*8c0984e5SSebastian Reichel /* 2012*8c0984e5SSebastian Reichel * No need to check the battery voltage every second when not close to 2013*8c0984e5SSebastian Reichel * the threshold. 2014*8c0984e5SSebastian Reichel */ 2015*8c0984e5SSebastian Reichel if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) && 2016*8c0984e5SSebastian Reichel (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100))) 2017*8c0984e5SSebastian Reichel t = 1; 2018*8c0984e5SSebastian Reichel 2019*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ); 2020*8c0984e5SSebastian Reichel } 2021*8c0984e5SSebastian Reichel 2022*8c0984e5SSebastian Reichel /** 2023*8c0984e5SSebastian Reichel * ab8500_charger_check_hw_failure_work() - check main charger failure 2024*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2025*8c0984e5SSebastian Reichel * 2026*8c0984e5SSebastian Reichel * Work queue function for checking the main charger status 2027*8c0984e5SSebastian Reichel */ 2028*8c0984e5SSebastian Reichel static void ab8500_charger_check_hw_failure_work(struct work_struct *work) 2029*8c0984e5SSebastian Reichel { 2030*8c0984e5SSebastian Reichel int ret; 2031*8c0984e5SSebastian Reichel u8 reg_value; 2032*8c0984e5SSebastian Reichel 2033*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2034*8c0984e5SSebastian Reichel struct ab8500_charger, check_hw_failure_work.work); 2035*8c0984e5SSebastian Reichel 2036*8c0984e5SSebastian Reichel /* Check if the status bits for HW failure is still active */ 2037*8c0984e5SSebastian Reichel if (di->flags.mainextchnotok) { 2038*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2039*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); 2040*8c0984e5SSebastian Reichel if (ret < 0) { 2041*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 2042*8c0984e5SSebastian Reichel return; 2043*8c0984e5SSebastian Reichel } 2044*8c0984e5SSebastian Reichel if (!(reg_value & MAIN_CH_NOK)) { 2045*8c0984e5SSebastian Reichel di->flags.mainextchnotok = false; 2046*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->ac_chg.psy); 2047*8c0984e5SSebastian Reichel } 2048*8c0984e5SSebastian Reichel } 2049*8c0984e5SSebastian Reichel if (di->flags.vbus_ovv) { 2050*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2051*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, 2052*8c0984e5SSebastian Reichel ®_value); 2053*8c0984e5SSebastian Reichel if (ret < 0) { 2054*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 2055*8c0984e5SSebastian Reichel return; 2056*8c0984e5SSebastian Reichel } 2057*8c0984e5SSebastian Reichel if (!(reg_value & VBUS_OVV_TH)) { 2058*8c0984e5SSebastian Reichel di->flags.vbus_ovv = false; 2059*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2060*8c0984e5SSebastian Reichel } 2061*8c0984e5SSebastian Reichel } 2062*8c0984e5SSebastian Reichel /* If we still have a failure, schedule a new check */ 2063*8c0984e5SSebastian Reichel if (di->flags.mainextchnotok || di->flags.vbus_ovv) { 2064*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2065*8c0984e5SSebastian Reichel &di->check_hw_failure_work, round_jiffies(HZ)); 2066*8c0984e5SSebastian Reichel } 2067*8c0984e5SSebastian Reichel } 2068*8c0984e5SSebastian Reichel 2069*8c0984e5SSebastian Reichel /** 2070*8c0984e5SSebastian Reichel * ab8500_charger_kick_watchdog_work() - kick the watchdog 2071*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2072*8c0984e5SSebastian Reichel * 2073*8c0984e5SSebastian Reichel * Work queue function for kicking the charger watchdog. 2074*8c0984e5SSebastian Reichel * 2075*8c0984e5SSebastian Reichel * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 2076*8c0984e5SSebastian Reichel * logic. That means we have to continously kick the charger 2077*8c0984e5SSebastian Reichel * watchdog even when no charger is connected. This is only 2078*8c0984e5SSebastian Reichel * valid once the AC charger has been enabled. This is 2079*8c0984e5SSebastian Reichel * a bug that is not handled by the algorithm and the 2080*8c0984e5SSebastian Reichel * watchdog have to be kicked by the charger driver 2081*8c0984e5SSebastian Reichel * when the AC charger is disabled 2082*8c0984e5SSebastian Reichel */ 2083*8c0984e5SSebastian Reichel static void ab8500_charger_kick_watchdog_work(struct work_struct *work) 2084*8c0984e5SSebastian Reichel { 2085*8c0984e5SSebastian Reichel int ret; 2086*8c0984e5SSebastian Reichel 2087*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2088*8c0984e5SSebastian Reichel struct ab8500_charger, kick_wd_work.work); 2089*8c0984e5SSebastian Reichel 2090*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 2091*8c0984e5SSebastian Reichel AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 2092*8c0984e5SSebastian Reichel if (ret) 2093*8c0984e5SSebastian Reichel dev_err(di->dev, "Failed to kick WD!\n"); 2094*8c0984e5SSebastian Reichel 2095*8c0984e5SSebastian Reichel /* Schedule a new watchdog kick */ 2096*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2097*8c0984e5SSebastian Reichel &di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL)); 2098*8c0984e5SSebastian Reichel } 2099*8c0984e5SSebastian Reichel 2100*8c0984e5SSebastian Reichel /** 2101*8c0984e5SSebastian Reichel * ab8500_charger_ac_work() - work to get and set main charger status 2102*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2103*8c0984e5SSebastian Reichel * 2104*8c0984e5SSebastian Reichel * Work queue function for checking the main charger status 2105*8c0984e5SSebastian Reichel */ 2106*8c0984e5SSebastian Reichel static void ab8500_charger_ac_work(struct work_struct *work) 2107*8c0984e5SSebastian Reichel { 2108*8c0984e5SSebastian Reichel int ret; 2109*8c0984e5SSebastian Reichel 2110*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2111*8c0984e5SSebastian Reichel struct ab8500_charger, ac_work); 2112*8c0984e5SSebastian Reichel 2113*8c0984e5SSebastian Reichel /* 2114*8c0984e5SSebastian Reichel * Since we can't be sure that the events are received 2115*8c0984e5SSebastian Reichel * synchronously, we have the check if the main charger is 2116*8c0984e5SSebastian Reichel * connected by reading the status register 2117*8c0984e5SSebastian Reichel */ 2118*8c0984e5SSebastian Reichel ret = ab8500_charger_detect_chargers(di, false); 2119*8c0984e5SSebastian Reichel if (ret < 0) 2120*8c0984e5SSebastian Reichel return; 2121*8c0984e5SSebastian Reichel 2122*8c0984e5SSebastian Reichel if (ret & AC_PW_CONN) { 2123*8c0984e5SSebastian Reichel di->ac.charger_connected = 1; 2124*8c0984e5SSebastian Reichel di->ac_conn = true; 2125*8c0984e5SSebastian Reichel } else { 2126*8c0984e5SSebastian Reichel di->ac.charger_connected = 0; 2127*8c0984e5SSebastian Reichel } 2128*8c0984e5SSebastian Reichel 2129*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->ac_chg.psy); 2130*8c0984e5SSebastian Reichel sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); 2131*8c0984e5SSebastian Reichel } 2132*8c0984e5SSebastian Reichel 2133*8c0984e5SSebastian Reichel static void ab8500_charger_usb_attached_work(struct work_struct *work) 2134*8c0984e5SSebastian Reichel { 2135*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2136*8c0984e5SSebastian Reichel struct ab8500_charger, 2137*8c0984e5SSebastian Reichel usb_charger_attached_work.work); 2138*8c0984e5SSebastian Reichel int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC); 2139*8c0984e5SSebastian Reichel int ret, i; 2140*8c0984e5SSebastian Reichel u8 statval; 2141*8c0984e5SSebastian Reichel 2142*8c0984e5SSebastian Reichel for (i = 0; i < 10; i++) { 2143*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2144*8c0984e5SSebastian Reichel AB8500_CHARGER, 2145*8c0984e5SSebastian Reichel AB8500_CH_USBCH_STAT1_REG, 2146*8c0984e5SSebastian Reichel &statval); 2147*8c0984e5SSebastian Reichel if (ret < 0) { 2148*8c0984e5SSebastian Reichel dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 2149*8c0984e5SSebastian Reichel goto reschedule; 2150*8c0984e5SSebastian Reichel } 2151*8c0984e5SSebastian Reichel if ((statval & usbch) != usbch) 2152*8c0984e5SSebastian Reichel goto reschedule; 2153*8c0984e5SSebastian Reichel 2154*8c0984e5SSebastian Reichel msleep(CHARGER_STATUS_POLL); 2155*8c0984e5SSebastian Reichel } 2156*8c0984e5SSebastian Reichel 2157*8c0984e5SSebastian Reichel ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0); 2158*8c0984e5SSebastian Reichel 2159*8c0984e5SSebastian Reichel mutex_lock(&di->charger_attached_mutex); 2160*8c0984e5SSebastian Reichel mutex_unlock(&di->charger_attached_mutex); 2161*8c0984e5SSebastian Reichel 2162*8c0984e5SSebastian Reichel return; 2163*8c0984e5SSebastian Reichel 2164*8c0984e5SSebastian Reichel reschedule: 2165*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2166*8c0984e5SSebastian Reichel &di->usb_charger_attached_work, 2167*8c0984e5SSebastian Reichel HZ); 2168*8c0984e5SSebastian Reichel } 2169*8c0984e5SSebastian Reichel 2170*8c0984e5SSebastian Reichel static void ab8500_charger_ac_attached_work(struct work_struct *work) 2171*8c0984e5SSebastian Reichel { 2172*8c0984e5SSebastian Reichel 2173*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2174*8c0984e5SSebastian Reichel struct ab8500_charger, 2175*8c0984e5SSebastian Reichel ac_charger_attached_work.work); 2176*8c0984e5SSebastian Reichel int mainch = (MAIN_CH_STATUS2_MAINCHGDROP | 2177*8c0984e5SSebastian Reichel MAIN_CH_STATUS2_MAINCHARGERDETDBNC); 2178*8c0984e5SSebastian Reichel int ret, i; 2179*8c0984e5SSebastian Reichel u8 statval; 2180*8c0984e5SSebastian Reichel 2181*8c0984e5SSebastian Reichel for (i = 0; i < 10; i++) { 2182*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2183*8c0984e5SSebastian Reichel AB8500_CHARGER, 2184*8c0984e5SSebastian Reichel AB8500_CH_STATUS2_REG, 2185*8c0984e5SSebastian Reichel &statval); 2186*8c0984e5SSebastian Reichel if (ret < 0) { 2187*8c0984e5SSebastian Reichel dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 2188*8c0984e5SSebastian Reichel goto reschedule; 2189*8c0984e5SSebastian Reichel } 2190*8c0984e5SSebastian Reichel 2191*8c0984e5SSebastian Reichel if ((statval & mainch) != mainch) 2192*8c0984e5SSebastian Reichel goto reschedule; 2193*8c0984e5SSebastian Reichel 2194*8c0984e5SSebastian Reichel msleep(CHARGER_STATUS_POLL); 2195*8c0984e5SSebastian Reichel } 2196*8c0984e5SSebastian Reichel 2197*8c0984e5SSebastian Reichel ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0); 2198*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->ac_work); 2199*8c0984e5SSebastian Reichel 2200*8c0984e5SSebastian Reichel mutex_lock(&di->charger_attached_mutex); 2201*8c0984e5SSebastian Reichel mutex_unlock(&di->charger_attached_mutex); 2202*8c0984e5SSebastian Reichel 2203*8c0984e5SSebastian Reichel return; 2204*8c0984e5SSebastian Reichel 2205*8c0984e5SSebastian Reichel reschedule: 2206*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2207*8c0984e5SSebastian Reichel &di->ac_charger_attached_work, 2208*8c0984e5SSebastian Reichel HZ); 2209*8c0984e5SSebastian Reichel } 2210*8c0984e5SSebastian Reichel 2211*8c0984e5SSebastian Reichel /** 2212*8c0984e5SSebastian Reichel * ab8500_charger_detect_usb_type_work() - work to detect USB type 2213*8c0984e5SSebastian Reichel * @work: Pointer to the work_struct structure 2214*8c0984e5SSebastian Reichel * 2215*8c0984e5SSebastian Reichel * Detect the type of USB plugged 2216*8c0984e5SSebastian Reichel */ 2217*8c0984e5SSebastian Reichel static void ab8500_charger_detect_usb_type_work(struct work_struct *work) 2218*8c0984e5SSebastian Reichel { 2219*8c0984e5SSebastian Reichel int ret; 2220*8c0984e5SSebastian Reichel 2221*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2222*8c0984e5SSebastian Reichel struct ab8500_charger, detect_usb_type_work); 2223*8c0984e5SSebastian Reichel 2224*8c0984e5SSebastian Reichel /* 2225*8c0984e5SSebastian Reichel * Since we can't be sure that the events are received 2226*8c0984e5SSebastian Reichel * synchronously, we have the check if is 2227*8c0984e5SSebastian Reichel * connected by reading the status register 2228*8c0984e5SSebastian Reichel */ 2229*8c0984e5SSebastian Reichel ret = ab8500_charger_detect_chargers(di, false); 2230*8c0984e5SSebastian Reichel if (ret < 0) 2231*8c0984e5SSebastian Reichel return; 2232*8c0984e5SSebastian Reichel 2233*8c0984e5SSebastian Reichel if (!(ret & USB_PW_CONN)) { 2234*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__); 2235*8c0984e5SSebastian Reichel di->vbus_detected = false; 2236*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, false); 2237*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2238*8c0984e5SSebastian Reichel } else { 2239*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__); 2240*8c0984e5SSebastian Reichel di->vbus_detected = true; 2241*8c0984e5SSebastian Reichel 2242*8c0984e5SSebastian Reichel if (is_ab8500_1p1_or_earlier(di->parent)) { 2243*8c0984e5SSebastian Reichel ret = ab8500_charger_detect_usb_type(di); 2244*8c0984e5SSebastian Reichel if (!ret) { 2245*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, true); 2246*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, 2247*8c0984e5SSebastian Reichel di->usb_chg.psy); 2248*8c0984e5SSebastian Reichel } 2249*8c0984e5SSebastian Reichel } else { 2250*8c0984e5SSebastian Reichel /* 2251*8c0984e5SSebastian Reichel * For ABB cut2.0 and onwards we have an IRQ, 2252*8c0984e5SSebastian Reichel * USB_LINK_STATUS that will be triggered when the USB 2253*8c0984e5SSebastian Reichel * link status changes. The exception is USB connected 2254*8c0984e5SSebastian Reichel * during startup. Then we don't get a 2255*8c0984e5SSebastian Reichel * USB_LINK_STATUS IRQ 2256*8c0984e5SSebastian Reichel */ 2257*8c0984e5SSebastian Reichel if (di->vbus_detected_start) { 2258*8c0984e5SSebastian Reichel di->vbus_detected_start = false; 2259*8c0984e5SSebastian Reichel ret = ab8500_charger_detect_usb_type(di); 2260*8c0984e5SSebastian Reichel if (!ret) { 2261*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, 2262*8c0984e5SSebastian Reichel true); 2263*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, 2264*8c0984e5SSebastian Reichel di->usb_chg.psy); 2265*8c0984e5SSebastian Reichel } 2266*8c0984e5SSebastian Reichel } 2267*8c0984e5SSebastian Reichel } 2268*8c0984e5SSebastian Reichel } 2269*8c0984e5SSebastian Reichel } 2270*8c0984e5SSebastian Reichel 2271*8c0984e5SSebastian Reichel /** 2272*8c0984e5SSebastian Reichel * ab8500_charger_usb_link_attach_work() - work to detect USB type 2273*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2274*8c0984e5SSebastian Reichel * 2275*8c0984e5SSebastian Reichel * Detect the type of USB plugged 2276*8c0984e5SSebastian Reichel */ 2277*8c0984e5SSebastian Reichel static void ab8500_charger_usb_link_attach_work(struct work_struct *work) 2278*8c0984e5SSebastian Reichel { 2279*8c0984e5SSebastian Reichel struct ab8500_charger *di = 2280*8c0984e5SSebastian Reichel container_of(work, struct ab8500_charger, attach_work.work); 2281*8c0984e5SSebastian Reichel int ret; 2282*8c0984e5SSebastian Reichel 2283*8c0984e5SSebastian Reichel /* Update maximum input current if USB enumeration is not detected */ 2284*8c0984e5SSebastian Reichel if (!di->usb.charger_online) { 2285*8c0984e5SSebastian Reichel ret = ab8500_charger_set_vbus_in_curr(di, 2286*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 2287*8c0984e5SSebastian Reichel if (ret) 2288*8c0984e5SSebastian Reichel return; 2289*8c0984e5SSebastian Reichel } 2290*8c0984e5SSebastian Reichel 2291*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, true); 2292*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2293*8c0984e5SSebastian Reichel } 2294*8c0984e5SSebastian Reichel 2295*8c0984e5SSebastian Reichel /** 2296*8c0984e5SSebastian Reichel * ab8500_charger_usb_link_status_work() - work to detect USB type 2297*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2298*8c0984e5SSebastian Reichel * 2299*8c0984e5SSebastian Reichel * Detect the type of USB plugged 2300*8c0984e5SSebastian Reichel */ 2301*8c0984e5SSebastian Reichel static void ab8500_charger_usb_link_status_work(struct work_struct *work) 2302*8c0984e5SSebastian Reichel { 2303*8c0984e5SSebastian Reichel int detected_chargers; 2304*8c0984e5SSebastian Reichel int ret; 2305*8c0984e5SSebastian Reichel u8 val; 2306*8c0984e5SSebastian Reichel u8 link_status; 2307*8c0984e5SSebastian Reichel 2308*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2309*8c0984e5SSebastian Reichel struct ab8500_charger, usb_link_status_work); 2310*8c0984e5SSebastian Reichel 2311*8c0984e5SSebastian Reichel /* 2312*8c0984e5SSebastian Reichel * Since we can't be sure that the events are received 2313*8c0984e5SSebastian Reichel * synchronously, we have the check if is 2314*8c0984e5SSebastian Reichel * connected by reading the status register 2315*8c0984e5SSebastian Reichel */ 2316*8c0984e5SSebastian Reichel detected_chargers = ab8500_charger_detect_chargers(di, false); 2317*8c0984e5SSebastian Reichel if (detected_chargers < 0) 2318*8c0984e5SSebastian Reichel return; 2319*8c0984e5SSebastian Reichel 2320*8c0984e5SSebastian Reichel /* 2321*8c0984e5SSebastian Reichel * Some chargers that breaks the USB spec is 2322*8c0984e5SSebastian Reichel * identified as invalid by AB8500 and it refuse 2323*8c0984e5SSebastian Reichel * to start the charging process. but by jumping 2324*8c0984e5SSebastian Reichel * thru a few hoops it can be forced to start. 2325*8c0984e5SSebastian Reichel */ 2326*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 2327*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 2328*8c0984e5SSebastian Reichel AB8500_USB_LINE_STAT_REG, &val); 2329*8c0984e5SSebastian Reichel else 2330*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 2331*8c0984e5SSebastian Reichel AB8500_USB_LINK1_STAT_REG, &val); 2332*8c0984e5SSebastian Reichel 2333*8c0984e5SSebastian Reichel if (ret >= 0) 2334*8c0984e5SSebastian Reichel dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val); 2335*8c0984e5SSebastian Reichel else 2336*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Error reading USB link status\n"); 2337*8c0984e5SSebastian Reichel 2338*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 2339*8c0984e5SSebastian Reichel link_status = AB8500_USB_LINK_STATUS; 2340*8c0984e5SSebastian Reichel else 2341*8c0984e5SSebastian Reichel link_status = AB8505_USB_LINK_STATUS; 2342*8c0984e5SSebastian Reichel 2343*8c0984e5SSebastian Reichel if (detected_chargers & USB_PW_CONN) { 2344*8c0984e5SSebastian Reichel if (((val & link_status) >> USB_LINK_STATUS_SHIFT) == 2345*8c0984e5SSebastian Reichel USB_STAT_NOT_VALID_LINK && 2346*8c0984e5SSebastian Reichel di->invalid_charger_detect_state == 0) { 2347*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2348*8c0984e5SSebastian Reichel "Invalid charger detected, state= 0\n"); 2349*8c0984e5SSebastian Reichel /*Enable charger*/ 2350*8c0984e5SSebastian Reichel abx500_mask_and_set_register_interruptible(di->dev, 2351*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_USBCH_CTRL1_REG, 2352*8c0984e5SSebastian Reichel USB_CH_ENA, USB_CH_ENA); 2353*8c0984e5SSebastian Reichel /*Enable charger detection*/ 2354*8c0984e5SSebastian Reichel abx500_mask_and_set_register_interruptible(di->dev, 2355*8c0984e5SSebastian Reichel AB8500_USB, AB8500_USB_LINE_CTRL2_REG, 2356*8c0984e5SSebastian Reichel USB_CH_DET, USB_CH_DET); 2357*8c0984e5SSebastian Reichel di->invalid_charger_detect_state = 1; 2358*8c0984e5SSebastian Reichel /*exit and wait for new link status interrupt.*/ 2359*8c0984e5SSebastian Reichel return; 2360*8c0984e5SSebastian Reichel 2361*8c0984e5SSebastian Reichel } 2362*8c0984e5SSebastian Reichel if (di->invalid_charger_detect_state == 1) { 2363*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2364*8c0984e5SSebastian Reichel "Invalid charger detected, state= 1\n"); 2365*8c0984e5SSebastian Reichel /*Stop charger detection*/ 2366*8c0984e5SSebastian Reichel abx500_mask_and_set_register_interruptible(di->dev, 2367*8c0984e5SSebastian Reichel AB8500_USB, AB8500_USB_LINE_CTRL2_REG, 2368*8c0984e5SSebastian Reichel USB_CH_DET, 0x00); 2369*8c0984e5SSebastian Reichel /*Check link status*/ 2370*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 2371*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2372*8c0984e5SSebastian Reichel AB8500_USB, AB8500_USB_LINE_STAT_REG, 2373*8c0984e5SSebastian Reichel &val); 2374*8c0984e5SSebastian Reichel else 2375*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2376*8c0984e5SSebastian Reichel AB8500_USB, AB8500_USB_LINK1_STAT_REG, 2377*8c0984e5SSebastian Reichel &val); 2378*8c0984e5SSebastian Reichel 2379*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB link status= 0x%02x\n", 2380*8c0984e5SSebastian Reichel (val & link_status) >> USB_LINK_STATUS_SHIFT); 2381*8c0984e5SSebastian Reichel di->invalid_charger_detect_state = 2; 2382*8c0984e5SSebastian Reichel } 2383*8c0984e5SSebastian Reichel } else { 2384*8c0984e5SSebastian Reichel di->invalid_charger_detect_state = 0; 2385*8c0984e5SSebastian Reichel } 2386*8c0984e5SSebastian Reichel 2387*8c0984e5SSebastian Reichel if (!(detected_chargers & USB_PW_CONN)) { 2388*8c0984e5SSebastian Reichel di->vbus_detected = false; 2389*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, false); 2390*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2391*8c0984e5SSebastian Reichel return; 2392*8c0984e5SSebastian Reichel } 2393*8c0984e5SSebastian Reichel 2394*8c0984e5SSebastian Reichel dev_dbg(di->dev,"%s di->vbus_detected = true\n",__func__); 2395*8c0984e5SSebastian Reichel di->vbus_detected = true; 2396*8c0984e5SSebastian Reichel ret = ab8500_charger_read_usb_type(di); 2397*8c0984e5SSebastian Reichel if (ret) { 2398*8c0984e5SSebastian Reichel if (ret == -ENXIO) { 2399*8c0984e5SSebastian Reichel /* No valid charger type detected */ 2400*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, false); 2401*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2402*8c0984e5SSebastian Reichel } 2403*8c0984e5SSebastian Reichel return; 2404*8c0984e5SSebastian Reichel } 2405*8c0984e5SSebastian Reichel 2406*8c0984e5SSebastian Reichel if (di->usb_device_is_unrecognised) { 2407*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2408*8c0984e5SSebastian Reichel "Potential Legacy Charger device. " 2409*8c0984e5SSebastian Reichel "Delay work for %d msec for USB enum " 2410*8c0984e5SSebastian Reichel "to finish", 2411*8c0984e5SSebastian Reichel WAIT_ACA_RID_ENUMERATION); 2412*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2413*8c0984e5SSebastian Reichel &di->attach_work, 2414*8c0984e5SSebastian Reichel msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION)); 2415*8c0984e5SSebastian Reichel } else if (di->is_aca_rid == 1) { 2416*8c0984e5SSebastian Reichel /* Only wait once */ 2417*8c0984e5SSebastian Reichel di->is_aca_rid++; 2418*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2419*8c0984e5SSebastian Reichel "%s Wait %d msec for USB enum to finish", 2420*8c0984e5SSebastian Reichel __func__, WAIT_ACA_RID_ENUMERATION); 2421*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2422*8c0984e5SSebastian Reichel &di->attach_work, 2423*8c0984e5SSebastian Reichel msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION)); 2424*8c0984e5SSebastian Reichel } else { 2425*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2426*8c0984e5SSebastian Reichel &di->attach_work, 2427*8c0984e5SSebastian Reichel 0); 2428*8c0984e5SSebastian Reichel } 2429*8c0984e5SSebastian Reichel } 2430*8c0984e5SSebastian Reichel 2431*8c0984e5SSebastian Reichel static void ab8500_charger_usb_state_changed_work(struct work_struct *work) 2432*8c0984e5SSebastian Reichel { 2433*8c0984e5SSebastian Reichel int ret; 2434*8c0984e5SSebastian Reichel unsigned long flags; 2435*8c0984e5SSebastian Reichel 2436*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2437*8c0984e5SSebastian Reichel struct ab8500_charger, usb_state_changed_work.work); 2438*8c0984e5SSebastian Reichel 2439*8c0984e5SSebastian Reichel if (!di->vbus_detected) { 2440*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2441*8c0984e5SSebastian Reichel "%s !di->vbus_detected\n", 2442*8c0984e5SSebastian Reichel __func__); 2443*8c0984e5SSebastian Reichel return; 2444*8c0984e5SSebastian Reichel } 2445*8c0984e5SSebastian Reichel 2446*8c0984e5SSebastian Reichel spin_lock_irqsave(&di->usb_state.usb_lock, flags); 2447*8c0984e5SSebastian Reichel di->usb_state.state = di->usb_state.state_tmp; 2448*8c0984e5SSebastian Reichel di->usb_state.usb_current = di->usb_state.usb_current_tmp; 2449*8c0984e5SSebastian Reichel spin_unlock_irqrestore(&di->usb_state.usb_lock, flags); 2450*8c0984e5SSebastian Reichel 2451*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n", 2452*8c0984e5SSebastian Reichel __func__, di->usb_state.state, di->usb_state.usb_current); 2453*8c0984e5SSebastian Reichel 2454*8c0984e5SSebastian Reichel switch (di->usb_state.state) { 2455*8c0984e5SSebastian Reichel case AB8500_BM_USB_STATE_RESET_HS: 2456*8c0984e5SSebastian Reichel case AB8500_BM_USB_STATE_RESET_FS: 2457*8c0984e5SSebastian Reichel case AB8500_BM_USB_STATE_SUSPEND: 2458*8c0984e5SSebastian Reichel case AB8500_BM_USB_STATE_MAX: 2459*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, false); 2460*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2461*8c0984e5SSebastian Reichel break; 2462*8c0984e5SSebastian Reichel 2463*8c0984e5SSebastian Reichel case AB8500_BM_USB_STATE_RESUME: 2464*8c0984e5SSebastian Reichel /* 2465*8c0984e5SSebastian Reichel * when suspend->resume there should be delay 2466*8c0984e5SSebastian Reichel * of 1sec for enabling charging 2467*8c0984e5SSebastian Reichel */ 2468*8c0984e5SSebastian Reichel msleep(1000); 2469*8c0984e5SSebastian Reichel /* Intentional fall through */ 2470*8c0984e5SSebastian Reichel case AB8500_BM_USB_STATE_CONFIGURED: 2471*8c0984e5SSebastian Reichel /* 2472*8c0984e5SSebastian Reichel * USB is configured, enable charging with the charging 2473*8c0984e5SSebastian Reichel * input current obtained from USB driver 2474*8c0984e5SSebastian Reichel */ 2475*8c0984e5SSebastian Reichel if (!ab8500_charger_get_usb_cur(di)) { 2476*8c0984e5SSebastian Reichel /* Update maximum input current */ 2477*8c0984e5SSebastian Reichel ret = ab8500_charger_set_vbus_in_curr(di, 2478*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 2479*8c0984e5SSebastian Reichel if (ret) 2480*8c0984e5SSebastian Reichel return; 2481*8c0984e5SSebastian Reichel 2482*8c0984e5SSebastian Reichel ab8500_charger_set_usb_connected(di, true); 2483*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2484*8c0984e5SSebastian Reichel } 2485*8c0984e5SSebastian Reichel break; 2486*8c0984e5SSebastian Reichel 2487*8c0984e5SSebastian Reichel default: 2488*8c0984e5SSebastian Reichel break; 2489*8c0984e5SSebastian Reichel }; 2490*8c0984e5SSebastian Reichel } 2491*8c0984e5SSebastian Reichel 2492*8c0984e5SSebastian Reichel /** 2493*8c0984e5SSebastian Reichel * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status 2494*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2495*8c0984e5SSebastian Reichel * 2496*8c0984e5SSebastian Reichel * Work queue function for checking the USB charger Not OK status 2497*8c0984e5SSebastian Reichel */ 2498*8c0984e5SSebastian Reichel static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work) 2499*8c0984e5SSebastian Reichel { 2500*8c0984e5SSebastian Reichel int ret; 2501*8c0984e5SSebastian Reichel u8 reg_value; 2502*8c0984e5SSebastian Reichel bool prev_status; 2503*8c0984e5SSebastian Reichel 2504*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2505*8c0984e5SSebastian Reichel struct ab8500_charger, check_usbchgnotok_work.work); 2506*8c0984e5SSebastian Reichel 2507*8c0984e5SSebastian Reichel /* Check if the status bit for usbchargernotok is still active */ 2508*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2509*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); 2510*8c0984e5SSebastian Reichel if (ret < 0) { 2511*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 2512*8c0984e5SSebastian Reichel return; 2513*8c0984e5SSebastian Reichel } 2514*8c0984e5SSebastian Reichel prev_status = di->flags.usbchargernotok; 2515*8c0984e5SSebastian Reichel 2516*8c0984e5SSebastian Reichel if (reg_value & VBUS_CH_NOK) { 2517*8c0984e5SSebastian Reichel di->flags.usbchargernotok = true; 2518*8c0984e5SSebastian Reichel /* Check again in 1sec */ 2519*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2520*8c0984e5SSebastian Reichel &di->check_usbchgnotok_work, HZ); 2521*8c0984e5SSebastian Reichel } else { 2522*8c0984e5SSebastian Reichel di->flags.usbchargernotok = false; 2523*8c0984e5SSebastian Reichel di->flags.vbus_collapse = false; 2524*8c0984e5SSebastian Reichel } 2525*8c0984e5SSebastian Reichel 2526*8c0984e5SSebastian Reichel if (prev_status != di->flags.usbchargernotok) 2527*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2528*8c0984e5SSebastian Reichel } 2529*8c0984e5SSebastian Reichel 2530*8c0984e5SSebastian Reichel /** 2531*8c0984e5SSebastian Reichel * ab8500_charger_check_main_thermal_prot_work() - check main thermal status 2532*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2533*8c0984e5SSebastian Reichel * 2534*8c0984e5SSebastian Reichel * Work queue function for checking the Main thermal prot status 2535*8c0984e5SSebastian Reichel */ 2536*8c0984e5SSebastian Reichel static void ab8500_charger_check_main_thermal_prot_work( 2537*8c0984e5SSebastian Reichel struct work_struct *work) 2538*8c0984e5SSebastian Reichel { 2539*8c0984e5SSebastian Reichel int ret; 2540*8c0984e5SSebastian Reichel u8 reg_value; 2541*8c0984e5SSebastian Reichel 2542*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2543*8c0984e5SSebastian Reichel struct ab8500_charger, check_main_thermal_prot_work); 2544*8c0984e5SSebastian Reichel 2545*8c0984e5SSebastian Reichel /* Check if the status bit for main_thermal_prot is still active */ 2546*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2547*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); 2548*8c0984e5SSebastian Reichel if (ret < 0) { 2549*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 2550*8c0984e5SSebastian Reichel return; 2551*8c0984e5SSebastian Reichel } 2552*8c0984e5SSebastian Reichel if (reg_value & MAIN_CH_TH_PROT) 2553*8c0984e5SSebastian Reichel di->flags.main_thermal_prot = true; 2554*8c0984e5SSebastian Reichel else 2555*8c0984e5SSebastian Reichel di->flags.main_thermal_prot = false; 2556*8c0984e5SSebastian Reichel 2557*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->ac_chg.psy); 2558*8c0984e5SSebastian Reichel } 2559*8c0984e5SSebastian Reichel 2560*8c0984e5SSebastian Reichel /** 2561*8c0984e5SSebastian Reichel * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status 2562*8c0984e5SSebastian Reichel * @work: pointer to the work_struct structure 2563*8c0984e5SSebastian Reichel * 2564*8c0984e5SSebastian Reichel * Work queue function for checking the USB thermal prot status 2565*8c0984e5SSebastian Reichel */ 2566*8c0984e5SSebastian Reichel static void ab8500_charger_check_usb_thermal_prot_work( 2567*8c0984e5SSebastian Reichel struct work_struct *work) 2568*8c0984e5SSebastian Reichel { 2569*8c0984e5SSebastian Reichel int ret; 2570*8c0984e5SSebastian Reichel u8 reg_value; 2571*8c0984e5SSebastian Reichel 2572*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2573*8c0984e5SSebastian Reichel struct ab8500_charger, check_usb_thermal_prot_work); 2574*8c0984e5SSebastian Reichel 2575*8c0984e5SSebastian Reichel /* Check if the status bit for usb_thermal_prot is still active */ 2576*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, 2577*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); 2578*8c0984e5SSebastian Reichel if (ret < 0) { 2579*8c0984e5SSebastian Reichel dev_err(di->dev, "%s ab8500 read failed\n", __func__); 2580*8c0984e5SSebastian Reichel return; 2581*8c0984e5SSebastian Reichel } 2582*8c0984e5SSebastian Reichel if (reg_value & USB_CH_TH_PROT) 2583*8c0984e5SSebastian Reichel di->flags.usb_thermal_prot = true; 2584*8c0984e5SSebastian Reichel else 2585*8c0984e5SSebastian Reichel di->flags.usb_thermal_prot = false; 2586*8c0984e5SSebastian Reichel 2587*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2588*8c0984e5SSebastian Reichel } 2589*8c0984e5SSebastian Reichel 2590*8c0984e5SSebastian Reichel /** 2591*8c0984e5SSebastian Reichel * ab8500_charger_mainchunplugdet_handler() - main charger unplugged 2592*8c0984e5SSebastian Reichel * @irq: interrupt number 2593*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2594*8c0984e5SSebastian Reichel * 2595*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2596*8c0984e5SSebastian Reichel */ 2597*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di) 2598*8c0984e5SSebastian Reichel { 2599*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2600*8c0984e5SSebastian Reichel 2601*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Main charger unplugged\n"); 2602*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->ac_work); 2603*8c0984e5SSebastian Reichel 2604*8c0984e5SSebastian Reichel cancel_delayed_work_sync(&di->ac_charger_attached_work); 2605*8c0984e5SSebastian Reichel mutex_lock(&di->charger_attached_mutex); 2606*8c0984e5SSebastian Reichel mutex_unlock(&di->charger_attached_mutex); 2607*8c0984e5SSebastian Reichel 2608*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2609*8c0984e5SSebastian Reichel } 2610*8c0984e5SSebastian Reichel 2611*8c0984e5SSebastian Reichel /** 2612*8c0984e5SSebastian Reichel * ab8500_charger_mainchplugdet_handler() - main charger plugged 2613*8c0984e5SSebastian Reichel * @irq: interrupt number 2614*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2615*8c0984e5SSebastian Reichel * 2616*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2617*8c0984e5SSebastian Reichel */ 2618*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di) 2619*8c0984e5SSebastian Reichel { 2620*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2621*8c0984e5SSebastian Reichel 2622*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Main charger plugged\n"); 2623*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->ac_work); 2624*8c0984e5SSebastian Reichel 2625*8c0984e5SSebastian Reichel mutex_lock(&di->charger_attached_mutex); 2626*8c0984e5SSebastian Reichel mutex_unlock(&di->charger_attached_mutex); 2627*8c0984e5SSebastian Reichel 2628*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 2629*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 2630*8c0984e5SSebastian Reichel &di->ac_charger_attached_work, 2631*8c0984e5SSebastian Reichel HZ); 2632*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2633*8c0984e5SSebastian Reichel } 2634*8c0984e5SSebastian Reichel 2635*8c0984e5SSebastian Reichel /** 2636*8c0984e5SSebastian Reichel * ab8500_charger_mainextchnotok_handler() - main charger not ok 2637*8c0984e5SSebastian Reichel * @irq: interrupt number 2638*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2639*8c0984e5SSebastian Reichel * 2640*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2641*8c0984e5SSebastian Reichel */ 2642*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di) 2643*8c0984e5SSebastian Reichel { 2644*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2645*8c0984e5SSebastian Reichel 2646*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Main charger not ok\n"); 2647*8c0984e5SSebastian Reichel di->flags.mainextchnotok = true; 2648*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->ac_chg.psy); 2649*8c0984e5SSebastian Reichel 2650*8c0984e5SSebastian Reichel /* Schedule a new HW failure check */ 2651*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); 2652*8c0984e5SSebastian Reichel 2653*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2654*8c0984e5SSebastian Reichel } 2655*8c0984e5SSebastian Reichel 2656*8c0984e5SSebastian Reichel /** 2657*8c0984e5SSebastian Reichel * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger 2658*8c0984e5SSebastian Reichel * thermal protection threshold 2659*8c0984e5SSebastian Reichel * @irq: interrupt number 2660*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2661*8c0984e5SSebastian Reichel * 2662*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2663*8c0984e5SSebastian Reichel */ 2664*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di) 2665*8c0984e5SSebastian Reichel { 2666*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2667*8c0984e5SSebastian Reichel 2668*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2669*8c0984e5SSebastian Reichel "Die temp above Main charger thermal protection threshold\n"); 2670*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->check_main_thermal_prot_work); 2671*8c0984e5SSebastian Reichel 2672*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2673*8c0984e5SSebastian Reichel } 2674*8c0984e5SSebastian Reichel 2675*8c0984e5SSebastian Reichel /** 2676*8c0984e5SSebastian Reichel * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger 2677*8c0984e5SSebastian Reichel * thermal protection threshold 2678*8c0984e5SSebastian Reichel * @irq: interrupt number 2679*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2680*8c0984e5SSebastian Reichel * 2681*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2682*8c0984e5SSebastian Reichel */ 2683*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di) 2684*8c0984e5SSebastian Reichel { 2685*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2686*8c0984e5SSebastian Reichel 2687*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2688*8c0984e5SSebastian Reichel "Die temp ok for Main charger thermal protection threshold\n"); 2689*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->check_main_thermal_prot_work); 2690*8c0984e5SSebastian Reichel 2691*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2692*8c0984e5SSebastian Reichel } 2693*8c0984e5SSebastian Reichel 2694*8c0984e5SSebastian Reichel static void ab8500_charger_vbus_drop_end_work(struct work_struct *work) 2695*8c0984e5SSebastian Reichel { 2696*8c0984e5SSebastian Reichel struct ab8500_charger *di = container_of(work, 2697*8c0984e5SSebastian Reichel struct ab8500_charger, vbus_drop_end_work.work); 2698*8c0984e5SSebastian Reichel int ret, curr; 2699*8c0984e5SSebastian Reichel u8 reg_value; 2700*8c0984e5SSebastian Reichel 2701*8c0984e5SSebastian Reichel di->flags.vbus_drop_end = false; 2702*8c0984e5SSebastian Reichel 2703*8c0984e5SSebastian Reichel /* Reset the drop counter */ 2704*8c0984e5SSebastian Reichel abx500_set_register_interruptible(di->dev, 2705*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01); 2706*8c0984e5SSebastian Reichel 2707*8c0984e5SSebastian Reichel if (is_ab8540(di->parent)) 2708*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 2709*8c0984e5SSebastian Reichel AB8540_CH_USBCH_STAT3_REG, ®_value); 2710*8c0984e5SSebastian Reichel else 2711*8c0984e5SSebastian Reichel ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 2712*8c0984e5SSebastian Reichel AB8500_CH_USBCH_STAT2_REG, ®_value); 2713*8c0984e5SSebastian Reichel if (ret < 0) { 2714*8c0984e5SSebastian Reichel dev_err(di->dev, "%s read failed\n", __func__); 2715*8c0984e5SSebastian Reichel return; 2716*8c0984e5SSebastian Reichel } 2717*8c0984e5SSebastian Reichel 2718*8c0984e5SSebastian Reichel if (is_ab8540(di->parent)) 2719*8c0984e5SSebastian Reichel curr = di->bm->chg_input_curr[ 2720*8c0984e5SSebastian Reichel reg_value & AB8540_AUTO_VBUS_IN_CURR_MASK]; 2721*8c0984e5SSebastian Reichel else 2722*8c0984e5SSebastian Reichel curr = di->bm->chg_input_curr[ 2723*8c0984e5SSebastian Reichel reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT]; 2724*8c0984e5SSebastian Reichel 2725*8c0984e5SSebastian Reichel if (di->max_usb_in_curr.calculated_max != curr) { 2726*8c0984e5SSebastian Reichel /* USB source is collapsing */ 2727*8c0984e5SSebastian Reichel di->max_usb_in_curr.calculated_max = curr; 2728*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2729*8c0984e5SSebastian Reichel "VBUS input current limiting to %d mA\n", 2730*8c0984e5SSebastian Reichel di->max_usb_in_curr.calculated_max); 2731*8c0984e5SSebastian Reichel } else { 2732*8c0984e5SSebastian Reichel /* 2733*8c0984e5SSebastian Reichel * USB source can not give more than this amount. 2734*8c0984e5SSebastian Reichel * Taking more will collapse the source. 2735*8c0984e5SSebastian Reichel */ 2736*8c0984e5SSebastian Reichel di->max_usb_in_curr.set_max = 2737*8c0984e5SSebastian Reichel di->max_usb_in_curr.calculated_max; 2738*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2739*8c0984e5SSebastian Reichel "VBUS input current limited to %d mA\n", 2740*8c0984e5SSebastian Reichel di->max_usb_in_curr.set_max); 2741*8c0984e5SSebastian Reichel } 2742*8c0984e5SSebastian Reichel 2743*8c0984e5SSebastian Reichel if (di->usb.charger_connected) 2744*8c0984e5SSebastian Reichel ab8500_charger_set_vbus_in_curr(di, 2745*8c0984e5SSebastian Reichel di->max_usb_in_curr.usb_type_max); 2746*8c0984e5SSebastian Reichel } 2747*8c0984e5SSebastian Reichel 2748*8c0984e5SSebastian Reichel /** 2749*8c0984e5SSebastian Reichel * ab8500_charger_vbusdetf_handler() - VBUS falling detected 2750*8c0984e5SSebastian Reichel * @irq: interrupt number 2751*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2752*8c0984e5SSebastian Reichel * 2753*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2754*8c0984e5SSebastian Reichel */ 2755*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di) 2756*8c0984e5SSebastian Reichel { 2757*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2758*8c0984e5SSebastian Reichel 2759*8c0984e5SSebastian Reichel di->vbus_detected = false; 2760*8c0984e5SSebastian Reichel dev_dbg(di->dev, "VBUS falling detected\n"); 2761*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->detect_usb_type_work); 2762*8c0984e5SSebastian Reichel 2763*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2764*8c0984e5SSebastian Reichel } 2765*8c0984e5SSebastian Reichel 2766*8c0984e5SSebastian Reichel /** 2767*8c0984e5SSebastian Reichel * ab8500_charger_vbusdetr_handler() - VBUS rising detected 2768*8c0984e5SSebastian Reichel * @irq: interrupt number 2769*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2770*8c0984e5SSebastian Reichel * 2771*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2772*8c0984e5SSebastian Reichel */ 2773*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di) 2774*8c0984e5SSebastian Reichel { 2775*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2776*8c0984e5SSebastian Reichel 2777*8c0984e5SSebastian Reichel di->vbus_detected = true; 2778*8c0984e5SSebastian Reichel dev_dbg(di->dev, "VBUS rising detected\n"); 2779*8c0984e5SSebastian Reichel 2780*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->detect_usb_type_work); 2781*8c0984e5SSebastian Reichel 2782*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2783*8c0984e5SSebastian Reichel } 2784*8c0984e5SSebastian Reichel 2785*8c0984e5SSebastian Reichel /** 2786*8c0984e5SSebastian Reichel * ab8500_charger_usblinkstatus_handler() - USB link status has changed 2787*8c0984e5SSebastian Reichel * @irq: interrupt number 2788*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2789*8c0984e5SSebastian Reichel * 2790*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2791*8c0984e5SSebastian Reichel */ 2792*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di) 2793*8c0984e5SSebastian Reichel { 2794*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2795*8c0984e5SSebastian Reichel 2796*8c0984e5SSebastian Reichel dev_dbg(di->dev, "USB link status changed\n"); 2797*8c0984e5SSebastian Reichel 2798*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->usb_link_status_work); 2799*8c0984e5SSebastian Reichel 2800*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2801*8c0984e5SSebastian Reichel } 2802*8c0984e5SSebastian Reichel 2803*8c0984e5SSebastian Reichel /** 2804*8c0984e5SSebastian Reichel * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger 2805*8c0984e5SSebastian Reichel * thermal protection threshold 2806*8c0984e5SSebastian Reichel * @irq: interrupt number 2807*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2808*8c0984e5SSebastian Reichel * 2809*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2810*8c0984e5SSebastian Reichel */ 2811*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di) 2812*8c0984e5SSebastian Reichel { 2813*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2814*8c0984e5SSebastian Reichel 2815*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2816*8c0984e5SSebastian Reichel "Die temp above USB charger thermal protection threshold\n"); 2817*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); 2818*8c0984e5SSebastian Reichel 2819*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2820*8c0984e5SSebastian Reichel } 2821*8c0984e5SSebastian Reichel 2822*8c0984e5SSebastian Reichel /** 2823*8c0984e5SSebastian Reichel * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger 2824*8c0984e5SSebastian Reichel * thermal protection threshold 2825*8c0984e5SSebastian Reichel * @irq: interrupt number 2826*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2827*8c0984e5SSebastian Reichel * 2828*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2829*8c0984e5SSebastian Reichel */ 2830*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di) 2831*8c0984e5SSebastian Reichel { 2832*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2833*8c0984e5SSebastian Reichel 2834*8c0984e5SSebastian Reichel dev_dbg(di->dev, 2835*8c0984e5SSebastian Reichel "Die temp ok for USB charger thermal protection threshold\n"); 2836*8c0984e5SSebastian Reichel queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); 2837*8c0984e5SSebastian Reichel 2838*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2839*8c0984e5SSebastian Reichel } 2840*8c0984e5SSebastian Reichel 2841*8c0984e5SSebastian Reichel /** 2842*8c0984e5SSebastian Reichel * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected 2843*8c0984e5SSebastian Reichel * @irq: interrupt number 2844*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2845*8c0984e5SSebastian Reichel * 2846*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2847*8c0984e5SSebastian Reichel */ 2848*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di) 2849*8c0984e5SSebastian Reichel { 2850*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2851*8c0984e5SSebastian Reichel 2852*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Not allowed USB charger detected\n"); 2853*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0); 2854*8c0984e5SSebastian Reichel 2855*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2856*8c0984e5SSebastian Reichel } 2857*8c0984e5SSebastian Reichel 2858*8c0984e5SSebastian Reichel /** 2859*8c0984e5SSebastian Reichel * ab8500_charger_chwdexp_handler() - Charger watchdog expired 2860*8c0984e5SSebastian Reichel * @irq: interrupt number 2861*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2862*8c0984e5SSebastian Reichel * 2863*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2864*8c0984e5SSebastian Reichel */ 2865*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di) 2866*8c0984e5SSebastian Reichel { 2867*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2868*8c0984e5SSebastian Reichel 2869*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Charger watchdog expired\n"); 2870*8c0984e5SSebastian Reichel 2871*8c0984e5SSebastian Reichel /* 2872*8c0984e5SSebastian Reichel * The charger that was online when the watchdog expired 2873*8c0984e5SSebastian Reichel * needs to be restarted for charging to start again 2874*8c0984e5SSebastian Reichel */ 2875*8c0984e5SSebastian Reichel if (di->ac.charger_online) { 2876*8c0984e5SSebastian Reichel di->ac.wd_expired = true; 2877*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->ac_chg.psy); 2878*8c0984e5SSebastian Reichel } 2879*8c0984e5SSebastian Reichel if (di->usb.charger_online) { 2880*8c0984e5SSebastian Reichel di->usb.wd_expired = true; 2881*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2882*8c0984e5SSebastian Reichel } 2883*8c0984e5SSebastian Reichel 2884*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2885*8c0984e5SSebastian Reichel } 2886*8c0984e5SSebastian Reichel 2887*8c0984e5SSebastian Reichel /** 2888*8c0984e5SSebastian Reichel * ab8500_charger_vbuschdropend_handler() - VBUS drop removed 2889*8c0984e5SSebastian Reichel * @irq: interrupt number 2890*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2891*8c0984e5SSebastian Reichel * 2892*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2893*8c0984e5SSebastian Reichel */ 2894*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di) 2895*8c0984e5SSebastian Reichel { 2896*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2897*8c0984e5SSebastian Reichel 2898*8c0984e5SSebastian Reichel dev_dbg(di->dev, "VBUS charger drop ended\n"); 2899*8c0984e5SSebastian Reichel di->flags.vbus_drop_end = true; 2900*8c0984e5SSebastian Reichel 2901*8c0984e5SSebastian Reichel /* 2902*8c0984e5SSebastian Reichel * VBUS might have dropped due to bad connection. 2903*8c0984e5SSebastian Reichel * Schedule a new input limit set to the value SW requests. 2904*8c0984e5SSebastian Reichel */ 2905*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 2906*8c0984e5SSebastian Reichel round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ)); 2907*8c0984e5SSebastian Reichel 2908*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2909*8c0984e5SSebastian Reichel } 2910*8c0984e5SSebastian Reichel 2911*8c0984e5SSebastian Reichel /** 2912*8c0984e5SSebastian Reichel * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected 2913*8c0984e5SSebastian Reichel * @irq: interrupt number 2914*8c0984e5SSebastian Reichel * @_di: pointer to the ab8500_charger structure 2915*8c0984e5SSebastian Reichel * 2916*8c0984e5SSebastian Reichel * Returns IRQ status(IRQ_HANDLED) 2917*8c0984e5SSebastian Reichel */ 2918*8c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di) 2919*8c0984e5SSebastian Reichel { 2920*8c0984e5SSebastian Reichel struct ab8500_charger *di = _di; 2921*8c0984e5SSebastian Reichel 2922*8c0984e5SSebastian Reichel dev_dbg(di->dev, "VBUS overvoltage detected\n"); 2923*8c0984e5SSebastian Reichel di->flags.vbus_ovv = true; 2924*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->usb_chg.psy); 2925*8c0984e5SSebastian Reichel 2926*8c0984e5SSebastian Reichel /* Schedule a new HW failure check */ 2927*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); 2928*8c0984e5SSebastian Reichel 2929*8c0984e5SSebastian Reichel return IRQ_HANDLED; 2930*8c0984e5SSebastian Reichel } 2931*8c0984e5SSebastian Reichel 2932*8c0984e5SSebastian Reichel /** 2933*8c0984e5SSebastian Reichel * ab8500_charger_ac_get_property() - get the ac/mains properties 2934*8c0984e5SSebastian Reichel * @psy: pointer to the power_supply structure 2935*8c0984e5SSebastian Reichel * @psp: pointer to the power_supply_property structure 2936*8c0984e5SSebastian Reichel * @val: pointer to the power_supply_propval union 2937*8c0984e5SSebastian Reichel * 2938*8c0984e5SSebastian Reichel * This function gets called when an application tries to get the ac/mains 2939*8c0984e5SSebastian Reichel * properties by reading the sysfs files. 2940*8c0984e5SSebastian Reichel * AC/Mains properties are online, present and voltage. 2941*8c0984e5SSebastian Reichel * online: ac/mains charging is in progress or not 2942*8c0984e5SSebastian Reichel * present: presence of the ac/mains 2943*8c0984e5SSebastian Reichel * voltage: AC/Mains voltage 2944*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 2945*8c0984e5SSebastian Reichel */ 2946*8c0984e5SSebastian Reichel static int ab8500_charger_ac_get_property(struct power_supply *psy, 2947*8c0984e5SSebastian Reichel enum power_supply_property psp, 2948*8c0984e5SSebastian Reichel union power_supply_propval *val) 2949*8c0984e5SSebastian Reichel { 2950*8c0984e5SSebastian Reichel struct ab8500_charger *di; 2951*8c0984e5SSebastian Reichel int ret; 2952*8c0984e5SSebastian Reichel 2953*8c0984e5SSebastian Reichel di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy)); 2954*8c0984e5SSebastian Reichel 2955*8c0984e5SSebastian Reichel switch (psp) { 2956*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_HEALTH: 2957*8c0984e5SSebastian Reichel if (di->flags.mainextchnotok) 2958*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 2959*8c0984e5SSebastian Reichel else if (di->ac.wd_expired || di->usb.wd_expired) 2960*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_DEAD; 2961*8c0984e5SSebastian Reichel else if (di->flags.main_thermal_prot) 2962*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 2963*8c0984e5SSebastian Reichel else 2964*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_GOOD; 2965*8c0984e5SSebastian Reichel break; 2966*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_ONLINE: 2967*8c0984e5SSebastian Reichel val->intval = di->ac.charger_online; 2968*8c0984e5SSebastian Reichel break; 2969*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_PRESENT: 2970*8c0984e5SSebastian Reichel val->intval = di->ac.charger_connected; 2971*8c0984e5SSebastian Reichel break; 2972*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_NOW: 2973*8c0984e5SSebastian Reichel ret = ab8500_charger_get_ac_voltage(di); 2974*8c0984e5SSebastian Reichel if (ret >= 0) 2975*8c0984e5SSebastian Reichel di->ac.charger_voltage = ret; 2976*8c0984e5SSebastian Reichel /* On error, use previous value */ 2977*8c0984e5SSebastian Reichel val->intval = di->ac.charger_voltage * 1000; 2978*8c0984e5SSebastian Reichel break; 2979*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_AVG: 2980*8c0984e5SSebastian Reichel /* 2981*8c0984e5SSebastian Reichel * This property is used to indicate when CV mode is entered 2982*8c0984e5SSebastian Reichel * for the AC charger 2983*8c0984e5SSebastian Reichel */ 2984*8c0984e5SSebastian Reichel di->ac.cv_active = ab8500_charger_ac_cv(di); 2985*8c0984e5SSebastian Reichel val->intval = di->ac.cv_active; 2986*8c0984e5SSebastian Reichel break; 2987*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CURRENT_NOW: 2988*8c0984e5SSebastian Reichel ret = ab8500_charger_get_ac_current(di); 2989*8c0984e5SSebastian Reichel if (ret >= 0) 2990*8c0984e5SSebastian Reichel di->ac.charger_current = ret; 2991*8c0984e5SSebastian Reichel val->intval = di->ac.charger_current * 1000; 2992*8c0984e5SSebastian Reichel break; 2993*8c0984e5SSebastian Reichel default: 2994*8c0984e5SSebastian Reichel return -EINVAL; 2995*8c0984e5SSebastian Reichel } 2996*8c0984e5SSebastian Reichel return 0; 2997*8c0984e5SSebastian Reichel } 2998*8c0984e5SSebastian Reichel 2999*8c0984e5SSebastian Reichel /** 3000*8c0984e5SSebastian Reichel * ab8500_charger_usb_get_property() - get the usb properties 3001*8c0984e5SSebastian Reichel * @psy: pointer to the power_supply structure 3002*8c0984e5SSebastian Reichel * @psp: pointer to the power_supply_property structure 3003*8c0984e5SSebastian Reichel * @val: pointer to the power_supply_propval union 3004*8c0984e5SSebastian Reichel * 3005*8c0984e5SSebastian Reichel * This function gets called when an application tries to get the usb 3006*8c0984e5SSebastian Reichel * properties by reading the sysfs files. 3007*8c0984e5SSebastian Reichel * USB properties are online, present and voltage. 3008*8c0984e5SSebastian Reichel * online: usb charging is in progress or not 3009*8c0984e5SSebastian Reichel * present: presence of the usb 3010*8c0984e5SSebastian Reichel * voltage: vbus voltage 3011*8c0984e5SSebastian Reichel * Returns error code in case of failure else 0(on success) 3012*8c0984e5SSebastian Reichel */ 3013*8c0984e5SSebastian Reichel static int ab8500_charger_usb_get_property(struct power_supply *psy, 3014*8c0984e5SSebastian Reichel enum power_supply_property psp, 3015*8c0984e5SSebastian Reichel union power_supply_propval *val) 3016*8c0984e5SSebastian Reichel { 3017*8c0984e5SSebastian Reichel struct ab8500_charger *di; 3018*8c0984e5SSebastian Reichel int ret; 3019*8c0984e5SSebastian Reichel 3020*8c0984e5SSebastian Reichel di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy)); 3021*8c0984e5SSebastian Reichel 3022*8c0984e5SSebastian Reichel switch (psp) { 3023*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_HEALTH: 3024*8c0984e5SSebastian Reichel if (di->flags.usbchargernotok) 3025*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 3026*8c0984e5SSebastian Reichel else if (di->ac.wd_expired || di->usb.wd_expired) 3027*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_DEAD; 3028*8c0984e5SSebastian Reichel else if (di->flags.usb_thermal_prot) 3029*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 3030*8c0984e5SSebastian Reichel else if (di->flags.vbus_ovv) 3031*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 3032*8c0984e5SSebastian Reichel else 3033*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_GOOD; 3034*8c0984e5SSebastian Reichel break; 3035*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_ONLINE: 3036*8c0984e5SSebastian Reichel val->intval = di->usb.charger_online; 3037*8c0984e5SSebastian Reichel break; 3038*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_PRESENT: 3039*8c0984e5SSebastian Reichel val->intval = di->usb.charger_connected; 3040*8c0984e5SSebastian Reichel break; 3041*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_NOW: 3042*8c0984e5SSebastian Reichel ret = ab8500_charger_get_vbus_voltage(di); 3043*8c0984e5SSebastian Reichel if (ret >= 0) 3044*8c0984e5SSebastian Reichel di->usb.charger_voltage = ret; 3045*8c0984e5SSebastian Reichel val->intval = di->usb.charger_voltage * 1000; 3046*8c0984e5SSebastian Reichel break; 3047*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_VOLTAGE_AVG: 3048*8c0984e5SSebastian Reichel /* 3049*8c0984e5SSebastian Reichel * This property is used to indicate when CV mode is entered 3050*8c0984e5SSebastian Reichel * for the USB charger 3051*8c0984e5SSebastian Reichel */ 3052*8c0984e5SSebastian Reichel di->usb.cv_active = ab8500_charger_usb_cv(di); 3053*8c0984e5SSebastian Reichel val->intval = di->usb.cv_active; 3054*8c0984e5SSebastian Reichel break; 3055*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CURRENT_NOW: 3056*8c0984e5SSebastian Reichel ret = ab8500_charger_get_usb_current(di); 3057*8c0984e5SSebastian Reichel if (ret >= 0) 3058*8c0984e5SSebastian Reichel di->usb.charger_current = ret; 3059*8c0984e5SSebastian Reichel val->intval = di->usb.charger_current * 1000; 3060*8c0984e5SSebastian Reichel break; 3061*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CURRENT_AVG: 3062*8c0984e5SSebastian Reichel /* 3063*8c0984e5SSebastian Reichel * This property is used to indicate when VBUS has collapsed 3064*8c0984e5SSebastian Reichel * due to too high output current from the USB charger 3065*8c0984e5SSebastian Reichel */ 3066*8c0984e5SSebastian Reichel if (di->flags.vbus_collapse) 3067*8c0984e5SSebastian Reichel val->intval = 1; 3068*8c0984e5SSebastian Reichel else 3069*8c0984e5SSebastian Reichel val->intval = 0; 3070*8c0984e5SSebastian Reichel break; 3071*8c0984e5SSebastian Reichel default: 3072*8c0984e5SSebastian Reichel return -EINVAL; 3073*8c0984e5SSebastian Reichel } 3074*8c0984e5SSebastian Reichel return 0; 3075*8c0984e5SSebastian Reichel } 3076*8c0984e5SSebastian Reichel 3077*8c0984e5SSebastian Reichel /** 3078*8c0984e5SSebastian Reichel * ab8500_charger_init_hw_registers() - Set up charger related registers 3079*8c0984e5SSebastian Reichel * @di: pointer to the ab8500_charger structure 3080*8c0984e5SSebastian Reichel * 3081*8c0984e5SSebastian Reichel * Set up charger OVV, watchdog and maximum voltage registers as well as 3082*8c0984e5SSebastian Reichel * charging of the backup battery 3083*8c0984e5SSebastian Reichel */ 3084*8c0984e5SSebastian Reichel static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) 3085*8c0984e5SSebastian Reichel { 3086*8c0984e5SSebastian Reichel int ret = 0; 3087*8c0984e5SSebastian Reichel u8 bup_vch_range = 0, vbup33_vrtcn = 0; 3088*8c0984e5SSebastian Reichel 3089*8c0984e5SSebastian Reichel /* Setup maximum charger current and voltage for ABB cut2.0 */ 3090*8c0984e5SSebastian Reichel if (!is_ab8500_1p1_or_earlier(di->parent)) { 3091*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3092*8c0984e5SSebastian Reichel AB8500_CHARGER, 3093*8c0984e5SSebastian Reichel AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6); 3094*8c0984e5SSebastian Reichel if (ret) { 3095*8c0984e5SSebastian Reichel dev_err(di->dev, 3096*8c0984e5SSebastian Reichel "failed to set CH_VOLT_LVL_MAX_REG\n"); 3097*8c0984e5SSebastian Reichel goto out; 3098*8c0984e5SSebastian Reichel } 3099*8c0984e5SSebastian Reichel 3100*8c0984e5SSebastian Reichel if (is_ab8540(di->parent)) 3101*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3102*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG, 3103*8c0984e5SSebastian Reichel CH_OP_CUR_LVL_2P); 3104*8c0984e5SSebastian Reichel else 3105*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3106*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG, 3107*8c0984e5SSebastian Reichel CH_OP_CUR_LVL_1P6); 3108*8c0984e5SSebastian Reichel if (ret) { 3109*8c0984e5SSebastian Reichel dev_err(di->dev, 3110*8c0984e5SSebastian Reichel "failed to set CH_OPT_CRNTLVL_MAX_REG\n"); 3111*8c0984e5SSebastian Reichel goto out; 3112*8c0984e5SSebastian Reichel } 3113*8c0984e5SSebastian Reichel } 3114*8c0984e5SSebastian Reichel 3115*8c0984e5SSebastian Reichel if (is_ab9540_2p0(di->parent) || is_ab9540_3p0(di->parent) 3116*8c0984e5SSebastian Reichel || is_ab8505_2p0(di->parent) || is_ab8540(di->parent)) 3117*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 3118*8c0984e5SSebastian Reichel AB8500_CHARGER, 3119*8c0984e5SSebastian Reichel AB8500_USBCH_CTRL2_REG, 3120*8c0984e5SSebastian Reichel VBUS_AUTO_IN_CURR_LIM_ENA, 3121*8c0984e5SSebastian Reichel VBUS_AUTO_IN_CURR_LIM_ENA); 3122*8c0984e5SSebastian Reichel else 3123*8c0984e5SSebastian Reichel /* 3124*8c0984e5SSebastian Reichel * VBUS OVV set to 6.3V and enable automatic current limitation 3125*8c0984e5SSebastian Reichel */ 3126*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3127*8c0984e5SSebastian Reichel AB8500_CHARGER, 3128*8c0984e5SSebastian Reichel AB8500_USBCH_CTRL2_REG, 3129*8c0984e5SSebastian Reichel VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA); 3130*8c0984e5SSebastian Reichel if (ret) { 3131*8c0984e5SSebastian Reichel dev_err(di->dev, 3132*8c0984e5SSebastian Reichel "failed to set automatic current limitation\n"); 3133*8c0984e5SSebastian Reichel goto out; 3134*8c0984e5SSebastian Reichel } 3135*8c0984e5SSebastian Reichel 3136*8c0984e5SSebastian Reichel /* Enable main watchdog in OTP */ 3137*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3138*8c0984e5SSebastian Reichel AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD); 3139*8c0984e5SSebastian Reichel if (ret) { 3140*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to enable main WD in OTP\n"); 3141*8c0984e5SSebastian Reichel goto out; 3142*8c0984e5SSebastian Reichel } 3143*8c0984e5SSebastian Reichel 3144*8c0984e5SSebastian Reichel /* Enable main watchdog */ 3145*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3146*8c0984e5SSebastian Reichel AB8500_SYS_CTRL2_BLOCK, 3147*8c0984e5SSebastian Reichel AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA); 3148*8c0984e5SSebastian Reichel if (ret) { 3149*8c0984e5SSebastian Reichel dev_err(di->dev, "faile to enable main watchdog\n"); 3150*8c0984e5SSebastian Reichel goto out; 3151*8c0984e5SSebastian Reichel } 3152*8c0984e5SSebastian Reichel 3153*8c0984e5SSebastian Reichel /* 3154*8c0984e5SSebastian Reichel * Due to internal synchronisation, Enable and Kick watchdog bits 3155*8c0984e5SSebastian Reichel * cannot be enabled in a single write. 3156*8c0984e5SSebastian Reichel * A minimum delay of 2*32 kHz period (62.5µs) must be inserted 3157*8c0984e5SSebastian Reichel * between writing Enable then Kick bits. 3158*8c0984e5SSebastian Reichel */ 3159*8c0984e5SSebastian Reichel udelay(63); 3160*8c0984e5SSebastian Reichel 3161*8c0984e5SSebastian Reichel /* Kick main watchdog */ 3162*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3163*8c0984e5SSebastian Reichel AB8500_SYS_CTRL2_BLOCK, 3164*8c0984e5SSebastian Reichel AB8500_MAIN_WDOG_CTRL_REG, 3165*8c0984e5SSebastian Reichel (MAIN_WDOG_ENA | MAIN_WDOG_KICK)); 3166*8c0984e5SSebastian Reichel if (ret) { 3167*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to kick main watchdog\n"); 3168*8c0984e5SSebastian Reichel goto out; 3169*8c0984e5SSebastian Reichel } 3170*8c0984e5SSebastian Reichel 3171*8c0984e5SSebastian Reichel /* Disable main watchdog */ 3172*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3173*8c0984e5SSebastian Reichel AB8500_SYS_CTRL2_BLOCK, 3174*8c0984e5SSebastian Reichel AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS); 3175*8c0984e5SSebastian Reichel if (ret) { 3176*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to disable main watchdog\n"); 3177*8c0984e5SSebastian Reichel goto out; 3178*8c0984e5SSebastian Reichel } 3179*8c0984e5SSebastian Reichel 3180*8c0984e5SSebastian Reichel /* Set watchdog timeout */ 3181*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 3182*8c0984e5SSebastian Reichel AB8500_CH_WD_TIMER_REG, WD_TIMER); 3183*8c0984e5SSebastian Reichel if (ret) { 3184*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to set charger watchdog timeout\n"); 3185*8c0984e5SSebastian Reichel goto out; 3186*8c0984e5SSebastian Reichel } 3187*8c0984e5SSebastian Reichel 3188*8c0984e5SSebastian Reichel ret = ab8500_charger_led_en(di, false); 3189*8c0984e5SSebastian Reichel if (ret < 0) { 3190*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to disable LED\n"); 3191*8c0984e5SSebastian Reichel goto out; 3192*8c0984e5SSebastian Reichel } 3193*8c0984e5SSebastian Reichel 3194*8c0984e5SSebastian Reichel /* Backup battery voltage and current */ 3195*8c0984e5SSebastian Reichel if (di->bm->bkup_bat_v > BUP_VCH_SEL_3P1V) 3196*8c0984e5SSebastian Reichel bup_vch_range = BUP_VCH_RANGE; 3197*8c0984e5SSebastian Reichel if (di->bm->bkup_bat_v == BUP_VCH_SEL_3P3V) 3198*8c0984e5SSebastian Reichel vbup33_vrtcn = VBUP33_VRTCN; 3199*8c0984e5SSebastian Reichel 3200*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3201*8c0984e5SSebastian Reichel AB8500_RTC, 3202*8c0984e5SSebastian Reichel AB8500_RTC_BACKUP_CHG_REG, 3203*8c0984e5SSebastian Reichel (di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i); 3204*8c0984e5SSebastian Reichel if (ret) { 3205*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to setup backup battery charging\n"); 3206*8c0984e5SSebastian Reichel goto out; 3207*8c0984e5SSebastian Reichel } 3208*8c0984e5SSebastian Reichel if (is_ab8540(di->parent)) { 3209*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, 3210*8c0984e5SSebastian Reichel AB8500_RTC, 3211*8c0984e5SSebastian Reichel AB8500_RTC_CTRL1_REG, 3212*8c0984e5SSebastian Reichel bup_vch_range | vbup33_vrtcn); 3213*8c0984e5SSebastian Reichel if (ret) { 3214*8c0984e5SSebastian Reichel dev_err(di->dev, 3215*8c0984e5SSebastian Reichel "failed to setup backup battery charging\n"); 3216*8c0984e5SSebastian Reichel goto out; 3217*8c0984e5SSebastian Reichel } 3218*8c0984e5SSebastian Reichel } 3219*8c0984e5SSebastian Reichel 3220*8c0984e5SSebastian Reichel /* Enable backup battery charging */ 3221*8c0984e5SSebastian Reichel abx500_mask_and_set_register_interruptible(di->dev, 3222*8c0984e5SSebastian Reichel AB8500_RTC, AB8500_RTC_CTRL_REG, 3223*8c0984e5SSebastian Reichel RTC_BUP_CH_ENA, RTC_BUP_CH_ENA); 3224*8c0984e5SSebastian Reichel if (ret < 0) 3225*8c0984e5SSebastian Reichel dev_err(di->dev, "%s mask and set failed\n", __func__); 3226*8c0984e5SSebastian Reichel 3227*8c0984e5SSebastian Reichel if (is_ab8540(di->parent)) { 3228*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 3229*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8540_USB_PP_MODE_REG, 3230*8c0984e5SSebastian Reichel BUS_VSYS_VOL_SELECT_MASK, BUS_VSYS_VOL_SELECT_3P6V); 3231*8c0984e5SSebastian Reichel if (ret) { 3232*8c0984e5SSebastian Reichel dev_err(di->dev, 3233*8c0984e5SSebastian Reichel "failed to setup usb power path vsys voltage\n"); 3234*8c0984e5SSebastian Reichel goto out; 3235*8c0984e5SSebastian Reichel } 3236*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 3237*8c0984e5SSebastian Reichel AB8500_CHARGER, AB8540_USB_PP_CHR_REG, 3238*8c0984e5SSebastian Reichel BUS_PP_PRECHG_CURRENT_MASK, 0); 3239*8c0984e5SSebastian Reichel if (ret) { 3240*8c0984e5SSebastian Reichel dev_err(di->dev, 3241*8c0984e5SSebastian Reichel "failed to setup usb power path prechage current\n"); 3242*8c0984e5SSebastian Reichel goto out; 3243*8c0984e5SSebastian Reichel } 3244*8c0984e5SSebastian Reichel } 3245*8c0984e5SSebastian Reichel 3246*8c0984e5SSebastian Reichel out: 3247*8c0984e5SSebastian Reichel return ret; 3248*8c0984e5SSebastian Reichel } 3249*8c0984e5SSebastian Reichel 3250*8c0984e5SSebastian Reichel /* 3251*8c0984e5SSebastian Reichel * ab8500 charger driver interrupts and their respective isr 3252*8c0984e5SSebastian Reichel */ 3253*8c0984e5SSebastian Reichel static struct ab8500_charger_interrupts ab8500_charger_irq[] = { 3254*8c0984e5SSebastian Reichel {"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler}, 3255*8c0984e5SSebastian Reichel {"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler}, 3256*8c0984e5SSebastian Reichel {"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler}, 3257*8c0984e5SSebastian Reichel {"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler}, 3258*8c0984e5SSebastian Reichel {"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler}, 3259*8c0984e5SSebastian Reichel {"VBUS_DET_F", ab8500_charger_vbusdetf_handler}, 3260*8c0984e5SSebastian Reichel {"VBUS_DET_R", ab8500_charger_vbusdetr_handler}, 3261*8c0984e5SSebastian Reichel {"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler}, 3262*8c0984e5SSebastian Reichel {"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler}, 3263*8c0984e5SSebastian Reichel {"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler}, 3264*8c0984e5SSebastian Reichel {"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler}, 3265*8c0984e5SSebastian Reichel {"VBUS_OVV", ab8500_charger_vbusovv_handler}, 3266*8c0984e5SSebastian Reichel {"CH_WD_EXP", ab8500_charger_chwdexp_handler}, 3267*8c0984e5SSebastian Reichel {"VBUS_CH_DROP_END", ab8500_charger_vbuschdropend_handler}, 3268*8c0984e5SSebastian Reichel }; 3269*8c0984e5SSebastian Reichel 3270*8c0984e5SSebastian Reichel static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, 3271*8c0984e5SSebastian Reichel unsigned long event, void *power) 3272*8c0984e5SSebastian Reichel { 3273*8c0984e5SSebastian Reichel struct ab8500_charger *di = 3274*8c0984e5SSebastian Reichel container_of(nb, struct ab8500_charger, nb); 3275*8c0984e5SSebastian Reichel enum ab8500_usb_state bm_usb_state; 3276*8c0984e5SSebastian Reichel unsigned mA = *((unsigned *)power); 3277*8c0984e5SSebastian Reichel 3278*8c0984e5SSebastian Reichel if (!di) 3279*8c0984e5SSebastian Reichel return NOTIFY_DONE; 3280*8c0984e5SSebastian Reichel 3281*8c0984e5SSebastian Reichel if (event != USB_EVENT_VBUS) { 3282*8c0984e5SSebastian Reichel dev_dbg(di->dev, "not a standard host, returning\n"); 3283*8c0984e5SSebastian Reichel return NOTIFY_DONE; 3284*8c0984e5SSebastian Reichel } 3285*8c0984e5SSebastian Reichel 3286*8c0984e5SSebastian Reichel /* TODO: State is fabricate here. See if charger really needs USB 3287*8c0984e5SSebastian Reichel * state or if mA is enough 3288*8c0984e5SSebastian Reichel */ 3289*8c0984e5SSebastian Reichel if ((di->usb_state.usb_current == 2) && (mA > 2)) 3290*8c0984e5SSebastian Reichel bm_usb_state = AB8500_BM_USB_STATE_RESUME; 3291*8c0984e5SSebastian Reichel else if (mA == 0) 3292*8c0984e5SSebastian Reichel bm_usb_state = AB8500_BM_USB_STATE_RESET_HS; 3293*8c0984e5SSebastian Reichel else if (mA == 2) 3294*8c0984e5SSebastian Reichel bm_usb_state = AB8500_BM_USB_STATE_SUSPEND; 3295*8c0984e5SSebastian Reichel else if (mA >= 8) /* 8, 100, 500 */ 3296*8c0984e5SSebastian Reichel bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED; 3297*8c0984e5SSebastian Reichel else /* Should never occur */ 3298*8c0984e5SSebastian Reichel bm_usb_state = AB8500_BM_USB_STATE_RESET_FS; 3299*8c0984e5SSebastian Reichel 3300*8c0984e5SSebastian Reichel dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", 3301*8c0984e5SSebastian Reichel __func__, bm_usb_state, mA); 3302*8c0984e5SSebastian Reichel 3303*8c0984e5SSebastian Reichel spin_lock(&di->usb_state.usb_lock); 3304*8c0984e5SSebastian Reichel di->usb_state.state_tmp = bm_usb_state; 3305*8c0984e5SSebastian Reichel di->usb_state.usb_current_tmp = mA; 3306*8c0984e5SSebastian Reichel spin_unlock(&di->usb_state.usb_lock); 3307*8c0984e5SSebastian Reichel 3308*8c0984e5SSebastian Reichel /* 3309*8c0984e5SSebastian Reichel * wait for some time until you get updates from the usb stack 3310*8c0984e5SSebastian Reichel * and negotiations are completed 3311*8c0984e5SSebastian Reichel */ 3312*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->usb_state_changed_work, HZ/2); 3313*8c0984e5SSebastian Reichel 3314*8c0984e5SSebastian Reichel return NOTIFY_OK; 3315*8c0984e5SSebastian Reichel } 3316*8c0984e5SSebastian Reichel 3317*8c0984e5SSebastian Reichel #if defined(CONFIG_PM) 3318*8c0984e5SSebastian Reichel static int ab8500_charger_resume(struct platform_device *pdev) 3319*8c0984e5SSebastian Reichel { 3320*8c0984e5SSebastian Reichel int ret; 3321*8c0984e5SSebastian Reichel struct ab8500_charger *di = platform_get_drvdata(pdev); 3322*8c0984e5SSebastian Reichel 3323*8c0984e5SSebastian Reichel /* 3324*8c0984e5SSebastian Reichel * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 3325*8c0984e5SSebastian Reichel * logic. That means we have to continously kick the charger 3326*8c0984e5SSebastian Reichel * watchdog even when no charger is connected. This is only 3327*8c0984e5SSebastian Reichel * valid once the AC charger has been enabled. This is 3328*8c0984e5SSebastian Reichel * a bug that is not handled by the algorithm and the 3329*8c0984e5SSebastian Reichel * watchdog have to be kicked by the charger driver 3330*8c0984e5SSebastian Reichel * when the AC charger is disabled 3331*8c0984e5SSebastian Reichel */ 3332*8c0984e5SSebastian Reichel if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) { 3333*8c0984e5SSebastian Reichel ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 3334*8c0984e5SSebastian Reichel AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 3335*8c0984e5SSebastian Reichel if (ret) 3336*8c0984e5SSebastian Reichel dev_err(di->dev, "Failed to kick WD!\n"); 3337*8c0984e5SSebastian Reichel 3338*8c0984e5SSebastian Reichel /* If not already pending start a new timer */ 3339*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->kick_wd_work, 3340*8c0984e5SSebastian Reichel round_jiffies(WD_KICK_INTERVAL)); 3341*8c0984e5SSebastian Reichel } 3342*8c0984e5SSebastian Reichel 3343*8c0984e5SSebastian Reichel /* If we still have a HW failure, schedule a new check */ 3344*8c0984e5SSebastian Reichel if (di->flags.mainextchnotok || di->flags.vbus_ovv) { 3345*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 3346*8c0984e5SSebastian Reichel &di->check_hw_failure_work, 0); 3347*8c0984e5SSebastian Reichel } 3348*8c0984e5SSebastian Reichel 3349*8c0984e5SSebastian Reichel if (di->flags.vbus_drop_end) 3350*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 0); 3351*8c0984e5SSebastian Reichel 3352*8c0984e5SSebastian Reichel return 0; 3353*8c0984e5SSebastian Reichel } 3354*8c0984e5SSebastian Reichel 3355*8c0984e5SSebastian Reichel static int ab8500_charger_suspend(struct platform_device *pdev, 3356*8c0984e5SSebastian Reichel pm_message_t state) 3357*8c0984e5SSebastian Reichel { 3358*8c0984e5SSebastian Reichel struct ab8500_charger *di = platform_get_drvdata(pdev); 3359*8c0984e5SSebastian Reichel 3360*8c0984e5SSebastian Reichel /* Cancel any pending jobs */ 3361*8c0984e5SSebastian Reichel cancel_delayed_work(&di->check_hw_failure_work); 3362*8c0984e5SSebastian Reichel cancel_delayed_work(&di->vbus_drop_end_work); 3363*8c0984e5SSebastian Reichel 3364*8c0984e5SSebastian Reichel flush_delayed_work(&di->attach_work); 3365*8c0984e5SSebastian Reichel flush_delayed_work(&di->usb_charger_attached_work); 3366*8c0984e5SSebastian Reichel flush_delayed_work(&di->ac_charger_attached_work); 3367*8c0984e5SSebastian Reichel flush_delayed_work(&di->check_usbchgnotok_work); 3368*8c0984e5SSebastian Reichel flush_delayed_work(&di->check_vbat_work); 3369*8c0984e5SSebastian Reichel flush_delayed_work(&di->kick_wd_work); 3370*8c0984e5SSebastian Reichel 3371*8c0984e5SSebastian Reichel flush_work(&di->usb_link_status_work); 3372*8c0984e5SSebastian Reichel flush_work(&di->ac_work); 3373*8c0984e5SSebastian Reichel flush_work(&di->detect_usb_type_work); 3374*8c0984e5SSebastian Reichel 3375*8c0984e5SSebastian Reichel if (atomic_read(&di->current_stepping_sessions)) 3376*8c0984e5SSebastian Reichel return -EAGAIN; 3377*8c0984e5SSebastian Reichel 3378*8c0984e5SSebastian Reichel return 0; 3379*8c0984e5SSebastian Reichel } 3380*8c0984e5SSebastian Reichel #else 3381*8c0984e5SSebastian Reichel #define ab8500_charger_suspend NULL 3382*8c0984e5SSebastian Reichel #define ab8500_charger_resume NULL 3383*8c0984e5SSebastian Reichel #endif 3384*8c0984e5SSebastian Reichel 3385*8c0984e5SSebastian Reichel static struct notifier_block charger_nb = { 3386*8c0984e5SSebastian Reichel .notifier_call = ab8500_external_charger_prepare, 3387*8c0984e5SSebastian Reichel }; 3388*8c0984e5SSebastian Reichel 3389*8c0984e5SSebastian Reichel static int ab8500_charger_remove(struct platform_device *pdev) 3390*8c0984e5SSebastian Reichel { 3391*8c0984e5SSebastian Reichel struct ab8500_charger *di = platform_get_drvdata(pdev); 3392*8c0984e5SSebastian Reichel int i, irq, ret; 3393*8c0984e5SSebastian Reichel 3394*8c0984e5SSebastian Reichel /* Disable AC charging */ 3395*8c0984e5SSebastian Reichel ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); 3396*8c0984e5SSebastian Reichel 3397*8c0984e5SSebastian Reichel /* Disable USB charging */ 3398*8c0984e5SSebastian Reichel ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); 3399*8c0984e5SSebastian Reichel 3400*8c0984e5SSebastian Reichel /* Disable interrupts */ 3401*8c0984e5SSebastian Reichel for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 3402*8c0984e5SSebastian Reichel irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 3403*8c0984e5SSebastian Reichel free_irq(irq, di); 3404*8c0984e5SSebastian Reichel } 3405*8c0984e5SSebastian Reichel 3406*8c0984e5SSebastian Reichel /* Backup battery voltage and current disable */ 3407*8c0984e5SSebastian Reichel ret = abx500_mask_and_set_register_interruptible(di->dev, 3408*8c0984e5SSebastian Reichel AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); 3409*8c0984e5SSebastian Reichel if (ret < 0) 3410*8c0984e5SSebastian Reichel dev_err(di->dev, "%s mask and set failed\n", __func__); 3411*8c0984e5SSebastian Reichel 3412*8c0984e5SSebastian Reichel usb_unregister_notifier(di->usb_phy, &di->nb); 3413*8c0984e5SSebastian Reichel usb_put_phy(di->usb_phy); 3414*8c0984e5SSebastian Reichel 3415*8c0984e5SSebastian Reichel /* Delete the work queue */ 3416*8c0984e5SSebastian Reichel destroy_workqueue(di->charger_wq); 3417*8c0984e5SSebastian Reichel 3418*8c0984e5SSebastian Reichel /* Unregister external charger enable notifier */ 3419*8c0984e5SSebastian Reichel if (!di->ac_chg.enabled) 3420*8c0984e5SSebastian Reichel blocking_notifier_chain_unregister( 3421*8c0984e5SSebastian Reichel &charger_notifier_list, &charger_nb); 3422*8c0984e5SSebastian Reichel 3423*8c0984e5SSebastian Reichel flush_scheduled_work(); 3424*8c0984e5SSebastian Reichel if (di->usb_chg.enabled) 3425*8c0984e5SSebastian Reichel power_supply_unregister(di->usb_chg.psy); 3426*8c0984e5SSebastian Reichel 3427*8c0984e5SSebastian Reichel if (di->ac_chg.enabled && !di->ac_chg.external) 3428*8c0984e5SSebastian Reichel power_supply_unregister(di->ac_chg.psy); 3429*8c0984e5SSebastian Reichel 3430*8c0984e5SSebastian Reichel return 0; 3431*8c0984e5SSebastian Reichel } 3432*8c0984e5SSebastian Reichel 3433*8c0984e5SSebastian Reichel static char *supply_interface[] = { 3434*8c0984e5SSebastian Reichel "ab8500_chargalg", 3435*8c0984e5SSebastian Reichel "ab8500_fg", 3436*8c0984e5SSebastian Reichel "ab8500_btemp", 3437*8c0984e5SSebastian Reichel }; 3438*8c0984e5SSebastian Reichel 3439*8c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_ac_chg_desc = { 3440*8c0984e5SSebastian Reichel .name = "ab8500_ac", 3441*8c0984e5SSebastian Reichel .type = POWER_SUPPLY_TYPE_MAINS, 3442*8c0984e5SSebastian Reichel .properties = ab8500_charger_ac_props, 3443*8c0984e5SSebastian Reichel .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), 3444*8c0984e5SSebastian Reichel .get_property = ab8500_charger_ac_get_property, 3445*8c0984e5SSebastian Reichel }; 3446*8c0984e5SSebastian Reichel 3447*8c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_usb_chg_desc = { 3448*8c0984e5SSebastian Reichel .name = "ab8500_usb", 3449*8c0984e5SSebastian Reichel .type = POWER_SUPPLY_TYPE_USB, 3450*8c0984e5SSebastian Reichel .properties = ab8500_charger_usb_props, 3451*8c0984e5SSebastian Reichel .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), 3452*8c0984e5SSebastian Reichel .get_property = ab8500_charger_usb_get_property, 3453*8c0984e5SSebastian Reichel }; 3454*8c0984e5SSebastian Reichel 3455*8c0984e5SSebastian Reichel static int ab8500_charger_probe(struct platform_device *pdev) 3456*8c0984e5SSebastian Reichel { 3457*8c0984e5SSebastian Reichel struct device_node *np = pdev->dev.of_node; 3458*8c0984e5SSebastian Reichel struct abx500_bm_data *plat = pdev->dev.platform_data; 3459*8c0984e5SSebastian Reichel struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; 3460*8c0984e5SSebastian Reichel struct ab8500_charger *di; 3461*8c0984e5SSebastian Reichel int irq, i, charger_status, ret = 0, ch_stat; 3462*8c0984e5SSebastian Reichel 3463*8c0984e5SSebastian Reichel di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); 3464*8c0984e5SSebastian Reichel if (!di) { 3465*8c0984e5SSebastian Reichel dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); 3466*8c0984e5SSebastian Reichel return -ENOMEM; 3467*8c0984e5SSebastian Reichel } 3468*8c0984e5SSebastian Reichel 3469*8c0984e5SSebastian Reichel if (!plat) { 3470*8c0984e5SSebastian Reichel dev_err(&pdev->dev, "no battery management data supplied\n"); 3471*8c0984e5SSebastian Reichel return -EINVAL; 3472*8c0984e5SSebastian Reichel } 3473*8c0984e5SSebastian Reichel di->bm = plat; 3474*8c0984e5SSebastian Reichel 3475*8c0984e5SSebastian Reichel if (np) { 3476*8c0984e5SSebastian Reichel ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); 3477*8c0984e5SSebastian Reichel if (ret) { 3478*8c0984e5SSebastian Reichel dev_err(&pdev->dev, "failed to get battery information\n"); 3479*8c0984e5SSebastian Reichel return ret; 3480*8c0984e5SSebastian Reichel } 3481*8c0984e5SSebastian Reichel di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); 3482*8c0984e5SSebastian Reichel } else 3483*8c0984e5SSebastian Reichel di->autopower_cfg = false; 3484*8c0984e5SSebastian Reichel 3485*8c0984e5SSebastian Reichel /* get parent data */ 3486*8c0984e5SSebastian Reichel di->dev = &pdev->dev; 3487*8c0984e5SSebastian Reichel di->parent = dev_get_drvdata(pdev->dev.parent); 3488*8c0984e5SSebastian Reichel di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); 3489*8c0984e5SSebastian Reichel 3490*8c0984e5SSebastian Reichel /* initialize lock */ 3491*8c0984e5SSebastian Reichel spin_lock_init(&di->usb_state.usb_lock); 3492*8c0984e5SSebastian Reichel mutex_init(&di->usb_ipt_crnt_lock); 3493*8c0984e5SSebastian Reichel 3494*8c0984e5SSebastian Reichel di->autopower = false; 3495*8c0984e5SSebastian Reichel di->invalid_charger_detect_state = 0; 3496*8c0984e5SSebastian Reichel 3497*8c0984e5SSebastian Reichel /* AC and USB supply config */ 3498*8c0984e5SSebastian Reichel ac_psy_cfg.supplied_to = supply_interface; 3499*8c0984e5SSebastian Reichel ac_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); 3500*8c0984e5SSebastian Reichel ac_psy_cfg.drv_data = &di->ac_chg; 3501*8c0984e5SSebastian Reichel usb_psy_cfg.supplied_to = supply_interface; 3502*8c0984e5SSebastian Reichel usb_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); 3503*8c0984e5SSebastian Reichel usb_psy_cfg.drv_data = &di->usb_chg; 3504*8c0984e5SSebastian Reichel 3505*8c0984e5SSebastian Reichel /* AC supply */ 3506*8c0984e5SSebastian Reichel /* ux500_charger sub-class */ 3507*8c0984e5SSebastian Reichel di->ac_chg.ops.enable = &ab8500_charger_ac_en; 3508*8c0984e5SSebastian Reichel di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable; 3509*8c0984e5SSebastian Reichel di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 3510*8c0984e5SSebastian Reichel di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; 3511*8c0984e5SSebastian Reichel di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ 3512*8c0984e5SSebastian Reichel ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3513*8c0984e5SSebastian Reichel di->ac_chg.max_out_curr = 3514*8c0984e5SSebastian Reichel di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3515*8c0984e5SSebastian Reichel di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; 3516*8c0984e5SSebastian Reichel di->ac_chg.enabled = di->bm->ac_enabled; 3517*8c0984e5SSebastian Reichel di->ac_chg.external = false; 3518*8c0984e5SSebastian Reichel 3519*8c0984e5SSebastian Reichel /*notifier for external charger enabling*/ 3520*8c0984e5SSebastian Reichel if (!di->ac_chg.enabled) 3521*8c0984e5SSebastian Reichel blocking_notifier_chain_register( 3522*8c0984e5SSebastian Reichel &charger_notifier_list, &charger_nb); 3523*8c0984e5SSebastian Reichel 3524*8c0984e5SSebastian Reichel /* USB supply */ 3525*8c0984e5SSebastian Reichel /* ux500_charger sub-class */ 3526*8c0984e5SSebastian Reichel di->usb_chg.ops.enable = &ab8500_charger_usb_en; 3527*8c0984e5SSebastian Reichel di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable; 3528*8c0984e5SSebastian Reichel di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 3529*8c0984e5SSebastian Reichel di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; 3530*8c0984e5SSebastian Reichel di->usb_chg.ops.pp_enable = &ab8540_charger_power_path_enable; 3531*8c0984e5SSebastian Reichel di->usb_chg.ops.pre_chg_enable = &ab8540_charger_usb_pre_chg_enable; 3532*8c0984e5SSebastian Reichel di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ 3533*8c0984e5SSebastian Reichel ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3534*8c0984e5SSebastian Reichel di->usb_chg.max_out_curr = 3535*8c0984e5SSebastian Reichel di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3536*8c0984e5SSebastian Reichel di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; 3537*8c0984e5SSebastian Reichel di->usb_chg.enabled = di->bm->usb_enabled; 3538*8c0984e5SSebastian Reichel di->usb_chg.external = false; 3539*8c0984e5SSebastian Reichel di->usb_chg.power_path = di->bm->usb_power_path; 3540*8c0984e5SSebastian Reichel di->usb_state.usb_current = -1; 3541*8c0984e5SSebastian Reichel 3542*8c0984e5SSebastian Reichel /* Create a work queue for the charger */ 3543*8c0984e5SSebastian Reichel di->charger_wq = 3544*8c0984e5SSebastian Reichel create_singlethread_workqueue("ab8500_charger_wq"); 3545*8c0984e5SSebastian Reichel if (di->charger_wq == NULL) { 3546*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to create work queue\n"); 3547*8c0984e5SSebastian Reichel return -ENOMEM; 3548*8c0984e5SSebastian Reichel } 3549*8c0984e5SSebastian Reichel 3550*8c0984e5SSebastian Reichel mutex_init(&di->charger_attached_mutex); 3551*8c0984e5SSebastian Reichel 3552*8c0984e5SSebastian Reichel /* Init work for HW failure check */ 3553*8c0984e5SSebastian Reichel INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, 3554*8c0984e5SSebastian Reichel ab8500_charger_check_hw_failure_work); 3555*8c0984e5SSebastian Reichel INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, 3556*8c0984e5SSebastian Reichel ab8500_charger_check_usbchargernotok_work); 3557*8c0984e5SSebastian Reichel 3558*8c0984e5SSebastian Reichel INIT_DELAYED_WORK(&di->ac_charger_attached_work, 3559*8c0984e5SSebastian Reichel ab8500_charger_ac_attached_work); 3560*8c0984e5SSebastian Reichel INIT_DELAYED_WORK(&di->usb_charger_attached_work, 3561*8c0984e5SSebastian Reichel ab8500_charger_usb_attached_work); 3562*8c0984e5SSebastian Reichel 3563*8c0984e5SSebastian Reichel /* 3564*8c0984e5SSebastian Reichel * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 3565*8c0984e5SSebastian Reichel * logic. That means we have to continously kick the charger 3566*8c0984e5SSebastian Reichel * watchdog even when no charger is connected. This is only 3567*8c0984e5SSebastian Reichel * valid once the AC charger has been enabled. This is 3568*8c0984e5SSebastian Reichel * a bug that is not handled by the algorithm and the 3569*8c0984e5SSebastian Reichel * watchdog have to be kicked by the charger driver 3570*8c0984e5SSebastian Reichel * when the AC charger is disabled 3571*8c0984e5SSebastian Reichel */ 3572*8c0984e5SSebastian Reichel INIT_DEFERRABLE_WORK(&di->kick_wd_work, 3573*8c0984e5SSebastian Reichel ab8500_charger_kick_watchdog_work); 3574*8c0984e5SSebastian Reichel 3575*8c0984e5SSebastian Reichel INIT_DEFERRABLE_WORK(&di->check_vbat_work, 3576*8c0984e5SSebastian Reichel ab8500_charger_check_vbat_work); 3577*8c0984e5SSebastian Reichel 3578*8c0984e5SSebastian Reichel INIT_DELAYED_WORK(&di->attach_work, 3579*8c0984e5SSebastian Reichel ab8500_charger_usb_link_attach_work); 3580*8c0984e5SSebastian Reichel 3581*8c0984e5SSebastian Reichel INIT_DELAYED_WORK(&di->usb_state_changed_work, 3582*8c0984e5SSebastian Reichel ab8500_charger_usb_state_changed_work); 3583*8c0984e5SSebastian Reichel 3584*8c0984e5SSebastian Reichel INIT_DELAYED_WORK(&di->vbus_drop_end_work, 3585*8c0984e5SSebastian Reichel ab8500_charger_vbus_drop_end_work); 3586*8c0984e5SSebastian Reichel 3587*8c0984e5SSebastian Reichel /* Init work for charger detection */ 3588*8c0984e5SSebastian Reichel INIT_WORK(&di->usb_link_status_work, 3589*8c0984e5SSebastian Reichel ab8500_charger_usb_link_status_work); 3590*8c0984e5SSebastian Reichel INIT_WORK(&di->ac_work, ab8500_charger_ac_work); 3591*8c0984e5SSebastian Reichel INIT_WORK(&di->detect_usb_type_work, 3592*8c0984e5SSebastian Reichel ab8500_charger_detect_usb_type_work); 3593*8c0984e5SSebastian Reichel 3594*8c0984e5SSebastian Reichel /* Init work for checking HW status */ 3595*8c0984e5SSebastian Reichel INIT_WORK(&di->check_main_thermal_prot_work, 3596*8c0984e5SSebastian Reichel ab8500_charger_check_main_thermal_prot_work); 3597*8c0984e5SSebastian Reichel INIT_WORK(&di->check_usb_thermal_prot_work, 3598*8c0984e5SSebastian Reichel ab8500_charger_check_usb_thermal_prot_work); 3599*8c0984e5SSebastian Reichel 3600*8c0984e5SSebastian Reichel /* 3601*8c0984e5SSebastian Reichel * VDD ADC supply needs to be enabled from this driver when there 3602*8c0984e5SSebastian Reichel * is a charger connected to avoid erroneous BTEMP_HIGH/LOW 3603*8c0984e5SSebastian Reichel * interrupts during charging 3604*8c0984e5SSebastian Reichel */ 3605*8c0984e5SSebastian Reichel di->regu = devm_regulator_get(di->dev, "vddadc"); 3606*8c0984e5SSebastian Reichel if (IS_ERR(di->regu)) { 3607*8c0984e5SSebastian Reichel ret = PTR_ERR(di->regu); 3608*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to get vddadc regulator\n"); 3609*8c0984e5SSebastian Reichel goto free_charger_wq; 3610*8c0984e5SSebastian Reichel } 3611*8c0984e5SSebastian Reichel 3612*8c0984e5SSebastian Reichel 3613*8c0984e5SSebastian Reichel /* Initialize OVV, and other registers */ 3614*8c0984e5SSebastian Reichel ret = ab8500_charger_init_hw_registers(di); 3615*8c0984e5SSebastian Reichel if (ret) { 3616*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to initialize ABB registers\n"); 3617*8c0984e5SSebastian Reichel goto free_charger_wq; 3618*8c0984e5SSebastian Reichel } 3619*8c0984e5SSebastian Reichel 3620*8c0984e5SSebastian Reichel /* Register AC charger class */ 3621*8c0984e5SSebastian Reichel if (di->ac_chg.enabled) { 3622*8c0984e5SSebastian Reichel di->ac_chg.psy = power_supply_register(di->dev, 3623*8c0984e5SSebastian Reichel &ab8500_ac_chg_desc, 3624*8c0984e5SSebastian Reichel &ac_psy_cfg); 3625*8c0984e5SSebastian Reichel if (IS_ERR(di->ac_chg.psy)) { 3626*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to register AC charger\n"); 3627*8c0984e5SSebastian Reichel ret = PTR_ERR(di->ac_chg.psy); 3628*8c0984e5SSebastian Reichel goto free_charger_wq; 3629*8c0984e5SSebastian Reichel } 3630*8c0984e5SSebastian Reichel } 3631*8c0984e5SSebastian Reichel 3632*8c0984e5SSebastian Reichel /* Register USB charger class */ 3633*8c0984e5SSebastian Reichel if (di->usb_chg.enabled) { 3634*8c0984e5SSebastian Reichel di->usb_chg.psy = power_supply_register(di->dev, 3635*8c0984e5SSebastian Reichel &ab8500_usb_chg_desc, 3636*8c0984e5SSebastian Reichel &usb_psy_cfg); 3637*8c0984e5SSebastian Reichel if (IS_ERR(di->usb_chg.psy)) { 3638*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to register USB charger\n"); 3639*8c0984e5SSebastian Reichel ret = PTR_ERR(di->usb_chg.psy); 3640*8c0984e5SSebastian Reichel goto free_ac; 3641*8c0984e5SSebastian Reichel } 3642*8c0984e5SSebastian Reichel } 3643*8c0984e5SSebastian Reichel 3644*8c0984e5SSebastian Reichel di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); 3645*8c0984e5SSebastian Reichel if (IS_ERR_OR_NULL(di->usb_phy)) { 3646*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to get usb transceiver\n"); 3647*8c0984e5SSebastian Reichel ret = -EINVAL; 3648*8c0984e5SSebastian Reichel goto free_usb; 3649*8c0984e5SSebastian Reichel } 3650*8c0984e5SSebastian Reichel di->nb.notifier_call = ab8500_charger_usb_notifier_call; 3651*8c0984e5SSebastian Reichel ret = usb_register_notifier(di->usb_phy, &di->nb); 3652*8c0984e5SSebastian Reichel if (ret) { 3653*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to register usb notifier\n"); 3654*8c0984e5SSebastian Reichel goto put_usb_phy; 3655*8c0984e5SSebastian Reichel } 3656*8c0984e5SSebastian Reichel 3657*8c0984e5SSebastian Reichel /* Identify the connected charger types during startup */ 3658*8c0984e5SSebastian Reichel charger_status = ab8500_charger_detect_chargers(di, true); 3659*8c0984e5SSebastian Reichel if (charger_status & AC_PW_CONN) { 3660*8c0984e5SSebastian Reichel di->ac.charger_connected = 1; 3661*8c0984e5SSebastian Reichel di->ac_conn = true; 3662*8c0984e5SSebastian Reichel ab8500_power_supply_changed(di, di->ac_chg.psy); 3663*8c0984e5SSebastian Reichel sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); 3664*8c0984e5SSebastian Reichel } 3665*8c0984e5SSebastian Reichel 3666*8c0984e5SSebastian Reichel if (charger_status & USB_PW_CONN) { 3667*8c0984e5SSebastian Reichel di->vbus_detected = true; 3668*8c0984e5SSebastian Reichel di->vbus_detected_start = true; 3669*8c0984e5SSebastian Reichel queue_work(di->charger_wq, 3670*8c0984e5SSebastian Reichel &di->detect_usb_type_work); 3671*8c0984e5SSebastian Reichel } 3672*8c0984e5SSebastian Reichel 3673*8c0984e5SSebastian Reichel /* Register interrupts */ 3674*8c0984e5SSebastian Reichel for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 3675*8c0984e5SSebastian Reichel irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 3676*8c0984e5SSebastian Reichel ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, 3677*8c0984e5SSebastian Reichel IRQF_SHARED | IRQF_NO_SUSPEND, 3678*8c0984e5SSebastian Reichel ab8500_charger_irq[i].name, di); 3679*8c0984e5SSebastian Reichel 3680*8c0984e5SSebastian Reichel if (ret != 0) { 3681*8c0984e5SSebastian Reichel dev_err(di->dev, "failed to request %s IRQ %d: %d\n" 3682*8c0984e5SSebastian Reichel , ab8500_charger_irq[i].name, irq, ret); 3683*8c0984e5SSebastian Reichel goto free_irq; 3684*8c0984e5SSebastian Reichel } 3685*8c0984e5SSebastian Reichel dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", 3686*8c0984e5SSebastian Reichel ab8500_charger_irq[i].name, irq, ret); 3687*8c0984e5SSebastian Reichel } 3688*8c0984e5SSebastian Reichel 3689*8c0984e5SSebastian Reichel platform_set_drvdata(pdev, di); 3690*8c0984e5SSebastian Reichel 3691*8c0984e5SSebastian Reichel mutex_lock(&di->charger_attached_mutex); 3692*8c0984e5SSebastian Reichel 3693*8c0984e5SSebastian Reichel ch_stat = ab8500_charger_detect_chargers(di, false); 3694*8c0984e5SSebastian Reichel 3695*8c0984e5SSebastian Reichel if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { 3696*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 3697*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 3698*8c0984e5SSebastian Reichel &di->ac_charger_attached_work, 3699*8c0984e5SSebastian Reichel HZ); 3700*8c0984e5SSebastian Reichel } 3701*8c0984e5SSebastian Reichel if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { 3702*8c0984e5SSebastian Reichel if (is_ab8500(di->parent)) 3703*8c0984e5SSebastian Reichel queue_delayed_work(di->charger_wq, 3704*8c0984e5SSebastian Reichel &di->usb_charger_attached_work, 3705*8c0984e5SSebastian Reichel HZ); 3706*8c0984e5SSebastian Reichel } 3707*8c0984e5SSebastian Reichel 3708*8c0984e5SSebastian Reichel mutex_unlock(&di->charger_attached_mutex); 3709*8c0984e5SSebastian Reichel 3710*8c0984e5SSebastian Reichel return ret; 3711*8c0984e5SSebastian Reichel 3712*8c0984e5SSebastian Reichel free_irq: 3713*8c0984e5SSebastian Reichel usb_unregister_notifier(di->usb_phy, &di->nb); 3714*8c0984e5SSebastian Reichel 3715*8c0984e5SSebastian Reichel /* We also have to free all successfully registered irqs */ 3716*8c0984e5SSebastian Reichel for (i = i - 1; i >= 0; i--) { 3717*8c0984e5SSebastian Reichel irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 3718*8c0984e5SSebastian Reichel free_irq(irq, di); 3719*8c0984e5SSebastian Reichel } 3720*8c0984e5SSebastian Reichel put_usb_phy: 3721*8c0984e5SSebastian Reichel usb_put_phy(di->usb_phy); 3722*8c0984e5SSebastian Reichel free_usb: 3723*8c0984e5SSebastian Reichel if (di->usb_chg.enabled) 3724*8c0984e5SSebastian Reichel power_supply_unregister(di->usb_chg.psy); 3725*8c0984e5SSebastian Reichel free_ac: 3726*8c0984e5SSebastian Reichel if (di->ac_chg.enabled) 3727*8c0984e5SSebastian Reichel power_supply_unregister(di->ac_chg.psy); 3728*8c0984e5SSebastian Reichel free_charger_wq: 3729*8c0984e5SSebastian Reichel destroy_workqueue(di->charger_wq); 3730*8c0984e5SSebastian Reichel return ret; 3731*8c0984e5SSebastian Reichel } 3732*8c0984e5SSebastian Reichel 3733*8c0984e5SSebastian Reichel static const struct of_device_id ab8500_charger_match[] = { 3734*8c0984e5SSebastian Reichel { .compatible = "stericsson,ab8500-charger", }, 3735*8c0984e5SSebastian Reichel { }, 3736*8c0984e5SSebastian Reichel }; 3737*8c0984e5SSebastian Reichel 3738*8c0984e5SSebastian Reichel static struct platform_driver ab8500_charger_driver = { 3739*8c0984e5SSebastian Reichel .probe = ab8500_charger_probe, 3740*8c0984e5SSebastian Reichel .remove = ab8500_charger_remove, 3741*8c0984e5SSebastian Reichel .suspend = ab8500_charger_suspend, 3742*8c0984e5SSebastian Reichel .resume = ab8500_charger_resume, 3743*8c0984e5SSebastian Reichel .driver = { 3744*8c0984e5SSebastian Reichel .name = "ab8500-charger", 3745*8c0984e5SSebastian Reichel .of_match_table = ab8500_charger_match, 3746*8c0984e5SSebastian Reichel }, 3747*8c0984e5SSebastian Reichel }; 3748*8c0984e5SSebastian Reichel 3749*8c0984e5SSebastian Reichel static int __init ab8500_charger_init(void) 3750*8c0984e5SSebastian Reichel { 3751*8c0984e5SSebastian Reichel return platform_driver_register(&ab8500_charger_driver); 3752*8c0984e5SSebastian Reichel } 3753*8c0984e5SSebastian Reichel 3754*8c0984e5SSebastian Reichel static void __exit ab8500_charger_exit(void) 3755*8c0984e5SSebastian Reichel { 3756*8c0984e5SSebastian Reichel platform_driver_unregister(&ab8500_charger_driver); 3757*8c0984e5SSebastian Reichel } 3758*8c0984e5SSebastian Reichel 3759*8c0984e5SSebastian Reichel subsys_initcall_sync(ab8500_charger_init); 3760*8c0984e5SSebastian Reichel module_exit(ab8500_charger_exit); 3761*8c0984e5SSebastian Reichel 3762*8c0984e5SSebastian Reichel MODULE_LICENSE("GPL v2"); 3763*8c0984e5SSebastian Reichel MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); 3764*8c0984e5SSebastian Reichel MODULE_ALIAS("platform:ab8500-charger"); 3765*8c0984e5SSebastian Reichel MODULE_DESCRIPTION("AB8500 charger management driver"); 3766