184edbeeab67c1575067335179513150115da367bArun Murthy/* 284edbeeab67c1575067335179513150115da367bArun Murthy * Copyright (C) ST-Ericsson SA 2012 384edbeeab67c1575067335179513150115da367bArun Murthy * 484edbeeab67c1575067335179513150115da367bArun Murthy * Charger driver for AB8500 584edbeeab67c1575067335179513150115da367bArun Murthy * 684edbeeab67c1575067335179513150115da367bArun Murthy * License Terms: GNU General Public License v2 784edbeeab67c1575067335179513150115da367bArun Murthy * Author: 884edbeeab67c1575067335179513150115da367bArun Murthy * Johan Palsson <johan.palsson@stericsson.com> 984edbeeab67c1575067335179513150115da367bArun Murthy * Karl Komierowski <karl.komierowski@stericsson.com> 1084edbeeab67c1575067335179513150115da367bArun Murthy * Arun R Murthy <arun.murthy@stericsson.com> 1184edbeeab67c1575067335179513150115da367bArun Murthy */ 1284edbeeab67c1575067335179513150115da367bArun Murthy 1384edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/init.h> 1484edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/module.h> 1584edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/device.h> 1684edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/interrupt.h> 1784edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/delay.h> 188891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#include <linux/notifier.h> 1984edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/slab.h> 2084edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/platform_device.h> 2184edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/power_supply.h> 2284edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/completion.h> 2384edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/regulator/consumer.h> 2484edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/err.h> 2584edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/workqueue.h> 2684edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/kobject.h> 274aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V#include <linux/of.h> 284aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V#include <linux/mfd/core.h> 2984edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500.h> 3084edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500.h> 3184edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500-bm.h> 3284edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500-gpadc.h> 3384edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ux500_chargalg.h> 3484edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/usb/otg.h> 35b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#include <linux/mutex.h> 3684edbeeab67c1575067335179513150115da367bArun Murthy 3784edbeeab67c1575067335179513150115da367bArun Murthy/* Charger constants */ 3884edbeeab67c1575067335179513150115da367bArun Murthy#define NO_PW_CONN 0 3984edbeeab67c1575067335179513150115da367bArun Murthy#define AC_PW_CONN 1 4084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_PW_CONN 2 4184edbeeab67c1575067335179513150115da367bArun Murthy 4284edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_ENA 0x01 4384edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_KICK 0x02 4484edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_DIS 0x00 4584edbeeab67c1575067335179513150115da367bArun Murthy#define CHARG_WD_KICK 0x01 4684edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_ENA 0x01 4784edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02 4884edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_ENA 0x01 4984edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CHG_NO_OVERSHOOT_ENA_N 0x02 5084edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_DET 0x01 5184edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_CV_ON 0x04 5284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_CV_ON 0x08 5384edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET_DBNC100 0x02 5484edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET_DBNC1 0x01 5584edbeeab67c1575067335179513150115da367bArun Murthy#define OTP_ENABLE_WD 0x01 564dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones#define DROP_COUNT_RESET 0x01 57b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper#define USB_CH_DET 0x01 5884edbeeab67c1575067335179513150115da367bArun Murthy 5984edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_INPUT_CURR_SHIFT 4 6084edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_IN_CURR_LIM_SHIFT 4 61861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones#define AB8540_VBUS_IN_CURR_LIM_SHIFT 2 6234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson#define AUTO_VBUS_IN_CURR_LIM_SHIFT 4 63861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones#define AB8540_AUTO_VBUS_IN_CURR_MASK 0x3F 64f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones#define VBUS_IN_CURR_LIM_RETRY_SET_TIME 30 /* seconds */ 6584edbeeab67c1575067335179513150115da367bArun Murthy 6684edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_ENA 0x01 6784edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_DIS 0x00 6884edbeeab67c1575067335179513150115da367bArun Murthy#define LED_IND_CUR_5MA 0x04 6984edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_DUTY_252_256 0xBF 7084edbeeab67c1575067335179513150115da367bArun Murthy 7184edbeeab67c1575067335179513150115da367bArun Murthy/* HW failure constants */ 7284edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_TH_PROT 0x02 7384edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_CH_NOK 0x08 7484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_TH_PROT 0x02 7584edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_OVV_TH 0x01 7684edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_NOK 0x01 7784edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET 0x80 7884edbeeab67c1575067335179513150115da367bArun Murthy 79b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define MAIN_CH_STATUS2_MAINCHGDROP 0x80 80b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define MAIN_CH_STATUS2_MAINCHARGERDETDBNC 0x40 81b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define USB_CH_VBUSDROP 0x40 82b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define USB_CH_VBUSDETDBNC 0x01 83b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 8484edbeeab67c1575067335179513150115da367bArun Murthy/* UsbLineStatus register bit masks */ 8584edbeeab67c1575067335179513150115da367bArun Murthy#define AB8500_USB_LINK_STATUS 0x78 86d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg#define AB8505_USB_LINK_STATUS 0xF8 8784edbeeab67c1575067335179513150115da367bArun Murthy#define AB8500_STD_HOST_SUSP 0x18 88861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones#define USB_LINK_STATUS_SHIFT 3 8984edbeeab67c1575067335179513150115da367bArun Murthy 9084edbeeab67c1575067335179513150115da367bArun Murthy/* Watchdog timeout constant */ 9184edbeeab67c1575067335179513150115da367bArun Murthy#define WD_TIMER 0x30 /* 4min */ 9284edbeeab67c1575067335179513150115da367bArun Murthy#define WD_KICK_INTERVAL (60 * HZ) 9384edbeeab67c1575067335179513150115da367bArun Murthy 9484edbeeab67c1575067335179513150115da367bArun Murthy/* Lowest charger voltage is 3.39V -> 0x4E */ 9584edbeeab67c1575067335179513150115da367bArun Murthy#define LOW_VOLT_REG 0x4E 9684edbeeab67c1575067335179513150115da367bArun Murthy 97f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/* Step up/down delay in us */ 98f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt#define STEP_UDELAY 1000 99f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt 100b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define CHARGER_STATUS_POLL 10 /* in ms */ 101b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 102e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy#define CHG_WD_INTERVAL (60 * HZ) 103e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy 104b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion#define AB8500_SW_CONTROL_FALLBACK 0x03 10534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson/* Wait for enumeration before charing in us */ 10634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson#define WAIT_ACA_RID_ENUMERATION (5 * 1000) 1078891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones/*External charger control*/ 1088891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#define AB8500_SYS_CHARGER_CONTROL_REG 0x52 1098891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#define EXTERNAL_CHARGER_DISABLE_REG_VAL 0x03 1108891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#define EXTERNAL_CHARGER_ENABLE_REG_VAL 0x07 111b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion 11284edbeeab67c1575067335179513150115da367bArun Murthy/* UsbLineStatus register - usb types */ 11384edbeeab67c1575067335179513150115da367bArun Murthyenum ab8500_charger_link_status { 11484edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_NOT_CONFIGURED, 11584edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_STD_HOST_NC, 11684edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_STD_HOST_C_NS, 11784edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_STD_HOST_C_S, 11884edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HOST_CHG_NM, 11984edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HOST_CHG_HS, 12084edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HOST_CHG_HS_CHIRP, 12184edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_DEDICATED_CHG, 12284edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_A, 12384edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_B, 12484edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_C_NM, 12584edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_C_HS, 12684edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_C_HS_CHIRP, 12784edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HM_IDGND, 12884edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_RESERVED, 12984edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_NOT_VALID_LINK, 13074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg USB_STAT_PHY_EN, 13174a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg USB_STAT_SUP_NO_IDGND_VBUS, 13274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg USB_STAT_SUP_IDGND_VBUS, 13374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg USB_STAT_CHARGER_LINE_1, 13474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg USB_STAT_CARKIT_1, 13574a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg USB_STAT_CARKIT_2, 13674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg USB_STAT_ACA_DOCK_CHARGER, 13784edbeeab67c1575067335179513150115da367bArun Murthy}; 13884edbeeab67c1575067335179513150115da367bArun Murthy 13984edbeeab67c1575067335179513150115da367bArun Murthyenum ab8500_usb_state { 14084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_RESET_HS, /* HighSpeed Reset */ 14184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_RESET_FS, /* FullSpeed/LowSpeed Reset */ 14284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_CONFIGURED, 14384edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_SUSPEND, 14484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_RESUME, 14584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_MAX, 14684edbeeab67c1575067335179513150115da367bArun Murthy}; 14784edbeeab67c1575067335179513150115da367bArun Murthy 14884edbeeab67c1575067335179513150115da367bArun Murthy/* VBUS input current limits supported in AB8500 in mA */ 14984edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P05 50 15084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P09 98 15184edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P19 193 15284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P29 290 15384edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P38 380 15484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P45 450 15584edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P5 500 15684edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P6 600 15784edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P7 700 15884edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P8 800 15984edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P9 900 16084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P0 1000 16184edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P1 1100 16284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P3 1300 16384edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P4 1400 16484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P5 1500 16584edbeeab67c1575067335179513150115da367bArun Murthy 16684edbeeab67c1575067335179513150115da367bArun Murthy#define VBAT_TRESH_IP_CUR_RED 3800 16784edbeeab67c1575067335179513150115da367bArun Murthy 16884edbeeab67c1575067335179513150115da367bArun Murthy#define to_ab8500_charger_usb_device_info(x) container_of((x), \ 16984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, usb_chg) 17084edbeeab67c1575067335179513150115da367bArun Murthy#define to_ab8500_charger_ac_device_info(x) container_of((x), \ 17184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, ac_chg) 17284edbeeab67c1575067335179513150115da367bArun Murthy 17384edbeeab67c1575067335179513150115da367bArun Murthy/** 17484edbeeab67c1575067335179513150115da367bArun Murthy * struct ab8500_charger_interrupts - ab8500 interupts 17584edbeeab67c1575067335179513150115da367bArun Murthy * @name: name of the interrupt 17684edbeeab67c1575067335179513150115da367bArun Murthy * @isr function pointer to the isr 17784edbeeab67c1575067335179513150115da367bArun Murthy */ 17884edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_interrupts { 17984edbeeab67c1575067335179513150115da367bArun Murthy char *name; 18084edbeeab67c1575067335179513150115da367bArun Murthy irqreturn_t (*isr)(int irq, void *data); 18184edbeeab67c1575067335179513150115da367bArun Murthy}; 18284edbeeab67c1575067335179513150115da367bArun Murthy 18384edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_info { 18484edbeeab67c1575067335179513150115da367bArun Murthy int charger_connected; 18584edbeeab67c1575067335179513150115da367bArun Murthy int charger_online; 18684edbeeab67c1575067335179513150115da367bArun Murthy int charger_voltage; 18784edbeeab67c1575067335179513150115da367bArun Murthy int cv_active; 18884edbeeab67c1575067335179513150115da367bArun Murthy bool wd_expired; 189a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg int charger_current; 19084edbeeab67c1575067335179513150115da367bArun Murthy}; 19184edbeeab67c1575067335179513150115da367bArun Murthy 19284edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_event_flags { 19384edbeeab67c1575067335179513150115da367bArun Murthy bool mainextchnotok; 19484edbeeab67c1575067335179513150115da367bArun Murthy bool main_thermal_prot; 19584edbeeab67c1575067335179513150115da367bArun Murthy bool usb_thermal_prot; 19684edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_ovv; 19784edbeeab67c1575067335179513150115da367bArun Murthy bool usbchargernotok; 19884edbeeab67c1575067335179513150115da367bArun Murthy bool chgwdexp; 19984edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_collapse; 20034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson bool vbus_drop_end; 20184edbeeab67c1575067335179513150115da367bArun Murthy}; 20284edbeeab67c1575067335179513150115da367bArun Murthy 20384edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_usb_state { 20484edbeeab67c1575067335179513150115da367bArun Murthy int usb_current; 20534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson int usb_current_tmp; 20684edbeeab67c1575067335179513150115da367bArun Murthy enum ab8500_usb_state state; 20734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson enum ab8500_usb_state state_tmp; 20884edbeeab67c1575067335179513150115da367bArun Murthy spinlock_t usb_lock; 20984edbeeab67c1575067335179513150115da367bArun Murthy}; 21084edbeeab67c1575067335179513150115da367bArun Murthy 211f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jonesstruct ab8500_charger_max_usb_in_curr { 212f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones int usb_type_max; 213f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones int set_max; 214f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones int calculated_max; 215f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones}; 216f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones 21784edbeeab67c1575067335179513150115da367bArun Murthy/** 21884edbeeab67c1575067335179513150115da367bArun Murthy * struct ab8500_charger - ab8500 Charger device information 21984edbeeab67c1575067335179513150115da367bArun Murthy * @dev: Pointer to the structure device 22084edbeeab67c1575067335179513150115da367bArun Murthy * @vbus_detected: VBUS detected 22184edbeeab67c1575067335179513150115da367bArun Murthy * @vbus_detected_start: 22284edbeeab67c1575067335179513150115da367bArun Murthy * VBUS detected during startup 22384edbeeab67c1575067335179513150115da367bArun Murthy * @ac_conn: This will be true when the AC charger has been plugged 22484edbeeab67c1575067335179513150115da367bArun Murthy * @vddadc_en_ac: Indicate if VDD ADC supply is enabled because AC 22584edbeeab67c1575067335179513150115da367bArun Murthy * charger is enabled 22684edbeeab67c1575067335179513150115da367bArun Murthy * @vddadc_en_usb: Indicate if VDD ADC supply is enabled because USB 22784edbeeab67c1575067335179513150115da367bArun Murthy * charger is enabled 22884edbeeab67c1575067335179513150115da367bArun Murthy * @vbat Battery voltage 22984edbeeab67c1575067335179513150115da367bArun Murthy * @old_vbat Previously measured battery voltage 2304b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper * @usb_device_is_unrecognised USB device is unrecognised by the hardware 23184edbeeab67c1575067335179513150115da367bArun Murthy * @autopower Indicate if we should have automatic pwron after pwrloss 2324aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V * @autopower_cfg platform specific power config support for "pwron after pwrloss" 233ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver * @invalid_charger_detect_state State when forcing AB to use invalid charger 23434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @is_aca_rid: Incicate if accessory is ACA type 23534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @current_stepping_sessions: 23634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * Counter for current stepping sessions 23784edbeeab67c1575067335179513150115da367bArun Murthy * @parent: Pointer to the struct ab8500 23884edbeeab67c1575067335179513150115da367bArun Murthy * @gpadc: Pointer to the struct gpadc 239b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones * @bm: Platform specific battery management information 24084edbeeab67c1575067335179513150115da367bArun Murthy * @flags: Structure for information about events triggered 24184edbeeab67c1575067335179513150115da367bArun Murthy * @usb_state: Structure for usb stack information 242f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * @max_usb_in_curr: Max USB charger input current 24384edbeeab67c1575067335179513150115da367bArun Murthy * @ac_chg: AC charger power supply 24484edbeeab67c1575067335179513150115da367bArun Murthy * @usb_chg: USB charger power supply 24584edbeeab67c1575067335179513150115da367bArun Murthy * @ac: Structure that holds the AC charger properties 24684edbeeab67c1575067335179513150115da367bArun Murthy * @usb: Structure that holds the USB charger properties 24784edbeeab67c1575067335179513150115da367bArun Murthy * @regu: Pointer to the struct regulator 24884edbeeab67c1575067335179513150115da367bArun Murthy * @charger_wq: Work queue for the IRQs and checking HW state 24934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @usb_ipt_crnt_lock: Lock to protect VBUS input current setting from mutuals 25034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @pm_lock: Lock to prevent system to suspend 25184edbeeab67c1575067335179513150115da367bArun Murthy * @check_vbat_work Work for checking vbat threshold to adjust vbus current 25284edbeeab67c1575067335179513150115da367bArun Murthy * @check_hw_failure_work: Work for checking HW state 25384edbeeab67c1575067335179513150115da367bArun Murthy * @check_usbchgnotok_work: Work for checking USB charger not ok status 25484edbeeab67c1575067335179513150115da367bArun Murthy * @kick_wd_work: Work for kicking the charger watchdog in case 25584edbeeab67c1575067335179513150115da367bArun Murthy * of ABB rev 1.* due to the watchog logic bug 256b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * @ac_charger_attached_work: Work for checking if AC charger is still 257b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * connected 258b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * @usb_charger_attached_work: Work for checking if USB charger is still 259b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * connected 26084edbeeab67c1575067335179513150115da367bArun Murthy * @ac_work: Work for checking AC charger connection 26184edbeeab67c1575067335179513150115da367bArun Murthy * @detect_usb_type_work: Work for detecting the USB type connected 26284edbeeab67c1575067335179513150115da367bArun Murthy * @usb_link_status_work: Work for checking the new USB link status 26384edbeeab67c1575067335179513150115da367bArun Murthy * @usb_state_changed_work: Work for checking USB state 26434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @attach_work: Work for detecting USB type 26534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @vbus_drop_end_work: Work for detecting VBUS drop end 26684edbeeab67c1575067335179513150115da367bArun Murthy * @check_main_thermal_prot_work: 26784edbeeab67c1575067335179513150115da367bArun Murthy * Work for checking Main thermal status 26884edbeeab67c1575067335179513150115da367bArun Murthy * @check_usb_thermal_prot_work: 26984edbeeab67c1575067335179513150115da367bArun Murthy * Work for checking USB thermal status 270b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * @charger_attached_mutex: For controlling the wakelock 27184edbeeab67c1575067335179513150115da367bArun Murthy */ 27284edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger { 27384edbeeab67c1575067335179513150115da367bArun Murthy struct device *dev; 27484edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_detected; 27584edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_detected_start; 27684edbeeab67c1575067335179513150115da367bArun Murthy bool ac_conn; 27784edbeeab67c1575067335179513150115da367bArun Murthy bool vddadc_en_ac; 27884edbeeab67c1575067335179513150115da367bArun Murthy bool vddadc_en_usb; 27984edbeeab67c1575067335179513150115da367bArun Murthy int vbat; 28084edbeeab67c1575067335179513150115da367bArun Murthy int old_vbat; 2814b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper bool usb_device_is_unrecognised; 28284edbeeab67c1575067335179513150115da367bArun Murthy bool autopower; 2834aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V bool autopower_cfg; 284ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver int invalid_charger_detect_state; 28534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson int is_aca_rid; 28634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson atomic_t current_stepping_sessions; 28784edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500 *parent; 28884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_gpadc *gpadc; 289b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones struct abx500_bm_data *bm; 29084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_event_flags flags; 29184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_usb_state usb_state; 292f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones struct ab8500_charger_max_usb_in_curr max_usb_in_curr; 29384edbeeab67c1575067335179513150115da367bArun Murthy struct ux500_charger ac_chg; 29484edbeeab67c1575067335179513150115da367bArun Murthy struct ux500_charger usb_chg; 29584edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_info ac; 29684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_info usb; 29784edbeeab67c1575067335179513150115da367bArun Murthy struct regulator *regu; 29884edbeeab67c1575067335179513150115da367bArun Murthy struct workqueue_struct *charger_wq; 29934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson struct mutex usb_ipt_crnt_lock; 30084edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work check_vbat_work; 30184edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work check_hw_failure_work; 30284edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work check_usbchgnotok_work; 30384edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work kick_wd_work; 30434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson struct delayed_work usb_state_changed_work; 3054b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper struct delayed_work attach_work; 306b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones struct delayed_work ac_charger_attached_work; 307b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones struct delayed_work usb_charger_attached_work; 30834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson struct delayed_work vbus_drop_end_work; 30984edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct ac_work; 31084edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct detect_usb_type_work; 31184edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct usb_link_status_work; 31284edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct check_main_thermal_prot_work; 31384edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct check_usb_thermal_prot_work; 314efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov struct usb_phy *usb_phy; 31584edbeeab67c1575067335179513150115da367bArun Murthy struct notifier_block nb; 316b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones struct mutex charger_attached_mutex; 31784edbeeab67c1575067335179513150115da367bArun Murthy}; 31884edbeeab67c1575067335179513150115da367bArun Murthy 31984edbeeab67c1575067335179513150115da367bArun Murthy/* AC properties */ 32084edbeeab67c1575067335179513150115da367bArun Murthystatic enum power_supply_property ab8500_charger_ac_props[] = { 32184edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_HEALTH, 32284edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_PRESENT, 32384edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_ONLINE, 32484edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_NOW, 32584edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_AVG, 32684edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_CURRENT_NOW, 32784edbeeab67c1575067335179513150115da367bArun Murthy}; 32884edbeeab67c1575067335179513150115da367bArun Murthy 32984edbeeab67c1575067335179513150115da367bArun Murthy/* USB properties */ 33084edbeeab67c1575067335179513150115da367bArun Murthystatic enum power_supply_property ab8500_charger_usb_props[] = { 33184edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_HEALTH, 33284edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_CURRENT_AVG, 33384edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_PRESENT, 33484edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_ONLINE, 33584edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_NOW, 33684edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_AVG, 33784edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_CURRENT_NOW, 33884edbeeab67c1575067335179513150115da367bArun Murthy}; 33984edbeeab67c1575067335179513150115da367bArun Murthy 340defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson/* 341defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson * Function for enabling and disabling sw fallback mode 342defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson * should always be disabled when no charger is connected. 34384edbeeab67c1575067335179513150115da367bArun Murthy */ 344defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakanssonstatic void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di, 345defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson bool fallback) 34684edbeeab67c1575067335179513150115da367bArun Murthy{ 347b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion u8 val; 34884edbeeab67c1575067335179513150115da367bArun Murthy u8 reg; 349b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion u8 bank; 350b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion u8 bit; 35184edbeeab67c1575067335179513150115da367bArun Murthy int ret; 35284edbeeab67c1575067335179513150115da367bArun Murthy 353defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson dev_dbg(di->dev, "SW Fallback: %d\n", fallback); 35484edbeeab67c1575067335179513150115da367bArun Murthy 355b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion if (is_ab8500(di->parent)) { 356b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion bank = 0x15; 357b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion reg = 0x0; 358b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion bit = 3; 359b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion } else { 360b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion bank = AB8500_SYS_CTRL1_BLOCK; 361b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion reg = AB8500_SW_CONTROL_FALLBACK; 362b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion bit = 0; 363b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion } 364b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion 365defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson /* read the register containing fallback bit */ 366b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion ret = abx500_get_register_interruptible(di->dev, bank, reg, &val); 367b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion if (ret < 0) { 368b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion dev_err(di->dev, "%d read failed\n", __LINE__); 36984edbeeab67c1575067335179513150115da367bArun Murthy return; 37084edbeeab67c1575067335179513150115da367bArun Murthy } 37184edbeeab67c1575067335179513150115da367bArun Murthy 372b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion if (is_ab8500(di->parent)) { 373b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion /* enable the OPT emulation registers */ 374b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2); 375b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion if (ret) { 376b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion dev_err(di->dev, "%d write failed\n", __LINE__); 377b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion goto disable_otp; 378b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion } 37984edbeeab67c1575067335179513150115da367bArun Murthy } 38084edbeeab67c1575067335179513150115da367bArun Murthy 381defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson if (fallback) 382b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion val |= (1 << bit); 38384edbeeab67c1575067335179513150115da367bArun Murthy else 384b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion val &= ~(1 << bit); 38584edbeeab67c1575067335179513150115da367bArun Murthy 386defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson /* write back the changed fallback bit value to register */ 387b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion ret = abx500_set_register_interruptible(di->dev, bank, reg, val); 38884edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 38984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%d write failed\n", __LINE__); 39084edbeeab67c1575067335179513150115da367bArun Murthy } 39184edbeeab67c1575067335179513150115da367bArun Murthy 392b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guiondisable_otp: 393b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion if (is_ab8500(di->parent)) { 394b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion /* disable the set OTP registers again */ 395b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0); 396b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion if (ret) { 397b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion dev_err(di->dev, "%d write failed\n", __LINE__); 398b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion } 39984edbeeab67c1575067335179513150115da367bArun Murthy } 40084edbeeab67c1575067335179513150115da367bArun Murthy} 40184edbeeab67c1575067335179513150115da367bArun Murthy 40284edbeeab67c1575067335179513150115da367bArun Murthy/** 40384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_power_supply_changed - a wrapper with local extentions for 40484edbeeab67c1575067335179513150115da367bArun Murthy * power_supply_changed 40584edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 40684edbeeab67c1575067335179513150115da367bArun Murthy * @psy: pointer to power_supply_that have changed. 40784edbeeab67c1575067335179513150115da367bArun Murthy * 40884edbeeab67c1575067335179513150115da367bArun Murthy */ 40984edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_power_supply_changed(struct ab8500_charger *di, 41084edbeeab67c1575067335179513150115da367bArun Murthy struct power_supply *psy) 41184edbeeab67c1575067335179513150115da367bArun Murthy{ 4124aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V if (di->autopower_cfg) { 41384edbeeab67c1575067335179513150115da367bArun Murthy if (!di->usb.charger_connected && 41484edbeeab67c1575067335179513150115da367bArun Murthy !di->ac.charger_connected && 41584edbeeab67c1575067335179513150115da367bArun Murthy di->autopower) { 41684edbeeab67c1575067335179513150115da367bArun Murthy di->autopower = false; 417defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson ab8500_enable_disable_sw_fallback(di, false); 41884edbeeab67c1575067335179513150115da367bArun Murthy } else if (!di->autopower && 41984edbeeab67c1575067335179513150115da367bArun Murthy (di->ac.charger_connected || 42084edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_connected)) { 42184edbeeab67c1575067335179513150115da367bArun Murthy di->autopower = true; 422defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson ab8500_enable_disable_sw_fallback(di, true); 42384edbeeab67c1575067335179513150115da367bArun Murthy } 42484edbeeab67c1575067335179513150115da367bArun Murthy } 42584edbeeab67c1575067335179513150115da367bArun Murthy power_supply_changed(psy); 42684edbeeab67c1575067335179513150115da367bArun Murthy} 42784edbeeab67c1575067335179513150115da367bArun Murthy 42884edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_set_usb_connected(struct ab8500_charger *di, 42984edbeeab67c1575067335179513150115da367bArun Murthy bool connected) 43084edbeeab67c1575067335179513150115da367bArun Murthy{ 43184edbeeab67c1575067335179513150115da367bArun Murthy if (connected != di->usb.charger_connected) { 43284edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB connected:%i\n", connected); 43384edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_connected = connected; 434f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones 435f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones if (!connected) 436f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->flags.vbus_drop_end = false; 437f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones 43884edbeeab67c1575067335179513150115da367bArun Murthy sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); 439b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 440b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones if (connected) { 441b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_lock(&di->charger_attached_mutex); 442b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_unlock(&di->charger_attached_mutex); 443b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 444261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent if (is_ab8500(di->parent)) 445261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent queue_delayed_work(di->charger_wq, 446b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones &di->usb_charger_attached_work, 447b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones HZ); 448b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } else { 449b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones cancel_delayed_work_sync(&di->usb_charger_attached_work); 450b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_lock(&di->charger_attached_mutex); 451b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_unlock(&di->charger_attached_mutex); 452b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } 45384edbeeab67c1575067335179513150115da367bArun Murthy } 45484edbeeab67c1575067335179513150115da367bArun Murthy} 45584edbeeab67c1575067335179513150115da367bArun Murthy 45684edbeeab67c1575067335179513150115da367bArun Murthy/** 45784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_ac_voltage() - get ac charger voltage 45884edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 45984edbeeab67c1575067335179513150115da367bArun Murthy * 46084edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger voltage (on success) 46184edbeeab67c1575067335179513150115da367bArun Murthy */ 46284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ac_voltage(struct ab8500_charger *di) 46384edbeeab67c1575067335179513150115da367bArun Murthy{ 46484edbeeab67c1575067335179513150115da367bArun Murthy int vch; 46584edbeeab67c1575067335179513150115da367bArun Murthy 46684edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure voltage if the charger is connected */ 46784edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_connected) { 46884edbeeab67c1575067335179513150115da367bArun Murthy vch = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_V); 46984edbeeab67c1575067335179513150115da367bArun Murthy if (vch < 0) 47084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed,\n", __func__); 47184edbeeab67c1575067335179513150115da367bArun Murthy } else { 47284edbeeab67c1575067335179513150115da367bArun Murthy vch = 0; 47384edbeeab67c1575067335179513150115da367bArun Murthy } 47484edbeeab67c1575067335179513150115da367bArun Murthy return vch; 47584edbeeab67c1575067335179513150115da367bArun Murthy} 47684edbeeab67c1575067335179513150115da367bArun Murthy 47784edbeeab67c1575067335179513150115da367bArun Murthy/** 47884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_cv() - check if the main charger is in CV mode 47984edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 48084edbeeab67c1575067335179513150115da367bArun Murthy * 48184edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger CV mode (on success) else error code 48284edbeeab67c1575067335179513150115da367bArun Murthy */ 48384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_cv(struct ab8500_charger *di) 48484edbeeab67c1575067335179513150115da367bArun Murthy{ 48584edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 48684edbeeab67c1575067335179513150115da367bArun Murthy int ret = 0; 48784edbeeab67c1575067335179513150115da367bArun Murthy 48884edbeeab67c1575067335179513150115da367bArun Murthy /* Only check CV mode if the charger is online */ 48984edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_online) { 49084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 49184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_STATUS1_REG, &val); 49284edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 49384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 49484edbeeab67c1575067335179513150115da367bArun Murthy return 0; 49584edbeeab67c1575067335179513150115da367bArun Murthy } 49684edbeeab67c1575067335179513150115da367bArun Murthy 49784edbeeab67c1575067335179513150115da367bArun Murthy if (val & MAIN_CH_CV_ON) 49884edbeeab67c1575067335179513150115da367bArun Murthy ret = 1; 49984edbeeab67c1575067335179513150115da367bArun Murthy else 50084edbeeab67c1575067335179513150115da367bArun Murthy ret = 0; 50184edbeeab67c1575067335179513150115da367bArun Murthy } 50284edbeeab67c1575067335179513150115da367bArun Murthy 50384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 50484edbeeab67c1575067335179513150115da367bArun Murthy} 50584edbeeab67c1575067335179513150115da367bArun Murthy 50684edbeeab67c1575067335179513150115da367bArun Murthy/** 50784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_vbus_voltage() - get vbus voltage 50884edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 50984edbeeab67c1575067335179513150115da367bArun Murthy * 51084edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the vbus voltage. 51184edbeeab67c1575067335179513150115da367bArun Murthy * Returns vbus voltage (on success) 51284edbeeab67c1575067335179513150115da367bArun Murthy */ 51384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di) 51484edbeeab67c1575067335179513150115da367bArun Murthy{ 51584edbeeab67c1575067335179513150115da367bArun Murthy int vch; 51684edbeeab67c1575067335179513150115da367bArun Murthy 51784edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure voltage if the charger is connected */ 51884edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_connected) { 51984edbeeab67c1575067335179513150115da367bArun Murthy vch = ab8500_gpadc_convert(di->gpadc, VBUS_V); 52084edbeeab67c1575067335179513150115da367bArun Murthy if (vch < 0) 52184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed\n", __func__); 52284edbeeab67c1575067335179513150115da367bArun Murthy } else { 52384edbeeab67c1575067335179513150115da367bArun Murthy vch = 0; 52484edbeeab67c1575067335179513150115da367bArun Murthy } 52584edbeeab67c1575067335179513150115da367bArun Murthy return vch; 52684edbeeab67c1575067335179513150115da367bArun Murthy} 52784edbeeab67c1575067335179513150115da367bArun Murthy 52884edbeeab67c1575067335179513150115da367bArun Murthy/** 52984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_usb_current() - get usb charger current 53084edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 53184edbeeab67c1575067335179513150115da367bArun Murthy * 53284edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the usb charger current. 53384edbeeab67c1575067335179513150115da367bArun Murthy * Returns usb current (on success) and error code on failure 53484edbeeab67c1575067335179513150115da367bArun Murthy */ 53584edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_usb_current(struct ab8500_charger *di) 53684edbeeab67c1575067335179513150115da367bArun Murthy{ 53784edbeeab67c1575067335179513150115da367bArun Murthy int ich; 53884edbeeab67c1575067335179513150115da367bArun Murthy 53984edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure current if the charger is online */ 54084edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_online) { 54184edbeeab67c1575067335179513150115da367bArun Murthy ich = ab8500_gpadc_convert(di->gpadc, USB_CHARGER_C); 54284edbeeab67c1575067335179513150115da367bArun Murthy if (ich < 0) 54384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed\n", __func__); 54484edbeeab67c1575067335179513150115da367bArun Murthy } else { 54584edbeeab67c1575067335179513150115da367bArun Murthy ich = 0; 54684edbeeab67c1575067335179513150115da367bArun Murthy } 54784edbeeab67c1575067335179513150115da367bArun Murthy return ich; 54884edbeeab67c1575067335179513150115da367bArun Murthy} 54984edbeeab67c1575067335179513150115da367bArun Murthy 55084edbeeab67c1575067335179513150115da367bArun Murthy/** 55184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_ac_current() - get ac charger current 55284edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 55384edbeeab67c1575067335179513150115da367bArun Murthy * 55484edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the ac charger current. 55584edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac current (on success) and error code on failure. 55684edbeeab67c1575067335179513150115da367bArun Murthy */ 55784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ac_current(struct ab8500_charger *di) 55884edbeeab67c1575067335179513150115da367bArun Murthy{ 55984edbeeab67c1575067335179513150115da367bArun Murthy int ich; 56084edbeeab67c1575067335179513150115da367bArun Murthy 56184edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure current if the charger is online */ 56284edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_online) { 56384edbeeab67c1575067335179513150115da367bArun Murthy ich = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_C); 56484edbeeab67c1575067335179513150115da367bArun Murthy if (ich < 0) 56584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed\n", __func__); 56684edbeeab67c1575067335179513150115da367bArun Murthy } else { 56784edbeeab67c1575067335179513150115da367bArun Murthy ich = 0; 56884edbeeab67c1575067335179513150115da367bArun Murthy } 56984edbeeab67c1575067335179513150115da367bArun Murthy return ich; 57084edbeeab67c1575067335179513150115da367bArun Murthy} 57184edbeeab67c1575067335179513150115da367bArun Murthy 57284edbeeab67c1575067335179513150115da367bArun Murthy/** 57384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_cv() - check if the usb charger is in CV mode 57484edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 57584edbeeab67c1575067335179513150115da367bArun Murthy * 57684edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger CV mode (on success) else error code 57784edbeeab67c1575067335179513150115da367bArun Murthy */ 57884edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_cv(struct ab8500_charger *di) 57984edbeeab67c1575067335179513150115da367bArun Murthy{ 58084edbeeab67c1575067335179513150115da367bArun Murthy int ret; 58184edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 58284edbeeab67c1575067335179513150115da367bArun Murthy 58384edbeeab67c1575067335179513150115da367bArun Murthy /* Only check CV mode if the charger is online */ 58484edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_online) { 58584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 58684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_USBCH_STAT1_REG, &val); 58784edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 58884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 58984edbeeab67c1575067335179513150115da367bArun Murthy return 0; 59084edbeeab67c1575067335179513150115da367bArun Murthy } 59184edbeeab67c1575067335179513150115da367bArun Murthy 59284edbeeab67c1575067335179513150115da367bArun Murthy if (val & USB_CH_CV_ON) 59384edbeeab67c1575067335179513150115da367bArun Murthy ret = 1; 59484edbeeab67c1575067335179513150115da367bArun Murthy else 59584edbeeab67c1575067335179513150115da367bArun Murthy ret = 0; 59684edbeeab67c1575067335179513150115da367bArun Murthy } else { 59784edbeeab67c1575067335179513150115da367bArun Murthy ret = 0; 59884edbeeab67c1575067335179513150115da367bArun Murthy } 59984edbeeab67c1575067335179513150115da367bArun Murthy 60084edbeeab67c1575067335179513150115da367bArun Murthy return ret; 60184edbeeab67c1575067335179513150115da367bArun Murthy} 60284edbeeab67c1575067335179513150115da367bArun Murthy 60384edbeeab67c1575067335179513150115da367bArun Murthy/** 60484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_chargers() - Detect the connected chargers 60584edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 60634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @probe: if probe, don't delay and wait for HW 60784edbeeab67c1575067335179513150115da367bArun Murthy * 60884edbeeab67c1575067335179513150115da367bArun Murthy * Returns the type of charger connected. 60984edbeeab67c1575067335179513150115da367bArun Murthy * For USB it will not mean we can actually charge from it 61084edbeeab67c1575067335179513150115da367bArun Murthy * but that there is a USB cable connected that we have to 61184edbeeab67c1575067335179513150115da367bArun Murthy * identify. This is used during startup when we don't get 61284edbeeab67c1575067335179513150115da367bArun Murthy * interrupts of the charger detection 61384edbeeab67c1575067335179513150115da367bArun Murthy * 61484edbeeab67c1575067335179513150115da367bArun Murthy * Returns an integer value, that means, 61584edbeeab67c1575067335179513150115da367bArun Murthy * NO_PW_CONN no power supply is connected 61684edbeeab67c1575067335179513150115da367bArun Murthy * AC_PW_CONN if the AC power supply is connected 61784edbeeab67c1575067335179513150115da367bArun Murthy * USB_PW_CONN if the USB power supply is connected 61884edbeeab67c1575067335179513150115da367bArun Murthy * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected 61984edbeeab67c1575067335179513150115da367bArun Murthy */ 62034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonstatic int ab8500_charger_detect_chargers(struct ab8500_charger *di, bool probe) 62184edbeeab67c1575067335179513150115da367bArun Murthy{ 62284edbeeab67c1575067335179513150115da367bArun Murthy int result = NO_PW_CONN; 62384edbeeab67c1575067335179513150115da367bArun Murthy int ret; 62484edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 62584edbeeab67c1575067335179513150115da367bArun Murthy 62684edbeeab67c1575067335179513150115da367bArun Murthy /* Check for AC charger */ 62784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 62884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_STATUS1_REG, &val); 62984edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 63084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 63184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 63284edbeeab67c1575067335179513150115da367bArun Murthy } 63384edbeeab67c1575067335179513150115da367bArun Murthy 63484edbeeab67c1575067335179513150115da367bArun Murthy if (val & MAIN_CH_DET) 63584edbeeab67c1575067335179513150115da367bArun Murthy result = AC_PW_CONN; 63684edbeeab67c1575067335179513150115da367bArun Murthy 63784edbeeab67c1575067335179513150115da367bArun Murthy /* Check for USB charger */ 63834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 63934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (!probe) { 64034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* 64134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * AB8500 says VBUS_DET_DBNC1 & VBUS_DET_DBNC100 64234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * when disconnecting ACA even though no 64334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * charger was connected. Try waiting a little 64434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * longer than the 100 ms of VBUS_DET_DBNC100... 64534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson */ 64634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson msleep(110); 64734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 64884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 64984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_USBCH_STAT1_REG, &val); 65084edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 65184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 65284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 65384edbeeab67c1575067335179513150115da367bArun Murthy } 65434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, 65534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "%s AB8500_CH_USBCH_STAT1_REG %x\n", __func__, 65634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson val); 65784edbeeab67c1575067335179513150115da367bArun Murthy if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100)) 65884edbeeab67c1575067335179513150115da367bArun Murthy result |= USB_PW_CONN; 65984edbeeab67c1575067335179513150115da367bArun Murthy 66084edbeeab67c1575067335179513150115da367bArun Murthy return result; 66184edbeeab67c1575067335179513150115da367bArun Murthy} 66284edbeeab67c1575067335179513150115da367bArun Murthy 66384edbeeab67c1575067335179513150115da367bArun Murthy/** 66484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_max_usb_curr() - get the max curr for the USB type 66584edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 66684edbeeab67c1575067335179513150115da367bArun Murthy * @link_status: the identified USB type 66784edbeeab67c1575067335179513150115da367bArun Murthy * 66884edbeeab67c1575067335179513150115da367bArun Murthy * Get the maximum current that is allowed to be drawn from the host 66984edbeeab67c1575067335179513150115da367bArun Murthy * based on the USB type. 67084edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success 67184edbeeab67c1575067335179513150115da367bArun Murthy */ 67284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_max_usb_curr(struct ab8500_charger *di, 67374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg enum ab8500_charger_link_status link_status) 67484edbeeab67c1575067335179513150115da367bArun Murthy{ 67584edbeeab67c1575067335179513150115da367bArun Murthy int ret = 0; 67684edbeeab67c1575067335179513150115da367bArun Murthy 6774b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper di->usb_device_is_unrecognised = false; 6784b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper 67934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* 68034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * Platform only supports USB 2.0. 68134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * This means that charging current from USB source 68234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * is maximum 500 mA. Every occurence of USB_STAT_*_HOST_* 68334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * should set USB_CH_IP_CUR_LVL_0P5. 68434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson */ 68534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 68684edbeeab67c1575067335179513150115da367bArun Murthy switch (link_status) { 68784edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_STD_HOST_NC: 68884edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_STD_HOST_C_NS: 68984edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_STD_HOST_C_S: 69084edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB Type - Standard host is " 69134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "detected through USB driver\n"); 692f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 69334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 0; 69484edbeeab67c1575067335179513150115da367bArun Murthy break; 69584edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HOST_CHG_HS_CHIRP: 696f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 69734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 0; 69884edbeeab67c1575067335179513150115da367bArun Murthy break; 69984edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HOST_CHG_HS: 700f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 70134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 0; 70234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson break; 70384edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_C_HS: 704f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P9; 70534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 0; 70684edbeeab67c1575067335179513150115da367bArun Murthy break; 70784edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_A: 70884edbeeab67c1575067335179513150115da367bArun Murthy /* 70984edbeeab67c1575067335179513150115da367bArun Murthy * Dedicated charger level minus maximum current accessory 71034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * can consume (900mA). Closest level is 500mA 71184edbeeab67c1575067335179513150115da367bArun Murthy */ 71234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n"); 713f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 71434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 1; 71584edbeeab67c1575067335179513150115da367bArun Murthy break; 71684edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_B: 71784edbeeab67c1575067335179513150115da367bArun Murthy /* 71884edbeeab67c1575067335179513150115da367bArun Murthy * Dedicated charger level minus 120mA (20mA for ACA and 71984edbeeab67c1575067335179513150115da367bArun Murthy * 100mA for potential accessory). Closest level is 1300mA 72084edbeeab67c1575067335179513150115da367bArun Murthy */ 721f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P3; 72274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, 723f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 72434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 1; 72584edbeeab67c1575067335179513150115da367bArun Murthy break; 72684edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HOST_CHG_NM: 727f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 72834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 0; 72934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson break; 73074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg case USB_STAT_DEDICATED_CHG: 731f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5; 73234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 0; 73334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson break; 73474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg case USB_STAT_ACA_RID_C_HS_CHIRP: 73534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson case USB_STAT_ACA_RID_C_NM: 736f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5; 73734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid = 1; 73884edbeeab67c1575067335179513150115da367bArun Murthy break; 7394b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper case USB_STAT_NOT_CONFIGURED: 7404b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper if (di->vbus_detected) { 7414b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper di->usb_device_is_unrecognised = true; 7424b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper dev_dbg(di->dev, "USB Type - Legacy charger.\n"); 743f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = 744f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones USB_CH_IP_CUR_LVL_1P5; 7454b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper break; 7464b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper } 74784edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HM_IDGND: 74884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "USB Type - Charging not allowed\n"); 749f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; 75084edbeeab67c1575067335179513150115da367bArun Murthy ret = -ENXIO; 75184edbeeab67c1575067335179513150115da367bArun Murthy break; 75274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg case USB_STAT_RESERVED: 75374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg if (is_ab8500(di->parent)) { 75474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg di->flags.vbus_collapse = true; 75574a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg dev_err(di->dev, "USB Type - USB_STAT_RESERVED " 75674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg "VBUS has collapsed\n"); 75774a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg ret = -ENXIO; 75874a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg break; 759861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones } else { 76074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg dev_dbg(di->dev, "USB Type - Charging not allowed\n"); 761f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = 762f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones USB_CH_IP_CUR_LVL_0P05; 76374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", 764f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones link_status, 765f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 76674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg ret = -ENXIO; 76774a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg break; 76874a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg } 76974a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg case USB_STAT_CARKIT_1: 77074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg case USB_STAT_CARKIT_2: 77174a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg case USB_STAT_ACA_DOCK_CHARGER: 77274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg case USB_STAT_CHARGER_LINE_1: 773f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 77474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, 775f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 776ed5243f8ab2470e988dce0e416eaaddb4d7d2cccDan Carpenter break; 777ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver case USB_STAT_NOT_VALID_LINK: 778ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver dev_err(di->dev, "USB Type invalid - try charging anyway\n"); 779f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 78074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg break; 78174a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg 78284edbeeab67c1575067335179513150115da367bArun Murthy default: 78384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "USB Type - Unknown\n"); 784f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; 78584edbeeab67c1575067335179513150115da367bArun Murthy ret = -ENXIO; 78684edbeeab67c1575067335179513150115da367bArun Murthy break; 78784edbeeab67c1575067335179513150115da367bArun Murthy }; 78884edbeeab67c1575067335179513150115da367bArun Murthy 789f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max; 79084edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", 791f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones link_status, di->max_usb_in_curr.set_max); 79284edbeeab67c1575067335179513150115da367bArun Murthy 79384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 79484edbeeab67c1575067335179513150115da367bArun Murthy} 79584edbeeab67c1575067335179513150115da367bArun Murthy 79684edbeeab67c1575067335179513150115da367bArun Murthy/** 79784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_read_usb_type() - read the type of usb connected 79884edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 79984edbeeab67c1575067335179513150115da367bArun Murthy * 80084edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of the plugged USB 80184edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success 80284edbeeab67c1575067335179513150115da367bArun Murthy */ 80384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_read_usb_type(struct ab8500_charger *di) 80484edbeeab67c1575067335179513150115da367bArun Murthy{ 80584edbeeab67c1575067335179513150115da367bArun Murthy int ret; 80684edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 80784edbeeab67c1575067335179513150115da367bArun Murthy 80884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 80984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val); 81084edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 81184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 81284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 81384edbeeab67c1575067335179513150115da367bArun Murthy } 814861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8500(di->parent)) 81574a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 816861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones AB8500_USB_LINE_STAT_REG, &val); 817861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 818861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones ret = abx500_get_register_interruptible(di->dev, 819861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); 82084edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 82184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 82284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 82384edbeeab67c1575067335179513150115da367bArun Murthy } 82484edbeeab67c1575067335179513150115da367bArun Murthy 82584edbeeab67c1575067335179513150115da367bArun Murthy /* get the USB type */ 826861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8500(di->parent)) 827861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones val = (val & AB8500_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT; 828861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 829861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones val = (val & AB8505_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT; 83084edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_max_usb_curr(di, 83184edbeeab67c1575067335179513150115da367bArun Murthy (enum ab8500_charger_link_status) val); 83284edbeeab67c1575067335179513150115da367bArun Murthy 83384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 83484edbeeab67c1575067335179513150115da367bArun Murthy} 83584edbeeab67c1575067335179513150115da367bArun Murthy 83684edbeeab67c1575067335179513150115da367bArun Murthy/** 83784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_usb_type() - get the type of usb connected 83884edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 83984edbeeab67c1575067335179513150115da367bArun Murthy * 84084edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of the plugged USB 84184edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success 84284edbeeab67c1575067335179513150115da367bArun Murthy */ 84384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_detect_usb_type(struct ab8500_charger *di) 84484edbeeab67c1575067335179513150115da367bArun Murthy{ 84584edbeeab67c1575067335179513150115da367bArun Murthy int i, ret; 84684edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 84784edbeeab67c1575067335179513150115da367bArun Murthy 84884edbeeab67c1575067335179513150115da367bArun Murthy /* 84984edbeeab67c1575067335179513150115da367bArun Murthy * On getting the VBUS rising edge detect interrupt there 85084edbeeab67c1575067335179513150115da367bArun Murthy * is a 250ms delay after which the register UsbLineStatus 85184edbeeab67c1575067335179513150115da367bArun Murthy * is filled with valid data. 85284edbeeab67c1575067335179513150115da367bArun Murthy */ 85384edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < 10; i++) { 85484edbeeab67c1575067335179513150115da367bArun Murthy msleep(250); 85584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 85684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, 85784edbeeab67c1575067335179513150115da367bArun Murthy &val); 85834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "%s AB8500_IT_SOURCE21_REG %x\n", 85934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson __func__, val); 86084edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 86184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 86284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 86384edbeeab67c1575067335179513150115da367bArun Murthy } 86474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg 865861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8500(di->parent)) 86674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg ret = abx500_get_register_interruptible(di->dev, 86774a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); 868861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 86974a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg ret = abx500_get_register_interruptible(di->dev, 87074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); 87184edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 87284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 87384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 87484edbeeab67c1575067335179513150115da367bArun Murthy } 87534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "%s AB8500_USB_LINE_STAT_REG %x\n", __func__, 87634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson val); 87784edbeeab67c1575067335179513150115da367bArun Murthy /* 87884edbeeab67c1575067335179513150115da367bArun Murthy * Until the IT source register is read the UsbLineStatus 87984edbeeab67c1575067335179513150115da367bArun Murthy * register is not updated, hence doing the same 88084edbeeab67c1575067335179513150115da367bArun Murthy * Revisit this: 88184edbeeab67c1575067335179513150115da367bArun Murthy */ 88284edbeeab67c1575067335179513150115da367bArun Murthy 88384edbeeab67c1575067335179513150115da367bArun Murthy /* get the USB type */ 884861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8500(di->parent)) 885861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones val = (val & AB8500_USB_LINK_STATUS) >> 886861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones USB_LINK_STATUS_SHIFT; 887861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 888861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones val = (val & AB8505_USB_LINK_STATUS) >> 889861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones USB_LINK_STATUS_SHIFT; 89084edbeeab67c1575067335179513150115da367bArun Murthy if (val) 89184edbeeab67c1575067335179513150115da367bArun Murthy break; 89284edbeeab67c1575067335179513150115da367bArun Murthy } 89384edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_max_usb_curr(di, 89484edbeeab67c1575067335179513150115da367bArun Murthy (enum ab8500_charger_link_status) val); 89584edbeeab67c1575067335179513150115da367bArun Murthy 89684edbeeab67c1575067335179513150115da367bArun Murthy return ret; 89784edbeeab67c1575067335179513150115da367bArun Murthy} 89884edbeeab67c1575067335179513150115da367bArun Murthy 89984edbeeab67c1575067335179513150115da367bArun Murthy/* 90084edbeeab67c1575067335179513150115da367bArun Murthy * This array maps the raw hex value to charger voltage used by the AB8500 90184edbeeab67c1575067335179513150115da367bArun Murthy * Values taken from the UM0836 90284edbeeab67c1575067335179513150115da367bArun Murthy */ 90384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_voltage_map[] = { 90484edbeeab67c1575067335179513150115da367bArun Murthy 3500 , 90584edbeeab67c1575067335179513150115da367bArun Murthy 3525 , 90684edbeeab67c1575067335179513150115da367bArun Murthy 3550 , 90784edbeeab67c1575067335179513150115da367bArun Murthy 3575 , 90884edbeeab67c1575067335179513150115da367bArun Murthy 3600 , 90984edbeeab67c1575067335179513150115da367bArun Murthy 3625 , 91084edbeeab67c1575067335179513150115da367bArun Murthy 3650 , 91184edbeeab67c1575067335179513150115da367bArun Murthy 3675 , 91284edbeeab67c1575067335179513150115da367bArun Murthy 3700 , 91384edbeeab67c1575067335179513150115da367bArun Murthy 3725 , 91484edbeeab67c1575067335179513150115da367bArun Murthy 3750 , 91584edbeeab67c1575067335179513150115da367bArun Murthy 3775 , 91684edbeeab67c1575067335179513150115da367bArun Murthy 3800 , 91784edbeeab67c1575067335179513150115da367bArun Murthy 3825 , 91884edbeeab67c1575067335179513150115da367bArun Murthy 3850 , 91984edbeeab67c1575067335179513150115da367bArun Murthy 3875 , 92084edbeeab67c1575067335179513150115da367bArun Murthy 3900 , 92184edbeeab67c1575067335179513150115da367bArun Murthy 3925 , 92284edbeeab67c1575067335179513150115da367bArun Murthy 3950 , 92384edbeeab67c1575067335179513150115da367bArun Murthy 3975 , 92484edbeeab67c1575067335179513150115da367bArun Murthy 4000 , 92584edbeeab67c1575067335179513150115da367bArun Murthy 4025 , 92684edbeeab67c1575067335179513150115da367bArun Murthy 4050 , 92784edbeeab67c1575067335179513150115da367bArun Murthy 4060 , 92884edbeeab67c1575067335179513150115da367bArun Murthy 4070 , 92984edbeeab67c1575067335179513150115da367bArun Murthy 4080 , 93084edbeeab67c1575067335179513150115da367bArun Murthy 4090 , 93184edbeeab67c1575067335179513150115da367bArun Murthy 4100 , 93284edbeeab67c1575067335179513150115da367bArun Murthy 4110 , 93384edbeeab67c1575067335179513150115da367bArun Murthy 4120 , 93484edbeeab67c1575067335179513150115da367bArun Murthy 4130 , 93584edbeeab67c1575067335179513150115da367bArun Murthy 4140 , 93684edbeeab67c1575067335179513150115da367bArun Murthy 4150 , 93784edbeeab67c1575067335179513150115da367bArun Murthy 4160 , 93884edbeeab67c1575067335179513150115da367bArun Murthy 4170 , 93984edbeeab67c1575067335179513150115da367bArun Murthy 4180 , 94084edbeeab67c1575067335179513150115da367bArun Murthy 4190 , 94184edbeeab67c1575067335179513150115da367bArun Murthy 4200 , 94284edbeeab67c1575067335179513150115da367bArun Murthy 4210 , 94384edbeeab67c1575067335179513150115da367bArun Murthy 4220 , 94484edbeeab67c1575067335179513150115da367bArun Murthy 4230 , 94584edbeeab67c1575067335179513150115da367bArun Murthy 4240 , 94684edbeeab67c1575067335179513150115da367bArun Murthy 4250 , 94784edbeeab67c1575067335179513150115da367bArun Murthy 4260 , 94884edbeeab67c1575067335179513150115da367bArun Murthy 4270 , 94984edbeeab67c1575067335179513150115da367bArun Murthy 4280 , 95084edbeeab67c1575067335179513150115da367bArun Murthy 4290 , 95184edbeeab67c1575067335179513150115da367bArun Murthy 4300 , 95284edbeeab67c1575067335179513150115da367bArun Murthy 4310 , 95384edbeeab67c1575067335179513150115da367bArun Murthy 4320 , 95484edbeeab67c1575067335179513150115da367bArun Murthy 4330 , 95584edbeeab67c1575067335179513150115da367bArun Murthy 4340 , 95684edbeeab67c1575067335179513150115da367bArun Murthy 4350 , 95784edbeeab67c1575067335179513150115da367bArun Murthy 4360 , 95884edbeeab67c1575067335179513150115da367bArun Murthy 4370 , 95984edbeeab67c1575067335179513150115da367bArun Murthy 4380 , 96084edbeeab67c1575067335179513150115da367bArun Murthy 4390 , 96184edbeeab67c1575067335179513150115da367bArun Murthy 4400 , 96284edbeeab67c1575067335179513150115da367bArun Murthy 4410 , 96384edbeeab67c1575067335179513150115da367bArun Murthy 4420 , 96484edbeeab67c1575067335179513150115da367bArun Murthy 4430 , 96584edbeeab67c1575067335179513150115da367bArun Murthy 4440 , 96684edbeeab67c1575067335179513150115da367bArun Murthy 4450 , 96784edbeeab67c1575067335179513150115da367bArun Murthy 4460 , 96884edbeeab67c1575067335179513150115da367bArun Murthy 4470 , 96984edbeeab67c1575067335179513150115da367bArun Murthy 4480 , 97084edbeeab67c1575067335179513150115da367bArun Murthy 4490 , 97184edbeeab67c1575067335179513150115da367bArun Murthy 4500 , 97284edbeeab67c1575067335179513150115da367bArun Murthy 4510 , 97384edbeeab67c1575067335179513150115da367bArun Murthy 4520 , 97484edbeeab67c1575067335179513150115da367bArun Murthy 4530 , 97584edbeeab67c1575067335179513150115da367bArun Murthy 4540 , 97684edbeeab67c1575067335179513150115da367bArun Murthy 4550 , 97784edbeeab67c1575067335179513150115da367bArun Murthy 4560 , 97884edbeeab67c1575067335179513150115da367bArun Murthy 4570 , 97984edbeeab67c1575067335179513150115da367bArun Murthy 4580 , 98084edbeeab67c1575067335179513150115da367bArun Murthy 4590 , 98184edbeeab67c1575067335179513150115da367bArun Murthy 4600 , 98284edbeeab67c1575067335179513150115da367bArun Murthy}; 98384edbeeab67c1575067335179513150115da367bArun Murthy 98484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_voltage_to_regval(int voltage) 98584edbeeab67c1575067335179513150115da367bArun Murthy{ 98684edbeeab67c1575067335179513150115da367bArun Murthy int i; 98784edbeeab67c1575067335179513150115da367bArun Murthy 98884edbeeab67c1575067335179513150115da367bArun Murthy /* Special case for voltage below 3.5V */ 98984edbeeab67c1575067335179513150115da367bArun Murthy if (voltage < ab8500_charger_voltage_map[0]) 99084edbeeab67c1575067335179513150115da367bArun Murthy return LOW_VOLT_REG; 99184edbeeab67c1575067335179513150115da367bArun Murthy 99284edbeeab67c1575067335179513150115da367bArun Murthy for (i = 1; i < ARRAY_SIZE(ab8500_charger_voltage_map); i++) { 99384edbeeab67c1575067335179513150115da367bArun Murthy if (voltage < ab8500_charger_voltage_map[i]) 99484edbeeab67c1575067335179513150115da367bArun Murthy return i - 1; 99584edbeeab67c1575067335179513150115da367bArun Murthy } 99684edbeeab67c1575067335179513150115da367bArun Murthy 99784edbeeab67c1575067335179513150115da367bArun Murthy /* If not last element, return error */ 99884edbeeab67c1575067335179513150115da367bArun Murthy i = ARRAY_SIZE(ab8500_charger_voltage_map) - 1; 99984edbeeab67c1575067335179513150115da367bArun Murthy if (voltage == ab8500_charger_voltage_map[i]) 100084edbeeab67c1575067335179513150115da367bArun Murthy return i; 100184edbeeab67c1575067335179513150115da367bArun Murthy else 100284edbeeab67c1575067335179513150115da367bArun Murthy return -1; 100384edbeeab67c1575067335179513150115da367bArun Murthy} 100484edbeeab67c1575067335179513150115da367bArun Murthy 1005861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jonesstatic int ab8500_current_to_regval(struct ab8500_charger *di, int curr) 100684edbeeab67c1575067335179513150115da367bArun Murthy{ 100784edbeeab67c1575067335179513150115da367bArun Murthy int i; 100884edbeeab67c1575067335179513150115da367bArun Murthy 1009861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (curr < di->bm->chg_output_curr[0]) 101084edbeeab67c1575067335179513150115da367bArun Murthy return 0; 101184edbeeab67c1575067335179513150115da367bArun Murthy 1012861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones for (i = 0; i < di->bm->n_chg_out_curr; i++) { 1013861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (curr < di->bm->chg_output_curr[i]) 101484edbeeab67c1575067335179513150115da367bArun Murthy return i - 1; 101584edbeeab67c1575067335179513150115da367bArun Murthy } 101684edbeeab67c1575067335179513150115da367bArun Murthy 101784edbeeab67c1575067335179513150115da367bArun Murthy /* If not last element, return error */ 1018861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones i = di->bm->n_chg_out_curr - 1; 1019861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (curr == di->bm->chg_output_curr[i]) 102084edbeeab67c1575067335179513150115da367bArun Murthy return i; 102184edbeeab67c1575067335179513150115da367bArun Murthy else 102284edbeeab67c1575067335179513150115da367bArun Murthy return -1; 102384edbeeab67c1575067335179513150115da367bArun Murthy} 102484edbeeab67c1575067335179513150115da367bArun Murthy 1025861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jonesstatic int ab8500_vbus_in_curr_to_regval(struct ab8500_charger *di, int curr) 102684edbeeab67c1575067335179513150115da367bArun Murthy{ 102784edbeeab67c1575067335179513150115da367bArun Murthy int i; 102884edbeeab67c1575067335179513150115da367bArun Murthy 1029861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (curr < di->bm->chg_input_curr[0]) 103084edbeeab67c1575067335179513150115da367bArun Murthy return 0; 103184edbeeab67c1575067335179513150115da367bArun Murthy 1032861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones for (i = 0; i < di->bm->n_chg_in_curr; i++) { 1033861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (curr < di->bm->chg_input_curr[i]) 103484edbeeab67c1575067335179513150115da367bArun Murthy return i - 1; 103584edbeeab67c1575067335179513150115da367bArun Murthy } 103684edbeeab67c1575067335179513150115da367bArun Murthy 103784edbeeab67c1575067335179513150115da367bArun Murthy /* If not last element, return error */ 1038861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones i = di->bm->n_chg_in_curr - 1; 1039861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (curr == di->bm->chg_input_curr[i]) 104084edbeeab67c1575067335179513150115da367bArun Murthy return i; 104184edbeeab67c1575067335179513150115da367bArun Murthy else 104284edbeeab67c1575067335179513150115da367bArun Murthy return -1; 104384edbeeab67c1575067335179513150115da367bArun Murthy} 104484edbeeab67c1575067335179513150115da367bArun Murthy 104584edbeeab67c1575067335179513150115da367bArun Murthy/** 104684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_usb_cur() - get usb current 104784edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structre 104884edbeeab67c1575067335179513150115da367bArun Murthy * 104984edbeeab67c1575067335179513150115da367bArun Murthy * The usb stack provides the maximum current that can be drawn from 105084edbeeab67c1575067335179513150115da367bArun Murthy * the standard usb host. This will be in mA. 105184edbeeab67c1575067335179513150115da367bArun Murthy * This function converts current in mA to a value that can be written 105284edbeeab67c1575067335179513150115da367bArun Murthy * to the register. Returns -1 if charging is not allowed 105384edbeeab67c1575067335179513150115da367bArun Murthy */ 105484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_usb_cur(struct ab8500_charger *di) 105584edbeeab67c1575067335179513150115da367bArun Murthy{ 1056f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones int ret = 0; 105784edbeeab67c1575067335179513150115da367bArun Murthy switch (di->usb_state.usb_current) { 105884edbeeab67c1575067335179513150115da367bArun Murthy case 100: 1059f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P09; 106084edbeeab67c1575067335179513150115da367bArun Murthy break; 106184edbeeab67c1575067335179513150115da367bArun Murthy case 200: 1062f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P19; 106384edbeeab67c1575067335179513150115da367bArun Murthy break; 106484edbeeab67c1575067335179513150115da367bArun Murthy case 300: 1065f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P29; 106684edbeeab67c1575067335179513150115da367bArun Murthy break; 106784edbeeab67c1575067335179513150115da367bArun Murthy case 400: 1068f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P38; 106984edbeeab67c1575067335179513150115da367bArun Murthy break; 107084edbeeab67c1575067335179513150115da367bArun Murthy case 500: 1071f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5; 107284edbeeab67c1575067335179513150115da367bArun Murthy break; 107384edbeeab67c1575067335179513150115da367bArun Murthy default: 1074f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; 1075f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones ret = -EPERM; 107684edbeeab67c1575067335179513150115da367bArun Murthy break; 107784edbeeab67c1575067335179513150115da367bArun Murthy }; 1078f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max; 1079f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones return ret; 1080f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones} 1081f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones 1082f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones/** 1083f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * ab8500_charger_check_continue_stepping() - Check to allow stepping 1084f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * @di: pointer to the ab8500_charger structure 1085f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * @reg: select what charger register to check 1086f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * 1087f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * Check if current stepping should be allowed to continue. 1088f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * Checks if charger source has not collapsed. If it has, further stepping 1089f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * is not allowed. 1090f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones */ 1091f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jonesstatic bool ab8500_charger_check_continue_stepping(struct ab8500_charger *di, 1092f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones int reg) 1093f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones{ 1094f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones if (reg == AB8500_USBCH_IPT_CRNTLVL_REG) 1095f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones return !di->flags.vbus_drop_end; 1096f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones else 1097f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones return true; 109884edbeeab67c1575067335179513150115da367bArun Murthy} 109984edbeeab67c1575067335179513150115da367bArun Murthy 110084edbeeab67c1575067335179513150115da367bArun Murthy/** 1101f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * ab8500_charger_set_current() - set charger current 1102f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @di: pointer to the ab8500_charger structure 1103f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @ich: charger current, in mA 1104f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @reg: select what charger register to set 1105f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * 1106f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Set charger current. 1107f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * There is no state machine in the AB to step up/down the charger 1108f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * current to avoid dips and spikes on MAIN, VBUS and VBAT when 1109f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * charging is started. Instead we need to implement 1110f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * this charger current step-up/down here. 1111f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Returns error code in case of failure else 0(on success) 1112f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt */ 1113f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedtstatic int ab8500_charger_set_current(struct ab8500_charger *di, 1114f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt int ich, int reg) 1115f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt{ 111634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson int ret = 0; 1117861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones int curr_index, prev_curr_index, shift_value, i; 1118f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt u8 reg_value; 111934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson u32 step_udelay; 112034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson bool no_stepping = false; 112134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 112234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson atomic_inc(&di->current_stepping_sessions); 112334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 112434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 112534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson reg, ®_value); 112634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret < 0) { 112734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_err(di->dev, "%s read failed\n", __func__); 112834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto exit_set_current; 112934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 1130f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt 1131f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt switch (reg) { 1132f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt case AB8500_MCH_IPT_CURLVL_REG: 1133f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt shift_value = MAIN_CH_INPUT_CURR_SHIFT; 113434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson prev_curr_index = (reg_value >> shift_value); 1135861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones curr_index = ab8500_current_to_regval(di, ich); 113634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson step_udelay = STEP_UDELAY; 113734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (!di->ac.charger_connected) 113834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson no_stepping = true; 1139f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt break; 1140f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt case AB8500_USBCH_IPT_CRNTLVL_REG: 1141861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8540(di->parent)) 1142861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones shift_value = AB8540_VBUS_IN_CURR_LIM_SHIFT; 1143861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 1144861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones shift_value = VBUS_IN_CURR_LIM_SHIFT; 114534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson prev_curr_index = (reg_value >> shift_value); 1146861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones curr_index = ab8500_vbus_in_curr_to_regval(di, ich); 114734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson step_udelay = STEP_UDELAY * 100; 114834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 114934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (!di->usb.charger_connected) 115034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson no_stepping = true; 1151f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt break; 1152f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt case AB8500_CH_OPT_CRNTLVL_REG: 1153f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt shift_value = 0; 115434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson prev_curr_index = (reg_value >> shift_value); 1155861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones curr_index = ab8500_current_to_regval(di, ich); 115634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson step_udelay = STEP_UDELAY; 115734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (curr_index && (curr_index - prev_curr_index) > 1) 115834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson step_udelay *= 100; 115934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 116034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (!di->usb.charger_connected && !di->ac.charger_connected) 116134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson no_stepping = true; 116234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 1163f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt break; 1164f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt default: 1165f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "%s current register not valid\n", __func__); 116634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = -ENXIO; 116734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto exit_set_current; 1168f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } 1169f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt 1170f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt if (curr_index < 0) { 1171f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "requested current limit out-of-range\n"); 117234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = -ENXIO; 117334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto exit_set_current; 1174f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } 1175f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt 1176f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt /* only update current if it's been changed */ 117734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (prev_curr_index == curr_index) { 117834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "%s current not changed for reg: 0x%02x\n", 117934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson __func__, reg); 118034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = 0; 118134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto exit_set_current; 118234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 1183f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt 1184f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n", 1185f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt __func__, ich, reg); 1186f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt 118734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (no_stepping) { 118834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 118934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson reg, (u8)curr_index << shift_value); 119034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret) 119134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_err(di->dev, "%s write failed\n", __func__); 119234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } else if (prev_curr_index > curr_index) { 1193f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt for (i = prev_curr_index - 1; i >= curr_index; i--) { 119434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "curr change_1 to: %x for 0x%02x\n", 119534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson (u8) i << shift_value, reg); 1196f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt ret = abx500_set_register_interruptible(di->dev, 119734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson AB8500_CHARGER, reg, (u8)i << shift_value); 1198f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt if (ret) { 1199f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "%s write failed\n", __func__); 120034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto exit_set_current; 1201f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } 120234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (i != curr_index) 120334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson usleep_range(step_udelay, step_udelay * 2); 1204f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } 1205f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } else { 1206f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones bool allow = true; 1207f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones for (i = prev_curr_index + 1; i <= curr_index && allow; i++) { 120834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n", 120934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson (u8)i << shift_value, reg); 1210f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt ret = abx500_set_register_interruptible(di->dev, 121134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson AB8500_CHARGER, reg, (u8)i << shift_value); 1212f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt if (ret) { 1213f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "%s write failed\n", __func__); 121434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto exit_set_current; 1215f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } 121634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (i != curr_index) 121734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson usleep_range(step_udelay, step_udelay * 2); 1218f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones 1219f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones allow = ab8500_charger_check_continue_stepping(di, reg); 1220f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } 1221f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt } 122234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 122334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonexit_set_current: 122434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson atomic_dec(&di->current_stepping_sessions); 122534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 1226f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt return ret; 1227f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt} 1228f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt 1229f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/** 123084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit 123184edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 123284edbeeab67c1575067335179513150115da367bArun Murthy * @ich_in: charger input current limit 123384edbeeab67c1575067335179513150115da367bArun Murthy * 123484edbeeab67c1575067335179513150115da367bArun Murthy * Sets the current that can be drawn from the USB host 123584edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 123684edbeeab67c1575067335179513150115da367bArun Murthy */ 123784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, 123884edbeeab67c1575067335179513150115da367bArun Murthy int ich_in) 123984edbeeab67c1575067335179513150115da367bArun Murthy{ 124084edbeeab67c1575067335179513150115da367bArun Murthy int min_value; 124134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson int ret; 124284edbeeab67c1575067335179513150115da367bArun Murthy 124384edbeeab67c1575067335179513150115da367bArun Murthy /* We should always use to lowest current limit */ 1244b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones min_value = min(di->bm->chg_params->usb_curr_max, ich_in); 1245f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones if (di->max_usb_in_curr.set_max > 0) 1246f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones min_value = min(di->max_usb_in_curr.set_max, min_value); 1247f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones 1248f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones if (di->usb_state.usb_current >= 0) 1249f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones min_value = min(di->usb_state.usb_current, min_value); 125084edbeeab67c1575067335179513150115da367bArun Murthy 125184edbeeab67c1575067335179513150115da367bArun Murthy switch (min_value) { 125284edbeeab67c1575067335179513150115da367bArun Murthy case 100: 125384edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbat < VBAT_TRESH_IP_CUR_RED) 125484edbeeab67c1575067335179513150115da367bArun Murthy min_value = USB_CH_IP_CUR_LVL_0P05; 125584edbeeab67c1575067335179513150115da367bArun Murthy break; 125684edbeeab67c1575067335179513150115da367bArun Murthy case 500: 125784edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbat < VBAT_TRESH_IP_CUR_RED) 125884edbeeab67c1575067335179513150115da367bArun Murthy min_value = USB_CH_IP_CUR_LVL_0P45; 125984edbeeab67c1575067335179513150115da367bArun Murthy break; 126084edbeeab67c1575067335179513150115da367bArun Murthy default: 126184edbeeab67c1575067335179513150115da367bArun Murthy break; 126284edbeeab67c1575067335179513150115da367bArun Murthy } 126384edbeeab67c1575067335179513150115da367bArun Murthy 126434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_info(di->dev, "VBUS input current limit set to %d mA\n", min_value); 126534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 126634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson mutex_lock(&di->usb_ipt_crnt_lock); 126734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = ab8500_charger_set_current(di, min_value, 1268f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt AB8500_USBCH_IPT_CRNTLVL_REG); 126934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson mutex_unlock(&di->usb_ipt_crnt_lock); 127034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 127134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return ret; 1272f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt} 127384edbeeab67c1575067335179513150115da367bArun Murthy 1274f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/** 1275f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * ab8500_charger_set_main_in_curr() - set main charger input current 1276f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @di: pointer to the ab8500_charger structure 1277f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @ich_in: input charger current, in mA 1278f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * 1279f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Set main charger input current. 1280f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Returns error code in case of failure else 0(on success) 1281f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt */ 1282f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedtstatic int ab8500_charger_set_main_in_curr(struct ab8500_charger *di, 1283f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt int ich_in) 1284f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt{ 1285f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt return ab8500_charger_set_current(di, ich_in, 1286f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt AB8500_MCH_IPT_CURLVL_REG); 1287f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt} 128884edbeeab67c1575067335179513150115da367bArun Murthy 1289f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/** 1290f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * ab8500_charger_set_output_curr() - set charger output current 1291f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @di: pointer to the ab8500_charger structure 1292f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @ich_out: output charger current, in mA 1293f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * 1294f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Set charger output current. 1295f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Returns error code in case of failure else 0(on success) 1296f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt */ 1297f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedtstatic int ab8500_charger_set_output_curr(struct ab8500_charger *di, 1298f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt int ich_out) 1299f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt{ 1300f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt return ab8500_charger_set_current(di, ich_out, 1301f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt AB8500_CH_OPT_CRNTLVL_REG); 130284edbeeab67c1575067335179513150115da367bArun Murthy} 130384edbeeab67c1575067335179513150115da367bArun Murthy 130484edbeeab67c1575067335179513150115da367bArun Murthy/** 130584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_led_en() - turn on/off chargign led 130684edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 130784edbeeab67c1575067335179513150115da367bArun Murthy * @on: flag to turn on/off the chargign led 130884edbeeab67c1575067335179513150115da367bArun Murthy * 130984edbeeab67c1575067335179513150115da367bArun Murthy * Power ON/OFF charging LED indication 131084edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 131184edbeeab67c1575067335179513150115da367bArun Murthy */ 131284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_led_en(struct ab8500_charger *di, int on) 131384edbeeab67c1575067335179513150115da367bArun Murthy{ 131484edbeeab67c1575067335179513150115da367bArun Murthy int ret; 131584edbeeab67c1575067335179513150115da367bArun Murthy 131684edbeeab67c1575067335179513150115da367bArun Murthy if (on) { 131784edbeeab67c1575067335179513150115da367bArun Murthy /* Power ON charging LED indicator, set LED current to 5mA */ 131884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 131984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_LED_INDICATOR_PWM_CTRL, 132084edbeeab67c1575067335179513150115da367bArun Murthy (LED_IND_CUR_5MA | LED_INDICATOR_PWM_ENA)); 132184edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 132284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Power ON LED failed\n"); 132384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 132484edbeeab67c1575067335179513150115da367bArun Murthy } 132584edbeeab67c1575067335179513150115da367bArun Murthy /* LED indicator PWM duty cycle 252/256 */ 132684edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 132784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_LED_INDICATOR_PWM_DUTY, 132884edbeeab67c1575067335179513150115da367bArun Murthy LED_INDICATOR_PWM_DUTY_252_256); 132984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 133084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Set LED PWM duty cycle failed\n"); 133184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 133284edbeeab67c1575067335179513150115da367bArun Murthy } 133384edbeeab67c1575067335179513150115da367bArun Murthy } else { 133484edbeeab67c1575067335179513150115da367bArun Murthy /* Power off charging LED indicator */ 133584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 133684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_LED_INDICATOR_PWM_CTRL, 133784edbeeab67c1575067335179513150115da367bArun Murthy LED_INDICATOR_PWM_DIS); 133884edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 133984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Power-off LED failed\n"); 134084edbeeab67c1575067335179513150115da367bArun Murthy return ret; 134184edbeeab67c1575067335179513150115da367bArun Murthy } 134284edbeeab67c1575067335179513150115da367bArun Murthy } 134384edbeeab67c1575067335179513150115da367bArun Murthy 134484edbeeab67c1575067335179513150115da367bArun Murthy return ret; 134584edbeeab67c1575067335179513150115da367bArun Murthy} 134684edbeeab67c1575067335179513150115da367bArun Murthy 134784edbeeab67c1575067335179513150115da367bArun Murthy/** 134884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_en() - enable or disable ac charging 134984edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 135084edbeeab67c1575067335179513150115da367bArun Murthy * @enable: enable/disable flag 135184edbeeab67c1575067335179513150115da367bArun Murthy * @vset: charging voltage 135284edbeeab67c1575067335179513150115da367bArun Murthy * @iset: charging current 135384edbeeab67c1575067335179513150115da367bArun Murthy * 135484edbeeab67c1575067335179513150115da367bArun Murthy * Enable/Disable AC/Mains charging and turns on/off the charging led 135584edbeeab67c1575067335179513150115da367bArun Murthy * respectively. 135684edbeeab67c1575067335179513150115da367bArun Murthy **/ 135784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_en(struct ux500_charger *charger, 135884edbeeab67c1575067335179513150115da367bArun Murthy int enable, int vset, int iset) 135984edbeeab67c1575067335179513150115da367bArun Murthy{ 136084edbeeab67c1575067335179513150115da367bArun Murthy int ret; 136184edbeeab67c1575067335179513150115da367bArun Murthy int volt_index; 136284edbeeab67c1575067335179513150115da367bArun Murthy int curr_index; 136384edbeeab67c1575067335179513150115da367bArun Murthy int input_curr_index; 136484edbeeab67c1575067335179513150115da367bArun Murthy u8 overshoot = 0; 136584edbeeab67c1575067335179513150115da367bArun Murthy 136684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); 136784edbeeab67c1575067335179513150115da367bArun Murthy 136884edbeeab67c1575067335179513150115da367bArun Murthy if (enable) { 136984edbeeab67c1575067335179513150115da367bArun Murthy /* Check if AC is connected */ 137084edbeeab67c1575067335179513150115da367bArun Murthy if (!di->ac.charger_connected) { 137184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "AC charger not connected\n"); 137284edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 137384edbeeab67c1575067335179513150115da367bArun Murthy } 137484edbeeab67c1575067335179513150115da367bArun Murthy 137584edbeeab67c1575067335179513150115da367bArun Murthy /* Enable AC charging */ 137684edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Enable AC: %dmV %dmA\n", vset, iset); 137784edbeeab67c1575067335179513150115da367bArun Murthy 137884edbeeab67c1575067335179513150115da367bArun Murthy /* 137984edbeeab67c1575067335179513150115da367bArun Murthy * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts 138084edbeeab67c1575067335179513150115da367bArun Murthy * will be triggered everytime we enable the VDD ADC supply. 138184edbeeab67c1575067335179513150115da367bArun Murthy * This will turn off charging for a short while. 138284edbeeab67c1575067335179513150115da367bArun Murthy * It can be avoided by having the supply on when 138384edbeeab67c1575067335179513150115da367bArun Murthy * there is a charger enabled. Normally the VDD ADC supply 138484edbeeab67c1575067335179513150115da367bArun Murthy * is enabled everytime a GPADC conversion is triggered. We will 138584edbeeab67c1575067335179513150115da367bArun Murthy * force it to be enabled from this driver to have 138684edbeeab67c1575067335179513150115da367bArun Murthy * the GPADC module independant of the AB8500 chargers 138784edbeeab67c1575067335179513150115da367bArun Murthy */ 138884edbeeab67c1575067335179513150115da367bArun Murthy if (!di->vddadc_en_ac) { 13896de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat ret = regulator_enable(di->regu); 13906de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat if (ret) 13916de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat dev_warn(di->dev, 13926de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat "Failed to enable regulator\n"); 13936de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat else 13946de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat di->vddadc_en_ac = true; 139584edbeeab67c1575067335179513150115da367bArun Murthy } 139684edbeeab67c1575067335179513150115da367bArun Murthy 139784edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the requested voltage or current is valid */ 139884edbeeab67c1575067335179513150115da367bArun Murthy volt_index = ab8500_voltage_to_regval(vset); 1399861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones curr_index = ab8500_current_to_regval(di, iset); 1400861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones input_curr_index = ab8500_current_to_regval(di, 1401b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones di->bm->chg_params->ac_curr_max); 140284edbeeab67c1575067335179513150115da367bArun Murthy if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { 140384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 140484edbeeab67c1575067335179513150115da367bArun Murthy "Charger voltage or current too high, " 140584edbeeab67c1575067335179513150115da367bArun Murthy "charging not started\n"); 140684edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 140784edbeeab67c1575067335179513150115da367bArun Murthy } 140884edbeeab67c1575067335179513150115da367bArun Murthy 140984edbeeab67c1575067335179513150115da367bArun Murthy /* ChVoltLevel: maximum battery charging voltage */ 141084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 141184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_REG, (u8) volt_index); 141284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 141384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 141484edbeeab67c1575067335179513150115da367bArun Murthy return ret; 141584edbeeab67c1575067335179513150115da367bArun Murthy } 141684edbeeab67c1575067335179513150115da367bArun Murthy /* MainChInputCurr: current that can be drawn from the charger*/ 1417f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt ret = ab8500_charger_set_main_in_curr(di, 1418b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones di->bm->chg_params->ac_curr_max); 141984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 1420f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "%s Failed to set MainChInputCurr\n", 1421f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt __func__); 142284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 142384edbeeab67c1575067335179513150115da367bArun Murthy } 142484edbeeab67c1575067335179513150115da367bArun Murthy /* ChOutputCurentLevel: protected output current */ 1425f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt ret = ab8500_charger_set_output_curr(di, iset); 142684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 1427f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "%s " 1428f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt "Failed to set ChOutputCurentLevel\n", 1429f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt __func__); 143084edbeeab67c1575067335179513150115da367bArun Murthy return ret; 143184edbeeab67c1575067335179513150115da367bArun Murthy } 143284edbeeab67c1575067335179513150115da367bArun Murthy 143384edbeeab67c1575067335179513150115da367bArun Murthy /* Check if VBAT overshoot control should be enabled */ 1434b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones if (!di->bm->enable_overshoot) 143584edbeeab67c1575067335179513150115da367bArun Murthy overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N; 143684edbeeab67c1575067335179513150115da367bArun Murthy 143784edbeeab67c1575067335179513150115da367bArun Murthy /* Enable Main Charger */ 143884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 143984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MCH_CTRL1, MAIN_CH_ENA | overshoot); 144084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 144184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 144284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 144384edbeeab67c1575067335179513150115da367bArun Murthy } 144484edbeeab67c1575067335179513150115da367bArun Murthy 144584edbeeab67c1575067335179513150115da367bArun Murthy /* Power on charging LED indication */ 144684edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, true); 144784edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 144884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to enable LED\n"); 144984edbeeab67c1575067335179513150115da367bArun Murthy 145084edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_online = 1; 145184edbeeab67c1575067335179513150115da367bArun Murthy } else { 145284edbeeab67c1575067335179513150115da367bArun Murthy /* Disable AC charging */ 145384edbeeab67c1575067335179513150115da367bArun Murthy if (is_ab8500_1p1_or_earlier(di->parent)) { 145484edbeeab67c1575067335179513150115da367bArun Murthy /* 145584edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the 145684edbeeab67c1575067335179513150115da367bArun Murthy * watchdog logic. That means we have to continously 145784edbeeab67c1575067335179513150115da367bArun Murthy * kick the charger watchdog even when no charger is 145884edbeeab67c1575067335179513150115da367bArun Murthy * connected. This is only valid once the AC charger 145984edbeeab67c1575067335179513150115da367bArun Murthy * has been enabled. This is a bug that is not handled 146084edbeeab67c1575067335179513150115da367bArun Murthy * by the algorithm and the watchdog have to be kicked 146184edbeeab67c1575067335179513150115da367bArun Murthy * by the charger driver when the AC charger 146284edbeeab67c1575067335179513150115da367bArun Murthy * is disabled 146384edbeeab67c1575067335179513150115da367bArun Murthy */ 146484edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac_conn) { 146584edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 146684edbeeab67c1575067335179513150115da367bArun Murthy &di->kick_wd_work, 146784edbeeab67c1575067335179513150115da367bArun Murthy round_jiffies(WD_KICK_INTERVAL)); 146884edbeeab67c1575067335179513150115da367bArun Murthy } 146984edbeeab67c1575067335179513150115da367bArun Murthy 147084edbeeab67c1575067335179513150115da367bArun Murthy /* 147184edbeeab67c1575067335179513150115da367bArun Murthy * We can't turn off charging completely 147284edbeeab67c1575067335179513150115da367bArun Murthy * due to a bug in AB8500 cut1. 147384edbeeab67c1575067335179513150115da367bArun Murthy * If we do, charging will not start again. 147484edbeeab67c1575067335179513150115da367bArun Murthy * That is why we set the lowest voltage 147584edbeeab67c1575067335179513150115da367bArun Murthy * and current possible 147684edbeeab67c1575067335179513150115da367bArun Murthy */ 147784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 147884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 147984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_REG, CH_VOL_LVL_3P5); 148084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 148184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 148284edbeeab67c1575067335179513150115da367bArun Murthy "%s write failed\n", __func__); 148384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 148484edbeeab67c1575067335179513150115da367bArun Murthy } 148584edbeeab67c1575067335179513150115da367bArun Murthy 1486f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt ret = ab8500_charger_set_output_curr(di, 0); 148784edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 1488f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "%s " 1489f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt "Failed to set ChOutputCurentLevel\n", 1490f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt __func__); 149184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 149284edbeeab67c1575067335179513150115da367bArun Murthy } 149384edbeeab67c1575067335179513150115da367bArun Murthy } else { 149484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 149584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 149684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MCH_CTRL1, 0); 149784edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 149884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 149984edbeeab67c1575067335179513150115da367bArun Murthy "%s write failed\n", __func__); 150084edbeeab67c1575067335179513150115da367bArun Murthy return ret; 150184edbeeab67c1575067335179513150115da367bArun Murthy } 150284edbeeab67c1575067335179513150115da367bArun Murthy } 150384edbeeab67c1575067335179513150115da367bArun Murthy 150484edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, false); 150584edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 150684edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to disable LED\n"); 150784edbeeab67c1575067335179513150115da367bArun Murthy 150884edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_online = 0; 150984edbeeab67c1575067335179513150115da367bArun Murthy di->ac.wd_expired = false; 151084edbeeab67c1575067335179513150115da367bArun Murthy 151184edbeeab67c1575067335179513150115da367bArun Murthy /* Disable regulator if enabled */ 151284edbeeab67c1575067335179513150115da367bArun Murthy if (di->vddadc_en_ac) { 151384edbeeab67c1575067335179513150115da367bArun Murthy regulator_disable(di->regu); 151484edbeeab67c1575067335179513150115da367bArun Murthy di->vddadc_en_ac = false; 151584edbeeab67c1575067335179513150115da367bArun Murthy } 151684edbeeab67c1575067335179513150115da367bArun Murthy 151784edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s Disabled AC charging\n", __func__); 151884edbeeab67c1575067335179513150115da367bArun Murthy } 151984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 152084edbeeab67c1575067335179513150115da367bArun Murthy 152184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 152284edbeeab67c1575067335179513150115da367bArun Murthy} 152384edbeeab67c1575067335179513150115da367bArun Murthy 152484edbeeab67c1575067335179513150115da367bArun Murthy/** 152584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_en() - enable usb charging 152684edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 152784edbeeab67c1575067335179513150115da367bArun Murthy * @enable: enable/disable flag 152884edbeeab67c1575067335179513150115da367bArun Murthy * @vset: charging voltage 152984edbeeab67c1575067335179513150115da367bArun Murthy * @ich_out: charger output current 153084edbeeab67c1575067335179513150115da367bArun Murthy * 153184edbeeab67c1575067335179513150115da367bArun Murthy * Enable/Disable USB charging and turns on/off the charging led respectively. 153284edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 153384edbeeab67c1575067335179513150115da367bArun Murthy */ 153484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_en(struct ux500_charger *charger, 153584edbeeab67c1575067335179513150115da367bArun Murthy int enable, int vset, int ich_out) 153684edbeeab67c1575067335179513150115da367bArun Murthy{ 153784edbeeab67c1575067335179513150115da367bArun Murthy int ret; 153884edbeeab67c1575067335179513150115da367bArun Murthy int volt_index; 153984edbeeab67c1575067335179513150115da367bArun Murthy int curr_index; 154084edbeeab67c1575067335179513150115da367bArun Murthy u8 overshoot = 0; 154184edbeeab67c1575067335179513150115da367bArun Murthy 154284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); 154384edbeeab67c1575067335179513150115da367bArun Murthy 154484edbeeab67c1575067335179513150115da367bArun Murthy if (enable) { 154584edbeeab67c1575067335179513150115da367bArun Murthy /* Check if USB is connected */ 154684edbeeab67c1575067335179513150115da367bArun Murthy if (!di->usb.charger_connected) { 154784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "USB charger not connected\n"); 154884edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 154984edbeeab67c1575067335179513150115da367bArun Murthy } 155084edbeeab67c1575067335179513150115da367bArun Murthy 155184edbeeab67c1575067335179513150115da367bArun Murthy /* 155284edbeeab67c1575067335179513150115da367bArun Murthy * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts 155384edbeeab67c1575067335179513150115da367bArun Murthy * will be triggered everytime we enable the VDD ADC supply. 155484edbeeab67c1575067335179513150115da367bArun Murthy * This will turn off charging for a short while. 155584edbeeab67c1575067335179513150115da367bArun Murthy * It can be avoided by having the supply on when 155684edbeeab67c1575067335179513150115da367bArun Murthy * there is a charger enabled. Normally the VDD ADC supply 155784edbeeab67c1575067335179513150115da367bArun Murthy * is enabled everytime a GPADC conversion is triggered. We will 155884edbeeab67c1575067335179513150115da367bArun Murthy * force it to be enabled from this driver to have 155984edbeeab67c1575067335179513150115da367bArun Murthy * the GPADC module independant of the AB8500 chargers 156084edbeeab67c1575067335179513150115da367bArun Murthy */ 156184edbeeab67c1575067335179513150115da367bArun Murthy if (!di->vddadc_en_usb) { 15626de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat ret = regulator_enable(di->regu); 15636de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat if (ret) 15646de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat dev_warn(di->dev, 15656de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat "Failed to enable regulator\n"); 15666de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat else 15676de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat di->vddadc_en_usb = true; 156884edbeeab67c1575067335179513150115da367bArun Murthy } 156984edbeeab67c1575067335179513150115da367bArun Murthy 157084edbeeab67c1575067335179513150115da367bArun Murthy /* Enable USB charging */ 157184edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Enable USB: %dmV %dmA\n", vset, ich_out); 157284edbeeab67c1575067335179513150115da367bArun Murthy 157384edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the requested voltage or current is valid */ 157484edbeeab67c1575067335179513150115da367bArun Murthy volt_index = ab8500_voltage_to_regval(vset); 1575861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones curr_index = ab8500_current_to_regval(di, ich_out); 157684edbeeab67c1575067335179513150115da367bArun Murthy if (volt_index < 0 || curr_index < 0) { 157784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 157884edbeeab67c1575067335179513150115da367bArun Murthy "Charger voltage or current too high, " 157984edbeeab67c1575067335179513150115da367bArun Murthy "charging not started\n"); 158084edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 158184edbeeab67c1575067335179513150115da367bArun Murthy } 158284edbeeab67c1575067335179513150115da367bArun Murthy 158384edbeeab67c1575067335179513150115da367bArun Murthy /* ChVoltLevel: max voltage upto which battery can be charged */ 158484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 158584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_REG, (u8) volt_index); 158684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 158784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 158884edbeeab67c1575067335179513150115da367bArun Murthy return ret; 158984edbeeab67c1575067335179513150115da367bArun Murthy } 159084edbeeab67c1575067335179513150115da367bArun Murthy /* Check if VBAT overshoot control should be enabled */ 1591b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones if (!di->bm->enable_overshoot) 159284edbeeab67c1575067335179513150115da367bArun Murthy overshoot = USB_CHG_NO_OVERSHOOT_ENA_N; 159384edbeeab67c1575067335179513150115da367bArun Murthy 159484edbeeab67c1575067335179513150115da367bArun Murthy /* Enable USB Charger */ 159534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, 159634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "Enabling USB with write to AB8500_USBCH_CTRL1_REG\n"); 159784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 159884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot); 159984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 160084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 160184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 160284edbeeab67c1575067335179513150115da367bArun Murthy } 160384edbeeab67c1575067335179513150115da367bArun Murthy 160484edbeeab67c1575067335179513150115da367bArun Murthy /* If success power on charging LED indication */ 160584edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, true); 160684edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 160784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to enable LED\n"); 160884edbeeab67c1575067335179513150115da367bArun Murthy 160934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->usb.charger_online = 1; 161034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 161134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* USBChInputCurr: current that can be drawn from the usb */ 1612f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones ret = ab8500_charger_set_vbus_in_curr(di, 1613f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 161434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret) { 161534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_err(di->dev, "setting USBChInputCurr failed\n"); 161634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return ret; 161734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 161834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 161934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* ChOutputCurentLevel: protected output current */ 162034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = ab8500_charger_set_output_curr(di, ich_out); 162134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret) { 162234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_err(di->dev, "%s " 162334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "Failed to set ChOutputCurentLevel\n", 162434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson __func__); 162534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return ret; 162634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 162734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 162884edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ); 162984edbeeab67c1575067335179513150115da367bArun Murthy 163084edbeeab67c1575067335179513150115da367bArun Murthy } else { 163184edbeeab67c1575067335179513150115da367bArun Murthy /* Disable USB charging */ 163234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); 163384edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 163484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 163584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USBCH_CTRL1_REG, 0); 163684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 163784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 163884edbeeab67c1575067335179513150115da367bArun Murthy "%s write failed\n", __func__); 163984edbeeab67c1575067335179513150115da367bArun Murthy return ret; 164084edbeeab67c1575067335179513150115da367bArun Murthy } 164184edbeeab67c1575067335179513150115da367bArun Murthy 164284edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, false); 164384edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 164484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to disable LED\n"); 164534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* USBChInputCurr: current that can be drawn from the usb */ 164634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = ab8500_charger_set_vbus_in_curr(di, 0); 164734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret) { 164834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_err(di->dev, "setting USBChInputCurr failed\n"); 164934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return ret; 165034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 165184edbeeab67c1575067335179513150115da367bArun Murthy 165234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* ChOutputCurentLevel: protected output current */ 165334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = ab8500_charger_set_output_curr(di, 0); 165434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret) { 165534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_err(di->dev, "%s " 165634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "Failed to reset ChOutputCurentLevel\n", 165734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson __func__); 165834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return ret; 165934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 166084edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_online = 0; 166184edbeeab67c1575067335179513150115da367bArun Murthy di->usb.wd_expired = false; 166284edbeeab67c1575067335179513150115da367bArun Murthy 166384edbeeab67c1575067335179513150115da367bArun Murthy /* Disable regulator if enabled */ 166484edbeeab67c1575067335179513150115da367bArun Murthy if (di->vddadc_en_usb) { 166584edbeeab67c1575067335179513150115da367bArun Murthy regulator_disable(di->regu); 166684edbeeab67c1575067335179513150115da367bArun Murthy di->vddadc_en_usb = false; 166784edbeeab67c1575067335179513150115da367bArun Murthy } 166884edbeeab67c1575067335179513150115da367bArun Murthy 166984edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); 167084edbeeab67c1575067335179513150115da367bArun Murthy 167184edbeeab67c1575067335179513150115da367bArun Murthy /* Cancel any pending Vbat check work */ 1672b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones cancel_delayed_work(&di->check_vbat_work); 167384edbeeab67c1575067335179513150115da367bArun Murthy 167484edbeeab67c1575067335179513150115da367bArun Murthy } 167584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 167684edbeeab67c1575067335179513150115da367bArun Murthy 167784edbeeab67c1575067335179513150115da367bArun Murthy return ret; 167884edbeeab67c1575067335179513150115da367bArun Murthy} 167984edbeeab67c1575067335179513150115da367bArun Murthy 16808891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jonesstatic int ab8500_external_charger_prepare(struct notifier_block *charger_nb, 16818891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones unsigned long event, void *data) 16828891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones{ 16838891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones int ret; 16848891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones struct device *dev = data; 16858891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones /*Toggle External charger control pin*/ 16868891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, 16878891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones AB8500_SYS_CHARGER_CONTROL_REG, 16888891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones EXTERNAL_CHARGER_DISABLE_REG_VAL); 16898891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones if (ret < 0) { 16908891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones dev_err(dev, "write reg failed %d\n", ret); 16918891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones goto out; 16928891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones } 16938891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, 16948891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones AB8500_SYS_CHARGER_CONTROL_REG, 16958891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones EXTERNAL_CHARGER_ENABLE_REG_VAL); 16968891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones if (ret < 0) 16978891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones dev_err(dev, "Write reg failed %d\n", ret); 16988891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones 16998891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jonesout: 17008891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones return ret; 17018891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones} 17028891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones 170384edbeeab67c1575067335179513150115da367bArun Murthy/** 17044dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * ab8500_charger_usb_check_enable() - enable usb charging 17054dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @charger: pointer to the ux500_charger structure 17064dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @vset: charging voltage 17074dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @iset: charger output current 17084dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * 17094dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * Check if the VBUS charger has been disconnected and reconnected without 17104dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * AB8500 rising an interrupt. Returns 0 on success. 17114dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones */ 17124dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jonesstatic int ab8500_charger_usb_check_enable(struct ux500_charger *charger, 17134dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones int vset, int iset) 17144dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones{ 17154dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones u8 usbch_ctrl1 = 0; 17164dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones int ret = 0; 17174dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17184dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); 17194dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17204dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (!di->usb.charger_connected) 17214dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17224dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17234dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 17244dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones AB8500_USBCH_CTRL1_REG, &usbch_ctrl1); 17254dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (ret < 0) { 17264dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 17274dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17284dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17294dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1); 17304dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17314dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (!(usbch_ctrl1 & USB_CH_ENA)) { 17324dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); 17334dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17344dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones ret = abx500_mask_and_set_register_interruptible(di->dev, 17354dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones AB8500_CHARGER, AB8500_CHARGER_CTRL, 17364dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones DROP_COUNT_RESET, DROP_COUNT_RESET); 17374dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (ret < 0) { 17384dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); 17394dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17404dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17414dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17424dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones ret = ab8500_charger_usb_en(&di->usb_chg, true, vset, iset); 17434dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (ret < 0) { 17444dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_err(di->dev, "Failed to enable VBUS charger %d\n", 17454dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones __LINE__); 17464dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17474dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17484dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17494dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17504dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones} 17514dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17524dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones/** 17534dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * ab8500_charger_ac_check_enable() - enable usb charging 17544dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @charger: pointer to the ux500_charger structure 17554dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @vset: charging voltage 17564dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @iset: charger output current 17574dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * 17584dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * Check if the AC charger has been disconnected and reconnected without 17594dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * AB8500 rising an interrupt. Returns 0 on success. 17604dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones */ 17614dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jonesstatic int ab8500_charger_ac_check_enable(struct ux500_charger *charger, 17624dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones int vset, int iset) 17634dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones{ 17644dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones u8 mainch_ctrl1 = 0; 17654dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones int ret = 0; 17664dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17674dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); 17684dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17694dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (!di->ac.charger_connected) 17704dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17714dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17724dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 17734dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones AB8500_MCH_CTRL1, &mainch_ctrl1); 17744dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (ret < 0) { 17754dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 17764dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17774dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17784dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1); 17794dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17804dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (!(mainch_ctrl1 & MAIN_CH_ENA)) { 17814dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n"); 17824dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17834dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones ret = abx500_mask_and_set_register_interruptible(di->dev, 17844dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones AB8500_CHARGER, AB8500_CHARGER_CTRL, 17854dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones DROP_COUNT_RESET, DROP_COUNT_RESET); 17864dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17874dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (ret < 0) { 17884dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_err(di->dev, "ab8500 write failed %d\n", __LINE__); 17894dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17904dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17914dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 17924dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones ret = ab8500_charger_ac_en(&di->usb_chg, true, vset, iset); 17934dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones if (ret < 0) { 17944dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones dev_err(di->dev, "failed to enable AC charger %d\n", 17954dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones __LINE__); 17964dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 17974dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17984dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones } 17994dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones return ret; 18004dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones} 18014dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones 18024dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones/** 180384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_watchdog_kick() - kick charger watchdog 180484edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 180584edbeeab67c1575067335179513150115da367bArun Murthy * 180684edbeeab67c1575067335179513150115da367bArun Murthy * Kick charger watchdog 180784edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 180884edbeeab67c1575067335179513150115da367bArun Murthy */ 180984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_watchdog_kick(struct ux500_charger *charger) 181084edbeeab67c1575067335179513150115da367bArun Murthy{ 181184edbeeab67c1575067335179513150115da367bArun Murthy int ret; 181284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 181384edbeeab67c1575067335179513150115da367bArun Murthy 181484edbeeab67c1575067335179513150115da367bArun Murthy if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) 181584edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_ac_device_info(charger); 181684edbeeab67c1575067335179513150115da367bArun Murthy else if (charger->psy.type == POWER_SUPPLY_TYPE_USB) 181784edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(charger); 181884edbeeab67c1575067335179513150115da367bArun Murthy else 181984edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 182084edbeeab67c1575067335179513150115da367bArun Murthy 182184edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 182284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 182384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 182484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Failed to kick WD!\n"); 182584edbeeab67c1575067335179513150115da367bArun Murthy 182684edbeeab67c1575067335179513150115da367bArun Murthy return ret; 182784edbeeab67c1575067335179513150115da367bArun Murthy} 182884edbeeab67c1575067335179513150115da367bArun Murthy 182984edbeeab67c1575067335179513150115da367bArun Murthy/** 183084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_update_charger_current() - update charger current 183184edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 183284edbeeab67c1575067335179513150115da367bArun Murthy * 183384edbeeab67c1575067335179513150115da367bArun Murthy * Update the charger output current for the specified charger 183484edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 183584edbeeab67c1575067335179513150115da367bArun Murthy */ 183684edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_update_charger_current(struct ux500_charger *charger, 183784edbeeab67c1575067335179513150115da367bArun Murthy int ich_out) 183884edbeeab67c1575067335179513150115da367bArun Murthy{ 183984edbeeab67c1575067335179513150115da367bArun Murthy int ret; 184084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 184184edbeeab67c1575067335179513150115da367bArun Murthy 184284edbeeab67c1575067335179513150115da367bArun Murthy if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) 184384edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_ac_device_info(charger); 184484edbeeab67c1575067335179513150115da367bArun Murthy else if (charger->psy.type == POWER_SUPPLY_TYPE_USB) 184584edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(charger); 184684edbeeab67c1575067335179513150115da367bArun Murthy else 184784edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 184884edbeeab67c1575067335179513150115da367bArun Murthy 1849f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt ret = ab8500_charger_set_output_curr(di, ich_out); 185084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 1851f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt dev_err(di->dev, "%s " 1852f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt "Failed to set ChOutputCurentLevel\n", 1853f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt __func__); 185484edbeeab67c1575067335179513150115da367bArun Murthy return ret; 185584edbeeab67c1575067335179513150115da367bArun Murthy } 185684edbeeab67c1575067335179513150115da367bArun Murthy 185784edbeeab67c1575067335179513150115da367bArun Murthy /* Reset the main and usb drop input current measurement counter */ 185884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 18594dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones AB8500_CHARGER_CTRL, DROP_COUNT_RESET); 186084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 186184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 186284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 186384edbeeab67c1575067335179513150115da367bArun Murthy } 186484edbeeab67c1575067335179513150115da367bArun Murthy 186584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 186684edbeeab67c1575067335179513150115da367bArun Murthy} 186784edbeeab67c1575067335179513150115da367bArun Murthy 1868db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones/** 1869db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * ab8540_charger_power_path_enable() - enable usb power path mode 1870db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @charger: pointer to the ux500_charger structure 1871db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @enable: enable/disable flag 1872db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * 1873db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Enable or disable the power path for usb mode 1874db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Returns error code in case of failure else 0(on success) 1875db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones */ 1876db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jonesstatic int ab8540_charger_power_path_enable(struct ux500_charger *charger, 1877db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones bool enable) 1878db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones{ 1879db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones int ret; 1880db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones struct ab8500_charger *di; 1881db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1882db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones if (charger->psy.type == POWER_SUPPLY_TYPE_USB) 1883db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones di = to_ab8500_charger_usb_device_info(charger); 1884db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones else 1885db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones return -ENXIO; 1886db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1887db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones ret = abx500_mask_and_set_register_interruptible(di->dev, 1888db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones AB8500_CHARGER, AB8540_USB_PP_MODE_REG, 1889db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones BUS_POWER_PATH_MODE_ENA, enable); 1890db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones if (ret) { 1891db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones dev_err(di->dev, "%s write failed\n", __func__); 1892db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones return ret; 1893db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones } 1894db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1895db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones return ret; 1896db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones} 1897db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1898db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1899db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones/** 1900db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * ab8540_charger_usb_pre_chg_enable() - enable usb pre change 1901db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @charger: pointer to the ux500_charger structure 1902db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @enable: enable/disable flag 1903db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * 1904db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Enable or disable the pre-chage for usb mode 1905db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Returns error code in case of failure else 0(on success) 1906db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones */ 1907db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jonesstatic int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger, 1908db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones bool enable) 1909db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones{ 1910db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones int ret; 1911db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones struct ab8500_charger *di; 1912db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1913db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones if (charger->psy.type == POWER_SUPPLY_TYPE_USB) 1914db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones di = to_ab8500_charger_usb_device_info(charger); 1915db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones else 1916db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones return -ENXIO; 1917db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1918db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones ret = abx500_mask_and_set_register_interruptible(di->dev, 1919db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones AB8500_CHARGER, AB8540_USB_PP_CHR_REG, 1920db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones BUS_POWER_PATH_PRECHG_ENA, enable); 1921db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones if (ret) { 1922db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones dev_err(di->dev, "%s write failed\n", __func__); 1923db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones return ret; 1924db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones } 1925db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 1926db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones return ret; 1927db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones} 1928db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 192984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ext_psy_data(struct device *dev, void *data) 193084edbeeab67c1575067335179513150115da367bArun Murthy{ 193184edbeeab67c1575067335179513150115da367bArun Murthy struct power_supply *psy; 193284edbeeab67c1575067335179513150115da367bArun Murthy struct power_supply *ext; 193384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 193484edbeeab67c1575067335179513150115da367bArun Murthy union power_supply_propval ret; 193584edbeeab67c1575067335179513150115da367bArun Murthy int i, j; 193684edbeeab67c1575067335179513150115da367bArun Murthy bool psy_found = false; 193784edbeeab67c1575067335179513150115da367bArun Murthy struct ux500_charger *usb_chg; 193884edbeeab67c1575067335179513150115da367bArun Murthy 193984edbeeab67c1575067335179513150115da367bArun Murthy usb_chg = (struct ux500_charger *)data; 194084edbeeab67c1575067335179513150115da367bArun Murthy psy = &usb_chg->psy; 194184edbeeab67c1575067335179513150115da367bArun Murthy 194284edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(usb_chg); 194384edbeeab67c1575067335179513150115da367bArun Murthy 194484edbeeab67c1575067335179513150115da367bArun Murthy ext = dev_get_drvdata(dev); 194584edbeeab67c1575067335179513150115da367bArun Murthy 194684edbeeab67c1575067335179513150115da367bArun Murthy /* For all psy where the driver name appears in any supplied_to */ 194784edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ext->num_supplicants; i++) { 194884edbeeab67c1575067335179513150115da367bArun Murthy if (!strcmp(ext->supplied_to[i], psy->name)) 194984edbeeab67c1575067335179513150115da367bArun Murthy psy_found = true; 195084edbeeab67c1575067335179513150115da367bArun Murthy } 195184edbeeab67c1575067335179513150115da367bArun Murthy 195284edbeeab67c1575067335179513150115da367bArun Murthy if (!psy_found) 195384edbeeab67c1575067335179513150115da367bArun Murthy return 0; 195484edbeeab67c1575067335179513150115da367bArun Murthy 195584edbeeab67c1575067335179513150115da367bArun Murthy /* Go through all properties for the psy */ 195684edbeeab67c1575067335179513150115da367bArun Murthy for (j = 0; j < ext->num_properties; j++) { 195784edbeeab67c1575067335179513150115da367bArun Murthy enum power_supply_property prop; 195884edbeeab67c1575067335179513150115da367bArun Murthy prop = ext->properties[j]; 195984edbeeab67c1575067335179513150115da367bArun Murthy 196084edbeeab67c1575067335179513150115da367bArun Murthy if (ext->get_property(ext, prop, &ret)) 196184edbeeab67c1575067335179513150115da367bArun Murthy continue; 196284edbeeab67c1575067335179513150115da367bArun Murthy 196384edbeeab67c1575067335179513150115da367bArun Murthy switch (prop) { 196484edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_NOW: 196584edbeeab67c1575067335179513150115da367bArun Murthy switch (ext->type) { 196684edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_TYPE_BATTERY: 196784edbeeab67c1575067335179513150115da367bArun Murthy di->vbat = ret.intval / 1000; 196884edbeeab67c1575067335179513150115da367bArun Murthy break; 196984edbeeab67c1575067335179513150115da367bArun Murthy default: 197084edbeeab67c1575067335179513150115da367bArun Murthy break; 197184edbeeab67c1575067335179513150115da367bArun Murthy } 197284edbeeab67c1575067335179513150115da367bArun Murthy break; 197384edbeeab67c1575067335179513150115da367bArun Murthy default: 197484edbeeab67c1575067335179513150115da367bArun Murthy break; 197584edbeeab67c1575067335179513150115da367bArun Murthy } 197684edbeeab67c1575067335179513150115da367bArun Murthy } 197784edbeeab67c1575067335179513150115da367bArun Murthy return 0; 197884edbeeab67c1575067335179513150115da367bArun Murthy} 197984edbeeab67c1575067335179513150115da367bArun Murthy 198084edbeeab67c1575067335179513150115da367bArun Murthy/** 198184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_vbat_work() - keep vbus current within spec 198284edbeeab67c1575067335179513150115da367bArun Murthy * @work pointer to the work_struct structure 198384edbeeab67c1575067335179513150115da367bArun Murthy * 198484edbeeab67c1575067335179513150115da367bArun Murthy * Due to a asic bug it is necessary to lower the input current to the vbus 198584edbeeab67c1575067335179513150115da367bArun Murthy * charger when charging with at some specific levels. This issue is only valid 198684edbeeab67c1575067335179513150115da367bArun Murthy * for below a certain battery voltage. This function makes sure that the 198784edbeeab67c1575067335179513150115da367bArun Murthy * the allowed current limit isn't exceeded. 198884edbeeab67c1575067335179513150115da367bArun Murthy */ 198984edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_vbat_work(struct work_struct *work) 199084edbeeab67c1575067335179513150115da367bArun Murthy{ 199184edbeeab67c1575067335179513150115da367bArun Murthy int t = 10; 199284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 199384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_vbat_work.work); 199484edbeeab67c1575067335179513150115da367bArun Murthy 199584edbeeab67c1575067335179513150115da367bArun Murthy class_for_each_device(power_supply_class, NULL, 199684edbeeab67c1575067335179513150115da367bArun Murthy &di->usb_chg.psy, ab8500_charger_get_ext_psy_data); 199784edbeeab67c1575067335179513150115da367bArun Murthy 199884edbeeab67c1575067335179513150115da367bArun Murthy /* First run old_vbat is 0. */ 199984edbeeab67c1575067335179513150115da367bArun Murthy if (di->old_vbat == 0) 200084edbeeab67c1575067335179513150115da367bArun Murthy di->old_vbat = di->vbat; 200184edbeeab67c1575067335179513150115da367bArun Murthy 200284edbeeab67c1575067335179513150115da367bArun Murthy if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED && 200384edbeeab67c1575067335179513150115da367bArun Murthy di->vbat <= VBAT_TRESH_IP_CUR_RED) || 200484edbeeab67c1575067335179513150115da367bArun Murthy (di->old_vbat > VBAT_TRESH_IP_CUR_RED && 200584edbeeab67c1575067335179513150115da367bArun Murthy di->vbat > VBAT_TRESH_IP_CUR_RED))) { 200684edbeeab67c1575067335179513150115da367bArun Murthy 200784edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d," 2008f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones " old: %d\n", di->max_usb_in_curr.usb_type_max, 2009f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->vbat, di->old_vbat); 2010f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones ab8500_charger_set_vbus_in_curr(di, 2011f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 201284edbeeab67c1575067335179513150115da367bArun Murthy power_supply_changed(&di->usb_chg.psy); 201384edbeeab67c1575067335179513150115da367bArun Murthy } 201484edbeeab67c1575067335179513150115da367bArun Murthy 201584edbeeab67c1575067335179513150115da367bArun Murthy di->old_vbat = di->vbat; 201684edbeeab67c1575067335179513150115da367bArun Murthy 201784edbeeab67c1575067335179513150115da367bArun Murthy /* 201884edbeeab67c1575067335179513150115da367bArun Murthy * No need to check the battery voltage every second when not close to 201984edbeeab67c1575067335179513150115da367bArun Murthy * the threshold. 202084edbeeab67c1575067335179513150115da367bArun Murthy */ 202184edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) && 202284edbeeab67c1575067335179513150115da367bArun Murthy (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100))) 202384edbeeab67c1575067335179513150115da367bArun Murthy t = 1; 202484edbeeab67c1575067335179513150115da367bArun Murthy 202584edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ); 202684edbeeab67c1575067335179513150115da367bArun Murthy} 202784edbeeab67c1575067335179513150115da367bArun Murthy 202884edbeeab67c1575067335179513150115da367bArun Murthy/** 202984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_hw_failure_work() - check main charger failure 203084edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 203184edbeeab67c1575067335179513150115da367bArun Murthy * 203284edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the main charger status 203384edbeeab67c1575067335179513150115da367bArun Murthy */ 203484edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_hw_failure_work(struct work_struct *work) 203584edbeeab67c1575067335179513150115da367bArun Murthy{ 203684edbeeab67c1575067335179513150115da367bArun Murthy int ret; 203784edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 203884edbeeab67c1575067335179513150115da367bArun Murthy 203984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 204084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_hw_failure_work.work); 204184edbeeab67c1575067335179513150115da367bArun Murthy 204284edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bits for HW failure is still active */ 204384edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok) { 204484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 204584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); 204684edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 204784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 204884edbeeab67c1575067335179513150115da367bArun Murthy return; 204984edbeeab67c1575067335179513150115da367bArun Murthy } 205084edbeeab67c1575067335179513150115da367bArun Murthy if (!(reg_value & MAIN_CH_NOK)) { 205184edbeeab67c1575067335179513150115da367bArun Murthy di->flags.mainextchnotok = false; 205284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 205384edbeeab67c1575067335179513150115da367bArun Murthy } 205484edbeeab67c1575067335179513150115da367bArun Murthy } 205584edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.vbus_ovv) { 205684edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 205784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, 205884edbeeab67c1575067335179513150115da367bArun Murthy ®_value); 205984edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 206084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 206184edbeeab67c1575067335179513150115da367bArun Murthy return; 206284edbeeab67c1575067335179513150115da367bArun Murthy } 206384edbeeab67c1575067335179513150115da367bArun Murthy if (!(reg_value & VBUS_OVV_TH)) { 206484edbeeab67c1575067335179513150115da367bArun Murthy di->flags.vbus_ovv = false; 206584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 206684edbeeab67c1575067335179513150115da367bArun Murthy } 206784edbeeab67c1575067335179513150115da367bArun Murthy } 206884edbeeab67c1575067335179513150115da367bArun Murthy /* If we still have a failure, schedule a new check */ 206984edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok || di->flags.vbus_ovv) { 207084edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 207184edbeeab67c1575067335179513150115da367bArun Murthy &di->check_hw_failure_work, round_jiffies(HZ)); 207284edbeeab67c1575067335179513150115da367bArun Murthy } 207384edbeeab67c1575067335179513150115da367bArun Murthy} 207484edbeeab67c1575067335179513150115da367bArun Murthy 207584edbeeab67c1575067335179513150115da367bArun Murthy/** 207684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_kick_watchdog_work() - kick the watchdog 207784edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 207884edbeeab67c1575067335179513150115da367bArun Murthy * 207984edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for kicking the charger watchdog. 208084edbeeab67c1575067335179513150115da367bArun Murthy * 208184edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 208284edbeeab67c1575067335179513150115da367bArun Murthy * logic. That means we have to continously kick the charger 208384edbeeab67c1575067335179513150115da367bArun Murthy * watchdog even when no charger is connected. This is only 208484edbeeab67c1575067335179513150115da367bArun Murthy * valid once the AC charger has been enabled. This is 208584edbeeab67c1575067335179513150115da367bArun Murthy * a bug that is not handled by the algorithm and the 208684edbeeab67c1575067335179513150115da367bArun Murthy * watchdog have to be kicked by the charger driver 208784edbeeab67c1575067335179513150115da367bArun Murthy * when the AC charger is disabled 208884edbeeab67c1575067335179513150115da367bArun Murthy */ 208984edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_kick_watchdog_work(struct work_struct *work) 209084edbeeab67c1575067335179513150115da367bArun Murthy{ 209184edbeeab67c1575067335179513150115da367bArun Murthy int ret; 209284edbeeab67c1575067335179513150115da367bArun Murthy 209384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 209484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, kick_wd_work.work); 209584edbeeab67c1575067335179513150115da367bArun Murthy 209684edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 209784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 209884edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 209984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Failed to kick WD!\n"); 210084edbeeab67c1575067335179513150115da367bArun Murthy 210184edbeeab67c1575067335179513150115da367bArun Murthy /* Schedule a new watchdog kick */ 210284edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 210384edbeeab67c1575067335179513150115da367bArun Murthy &di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL)); 210484edbeeab67c1575067335179513150115da367bArun Murthy} 210584edbeeab67c1575067335179513150115da367bArun Murthy 210684edbeeab67c1575067335179513150115da367bArun Murthy/** 210784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_work() - work to get and set main charger status 210884edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 210984edbeeab67c1575067335179513150115da367bArun Murthy * 211084edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the main charger status 211184edbeeab67c1575067335179513150115da367bArun Murthy */ 211284edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_ac_work(struct work_struct *work) 211384edbeeab67c1575067335179513150115da367bArun Murthy{ 211484edbeeab67c1575067335179513150115da367bArun Murthy int ret; 211584edbeeab67c1575067335179513150115da367bArun Murthy 211684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 211784edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, ac_work); 211884edbeeab67c1575067335179513150115da367bArun Murthy 211984edbeeab67c1575067335179513150115da367bArun Murthy /* 212084edbeeab67c1575067335179513150115da367bArun Murthy * Since we can't be sure that the events are received 212184edbeeab67c1575067335179513150115da367bArun Murthy * synchronously, we have the check if the main charger is 212284edbeeab67c1575067335179513150115da367bArun Murthy * connected by reading the status register 212384edbeeab67c1575067335179513150115da367bArun Murthy */ 212434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = ab8500_charger_detect_chargers(di, false); 212584edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 212684edbeeab67c1575067335179513150115da367bArun Murthy return; 212784edbeeab67c1575067335179513150115da367bArun Murthy 212884edbeeab67c1575067335179513150115da367bArun Murthy if (ret & AC_PW_CONN) { 212984edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_connected = 1; 213084edbeeab67c1575067335179513150115da367bArun Murthy di->ac_conn = true; 213184edbeeab67c1575067335179513150115da367bArun Murthy } else { 213284edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_connected = 0; 213384edbeeab67c1575067335179513150115da367bArun Murthy } 213484edbeeab67c1575067335179513150115da367bArun Murthy 213584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 213684edbeeab67c1575067335179513150115da367bArun Murthy sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); 213784edbeeab67c1575067335179513150115da367bArun Murthy} 213884edbeeab67c1575067335179513150115da367bArun Murthy 2139b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesstatic void ab8500_charger_usb_attached_work(struct work_struct *work) 2140b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones{ 2141b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones struct ab8500_charger *di = container_of(work, 2142b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones struct ab8500_charger, 2143b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones usb_charger_attached_work.work); 2144b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC); 2145b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones int ret, i; 2146b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones u8 statval; 2147b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2148b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones for (i = 0; i < 10; i++) { 2149b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones ret = abx500_get_register_interruptible(di->dev, 2150b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones AB8500_CHARGER, 2151b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones AB8500_CH_USBCH_STAT1_REG, 2152b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones &statval); 2153b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones if (ret < 0) { 2154b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 2155b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones goto reschedule; 2156b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } 2157b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones if ((statval & usbch) != usbch) 2158b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones goto reschedule; 2159b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2160b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones msleep(CHARGER_STATUS_POLL); 2161b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } 2162b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2163b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0); 2164b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2165b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_lock(&di->charger_attached_mutex); 2166b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_unlock(&di->charger_attached_mutex); 2167b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2168b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones return; 2169b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2170b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesreschedule: 2171b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones queue_delayed_work(di->charger_wq, 2172b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones &di->usb_charger_attached_work, 2173b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones HZ); 2174b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones} 2175b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2176b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesstatic void ab8500_charger_ac_attached_work(struct work_struct *work) 2177b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones{ 2178b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2179b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones struct ab8500_charger *di = container_of(work, 2180b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones struct ab8500_charger, 2181b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones ac_charger_attached_work.work); 2182b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones int mainch = (MAIN_CH_STATUS2_MAINCHGDROP | 2183b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones MAIN_CH_STATUS2_MAINCHARGERDETDBNC); 2184b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones int ret, i; 2185b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones u8 statval; 2186b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2187b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones for (i = 0; i < 10; i++) { 2188b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones ret = abx500_get_register_interruptible(di->dev, 2189b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones AB8500_CHARGER, 2190b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones AB8500_CH_STATUS2_REG, 2191b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones &statval); 2192b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones if (ret < 0) { 2193b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); 2194b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones goto reschedule; 2195b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } 2196b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2197b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones if ((statval & mainch) != mainch) 2198b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones goto reschedule; 2199b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2200b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones msleep(CHARGER_STATUS_POLL); 2201b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } 2202b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2203b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0); 2204b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones queue_work(di->charger_wq, &di->ac_work); 2205b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2206b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_lock(&di->charger_attached_mutex); 2207b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_unlock(&di->charger_attached_mutex); 2208b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2209b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones return; 2210b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 2211b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesreschedule: 2212b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones queue_delayed_work(di->charger_wq, 2213b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones &di->ac_charger_attached_work, 2214b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones HZ); 2215b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones} 2216b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 221784edbeeab67c1575067335179513150115da367bArun Murthy/** 221884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_usb_type_work() - work to detect USB type 221984edbeeab67c1575067335179513150115da367bArun Murthy * @work: Pointer to the work_struct structure 222084edbeeab67c1575067335179513150115da367bArun Murthy * 222184edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of USB plugged 222284edbeeab67c1575067335179513150115da367bArun Murthy */ 222364eb9b02bfbbc2a53b6092cc12c1f42cc3261dbcAnton Vorontsovstatic void ab8500_charger_detect_usb_type_work(struct work_struct *work) 222484edbeeab67c1575067335179513150115da367bArun Murthy{ 222584edbeeab67c1575067335179513150115da367bArun Murthy int ret; 222684edbeeab67c1575067335179513150115da367bArun Murthy 222784edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 222884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, detect_usb_type_work); 222984edbeeab67c1575067335179513150115da367bArun Murthy 223084edbeeab67c1575067335179513150115da367bArun Murthy /* 223184edbeeab67c1575067335179513150115da367bArun Murthy * Since we can't be sure that the events are received 223284edbeeab67c1575067335179513150115da367bArun Murthy * synchronously, we have the check if is 223384edbeeab67c1575067335179513150115da367bArun Murthy * connected by reading the status register 223484edbeeab67c1575067335179513150115da367bArun Murthy */ 223534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = ab8500_charger_detect_chargers(di, false); 223684edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 223784edbeeab67c1575067335179513150115da367bArun Murthy return; 223884edbeeab67c1575067335179513150115da367bArun Murthy 223984edbeeab67c1575067335179513150115da367bArun Murthy if (!(ret & USB_PW_CONN)) { 224034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__); 224134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->vbus_detected = false; 224284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, false); 224384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 224484edbeeab67c1575067335179513150115da367bArun Murthy } else { 224534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__); 224634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->vbus_detected = true; 224784edbeeab67c1575067335179513150115da367bArun Murthy 224884edbeeab67c1575067335179513150115da367bArun Murthy if (is_ab8500_1p1_or_earlier(di->parent)) { 224984edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_detect_usb_type(di); 225084edbeeab67c1575067335179513150115da367bArun Murthy if (!ret) { 225184edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, true); 225284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, 225384edbeeab67c1575067335179513150115da367bArun Murthy &di->usb_chg.psy); 225484edbeeab67c1575067335179513150115da367bArun Murthy } 225584edbeeab67c1575067335179513150115da367bArun Murthy } else { 225634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* 225734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * For ABB cut2.0 and onwards we have an IRQ, 225884edbeeab67c1575067335179513150115da367bArun Murthy * USB_LINK_STATUS that will be triggered when the USB 225984edbeeab67c1575067335179513150115da367bArun Murthy * link status changes. The exception is USB connected 226084edbeeab67c1575067335179513150115da367bArun Murthy * during startup. Then we don't get a 226184edbeeab67c1575067335179513150115da367bArun Murthy * USB_LINK_STATUS IRQ 226284edbeeab67c1575067335179513150115da367bArun Murthy */ 226384edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbus_detected_start) { 226484edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected_start = false; 226584edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_detect_usb_type(di); 226684edbeeab67c1575067335179513150115da367bArun Murthy if (!ret) { 226784edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, 226884edbeeab67c1575067335179513150115da367bArun Murthy true); 226984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, 227084edbeeab67c1575067335179513150115da367bArun Murthy &di->usb_chg.psy); 227184edbeeab67c1575067335179513150115da367bArun Murthy } 227284edbeeab67c1575067335179513150115da367bArun Murthy } 227384edbeeab67c1575067335179513150115da367bArun Murthy } 227484edbeeab67c1575067335179513150115da367bArun Murthy } 227584edbeeab67c1575067335179513150115da367bArun Murthy} 227684edbeeab67c1575067335179513150115da367bArun Murthy 227784edbeeab67c1575067335179513150115da367bArun Murthy/** 227834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * ab8500_charger_usb_link_attach_work() - work to detect USB type 22794b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper * @work: pointer to the work_struct structure 22804b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper * 22814b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper * Detect the type of USB plugged 22824b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper */ 22834b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooperstatic void ab8500_charger_usb_link_attach_work(struct work_struct *work) 22844b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper{ 22854b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper struct ab8500_charger *di = 22864b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper container_of(work, struct ab8500_charger, attach_work.work); 22874b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper int ret; 22884b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper 22894b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper /* Update maximum input current if USB enumeration is not detected */ 22904b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper if (!di->usb.charger_online) { 2291f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones ret = ab8500_charger_set_vbus_in_curr(di, 2292f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 22934b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper if (ret) 22944b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper return; 22954b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper } 22964b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper 22974b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper ab8500_charger_set_usb_connected(di, true); 22984b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper ab8500_power_supply_changed(di, &di->usb_chg.psy); 22994b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper} 23004b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper 23014b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper/** 230284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_link_status_work() - work to detect USB type 230384edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 230484edbeeab67c1575067335179513150115da367bArun Murthy * 230584edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of USB plugged 230684edbeeab67c1575067335179513150115da367bArun Murthy */ 230784edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_usb_link_status_work(struct work_struct *work) 230884edbeeab67c1575067335179513150115da367bArun Murthy{ 2309ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver int detected_chargers; 231084edbeeab67c1575067335179513150115da367bArun Murthy int ret; 2311ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver u8 val; 2312d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg u8 link_status; 231384edbeeab67c1575067335179513150115da367bArun Murthy 231484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 231584edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, usb_link_status_work); 231684edbeeab67c1575067335179513150115da367bArun Murthy 231784edbeeab67c1575067335179513150115da367bArun Murthy /* 231884edbeeab67c1575067335179513150115da367bArun Murthy * Since we can't be sure that the events are received 231984edbeeab67c1575067335179513150115da367bArun Murthy * synchronously, we have the check if is 232084edbeeab67c1575067335179513150115da367bArun Murthy * connected by reading the status register 232184edbeeab67c1575067335179513150115da367bArun Murthy */ 232234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson detected_chargers = ab8500_charger_detect_chargers(di, false); 2323ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver if (detected_chargers < 0) 232484edbeeab67c1575067335179513150115da367bArun Murthy return; 232584edbeeab67c1575067335179513150115da367bArun Murthy 2326ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver /* 2327ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver * Some chargers that breaks the USB spec is 2328ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver * identified as invalid by AB8500 and it refuse 2329ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver * to start the charging process. but by jumping 2330ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver * thru a few hoops it can be forced to start. 2331ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver */ 233288efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper if (is_ab8500(di->parent)) 233388efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 233488efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper AB8500_USB_LINE_STAT_REG, &val); 233588efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper else 233688efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 233788efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper AB8500_USB_LINK1_STAT_REG, &val); 233888efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper 2339ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver if (ret >= 0) 2340ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val); 2341ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver else 2342ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver dev_dbg(di->dev, "Error reading USB link status\n"); 2343ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver 2344861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8500(di->parent)) 2345d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg link_status = AB8500_USB_LINK_STATUS; 2346861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 2347861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones link_status = AB8505_USB_LINK_STATUS; 2348d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg 2349ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver if (detected_chargers & USB_PW_CONN) { 2350861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (((val & link_status) >> USB_LINK_STATUS_SHIFT) == 2351861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones USB_STAT_NOT_VALID_LINK && 2352ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver di->invalid_charger_detect_state == 0) { 2353861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_dbg(di->dev, 2354861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones "Invalid charger detected, state= 0\n"); 2355ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver /*Enable charger*/ 2356ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver abx500_mask_and_set_register_interruptible(di->dev, 2357861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones AB8500_CHARGER, AB8500_USBCH_CTRL1_REG, 2358861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones USB_CH_ENA, USB_CH_ENA); 2359ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver /*Enable charger detection*/ 2360b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper abx500_mask_and_set_register_interruptible(di->dev, 2361b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper AB8500_USB, AB8500_USB_LINE_CTRL2_REG, 2362b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper USB_CH_DET, USB_CH_DET); 2363ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver di->invalid_charger_detect_state = 1; 2364ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver /*exit and wait for new link status interrupt.*/ 2365ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver return; 2366ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver 2367ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver } 2368ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver if (di->invalid_charger_detect_state == 1) { 2369861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_dbg(di->dev, 2370861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones "Invalid charger detected, state= 1\n"); 2371ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver /*Stop charger detection*/ 2372b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper abx500_mask_and_set_register_interruptible(di->dev, 2373b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper AB8500_USB, AB8500_USB_LINE_CTRL2_REG, 2374b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper USB_CH_DET, 0x00); 2375ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver /*Check link status*/ 237688efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper if (is_ab8500(di->parent)) 237788efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper ret = abx500_get_register_interruptible(di->dev, 237888efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper AB8500_USB, AB8500_USB_LINE_STAT_REG, 237988efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper &val); 238088efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper else 238188efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper ret = abx500_get_register_interruptible(di->dev, 238288efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper AB8500_USB, AB8500_USB_LINK1_STAT_REG, 238388efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper &val); 238488efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper 2385ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver dev_dbg(di->dev, "USB link status= 0x%02x\n", 2386861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones (val & link_status) >> USB_LINK_STATUS_SHIFT); 2387ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver di->invalid_charger_detect_state = 2; 2388ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver } 2389ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver } else { 2390ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver di->invalid_charger_detect_state = 0; 2391ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver } 2392ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver 2393ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver if (!(detected_chargers & USB_PW_CONN)) { 239434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->vbus_detected = false; 239584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, false); 239684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 23974b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper return; 23984b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper } 239984edbeeab67c1575067335179513150115da367bArun Murthy 240034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev,"%s di->vbus_detected = true\n",__func__); 240134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->vbus_detected = true; 24024b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper ret = ab8500_charger_read_usb_type(di); 240334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret) { 240434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret == -ENXIO) { 240534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* No valid charger type detected */ 240634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ab8500_charger_set_usb_connected(di, false); 240734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ab8500_power_supply_changed(di, &di->usb_chg.psy); 240884edbeeab67c1575067335179513150115da367bArun Murthy } 240934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return; 241034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 241134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 241234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (di->usb_device_is_unrecognised) { 241334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, 241434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "Potential Legacy Charger device. " 241534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "Delay work for %d msec for USB enum " 241634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "to finish", 241734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson WAIT_ACA_RID_ENUMERATION); 241834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson queue_delayed_work(di->charger_wq, 241934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson &di->attach_work, 242034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION)); 242134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } else if (di->is_aca_rid == 1) { 242234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* Only wait once */ 242334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->is_aca_rid++; 242434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, 242534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "%s Wait %d msec for USB enum to finish", 242634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson __func__, WAIT_ACA_RID_ENUMERATION); 242734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson queue_delayed_work(di->charger_wq, 242834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson &di->attach_work, 242934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION)); 243034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } else { 243134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson queue_delayed_work(di->charger_wq, 243234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson &di->attach_work, 243334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 0); 243484edbeeab67c1575067335179513150115da367bArun Murthy } 243584edbeeab67c1575067335179513150115da367bArun Murthy} 243684edbeeab67c1575067335179513150115da367bArun Murthy 243784edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_usb_state_changed_work(struct work_struct *work) 243884edbeeab67c1575067335179513150115da367bArun Murthy{ 243984edbeeab67c1575067335179513150115da367bArun Murthy int ret; 244084edbeeab67c1575067335179513150115da367bArun Murthy unsigned long flags; 244184edbeeab67c1575067335179513150115da367bArun Murthy 244284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 244334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson struct ab8500_charger, usb_state_changed_work.work); 244484edbeeab67c1575067335179513150115da367bArun Murthy 244534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (!di->vbus_detected) { 244634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, 244734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson "%s !di->vbus_detected\n", 244834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson __func__); 244984edbeeab67c1575067335179513150115da367bArun Murthy return; 245034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 245184edbeeab67c1575067335179513150115da367bArun Murthy 245284edbeeab67c1575067335179513150115da367bArun Murthy spin_lock_irqsave(&di->usb_state.usb_lock, flags); 245334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->usb_state.state = di->usb_state.state_tmp; 245434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->usb_state.usb_current = di->usb_state.usb_current_tmp; 245584edbeeab67c1575067335179513150115da367bArun Murthy spin_unlock_irqrestore(&di->usb_state.usb_lock, flags); 245684edbeeab67c1575067335179513150115da367bArun Murthy 245784edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n", 245884edbeeab67c1575067335179513150115da367bArun Murthy __func__, di->usb_state.state, di->usb_state.usb_current); 245984edbeeab67c1575067335179513150115da367bArun Murthy 246084edbeeab67c1575067335179513150115da367bArun Murthy switch (di->usb_state.state) { 246184edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_RESET_HS: 246284edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_RESET_FS: 246384edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_SUSPEND: 246484edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_MAX: 246584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, false); 246684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 246784edbeeab67c1575067335179513150115da367bArun Murthy break; 246884edbeeab67c1575067335179513150115da367bArun Murthy 246984edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_RESUME: 247084edbeeab67c1575067335179513150115da367bArun Murthy /* 247184edbeeab67c1575067335179513150115da367bArun Murthy * when suspend->resume there should be delay 247284edbeeab67c1575067335179513150115da367bArun Murthy * of 1sec for enabling charging 247384edbeeab67c1575067335179513150115da367bArun Murthy */ 247484edbeeab67c1575067335179513150115da367bArun Murthy msleep(1000); 247584edbeeab67c1575067335179513150115da367bArun Murthy /* Intentional fall through */ 247684edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_CONFIGURED: 247784edbeeab67c1575067335179513150115da367bArun Murthy /* 247884edbeeab67c1575067335179513150115da367bArun Murthy * USB is configured, enable charging with the charging 247984edbeeab67c1575067335179513150115da367bArun Murthy * input current obtained from USB driver 248084edbeeab67c1575067335179513150115da367bArun Murthy */ 248184edbeeab67c1575067335179513150115da367bArun Murthy if (!ab8500_charger_get_usb_cur(di)) { 248284edbeeab67c1575067335179513150115da367bArun Murthy /* Update maximum input current */ 248384edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_set_vbus_in_curr(di, 2484f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 248584edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 248684edbeeab67c1575067335179513150115da367bArun Murthy return; 248784edbeeab67c1575067335179513150115da367bArun Murthy 248884edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, true); 248984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 249084edbeeab67c1575067335179513150115da367bArun Murthy } 249184edbeeab67c1575067335179513150115da367bArun Murthy break; 249284edbeeab67c1575067335179513150115da367bArun Murthy 249384edbeeab67c1575067335179513150115da367bArun Murthy default: 249484edbeeab67c1575067335179513150115da367bArun Murthy break; 249584edbeeab67c1575067335179513150115da367bArun Murthy }; 249684edbeeab67c1575067335179513150115da367bArun Murthy} 249784edbeeab67c1575067335179513150115da367bArun Murthy 249884edbeeab67c1575067335179513150115da367bArun Murthy/** 249984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status 250084edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 250184edbeeab67c1575067335179513150115da367bArun Murthy * 250284edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the USB charger Not OK status 250384edbeeab67c1575067335179513150115da367bArun Murthy */ 250484edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_usbchargernotok_work(struct work_struct *work) 250584edbeeab67c1575067335179513150115da367bArun Murthy{ 250684edbeeab67c1575067335179513150115da367bArun Murthy int ret; 250784edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 250884edbeeab67c1575067335179513150115da367bArun Murthy bool prev_status; 250984edbeeab67c1575067335179513150115da367bArun Murthy 251084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 251184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_usbchgnotok_work.work); 251284edbeeab67c1575067335179513150115da367bArun Murthy 251384edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bit for usbchargernotok is still active */ 251484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 251584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); 251684edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 251784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 251884edbeeab67c1575067335179513150115da367bArun Murthy return; 251984edbeeab67c1575067335179513150115da367bArun Murthy } 252084edbeeab67c1575067335179513150115da367bArun Murthy prev_status = di->flags.usbchargernotok; 252184edbeeab67c1575067335179513150115da367bArun Murthy 252284edbeeab67c1575067335179513150115da367bArun Murthy if (reg_value & VBUS_CH_NOK) { 252384edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usbchargernotok = true; 252484edbeeab67c1575067335179513150115da367bArun Murthy /* Check again in 1sec */ 252584edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 252684edbeeab67c1575067335179513150115da367bArun Murthy &di->check_usbchgnotok_work, HZ); 252784edbeeab67c1575067335179513150115da367bArun Murthy } else { 252884edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usbchargernotok = false; 252984edbeeab67c1575067335179513150115da367bArun Murthy di->flags.vbus_collapse = false; 253084edbeeab67c1575067335179513150115da367bArun Murthy } 253184edbeeab67c1575067335179513150115da367bArun Murthy 253284edbeeab67c1575067335179513150115da367bArun Murthy if (prev_status != di->flags.usbchargernotok) 253384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 253484edbeeab67c1575067335179513150115da367bArun Murthy} 253584edbeeab67c1575067335179513150115da367bArun Murthy 253684edbeeab67c1575067335179513150115da367bArun Murthy/** 253784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_main_thermal_prot_work() - check main thermal status 253884edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 253984edbeeab67c1575067335179513150115da367bArun Murthy * 254084edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the Main thermal prot status 254184edbeeab67c1575067335179513150115da367bArun Murthy */ 254284edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_main_thermal_prot_work( 254384edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct *work) 254484edbeeab67c1575067335179513150115da367bArun Murthy{ 254584edbeeab67c1575067335179513150115da367bArun Murthy int ret; 254684edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 254784edbeeab67c1575067335179513150115da367bArun Murthy 254884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 254984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_main_thermal_prot_work); 255084edbeeab67c1575067335179513150115da367bArun Murthy 255184edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bit for main_thermal_prot is still active */ 255284edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 255384edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); 255484edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 255584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 255684edbeeab67c1575067335179513150115da367bArun Murthy return; 255784edbeeab67c1575067335179513150115da367bArun Murthy } 255884edbeeab67c1575067335179513150115da367bArun Murthy if (reg_value & MAIN_CH_TH_PROT) 255984edbeeab67c1575067335179513150115da367bArun Murthy di->flags.main_thermal_prot = true; 256084edbeeab67c1575067335179513150115da367bArun Murthy else 256184edbeeab67c1575067335179513150115da367bArun Murthy di->flags.main_thermal_prot = false; 256284edbeeab67c1575067335179513150115da367bArun Murthy 256384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 256484edbeeab67c1575067335179513150115da367bArun Murthy} 256584edbeeab67c1575067335179513150115da367bArun Murthy 256684edbeeab67c1575067335179513150115da367bArun Murthy/** 256784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status 256884edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 256984edbeeab67c1575067335179513150115da367bArun Murthy * 257084edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the USB thermal prot status 257184edbeeab67c1575067335179513150115da367bArun Murthy */ 257284edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_usb_thermal_prot_work( 257384edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct *work) 257484edbeeab67c1575067335179513150115da367bArun Murthy{ 257584edbeeab67c1575067335179513150115da367bArun Murthy int ret; 257684edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 257784edbeeab67c1575067335179513150115da367bArun Murthy 257884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 257984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_usb_thermal_prot_work); 258084edbeeab67c1575067335179513150115da367bArun Murthy 258184edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bit for usb_thermal_prot is still active */ 258284edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 258384edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); 258484edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 258584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 258684edbeeab67c1575067335179513150115da367bArun Murthy return; 258784edbeeab67c1575067335179513150115da367bArun Murthy } 258884edbeeab67c1575067335179513150115da367bArun Murthy if (reg_value & USB_CH_TH_PROT) 258984edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usb_thermal_prot = true; 259084edbeeab67c1575067335179513150115da367bArun Murthy else 259184edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usb_thermal_prot = false; 259284edbeeab67c1575067335179513150115da367bArun Murthy 259384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 259484edbeeab67c1575067335179513150115da367bArun Murthy} 259584edbeeab67c1575067335179513150115da367bArun Murthy 259684edbeeab67c1575067335179513150115da367bArun Murthy/** 259784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchunplugdet_handler() - main charger unplugged 259884edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 259984edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 260084edbeeab67c1575067335179513150115da367bArun Murthy * 260184edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 260284edbeeab67c1575067335179513150115da367bArun Murthy */ 260384edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di) 260484edbeeab67c1575067335179513150115da367bArun Murthy{ 260584edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 260684edbeeab67c1575067335179513150115da367bArun Murthy 260784edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Main charger unplugged\n"); 260884edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->ac_work); 260984edbeeab67c1575067335179513150115da367bArun Murthy 2610b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones cancel_delayed_work_sync(&di->ac_charger_attached_work); 2611b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_lock(&di->charger_attached_mutex); 2612b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_unlock(&di->charger_attached_mutex); 2613b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 261484edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 261584edbeeab67c1575067335179513150115da367bArun Murthy} 261684edbeeab67c1575067335179513150115da367bArun Murthy 261784edbeeab67c1575067335179513150115da367bArun Murthy/** 261884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchplugdet_handler() - main charger plugged 261984edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 262084edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 262184edbeeab67c1575067335179513150115da367bArun Murthy * 262284edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 262384edbeeab67c1575067335179513150115da367bArun Murthy */ 262484edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di) 262584edbeeab67c1575067335179513150115da367bArun Murthy{ 262684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 262784edbeeab67c1575067335179513150115da367bArun Murthy 262884edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Main charger plugged\n"); 262984edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->ac_work); 263084edbeeab67c1575067335179513150115da367bArun Murthy 2631b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_lock(&di->charger_attached_mutex); 2632b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_unlock(&di->charger_attached_mutex); 2633261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent 2634261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent if (is_ab8500(di->parent)) 2635261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent queue_delayed_work(di->charger_wq, 2636b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones &di->ac_charger_attached_work, 2637b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones HZ); 263884edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 263984edbeeab67c1575067335179513150115da367bArun Murthy} 264084edbeeab67c1575067335179513150115da367bArun Murthy 264184edbeeab67c1575067335179513150115da367bArun Murthy/** 264284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainextchnotok_handler() - main charger not ok 264384edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 264484edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 264584edbeeab67c1575067335179513150115da367bArun Murthy * 264684edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 264784edbeeab67c1575067335179513150115da367bArun Murthy */ 264884edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di) 264984edbeeab67c1575067335179513150115da367bArun Murthy{ 265084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 265184edbeeab67c1575067335179513150115da367bArun Murthy 265284edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Main charger not ok\n"); 265384edbeeab67c1575067335179513150115da367bArun Murthy di->flags.mainextchnotok = true; 265484edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 265584edbeeab67c1575067335179513150115da367bArun Murthy 265684edbeeab67c1575067335179513150115da367bArun Murthy /* Schedule a new HW failure check */ 265784edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); 265884edbeeab67c1575067335179513150115da367bArun Murthy 265984edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 266084edbeeab67c1575067335179513150115da367bArun Murthy} 266184edbeeab67c1575067335179513150115da367bArun Murthy 266284edbeeab67c1575067335179513150115da367bArun Murthy/** 266384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger 266484edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 266584edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 266684edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 266784edbeeab67c1575067335179513150115da367bArun Murthy * 266884edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 266984edbeeab67c1575067335179513150115da367bArun Murthy */ 267084edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di) 267184edbeeab67c1575067335179513150115da367bArun Murthy{ 267284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 267384edbeeab67c1575067335179513150115da367bArun Murthy 267484edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 267584edbeeab67c1575067335179513150115da367bArun Murthy "Die temp above Main charger thermal protection threshold\n"); 267684edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_main_thermal_prot_work); 267784edbeeab67c1575067335179513150115da367bArun Murthy 267884edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 267984edbeeab67c1575067335179513150115da367bArun Murthy} 268084edbeeab67c1575067335179513150115da367bArun Murthy 268184edbeeab67c1575067335179513150115da367bArun Murthy/** 268284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger 268384edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 268484edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 268584edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 268684edbeeab67c1575067335179513150115da367bArun Murthy * 268784edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 268884edbeeab67c1575067335179513150115da367bArun Murthy */ 268984edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di) 269084edbeeab67c1575067335179513150115da367bArun Murthy{ 269184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 269284edbeeab67c1575067335179513150115da367bArun Murthy 269384edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 269484edbeeab67c1575067335179513150115da367bArun Murthy "Die temp ok for Main charger thermal protection threshold\n"); 269584edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_main_thermal_prot_work); 269684edbeeab67c1575067335179513150115da367bArun Murthy 269784edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 269884edbeeab67c1575067335179513150115da367bArun Murthy} 269984edbeeab67c1575067335179513150115da367bArun Murthy 270034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonstatic void ab8500_charger_vbus_drop_end_work(struct work_struct *work) 270134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson{ 270234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson struct ab8500_charger *di = container_of(work, 270334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson struct ab8500_charger, vbus_drop_end_work.work); 2704861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones int ret, curr; 2705f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones u8 reg_value; 270634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 270734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->flags.vbus_drop_end = false; 270834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 270934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* Reset the drop counter */ 271034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson abx500_set_register_interruptible(di->dev, 271134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01); 2712861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones 2713861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8540(di->parent)) 2714861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 2715861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones AB8540_CH_USBCH_STAT3_REG, ®_value); 2716861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 2717861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 2718861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones AB8500_CH_USBCH_STAT2_REG, ®_value); 2719f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones if (ret < 0) { 2720861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_err(di->dev, "%s read failed\n", __func__); 2721861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones return; 2722861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones } 2723861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones 2724861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8540(di->parent)) 2725861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones curr = di->bm->chg_input_curr[ 2726861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones reg_value & AB8540_AUTO_VBUS_IN_CURR_MASK]; 2727861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 2728861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones curr = di->bm->chg_input_curr[ 2729f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT]; 2730861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones 2731861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (di->max_usb_in_curr.calculated_max != curr) { 2732861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones /* USB source is collapsing */ 2733861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->max_usb_in_curr.calculated_max = curr; 2734861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_dbg(di->dev, 2735861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones "VBUS input current limiting to %d mA\n", 2736861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->max_usb_in_curr.calculated_max); 2737861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones } else { 2738861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones /* 2739861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones * USB source can not give more than this amount. 2740861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones * Taking more will collapse the source. 2741861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones */ 2742861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->max_usb_in_curr.set_max = 2743861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->max_usb_in_curr.calculated_max; 2744861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_dbg(di->dev, 2745861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones "VBUS input current limited to %d mA\n", 2746861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->max_usb_in_curr.set_max); 2747f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones } 274834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 274934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (di->usb.charger_connected) 2750f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones ab8500_charger_set_vbus_in_curr(di, 2751f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->max_usb_in_curr.usb_type_max); 275234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson} 275334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 275484edbeeab67c1575067335179513150115da367bArun Murthy/** 275584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusdetf_handler() - VBUS falling detected 275684edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 275784edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 275884edbeeab67c1575067335179513150115da367bArun Murthy * 275984edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 276084edbeeab67c1575067335179513150115da367bArun Murthy */ 276184edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di) 276284edbeeab67c1575067335179513150115da367bArun Murthy{ 276384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 276484edbeeab67c1575067335179513150115da367bArun Murthy 276534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->vbus_detected = false; 276684edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "VBUS falling detected\n"); 276784edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->detect_usb_type_work); 276884edbeeab67c1575067335179513150115da367bArun Murthy 276984edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 277084edbeeab67c1575067335179513150115da367bArun Murthy} 277184edbeeab67c1575067335179513150115da367bArun Murthy 277284edbeeab67c1575067335179513150115da367bArun Murthy/** 277384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusdetr_handler() - VBUS rising detected 277484edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 277584edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 277684edbeeab67c1575067335179513150115da367bArun Murthy * 277784edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 277884edbeeab67c1575067335179513150115da367bArun Murthy */ 277984edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di) 278084edbeeab67c1575067335179513150115da367bArun Murthy{ 278184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 278284edbeeab67c1575067335179513150115da367bArun Murthy 278384edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = true; 278484edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "VBUS rising detected\n"); 278534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 278684edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->detect_usb_type_work); 278784edbeeab67c1575067335179513150115da367bArun Murthy 278884edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 278984edbeeab67c1575067335179513150115da367bArun Murthy} 279084edbeeab67c1575067335179513150115da367bArun Murthy 279184edbeeab67c1575067335179513150115da367bArun Murthy/** 279284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usblinkstatus_handler() - USB link status has changed 279384edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 279484edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 279584edbeeab67c1575067335179513150115da367bArun Murthy * 279684edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 279784edbeeab67c1575067335179513150115da367bArun Murthy */ 279884edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di) 279984edbeeab67c1575067335179513150115da367bArun Murthy{ 280084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 280184edbeeab67c1575067335179513150115da367bArun Murthy 280284edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB link status changed\n"); 280384edbeeab67c1575067335179513150115da367bArun Murthy 280484edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->usb_link_status_work); 280584edbeeab67c1575067335179513150115da367bArun Murthy 280684edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 280784edbeeab67c1575067335179513150115da367bArun Murthy} 280884edbeeab67c1575067335179513150115da367bArun Murthy 280984edbeeab67c1575067335179513150115da367bArun Murthy/** 281084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger 281184edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 281284edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 281384edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 281484edbeeab67c1575067335179513150115da367bArun Murthy * 281584edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 281684edbeeab67c1575067335179513150115da367bArun Murthy */ 281784edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di) 281884edbeeab67c1575067335179513150115da367bArun Murthy{ 281984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 282084edbeeab67c1575067335179513150115da367bArun Murthy 282184edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 282284edbeeab67c1575067335179513150115da367bArun Murthy "Die temp above USB charger thermal protection threshold\n"); 282384edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); 282484edbeeab67c1575067335179513150115da367bArun Murthy 282584edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 282684edbeeab67c1575067335179513150115da367bArun Murthy} 282784edbeeab67c1575067335179513150115da367bArun Murthy 282884edbeeab67c1575067335179513150115da367bArun Murthy/** 282984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger 283084edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 283184edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 283284edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 283384edbeeab67c1575067335179513150115da367bArun Murthy * 283484edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 283584edbeeab67c1575067335179513150115da367bArun Murthy */ 283684edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di) 283784edbeeab67c1575067335179513150115da367bArun Murthy{ 283884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 283984edbeeab67c1575067335179513150115da367bArun Murthy 284084edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 284184edbeeab67c1575067335179513150115da367bArun Murthy "Die temp ok for USB charger thermal protection threshold\n"); 284284edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); 284384edbeeab67c1575067335179513150115da367bArun Murthy 284484edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 284584edbeeab67c1575067335179513150115da367bArun Murthy} 284684edbeeab67c1575067335179513150115da367bArun Murthy 284784edbeeab67c1575067335179513150115da367bArun Murthy/** 284884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected 284984edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 285084edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 285184edbeeab67c1575067335179513150115da367bArun Murthy * 285284edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 285384edbeeab67c1575067335179513150115da367bArun Murthy */ 285484edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di) 285584edbeeab67c1575067335179513150115da367bArun Murthy{ 285684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 285784edbeeab67c1575067335179513150115da367bArun Murthy 285884edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Not allowed USB charger detected\n"); 285984edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0); 286084edbeeab67c1575067335179513150115da367bArun Murthy 286184edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 286284edbeeab67c1575067335179513150115da367bArun Murthy} 286384edbeeab67c1575067335179513150115da367bArun Murthy 286484edbeeab67c1575067335179513150115da367bArun Murthy/** 286584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_chwdexp_handler() - Charger watchdog expired 286684edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 286784edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 286884edbeeab67c1575067335179513150115da367bArun Murthy * 286984edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 287084edbeeab67c1575067335179513150115da367bArun Murthy */ 287184edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di) 287284edbeeab67c1575067335179513150115da367bArun Murthy{ 287384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 287484edbeeab67c1575067335179513150115da367bArun Murthy 287584edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Charger watchdog expired\n"); 287684edbeeab67c1575067335179513150115da367bArun Murthy 287784edbeeab67c1575067335179513150115da367bArun Murthy /* 287884edbeeab67c1575067335179513150115da367bArun Murthy * The charger that was online when the watchdog expired 287984edbeeab67c1575067335179513150115da367bArun Murthy * needs to be restarted for charging to start again 288084edbeeab67c1575067335179513150115da367bArun Murthy */ 288184edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_online) { 288284edbeeab67c1575067335179513150115da367bArun Murthy di->ac.wd_expired = true; 288384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 288484edbeeab67c1575067335179513150115da367bArun Murthy } 288584edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_online) { 288684edbeeab67c1575067335179513150115da367bArun Murthy di->usb.wd_expired = true; 288784edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 288884edbeeab67c1575067335179513150115da367bArun Murthy } 288984edbeeab67c1575067335179513150115da367bArun Murthy 289084edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 289184edbeeab67c1575067335179513150115da367bArun Murthy} 289284edbeeab67c1575067335179513150115da367bArun Murthy 289384edbeeab67c1575067335179513150115da367bArun Murthy/** 289434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * ab8500_charger_vbuschdropend_handler() - VBUS drop removed 289534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @irq: interrupt number 289634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @_di: pointer to the ab8500_charger structure 289734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * 289834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * Returns IRQ status(IRQ_HANDLED) 289934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson */ 290034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonstatic irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di) 290134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson{ 290234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson struct ab8500_charger *di = _di; 290334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 290434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_dbg(di->dev, "VBUS charger drop ended\n"); 290534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->flags.vbus_drop_end = true; 2906f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones 2907f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones /* 2908f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * VBUS might have dropped due to bad connection. 2909f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * Schedule a new input limit set to the value SW requests. 2910f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones */ 291134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 2912f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ)); 291334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 291434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return IRQ_HANDLED; 291534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson} 291634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 291734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson/** 291884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected 291984edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 292084edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 292184edbeeab67c1575067335179513150115da367bArun Murthy * 292284edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 292384edbeeab67c1575067335179513150115da367bArun Murthy */ 292484edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di) 292584edbeeab67c1575067335179513150115da367bArun Murthy{ 292684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 292784edbeeab67c1575067335179513150115da367bArun Murthy 292884edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "VBUS overvoltage detected\n"); 292984edbeeab67c1575067335179513150115da367bArun Murthy di->flags.vbus_ovv = true; 293084edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 293184edbeeab67c1575067335179513150115da367bArun Murthy 293284edbeeab67c1575067335179513150115da367bArun Murthy /* Schedule a new HW failure check */ 293384edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); 293484edbeeab67c1575067335179513150115da367bArun Murthy 293584edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 293684edbeeab67c1575067335179513150115da367bArun Murthy} 293784edbeeab67c1575067335179513150115da367bArun Murthy 293884edbeeab67c1575067335179513150115da367bArun Murthy/** 293984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_get_property() - get the ac/mains properties 294084edbeeab67c1575067335179513150115da367bArun Murthy * @psy: pointer to the power_supply structure 294184edbeeab67c1575067335179513150115da367bArun Murthy * @psp: pointer to the power_supply_property structure 294284edbeeab67c1575067335179513150115da367bArun Murthy * @val: pointer to the power_supply_propval union 294384edbeeab67c1575067335179513150115da367bArun Murthy * 294484edbeeab67c1575067335179513150115da367bArun Murthy * This function gets called when an application tries to get the ac/mains 294584edbeeab67c1575067335179513150115da367bArun Murthy * properties by reading the sysfs files. 294684edbeeab67c1575067335179513150115da367bArun Murthy * AC/Mains properties are online, present and voltage. 294784edbeeab67c1575067335179513150115da367bArun Murthy * online: ac/mains charging is in progress or not 294884edbeeab67c1575067335179513150115da367bArun Murthy * present: presence of the ac/mains 294984edbeeab67c1575067335179513150115da367bArun Murthy * voltage: AC/Mains voltage 295084edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 295184edbeeab67c1575067335179513150115da367bArun Murthy */ 295284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_get_property(struct power_supply *psy, 295384edbeeab67c1575067335179513150115da367bArun Murthy enum power_supply_property psp, 295484edbeeab67c1575067335179513150115da367bArun Murthy union power_supply_propval *val) 295584edbeeab67c1575067335179513150115da367bArun Murthy{ 295684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 2957a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg int ret; 295884edbeeab67c1575067335179513150115da367bArun Murthy 295984edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy)); 296084edbeeab67c1575067335179513150115da367bArun Murthy 296184edbeeab67c1575067335179513150115da367bArun Murthy switch (psp) { 296284edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_HEALTH: 296384edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok) 296484edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 296584edbeeab67c1575067335179513150115da367bArun Murthy else if (di->ac.wd_expired || di->usb.wd_expired) 296684edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_DEAD; 296784edbeeab67c1575067335179513150115da367bArun Murthy else if (di->flags.main_thermal_prot) 296884edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 296984edbeeab67c1575067335179513150115da367bArun Murthy else 297084edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_GOOD; 297184edbeeab67c1575067335179513150115da367bArun Murthy break; 297284edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_ONLINE: 297384edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.charger_online; 297484edbeeab67c1575067335179513150115da367bArun Murthy break; 297584edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_PRESENT: 297684edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.charger_connected; 297784edbeeab67c1575067335179513150115da367bArun Murthy break; 297884edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_NOW: 2979a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg ret = ab8500_charger_get_ac_voltage(di); 2980a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg if (ret >= 0) 2981a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg di->ac.charger_voltage = ret; 2982a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg /* On error, use previous value */ 298384edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.charger_voltage * 1000; 298484edbeeab67c1575067335179513150115da367bArun Murthy break; 298584edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_AVG: 298684edbeeab67c1575067335179513150115da367bArun Murthy /* 298784edbeeab67c1575067335179513150115da367bArun Murthy * This property is used to indicate when CV mode is entered 298884edbeeab67c1575067335179513150115da367bArun Murthy * for the AC charger 298984edbeeab67c1575067335179513150115da367bArun Murthy */ 299084edbeeab67c1575067335179513150115da367bArun Murthy di->ac.cv_active = ab8500_charger_ac_cv(di); 299184edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.cv_active; 299284edbeeab67c1575067335179513150115da367bArun Murthy break; 299384edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_CURRENT_NOW: 2994a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg ret = ab8500_charger_get_ac_current(di); 2995a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg if (ret >= 0) 2996a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg di->ac.charger_current = ret; 2997a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg val->intval = di->ac.charger_current * 1000; 299884edbeeab67c1575067335179513150115da367bArun Murthy break; 299984edbeeab67c1575067335179513150115da367bArun Murthy default: 300084edbeeab67c1575067335179513150115da367bArun Murthy return -EINVAL; 300184edbeeab67c1575067335179513150115da367bArun Murthy } 300284edbeeab67c1575067335179513150115da367bArun Murthy return 0; 300384edbeeab67c1575067335179513150115da367bArun Murthy} 300484edbeeab67c1575067335179513150115da367bArun Murthy 300584edbeeab67c1575067335179513150115da367bArun Murthy/** 300684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_get_property() - get the usb properties 300784edbeeab67c1575067335179513150115da367bArun Murthy * @psy: pointer to the power_supply structure 300884edbeeab67c1575067335179513150115da367bArun Murthy * @psp: pointer to the power_supply_property structure 300984edbeeab67c1575067335179513150115da367bArun Murthy * @val: pointer to the power_supply_propval union 301084edbeeab67c1575067335179513150115da367bArun Murthy * 301184edbeeab67c1575067335179513150115da367bArun Murthy * This function gets called when an application tries to get the usb 301284edbeeab67c1575067335179513150115da367bArun Murthy * properties by reading the sysfs files. 301384edbeeab67c1575067335179513150115da367bArun Murthy * USB properties are online, present and voltage. 301484edbeeab67c1575067335179513150115da367bArun Murthy * online: usb charging is in progress or not 301584edbeeab67c1575067335179513150115da367bArun Murthy * present: presence of the usb 301684edbeeab67c1575067335179513150115da367bArun Murthy * voltage: vbus voltage 301784edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 301884edbeeab67c1575067335179513150115da367bArun Murthy */ 301984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_get_property(struct power_supply *psy, 302084edbeeab67c1575067335179513150115da367bArun Murthy enum power_supply_property psp, 302184edbeeab67c1575067335179513150115da367bArun Murthy union power_supply_propval *val) 302284edbeeab67c1575067335179513150115da367bArun Murthy{ 302384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 3024a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg int ret; 302584edbeeab67c1575067335179513150115da367bArun Murthy 302684edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy)); 302784edbeeab67c1575067335179513150115da367bArun Murthy 302884edbeeab67c1575067335179513150115da367bArun Murthy switch (psp) { 302984edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_HEALTH: 303084edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.usbchargernotok) 303184edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 303284edbeeab67c1575067335179513150115da367bArun Murthy else if (di->ac.wd_expired || di->usb.wd_expired) 303384edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_DEAD; 303484edbeeab67c1575067335179513150115da367bArun Murthy else if (di->flags.usb_thermal_prot) 303584edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 303684edbeeab67c1575067335179513150115da367bArun Murthy else if (di->flags.vbus_ovv) 303784edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 303884edbeeab67c1575067335179513150115da367bArun Murthy else 303984edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_GOOD; 304084edbeeab67c1575067335179513150115da367bArun Murthy break; 304184edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_ONLINE: 304284edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.charger_online; 304384edbeeab67c1575067335179513150115da367bArun Murthy break; 304484edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_PRESENT: 304584edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.charger_connected; 304684edbeeab67c1575067335179513150115da367bArun Murthy break; 304784edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_NOW: 3048a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg ret = ab8500_charger_get_vbus_voltage(di); 3049a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg if (ret >= 0) 3050a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg di->usb.charger_voltage = ret; 305184edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.charger_voltage * 1000; 305284edbeeab67c1575067335179513150115da367bArun Murthy break; 305384edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_AVG: 305484edbeeab67c1575067335179513150115da367bArun Murthy /* 305584edbeeab67c1575067335179513150115da367bArun Murthy * This property is used to indicate when CV mode is entered 305684edbeeab67c1575067335179513150115da367bArun Murthy * for the USB charger 305784edbeeab67c1575067335179513150115da367bArun Murthy */ 305884edbeeab67c1575067335179513150115da367bArun Murthy di->usb.cv_active = ab8500_charger_usb_cv(di); 305984edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.cv_active; 306084edbeeab67c1575067335179513150115da367bArun Murthy break; 306184edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_CURRENT_NOW: 3062a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg ret = ab8500_charger_get_usb_current(di); 3063a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg if (ret >= 0) 3064a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg di->usb.charger_current = ret; 3065a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg val->intval = di->usb.charger_current * 1000; 306684edbeeab67c1575067335179513150115da367bArun Murthy break; 306784edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_CURRENT_AVG: 306884edbeeab67c1575067335179513150115da367bArun Murthy /* 306984edbeeab67c1575067335179513150115da367bArun Murthy * This property is used to indicate when VBUS has collapsed 307084edbeeab67c1575067335179513150115da367bArun Murthy * due to too high output current from the USB charger 307184edbeeab67c1575067335179513150115da367bArun Murthy */ 307284edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.vbus_collapse) 307384edbeeab67c1575067335179513150115da367bArun Murthy val->intval = 1; 307484edbeeab67c1575067335179513150115da367bArun Murthy else 307584edbeeab67c1575067335179513150115da367bArun Murthy val->intval = 0; 307684edbeeab67c1575067335179513150115da367bArun Murthy break; 307784edbeeab67c1575067335179513150115da367bArun Murthy default: 307884edbeeab67c1575067335179513150115da367bArun Murthy return -EINVAL; 307984edbeeab67c1575067335179513150115da367bArun Murthy } 308084edbeeab67c1575067335179513150115da367bArun Murthy return 0; 308184edbeeab67c1575067335179513150115da367bArun Murthy} 308284edbeeab67c1575067335179513150115da367bArun Murthy 308384edbeeab67c1575067335179513150115da367bArun Murthy/** 308484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_init_hw_registers() - Set up charger related registers 308584edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 308684edbeeab67c1575067335179513150115da367bArun Murthy * 308784edbeeab67c1575067335179513150115da367bArun Murthy * Set up charger OVV, watchdog and maximum voltage registers as well as 308884edbeeab67c1575067335179513150115da367bArun Murthy * charging of the backup battery 308984edbeeab67c1575067335179513150115da367bArun Murthy */ 309084edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_init_hw_registers(struct ab8500_charger *di) 309184edbeeab67c1575067335179513150115da367bArun Murthy{ 309284edbeeab67c1575067335179513150115da367bArun Murthy int ret = 0; 30930f4aa401853e07885707aedfc68c608051b0d6e4Yang QU u8 bup_vch_range = 0, vbup33_vrtcn = 0; 309484edbeeab67c1575067335179513150115da367bArun Murthy 309584edbeeab67c1575067335179513150115da367bArun Murthy /* Setup maximum charger current and voltage for ABB cut2.0 */ 309684edbeeab67c1575067335179513150115da367bArun Murthy if (!is_ab8500_1p1_or_earlier(di->parent)) { 309784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 309884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 309984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6); 310084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 310184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 310284edbeeab67c1575067335179513150115da367bArun Murthy "failed to set CH_VOLT_LVL_MAX_REG\n"); 310384edbeeab67c1575067335179513150115da367bArun Murthy goto out; 310484edbeeab67c1575067335179513150115da367bArun Murthy } 310584edbeeab67c1575067335179513150115da367bArun Murthy 3106861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab8540(di->parent)) 3107861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones ret = abx500_set_register_interruptible(di->dev, 3108861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG, 3109861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones CH_OP_CUR_LVL_2P); 3110861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones else 3111861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones ret = abx500_set_register_interruptible(di->dev, 3112861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG, 3113861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones CH_OP_CUR_LVL_1P6); 311484edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 311584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 311684edbeeab67c1575067335179513150115da367bArun Murthy "failed to set CH_OPT_CRNTLVL_MAX_REG\n"); 311784edbeeab67c1575067335179513150115da367bArun Murthy goto out; 311884edbeeab67c1575067335179513150115da367bArun Murthy } 311984edbeeab67c1575067335179513150115da367bArun Murthy } 312084edbeeab67c1575067335179513150115da367bArun Murthy 3121861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones if (is_ab9540_2p0(di->parent) || is_ab9540_3p0(di->parent) 3122861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones || is_ab8505_2p0(di->parent) || is_ab8540(di->parent)) 31230ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg ret = abx500_mask_and_set_register_interruptible(di->dev, 31240ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg AB8500_CHARGER, 31250ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg AB8500_USBCH_CTRL2_REG, 31260ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg VBUS_AUTO_IN_CURR_LIM_ENA, 31270ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg VBUS_AUTO_IN_CURR_LIM_ENA); 31280ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg else 31290ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg /* 31300ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg * VBUS OVV set to 6.3V and enable automatic current limitation 31310ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg */ 31320ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg ret = abx500_set_register_interruptible(di->dev, 31330ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg AB8500_CHARGER, 31340ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg AB8500_USBCH_CTRL2_REG, 31350ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA); 313684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 31370ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg dev_err(di->dev, 31380ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg "failed to set automatic current limitation\n"); 313984edbeeab67c1575067335179513150115da367bArun Murthy goto out; 314084edbeeab67c1575067335179513150115da367bArun Murthy } 314184edbeeab67c1575067335179513150115da367bArun Murthy 314284edbeeab67c1575067335179513150115da367bArun Murthy /* Enable main watchdog in OTP */ 314384edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 314484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD); 314584edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 314684edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to enable main WD in OTP\n"); 314784edbeeab67c1575067335179513150115da367bArun Murthy goto out; 314884edbeeab67c1575067335179513150115da367bArun Murthy } 314984edbeeab67c1575067335179513150115da367bArun Murthy 315084edbeeab67c1575067335179513150115da367bArun Murthy /* Enable main watchdog */ 315184edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 315284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_SYS_CTRL2_BLOCK, 315384edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA); 315484edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 315584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "faile to enable main watchdog\n"); 315684edbeeab67c1575067335179513150115da367bArun Murthy goto out; 315784edbeeab67c1575067335179513150115da367bArun Murthy } 315884edbeeab67c1575067335179513150115da367bArun Murthy 315984edbeeab67c1575067335179513150115da367bArun Murthy /* 316084edbeeab67c1575067335179513150115da367bArun Murthy * Due to internal synchronisation, Enable and Kick watchdog bits 316184edbeeab67c1575067335179513150115da367bArun Murthy * cannot be enabled in a single write. 316284edbeeab67c1575067335179513150115da367bArun Murthy * A minimum delay of 2*32 kHz period (62.5µs) must be inserted 316384edbeeab67c1575067335179513150115da367bArun Murthy * between writing Enable then Kick bits. 316484edbeeab67c1575067335179513150115da367bArun Murthy */ 316584edbeeab67c1575067335179513150115da367bArun Murthy udelay(63); 316684edbeeab67c1575067335179513150115da367bArun Murthy 316784edbeeab67c1575067335179513150115da367bArun Murthy /* Kick main watchdog */ 316884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 316984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_SYS_CTRL2_BLOCK, 317084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MAIN_WDOG_CTRL_REG, 317184edbeeab67c1575067335179513150115da367bArun Murthy (MAIN_WDOG_ENA | MAIN_WDOG_KICK)); 317284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 317384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to kick main watchdog\n"); 317484edbeeab67c1575067335179513150115da367bArun Murthy goto out; 317584edbeeab67c1575067335179513150115da367bArun Murthy } 317684edbeeab67c1575067335179513150115da367bArun Murthy 317784edbeeab67c1575067335179513150115da367bArun Murthy /* Disable main watchdog */ 317884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 317984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_SYS_CTRL2_BLOCK, 318084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS); 318184edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 318284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to disable main watchdog\n"); 318384edbeeab67c1575067335179513150115da367bArun Murthy goto out; 318484edbeeab67c1575067335179513150115da367bArun Murthy } 318584edbeeab67c1575067335179513150115da367bArun Murthy 318684edbeeab67c1575067335179513150115da367bArun Murthy /* Set watchdog timeout */ 318784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 318884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_WD_TIMER_REG, WD_TIMER); 318984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 319084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to set charger watchdog timeout\n"); 319134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto out; 319234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 319334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 319434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ret = ab8500_charger_led_en(di, false); 319534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (ret < 0) { 319634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson dev_err(di->dev, "failed to disable LED\n"); 319734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson goto out; 319834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson } 319934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 320084edbeeab67c1575067335179513150115da367bArun Murthy /* Backup battery voltage and current */ 32010f4aa401853e07885707aedfc68c608051b0d6e4Yang QU if (di->bm->bkup_bat_v > BUP_VCH_SEL_3P1V) 32020f4aa401853e07885707aedfc68c608051b0d6e4Yang QU bup_vch_range = BUP_VCH_RANGE; 32030f4aa401853e07885707aedfc68c608051b0d6e4Yang QU if (di->bm->bkup_bat_v == BUP_VCH_SEL_3P3V) 32040f4aa401853e07885707aedfc68c608051b0d6e4Yang QU vbup33_vrtcn = VBUP33_VRTCN; 32050f4aa401853e07885707aedfc68c608051b0d6e4Yang QU 320684edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 320784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC, 320884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC_BACKUP_CHG_REG, 32090f4aa401853e07885707aedfc68c608051b0d6e4Yang QU (di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i); 321084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 321184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to setup backup battery charging\n"); 321284edbeeab67c1575067335179513150115da367bArun Murthy goto out; 321384edbeeab67c1575067335179513150115da367bArun Murthy } 32140f4aa401853e07885707aedfc68c608051b0d6e4Yang QU if (is_ab8540(di->parent)) { 32150f4aa401853e07885707aedfc68c608051b0d6e4Yang QU ret = abx500_set_register_interruptible(di->dev, 32160f4aa401853e07885707aedfc68c608051b0d6e4Yang QU AB8500_RTC, 32170f4aa401853e07885707aedfc68c608051b0d6e4Yang QU AB8500_RTC_CTRL1_REG, 32180f4aa401853e07885707aedfc68c608051b0d6e4Yang QU bup_vch_range | vbup33_vrtcn); 32190f4aa401853e07885707aedfc68c608051b0d6e4Yang QU if (ret) { 3220861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_err(di->dev, 3221861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones "failed to setup backup battery charging\n"); 32220f4aa401853e07885707aedfc68c608051b0d6e4Yang QU goto out; 32230f4aa401853e07885707aedfc68c608051b0d6e4Yang QU } 32240f4aa401853e07885707aedfc68c608051b0d6e4Yang QU } 322584edbeeab67c1575067335179513150115da367bArun Murthy 322684edbeeab67c1575067335179513150115da367bArun Murthy /* Enable backup battery charging */ 322784edbeeab67c1575067335179513150115da367bArun Murthy abx500_mask_and_set_register_interruptible(di->dev, 322884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC, AB8500_RTC_CTRL_REG, 322984edbeeab67c1575067335179513150115da367bArun Murthy RTC_BUP_CH_ENA, RTC_BUP_CH_ENA); 323084edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 323184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s mask and set failed\n", __func__); 323284edbeeab67c1575067335179513150115da367bArun Murthy 3233db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones if (is_ab8540(di->parent)) { 3234db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones ret = abx500_mask_and_set_register_interruptible(di->dev, 3235db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones AB8500_CHARGER, AB8540_USB_PP_MODE_REG, 3236db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones BUS_VSYS_VOL_SELECT_MASK, BUS_VSYS_VOL_SELECT_3P6V); 3237db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones if (ret) { 3238861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_err(di->dev, 3239861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones "failed to setup usb power path vsys voltage\n"); 3240db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones goto out; 3241db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones } 3242db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones ret = abx500_mask_and_set_register_interruptible(di->dev, 3243db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones AB8500_CHARGER, AB8540_USB_PP_CHR_REG, 3244db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones BUS_PP_PRECHG_CURRENT_MASK, 0); 3245db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones if (ret) { 3246861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones dev_err(di->dev, 3247861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones "failed to setup usb power path prechage current\n"); 3248db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones goto out; 3249db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones } 3250db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones } 3251db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones 325284edbeeab67c1575067335179513150115da367bArun Murthyout: 325384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 325484edbeeab67c1575067335179513150115da367bArun Murthy} 325584edbeeab67c1575067335179513150115da367bArun Murthy 325684edbeeab67c1575067335179513150115da367bArun Murthy/* 325784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500 charger driver interrupts and their respective isr 325884edbeeab67c1575067335179513150115da367bArun Murthy */ 325984edbeeab67c1575067335179513150115da367bArun Murthystatic struct ab8500_charger_interrupts ab8500_charger_irq[] = { 326084edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler}, 326184edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler}, 326284edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler}, 326384edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler}, 326484edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler}, 326584edbeeab67c1575067335179513150115da367bArun Murthy {"VBUS_DET_F", ab8500_charger_vbusdetf_handler}, 326684edbeeab67c1575067335179513150115da367bArun Murthy {"VBUS_DET_R", ab8500_charger_vbusdetr_handler}, 326784edbeeab67c1575067335179513150115da367bArun Murthy {"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler}, 326884edbeeab67c1575067335179513150115da367bArun Murthy {"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler}, 326984edbeeab67c1575067335179513150115da367bArun Murthy {"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler}, 327084edbeeab67c1575067335179513150115da367bArun Murthy {"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler}, 327184edbeeab67c1575067335179513150115da367bArun Murthy {"VBUS_OVV", ab8500_charger_vbusovv_handler}, 327284edbeeab67c1575067335179513150115da367bArun Murthy {"CH_WD_EXP", ab8500_charger_chwdexp_handler}, 327334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson {"VBUS_CH_DROP_END", ab8500_charger_vbuschdropend_handler}, 327484edbeeab67c1575067335179513150115da367bArun Murthy}; 327584edbeeab67c1575067335179513150115da367bArun Murthy 327684edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_notifier_call(struct notifier_block *nb, 327784edbeeab67c1575067335179513150115da367bArun Murthy unsigned long event, void *power) 327884edbeeab67c1575067335179513150115da367bArun Murthy{ 327984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = 328084edbeeab67c1575067335179513150115da367bArun Murthy container_of(nb, struct ab8500_charger, nb); 328184edbeeab67c1575067335179513150115da367bArun Murthy enum ab8500_usb_state bm_usb_state; 328284edbeeab67c1575067335179513150115da367bArun Murthy unsigned mA = *((unsigned *)power); 328384edbeeab67c1575067335179513150115da367bArun Murthy 3284c9ade0fca3f7939194677353097b16c9795df46bLee Jones if (!di) 3285c9ade0fca3f7939194677353097b16c9795df46bLee Jones return NOTIFY_DONE; 3286c9ade0fca3f7939194677353097b16c9795df46bLee Jones 328784edbeeab67c1575067335179513150115da367bArun Murthy if (event != USB_EVENT_VBUS) { 328884edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "not a standard host, returning\n"); 328984edbeeab67c1575067335179513150115da367bArun Murthy return NOTIFY_DONE; 329084edbeeab67c1575067335179513150115da367bArun Murthy } 329184edbeeab67c1575067335179513150115da367bArun Murthy 329284edbeeab67c1575067335179513150115da367bArun Murthy /* TODO: State is fabricate here. See if charger really needs USB 329384edbeeab67c1575067335179513150115da367bArun Murthy * state or if mA is enough 329484edbeeab67c1575067335179513150115da367bArun Murthy */ 329584edbeeab67c1575067335179513150115da367bArun Murthy if ((di->usb_state.usb_current == 2) && (mA > 2)) 329684edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_RESUME; 329784edbeeab67c1575067335179513150115da367bArun Murthy else if (mA == 0) 329884edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_RESET_HS; 329984edbeeab67c1575067335179513150115da367bArun Murthy else if (mA == 2) 330084edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_SUSPEND; 330184edbeeab67c1575067335179513150115da367bArun Murthy else if (mA >= 8) /* 8, 100, 500 */ 330284edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED; 330384edbeeab67c1575067335179513150115da367bArun Murthy else /* Should never occur */ 330484edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_RESET_FS; 330584edbeeab67c1575067335179513150115da367bArun Murthy 330684edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", 330784edbeeab67c1575067335179513150115da367bArun Murthy __func__, bm_usb_state, mA); 330884edbeeab67c1575067335179513150115da367bArun Murthy 330984edbeeab67c1575067335179513150115da367bArun Murthy spin_lock(&di->usb_state.usb_lock); 331034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->usb_state.state_tmp = bm_usb_state; 331134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson di->usb_state.usb_current_tmp = mA; 331284edbeeab67c1575067335179513150115da367bArun Murthy spin_unlock(&di->usb_state.usb_lock); 331384edbeeab67c1575067335179513150115da367bArun Murthy 331434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson /* 331534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * wait for some time until you get updates from the usb stack 331634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * and negotiations are completed 331734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson */ 331834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson queue_delayed_work(di->charger_wq, &di->usb_state_changed_work, HZ/2); 331984edbeeab67c1575067335179513150115da367bArun Murthy 332084edbeeab67c1575067335179513150115da367bArun Murthy return NOTIFY_OK; 332184edbeeab67c1575067335179513150115da367bArun Murthy} 332284edbeeab67c1575067335179513150115da367bArun Murthy 332384edbeeab67c1575067335179513150115da367bArun Murthy#if defined(CONFIG_PM) 332484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_resume(struct platform_device *pdev) 332584edbeeab67c1575067335179513150115da367bArun Murthy{ 332684edbeeab67c1575067335179513150115da367bArun Murthy int ret; 332784edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = platform_get_drvdata(pdev); 332884edbeeab67c1575067335179513150115da367bArun Murthy 332984edbeeab67c1575067335179513150115da367bArun Murthy /* 333084edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 333184edbeeab67c1575067335179513150115da367bArun Murthy * logic. That means we have to continously kick the charger 333284edbeeab67c1575067335179513150115da367bArun Murthy * watchdog even when no charger is connected. This is only 333384edbeeab67c1575067335179513150115da367bArun Murthy * valid once the AC charger has been enabled. This is 333484edbeeab67c1575067335179513150115da367bArun Murthy * a bug that is not handled by the algorithm and the 333584edbeeab67c1575067335179513150115da367bArun Murthy * watchdog have to be kicked by the charger driver 333684edbeeab67c1575067335179513150115da367bArun Murthy * when the AC charger is disabled 333784edbeeab67c1575067335179513150115da367bArun Murthy */ 333884edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) { 333984edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 334084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 334184edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 334284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Failed to kick WD!\n"); 334384edbeeab67c1575067335179513150115da367bArun Murthy 334484edbeeab67c1575067335179513150115da367bArun Murthy /* If not already pending start a new timer */ 3345b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones queue_delayed_work(di->charger_wq, &di->kick_wd_work, 3346b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones round_jiffies(WD_KICK_INTERVAL)); 334784edbeeab67c1575067335179513150115da367bArun Murthy } 334884edbeeab67c1575067335179513150115da367bArun Murthy 334984edbeeab67c1575067335179513150115da367bArun Murthy /* If we still have a HW failure, schedule a new check */ 335084edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok || di->flags.vbus_ovv) { 335184edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 335284edbeeab67c1575067335179513150115da367bArun Murthy &di->check_hw_failure_work, 0); 335384edbeeab67c1575067335179513150115da367bArun Murthy } 335484edbeeab67c1575067335179513150115da367bArun Murthy 335534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (di->flags.vbus_drop_end) 335634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 0); 335734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 335884edbeeab67c1575067335179513150115da367bArun Murthy return 0; 335984edbeeab67c1575067335179513150115da367bArun Murthy} 336084edbeeab67c1575067335179513150115da367bArun Murthy 336184edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_suspend(struct platform_device *pdev, 336284edbeeab67c1575067335179513150115da367bArun Murthy pm_message_t state) 336384edbeeab67c1575067335179513150115da367bArun Murthy{ 336484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = platform_get_drvdata(pdev); 336584edbeeab67c1575067335179513150115da367bArun Murthy 3366b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones /* Cancel any pending jobs */ 3367b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones cancel_delayed_work(&di->check_hw_failure_work); 3368b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones cancel_delayed_work(&di->vbus_drop_end_work); 336934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 337053ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_delayed_work(&di->attach_work); 337153ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_delayed_work(&di->usb_charger_attached_work); 337253ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_delayed_work(&di->ac_charger_attached_work); 337353ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_delayed_work(&di->check_usbchgnotok_work); 337453ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_delayed_work(&di->check_vbat_work); 337553ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_delayed_work(&di->kick_wd_work); 337653ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg 337753ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_work(&di->usb_link_status_work); 337853ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_work(&di->ac_work); 337953ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg flush_work(&di->detect_usb_type_work); 338053ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg 338134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson if (atomic_read(&di->current_stepping_sessions)) 338234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson return -EAGAIN; 338334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 338484edbeeab67c1575067335179513150115da367bArun Murthy return 0; 338584edbeeab67c1575067335179513150115da367bArun Murthy} 338684edbeeab67c1575067335179513150115da367bArun Murthy#else 338784edbeeab67c1575067335179513150115da367bArun Murthy#define ab8500_charger_suspend NULL 338884edbeeab67c1575067335179513150115da367bArun Murthy#define ab8500_charger_resume NULL 338984edbeeab67c1575067335179513150115da367bArun Murthy#endif 339084edbeeab67c1575067335179513150115da367bArun Murthy 33918891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jonesstatic struct notifier_block charger_nb = { 33928891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones .notifier_call = ab8500_external_charger_prepare, 33938891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones}; 33948891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones 3395415ec69fb1861fc377c65cb30ddc76999891b8e1Bill Pembertonstatic int ab8500_charger_remove(struct platform_device *pdev) 339684edbeeab67c1575067335179513150115da367bArun Murthy{ 339784edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = platform_get_drvdata(pdev); 339884edbeeab67c1575067335179513150115da367bArun Murthy int i, irq, ret; 339984edbeeab67c1575067335179513150115da367bArun Murthy 340084edbeeab67c1575067335179513150115da367bArun Murthy /* Disable AC charging */ 340184edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); 340284edbeeab67c1575067335179513150115da367bArun Murthy 340384edbeeab67c1575067335179513150115da367bArun Murthy /* Disable USB charging */ 340484edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); 340584edbeeab67c1575067335179513150115da367bArun Murthy 340684edbeeab67c1575067335179513150115da367bArun Murthy /* Disable interrupts */ 340784edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 340884edbeeab67c1575067335179513150115da367bArun Murthy irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 340984edbeeab67c1575067335179513150115da367bArun Murthy free_irq(irq, di); 341084edbeeab67c1575067335179513150115da367bArun Murthy } 341184edbeeab67c1575067335179513150115da367bArun Murthy 341284edbeeab67c1575067335179513150115da367bArun Murthy /* Backup battery voltage and current disable */ 341384edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_mask_and_set_register_interruptible(di->dev, 341484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); 341584edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 341684edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s mask and set failed\n", __func__); 341784edbeeab67c1575067335179513150115da367bArun Murthy 3418efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov usb_unregister_notifier(di->usb_phy, &di->nb); 3419721002ec1dd55a52425455826af49cf8853b2d4fKishon Vijay Abraham I usb_put_phy(di->usb_phy); 342084edbeeab67c1575067335179513150115da367bArun Murthy 342184edbeeab67c1575067335179513150115da367bArun Murthy /* Delete the work queue */ 342284edbeeab67c1575067335179513150115da367bArun Murthy destroy_workqueue(di->charger_wq); 342384edbeeab67c1575067335179513150115da367bArun Murthy 34248891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones /* Unregister external charger enable notifier */ 34258891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones if (!di->ac_chg.enabled) 34268891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones blocking_notifier_chain_unregister( 34278891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones &charger_notifier_list, &charger_nb); 34288891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones 342984edbeeab67c1575067335179513150115da367bArun Murthy flush_scheduled_work(); 343072a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones if (di->usb_chg.enabled) 343101ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN power_supply_unregister(&di->usb_chg.psy); 3432405fea1c6691eb8259f2ca879c9348a4cf5d898dMarcus Cooper 3433405fea1c6691eb8259f2ca879c9348a4cf5d898dMarcus Cooper if (di->ac_chg.enabled && !di->ac_chg.external) 343401ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN power_supply_unregister(&di->ac_chg.psy); 3435405fea1c6691eb8259f2ca879c9348a4cf5d898dMarcus Cooper 343684edbeeab67c1575067335179513150115da367bArun Murthy return 0; 343784edbeeab67c1575067335179513150115da367bArun Murthy} 343884edbeeab67c1575067335179513150115da367bArun Murthy 34394aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.Vstatic char *supply_interface[] = { 34404aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V "ab8500_chargalg", 34414aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V "ab8500_fg", 34424aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V "ab8500_btemp", 34434aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V}; 34444aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V 3445c8afa6406e60aec6ff90033e5ffe41a206609296Bill Pembertonstatic int ab8500_charger_probe(struct platform_device *pdev) 344684edbeeab67c1575067335179513150115da367bArun Murthy{ 34474aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V struct device_node *np = pdev->dev.of_node; 34487722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones struct abx500_bm_data *plat = pdev->dev.platform_data; 34492aac3de19b72608f474c90034185c2be4908728fLee Jones struct ab8500_charger *di; 3450b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones int irq, i, charger_status, ret = 0, ch_stat; 345184edbeeab67c1575067335179513150115da367bArun Murthy 34524aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); 34534aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V if (!di) { 34544aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); 345584edbeeab67c1575067335179513150115da367bArun Murthy return -ENOMEM; 34564aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V } 34577722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones 34587722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones if (!plat) { 34597722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones dev_err(&pdev->dev, "no battery management data supplied\n"); 34607722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones return -EINVAL; 34617722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones } 34627722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones di->bm = plat; 34637722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones 34647722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones if (np) { 34657722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); 34667722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones if (ret) { 34677722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones dev_err(&pdev->dev, "failed to get battery information\n"); 34687722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones return ret; 34694aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V } 34707722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); 34717722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones } else 34724aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V di->autopower_cfg = false; 347384edbeeab67c1575067335179513150115da367bArun Murthy 347484edbeeab67c1575067335179513150115da367bArun Murthy /* get parent data */ 347584edbeeab67c1575067335179513150115da367bArun Murthy di->dev = &pdev->dev; 347684edbeeab67c1575067335179513150115da367bArun Murthy di->parent = dev_get_drvdata(pdev->dev.parent); 347784edbeeab67c1575067335179513150115da367bArun Murthy di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); 347884edbeeab67c1575067335179513150115da367bArun Murthy 347984edbeeab67c1575067335179513150115da367bArun Murthy /* initialize lock */ 348084edbeeab67c1575067335179513150115da367bArun Murthy spin_lock_init(&di->usb_state.usb_lock); 348134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson mutex_init(&di->usb_ipt_crnt_lock); 348284edbeeab67c1575067335179513150115da367bArun Murthy 348384edbeeab67c1575067335179513150115da367bArun Murthy di->autopower = false; 3484ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver di->invalid_charger_detect_state = 0; 348584edbeeab67c1575067335179513150115da367bArun Murthy 348684edbeeab67c1575067335179513150115da367bArun Murthy /* AC supply */ 348784edbeeab67c1575067335179513150115da367bArun Murthy /* power_supply base class */ 348884edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.name = "ab8500_ac"; 348984edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS; 349084edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.properties = ab8500_charger_ac_props; 349184edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); 349284edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; 34934aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V di->ac_chg.psy.supplied_to = supply_interface; 34944aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), 349584edbeeab67c1575067335179513150115da367bArun Murthy /* ux500_charger sub-class */ 349684edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.ops.enable = &ab8500_charger_ac_en; 34974dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable; 349884edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 349984edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; 350084edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ 350184edbeeab67c1575067335179513150115da367bArun Murthy ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3502861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->ac_chg.max_out_curr = 3503861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3504e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; 350597034a1e042d4316a83a3f68d61edf6c42e3f265Lee Jones di->ac_chg.enabled = di->bm->ac_enabled; 3506e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy di->ac_chg.external = false; 350784edbeeab67c1575067335179513150115da367bArun Murthy 35088891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones /*notifier for external charger enabling*/ 35098891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones if (!di->ac_chg.enabled) 35108891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones blocking_notifier_chain_register( 35118891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones &charger_notifier_list, &charger_nb); 35128891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones 351384edbeeab67c1575067335179513150115da367bArun Murthy /* USB supply */ 351484edbeeab67c1575067335179513150115da367bArun Murthy /* power_supply base class */ 351584edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.name = "ab8500_usb"; 351684edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.type = POWER_SUPPLY_TYPE_USB; 351784edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.properties = ab8500_charger_usb_props; 351884edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); 351984edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; 35204aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V di->usb_chg.psy.supplied_to = supply_interface; 35214aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), 352284edbeeab67c1575067335179513150115da367bArun Murthy /* ux500_charger sub-class */ 352384edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.ops.enable = &ab8500_charger_usb_en; 35244dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable; 352584edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 352684edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; 3527db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones di->usb_chg.ops.pp_enable = &ab8540_charger_power_path_enable; 3528db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones di->usb_chg.ops.pre_chg_enable = &ab8540_charger_usb_pre_chg_enable; 352984edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ 353084edbeeab67c1575067335179513150115da367bArun Murthy ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3531861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->usb_chg.max_out_curr = 3532861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3533e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; 353497034a1e042d4316a83a3f68d61edf6c42e3f265Lee Jones di->usb_chg.enabled = di->bm->usb_enabled; 3535e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy di->usb_chg.external = false; 3536db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones di->usb_chg.power_path = di->bm->usb_power_path; 3537f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones di->usb_state.usb_current = -1; 353884edbeeab67c1575067335179513150115da367bArun Murthy 353984edbeeab67c1575067335179513150115da367bArun Murthy /* Create a work queue for the charger */ 354084edbeeab67c1575067335179513150115da367bArun Murthy di->charger_wq = 354184edbeeab67c1575067335179513150115da367bArun Murthy create_singlethread_workqueue("ab8500_charger_wq"); 354284edbeeab67c1575067335179513150115da367bArun Murthy if (di->charger_wq == NULL) { 354384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to create work queue\n"); 35444aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V return -ENOMEM; 354584edbeeab67c1575067335179513150115da367bArun Murthy } 354684edbeeab67c1575067335179513150115da367bArun Murthy 3547b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_init(&di->charger_attached_mutex); 3548b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 354984edbeeab67c1575067335179513150115da367bArun Murthy /* Init work for HW failure check */ 3550203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, 355184edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_hw_failure_work); 3552203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, 355384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_usbchargernotok_work); 355484edbeeab67c1575067335179513150115da367bArun Murthy 3555b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones INIT_DELAYED_WORK(&di->ac_charger_attached_work, 3556b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones ab8500_charger_ac_attached_work); 3557b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones INIT_DELAYED_WORK(&di->usb_charger_attached_work, 3558b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones ab8500_charger_usb_attached_work); 3559b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 356084edbeeab67c1575067335179513150115da367bArun Murthy /* 356184edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 356284edbeeab67c1575067335179513150115da367bArun Murthy * logic. That means we have to continously kick the charger 356384edbeeab67c1575067335179513150115da367bArun Murthy * watchdog even when no charger is connected. This is only 356484edbeeab67c1575067335179513150115da367bArun Murthy * valid once the AC charger has been enabled. This is 356584edbeeab67c1575067335179513150115da367bArun Murthy * a bug that is not handled by the algorithm and the 356684edbeeab67c1575067335179513150115da367bArun Murthy * watchdog have to be kicked by the charger driver 356784edbeeab67c1575067335179513150115da367bArun Murthy * when the AC charger is disabled 356884edbeeab67c1575067335179513150115da367bArun Murthy */ 3569203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo INIT_DEFERRABLE_WORK(&di->kick_wd_work, 357084edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_kick_watchdog_work); 357184edbeeab67c1575067335179513150115da367bArun Murthy 3572203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo INIT_DEFERRABLE_WORK(&di->check_vbat_work, 357384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_vbat_work); 357484edbeeab67c1575067335179513150115da367bArun Murthy 35754b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper INIT_DELAYED_WORK(&di->attach_work, 35764b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper ab8500_charger_usb_link_attach_work); 35774b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper 357834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson INIT_DELAYED_WORK(&di->usb_state_changed_work, 357934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ab8500_charger_usb_state_changed_work); 358034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 358134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson INIT_DELAYED_WORK(&di->vbus_drop_end_work, 358234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ab8500_charger_vbus_drop_end_work); 358334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson 358484edbeeab67c1575067335179513150115da367bArun Murthy /* Init work for charger detection */ 358584edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->usb_link_status_work, 358684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_usb_link_status_work); 358784edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->ac_work, ab8500_charger_ac_work); 358884edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->detect_usb_type_work, 358984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_detect_usb_type_work); 359084edbeeab67c1575067335179513150115da367bArun Murthy 359184edbeeab67c1575067335179513150115da367bArun Murthy /* Init work for checking HW status */ 359284edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->check_main_thermal_prot_work, 359384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_main_thermal_prot_work); 359484edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->check_usb_thermal_prot_work, 359584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_usb_thermal_prot_work); 359684edbeeab67c1575067335179513150115da367bArun Murthy 359784edbeeab67c1575067335179513150115da367bArun Murthy /* 359884edbeeab67c1575067335179513150115da367bArun Murthy * VDD ADC supply needs to be enabled from this driver when there 359984edbeeab67c1575067335179513150115da367bArun Murthy * is a charger connected to avoid erroneous BTEMP_HIGH/LOW 360084edbeeab67c1575067335179513150115da367bArun Murthy * interrupts during charging 360184edbeeab67c1575067335179513150115da367bArun Murthy */ 36028feffd109977c045669913f4e80e8811f2212cd9Sachin Kamat di->regu = devm_regulator_get(di->dev, "vddadc"); 360384edbeeab67c1575067335179513150115da367bArun Murthy if (IS_ERR(di->regu)) { 360484edbeeab67c1575067335179513150115da367bArun Murthy ret = PTR_ERR(di->regu); 360584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to get vddadc regulator\n"); 360684edbeeab67c1575067335179513150115da367bArun Murthy goto free_charger_wq; 360784edbeeab67c1575067335179513150115da367bArun Murthy } 360884edbeeab67c1575067335179513150115da367bArun Murthy 360984edbeeab67c1575067335179513150115da367bArun Murthy 361084edbeeab67c1575067335179513150115da367bArun Murthy /* Initialize OVV, and other registers */ 361184edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_init_hw_registers(di); 361284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 361384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to initialize ABB registers\n"); 36148feffd109977c045669913f4e80e8811f2212cd9Sachin Kamat goto free_charger_wq; 361584edbeeab67c1575067335179513150115da367bArun Murthy } 361684edbeeab67c1575067335179513150115da367bArun Murthy 361784edbeeab67c1575067335179513150115da367bArun Murthy /* Register AC charger class */ 361872a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones if (di->ac_chg.enabled) { 361901ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN ret = power_supply_register(di->dev, &di->ac_chg.psy); 362001ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN if (ret) { 362101ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN dev_err(di->dev, "failed to register AC charger\n"); 362201ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN goto free_charger_wq; 362301ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN } 362484edbeeab67c1575067335179513150115da367bArun Murthy } 362584edbeeab67c1575067335179513150115da367bArun Murthy 362684edbeeab67c1575067335179513150115da367bArun Murthy /* Register USB charger class */ 362772a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones if (di->usb_chg.enabled) { 362801ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN ret = power_supply_register(di->dev, &di->usb_chg.psy); 362901ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN if (ret) { 363001ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN dev_err(di->dev, "failed to register USB charger\n"); 363101ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN goto free_ac; 363201ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN } 363384edbeeab67c1575067335179513150115da367bArun Murthy } 363484edbeeab67c1575067335179513150115da367bArun Murthy 3635662dca54ca67c92b7aa14b9a2ec54acacf33ce45Kishon Vijay Abraham I di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); 3636ded017ee6c7b90f7356bd8488f8af1c10ba90490Kishon Vijay Abraham I if (IS_ERR_OR_NULL(di->usb_phy)) { 3637efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov dev_err(di->dev, "failed to get usb transceiver\n"); 363884edbeeab67c1575067335179513150115da367bArun Murthy ret = -EINVAL; 363984edbeeab67c1575067335179513150115da367bArun Murthy goto free_usb; 364084edbeeab67c1575067335179513150115da367bArun Murthy } 364184edbeeab67c1575067335179513150115da367bArun Murthy di->nb.notifier_call = ab8500_charger_usb_notifier_call; 3642efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov ret = usb_register_notifier(di->usb_phy, &di->nb); 364384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 3644efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov dev_err(di->dev, "failed to register usb notifier\n"); 3645efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov goto put_usb_phy; 364684edbeeab67c1575067335179513150115da367bArun Murthy } 364784edbeeab67c1575067335179513150115da367bArun Murthy 364884edbeeab67c1575067335179513150115da367bArun Murthy /* Identify the connected charger types during startup */ 364934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson charger_status = ab8500_charger_detect_chargers(di, true); 365084edbeeab67c1575067335179513150115da367bArun Murthy if (charger_status & AC_PW_CONN) { 365184edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_connected = 1; 365284edbeeab67c1575067335179513150115da367bArun Murthy di->ac_conn = true; 365384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 365484edbeeab67c1575067335179513150115da367bArun Murthy sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); 365584edbeeab67c1575067335179513150115da367bArun Murthy } 365684edbeeab67c1575067335179513150115da367bArun Murthy 365784edbeeab67c1575067335179513150115da367bArun Murthy if (charger_status & USB_PW_CONN) { 365884edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = true; 365984edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected_start = true; 366084edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, 366184edbeeab67c1575067335179513150115da367bArun Murthy &di->detect_usb_type_work); 366284edbeeab67c1575067335179513150115da367bArun Murthy } 366384edbeeab67c1575067335179513150115da367bArun Murthy 366484edbeeab67c1575067335179513150115da367bArun Murthy /* Register interrupts */ 366584edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 366684edbeeab67c1575067335179513150115da367bArun Murthy irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 366784edbeeab67c1575067335179513150115da367bArun Murthy ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, 366884edbeeab67c1575067335179513150115da367bArun Murthy IRQF_SHARED | IRQF_NO_SUSPEND, 366984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_irq[i].name, di); 367084edbeeab67c1575067335179513150115da367bArun Murthy 367184edbeeab67c1575067335179513150115da367bArun Murthy if (ret != 0) { 367284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to request %s IRQ %d: %d\n" 367384edbeeab67c1575067335179513150115da367bArun Murthy , ab8500_charger_irq[i].name, irq, ret); 367484edbeeab67c1575067335179513150115da367bArun Murthy goto free_irq; 367584edbeeab67c1575067335179513150115da367bArun Murthy } 367684edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", 367784edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_irq[i].name, irq, ret); 367884edbeeab67c1575067335179513150115da367bArun Murthy } 367984edbeeab67c1575067335179513150115da367bArun Murthy 368084edbeeab67c1575067335179513150115da367bArun Murthy platform_set_drvdata(pdev, di); 368184edbeeab67c1575067335179513150115da367bArun Murthy 3682b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_lock(&di->charger_attached_mutex); 3683b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 368434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson ch_stat = ab8500_charger_detect_chargers(di, false); 3685b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 3686b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { 3687261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent if (is_ab8500(di->parent)) 3688261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent queue_delayed_work(di->charger_wq, 3689261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent &di->ac_charger_attached_work, 3690261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent HZ); 3691b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } 3692b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { 3693261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent if (is_ab8500(di->parent)) 3694261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent queue_delayed_work(di->charger_wq, 3695261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent &di->usb_charger_attached_work, 3696261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent HZ); 3697b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones } 3698b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 3699b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones mutex_unlock(&di->charger_attached_mutex); 3700b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones 370184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 370284edbeeab67c1575067335179513150115da367bArun Murthy 370384edbeeab67c1575067335179513150115da367bArun Murthyfree_irq: 3704efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov usb_unregister_notifier(di->usb_phy, &di->nb); 370584edbeeab67c1575067335179513150115da367bArun Murthy 370684edbeeab67c1575067335179513150115da367bArun Murthy /* We also have to free all successfully registered irqs */ 370784edbeeab67c1575067335179513150115da367bArun Murthy for (i = i - 1; i >= 0; i--) { 370884edbeeab67c1575067335179513150115da367bArun Murthy irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 370984edbeeab67c1575067335179513150115da367bArun Murthy free_irq(irq, di); 371084edbeeab67c1575067335179513150115da367bArun Murthy } 3711efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsovput_usb_phy: 3712721002ec1dd55a52425455826af49cf8853b2d4fKishon Vijay Abraham I usb_put_phy(di->usb_phy); 371384edbeeab67c1575067335179513150115da367bArun Murthyfree_usb: 371472a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones if (di->usb_chg.enabled) 371501ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN power_supply_unregister(&di->usb_chg.psy); 371684edbeeab67c1575067335179513150115da367bArun Murthyfree_ac: 371772a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones if (di->ac_chg.enabled) 371801ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN power_supply_unregister(&di->ac_chg.psy); 371984edbeeab67c1575067335179513150115da367bArun Murthyfree_charger_wq: 372084edbeeab67c1575067335179513150115da367bArun Murthy destroy_workqueue(di->charger_wq); 372184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 372284edbeeab67c1575067335179513150115da367bArun Murthy} 372384edbeeab67c1575067335179513150115da367bArun Murthy 37244aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.Vstatic const struct of_device_id ab8500_charger_match[] = { 37254aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V { .compatible = "stericsson,ab8500-charger", }, 37264aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V { }, 37274aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V}; 37284aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V 372984edbeeab67c1575067335179513150115da367bArun Murthystatic struct platform_driver ab8500_charger_driver = { 373084edbeeab67c1575067335179513150115da367bArun Murthy .probe = ab8500_charger_probe, 373128ea73f4c67cb3dd8c972b21d9fdf84ea78d6daaBill Pemberton .remove = ab8500_charger_remove, 373284edbeeab67c1575067335179513150115da367bArun Murthy .suspend = ab8500_charger_suspend, 373384edbeeab67c1575067335179513150115da367bArun Murthy .resume = ab8500_charger_resume, 373484edbeeab67c1575067335179513150115da367bArun Murthy .driver = { 373584edbeeab67c1575067335179513150115da367bArun Murthy .name = "ab8500-charger", 373684edbeeab67c1575067335179513150115da367bArun Murthy .owner = THIS_MODULE, 37374aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V .of_match_table = ab8500_charger_match, 373884edbeeab67c1575067335179513150115da367bArun Murthy }, 373984edbeeab67c1575067335179513150115da367bArun Murthy}; 374084edbeeab67c1575067335179513150115da367bArun Murthy 374184edbeeab67c1575067335179513150115da367bArun Murthystatic int __init ab8500_charger_init(void) 374284edbeeab67c1575067335179513150115da367bArun Murthy{ 374384edbeeab67c1575067335179513150115da367bArun Murthy return platform_driver_register(&ab8500_charger_driver); 374484edbeeab67c1575067335179513150115da367bArun Murthy} 374584edbeeab67c1575067335179513150115da367bArun Murthy 374684edbeeab67c1575067335179513150115da367bArun Murthystatic void __exit ab8500_charger_exit(void) 374784edbeeab67c1575067335179513150115da367bArun Murthy{ 374884edbeeab67c1575067335179513150115da367bArun Murthy platform_driver_unregister(&ab8500_charger_driver); 374984edbeeab67c1575067335179513150115da367bArun Murthy} 375084edbeeab67c1575067335179513150115da367bArun Murthy 375184edbeeab67c1575067335179513150115da367bArun Murthysubsys_initcall_sync(ab8500_charger_init); 375284edbeeab67c1575067335179513150115da367bArun Murthymodule_exit(ab8500_charger_exit); 375384edbeeab67c1575067335179513150115da367bArun Murthy 375484edbeeab67c1575067335179513150115da367bArun MurthyMODULE_LICENSE("GPL v2"); 375584edbeeab67c1575067335179513150115da367bArun MurthyMODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); 375684edbeeab67c1575067335179513150115da367bArun MurthyMODULE_ALIAS("platform:ab8500-charger"); 375784edbeeab67c1575067335179513150115da367bArun MurthyMODULE_DESCRIPTION("AB8500 charger management driver"); 3758