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> 1884edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/slab.h> 1984edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/platform_device.h> 2084edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/power_supply.h> 2184edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/completion.h> 2284edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/regulator/consumer.h> 2384edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/err.h> 2484edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/workqueue.h> 2584edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/kobject.h> 2684edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500.h> 2784edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500.h> 2884edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500-bm.h> 2984edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500-gpadc.h> 3084edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ux500_chargalg.h> 3184edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/usb/otg.h> 3284edbeeab67c1575067335179513150115da367bArun Murthy 3384edbeeab67c1575067335179513150115da367bArun Murthy/* Charger constants */ 3484edbeeab67c1575067335179513150115da367bArun Murthy#define NO_PW_CONN 0 3584edbeeab67c1575067335179513150115da367bArun Murthy#define AC_PW_CONN 1 3684edbeeab67c1575067335179513150115da367bArun Murthy#define USB_PW_CONN 2 3784edbeeab67c1575067335179513150115da367bArun Murthy 3884edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_ENA 0x01 3984edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_KICK 0x02 4084edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_DIS 0x00 4184edbeeab67c1575067335179513150115da367bArun Murthy#define CHARG_WD_KICK 0x01 4284edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_ENA 0x01 4384edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02 4484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_ENA 0x01 4584edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CHG_NO_OVERSHOOT_ENA_N 0x02 4684edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_DET 0x01 4784edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_CV_ON 0x04 4884edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_CV_ON 0x08 4984edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET_DBNC100 0x02 5084edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET_DBNC1 0x01 5184edbeeab67c1575067335179513150115da367bArun Murthy#define OTP_ENABLE_WD 0x01 5284edbeeab67c1575067335179513150115da367bArun Murthy 5384edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_INPUT_CURR_SHIFT 4 5484edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_IN_CURR_LIM_SHIFT 4 5584edbeeab67c1575067335179513150115da367bArun Murthy 5684edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_ENA 0x01 5784edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_DIS 0x00 5884edbeeab67c1575067335179513150115da367bArun Murthy#define LED_IND_CUR_5MA 0x04 5984edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_DUTY_252_256 0xBF 6084edbeeab67c1575067335179513150115da367bArun Murthy 6184edbeeab67c1575067335179513150115da367bArun Murthy/* HW failure constants */ 6284edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_TH_PROT 0x02 6384edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_CH_NOK 0x08 6484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_TH_PROT 0x02 6584edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_OVV_TH 0x01 6684edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_NOK 0x01 6784edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET 0x80 6884edbeeab67c1575067335179513150115da367bArun Murthy 6984edbeeab67c1575067335179513150115da367bArun Murthy/* UsbLineStatus register bit masks */ 7084edbeeab67c1575067335179513150115da367bArun Murthy#define AB8500_USB_LINK_STATUS 0x78 7184edbeeab67c1575067335179513150115da367bArun Murthy#define AB8500_STD_HOST_SUSP 0x18 7284edbeeab67c1575067335179513150115da367bArun Murthy 7384edbeeab67c1575067335179513150115da367bArun Murthy/* Watchdog timeout constant */ 7484edbeeab67c1575067335179513150115da367bArun Murthy#define WD_TIMER 0x30 /* 4min */ 7584edbeeab67c1575067335179513150115da367bArun Murthy#define WD_KICK_INTERVAL (60 * HZ) 7684edbeeab67c1575067335179513150115da367bArun Murthy 7784edbeeab67c1575067335179513150115da367bArun Murthy/* Lowest charger voltage is 3.39V -> 0x4E */ 7884edbeeab67c1575067335179513150115da367bArun Murthy#define LOW_VOLT_REG 0x4E 7984edbeeab67c1575067335179513150115da367bArun Murthy 8084edbeeab67c1575067335179513150115da367bArun Murthy/* UsbLineStatus register - usb types */ 8184edbeeab67c1575067335179513150115da367bArun Murthyenum ab8500_charger_link_status { 8284edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_NOT_CONFIGURED, 8384edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_STD_HOST_NC, 8484edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_STD_HOST_C_NS, 8584edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_STD_HOST_C_S, 8684edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HOST_CHG_NM, 8784edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HOST_CHG_HS, 8884edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HOST_CHG_HS_CHIRP, 8984edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_DEDICATED_CHG, 9084edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_A, 9184edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_B, 9284edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_C_NM, 9384edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_C_HS, 9484edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_ACA_RID_C_HS_CHIRP, 9584edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_HM_IDGND, 9684edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_RESERVED, 9784edbeeab67c1575067335179513150115da367bArun Murthy USB_STAT_NOT_VALID_LINK, 9884edbeeab67c1575067335179513150115da367bArun Murthy}; 9984edbeeab67c1575067335179513150115da367bArun Murthy 10084edbeeab67c1575067335179513150115da367bArun Murthyenum ab8500_usb_state { 10184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_RESET_HS, /* HighSpeed Reset */ 10284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_RESET_FS, /* FullSpeed/LowSpeed Reset */ 10384edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_CONFIGURED, 10484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_SUSPEND, 10584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_RESUME, 10684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_BM_USB_STATE_MAX, 10784edbeeab67c1575067335179513150115da367bArun Murthy}; 10884edbeeab67c1575067335179513150115da367bArun Murthy 10984edbeeab67c1575067335179513150115da367bArun Murthy/* VBUS input current limits supported in AB8500 in mA */ 11084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P05 50 11184edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P09 98 11284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P19 193 11384edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P29 290 11484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P38 380 11584edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P45 450 11684edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P5 500 11784edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P6 600 11884edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P7 700 11984edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P8 800 12084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P9 900 12184edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P0 1000 12284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P1 1100 12384edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P3 1300 12484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P4 1400 12584edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P5 1500 12684edbeeab67c1575067335179513150115da367bArun Murthy 12784edbeeab67c1575067335179513150115da367bArun Murthy#define VBAT_TRESH_IP_CUR_RED 3800 12884edbeeab67c1575067335179513150115da367bArun Murthy 12984edbeeab67c1575067335179513150115da367bArun Murthy#define to_ab8500_charger_usb_device_info(x) container_of((x), \ 13084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, usb_chg) 13184edbeeab67c1575067335179513150115da367bArun Murthy#define to_ab8500_charger_ac_device_info(x) container_of((x), \ 13284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, ac_chg) 13384edbeeab67c1575067335179513150115da367bArun Murthy 13484edbeeab67c1575067335179513150115da367bArun Murthy/** 13584edbeeab67c1575067335179513150115da367bArun Murthy * struct ab8500_charger_interrupts - ab8500 interupts 13684edbeeab67c1575067335179513150115da367bArun Murthy * @name: name of the interrupt 13784edbeeab67c1575067335179513150115da367bArun Murthy * @isr function pointer to the isr 13884edbeeab67c1575067335179513150115da367bArun Murthy */ 13984edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_interrupts { 14084edbeeab67c1575067335179513150115da367bArun Murthy char *name; 14184edbeeab67c1575067335179513150115da367bArun Murthy irqreturn_t (*isr)(int irq, void *data); 14284edbeeab67c1575067335179513150115da367bArun Murthy}; 14384edbeeab67c1575067335179513150115da367bArun Murthy 14484edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_info { 14584edbeeab67c1575067335179513150115da367bArun Murthy int charger_connected; 14684edbeeab67c1575067335179513150115da367bArun Murthy int charger_online; 14784edbeeab67c1575067335179513150115da367bArun Murthy int charger_voltage; 14884edbeeab67c1575067335179513150115da367bArun Murthy int cv_active; 14984edbeeab67c1575067335179513150115da367bArun Murthy bool wd_expired; 15084edbeeab67c1575067335179513150115da367bArun Murthy}; 15184edbeeab67c1575067335179513150115da367bArun Murthy 15284edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_event_flags { 15384edbeeab67c1575067335179513150115da367bArun Murthy bool mainextchnotok; 15484edbeeab67c1575067335179513150115da367bArun Murthy bool main_thermal_prot; 15584edbeeab67c1575067335179513150115da367bArun Murthy bool usb_thermal_prot; 15684edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_ovv; 15784edbeeab67c1575067335179513150115da367bArun Murthy bool usbchargernotok; 15884edbeeab67c1575067335179513150115da367bArun Murthy bool chgwdexp; 15984edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_collapse; 16084edbeeab67c1575067335179513150115da367bArun Murthy}; 16184edbeeab67c1575067335179513150115da367bArun Murthy 16284edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_usb_state { 16384edbeeab67c1575067335179513150115da367bArun Murthy bool usb_changed; 16484edbeeab67c1575067335179513150115da367bArun Murthy int usb_current; 16584edbeeab67c1575067335179513150115da367bArun Murthy enum ab8500_usb_state state; 16684edbeeab67c1575067335179513150115da367bArun Murthy spinlock_t usb_lock; 16784edbeeab67c1575067335179513150115da367bArun Murthy}; 16884edbeeab67c1575067335179513150115da367bArun Murthy 16984edbeeab67c1575067335179513150115da367bArun Murthy/** 17084edbeeab67c1575067335179513150115da367bArun Murthy * struct ab8500_charger - ab8500 Charger device information 17184edbeeab67c1575067335179513150115da367bArun Murthy * @dev: Pointer to the structure device 17284edbeeab67c1575067335179513150115da367bArun Murthy * @max_usb_in_curr: Max USB charger input current 17384edbeeab67c1575067335179513150115da367bArun Murthy * @vbus_detected: VBUS detected 17484edbeeab67c1575067335179513150115da367bArun Murthy * @vbus_detected_start: 17584edbeeab67c1575067335179513150115da367bArun Murthy * VBUS detected during startup 17684edbeeab67c1575067335179513150115da367bArun Murthy * @ac_conn: This will be true when the AC charger has been plugged 17784edbeeab67c1575067335179513150115da367bArun Murthy * @vddadc_en_ac: Indicate if VDD ADC supply is enabled because AC 17884edbeeab67c1575067335179513150115da367bArun Murthy * charger is enabled 17984edbeeab67c1575067335179513150115da367bArun Murthy * @vddadc_en_usb: Indicate if VDD ADC supply is enabled because USB 18084edbeeab67c1575067335179513150115da367bArun Murthy * charger is enabled 18184edbeeab67c1575067335179513150115da367bArun Murthy * @vbat Battery voltage 18284edbeeab67c1575067335179513150115da367bArun Murthy * @old_vbat Previously measured battery voltage 18384edbeeab67c1575067335179513150115da367bArun Murthy * @autopower Indicate if we should have automatic pwron after pwrloss 18484edbeeab67c1575067335179513150115da367bArun Murthy * @parent: Pointer to the struct ab8500 18584edbeeab67c1575067335179513150115da367bArun Murthy * @gpadc: Pointer to the struct gpadc 18684edbeeab67c1575067335179513150115da367bArun Murthy * @pdata: Pointer to the abx500_charger platform data 18784edbeeab67c1575067335179513150115da367bArun Murthy * @bat: Pointer to the abx500_bm platform data 18884edbeeab67c1575067335179513150115da367bArun Murthy * @flags: Structure for information about events triggered 18984edbeeab67c1575067335179513150115da367bArun Murthy * @usb_state: Structure for usb stack information 19084edbeeab67c1575067335179513150115da367bArun Murthy * @ac_chg: AC charger power supply 19184edbeeab67c1575067335179513150115da367bArun Murthy * @usb_chg: USB charger power supply 19284edbeeab67c1575067335179513150115da367bArun Murthy * @ac: Structure that holds the AC charger properties 19384edbeeab67c1575067335179513150115da367bArun Murthy * @usb: Structure that holds the USB charger properties 19484edbeeab67c1575067335179513150115da367bArun Murthy * @regu: Pointer to the struct regulator 19584edbeeab67c1575067335179513150115da367bArun Murthy * @charger_wq: Work queue for the IRQs and checking HW state 19684edbeeab67c1575067335179513150115da367bArun Murthy * @check_vbat_work Work for checking vbat threshold to adjust vbus current 19784edbeeab67c1575067335179513150115da367bArun Murthy * @check_hw_failure_work: Work for checking HW state 19884edbeeab67c1575067335179513150115da367bArun Murthy * @check_usbchgnotok_work: Work for checking USB charger not ok status 19984edbeeab67c1575067335179513150115da367bArun Murthy * @kick_wd_work: Work for kicking the charger watchdog in case 20084edbeeab67c1575067335179513150115da367bArun Murthy * of ABB rev 1.* due to the watchog logic bug 20184edbeeab67c1575067335179513150115da367bArun Murthy * @ac_work: Work for checking AC charger connection 20284edbeeab67c1575067335179513150115da367bArun Murthy * @detect_usb_type_work: Work for detecting the USB type connected 20384edbeeab67c1575067335179513150115da367bArun Murthy * @usb_link_status_work: Work for checking the new USB link status 20484edbeeab67c1575067335179513150115da367bArun Murthy * @usb_state_changed_work: Work for checking USB state 20584edbeeab67c1575067335179513150115da367bArun Murthy * @check_main_thermal_prot_work: 20684edbeeab67c1575067335179513150115da367bArun Murthy * Work for checking Main thermal status 20784edbeeab67c1575067335179513150115da367bArun Murthy * @check_usb_thermal_prot_work: 20884edbeeab67c1575067335179513150115da367bArun Murthy * Work for checking USB thermal status 20984edbeeab67c1575067335179513150115da367bArun Murthy */ 21084edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger { 21184edbeeab67c1575067335179513150115da367bArun Murthy struct device *dev; 21284edbeeab67c1575067335179513150115da367bArun Murthy int max_usb_in_curr; 21384edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_detected; 21484edbeeab67c1575067335179513150115da367bArun Murthy bool vbus_detected_start; 21584edbeeab67c1575067335179513150115da367bArun Murthy bool ac_conn; 21684edbeeab67c1575067335179513150115da367bArun Murthy bool vddadc_en_ac; 21784edbeeab67c1575067335179513150115da367bArun Murthy bool vddadc_en_usb; 21884edbeeab67c1575067335179513150115da367bArun Murthy int vbat; 21984edbeeab67c1575067335179513150115da367bArun Murthy int old_vbat; 22084edbeeab67c1575067335179513150115da367bArun Murthy bool autopower; 22184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500 *parent; 22284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_gpadc *gpadc; 22384edbeeab67c1575067335179513150115da367bArun Murthy struct abx500_charger_platform_data *pdata; 22484edbeeab67c1575067335179513150115da367bArun Murthy struct abx500_bm_data *bat; 22584edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_event_flags flags; 22684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_usb_state usb_state; 22784edbeeab67c1575067335179513150115da367bArun Murthy struct ux500_charger ac_chg; 22884edbeeab67c1575067335179513150115da367bArun Murthy struct ux500_charger usb_chg; 22984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_info ac; 23084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger_info usb; 23184edbeeab67c1575067335179513150115da367bArun Murthy struct regulator *regu; 23284edbeeab67c1575067335179513150115da367bArun Murthy struct workqueue_struct *charger_wq; 23384edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work check_vbat_work; 23484edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work check_hw_failure_work; 23584edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work check_usbchgnotok_work; 23684edbeeab67c1575067335179513150115da367bArun Murthy struct delayed_work kick_wd_work; 23784edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct ac_work; 23884edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct detect_usb_type_work; 23984edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct usb_link_status_work; 24084edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct usb_state_changed_work; 24184edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct check_main_thermal_prot_work; 24284edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct check_usb_thermal_prot_work; 243efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov struct usb_phy *usb_phy; 24484edbeeab67c1575067335179513150115da367bArun Murthy struct notifier_block nb; 24584edbeeab67c1575067335179513150115da367bArun Murthy}; 24684edbeeab67c1575067335179513150115da367bArun Murthy 24784edbeeab67c1575067335179513150115da367bArun Murthy/* AC properties */ 24884edbeeab67c1575067335179513150115da367bArun Murthystatic enum power_supply_property ab8500_charger_ac_props[] = { 24984edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_HEALTH, 25084edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_PRESENT, 25184edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_ONLINE, 25284edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_NOW, 25384edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_AVG, 25484edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_CURRENT_NOW, 25584edbeeab67c1575067335179513150115da367bArun Murthy}; 25684edbeeab67c1575067335179513150115da367bArun Murthy 25784edbeeab67c1575067335179513150115da367bArun Murthy/* USB properties */ 25884edbeeab67c1575067335179513150115da367bArun Murthystatic enum power_supply_property ab8500_charger_usb_props[] = { 25984edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_HEALTH, 26084edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_CURRENT_AVG, 26184edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_PRESENT, 26284edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_ONLINE, 26384edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_NOW, 26484edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_VOLTAGE_AVG, 26584edbeeab67c1575067335179513150115da367bArun Murthy POWER_SUPPLY_PROP_CURRENT_NOW, 26684edbeeab67c1575067335179513150115da367bArun Murthy}; 26784edbeeab67c1575067335179513150115da367bArun Murthy 26884edbeeab67c1575067335179513150115da367bArun Murthy/** 26984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_power_loss_handling - set how we handle powerloss. 27084edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 27184edbeeab67c1575067335179513150115da367bArun Murthy * 27284edbeeab67c1575067335179513150115da367bArun Murthy * Magic nummbers are from STE HW department. 27384edbeeab67c1575067335179513150115da367bArun Murthy */ 27484edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_power_loss_handling(struct ab8500_charger *di) 27584edbeeab67c1575067335179513150115da367bArun Murthy{ 27684edbeeab67c1575067335179513150115da367bArun Murthy u8 reg; 27784edbeeab67c1575067335179513150115da367bArun Murthy int ret; 27884edbeeab67c1575067335179513150115da367bArun Murthy 27984edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Autopower : %d\n", di->autopower); 28084edbeeab67c1575067335179513150115da367bArun Murthy 28184edbeeab67c1575067335179513150115da367bArun Murthy /* read the autopower register */ 28284edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 0x15, 0x00, ®); 28384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 28484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%d write failed\n", __LINE__); 28584edbeeab67c1575067335179513150115da367bArun Murthy return; 28684edbeeab67c1575067335179513150115da367bArun Murthy } 28784edbeeab67c1575067335179513150115da367bArun Murthy 28884edbeeab67c1575067335179513150115da367bArun Murthy /* enable the OPT emulation registers */ 28984edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2); 29084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 29184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%d write failed\n", __LINE__); 29284edbeeab67c1575067335179513150115da367bArun Murthy return; 29384edbeeab67c1575067335179513150115da367bArun Murthy } 29484edbeeab67c1575067335179513150115da367bArun Murthy 29584edbeeab67c1575067335179513150115da367bArun Murthy if (di->autopower) 29684edbeeab67c1575067335179513150115da367bArun Murthy reg |= 0x8; 29784edbeeab67c1575067335179513150115da367bArun Murthy else 29884edbeeab67c1575067335179513150115da367bArun Murthy reg &= ~0x8; 29984edbeeab67c1575067335179513150115da367bArun Murthy 30084edbeeab67c1575067335179513150115da367bArun Murthy /* write back the changed value to autopower reg */ 30184edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 0x15, 0x00, reg); 30284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 30384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%d write failed\n", __LINE__); 30484edbeeab67c1575067335179513150115da367bArun Murthy return; 30584edbeeab67c1575067335179513150115da367bArun Murthy } 30684edbeeab67c1575067335179513150115da367bArun Murthy 30784edbeeab67c1575067335179513150115da367bArun Murthy /* disable the set OTP registers again */ 30884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0); 30984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 31084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%d write failed\n", __LINE__); 31184edbeeab67c1575067335179513150115da367bArun Murthy return; 31284edbeeab67c1575067335179513150115da367bArun Murthy } 31384edbeeab67c1575067335179513150115da367bArun Murthy} 31484edbeeab67c1575067335179513150115da367bArun Murthy 31584edbeeab67c1575067335179513150115da367bArun Murthy/** 31684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_power_supply_changed - a wrapper with local extentions for 31784edbeeab67c1575067335179513150115da367bArun Murthy * power_supply_changed 31884edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 31984edbeeab67c1575067335179513150115da367bArun Murthy * @psy: pointer to power_supply_that have changed. 32084edbeeab67c1575067335179513150115da367bArun Murthy * 32184edbeeab67c1575067335179513150115da367bArun Murthy */ 32284edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_power_supply_changed(struct ab8500_charger *di, 32384edbeeab67c1575067335179513150115da367bArun Murthy struct power_supply *psy) 32484edbeeab67c1575067335179513150115da367bArun Murthy{ 32584edbeeab67c1575067335179513150115da367bArun Murthy if (di->pdata->autopower_cfg) { 32684edbeeab67c1575067335179513150115da367bArun Murthy if (!di->usb.charger_connected && 32784edbeeab67c1575067335179513150115da367bArun Murthy !di->ac.charger_connected && 32884edbeeab67c1575067335179513150115da367bArun Murthy di->autopower) { 32984edbeeab67c1575067335179513150115da367bArun Murthy di->autopower = false; 33084edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_loss_handling(di); 33184edbeeab67c1575067335179513150115da367bArun Murthy } else if (!di->autopower && 33284edbeeab67c1575067335179513150115da367bArun Murthy (di->ac.charger_connected || 33384edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_connected)) { 33484edbeeab67c1575067335179513150115da367bArun Murthy di->autopower = true; 33584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_loss_handling(di); 33684edbeeab67c1575067335179513150115da367bArun Murthy } 33784edbeeab67c1575067335179513150115da367bArun Murthy } 33884edbeeab67c1575067335179513150115da367bArun Murthy power_supply_changed(psy); 33984edbeeab67c1575067335179513150115da367bArun Murthy} 34084edbeeab67c1575067335179513150115da367bArun Murthy 34184edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_set_usb_connected(struct ab8500_charger *di, 34284edbeeab67c1575067335179513150115da367bArun Murthy bool connected) 34384edbeeab67c1575067335179513150115da367bArun Murthy{ 34484edbeeab67c1575067335179513150115da367bArun Murthy if (connected != di->usb.charger_connected) { 34584edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB connected:%i\n", connected); 34684edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_connected = connected; 34784edbeeab67c1575067335179513150115da367bArun Murthy sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); 34884edbeeab67c1575067335179513150115da367bArun Murthy } 34984edbeeab67c1575067335179513150115da367bArun Murthy} 35084edbeeab67c1575067335179513150115da367bArun Murthy 35184edbeeab67c1575067335179513150115da367bArun Murthy/** 35284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_ac_voltage() - get ac charger voltage 35384edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 35484edbeeab67c1575067335179513150115da367bArun Murthy * 35584edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger voltage (on success) 35684edbeeab67c1575067335179513150115da367bArun Murthy */ 35784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ac_voltage(struct ab8500_charger *di) 35884edbeeab67c1575067335179513150115da367bArun Murthy{ 35984edbeeab67c1575067335179513150115da367bArun Murthy int vch; 36084edbeeab67c1575067335179513150115da367bArun Murthy 36184edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure voltage if the charger is connected */ 36284edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_connected) { 36384edbeeab67c1575067335179513150115da367bArun Murthy vch = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_V); 36484edbeeab67c1575067335179513150115da367bArun Murthy if (vch < 0) 36584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed,\n", __func__); 36684edbeeab67c1575067335179513150115da367bArun Murthy } else { 36784edbeeab67c1575067335179513150115da367bArun Murthy vch = 0; 36884edbeeab67c1575067335179513150115da367bArun Murthy } 36984edbeeab67c1575067335179513150115da367bArun Murthy return vch; 37084edbeeab67c1575067335179513150115da367bArun Murthy} 37184edbeeab67c1575067335179513150115da367bArun Murthy 37284edbeeab67c1575067335179513150115da367bArun Murthy/** 37384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_cv() - check if the main charger is in CV mode 37484edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 37584edbeeab67c1575067335179513150115da367bArun Murthy * 37684edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger CV mode (on success) else error code 37784edbeeab67c1575067335179513150115da367bArun Murthy */ 37884edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_cv(struct ab8500_charger *di) 37984edbeeab67c1575067335179513150115da367bArun Murthy{ 38084edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 38184edbeeab67c1575067335179513150115da367bArun Murthy int ret = 0; 38284edbeeab67c1575067335179513150115da367bArun Murthy 38384edbeeab67c1575067335179513150115da367bArun Murthy /* Only check CV mode if the charger is online */ 38484edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_online) { 38584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 38684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_STATUS1_REG, &val); 38784edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 38884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 38984edbeeab67c1575067335179513150115da367bArun Murthy return 0; 39084edbeeab67c1575067335179513150115da367bArun Murthy } 39184edbeeab67c1575067335179513150115da367bArun Murthy 39284edbeeab67c1575067335179513150115da367bArun Murthy if (val & MAIN_CH_CV_ON) 39384edbeeab67c1575067335179513150115da367bArun Murthy ret = 1; 39484edbeeab67c1575067335179513150115da367bArun Murthy else 39584edbeeab67c1575067335179513150115da367bArun Murthy ret = 0; 39684edbeeab67c1575067335179513150115da367bArun Murthy } 39784edbeeab67c1575067335179513150115da367bArun Murthy 39884edbeeab67c1575067335179513150115da367bArun Murthy return ret; 39984edbeeab67c1575067335179513150115da367bArun Murthy} 40084edbeeab67c1575067335179513150115da367bArun Murthy 40184edbeeab67c1575067335179513150115da367bArun Murthy/** 40284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_vbus_voltage() - get vbus voltage 40384edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 40484edbeeab67c1575067335179513150115da367bArun Murthy * 40584edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the vbus voltage. 40684edbeeab67c1575067335179513150115da367bArun Murthy * Returns vbus voltage (on success) 40784edbeeab67c1575067335179513150115da367bArun Murthy */ 40884edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di) 40984edbeeab67c1575067335179513150115da367bArun Murthy{ 41084edbeeab67c1575067335179513150115da367bArun Murthy int vch; 41184edbeeab67c1575067335179513150115da367bArun Murthy 41284edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure voltage if the charger is connected */ 41384edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_connected) { 41484edbeeab67c1575067335179513150115da367bArun Murthy vch = ab8500_gpadc_convert(di->gpadc, VBUS_V); 41584edbeeab67c1575067335179513150115da367bArun Murthy if (vch < 0) 41684edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed\n", __func__); 41784edbeeab67c1575067335179513150115da367bArun Murthy } else { 41884edbeeab67c1575067335179513150115da367bArun Murthy vch = 0; 41984edbeeab67c1575067335179513150115da367bArun Murthy } 42084edbeeab67c1575067335179513150115da367bArun Murthy return vch; 42184edbeeab67c1575067335179513150115da367bArun Murthy} 42284edbeeab67c1575067335179513150115da367bArun Murthy 42384edbeeab67c1575067335179513150115da367bArun Murthy/** 42484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_usb_current() - get usb charger current 42584edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 42684edbeeab67c1575067335179513150115da367bArun Murthy * 42784edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the usb charger current. 42884edbeeab67c1575067335179513150115da367bArun Murthy * Returns usb current (on success) and error code on failure 42984edbeeab67c1575067335179513150115da367bArun Murthy */ 43084edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_usb_current(struct ab8500_charger *di) 43184edbeeab67c1575067335179513150115da367bArun Murthy{ 43284edbeeab67c1575067335179513150115da367bArun Murthy int ich; 43384edbeeab67c1575067335179513150115da367bArun Murthy 43484edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure current if the charger is online */ 43584edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_online) { 43684edbeeab67c1575067335179513150115da367bArun Murthy ich = ab8500_gpadc_convert(di->gpadc, USB_CHARGER_C); 43784edbeeab67c1575067335179513150115da367bArun Murthy if (ich < 0) 43884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed\n", __func__); 43984edbeeab67c1575067335179513150115da367bArun Murthy } else { 44084edbeeab67c1575067335179513150115da367bArun Murthy ich = 0; 44184edbeeab67c1575067335179513150115da367bArun Murthy } 44284edbeeab67c1575067335179513150115da367bArun Murthy return ich; 44384edbeeab67c1575067335179513150115da367bArun Murthy} 44484edbeeab67c1575067335179513150115da367bArun Murthy 44584edbeeab67c1575067335179513150115da367bArun Murthy/** 44684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_ac_current() - get ac charger current 44784edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 44884edbeeab67c1575067335179513150115da367bArun Murthy * 44984edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the ac charger current. 45084edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac current (on success) and error code on failure. 45184edbeeab67c1575067335179513150115da367bArun Murthy */ 45284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ac_current(struct ab8500_charger *di) 45384edbeeab67c1575067335179513150115da367bArun Murthy{ 45484edbeeab67c1575067335179513150115da367bArun Murthy int ich; 45584edbeeab67c1575067335179513150115da367bArun Murthy 45684edbeeab67c1575067335179513150115da367bArun Murthy /* Only measure current if the charger is online */ 45784edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_online) { 45884edbeeab67c1575067335179513150115da367bArun Murthy ich = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_C); 45984edbeeab67c1575067335179513150115da367bArun Murthy if (ich < 0) 46084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s gpadc conv failed\n", __func__); 46184edbeeab67c1575067335179513150115da367bArun Murthy } else { 46284edbeeab67c1575067335179513150115da367bArun Murthy ich = 0; 46384edbeeab67c1575067335179513150115da367bArun Murthy } 46484edbeeab67c1575067335179513150115da367bArun Murthy return ich; 46584edbeeab67c1575067335179513150115da367bArun Murthy} 46684edbeeab67c1575067335179513150115da367bArun Murthy 46784edbeeab67c1575067335179513150115da367bArun Murthy/** 46884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_cv() - check if the usb charger is in CV mode 46984edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 47084edbeeab67c1575067335179513150115da367bArun Murthy * 47184edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger CV mode (on success) else error code 47284edbeeab67c1575067335179513150115da367bArun Murthy */ 47384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_cv(struct ab8500_charger *di) 47484edbeeab67c1575067335179513150115da367bArun Murthy{ 47584edbeeab67c1575067335179513150115da367bArun Murthy int ret; 47684edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 47784edbeeab67c1575067335179513150115da367bArun Murthy 47884edbeeab67c1575067335179513150115da367bArun Murthy /* Only check CV mode if the charger is online */ 47984edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_online) { 48084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 48184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_USBCH_STAT1_REG, &val); 48284edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 48384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 48484edbeeab67c1575067335179513150115da367bArun Murthy return 0; 48584edbeeab67c1575067335179513150115da367bArun Murthy } 48684edbeeab67c1575067335179513150115da367bArun Murthy 48784edbeeab67c1575067335179513150115da367bArun Murthy if (val & USB_CH_CV_ON) 48884edbeeab67c1575067335179513150115da367bArun Murthy ret = 1; 48984edbeeab67c1575067335179513150115da367bArun Murthy else 49084edbeeab67c1575067335179513150115da367bArun Murthy ret = 0; 49184edbeeab67c1575067335179513150115da367bArun Murthy } else { 49284edbeeab67c1575067335179513150115da367bArun Murthy ret = 0; 49384edbeeab67c1575067335179513150115da367bArun Murthy } 49484edbeeab67c1575067335179513150115da367bArun Murthy 49584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 49684edbeeab67c1575067335179513150115da367bArun Murthy} 49784edbeeab67c1575067335179513150115da367bArun Murthy 49884edbeeab67c1575067335179513150115da367bArun Murthy/** 49984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_chargers() - Detect the connected chargers 50084edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 50184edbeeab67c1575067335179513150115da367bArun Murthy * 50284edbeeab67c1575067335179513150115da367bArun Murthy * Returns the type of charger connected. 50384edbeeab67c1575067335179513150115da367bArun Murthy * For USB it will not mean we can actually charge from it 50484edbeeab67c1575067335179513150115da367bArun Murthy * but that there is a USB cable connected that we have to 50584edbeeab67c1575067335179513150115da367bArun Murthy * identify. This is used during startup when we don't get 50684edbeeab67c1575067335179513150115da367bArun Murthy * interrupts of the charger detection 50784edbeeab67c1575067335179513150115da367bArun Murthy * 50884edbeeab67c1575067335179513150115da367bArun Murthy * Returns an integer value, that means, 50984edbeeab67c1575067335179513150115da367bArun Murthy * NO_PW_CONN no power supply is connected 51084edbeeab67c1575067335179513150115da367bArun Murthy * AC_PW_CONN if the AC power supply is connected 51184edbeeab67c1575067335179513150115da367bArun Murthy * USB_PW_CONN if the USB power supply is connected 51284edbeeab67c1575067335179513150115da367bArun Murthy * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected 51384edbeeab67c1575067335179513150115da367bArun Murthy */ 51484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_detect_chargers(struct ab8500_charger *di) 51584edbeeab67c1575067335179513150115da367bArun Murthy{ 51684edbeeab67c1575067335179513150115da367bArun Murthy int result = NO_PW_CONN; 51784edbeeab67c1575067335179513150115da367bArun Murthy int ret; 51884edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 51984edbeeab67c1575067335179513150115da367bArun Murthy 52084edbeeab67c1575067335179513150115da367bArun Murthy /* Check for AC charger */ 52184edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 52284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_STATUS1_REG, &val); 52384edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 52484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 52584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 52684edbeeab67c1575067335179513150115da367bArun Murthy } 52784edbeeab67c1575067335179513150115da367bArun Murthy 52884edbeeab67c1575067335179513150115da367bArun Murthy if (val & MAIN_CH_DET) 52984edbeeab67c1575067335179513150115da367bArun Murthy result = AC_PW_CONN; 53084edbeeab67c1575067335179513150115da367bArun Murthy 53184edbeeab67c1575067335179513150115da367bArun Murthy /* Check for USB charger */ 53284edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, 53384edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_USBCH_STAT1_REG, &val); 53484edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 53584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 53684edbeeab67c1575067335179513150115da367bArun Murthy return ret; 53784edbeeab67c1575067335179513150115da367bArun Murthy } 53884edbeeab67c1575067335179513150115da367bArun Murthy 53984edbeeab67c1575067335179513150115da367bArun Murthy if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100)) 54084edbeeab67c1575067335179513150115da367bArun Murthy result |= USB_PW_CONN; 54184edbeeab67c1575067335179513150115da367bArun Murthy 54284edbeeab67c1575067335179513150115da367bArun Murthy return result; 54384edbeeab67c1575067335179513150115da367bArun Murthy} 54484edbeeab67c1575067335179513150115da367bArun Murthy 54584edbeeab67c1575067335179513150115da367bArun Murthy/** 54684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_max_usb_curr() - get the max curr for the USB type 54784edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 54884edbeeab67c1575067335179513150115da367bArun Murthy * @link_status: the identified USB type 54984edbeeab67c1575067335179513150115da367bArun Murthy * 55084edbeeab67c1575067335179513150115da367bArun Murthy * Get the maximum current that is allowed to be drawn from the host 55184edbeeab67c1575067335179513150115da367bArun Murthy * based on the USB type. 55284edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success 55384edbeeab67c1575067335179513150115da367bArun Murthy */ 55484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_max_usb_curr(struct ab8500_charger *di, 55584edbeeab67c1575067335179513150115da367bArun Murthy enum ab8500_charger_link_status link_status) 55684edbeeab67c1575067335179513150115da367bArun Murthy{ 55784edbeeab67c1575067335179513150115da367bArun Murthy int ret = 0; 55884edbeeab67c1575067335179513150115da367bArun Murthy 55984edbeeab67c1575067335179513150115da367bArun Murthy switch (link_status) { 56084edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_STD_HOST_NC: 56184edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_STD_HOST_C_NS: 56284edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_STD_HOST_C_S: 56384edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB Type - Standard host is " 56484edbeeab67c1575067335179513150115da367bArun Murthy "detected through USB driver\n"); 56584edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; 56684edbeeab67c1575067335179513150115da367bArun Murthy break; 56784edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HOST_CHG_HS_CHIRP: 56884edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; 56984edbeeab67c1575067335179513150115da367bArun Murthy break; 57084edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HOST_CHG_HS: 57184edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_C_HS: 57284edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; 57384edbeeab67c1575067335179513150115da367bArun Murthy break; 57484edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_A: 57584edbeeab67c1575067335179513150115da367bArun Murthy /* 57684edbeeab67c1575067335179513150115da367bArun Murthy * Dedicated charger level minus maximum current accessory 57784edbeeab67c1575067335179513150115da367bArun Murthy * can consume (300mA). Closest level is 1100mA 57884edbeeab67c1575067335179513150115da367bArun Murthy */ 57984edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P1; 58084edbeeab67c1575067335179513150115da367bArun Murthy break; 58184edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_B: 58284edbeeab67c1575067335179513150115da367bArun Murthy /* 58384edbeeab67c1575067335179513150115da367bArun Murthy * Dedicated charger level minus 120mA (20mA for ACA and 58484edbeeab67c1575067335179513150115da367bArun Murthy * 100mA for potential accessory). Closest level is 1300mA 58584edbeeab67c1575067335179513150115da367bArun Murthy */ 58684edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; 58784edbeeab67c1575067335179513150115da367bArun Murthy break; 58884edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_DEDICATED_CHG: 58984edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HOST_CHG_NM: 59084edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_C_HS_CHIRP: 59184edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_ACA_RID_C_NM: 59284edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; 59384edbeeab67c1575067335179513150115da367bArun Murthy break; 59484edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_RESERVED: 59584edbeeab67c1575067335179513150115da367bArun Murthy /* 59684edbeeab67c1575067335179513150115da367bArun Murthy * This state is used to indicate that VBUS has dropped below 59784edbeeab67c1575067335179513150115da367bArun Murthy * the detection level 4 times in a row. This is due to the 59884edbeeab67c1575067335179513150115da367bArun Murthy * charger output current is set to high making the charger 59984edbeeab67c1575067335179513150115da367bArun Murthy * voltage collapse. This have to be propagated through to 60084edbeeab67c1575067335179513150115da367bArun Murthy * chargalg. This is done using the property 60184edbeeab67c1575067335179513150115da367bArun Murthy * POWER_SUPPLY_PROP_CURRENT_AVG = 1 60284edbeeab67c1575067335179513150115da367bArun Murthy */ 60384edbeeab67c1575067335179513150115da367bArun Murthy di->flags.vbus_collapse = true; 60484edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB Type - USB_STAT_RESERVED " 60584edbeeab67c1575067335179513150115da367bArun Murthy "VBUS has collapsed\n"); 60684edbeeab67c1575067335179513150115da367bArun Murthy ret = -1; 60784edbeeab67c1575067335179513150115da367bArun Murthy break; 60884edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_HM_IDGND: 60984edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_NOT_CONFIGURED: 61084edbeeab67c1575067335179513150115da367bArun Murthy case USB_STAT_NOT_VALID_LINK: 61184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "USB Type - Charging not allowed\n"); 61284edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; 61384edbeeab67c1575067335179513150115da367bArun Murthy ret = -ENXIO; 61484edbeeab67c1575067335179513150115da367bArun Murthy break; 61584edbeeab67c1575067335179513150115da367bArun Murthy default: 61684edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "USB Type - Unknown\n"); 61784edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; 61884edbeeab67c1575067335179513150115da367bArun Murthy ret = -ENXIO; 61984edbeeab67c1575067335179513150115da367bArun Murthy break; 62084edbeeab67c1575067335179513150115da367bArun Murthy }; 62184edbeeab67c1575067335179513150115da367bArun Murthy 62284edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", 62384edbeeab67c1575067335179513150115da367bArun Murthy link_status, di->max_usb_in_curr); 62484edbeeab67c1575067335179513150115da367bArun Murthy 62584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 62684edbeeab67c1575067335179513150115da367bArun Murthy} 62784edbeeab67c1575067335179513150115da367bArun Murthy 62884edbeeab67c1575067335179513150115da367bArun Murthy/** 62984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_read_usb_type() - read the type of usb connected 63084edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 63184edbeeab67c1575067335179513150115da367bArun Murthy * 63284edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of the plugged USB 63384edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success 63484edbeeab67c1575067335179513150115da367bArun Murthy */ 63584edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_read_usb_type(struct ab8500_charger *di) 63684edbeeab67c1575067335179513150115da367bArun Murthy{ 63784edbeeab67c1575067335179513150115da367bArun Murthy int ret; 63884edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 63984edbeeab67c1575067335179513150115da367bArun Murthy 64084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 64184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val); 64284edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 64384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 64484edbeeab67c1575067335179513150115da367bArun Murthy return ret; 64584edbeeab67c1575067335179513150115da367bArun Murthy } 64684edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 64784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USB_LINE_STAT_REG, &val); 64884edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 64984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 65084edbeeab67c1575067335179513150115da367bArun Murthy return ret; 65184edbeeab67c1575067335179513150115da367bArun Murthy } 65284edbeeab67c1575067335179513150115da367bArun Murthy 65384edbeeab67c1575067335179513150115da367bArun Murthy /* get the USB type */ 65484edbeeab67c1575067335179513150115da367bArun Murthy val = (val & AB8500_USB_LINK_STATUS) >> 3; 65584edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_max_usb_curr(di, 65684edbeeab67c1575067335179513150115da367bArun Murthy (enum ab8500_charger_link_status) val); 65784edbeeab67c1575067335179513150115da367bArun Murthy 65884edbeeab67c1575067335179513150115da367bArun Murthy return ret; 65984edbeeab67c1575067335179513150115da367bArun Murthy} 66084edbeeab67c1575067335179513150115da367bArun Murthy 66184edbeeab67c1575067335179513150115da367bArun Murthy/** 66284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_usb_type() - get the type of usb connected 66384edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 66484edbeeab67c1575067335179513150115da367bArun Murthy * 66584edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of the plugged USB 66684edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success 66784edbeeab67c1575067335179513150115da367bArun Murthy */ 66884edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_detect_usb_type(struct ab8500_charger *di) 66984edbeeab67c1575067335179513150115da367bArun Murthy{ 67084edbeeab67c1575067335179513150115da367bArun Murthy int i, ret; 67184edbeeab67c1575067335179513150115da367bArun Murthy u8 val; 67284edbeeab67c1575067335179513150115da367bArun Murthy 67384edbeeab67c1575067335179513150115da367bArun Murthy /* 67484edbeeab67c1575067335179513150115da367bArun Murthy * On getting the VBUS rising edge detect interrupt there 67584edbeeab67c1575067335179513150115da367bArun Murthy * is a 250ms delay after which the register UsbLineStatus 67684edbeeab67c1575067335179513150115da367bArun Murthy * is filled with valid data. 67784edbeeab67c1575067335179513150115da367bArun Murthy */ 67884edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < 10; i++) { 67984edbeeab67c1575067335179513150115da367bArun Murthy msleep(250); 68084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 68184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, 68284edbeeab67c1575067335179513150115da367bArun Murthy &val); 68384edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 68484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 68584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 68684edbeeab67c1575067335179513150115da367bArun Murthy } 68784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, AB8500_USB, 68884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USB_LINE_STAT_REG, &val); 68984edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 69084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 69184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 69284edbeeab67c1575067335179513150115da367bArun Murthy } 69384edbeeab67c1575067335179513150115da367bArun Murthy /* 69484edbeeab67c1575067335179513150115da367bArun Murthy * Until the IT source register is read the UsbLineStatus 69584edbeeab67c1575067335179513150115da367bArun Murthy * register is not updated, hence doing the same 69684edbeeab67c1575067335179513150115da367bArun Murthy * Revisit this: 69784edbeeab67c1575067335179513150115da367bArun Murthy */ 69884edbeeab67c1575067335179513150115da367bArun Murthy 69984edbeeab67c1575067335179513150115da367bArun Murthy /* get the USB type */ 70084edbeeab67c1575067335179513150115da367bArun Murthy val = (val & AB8500_USB_LINK_STATUS) >> 3; 70184edbeeab67c1575067335179513150115da367bArun Murthy if (val) 70284edbeeab67c1575067335179513150115da367bArun Murthy break; 70384edbeeab67c1575067335179513150115da367bArun Murthy } 70484edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_max_usb_curr(di, 70584edbeeab67c1575067335179513150115da367bArun Murthy (enum ab8500_charger_link_status) val); 70684edbeeab67c1575067335179513150115da367bArun Murthy 70784edbeeab67c1575067335179513150115da367bArun Murthy return ret; 70884edbeeab67c1575067335179513150115da367bArun Murthy} 70984edbeeab67c1575067335179513150115da367bArun Murthy 71084edbeeab67c1575067335179513150115da367bArun Murthy/* 71184edbeeab67c1575067335179513150115da367bArun Murthy * This array maps the raw hex value to charger voltage used by the AB8500 71284edbeeab67c1575067335179513150115da367bArun Murthy * Values taken from the UM0836 71384edbeeab67c1575067335179513150115da367bArun Murthy */ 71484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_voltage_map[] = { 71584edbeeab67c1575067335179513150115da367bArun Murthy 3500 , 71684edbeeab67c1575067335179513150115da367bArun Murthy 3525 , 71784edbeeab67c1575067335179513150115da367bArun Murthy 3550 , 71884edbeeab67c1575067335179513150115da367bArun Murthy 3575 , 71984edbeeab67c1575067335179513150115da367bArun Murthy 3600 , 72084edbeeab67c1575067335179513150115da367bArun Murthy 3625 , 72184edbeeab67c1575067335179513150115da367bArun Murthy 3650 , 72284edbeeab67c1575067335179513150115da367bArun Murthy 3675 , 72384edbeeab67c1575067335179513150115da367bArun Murthy 3700 , 72484edbeeab67c1575067335179513150115da367bArun Murthy 3725 , 72584edbeeab67c1575067335179513150115da367bArun Murthy 3750 , 72684edbeeab67c1575067335179513150115da367bArun Murthy 3775 , 72784edbeeab67c1575067335179513150115da367bArun Murthy 3800 , 72884edbeeab67c1575067335179513150115da367bArun Murthy 3825 , 72984edbeeab67c1575067335179513150115da367bArun Murthy 3850 , 73084edbeeab67c1575067335179513150115da367bArun Murthy 3875 , 73184edbeeab67c1575067335179513150115da367bArun Murthy 3900 , 73284edbeeab67c1575067335179513150115da367bArun Murthy 3925 , 73384edbeeab67c1575067335179513150115da367bArun Murthy 3950 , 73484edbeeab67c1575067335179513150115da367bArun Murthy 3975 , 73584edbeeab67c1575067335179513150115da367bArun Murthy 4000 , 73684edbeeab67c1575067335179513150115da367bArun Murthy 4025 , 73784edbeeab67c1575067335179513150115da367bArun Murthy 4050 , 73884edbeeab67c1575067335179513150115da367bArun Murthy 4060 , 73984edbeeab67c1575067335179513150115da367bArun Murthy 4070 , 74084edbeeab67c1575067335179513150115da367bArun Murthy 4080 , 74184edbeeab67c1575067335179513150115da367bArun Murthy 4090 , 74284edbeeab67c1575067335179513150115da367bArun Murthy 4100 , 74384edbeeab67c1575067335179513150115da367bArun Murthy 4110 , 74484edbeeab67c1575067335179513150115da367bArun Murthy 4120 , 74584edbeeab67c1575067335179513150115da367bArun Murthy 4130 , 74684edbeeab67c1575067335179513150115da367bArun Murthy 4140 , 74784edbeeab67c1575067335179513150115da367bArun Murthy 4150 , 74884edbeeab67c1575067335179513150115da367bArun Murthy 4160 , 74984edbeeab67c1575067335179513150115da367bArun Murthy 4170 , 75084edbeeab67c1575067335179513150115da367bArun Murthy 4180 , 75184edbeeab67c1575067335179513150115da367bArun Murthy 4190 , 75284edbeeab67c1575067335179513150115da367bArun Murthy 4200 , 75384edbeeab67c1575067335179513150115da367bArun Murthy 4210 , 75484edbeeab67c1575067335179513150115da367bArun Murthy 4220 , 75584edbeeab67c1575067335179513150115da367bArun Murthy 4230 , 75684edbeeab67c1575067335179513150115da367bArun Murthy 4240 , 75784edbeeab67c1575067335179513150115da367bArun Murthy 4250 , 75884edbeeab67c1575067335179513150115da367bArun Murthy 4260 , 75984edbeeab67c1575067335179513150115da367bArun Murthy 4270 , 76084edbeeab67c1575067335179513150115da367bArun Murthy 4280 , 76184edbeeab67c1575067335179513150115da367bArun Murthy 4290 , 76284edbeeab67c1575067335179513150115da367bArun Murthy 4300 , 76384edbeeab67c1575067335179513150115da367bArun Murthy 4310 , 76484edbeeab67c1575067335179513150115da367bArun Murthy 4320 , 76584edbeeab67c1575067335179513150115da367bArun Murthy 4330 , 76684edbeeab67c1575067335179513150115da367bArun Murthy 4340 , 76784edbeeab67c1575067335179513150115da367bArun Murthy 4350 , 76884edbeeab67c1575067335179513150115da367bArun Murthy 4360 , 76984edbeeab67c1575067335179513150115da367bArun Murthy 4370 , 77084edbeeab67c1575067335179513150115da367bArun Murthy 4380 , 77184edbeeab67c1575067335179513150115da367bArun Murthy 4390 , 77284edbeeab67c1575067335179513150115da367bArun Murthy 4400 , 77384edbeeab67c1575067335179513150115da367bArun Murthy 4410 , 77484edbeeab67c1575067335179513150115da367bArun Murthy 4420 , 77584edbeeab67c1575067335179513150115da367bArun Murthy 4430 , 77684edbeeab67c1575067335179513150115da367bArun Murthy 4440 , 77784edbeeab67c1575067335179513150115da367bArun Murthy 4450 , 77884edbeeab67c1575067335179513150115da367bArun Murthy 4460 , 77984edbeeab67c1575067335179513150115da367bArun Murthy 4470 , 78084edbeeab67c1575067335179513150115da367bArun Murthy 4480 , 78184edbeeab67c1575067335179513150115da367bArun Murthy 4490 , 78284edbeeab67c1575067335179513150115da367bArun Murthy 4500 , 78384edbeeab67c1575067335179513150115da367bArun Murthy 4510 , 78484edbeeab67c1575067335179513150115da367bArun Murthy 4520 , 78584edbeeab67c1575067335179513150115da367bArun Murthy 4530 , 78684edbeeab67c1575067335179513150115da367bArun Murthy 4540 , 78784edbeeab67c1575067335179513150115da367bArun Murthy 4550 , 78884edbeeab67c1575067335179513150115da367bArun Murthy 4560 , 78984edbeeab67c1575067335179513150115da367bArun Murthy 4570 , 79084edbeeab67c1575067335179513150115da367bArun Murthy 4580 , 79184edbeeab67c1575067335179513150115da367bArun Murthy 4590 , 79284edbeeab67c1575067335179513150115da367bArun Murthy 4600 , 79384edbeeab67c1575067335179513150115da367bArun Murthy}; 79484edbeeab67c1575067335179513150115da367bArun Murthy 79584edbeeab67c1575067335179513150115da367bArun Murthy/* 79684edbeeab67c1575067335179513150115da367bArun Murthy * This array maps the raw hex value to charger current used by the AB8500 79784edbeeab67c1575067335179513150115da367bArun Murthy * Values taken from the UM0836 79884edbeeab67c1575067335179513150115da367bArun Murthy */ 79984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_current_map[] = { 80084edbeeab67c1575067335179513150115da367bArun Murthy 100 , 80184edbeeab67c1575067335179513150115da367bArun Murthy 200 , 80284edbeeab67c1575067335179513150115da367bArun Murthy 300 , 80384edbeeab67c1575067335179513150115da367bArun Murthy 400 , 80484edbeeab67c1575067335179513150115da367bArun Murthy 500 , 80584edbeeab67c1575067335179513150115da367bArun Murthy 600 , 80684edbeeab67c1575067335179513150115da367bArun Murthy 700 , 80784edbeeab67c1575067335179513150115da367bArun Murthy 800 , 80884edbeeab67c1575067335179513150115da367bArun Murthy 900 , 80984edbeeab67c1575067335179513150115da367bArun Murthy 1000 , 81084edbeeab67c1575067335179513150115da367bArun Murthy 1100 , 81184edbeeab67c1575067335179513150115da367bArun Murthy 1200 , 81284edbeeab67c1575067335179513150115da367bArun Murthy 1300 , 81384edbeeab67c1575067335179513150115da367bArun Murthy 1400 , 81484edbeeab67c1575067335179513150115da367bArun Murthy 1500 , 81584edbeeab67c1575067335179513150115da367bArun Murthy}; 81684edbeeab67c1575067335179513150115da367bArun Murthy 81784edbeeab67c1575067335179513150115da367bArun Murthy/* 81884edbeeab67c1575067335179513150115da367bArun Murthy * This array maps the raw hex value to VBUS input current used by the AB8500 81984edbeeab67c1575067335179513150115da367bArun Murthy * Values taken from the UM0836 82084edbeeab67c1575067335179513150115da367bArun Murthy */ 82184edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_vbus_in_curr_map[] = { 82284edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P05, 82384edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P09, 82484edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P19, 82584edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P29, 82684edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P38, 82784edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P45, 82884edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P5, 82984edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P6, 83084edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P7, 83184edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P8, 83284edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_0P9, 83384edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_1P0, 83484edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_1P1, 83584edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_1P3, 83684edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_1P4, 83784edbeeab67c1575067335179513150115da367bArun Murthy USB_CH_IP_CUR_LVL_1P5, 83884edbeeab67c1575067335179513150115da367bArun Murthy}; 83984edbeeab67c1575067335179513150115da367bArun Murthy 84084edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_voltage_to_regval(int voltage) 84184edbeeab67c1575067335179513150115da367bArun Murthy{ 84284edbeeab67c1575067335179513150115da367bArun Murthy int i; 84384edbeeab67c1575067335179513150115da367bArun Murthy 84484edbeeab67c1575067335179513150115da367bArun Murthy /* Special case for voltage below 3.5V */ 84584edbeeab67c1575067335179513150115da367bArun Murthy if (voltage < ab8500_charger_voltage_map[0]) 84684edbeeab67c1575067335179513150115da367bArun Murthy return LOW_VOLT_REG; 84784edbeeab67c1575067335179513150115da367bArun Murthy 84884edbeeab67c1575067335179513150115da367bArun Murthy for (i = 1; i < ARRAY_SIZE(ab8500_charger_voltage_map); i++) { 84984edbeeab67c1575067335179513150115da367bArun Murthy if (voltage < ab8500_charger_voltage_map[i]) 85084edbeeab67c1575067335179513150115da367bArun Murthy return i - 1; 85184edbeeab67c1575067335179513150115da367bArun Murthy } 85284edbeeab67c1575067335179513150115da367bArun Murthy 85384edbeeab67c1575067335179513150115da367bArun Murthy /* If not last element, return error */ 85484edbeeab67c1575067335179513150115da367bArun Murthy i = ARRAY_SIZE(ab8500_charger_voltage_map) - 1; 85584edbeeab67c1575067335179513150115da367bArun Murthy if (voltage == ab8500_charger_voltage_map[i]) 85684edbeeab67c1575067335179513150115da367bArun Murthy return i; 85784edbeeab67c1575067335179513150115da367bArun Murthy else 85884edbeeab67c1575067335179513150115da367bArun Murthy return -1; 85984edbeeab67c1575067335179513150115da367bArun Murthy} 86084edbeeab67c1575067335179513150115da367bArun Murthy 86184edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_current_to_regval(int curr) 86284edbeeab67c1575067335179513150115da367bArun Murthy{ 86384edbeeab67c1575067335179513150115da367bArun Murthy int i; 86484edbeeab67c1575067335179513150115da367bArun Murthy 86584edbeeab67c1575067335179513150115da367bArun Murthy if (curr < ab8500_charger_current_map[0]) 86684edbeeab67c1575067335179513150115da367bArun Murthy return 0; 86784edbeeab67c1575067335179513150115da367bArun Murthy 86884edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ARRAY_SIZE(ab8500_charger_current_map); i++) { 86984edbeeab67c1575067335179513150115da367bArun Murthy if (curr < ab8500_charger_current_map[i]) 87084edbeeab67c1575067335179513150115da367bArun Murthy return i - 1; 87184edbeeab67c1575067335179513150115da367bArun Murthy } 87284edbeeab67c1575067335179513150115da367bArun Murthy 87384edbeeab67c1575067335179513150115da367bArun Murthy /* If not last element, return error */ 87484edbeeab67c1575067335179513150115da367bArun Murthy i = ARRAY_SIZE(ab8500_charger_current_map) - 1; 87584edbeeab67c1575067335179513150115da367bArun Murthy if (curr == ab8500_charger_current_map[i]) 87684edbeeab67c1575067335179513150115da367bArun Murthy return i; 87784edbeeab67c1575067335179513150115da367bArun Murthy else 87884edbeeab67c1575067335179513150115da367bArun Murthy return -1; 87984edbeeab67c1575067335179513150115da367bArun Murthy} 88084edbeeab67c1575067335179513150115da367bArun Murthy 88184edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_vbus_in_curr_to_regval(int curr) 88284edbeeab67c1575067335179513150115da367bArun Murthy{ 88384edbeeab67c1575067335179513150115da367bArun Murthy int i; 88484edbeeab67c1575067335179513150115da367bArun Murthy 88584edbeeab67c1575067335179513150115da367bArun Murthy if (curr < ab8500_charger_vbus_in_curr_map[0]) 88684edbeeab67c1575067335179513150115da367bArun Murthy return 0; 88784edbeeab67c1575067335179513150115da367bArun Murthy 88884edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ARRAY_SIZE(ab8500_charger_vbus_in_curr_map); i++) { 88984edbeeab67c1575067335179513150115da367bArun Murthy if (curr < ab8500_charger_vbus_in_curr_map[i]) 89084edbeeab67c1575067335179513150115da367bArun Murthy return i - 1; 89184edbeeab67c1575067335179513150115da367bArun Murthy } 89284edbeeab67c1575067335179513150115da367bArun Murthy 89384edbeeab67c1575067335179513150115da367bArun Murthy /* If not last element, return error */ 89484edbeeab67c1575067335179513150115da367bArun Murthy i = ARRAY_SIZE(ab8500_charger_vbus_in_curr_map) - 1; 89584edbeeab67c1575067335179513150115da367bArun Murthy if (curr == ab8500_charger_vbus_in_curr_map[i]) 89684edbeeab67c1575067335179513150115da367bArun Murthy return i; 89784edbeeab67c1575067335179513150115da367bArun Murthy else 89884edbeeab67c1575067335179513150115da367bArun Murthy return -1; 89984edbeeab67c1575067335179513150115da367bArun Murthy} 90084edbeeab67c1575067335179513150115da367bArun Murthy 90184edbeeab67c1575067335179513150115da367bArun Murthy/** 90284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_usb_cur() - get usb current 90384edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structre 90484edbeeab67c1575067335179513150115da367bArun Murthy * 90584edbeeab67c1575067335179513150115da367bArun Murthy * The usb stack provides the maximum current that can be drawn from 90684edbeeab67c1575067335179513150115da367bArun Murthy * the standard usb host. This will be in mA. 90784edbeeab67c1575067335179513150115da367bArun Murthy * This function converts current in mA to a value that can be written 90884edbeeab67c1575067335179513150115da367bArun Murthy * to the register. Returns -1 if charging is not allowed 90984edbeeab67c1575067335179513150115da367bArun Murthy */ 91084edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_usb_cur(struct ab8500_charger *di) 91184edbeeab67c1575067335179513150115da367bArun Murthy{ 91284edbeeab67c1575067335179513150115da367bArun Murthy switch (di->usb_state.usb_current) { 91384edbeeab67c1575067335179513150115da367bArun Murthy case 100: 91484edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; 91584edbeeab67c1575067335179513150115da367bArun Murthy break; 91684edbeeab67c1575067335179513150115da367bArun Murthy case 200: 91784edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P19; 91884edbeeab67c1575067335179513150115da367bArun Murthy break; 91984edbeeab67c1575067335179513150115da367bArun Murthy case 300: 92084edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P29; 92184edbeeab67c1575067335179513150115da367bArun Murthy break; 92284edbeeab67c1575067335179513150115da367bArun Murthy case 400: 92384edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P38; 92484edbeeab67c1575067335179513150115da367bArun Murthy break; 92584edbeeab67c1575067335179513150115da367bArun Murthy case 500: 92684edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; 92784edbeeab67c1575067335179513150115da367bArun Murthy break; 92884edbeeab67c1575067335179513150115da367bArun Murthy default: 92984edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; 93084edbeeab67c1575067335179513150115da367bArun Murthy return -1; 93184edbeeab67c1575067335179513150115da367bArun Murthy break; 93284edbeeab67c1575067335179513150115da367bArun Murthy }; 93384edbeeab67c1575067335179513150115da367bArun Murthy return 0; 93484edbeeab67c1575067335179513150115da367bArun Murthy} 93584edbeeab67c1575067335179513150115da367bArun Murthy 93684edbeeab67c1575067335179513150115da367bArun Murthy/** 93784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit 93884edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 93984edbeeab67c1575067335179513150115da367bArun Murthy * @ich_in: charger input current limit 94084edbeeab67c1575067335179513150115da367bArun Murthy * 94184edbeeab67c1575067335179513150115da367bArun Murthy * Sets the current that can be drawn from the USB host 94284edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 94384edbeeab67c1575067335179513150115da367bArun Murthy */ 94484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, 94584edbeeab67c1575067335179513150115da367bArun Murthy int ich_in) 94684edbeeab67c1575067335179513150115da367bArun Murthy{ 94784edbeeab67c1575067335179513150115da367bArun Murthy int ret; 94884edbeeab67c1575067335179513150115da367bArun Murthy int input_curr_index; 94984edbeeab67c1575067335179513150115da367bArun Murthy int min_value; 95084edbeeab67c1575067335179513150115da367bArun Murthy 95184edbeeab67c1575067335179513150115da367bArun Murthy /* We should always use to lowest current limit */ 95284edbeeab67c1575067335179513150115da367bArun Murthy min_value = min(di->bat->chg_params->usb_curr_max, ich_in); 95384edbeeab67c1575067335179513150115da367bArun Murthy 95484edbeeab67c1575067335179513150115da367bArun Murthy switch (min_value) { 95584edbeeab67c1575067335179513150115da367bArun Murthy case 100: 95684edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbat < VBAT_TRESH_IP_CUR_RED) 95784edbeeab67c1575067335179513150115da367bArun Murthy min_value = USB_CH_IP_CUR_LVL_0P05; 95884edbeeab67c1575067335179513150115da367bArun Murthy break; 95984edbeeab67c1575067335179513150115da367bArun Murthy case 500: 96084edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbat < VBAT_TRESH_IP_CUR_RED) 96184edbeeab67c1575067335179513150115da367bArun Murthy min_value = USB_CH_IP_CUR_LVL_0P45; 96284edbeeab67c1575067335179513150115da367bArun Murthy break; 96384edbeeab67c1575067335179513150115da367bArun Murthy default: 96484edbeeab67c1575067335179513150115da367bArun Murthy break; 96584edbeeab67c1575067335179513150115da367bArun Murthy } 96684edbeeab67c1575067335179513150115da367bArun Murthy 96784edbeeab67c1575067335179513150115da367bArun Murthy input_curr_index = ab8500_vbus_in_curr_to_regval(min_value); 96884edbeeab67c1575067335179513150115da367bArun Murthy if (input_curr_index < 0) { 96984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "VBUS input current limit too high\n"); 97084edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 97184edbeeab67c1575067335179513150115da367bArun Murthy } 97284edbeeab67c1575067335179513150115da367bArun Murthy 97384edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 97484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USBCH_IPT_CRNTLVL_REG, 97584edbeeab67c1575067335179513150115da367bArun Murthy input_curr_index << VBUS_IN_CURR_LIM_SHIFT); 97684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 97784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 97884edbeeab67c1575067335179513150115da367bArun Murthy 97984edbeeab67c1575067335179513150115da367bArun Murthy return ret; 98084edbeeab67c1575067335179513150115da367bArun Murthy} 98184edbeeab67c1575067335179513150115da367bArun Murthy 98284edbeeab67c1575067335179513150115da367bArun Murthy/** 98384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_led_en() - turn on/off chargign led 98484edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 98584edbeeab67c1575067335179513150115da367bArun Murthy * @on: flag to turn on/off the chargign led 98684edbeeab67c1575067335179513150115da367bArun Murthy * 98784edbeeab67c1575067335179513150115da367bArun Murthy * Power ON/OFF charging LED indication 98884edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 98984edbeeab67c1575067335179513150115da367bArun Murthy */ 99084edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_led_en(struct ab8500_charger *di, int on) 99184edbeeab67c1575067335179513150115da367bArun Murthy{ 99284edbeeab67c1575067335179513150115da367bArun Murthy int ret; 99384edbeeab67c1575067335179513150115da367bArun Murthy 99484edbeeab67c1575067335179513150115da367bArun Murthy if (on) { 99584edbeeab67c1575067335179513150115da367bArun Murthy /* Power ON charging LED indicator, set LED current to 5mA */ 99684edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 99784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_LED_INDICATOR_PWM_CTRL, 99884edbeeab67c1575067335179513150115da367bArun Murthy (LED_IND_CUR_5MA | LED_INDICATOR_PWM_ENA)); 99984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 100084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Power ON LED failed\n"); 100184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 100284edbeeab67c1575067335179513150115da367bArun Murthy } 100384edbeeab67c1575067335179513150115da367bArun Murthy /* LED indicator PWM duty cycle 252/256 */ 100484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 100584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_LED_INDICATOR_PWM_DUTY, 100684edbeeab67c1575067335179513150115da367bArun Murthy LED_INDICATOR_PWM_DUTY_252_256); 100784edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 100884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Set LED PWM duty cycle failed\n"); 100984edbeeab67c1575067335179513150115da367bArun Murthy return ret; 101084edbeeab67c1575067335179513150115da367bArun Murthy } 101184edbeeab67c1575067335179513150115da367bArun Murthy } else { 101284edbeeab67c1575067335179513150115da367bArun Murthy /* Power off charging LED indicator */ 101384edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 101484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_LED_INDICATOR_PWM_CTRL, 101584edbeeab67c1575067335179513150115da367bArun Murthy LED_INDICATOR_PWM_DIS); 101684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 101784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Power-off LED failed\n"); 101884edbeeab67c1575067335179513150115da367bArun Murthy return ret; 101984edbeeab67c1575067335179513150115da367bArun Murthy } 102084edbeeab67c1575067335179513150115da367bArun Murthy } 102184edbeeab67c1575067335179513150115da367bArun Murthy 102284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 102384edbeeab67c1575067335179513150115da367bArun Murthy} 102484edbeeab67c1575067335179513150115da367bArun Murthy 102584edbeeab67c1575067335179513150115da367bArun Murthy/** 102684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_en() - enable or disable ac charging 102784edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 102884edbeeab67c1575067335179513150115da367bArun Murthy * @enable: enable/disable flag 102984edbeeab67c1575067335179513150115da367bArun Murthy * @vset: charging voltage 103084edbeeab67c1575067335179513150115da367bArun Murthy * @iset: charging current 103184edbeeab67c1575067335179513150115da367bArun Murthy * 103284edbeeab67c1575067335179513150115da367bArun Murthy * Enable/Disable AC/Mains charging and turns on/off the charging led 103384edbeeab67c1575067335179513150115da367bArun Murthy * respectively. 103484edbeeab67c1575067335179513150115da367bArun Murthy **/ 103584edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_en(struct ux500_charger *charger, 103684edbeeab67c1575067335179513150115da367bArun Murthy int enable, int vset, int iset) 103784edbeeab67c1575067335179513150115da367bArun Murthy{ 103884edbeeab67c1575067335179513150115da367bArun Murthy int ret; 103984edbeeab67c1575067335179513150115da367bArun Murthy int volt_index; 104084edbeeab67c1575067335179513150115da367bArun Murthy int curr_index; 104184edbeeab67c1575067335179513150115da367bArun Murthy int input_curr_index; 104284edbeeab67c1575067335179513150115da367bArun Murthy u8 overshoot = 0; 104384edbeeab67c1575067335179513150115da367bArun Murthy 104484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger); 104584edbeeab67c1575067335179513150115da367bArun Murthy 104684edbeeab67c1575067335179513150115da367bArun Murthy if (enable) { 104784edbeeab67c1575067335179513150115da367bArun Murthy /* Check if AC is connected */ 104884edbeeab67c1575067335179513150115da367bArun Murthy if (!di->ac.charger_connected) { 104984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "AC charger not connected\n"); 105084edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 105184edbeeab67c1575067335179513150115da367bArun Murthy } 105284edbeeab67c1575067335179513150115da367bArun Murthy 105384edbeeab67c1575067335179513150115da367bArun Murthy /* Enable AC charging */ 105484edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Enable AC: %dmV %dmA\n", vset, iset); 105584edbeeab67c1575067335179513150115da367bArun Murthy 105684edbeeab67c1575067335179513150115da367bArun Murthy /* 105784edbeeab67c1575067335179513150115da367bArun Murthy * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts 105884edbeeab67c1575067335179513150115da367bArun Murthy * will be triggered everytime we enable the VDD ADC supply. 105984edbeeab67c1575067335179513150115da367bArun Murthy * This will turn off charging for a short while. 106084edbeeab67c1575067335179513150115da367bArun Murthy * It can be avoided by having the supply on when 106184edbeeab67c1575067335179513150115da367bArun Murthy * there is a charger enabled. Normally the VDD ADC supply 106284edbeeab67c1575067335179513150115da367bArun Murthy * is enabled everytime a GPADC conversion is triggered. We will 106384edbeeab67c1575067335179513150115da367bArun Murthy * force it to be enabled from this driver to have 106484edbeeab67c1575067335179513150115da367bArun Murthy * the GPADC module independant of the AB8500 chargers 106584edbeeab67c1575067335179513150115da367bArun Murthy */ 106684edbeeab67c1575067335179513150115da367bArun Murthy if (!di->vddadc_en_ac) { 106784edbeeab67c1575067335179513150115da367bArun Murthy regulator_enable(di->regu); 106884edbeeab67c1575067335179513150115da367bArun Murthy di->vddadc_en_ac = true; 106984edbeeab67c1575067335179513150115da367bArun Murthy } 107084edbeeab67c1575067335179513150115da367bArun Murthy 107184edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the requested voltage or current is valid */ 107284edbeeab67c1575067335179513150115da367bArun Murthy volt_index = ab8500_voltage_to_regval(vset); 107384edbeeab67c1575067335179513150115da367bArun Murthy curr_index = ab8500_current_to_regval(iset); 107484edbeeab67c1575067335179513150115da367bArun Murthy input_curr_index = ab8500_current_to_regval( 107584edbeeab67c1575067335179513150115da367bArun Murthy di->bat->chg_params->ac_curr_max); 107684edbeeab67c1575067335179513150115da367bArun Murthy if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { 107784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 107884edbeeab67c1575067335179513150115da367bArun Murthy "Charger voltage or current too high, " 107984edbeeab67c1575067335179513150115da367bArun Murthy "charging not started\n"); 108084edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 108184edbeeab67c1575067335179513150115da367bArun Murthy } 108284edbeeab67c1575067335179513150115da367bArun Murthy 108384edbeeab67c1575067335179513150115da367bArun Murthy /* ChVoltLevel: maximum battery charging voltage */ 108484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 108584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_REG, (u8) volt_index); 108684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 108784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 108884edbeeab67c1575067335179513150115da367bArun Murthy return ret; 108984edbeeab67c1575067335179513150115da367bArun Murthy } 109084edbeeab67c1575067335179513150115da367bArun Murthy /* MainChInputCurr: current that can be drawn from the charger*/ 109184edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 109284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MCH_IPT_CURLVL_REG, 109384edbeeab67c1575067335179513150115da367bArun Murthy input_curr_index << MAIN_CH_INPUT_CURR_SHIFT); 109484edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 109584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 109684edbeeab67c1575067335179513150115da367bArun Murthy return ret; 109784edbeeab67c1575067335179513150115da367bArun Murthy } 109884edbeeab67c1575067335179513150115da367bArun Murthy /* ChOutputCurentLevel: protected output current */ 109984edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 110084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); 110184edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 110284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 110384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 110484edbeeab67c1575067335179513150115da367bArun Murthy } 110584edbeeab67c1575067335179513150115da367bArun Murthy 110684edbeeab67c1575067335179513150115da367bArun Murthy /* Check if VBAT overshoot control should be enabled */ 110784edbeeab67c1575067335179513150115da367bArun Murthy if (!di->bat->enable_overshoot) 110884edbeeab67c1575067335179513150115da367bArun Murthy overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N; 110984edbeeab67c1575067335179513150115da367bArun Murthy 111084edbeeab67c1575067335179513150115da367bArun Murthy /* Enable Main Charger */ 111184edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 111284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MCH_CTRL1, MAIN_CH_ENA | overshoot); 111384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 111484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 111584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 111684edbeeab67c1575067335179513150115da367bArun Murthy } 111784edbeeab67c1575067335179513150115da367bArun Murthy 111884edbeeab67c1575067335179513150115da367bArun Murthy /* Power on charging LED indication */ 111984edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, true); 112084edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 112184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to enable LED\n"); 112284edbeeab67c1575067335179513150115da367bArun Murthy 112384edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_online = 1; 112484edbeeab67c1575067335179513150115da367bArun Murthy } else { 112584edbeeab67c1575067335179513150115da367bArun Murthy /* Disable AC charging */ 112684edbeeab67c1575067335179513150115da367bArun Murthy if (is_ab8500_1p1_or_earlier(di->parent)) { 112784edbeeab67c1575067335179513150115da367bArun Murthy /* 112884edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the 112984edbeeab67c1575067335179513150115da367bArun Murthy * watchdog logic. That means we have to continously 113084edbeeab67c1575067335179513150115da367bArun Murthy * kick the charger watchdog even when no charger is 113184edbeeab67c1575067335179513150115da367bArun Murthy * connected. This is only valid once the AC charger 113284edbeeab67c1575067335179513150115da367bArun Murthy * has been enabled. This is a bug that is not handled 113384edbeeab67c1575067335179513150115da367bArun Murthy * by the algorithm and the watchdog have to be kicked 113484edbeeab67c1575067335179513150115da367bArun Murthy * by the charger driver when the AC charger 113584edbeeab67c1575067335179513150115da367bArun Murthy * is disabled 113684edbeeab67c1575067335179513150115da367bArun Murthy */ 113784edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac_conn) { 113884edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 113984edbeeab67c1575067335179513150115da367bArun Murthy &di->kick_wd_work, 114084edbeeab67c1575067335179513150115da367bArun Murthy round_jiffies(WD_KICK_INTERVAL)); 114184edbeeab67c1575067335179513150115da367bArun Murthy } 114284edbeeab67c1575067335179513150115da367bArun Murthy 114384edbeeab67c1575067335179513150115da367bArun Murthy /* 114484edbeeab67c1575067335179513150115da367bArun Murthy * We can't turn off charging completely 114584edbeeab67c1575067335179513150115da367bArun Murthy * due to a bug in AB8500 cut1. 114684edbeeab67c1575067335179513150115da367bArun Murthy * If we do, charging will not start again. 114784edbeeab67c1575067335179513150115da367bArun Murthy * That is why we set the lowest voltage 114884edbeeab67c1575067335179513150115da367bArun Murthy * and current possible 114984edbeeab67c1575067335179513150115da367bArun Murthy */ 115084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 115184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 115284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_REG, CH_VOL_LVL_3P5); 115384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 115484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 115584edbeeab67c1575067335179513150115da367bArun Murthy "%s write failed\n", __func__); 115684edbeeab67c1575067335179513150115da367bArun Murthy return ret; 115784edbeeab67c1575067335179513150115da367bArun Murthy } 115884edbeeab67c1575067335179513150115da367bArun Murthy 115984edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 116084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 116184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_OPT_CRNTLVL_REG, CH_OP_CUR_LVL_0P1); 116284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 116384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 116484edbeeab67c1575067335179513150115da367bArun Murthy "%s write failed\n", __func__); 116584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 116684edbeeab67c1575067335179513150115da367bArun Murthy } 116784edbeeab67c1575067335179513150115da367bArun Murthy } else { 116884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 116984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 117084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MCH_CTRL1, 0); 117184edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 117284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 117384edbeeab67c1575067335179513150115da367bArun Murthy "%s write failed\n", __func__); 117484edbeeab67c1575067335179513150115da367bArun Murthy return ret; 117584edbeeab67c1575067335179513150115da367bArun Murthy } 117684edbeeab67c1575067335179513150115da367bArun Murthy } 117784edbeeab67c1575067335179513150115da367bArun Murthy 117884edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, false); 117984edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 118084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to disable LED\n"); 118184edbeeab67c1575067335179513150115da367bArun Murthy 118284edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_online = 0; 118384edbeeab67c1575067335179513150115da367bArun Murthy di->ac.wd_expired = false; 118484edbeeab67c1575067335179513150115da367bArun Murthy 118584edbeeab67c1575067335179513150115da367bArun Murthy /* Disable regulator if enabled */ 118684edbeeab67c1575067335179513150115da367bArun Murthy if (di->vddadc_en_ac) { 118784edbeeab67c1575067335179513150115da367bArun Murthy regulator_disable(di->regu); 118884edbeeab67c1575067335179513150115da367bArun Murthy di->vddadc_en_ac = false; 118984edbeeab67c1575067335179513150115da367bArun Murthy } 119084edbeeab67c1575067335179513150115da367bArun Murthy 119184edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s Disabled AC charging\n", __func__); 119284edbeeab67c1575067335179513150115da367bArun Murthy } 119384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 119484edbeeab67c1575067335179513150115da367bArun Murthy 119584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 119684edbeeab67c1575067335179513150115da367bArun Murthy} 119784edbeeab67c1575067335179513150115da367bArun Murthy 119884edbeeab67c1575067335179513150115da367bArun Murthy/** 119984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_en() - enable usb charging 120084edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 120184edbeeab67c1575067335179513150115da367bArun Murthy * @enable: enable/disable flag 120284edbeeab67c1575067335179513150115da367bArun Murthy * @vset: charging voltage 120384edbeeab67c1575067335179513150115da367bArun Murthy * @ich_out: charger output current 120484edbeeab67c1575067335179513150115da367bArun Murthy * 120584edbeeab67c1575067335179513150115da367bArun Murthy * Enable/Disable USB charging and turns on/off the charging led respectively. 120684edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 120784edbeeab67c1575067335179513150115da367bArun Murthy */ 120884edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_en(struct ux500_charger *charger, 120984edbeeab67c1575067335179513150115da367bArun Murthy int enable, int vset, int ich_out) 121084edbeeab67c1575067335179513150115da367bArun Murthy{ 121184edbeeab67c1575067335179513150115da367bArun Murthy int ret; 121284edbeeab67c1575067335179513150115da367bArun Murthy int volt_index; 121384edbeeab67c1575067335179513150115da367bArun Murthy int curr_index; 121484edbeeab67c1575067335179513150115da367bArun Murthy u8 overshoot = 0; 121584edbeeab67c1575067335179513150115da367bArun Murthy 121684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger); 121784edbeeab67c1575067335179513150115da367bArun Murthy 121884edbeeab67c1575067335179513150115da367bArun Murthy if (enable) { 121984edbeeab67c1575067335179513150115da367bArun Murthy /* Check if USB is connected */ 122084edbeeab67c1575067335179513150115da367bArun Murthy if (!di->usb.charger_connected) { 122184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "USB charger not connected\n"); 122284edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 122384edbeeab67c1575067335179513150115da367bArun Murthy } 122484edbeeab67c1575067335179513150115da367bArun Murthy 122584edbeeab67c1575067335179513150115da367bArun Murthy /* 122684edbeeab67c1575067335179513150115da367bArun Murthy * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts 122784edbeeab67c1575067335179513150115da367bArun Murthy * will be triggered everytime we enable the VDD ADC supply. 122884edbeeab67c1575067335179513150115da367bArun Murthy * This will turn off charging for a short while. 122984edbeeab67c1575067335179513150115da367bArun Murthy * It can be avoided by having the supply on when 123084edbeeab67c1575067335179513150115da367bArun Murthy * there is a charger enabled. Normally the VDD ADC supply 123184edbeeab67c1575067335179513150115da367bArun Murthy * is enabled everytime a GPADC conversion is triggered. We will 123284edbeeab67c1575067335179513150115da367bArun Murthy * force it to be enabled from this driver to have 123384edbeeab67c1575067335179513150115da367bArun Murthy * the GPADC module independant of the AB8500 chargers 123484edbeeab67c1575067335179513150115da367bArun Murthy */ 123584edbeeab67c1575067335179513150115da367bArun Murthy if (!di->vddadc_en_usb) { 123684edbeeab67c1575067335179513150115da367bArun Murthy regulator_enable(di->regu); 123784edbeeab67c1575067335179513150115da367bArun Murthy di->vddadc_en_usb = true; 123884edbeeab67c1575067335179513150115da367bArun Murthy } 123984edbeeab67c1575067335179513150115da367bArun Murthy 124084edbeeab67c1575067335179513150115da367bArun Murthy /* Enable USB charging */ 124184edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Enable USB: %dmV %dmA\n", vset, ich_out); 124284edbeeab67c1575067335179513150115da367bArun Murthy 124384edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the requested voltage or current is valid */ 124484edbeeab67c1575067335179513150115da367bArun Murthy volt_index = ab8500_voltage_to_regval(vset); 124584edbeeab67c1575067335179513150115da367bArun Murthy curr_index = ab8500_current_to_regval(ich_out); 124684edbeeab67c1575067335179513150115da367bArun Murthy if (volt_index < 0 || curr_index < 0) { 124784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 124884edbeeab67c1575067335179513150115da367bArun Murthy "Charger voltage or current too high, " 124984edbeeab67c1575067335179513150115da367bArun Murthy "charging not started\n"); 125084edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 125184edbeeab67c1575067335179513150115da367bArun Murthy } 125284edbeeab67c1575067335179513150115da367bArun Murthy 125384edbeeab67c1575067335179513150115da367bArun Murthy /* ChVoltLevel: max voltage upto which battery can be charged */ 125484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 125584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_REG, (u8) volt_index); 125684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 125784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 125884edbeeab67c1575067335179513150115da367bArun Murthy return ret; 125984edbeeab67c1575067335179513150115da367bArun Murthy } 126084edbeeab67c1575067335179513150115da367bArun Murthy /* USBChInputCurr: current that can be drawn from the usb */ 126184edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); 126284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 126384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "setting USBChInputCurr failed\n"); 126484edbeeab67c1575067335179513150115da367bArun Murthy return ret; 126584edbeeab67c1575067335179513150115da367bArun Murthy } 126684edbeeab67c1575067335179513150115da367bArun Murthy /* ChOutputCurentLevel: protected output current */ 126784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 126884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); 126984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 127084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 127184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 127284edbeeab67c1575067335179513150115da367bArun Murthy } 127384edbeeab67c1575067335179513150115da367bArun Murthy /* Check if VBAT overshoot control should be enabled */ 127484edbeeab67c1575067335179513150115da367bArun Murthy if (!di->bat->enable_overshoot) 127584edbeeab67c1575067335179513150115da367bArun Murthy overshoot = USB_CHG_NO_OVERSHOOT_ENA_N; 127684edbeeab67c1575067335179513150115da367bArun Murthy 127784edbeeab67c1575067335179513150115da367bArun Murthy /* Enable USB Charger */ 127884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 127984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot); 128084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 128184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 128284edbeeab67c1575067335179513150115da367bArun Murthy return ret; 128384edbeeab67c1575067335179513150115da367bArun Murthy } 128484edbeeab67c1575067335179513150115da367bArun Murthy 128584edbeeab67c1575067335179513150115da367bArun Murthy /* If success power on charging LED indication */ 128684edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, true); 128784edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 128884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to enable LED\n"); 128984edbeeab67c1575067335179513150115da367bArun Murthy 129084edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ); 129184edbeeab67c1575067335179513150115da367bArun Murthy 129284edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_online = 1; 129384edbeeab67c1575067335179513150115da367bArun Murthy } else { 129484edbeeab67c1575067335179513150115da367bArun Murthy /* Disable USB charging */ 129584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 129684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 129784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USBCH_CTRL1_REG, 0); 129884edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 129984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 130084edbeeab67c1575067335179513150115da367bArun Murthy "%s write failed\n", __func__); 130184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 130284edbeeab67c1575067335179513150115da367bArun Murthy } 130384edbeeab67c1575067335179513150115da367bArun Murthy 130484edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_led_en(di, false); 130584edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 130684edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to disable LED\n"); 130784edbeeab67c1575067335179513150115da367bArun Murthy 130884edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_online = 0; 130984edbeeab67c1575067335179513150115da367bArun Murthy di->usb.wd_expired = false; 131084edbeeab67c1575067335179513150115da367bArun Murthy 131184edbeeab67c1575067335179513150115da367bArun Murthy /* Disable regulator if enabled */ 131284edbeeab67c1575067335179513150115da367bArun Murthy if (di->vddadc_en_usb) { 131384edbeeab67c1575067335179513150115da367bArun Murthy regulator_disable(di->regu); 131484edbeeab67c1575067335179513150115da367bArun Murthy di->vddadc_en_usb = false; 131584edbeeab67c1575067335179513150115da367bArun Murthy } 131684edbeeab67c1575067335179513150115da367bArun Murthy 131784edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); 131884edbeeab67c1575067335179513150115da367bArun Murthy 131984edbeeab67c1575067335179513150115da367bArun Murthy /* Cancel any pending Vbat check work */ 132084edbeeab67c1575067335179513150115da367bArun Murthy if (delayed_work_pending(&di->check_vbat_work)) 132184edbeeab67c1575067335179513150115da367bArun Murthy cancel_delayed_work(&di->check_vbat_work); 132284edbeeab67c1575067335179513150115da367bArun Murthy 132384edbeeab67c1575067335179513150115da367bArun Murthy } 132484edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 132584edbeeab67c1575067335179513150115da367bArun Murthy 132684edbeeab67c1575067335179513150115da367bArun Murthy return ret; 132784edbeeab67c1575067335179513150115da367bArun Murthy} 132884edbeeab67c1575067335179513150115da367bArun Murthy 132984edbeeab67c1575067335179513150115da367bArun Murthy/** 133084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_watchdog_kick() - kick charger watchdog 133184edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 133284edbeeab67c1575067335179513150115da367bArun Murthy * 133384edbeeab67c1575067335179513150115da367bArun Murthy * Kick charger watchdog 133484edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 133584edbeeab67c1575067335179513150115da367bArun Murthy */ 133684edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_watchdog_kick(struct ux500_charger *charger) 133784edbeeab67c1575067335179513150115da367bArun Murthy{ 133884edbeeab67c1575067335179513150115da367bArun Murthy int ret; 133984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 134084edbeeab67c1575067335179513150115da367bArun Murthy 134184edbeeab67c1575067335179513150115da367bArun Murthy if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) 134284edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_ac_device_info(charger); 134384edbeeab67c1575067335179513150115da367bArun Murthy else if (charger->psy.type == POWER_SUPPLY_TYPE_USB) 134484edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(charger); 134584edbeeab67c1575067335179513150115da367bArun Murthy else 134684edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 134784edbeeab67c1575067335179513150115da367bArun Murthy 134884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 134984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 135084edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 135184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Failed to kick WD!\n"); 135284edbeeab67c1575067335179513150115da367bArun Murthy 135384edbeeab67c1575067335179513150115da367bArun Murthy return ret; 135484edbeeab67c1575067335179513150115da367bArun Murthy} 135584edbeeab67c1575067335179513150115da367bArun Murthy 135684edbeeab67c1575067335179513150115da367bArun Murthy/** 135784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_update_charger_current() - update charger current 135884edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 135984edbeeab67c1575067335179513150115da367bArun Murthy * 136084edbeeab67c1575067335179513150115da367bArun Murthy * Update the charger output current for the specified charger 136184edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 136284edbeeab67c1575067335179513150115da367bArun Murthy */ 136384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_update_charger_current(struct ux500_charger *charger, 136484edbeeab67c1575067335179513150115da367bArun Murthy int ich_out) 136584edbeeab67c1575067335179513150115da367bArun Murthy{ 136684edbeeab67c1575067335179513150115da367bArun Murthy int ret; 136784edbeeab67c1575067335179513150115da367bArun Murthy int curr_index; 136884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 136984edbeeab67c1575067335179513150115da367bArun Murthy 137084edbeeab67c1575067335179513150115da367bArun Murthy if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) 137184edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_ac_device_info(charger); 137284edbeeab67c1575067335179513150115da367bArun Murthy else if (charger->psy.type == POWER_SUPPLY_TYPE_USB) 137384edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(charger); 137484edbeeab67c1575067335179513150115da367bArun Murthy else 137584edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 137684edbeeab67c1575067335179513150115da367bArun Murthy 137784edbeeab67c1575067335179513150115da367bArun Murthy curr_index = ab8500_current_to_regval(ich_out); 137884edbeeab67c1575067335179513150115da367bArun Murthy if (curr_index < 0) { 137984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 138084edbeeab67c1575067335179513150115da367bArun Murthy "Charger current too high, " 138184edbeeab67c1575067335179513150115da367bArun Murthy "charging not started\n"); 138284edbeeab67c1575067335179513150115da367bArun Murthy return -ENXIO; 138384edbeeab67c1575067335179513150115da367bArun Murthy } 138484edbeeab67c1575067335179513150115da367bArun Murthy 138584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 138684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); 138784edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 138884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 138984edbeeab67c1575067335179513150115da367bArun Murthy return ret; 139084edbeeab67c1575067335179513150115da367bArun Murthy } 139184edbeeab67c1575067335179513150115da367bArun Murthy 139284edbeeab67c1575067335179513150115da367bArun Murthy /* Reset the main and usb drop input current measurement counter */ 139384edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 139484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER_CTRL, 139584edbeeab67c1575067335179513150115da367bArun Murthy 0x1); 139684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 139784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s write failed\n", __func__); 139884edbeeab67c1575067335179513150115da367bArun Murthy return ret; 139984edbeeab67c1575067335179513150115da367bArun Murthy } 140084edbeeab67c1575067335179513150115da367bArun Murthy 140184edbeeab67c1575067335179513150115da367bArun Murthy return ret; 140284edbeeab67c1575067335179513150115da367bArun Murthy} 140384edbeeab67c1575067335179513150115da367bArun Murthy 140484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ext_psy_data(struct device *dev, void *data) 140584edbeeab67c1575067335179513150115da367bArun Murthy{ 140684edbeeab67c1575067335179513150115da367bArun Murthy struct power_supply *psy; 140784edbeeab67c1575067335179513150115da367bArun Murthy struct power_supply *ext; 140884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 140984edbeeab67c1575067335179513150115da367bArun Murthy union power_supply_propval ret; 141084edbeeab67c1575067335179513150115da367bArun Murthy int i, j; 141184edbeeab67c1575067335179513150115da367bArun Murthy bool psy_found = false; 141284edbeeab67c1575067335179513150115da367bArun Murthy struct ux500_charger *usb_chg; 141384edbeeab67c1575067335179513150115da367bArun Murthy 141484edbeeab67c1575067335179513150115da367bArun Murthy usb_chg = (struct ux500_charger *)data; 141584edbeeab67c1575067335179513150115da367bArun Murthy psy = &usb_chg->psy; 141684edbeeab67c1575067335179513150115da367bArun Murthy 141784edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(usb_chg); 141884edbeeab67c1575067335179513150115da367bArun Murthy 141984edbeeab67c1575067335179513150115da367bArun Murthy ext = dev_get_drvdata(dev); 142084edbeeab67c1575067335179513150115da367bArun Murthy 142184edbeeab67c1575067335179513150115da367bArun Murthy /* For all psy where the driver name appears in any supplied_to */ 142284edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ext->num_supplicants; i++) { 142384edbeeab67c1575067335179513150115da367bArun Murthy if (!strcmp(ext->supplied_to[i], psy->name)) 142484edbeeab67c1575067335179513150115da367bArun Murthy psy_found = true; 142584edbeeab67c1575067335179513150115da367bArun Murthy } 142684edbeeab67c1575067335179513150115da367bArun Murthy 142784edbeeab67c1575067335179513150115da367bArun Murthy if (!psy_found) 142884edbeeab67c1575067335179513150115da367bArun Murthy return 0; 142984edbeeab67c1575067335179513150115da367bArun Murthy 143084edbeeab67c1575067335179513150115da367bArun Murthy /* Go through all properties for the psy */ 143184edbeeab67c1575067335179513150115da367bArun Murthy for (j = 0; j < ext->num_properties; j++) { 143284edbeeab67c1575067335179513150115da367bArun Murthy enum power_supply_property prop; 143384edbeeab67c1575067335179513150115da367bArun Murthy prop = ext->properties[j]; 143484edbeeab67c1575067335179513150115da367bArun Murthy 143584edbeeab67c1575067335179513150115da367bArun Murthy if (ext->get_property(ext, prop, &ret)) 143684edbeeab67c1575067335179513150115da367bArun Murthy continue; 143784edbeeab67c1575067335179513150115da367bArun Murthy 143884edbeeab67c1575067335179513150115da367bArun Murthy switch (prop) { 143984edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_NOW: 144084edbeeab67c1575067335179513150115da367bArun Murthy switch (ext->type) { 144184edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_TYPE_BATTERY: 144284edbeeab67c1575067335179513150115da367bArun Murthy di->vbat = ret.intval / 1000; 144384edbeeab67c1575067335179513150115da367bArun Murthy break; 144484edbeeab67c1575067335179513150115da367bArun Murthy default: 144584edbeeab67c1575067335179513150115da367bArun Murthy break; 144684edbeeab67c1575067335179513150115da367bArun Murthy } 144784edbeeab67c1575067335179513150115da367bArun Murthy break; 144884edbeeab67c1575067335179513150115da367bArun Murthy default: 144984edbeeab67c1575067335179513150115da367bArun Murthy break; 145084edbeeab67c1575067335179513150115da367bArun Murthy } 145184edbeeab67c1575067335179513150115da367bArun Murthy } 145284edbeeab67c1575067335179513150115da367bArun Murthy return 0; 145384edbeeab67c1575067335179513150115da367bArun Murthy} 145484edbeeab67c1575067335179513150115da367bArun Murthy 145584edbeeab67c1575067335179513150115da367bArun Murthy/** 145684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_vbat_work() - keep vbus current within spec 145784edbeeab67c1575067335179513150115da367bArun Murthy * @work pointer to the work_struct structure 145884edbeeab67c1575067335179513150115da367bArun Murthy * 145984edbeeab67c1575067335179513150115da367bArun Murthy * Due to a asic bug it is necessary to lower the input current to the vbus 146084edbeeab67c1575067335179513150115da367bArun Murthy * charger when charging with at some specific levels. This issue is only valid 146184edbeeab67c1575067335179513150115da367bArun Murthy * for below a certain battery voltage. This function makes sure that the 146284edbeeab67c1575067335179513150115da367bArun Murthy * the allowed current limit isn't exceeded. 146384edbeeab67c1575067335179513150115da367bArun Murthy */ 146484edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_vbat_work(struct work_struct *work) 146584edbeeab67c1575067335179513150115da367bArun Murthy{ 146684edbeeab67c1575067335179513150115da367bArun Murthy int t = 10; 146784edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 146884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_vbat_work.work); 146984edbeeab67c1575067335179513150115da367bArun Murthy 147084edbeeab67c1575067335179513150115da367bArun Murthy class_for_each_device(power_supply_class, NULL, 147184edbeeab67c1575067335179513150115da367bArun Murthy &di->usb_chg.psy, ab8500_charger_get_ext_psy_data); 147284edbeeab67c1575067335179513150115da367bArun Murthy 147384edbeeab67c1575067335179513150115da367bArun Murthy /* First run old_vbat is 0. */ 147484edbeeab67c1575067335179513150115da367bArun Murthy if (di->old_vbat == 0) 147584edbeeab67c1575067335179513150115da367bArun Murthy di->old_vbat = di->vbat; 147684edbeeab67c1575067335179513150115da367bArun Murthy 147784edbeeab67c1575067335179513150115da367bArun Murthy if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED && 147884edbeeab67c1575067335179513150115da367bArun Murthy di->vbat <= VBAT_TRESH_IP_CUR_RED) || 147984edbeeab67c1575067335179513150115da367bArun Murthy (di->old_vbat > VBAT_TRESH_IP_CUR_RED && 148084edbeeab67c1575067335179513150115da367bArun Murthy di->vbat > VBAT_TRESH_IP_CUR_RED))) { 148184edbeeab67c1575067335179513150115da367bArun Murthy 148284edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d," 148384edbeeab67c1575067335179513150115da367bArun Murthy " old: %d\n", di->max_usb_in_curr, di->vbat, 148484edbeeab67c1575067335179513150115da367bArun Murthy di->old_vbat); 148584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); 148684edbeeab67c1575067335179513150115da367bArun Murthy power_supply_changed(&di->usb_chg.psy); 148784edbeeab67c1575067335179513150115da367bArun Murthy } 148884edbeeab67c1575067335179513150115da367bArun Murthy 148984edbeeab67c1575067335179513150115da367bArun Murthy di->old_vbat = di->vbat; 149084edbeeab67c1575067335179513150115da367bArun Murthy 149184edbeeab67c1575067335179513150115da367bArun Murthy /* 149284edbeeab67c1575067335179513150115da367bArun Murthy * No need to check the battery voltage every second when not close to 149384edbeeab67c1575067335179513150115da367bArun Murthy * the threshold. 149484edbeeab67c1575067335179513150115da367bArun Murthy */ 149584edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) && 149684edbeeab67c1575067335179513150115da367bArun Murthy (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100))) 149784edbeeab67c1575067335179513150115da367bArun Murthy t = 1; 149884edbeeab67c1575067335179513150115da367bArun Murthy 149984edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ); 150084edbeeab67c1575067335179513150115da367bArun Murthy} 150184edbeeab67c1575067335179513150115da367bArun Murthy 150284edbeeab67c1575067335179513150115da367bArun Murthy/** 150384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_hw_failure_work() - check main charger failure 150484edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 150584edbeeab67c1575067335179513150115da367bArun Murthy * 150684edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the main charger status 150784edbeeab67c1575067335179513150115da367bArun Murthy */ 150884edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_hw_failure_work(struct work_struct *work) 150984edbeeab67c1575067335179513150115da367bArun Murthy{ 151084edbeeab67c1575067335179513150115da367bArun Murthy int ret; 151184edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 151284edbeeab67c1575067335179513150115da367bArun Murthy 151384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 151484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_hw_failure_work.work); 151584edbeeab67c1575067335179513150115da367bArun Murthy 151684edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bits for HW failure is still active */ 151784edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok) { 151884edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 151984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); 152084edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 152184edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 152284edbeeab67c1575067335179513150115da367bArun Murthy return; 152384edbeeab67c1575067335179513150115da367bArun Murthy } 152484edbeeab67c1575067335179513150115da367bArun Murthy if (!(reg_value & MAIN_CH_NOK)) { 152584edbeeab67c1575067335179513150115da367bArun Murthy di->flags.mainextchnotok = false; 152684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 152784edbeeab67c1575067335179513150115da367bArun Murthy } 152884edbeeab67c1575067335179513150115da367bArun Murthy } 152984edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.vbus_ovv) { 153084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 153184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, 153284edbeeab67c1575067335179513150115da367bArun Murthy ®_value); 153384edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 153484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 153584edbeeab67c1575067335179513150115da367bArun Murthy return; 153684edbeeab67c1575067335179513150115da367bArun Murthy } 153784edbeeab67c1575067335179513150115da367bArun Murthy if (!(reg_value & VBUS_OVV_TH)) { 153884edbeeab67c1575067335179513150115da367bArun Murthy di->flags.vbus_ovv = false; 153984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 154084edbeeab67c1575067335179513150115da367bArun Murthy } 154184edbeeab67c1575067335179513150115da367bArun Murthy } 154284edbeeab67c1575067335179513150115da367bArun Murthy /* If we still have a failure, schedule a new check */ 154384edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok || di->flags.vbus_ovv) { 154484edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 154584edbeeab67c1575067335179513150115da367bArun Murthy &di->check_hw_failure_work, round_jiffies(HZ)); 154684edbeeab67c1575067335179513150115da367bArun Murthy } 154784edbeeab67c1575067335179513150115da367bArun Murthy} 154884edbeeab67c1575067335179513150115da367bArun Murthy 154984edbeeab67c1575067335179513150115da367bArun Murthy/** 155084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_kick_watchdog_work() - kick the watchdog 155184edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 155284edbeeab67c1575067335179513150115da367bArun Murthy * 155384edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for kicking the charger watchdog. 155484edbeeab67c1575067335179513150115da367bArun Murthy * 155584edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 155684edbeeab67c1575067335179513150115da367bArun Murthy * logic. That means we have to continously kick the charger 155784edbeeab67c1575067335179513150115da367bArun Murthy * watchdog even when no charger is connected. This is only 155884edbeeab67c1575067335179513150115da367bArun Murthy * valid once the AC charger has been enabled. This is 155984edbeeab67c1575067335179513150115da367bArun Murthy * a bug that is not handled by the algorithm and the 156084edbeeab67c1575067335179513150115da367bArun Murthy * watchdog have to be kicked by the charger driver 156184edbeeab67c1575067335179513150115da367bArun Murthy * when the AC charger is disabled 156284edbeeab67c1575067335179513150115da367bArun Murthy */ 156384edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_kick_watchdog_work(struct work_struct *work) 156484edbeeab67c1575067335179513150115da367bArun Murthy{ 156584edbeeab67c1575067335179513150115da367bArun Murthy int ret; 156684edbeeab67c1575067335179513150115da367bArun Murthy 156784edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 156884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, kick_wd_work.work); 156984edbeeab67c1575067335179513150115da367bArun Murthy 157084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 157184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 157284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 157384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Failed to kick WD!\n"); 157484edbeeab67c1575067335179513150115da367bArun Murthy 157584edbeeab67c1575067335179513150115da367bArun Murthy /* Schedule a new watchdog kick */ 157684edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 157784edbeeab67c1575067335179513150115da367bArun Murthy &di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL)); 157884edbeeab67c1575067335179513150115da367bArun Murthy} 157984edbeeab67c1575067335179513150115da367bArun Murthy 158084edbeeab67c1575067335179513150115da367bArun Murthy/** 158184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_work() - work to get and set main charger status 158284edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 158384edbeeab67c1575067335179513150115da367bArun Murthy * 158484edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the main charger status 158584edbeeab67c1575067335179513150115da367bArun Murthy */ 158684edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_ac_work(struct work_struct *work) 158784edbeeab67c1575067335179513150115da367bArun Murthy{ 158884edbeeab67c1575067335179513150115da367bArun Murthy int ret; 158984edbeeab67c1575067335179513150115da367bArun Murthy 159084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 159184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, ac_work); 159284edbeeab67c1575067335179513150115da367bArun Murthy 159384edbeeab67c1575067335179513150115da367bArun Murthy /* 159484edbeeab67c1575067335179513150115da367bArun Murthy * Since we can't be sure that the events are received 159584edbeeab67c1575067335179513150115da367bArun Murthy * synchronously, we have the check if the main charger is 159684edbeeab67c1575067335179513150115da367bArun Murthy * connected by reading the status register 159784edbeeab67c1575067335179513150115da367bArun Murthy */ 159884edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_detect_chargers(di); 159984edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 160084edbeeab67c1575067335179513150115da367bArun Murthy return; 160184edbeeab67c1575067335179513150115da367bArun Murthy 160284edbeeab67c1575067335179513150115da367bArun Murthy if (ret & AC_PW_CONN) { 160384edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_connected = 1; 160484edbeeab67c1575067335179513150115da367bArun Murthy di->ac_conn = true; 160584edbeeab67c1575067335179513150115da367bArun Murthy } else { 160684edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_connected = 0; 160784edbeeab67c1575067335179513150115da367bArun Murthy } 160884edbeeab67c1575067335179513150115da367bArun Murthy 160984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 161084edbeeab67c1575067335179513150115da367bArun Murthy sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); 161184edbeeab67c1575067335179513150115da367bArun Murthy} 161284edbeeab67c1575067335179513150115da367bArun Murthy 161384edbeeab67c1575067335179513150115da367bArun Murthy/** 161484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_usb_type_work() - work to detect USB type 161584edbeeab67c1575067335179513150115da367bArun Murthy * @work: Pointer to the work_struct structure 161684edbeeab67c1575067335179513150115da367bArun Murthy * 161784edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of USB plugged 161884edbeeab67c1575067335179513150115da367bArun Murthy */ 161964eb9b02bfbbc2a53b6092cc12c1f42cc3261dbcAnton Vorontsovstatic void ab8500_charger_detect_usb_type_work(struct work_struct *work) 162084edbeeab67c1575067335179513150115da367bArun Murthy{ 162184edbeeab67c1575067335179513150115da367bArun Murthy int ret; 162284edbeeab67c1575067335179513150115da367bArun Murthy 162384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 162484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, detect_usb_type_work); 162584edbeeab67c1575067335179513150115da367bArun Murthy 162684edbeeab67c1575067335179513150115da367bArun Murthy /* 162784edbeeab67c1575067335179513150115da367bArun Murthy * Since we can't be sure that the events are received 162884edbeeab67c1575067335179513150115da367bArun Murthy * synchronously, we have the check if is 162984edbeeab67c1575067335179513150115da367bArun Murthy * connected by reading the status register 163084edbeeab67c1575067335179513150115da367bArun Murthy */ 163184edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_detect_chargers(di); 163284edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 163384edbeeab67c1575067335179513150115da367bArun Murthy return; 163484edbeeab67c1575067335179513150115da367bArun Murthy 163584edbeeab67c1575067335179513150115da367bArun Murthy if (!(ret & USB_PW_CONN)) { 163684edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = 0; 163784edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, false); 163884edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 163984edbeeab67c1575067335179513150115da367bArun Murthy } else { 164084edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = 1; 164184edbeeab67c1575067335179513150115da367bArun Murthy 164284edbeeab67c1575067335179513150115da367bArun Murthy if (is_ab8500_1p1_or_earlier(di->parent)) { 164384edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_detect_usb_type(di); 164484edbeeab67c1575067335179513150115da367bArun Murthy if (!ret) { 164584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, true); 164684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, 164784edbeeab67c1575067335179513150115da367bArun Murthy &di->usb_chg.psy); 164884edbeeab67c1575067335179513150115da367bArun Murthy } 164984edbeeab67c1575067335179513150115da367bArun Murthy } else { 165084edbeeab67c1575067335179513150115da367bArun Murthy /* For ABB cut2.0 and onwards we have an IRQ, 165184edbeeab67c1575067335179513150115da367bArun Murthy * USB_LINK_STATUS that will be triggered when the USB 165284edbeeab67c1575067335179513150115da367bArun Murthy * link status changes. The exception is USB connected 165384edbeeab67c1575067335179513150115da367bArun Murthy * during startup. Then we don't get a 165484edbeeab67c1575067335179513150115da367bArun Murthy * USB_LINK_STATUS IRQ 165584edbeeab67c1575067335179513150115da367bArun Murthy */ 165684edbeeab67c1575067335179513150115da367bArun Murthy if (di->vbus_detected_start) { 165784edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected_start = false; 165884edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_detect_usb_type(di); 165984edbeeab67c1575067335179513150115da367bArun Murthy if (!ret) { 166084edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, 166184edbeeab67c1575067335179513150115da367bArun Murthy true); 166284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, 166384edbeeab67c1575067335179513150115da367bArun Murthy &di->usb_chg.psy); 166484edbeeab67c1575067335179513150115da367bArun Murthy } 166584edbeeab67c1575067335179513150115da367bArun Murthy } 166684edbeeab67c1575067335179513150115da367bArun Murthy } 166784edbeeab67c1575067335179513150115da367bArun Murthy } 166884edbeeab67c1575067335179513150115da367bArun Murthy} 166984edbeeab67c1575067335179513150115da367bArun Murthy 167084edbeeab67c1575067335179513150115da367bArun Murthy/** 167184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_link_status_work() - work to detect USB type 167284edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 167384edbeeab67c1575067335179513150115da367bArun Murthy * 167484edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of USB plugged 167584edbeeab67c1575067335179513150115da367bArun Murthy */ 167684edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_usb_link_status_work(struct work_struct *work) 167784edbeeab67c1575067335179513150115da367bArun Murthy{ 167884edbeeab67c1575067335179513150115da367bArun Murthy int ret; 167984edbeeab67c1575067335179513150115da367bArun Murthy 168084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 168184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, usb_link_status_work); 168284edbeeab67c1575067335179513150115da367bArun Murthy 168384edbeeab67c1575067335179513150115da367bArun Murthy /* 168484edbeeab67c1575067335179513150115da367bArun Murthy * Since we can't be sure that the events are received 168584edbeeab67c1575067335179513150115da367bArun Murthy * synchronously, we have the check if is 168684edbeeab67c1575067335179513150115da367bArun Murthy * connected by reading the status register 168784edbeeab67c1575067335179513150115da367bArun Murthy */ 168884edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_detect_chargers(di); 168984edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 169084edbeeab67c1575067335179513150115da367bArun Murthy return; 169184edbeeab67c1575067335179513150115da367bArun Murthy 169284edbeeab67c1575067335179513150115da367bArun Murthy if (!(ret & USB_PW_CONN)) { 169384edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = 0; 169484edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, false); 169584edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 169684edbeeab67c1575067335179513150115da367bArun Murthy } else { 169784edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = 1; 169884edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_read_usb_type(di); 169984edbeeab67c1575067335179513150115da367bArun Murthy if (!ret) { 170084edbeeab67c1575067335179513150115da367bArun Murthy /* Update maximum input current */ 170184edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_set_vbus_in_curr(di, 170284edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr); 170384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 170484edbeeab67c1575067335179513150115da367bArun Murthy return; 170584edbeeab67c1575067335179513150115da367bArun Murthy 170684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, true); 170784edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 170884edbeeab67c1575067335179513150115da367bArun Murthy } else if (ret == -ENXIO) { 170984edbeeab67c1575067335179513150115da367bArun Murthy /* No valid charger type detected */ 171084edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, false); 171184edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 171284edbeeab67c1575067335179513150115da367bArun Murthy } 171384edbeeab67c1575067335179513150115da367bArun Murthy } 171484edbeeab67c1575067335179513150115da367bArun Murthy} 171584edbeeab67c1575067335179513150115da367bArun Murthy 171684edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_usb_state_changed_work(struct work_struct *work) 171784edbeeab67c1575067335179513150115da367bArun Murthy{ 171884edbeeab67c1575067335179513150115da367bArun Murthy int ret; 171984edbeeab67c1575067335179513150115da367bArun Murthy unsigned long flags; 172084edbeeab67c1575067335179513150115da367bArun Murthy 172184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 172284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, usb_state_changed_work); 172384edbeeab67c1575067335179513150115da367bArun Murthy 172484edbeeab67c1575067335179513150115da367bArun Murthy if (!di->vbus_detected) 172584edbeeab67c1575067335179513150115da367bArun Murthy return; 172684edbeeab67c1575067335179513150115da367bArun Murthy 172784edbeeab67c1575067335179513150115da367bArun Murthy spin_lock_irqsave(&di->usb_state.usb_lock, flags); 172884edbeeab67c1575067335179513150115da367bArun Murthy di->usb_state.usb_changed = false; 172984edbeeab67c1575067335179513150115da367bArun Murthy spin_unlock_irqrestore(&di->usb_state.usb_lock, flags); 173084edbeeab67c1575067335179513150115da367bArun Murthy 173184edbeeab67c1575067335179513150115da367bArun Murthy /* 173284edbeeab67c1575067335179513150115da367bArun Murthy * wait for some time until you get updates from the usb stack 173384edbeeab67c1575067335179513150115da367bArun Murthy * and negotiations are completed 173484edbeeab67c1575067335179513150115da367bArun Murthy */ 173584edbeeab67c1575067335179513150115da367bArun Murthy msleep(250); 173684edbeeab67c1575067335179513150115da367bArun Murthy 173784edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb_state.usb_changed) 173884edbeeab67c1575067335179513150115da367bArun Murthy return; 173984edbeeab67c1575067335179513150115da367bArun Murthy 174084edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n", 174184edbeeab67c1575067335179513150115da367bArun Murthy __func__, di->usb_state.state, di->usb_state.usb_current); 174284edbeeab67c1575067335179513150115da367bArun Murthy 174384edbeeab67c1575067335179513150115da367bArun Murthy switch (di->usb_state.state) { 174484edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_RESET_HS: 174584edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_RESET_FS: 174684edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_SUSPEND: 174784edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_MAX: 174884edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, false); 174984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 175084edbeeab67c1575067335179513150115da367bArun Murthy break; 175184edbeeab67c1575067335179513150115da367bArun Murthy 175284edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_RESUME: 175384edbeeab67c1575067335179513150115da367bArun Murthy /* 175484edbeeab67c1575067335179513150115da367bArun Murthy * when suspend->resume there should be delay 175584edbeeab67c1575067335179513150115da367bArun Murthy * of 1sec for enabling charging 175684edbeeab67c1575067335179513150115da367bArun Murthy */ 175784edbeeab67c1575067335179513150115da367bArun Murthy msleep(1000); 175884edbeeab67c1575067335179513150115da367bArun Murthy /* Intentional fall through */ 175984edbeeab67c1575067335179513150115da367bArun Murthy case AB8500_BM_USB_STATE_CONFIGURED: 176084edbeeab67c1575067335179513150115da367bArun Murthy /* 176184edbeeab67c1575067335179513150115da367bArun Murthy * USB is configured, enable charging with the charging 176284edbeeab67c1575067335179513150115da367bArun Murthy * input current obtained from USB driver 176384edbeeab67c1575067335179513150115da367bArun Murthy */ 176484edbeeab67c1575067335179513150115da367bArun Murthy if (!ab8500_charger_get_usb_cur(di)) { 176584edbeeab67c1575067335179513150115da367bArun Murthy /* Update maximum input current */ 176684edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_set_vbus_in_curr(di, 176784edbeeab67c1575067335179513150115da367bArun Murthy di->max_usb_in_curr); 176884edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 176984edbeeab67c1575067335179513150115da367bArun Murthy return; 177084edbeeab67c1575067335179513150115da367bArun Murthy 177184edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_set_usb_connected(di, true); 177284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 177384edbeeab67c1575067335179513150115da367bArun Murthy } 177484edbeeab67c1575067335179513150115da367bArun Murthy break; 177584edbeeab67c1575067335179513150115da367bArun Murthy 177684edbeeab67c1575067335179513150115da367bArun Murthy default: 177784edbeeab67c1575067335179513150115da367bArun Murthy break; 177884edbeeab67c1575067335179513150115da367bArun Murthy }; 177984edbeeab67c1575067335179513150115da367bArun Murthy} 178084edbeeab67c1575067335179513150115da367bArun Murthy 178184edbeeab67c1575067335179513150115da367bArun Murthy/** 178284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status 178384edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 178484edbeeab67c1575067335179513150115da367bArun Murthy * 178584edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the USB charger Not OK status 178684edbeeab67c1575067335179513150115da367bArun Murthy */ 178784edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_usbchargernotok_work(struct work_struct *work) 178884edbeeab67c1575067335179513150115da367bArun Murthy{ 178984edbeeab67c1575067335179513150115da367bArun Murthy int ret; 179084edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 179184edbeeab67c1575067335179513150115da367bArun Murthy bool prev_status; 179284edbeeab67c1575067335179513150115da367bArun Murthy 179384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 179484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_usbchgnotok_work.work); 179584edbeeab67c1575067335179513150115da367bArun Murthy 179684edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bit for usbchargernotok is still active */ 179784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 179884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); 179984edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 180084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 180184edbeeab67c1575067335179513150115da367bArun Murthy return; 180284edbeeab67c1575067335179513150115da367bArun Murthy } 180384edbeeab67c1575067335179513150115da367bArun Murthy prev_status = di->flags.usbchargernotok; 180484edbeeab67c1575067335179513150115da367bArun Murthy 180584edbeeab67c1575067335179513150115da367bArun Murthy if (reg_value & VBUS_CH_NOK) { 180684edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usbchargernotok = true; 180784edbeeab67c1575067335179513150115da367bArun Murthy /* Check again in 1sec */ 180884edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 180984edbeeab67c1575067335179513150115da367bArun Murthy &di->check_usbchgnotok_work, HZ); 181084edbeeab67c1575067335179513150115da367bArun Murthy } else { 181184edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usbchargernotok = false; 181284edbeeab67c1575067335179513150115da367bArun Murthy di->flags.vbus_collapse = false; 181384edbeeab67c1575067335179513150115da367bArun Murthy } 181484edbeeab67c1575067335179513150115da367bArun Murthy 181584edbeeab67c1575067335179513150115da367bArun Murthy if (prev_status != di->flags.usbchargernotok) 181684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 181784edbeeab67c1575067335179513150115da367bArun Murthy} 181884edbeeab67c1575067335179513150115da367bArun Murthy 181984edbeeab67c1575067335179513150115da367bArun Murthy/** 182084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_main_thermal_prot_work() - check main thermal status 182184edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 182284edbeeab67c1575067335179513150115da367bArun Murthy * 182384edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the Main thermal prot status 182484edbeeab67c1575067335179513150115da367bArun Murthy */ 182584edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_main_thermal_prot_work( 182684edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct *work) 182784edbeeab67c1575067335179513150115da367bArun Murthy{ 182884edbeeab67c1575067335179513150115da367bArun Murthy int ret; 182984edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 183084edbeeab67c1575067335179513150115da367bArun Murthy 183184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 183284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_main_thermal_prot_work); 183384edbeeab67c1575067335179513150115da367bArun Murthy 183484edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bit for main_thermal_prot is still active */ 183584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 183684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_STATUS2_REG, ®_value); 183784edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 183884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 183984edbeeab67c1575067335179513150115da367bArun Murthy return; 184084edbeeab67c1575067335179513150115da367bArun Murthy } 184184edbeeab67c1575067335179513150115da367bArun Murthy if (reg_value & MAIN_CH_TH_PROT) 184284edbeeab67c1575067335179513150115da367bArun Murthy di->flags.main_thermal_prot = true; 184384edbeeab67c1575067335179513150115da367bArun Murthy else 184484edbeeab67c1575067335179513150115da367bArun Murthy di->flags.main_thermal_prot = false; 184584edbeeab67c1575067335179513150115da367bArun Murthy 184684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 184784edbeeab67c1575067335179513150115da367bArun Murthy} 184884edbeeab67c1575067335179513150115da367bArun Murthy 184984edbeeab67c1575067335179513150115da367bArun Murthy/** 185084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status 185184edbeeab67c1575067335179513150115da367bArun Murthy * @work: pointer to the work_struct structure 185284edbeeab67c1575067335179513150115da367bArun Murthy * 185384edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the USB thermal prot status 185484edbeeab67c1575067335179513150115da367bArun Murthy */ 185584edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_usb_thermal_prot_work( 185684edbeeab67c1575067335179513150115da367bArun Murthy struct work_struct *work) 185784edbeeab67c1575067335179513150115da367bArun Murthy{ 185884edbeeab67c1575067335179513150115da367bArun Murthy int ret; 185984edbeeab67c1575067335179513150115da367bArun Murthy u8 reg_value; 186084edbeeab67c1575067335179513150115da367bArun Murthy 186184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = container_of(work, 186284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger, check_usb_thermal_prot_work); 186384edbeeab67c1575067335179513150115da367bArun Murthy 186484edbeeab67c1575067335179513150115da367bArun Murthy /* Check if the status bit for usb_thermal_prot is still active */ 186584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_get_register_interruptible(di->dev, 186684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, ®_value); 186784edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) { 186884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s ab8500 read failed\n", __func__); 186984edbeeab67c1575067335179513150115da367bArun Murthy return; 187084edbeeab67c1575067335179513150115da367bArun Murthy } 187184edbeeab67c1575067335179513150115da367bArun Murthy if (reg_value & USB_CH_TH_PROT) 187284edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usb_thermal_prot = true; 187384edbeeab67c1575067335179513150115da367bArun Murthy else 187484edbeeab67c1575067335179513150115da367bArun Murthy di->flags.usb_thermal_prot = false; 187584edbeeab67c1575067335179513150115da367bArun Murthy 187684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 187784edbeeab67c1575067335179513150115da367bArun Murthy} 187884edbeeab67c1575067335179513150115da367bArun Murthy 187984edbeeab67c1575067335179513150115da367bArun Murthy/** 188084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchunplugdet_handler() - main charger unplugged 188184edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 188284edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 188384edbeeab67c1575067335179513150115da367bArun Murthy * 188484edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 188584edbeeab67c1575067335179513150115da367bArun Murthy */ 188684edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di) 188784edbeeab67c1575067335179513150115da367bArun Murthy{ 188884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 188984edbeeab67c1575067335179513150115da367bArun Murthy 189084edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Main charger unplugged\n"); 189184edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->ac_work); 189284edbeeab67c1575067335179513150115da367bArun Murthy 189384edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 189484edbeeab67c1575067335179513150115da367bArun Murthy} 189584edbeeab67c1575067335179513150115da367bArun Murthy 189684edbeeab67c1575067335179513150115da367bArun Murthy/** 189784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchplugdet_handler() - main charger plugged 189884edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 189984edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 190084edbeeab67c1575067335179513150115da367bArun Murthy * 190184edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 190284edbeeab67c1575067335179513150115da367bArun Murthy */ 190384edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di) 190484edbeeab67c1575067335179513150115da367bArun Murthy{ 190584edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 190684edbeeab67c1575067335179513150115da367bArun Murthy 190784edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Main charger plugged\n"); 190884edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->ac_work); 190984edbeeab67c1575067335179513150115da367bArun Murthy 191084edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 191184edbeeab67c1575067335179513150115da367bArun Murthy} 191284edbeeab67c1575067335179513150115da367bArun Murthy 191384edbeeab67c1575067335179513150115da367bArun Murthy/** 191484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainextchnotok_handler() - main charger not ok 191584edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 191684edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 191784edbeeab67c1575067335179513150115da367bArun Murthy * 191884edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 191984edbeeab67c1575067335179513150115da367bArun Murthy */ 192084edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di) 192184edbeeab67c1575067335179513150115da367bArun Murthy{ 192284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 192384edbeeab67c1575067335179513150115da367bArun Murthy 192484edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Main charger not ok\n"); 192584edbeeab67c1575067335179513150115da367bArun Murthy di->flags.mainextchnotok = true; 192684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 192784edbeeab67c1575067335179513150115da367bArun Murthy 192884edbeeab67c1575067335179513150115da367bArun Murthy /* Schedule a new HW failure check */ 192984edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); 193084edbeeab67c1575067335179513150115da367bArun Murthy 193184edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 193284edbeeab67c1575067335179513150115da367bArun Murthy} 193384edbeeab67c1575067335179513150115da367bArun Murthy 193484edbeeab67c1575067335179513150115da367bArun Murthy/** 193584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger 193684edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 193784edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 193884edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 193984edbeeab67c1575067335179513150115da367bArun Murthy * 194084edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 194184edbeeab67c1575067335179513150115da367bArun Murthy */ 194284edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di) 194384edbeeab67c1575067335179513150115da367bArun Murthy{ 194484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 194584edbeeab67c1575067335179513150115da367bArun Murthy 194684edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 194784edbeeab67c1575067335179513150115da367bArun Murthy "Die temp above Main charger thermal protection threshold\n"); 194884edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_main_thermal_prot_work); 194984edbeeab67c1575067335179513150115da367bArun Murthy 195084edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 195184edbeeab67c1575067335179513150115da367bArun Murthy} 195284edbeeab67c1575067335179513150115da367bArun Murthy 195384edbeeab67c1575067335179513150115da367bArun Murthy/** 195484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger 195584edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 195684edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 195784edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 195884edbeeab67c1575067335179513150115da367bArun Murthy * 195984edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 196084edbeeab67c1575067335179513150115da367bArun Murthy */ 196184edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di) 196284edbeeab67c1575067335179513150115da367bArun Murthy{ 196384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 196484edbeeab67c1575067335179513150115da367bArun Murthy 196584edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 196684edbeeab67c1575067335179513150115da367bArun Murthy "Die temp ok for Main charger thermal protection threshold\n"); 196784edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_main_thermal_prot_work); 196884edbeeab67c1575067335179513150115da367bArun Murthy 196984edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 197084edbeeab67c1575067335179513150115da367bArun Murthy} 197184edbeeab67c1575067335179513150115da367bArun Murthy 197284edbeeab67c1575067335179513150115da367bArun Murthy/** 197384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusdetf_handler() - VBUS falling detected 197484edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 197584edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 197684edbeeab67c1575067335179513150115da367bArun Murthy * 197784edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 197884edbeeab67c1575067335179513150115da367bArun Murthy */ 197984edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di) 198084edbeeab67c1575067335179513150115da367bArun Murthy{ 198184edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 198284edbeeab67c1575067335179513150115da367bArun Murthy 198384edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "VBUS falling detected\n"); 198484edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->detect_usb_type_work); 198584edbeeab67c1575067335179513150115da367bArun Murthy 198684edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 198784edbeeab67c1575067335179513150115da367bArun Murthy} 198884edbeeab67c1575067335179513150115da367bArun Murthy 198984edbeeab67c1575067335179513150115da367bArun Murthy/** 199084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusdetr_handler() - VBUS rising detected 199184edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 199284edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 199384edbeeab67c1575067335179513150115da367bArun Murthy * 199484edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 199584edbeeab67c1575067335179513150115da367bArun Murthy */ 199684edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di) 199784edbeeab67c1575067335179513150115da367bArun Murthy{ 199884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 199984edbeeab67c1575067335179513150115da367bArun Murthy 200084edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = true; 200184edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "VBUS rising detected\n"); 200284edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->detect_usb_type_work); 200384edbeeab67c1575067335179513150115da367bArun Murthy 200484edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 200584edbeeab67c1575067335179513150115da367bArun Murthy} 200684edbeeab67c1575067335179513150115da367bArun Murthy 200784edbeeab67c1575067335179513150115da367bArun Murthy/** 200884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usblinkstatus_handler() - USB link status has changed 200984edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 201084edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 201184edbeeab67c1575067335179513150115da367bArun Murthy * 201284edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 201384edbeeab67c1575067335179513150115da367bArun Murthy */ 201484edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di) 201584edbeeab67c1575067335179513150115da367bArun Murthy{ 201684edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 201784edbeeab67c1575067335179513150115da367bArun Murthy 201884edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "USB link status changed\n"); 201984edbeeab67c1575067335179513150115da367bArun Murthy 202084edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->usb_link_status_work); 202184edbeeab67c1575067335179513150115da367bArun Murthy 202284edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 202384edbeeab67c1575067335179513150115da367bArun Murthy} 202484edbeeab67c1575067335179513150115da367bArun Murthy 202584edbeeab67c1575067335179513150115da367bArun Murthy/** 202684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger 202784edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 202884edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 202984edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 203084edbeeab67c1575067335179513150115da367bArun Murthy * 203184edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 203284edbeeab67c1575067335179513150115da367bArun Murthy */ 203384edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di) 203484edbeeab67c1575067335179513150115da367bArun Murthy{ 203584edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 203684edbeeab67c1575067335179513150115da367bArun Murthy 203784edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 203884edbeeab67c1575067335179513150115da367bArun Murthy "Die temp above USB charger thermal protection threshold\n"); 203984edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); 204084edbeeab67c1575067335179513150115da367bArun Murthy 204184edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 204284edbeeab67c1575067335179513150115da367bArun Murthy} 204384edbeeab67c1575067335179513150115da367bArun Murthy 204484edbeeab67c1575067335179513150115da367bArun Murthy/** 204584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger 204684edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold 204784edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 204884edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 204984edbeeab67c1575067335179513150115da367bArun Murthy * 205084edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 205184edbeeab67c1575067335179513150115da367bArun Murthy */ 205284edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di) 205384edbeeab67c1575067335179513150115da367bArun Murthy{ 205484edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 205584edbeeab67c1575067335179513150115da367bArun Murthy 205684edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, 205784edbeeab67c1575067335179513150115da367bArun Murthy "Die temp ok for USB charger thermal protection threshold\n"); 205884edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->check_usb_thermal_prot_work); 205984edbeeab67c1575067335179513150115da367bArun Murthy 206084edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 206184edbeeab67c1575067335179513150115da367bArun Murthy} 206284edbeeab67c1575067335179513150115da367bArun Murthy 206384edbeeab67c1575067335179513150115da367bArun Murthy/** 206484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected 206584edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 206684edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 206784edbeeab67c1575067335179513150115da367bArun Murthy * 206884edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 206984edbeeab67c1575067335179513150115da367bArun Murthy */ 207084edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di) 207184edbeeab67c1575067335179513150115da367bArun Murthy{ 207284edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 207384edbeeab67c1575067335179513150115da367bArun Murthy 207484edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Not allowed USB charger detected\n"); 207584edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0); 207684edbeeab67c1575067335179513150115da367bArun Murthy 207784edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 207884edbeeab67c1575067335179513150115da367bArun Murthy} 207984edbeeab67c1575067335179513150115da367bArun Murthy 208084edbeeab67c1575067335179513150115da367bArun Murthy/** 208184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_chwdexp_handler() - Charger watchdog expired 208284edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 208384edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 208484edbeeab67c1575067335179513150115da367bArun Murthy * 208584edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 208684edbeeab67c1575067335179513150115da367bArun Murthy */ 208784edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di) 208884edbeeab67c1575067335179513150115da367bArun Murthy{ 208984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 209084edbeeab67c1575067335179513150115da367bArun Murthy 209184edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Charger watchdog expired\n"); 209284edbeeab67c1575067335179513150115da367bArun Murthy 209384edbeeab67c1575067335179513150115da367bArun Murthy /* 209484edbeeab67c1575067335179513150115da367bArun Murthy * The charger that was online when the watchdog expired 209584edbeeab67c1575067335179513150115da367bArun Murthy * needs to be restarted for charging to start again 209684edbeeab67c1575067335179513150115da367bArun Murthy */ 209784edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac.charger_online) { 209884edbeeab67c1575067335179513150115da367bArun Murthy di->ac.wd_expired = true; 209984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 210084edbeeab67c1575067335179513150115da367bArun Murthy } 210184edbeeab67c1575067335179513150115da367bArun Murthy if (di->usb.charger_online) { 210284edbeeab67c1575067335179513150115da367bArun Murthy di->usb.wd_expired = true; 210384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 210484edbeeab67c1575067335179513150115da367bArun Murthy } 210584edbeeab67c1575067335179513150115da367bArun Murthy 210684edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 210784edbeeab67c1575067335179513150115da367bArun Murthy} 210884edbeeab67c1575067335179513150115da367bArun Murthy 210984edbeeab67c1575067335179513150115da367bArun Murthy/** 211084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected 211184edbeeab67c1575067335179513150115da367bArun Murthy * @irq: interrupt number 211284edbeeab67c1575067335179513150115da367bArun Murthy * @_di: pointer to the ab8500_charger structure 211384edbeeab67c1575067335179513150115da367bArun Murthy * 211484edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED) 211584edbeeab67c1575067335179513150115da367bArun Murthy */ 211684edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di) 211784edbeeab67c1575067335179513150115da367bArun Murthy{ 211884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = _di; 211984edbeeab67c1575067335179513150115da367bArun Murthy 212084edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "VBUS overvoltage detected\n"); 212184edbeeab67c1575067335179513150115da367bArun Murthy di->flags.vbus_ovv = true; 212284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->usb_chg.psy); 212384edbeeab67c1575067335179513150115da367bArun Murthy 212484edbeeab67c1575067335179513150115da367bArun Murthy /* Schedule a new HW failure check */ 212584edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0); 212684edbeeab67c1575067335179513150115da367bArun Murthy 212784edbeeab67c1575067335179513150115da367bArun Murthy return IRQ_HANDLED; 212884edbeeab67c1575067335179513150115da367bArun Murthy} 212984edbeeab67c1575067335179513150115da367bArun Murthy 213084edbeeab67c1575067335179513150115da367bArun Murthy/** 213184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_get_property() - get the ac/mains properties 213284edbeeab67c1575067335179513150115da367bArun Murthy * @psy: pointer to the power_supply structure 213384edbeeab67c1575067335179513150115da367bArun Murthy * @psp: pointer to the power_supply_property structure 213484edbeeab67c1575067335179513150115da367bArun Murthy * @val: pointer to the power_supply_propval union 213584edbeeab67c1575067335179513150115da367bArun Murthy * 213684edbeeab67c1575067335179513150115da367bArun Murthy * This function gets called when an application tries to get the ac/mains 213784edbeeab67c1575067335179513150115da367bArun Murthy * properties by reading the sysfs files. 213884edbeeab67c1575067335179513150115da367bArun Murthy * AC/Mains properties are online, present and voltage. 213984edbeeab67c1575067335179513150115da367bArun Murthy * online: ac/mains charging is in progress or not 214084edbeeab67c1575067335179513150115da367bArun Murthy * present: presence of the ac/mains 214184edbeeab67c1575067335179513150115da367bArun Murthy * voltage: AC/Mains voltage 214284edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 214384edbeeab67c1575067335179513150115da367bArun Murthy */ 214484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_get_property(struct power_supply *psy, 214584edbeeab67c1575067335179513150115da367bArun Murthy enum power_supply_property psp, 214684edbeeab67c1575067335179513150115da367bArun Murthy union power_supply_propval *val) 214784edbeeab67c1575067335179513150115da367bArun Murthy{ 214884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 214984edbeeab67c1575067335179513150115da367bArun Murthy 215084edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy)); 215184edbeeab67c1575067335179513150115da367bArun Murthy 215284edbeeab67c1575067335179513150115da367bArun Murthy switch (psp) { 215384edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_HEALTH: 215484edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok) 215584edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 215684edbeeab67c1575067335179513150115da367bArun Murthy else if (di->ac.wd_expired || di->usb.wd_expired) 215784edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_DEAD; 215884edbeeab67c1575067335179513150115da367bArun Murthy else if (di->flags.main_thermal_prot) 215984edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 216084edbeeab67c1575067335179513150115da367bArun Murthy else 216184edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_GOOD; 216284edbeeab67c1575067335179513150115da367bArun Murthy break; 216384edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_ONLINE: 216484edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.charger_online; 216584edbeeab67c1575067335179513150115da367bArun Murthy break; 216684edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_PRESENT: 216784edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.charger_connected; 216884edbeeab67c1575067335179513150115da367bArun Murthy break; 216984edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_NOW: 217084edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_voltage = ab8500_charger_get_ac_voltage(di); 217184edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.charger_voltage * 1000; 217284edbeeab67c1575067335179513150115da367bArun Murthy break; 217384edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_AVG: 217484edbeeab67c1575067335179513150115da367bArun Murthy /* 217584edbeeab67c1575067335179513150115da367bArun Murthy * This property is used to indicate when CV mode is entered 217684edbeeab67c1575067335179513150115da367bArun Murthy * for the AC charger 217784edbeeab67c1575067335179513150115da367bArun Murthy */ 217884edbeeab67c1575067335179513150115da367bArun Murthy di->ac.cv_active = ab8500_charger_ac_cv(di); 217984edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->ac.cv_active; 218084edbeeab67c1575067335179513150115da367bArun Murthy break; 218184edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_CURRENT_NOW: 218284edbeeab67c1575067335179513150115da367bArun Murthy val->intval = ab8500_charger_get_ac_current(di) * 1000; 218384edbeeab67c1575067335179513150115da367bArun Murthy break; 218484edbeeab67c1575067335179513150115da367bArun Murthy default: 218584edbeeab67c1575067335179513150115da367bArun Murthy return -EINVAL; 218684edbeeab67c1575067335179513150115da367bArun Murthy } 218784edbeeab67c1575067335179513150115da367bArun Murthy return 0; 218884edbeeab67c1575067335179513150115da367bArun Murthy} 218984edbeeab67c1575067335179513150115da367bArun Murthy 219084edbeeab67c1575067335179513150115da367bArun Murthy/** 219184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_get_property() - get the usb properties 219284edbeeab67c1575067335179513150115da367bArun Murthy * @psy: pointer to the power_supply structure 219384edbeeab67c1575067335179513150115da367bArun Murthy * @psp: pointer to the power_supply_property structure 219484edbeeab67c1575067335179513150115da367bArun Murthy * @val: pointer to the power_supply_propval union 219584edbeeab67c1575067335179513150115da367bArun Murthy * 219684edbeeab67c1575067335179513150115da367bArun Murthy * This function gets called when an application tries to get the usb 219784edbeeab67c1575067335179513150115da367bArun Murthy * properties by reading the sysfs files. 219884edbeeab67c1575067335179513150115da367bArun Murthy * USB properties are online, present and voltage. 219984edbeeab67c1575067335179513150115da367bArun Murthy * online: usb charging is in progress or not 220084edbeeab67c1575067335179513150115da367bArun Murthy * present: presence of the usb 220184edbeeab67c1575067335179513150115da367bArun Murthy * voltage: vbus voltage 220284edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success) 220384edbeeab67c1575067335179513150115da367bArun Murthy */ 220484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_get_property(struct power_supply *psy, 220584edbeeab67c1575067335179513150115da367bArun Murthy enum power_supply_property psp, 220684edbeeab67c1575067335179513150115da367bArun Murthy union power_supply_propval *val) 220784edbeeab67c1575067335179513150115da367bArun Murthy{ 220884edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di; 220984edbeeab67c1575067335179513150115da367bArun Murthy 221084edbeeab67c1575067335179513150115da367bArun Murthy di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy)); 221184edbeeab67c1575067335179513150115da367bArun Murthy 221284edbeeab67c1575067335179513150115da367bArun Murthy switch (psp) { 221384edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_HEALTH: 221484edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.usbchargernotok) 221584edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 221684edbeeab67c1575067335179513150115da367bArun Murthy else if (di->ac.wd_expired || di->usb.wd_expired) 221784edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_DEAD; 221884edbeeab67c1575067335179513150115da367bArun Murthy else if (di->flags.usb_thermal_prot) 221984edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 222084edbeeab67c1575067335179513150115da367bArun Murthy else if (di->flags.vbus_ovv) 222184edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 222284edbeeab67c1575067335179513150115da367bArun Murthy else 222384edbeeab67c1575067335179513150115da367bArun Murthy val->intval = POWER_SUPPLY_HEALTH_GOOD; 222484edbeeab67c1575067335179513150115da367bArun Murthy break; 222584edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_ONLINE: 222684edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.charger_online; 222784edbeeab67c1575067335179513150115da367bArun Murthy break; 222884edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_PRESENT: 222984edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.charger_connected; 223084edbeeab67c1575067335179513150115da367bArun Murthy break; 223184edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_NOW: 223284edbeeab67c1575067335179513150115da367bArun Murthy di->usb.charger_voltage = ab8500_charger_get_vbus_voltage(di); 223384edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.charger_voltage * 1000; 223484edbeeab67c1575067335179513150115da367bArun Murthy break; 223584edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_VOLTAGE_AVG: 223684edbeeab67c1575067335179513150115da367bArun Murthy /* 223784edbeeab67c1575067335179513150115da367bArun Murthy * This property is used to indicate when CV mode is entered 223884edbeeab67c1575067335179513150115da367bArun Murthy * for the USB charger 223984edbeeab67c1575067335179513150115da367bArun Murthy */ 224084edbeeab67c1575067335179513150115da367bArun Murthy di->usb.cv_active = ab8500_charger_usb_cv(di); 224184edbeeab67c1575067335179513150115da367bArun Murthy val->intval = di->usb.cv_active; 224284edbeeab67c1575067335179513150115da367bArun Murthy break; 224384edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_CURRENT_NOW: 224484edbeeab67c1575067335179513150115da367bArun Murthy val->intval = ab8500_charger_get_usb_current(di) * 1000; 224584edbeeab67c1575067335179513150115da367bArun Murthy break; 224684edbeeab67c1575067335179513150115da367bArun Murthy case POWER_SUPPLY_PROP_CURRENT_AVG: 224784edbeeab67c1575067335179513150115da367bArun Murthy /* 224884edbeeab67c1575067335179513150115da367bArun Murthy * This property is used to indicate when VBUS has collapsed 224984edbeeab67c1575067335179513150115da367bArun Murthy * due to too high output current from the USB charger 225084edbeeab67c1575067335179513150115da367bArun Murthy */ 225184edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.vbus_collapse) 225284edbeeab67c1575067335179513150115da367bArun Murthy val->intval = 1; 225384edbeeab67c1575067335179513150115da367bArun Murthy else 225484edbeeab67c1575067335179513150115da367bArun Murthy val->intval = 0; 225584edbeeab67c1575067335179513150115da367bArun Murthy break; 225684edbeeab67c1575067335179513150115da367bArun Murthy default: 225784edbeeab67c1575067335179513150115da367bArun Murthy return -EINVAL; 225884edbeeab67c1575067335179513150115da367bArun Murthy } 225984edbeeab67c1575067335179513150115da367bArun Murthy return 0; 226084edbeeab67c1575067335179513150115da367bArun Murthy} 226184edbeeab67c1575067335179513150115da367bArun Murthy 226284edbeeab67c1575067335179513150115da367bArun Murthy/** 226384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_init_hw_registers() - Set up charger related registers 226484edbeeab67c1575067335179513150115da367bArun Murthy * @di: pointer to the ab8500_charger structure 226584edbeeab67c1575067335179513150115da367bArun Murthy * 226684edbeeab67c1575067335179513150115da367bArun Murthy * Set up charger OVV, watchdog and maximum voltage registers as well as 226784edbeeab67c1575067335179513150115da367bArun Murthy * charging of the backup battery 226884edbeeab67c1575067335179513150115da367bArun Murthy */ 226984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_init_hw_registers(struct ab8500_charger *di) 227084edbeeab67c1575067335179513150115da367bArun Murthy{ 227184edbeeab67c1575067335179513150115da367bArun Murthy int ret = 0; 227284edbeeab67c1575067335179513150115da367bArun Murthy 227384edbeeab67c1575067335179513150115da367bArun Murthy /* Setup maximum charger current and voltage for ABB cut2.0 */ 227484edbeeab67c1575067335179513150115da367bArun Murthy if (!is_ab8500_1p1_or_earlier(di->parent)) { 227584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 227684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 227784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6); 227884edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 227984edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 228084edbeeab67c1575067335179513150115da367bArun Murthy "failed to set CH_VOLT_LVL_MAX_REG\n"); 228184edbeeab67c1575067335179513150115da367bArun Murthy goto out; 228284edbeeab67c1575067335179513150115da367bArun Murthy } 228384edbeeab67c1575067335179513150115da367bArun Murthy 228484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 228584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 228684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_OPT_CRNTLVL_MAX_REG, CH_OP_CUR_LVL_1P6); 228784edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 228884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, 228984edbeeab67c1575067335179513150115da367bArun Murthy "failed to set CH_OPT_CRNTLVL_MAX_REG\n"); 229084edbeeab67c1575067335179513150115da367bArun Murthy goto out; 229184edbeeab67c1575067335179513150115da367bArun Murthy } 229284edbeeab67c1575067335179513150115da367bArun Murthy } 229384edbeeab67c1575067335179513150115da367bArun Murthy 229484edbeeab67c1575067335179513150115da367bArun Murthy /* VBUS OVV set to 6.3V and enable automatic current limitiation */ 229584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 229684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARGER, 229784edbeeab67c1575067335179513150115da367bArun Murthy AB8500_USBCH_CTRL2_REG, 229884edbeeab67c1575067335179513150115da367bArun Murthy VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA); 229984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 230084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to set VBUS OVV\n"); 230184edbeeab67c1575067335179513150115da367bArun Murthy goto out; 230284edbeeab67c1575067335179513150115da367bArun Murthy } 230384edbeeab67c1575067335179513150115da367bArun Murthy 230484edbeeab67c1575067335179513150115da367bArun Murthy /* Enable main watchdog in OTP */ 230584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 230684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD); 230784edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 230884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to enable main WD in OTP\n"); 230984edbeeab67c1575067335179513150115da367bArun Murthy goto out; 231084edbeeab67c1575067335179513150115da367bArun Murthy } 231184edbeeab67c1575067335179513150115da367bArun Murthy 231284edbeeab67c1575067335179513150115da367bArun Murthy /* Enable main watchdog */ 231384edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 231484edbeeab67c1575067335179513150115da367bArun Murthy AB8500_SYS_CTRL2_BLOCK, 231584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA); 231684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 231784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "faile to enable main watchdog\n"); 231884edbeeab67c1575067335179513150115da367bArun Murthy goto out; 231984edbeeab67c1575067335179513150115da367bArun Murthy } 232084edbeeab67c1575067335179513150115da367bArun Murthy 232184edbeeab67c1575067335179513150115da367bArun Murthy /* 232284edbeeab67c1575067335179513150115da367bArun Murthy * Due to internal synchronisation, Enable and Kick watchdog bits 232384edbeeab67c1575067335179513150115da367bArun Murthy * cannot be enabled in a single write. 232484edbeeab67c1575067335179513150115da367bArun Murthy * A minimum delay of 2*32 kHz period (62.5µs) must be inserted 232584edbeeab67c1575067335179513150115da367bArun Murthy * between writing Enable then Kick bits. 232684edbeeab67c1575067335179513150115da367bArun Murthy */ 232784edbeeab67c1575067335179513150115da367bArun Murthy udelay(63); 232884edbeeab67c1575067335179513150115da367bArun Murthy 232984edbeeab67c1575067335179513150115da367bArun Murthy /* Kick main watchdog */ 233084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 233184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_SYS_CTRL2_BLOCK, 233284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MAIN_WDOG_CTRL_REG, 233384edbeeab67c1575067335179513150115da367bArun Murthy (MAIN_WDOG_ENA | MAIN_WDOG_KICK)); 233484edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 233584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to kick main watchdog\n"); 233684edbeeab67c1575067335179513150115da367bArun Murthy goto out; 233784edbeeab67c1575067335179513150115da367bArun Murthy } 233884edbeeab67c1575067335179513150115da367bArun Murthy 233984edbeeab67c1575067335179513150115da367bArun Murthy /* Disable main watchdog */ 234084edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 234184edbeeab67c1575067335179513150115da367bArun Murthy AB8500_SYS_CTRL2_BLOCK, 234284edbeeab67c1575067335179513150115da367bArun Murthy AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS); 234384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 234484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to disable main watchdog\n"); 234584edbeeab67c1575067335179513150115da367bArun Murthy goto out; 234684edbeeab67c1575067335179513150115da367bArun Murthy } 234784edbeeab67c1575067335179513150115da367bArun Murthy 234884edbeeab67c1575067335179513150115da367bArun Murthy /* Set watchdog timeout */ 234984edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 235084edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CH_WD_TIMER_REG, WD_TIMER); 235184edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 235284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to set charger watchdog timeout\n"); 235384edbeeab67c1575067335179513150115da367bArun Murthy goto out; 235484edbeeab67c1575067335179513150115da367bArun Murthy } 235584edbeeab67c1575067335179513150115da367bArun Murthy 235684edbeeab67c1575067335179513150115da367bArun Murthy /* Backup battery voltage and current */ 235784edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, 235884edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC, 235984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC_BACKUP_CHG_REG, 236084edbeeab67c1575067335179513150115da367bArun Murthy di->bat->bkup_bat_v | 236184edbeeab67c1575067335179513150115da367bArun Murthy di->bat->bkup_bat_i); 236284edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 236384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to setup backup battery charging\n"); 236484edbeeab67c1575067335179513150115da367bArun Murthy goto out; 236584edbeeab67c1575067335179513150115da367bArun Murthy } 236684edbeeab67c1575067335179513150115da367bArun Murthy 236784edbeeab67c1575067335179513150115da367bArun Murthy /* Enable backup battery charging */ 236884edbeeab67c1575067335179513150115da367bArun Murthy abx500_mask_and_set_register_interruptible(di->dev, 236984edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC, AB8500_RTC_CTRL_REG, 237084edbeeab67c1575067335179513150115da367bArun Murthy RTC_BUP_CH_ENA, RTC_BUP_CH_ENA); 237184edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 237284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s mask and set failed\n", __func__); 237384edbeeab67c1575067335179513150115da367bArun Murthy 237484edbeeab67c1575067335179513150115da367bArun Murthyout: 237584edbeeab67c1575067335179513150115da367bArun Murthy return ret; 237684edbeeab67c1575067335179513150115da367bArun Murthy} 237784edbeeab67c1575067335179513150115da367bArun Murthy 237884edbeeab67c1575067335179513150115da367bArun Murthy/* 237984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500 charger driver interrupts and their respective isr 238084edbeeab67c1575067335179513150115da367bArun Murthy */ 238184edbeeab67c1575067335179513150115da367bArun Murthystatic struct ab8500_charger_interrupts ab8500_charger_irq[] = { 238284edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler}, 238384edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler}, 238484edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler}, 238584edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler}, 238684edbeeab67c1575067335179513150115da367bArun Murthy {"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler}, 238784edbeeab67c1575067335179513150115da367bArun Murthy {"VBUS_DET_F", ab8500_charger_vbusdetf_handler}, 238884edbeeab67c1575067335179513150115da367bArun Murthy {"VBUS_DET_R", ab8500_charger_vbusdetr_handler}, 238984edbeeab67c1575067335179513150115da367bArun Murthy {"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler}, 239084edbeeab67c1575067335179513150115da367bArun Murthy {"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler}, 239184edbeeab67c1575067335179513150115da367bArun Murthy {"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler}, 239284edbeeab67c1575067335179513150115da367bArun Murthy {"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler}, 239384edbeeab67c1575067335179513150115da367bArun Murthy {"VBUS_OVV", ab8500_charger_vbusovv_handler}, 239484edbeeab67c1575067335179513150115da367bArun Murthy {"CH_WD_EXP", ab8500_charger_chwdexp_handler}, 239584edbeeab67c1575067335179513150115da367bArun Murthy}; 239684edbeeab67c1575067335179513150115da367bArun Murthy 239784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_notifier_call(struct notifier_block *nb, 239884edbeeab67c1575067335179513150115da367bArun Murthy unsigned long event, void *power) 239984edbeeab67c1575067335179513150115da367bArun Murthy{ 240084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = 240184edbeeab67c1575067335179513150115da367bArun Murthy container_of(nb, struct ab8500_charger, nb); 240284edbeeab67c1575067335179513150115da367bArun Murthy enum ab8500_usb_state bm_usb_state; 240384edbeeab67c1575067335179513150115da367bArun Murthy unsigned mA = *((unsigned *)power); 240484edbeeab67c1575067335179513150115da367bArun Murthy 240584edbeeab67c1575067335179513150115da367bArun Murthy if (event != USB_EVENT_VBUS) { 240684edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "not a standard host, returning\n"); 240784edbeeab67c1575067335179513150115da367bArun Murthy return NOTIFY_DONE; 240884edbeeab67c1575067335179513150115da367bArun Murthy } 240984edbeeab67c1575067335179513150115da367bArun Murthy 241084edbeeab67c1575067335179513150115da367bArun Murthy /* TODO: State is fabricate here. See if charger really needs USB 241184edbeeab67c1575067335179513150115da367bArun Murthy * state or if mA is enough 241284edbeeab67c1575067335179513150115da367bArun Murthy */ 241384edbeeab67c1575067335179513150115da367bArun Murthy if ((di->usb_state.usb_current == 2) && (mA > 2)) 241484edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_RESUME; 241584edbeeab67c1575067335179513150115da367bArun Murthy else if (mA == 0) 241684edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_RESET_HS; 241784edbeeab67c1575067335179513150115da367bArun Murthy else if (mA == 2) 241884edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_SUSPEND; 241984edbeeab67c1575067335179513150115da367bArun Murthy else if (mA >= 8) /* 8, 100, 500 */ 242084edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED; 242184edbeeab67c1575067335179513150115da367bArun Murthy else /* Should never occur */ 242284edbeeab67c1575067335179513150115da367bArun Murthy bm_usb_state = AB8500_BM_USB_STATE_RESET_FS; 242384edbeeab67c1575067335179513150115da367bArun Murthy 242484edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n", 242584edbeeab67c1575067335179513150115da367bArun Murthy __func__, bm_usb_state, mA); 242684edbeeab67c1575067335179513150115da367bArun Murthy 242784edbeeab67c1575067335179513150115da367bArun Murthy spin_lock(&di->usb_state.usb_lock); 242884edbeeab67c1575067335179513150115da367bArun Murthy di->usb_state.usb_changed = true; 242984edbeeab67c1575067335179513150115da367bArun Murthy spin_unlock(&di->usb_state.usb_lock); 243084edbeeab67c1575067335179513150115da367bArun Murthy 243184edbeeab67c1575067335179513150115da367bArun Murthy di->usb_state.state = bm_usb_state; 243284edbeeab67c1575067335179513150115da367bArun Murthy di->usb_state.usb_current = mA; 243384edbeeab67c1575067335179513150115da367bArun Murthy 243484edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, &di->usb_state_changed_work); 243584edbeeab67c1575067335179513150115da367bArun Murthy 243684edbeeab67c1575067335179513150115da367bArun Murthy return NOTIFY_OK; 243784edbeeab67c1575067335179513150115da367bArun Murthy} 243884edbeeab67c1575067335179513150115da367bArun Murthy 243984edbeeab67c1575067335179513150115da367bArun Murthy#if defined(CONFIG_PM) 244084edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_resume(struct platform_device *pdev) 244184edbeeab67c1575067335179513150115da367bArun Murthy{ 244284edbeeab67c1575067335179513150115da367bArun Murthy int ret; 244384edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = platform_get_drvdata(pdev); 244484edbeeab67c1575067335179513150115da367bArun Murthy 244584edbeeab67c1575067335179513150115da367bArun Murthy /* 244684edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 244784edbeeab67c1575067335179513150115da367bArun Murthy * logic. That means we have to continously kick the charger 244884edbeeab67c1575067335179513150115da367bArun Murthy * watchdog even when no charger is connected. This is only 244984edbeeab67c1575067335179513150115da367bArun Murthy * valid once the AC charger has been enabled. This is 245084edbeeab67c1575067335179513150115da367bArun Murthy * a bug that is not handled by the algorithm and the 245184edbeeab67c1575067335179513150115da367bArun Murthy * watchdog have to be kicked by the charger driver 245284edbeeab67c1575067335179513150115da367bArun Murthy * when the AC charger is disabled 245384edbeeab67c1575067335179513150115da367bArun Murthy */ 245484edbeeab67c1575067335179513150115da367bArun Murthy if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) { 245584edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, 245684edbeeab67c1575067335179513150115da367bArun Murthy AB8500_CHARG_WD_CTRL, CHARG_WD_KICK); 245784edbeeab67c1575067335179513150115da367bArun Murthy if (ret) 245884edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "Failed to kick WD!\n"); 245984edbeeab67c1575067335179513150115da367bArun Murthy 246084edbeeab67c1575067335179513150115da367bArun Murthy /* If not already pending start a new timer */ 246184edbeeab67c1575067335179513150115da367bArun Murthy if (!delayed_work_pending( 246284edbeeab67c1575067335179513150115da367bArun Murthy &di->kick_wd_work)) { 246384edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, &di->kick_wd_work, 246484edbeeab67c1575067335179513150115da367bArun Murthy round_jiffies(WD_KICK_INTERVAL)); 246584edbeeab67c1575067335179513150115da367bArun Murthy } 246684edbeeab67c1575067335179513150115da367bArun Murthy } 246784edbeeab67c1575067335179513150115da367bArun Murthy 246884edbeeab67c1575067335179513150115da367bArun Murthy /* If we still have a HW failure, schedule a new check */ 246984edbeeab67c1575067335179513150115da367bArun Murthy if (di->flags.mainextchnotok || di->flags.vbus_ovv) { 247084edbeeab67c1575067335179513150115da367bArun Murthy queue_delayed_work(di->charger_wq, 247184edbeeab67c1575067335179513150115da367bArun Murthy &di->check_hw_failure_work, 0); 247284edbeeab67c1575067335179513150115da367bArun Murthy } 247384edbeeab67c1575067335179513150115da367bArun Murthy 247484edbeeab67c1575067335179513150115da367bArun Murthy return 0; 247584edbeeab67c1575067335179513150115da367bArun Murthy} 247684edbeeab67c1575067335179513150115da367bArun Murthy 247784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_suspend(struct platform_device *pdev, 247884edbeeab67c1575067335179513150115da367bArun Murthy pm_message_t state) 247984edbeeab67c1575067335179513150115da367bArun Murthy{ 248084edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = platform_get_drvdata(pdev); 248184edbeeab67c1575067335179513150115da367bArun Murthy 248284edbeeab67c1575067335179513150115da367bArun Murthy /* Cancel any pending HW failure check */ 248384edbeeab67c1575067335179513150115da367bArun Murthy if (delayed_work_pending(&di->check_hw_failure_work)) 248484edbeeab67c1575067335179513150115da367bArun Murthy cancel_delayed_work(&di->check_hw_failure_work); 248584edbeeab67c1575067335179513150115da367bArun Murthy 248684edbeeab67c1575067335179513150115da367bArun Murthy return 0; 248784edbeeab67c1575067335179513150115da367bArun Murthy} 248884edbeeab67c1575067335179513150115da367bArun Murthy#else 248984edbeeab67c1575067335179513150115da367bArun Murthy#define ab8500_charger_suspend NULL 249084edbeeab67c1575067335179513150115da367bArun Murthy#define ab8500_charger_resume NULL 249184edbeeab67c1575067335179513150115da367bArun Murthy#endif 249284edbeeab67c1575067335179513150115da367bArun Murthy 249384edbeeab67c1575067335179513150115da367bArun Murthystatic int __devexit ab8500_charger_remove(struct platform_device *pdev) 249484edbeeab67c1575067335179513150115da367bArun Murthy{ 249584edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = platform_get_drvdata(pdev); 249684edbeeab67c1575067335179513150115da367bArun Murthy int i, irq, ret; 249784edbeeab67c1575067335179513150115da367bArun Murthy 249884edbeeab67c1575067335179513150115da367bArun Murthy /* Disable AC charging */ 249984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); 250084edbeeab67c1575067335179513150115da367bArun Murthy 250184edbeeab67c1575067335179513150115da367bArun Murthy /* Disable USB charging */ 250284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); 250384edbeeab67c1575067335179513150115da367bArun Murthy 250484edbeeab67c1575067335179513150115da367bArun Murthy /* Disable interrupts */ 250584edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 250684edbeeab67c1575067335179513150115da367bArun Murthy irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 250784edbeeab67c1575067335179513150115da367bArun Murthy free_irq(irq, di); 250884edbeeab67c1575067335179513150115da367bArun Murthy } 250984edbeeab67c1575067335179513150115da367bArun Murthy 251084edbeeab67c1575067335179513150115da367bArun Murthy /* disable the regulator */ 251184edbeeab67c1575067335179513150115da367bArun Murthy regulator_put(di->regu); 251284edbeeab67c1575067335179513150115da367bArun Murthy 251384edbeeab67c1575067335179513150115da367bArun Murthy /* Backup battery voltage and current disable */ 251484edbeeab67c1575067335179513150115da367bArun Murthy ret = abx500_mask_and_set_register_interruptible(di->dev, 251584edbeeab67c1575067335179513150115da367bArun Murthy AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); 251684edbeeab67c1575067335179513150115da367bArun Murthy if (ret < 0) 251784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "%s mask and set failed\n", __func__); 251884edbeeab67c1575067335179513150115da367bArun Murthy 2519efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov usb_unregister_notifier(di->usb_phy, &di->nb); 2520efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov usb_put_transceiver(di->usb_phy); 252184edbeeab67c1575067335179513150115da367bArun Murthy 252284edbeeab67c1575067335179513150115da367bArun Murthy /* Delete the work queue */ 252384edbeeab67c1575067335179513150115da367bArun Murthy destroy_workqueue(di->charger_wq); 252484edbeeab67c1575067335179513150115da367bArun Murthy 252584edbeeab67c1575067335179513150115da367bArun Murthy flush_scheduled_work(); 252684edbeeab67c1575067335179513150115da367bArun Murthy power_supply_unregister(&di->usb_chg.psy); 252784edbeeab67c1575067335179513150115da367bArun Murthy power_supply_unregister(&di->ac_chg.psy); 252884edbeeab67c1575067335179513150115da367bArun Murthy platform_set_drvdata(pdev, NULL); 252984edbeeab67c1575067335179513150115da367bArun Murthy kfree(di); 253084edbeeab67c1575067335179513150115da367bArun Murthy 253184edbeeab67c1575067335179513150115da367bArun Murthy return 0; 253284edbeeab67c1575067335179513150115da367bArun Murthy} 253384edbeeab67c1575067335179513150115da367bArun Murthy 253484edbeeab67c1575067335179513150115da367bArun Murthystatic int __devinit ab8500_charger_probe(struct platform_device *pdev) 253584edbeeab67c1575067335179513150115da367bArun Murthy{ 253684edbeeab67c1575067335179513150115da367bArun Murthy int irq, i, charger_status, ret = 0; 253784edbeeab67c1575067335179513150115da367bArun Murthy struct abx500_bm_plat_data *plat_data; 253884edbeeab67c1575067335179513150115da367bArun Murthy 253984edbeeab67c1575067335179513150115da367bArun Murthy struct ab8500_charger *di = 254084edbeeab67c1575067335179513150115da367bArun Murthy kzalloc(sizeof(struct ab8500_charger), GFP_KERNEL); 254184edbeeab67c1575067335179513150115da367bArun Murthy if (!di) 254284edbeeab67c1575067335179513150115da367bArun Murthy return -ENOMEM; 254384edbeeab67c1575067335179513150115da367bArun Murthy 254484edbeeab67c1575067335179513150115da367bArun Murthy /* get parent data */ 254584edbeeab67c1575067335179513150115da367bArun Murthy di->dev = &pdev->dev; 254684edbeeab67c1575067335179513150115da367bArun Murthy di->parent = dev_get_drvdata(pdev->dev.parent); 254784edbeeab67c1575067335179513150115da367bArun Murthy di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); 254884edbeeab67c1575067335179513150115da367bArun Murthy 254984edbeeab67c1575067335179513150115da367bArun Murthy /* initialize lock */ 255084edbeeab67c1575067335179513150115da367bArun Murthy spin_lock_init(&di->usb_state.usb_lock); 255184edbeeab67c1575067335179513150115da367bArun Murthy 255284edbeeab67c1575067335179513150115da367bArun Murthy /* get charger specific platform data */ 255384edbeeab67c1575067335179513150115da367bArun Murthy plat_data = pdev->dev.platform_data; 255484edbeeab67c1575067335179513150115da367bArun Murthy di->pdata = plat_data->charger; 255584edbeeab67c1575067335179513150115da367bArun Murthy 255684edbeeab67c1575067335179513150115da367bArun Murthy if (!di->pdata) { 255784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "no charger platform data supplied\n"); 255884edbeeab67c1575067335179513150115da367bArun Murthy ret = -EINVAL; 255984edbeeab67c1575067335179513150115da367bArun Murthy goto free_device_info; 256084edbeeab67c1575067335179513150115da367bArun Murthy } 256184edbeeab67c1575067335179513150115da367bArun Murthy 256284edbeeab67c1575067335179513150115da367bArun Murthy /* get battery specific platform data */ 256384edbeeab67c1575067335179513150115da367bArun Murthy di->bat = plat_data->battery; 256484edbeeab67c1575067335179513150115da367bArun Murthy if (!di->bat) { 256584edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "no battery platform data supplied\n"); 256684edbeeab67c1575067335179513150115da367bArun Murthy ret = -EINVAL; 256784edbeeab67c1575067335179513150115da367bArun Murthy goto free_device_info; 256884edbeeab67c1575067335179513150115da367bArun Murthy } 256984edbeeab67c1575067335179513150115da367bArun Murthy 257084edbeeab67c1575067335179513150115da367bArun Murthy di->autopower = false; 257184edbeeab67c1575067335179513150115da367bArun Murthy 257284edbeeab67c1575067335179513150115da367bArun Murthy /* AC supply */ 257384edbeeab67c1575067335179513150115da367bArun Murthy /* power_supply base class */ 257484edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.name = "ab8500_ac"; 257584edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS; 257684edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.properties = ab8500_charger_ac_props; 257784edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); 257884edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; 257984edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.supplied_to = di->pdata->supplied_to; 258084edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants; 258184edbeeab67c1575067335179513150115da367bArun Murthy /* ux500_charger sub-class */ 258284edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.ops.enable = &ab8500_charger_ac_en; 258384edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 258484edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current; 258584edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ 258684edbeeab67c1575067335179513150115da367bArun Murthy ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 258784edbeeab67c1575067335179513150115da367bArun Murthy di->ac_chg.max_out_curr = ab8500_charger_current_map[ 258884edbeeab67c1575067335179513150115da367bArun Murthy ARRAY_SIZE(ab8500_charger_current_map) - 1]; 258984edbeeab67c1575067335179513150115da367bArun Murthy 259084edbeeab67c1575067335179513150115da367bArun Murthy /* USB supply */ 259184edbeeab67c1575067335179513150115da367bArun Murthy /* power_supply base class */ 259284edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.name = "ab8500_usb"; 259384edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.type = POWER_SUPPLY_TYPE_USB; 259484edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.properties = ab8500_charger_usb_props; 259584edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); 259684edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; 259784edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.supplied_to = di->pdata->supplied_to; 259884edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants; 259984edbeeab67c1575067335179513150115da367bArun Murthy /* ux500_charger sub-class */ 260084edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.ops.enable = &ab8500_charger_usb_en; 260184edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 260284edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; 260384edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ 260484edbeeab67c1575067335179513150115da367bArun Murthy ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 260584edbeeab67c1575067335179513150115da367bArun Murthy di->usb_chg.max_out_curr = ab8500_charger_current_map[ 260684edbeeab67c1575067335179513150115da367bArun Murthy ARRAY_SIZE(ab8500_charger_current_map) - 1]; 260784edbeeab67c1575067335179513150115da367bArun Murthy 260884edbeeab67c1575067335179513150115da367bArun Murthy 260984edbeeab67c1575067335179513150115da367bArun Murthy /* Create a work queue for the charger */ 261084edbeeab67c1575067335179513150115da367bArun Murthy di->charger_wq = 261184edbeeab67c1575067335179513150115da367bArun Murthy create_singlethread_workqueue("ab8500_charger_wq"); 261284edbeeab67c1575067335179513150115da367bArun Murthy if (di->charger_wq == NULL) { 261384edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to create work queue\n"); 261484edbeeab67c1575067335179513150115da367bArun Murthy goto free_device_info; 261584edbeeab67c1575067335179513150115da367bArun Murthy } 261684edbeeab67c1575067335179513150115da367bArun Murthy 261784edbeeab67c1575067335179513150115da367bArun Murthy /* Init work for HW failure check */ 261884edbeeab67c1575067335179513150115da367bArun Murthy INIT_DELAYED_WORK_DEFERRABLE(&di->check_hw_failure_work, 261984edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_hw_failure_work); 262084edbeeab67c1575067335179513150115da367bArun Murthy INIT_DELAYED_WORK_DEFERRABLE(&di->check_usbchgnotok_work, 262184edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_usbchargernotok_work); 262284edbeeab67c1575067335179513150115da367bArun Murthy 262384edbeeab67c1575067335179513150115da367bArun Murthy /* 262484edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the watchdog 262584edbeeab67c1575067335179513150115da367bArun Murthy * logic. That means we have to continously kick the charger 262684edbeeab67c1575067335179513150115da367bArun Murthy * watchdog even when no charger is connected. This is only 262784edbeeab67c1575067335179513150115da367bArun Murthy * valid once the AC charger has been enabled. This is 262884edbeeab67c1575067335179513150115da367bArun Murthy * a bug that is not handled by the algorithm and the 262984edbeeab67c1575067335179513150115da367bArun Murthy * watchdog have to be kicked by the charger driver 263084edbeeab67c1575067335179513150115da367bArun Murthy * when the AC charger is disabled 263184edbeeab67c1575067335179513150115da367bArun Murthy */ 263284edbeeab67c1575067335179513150115da367bArun Murthy INIT_DELAYED_WORK_DEFERRABLE(&di->kick_wd_work, 263384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_kick_watchdog_work); 263484edbeeab67c1575067335179513150115da367bArun Murthy 263584edbeeab67c1575067335179513150115da367bArun Murthy INIT_DELAYED_WORK_DEFERRABLE(&di->check_vbat_work, 263684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_vbat_work); 263784edbeeab67c1575067335179513150115da367bArun Murthy 263884edbeeab67c1575067335179513150115da367bArun Murthy /* Init work for charger detection */ 263984edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->usb_link_status_work, 264084edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_usb_link_status_work); 264184edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->ac_work, ab8500_charger_ac_work); 264284edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->detect_usb_type_work, 264384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_detect_usb_type_work); 264484edbeeab67c1575067335179513150115da367bArun Murthy 264584edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->usb_state_changed_work, 264684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_usb_state_changed_work); 264784edbeeab67c1575067335179513150115da367bArun Murthy 264884edbeeab67c1575067335179513150115da367bArun Murthy /* Init work for checking HW status */ 264984edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->check_main_thermal_prot_work, 265084edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_main_thermal_prot_work); 265184edbeeab67c1575067335179513150115da367bArun Murthy INIT_WORK(&di->check_usb_thermal_prot_work, 265284edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_check_usb_thermal_prot_work); 265384edbeeab67c1575067335179513150115da367bArun Murthy 265484edbeeab67c1575067335179513150115da367bArun Murthy /* 265584edbeeab67c1575067335179513150115da367bArun Murthy * VDD ADC supply needs to be enabled from this driver when there 265684edbeeab67c1575067335179513150115da367bArun Murthy * is a charger connected to avoid erroneous BTEMP_HIGH/LOW 265784edbeeab67c1575067335179513150115da367bArun Murthy * interrupts during charging 265884edbeeab67c1575067335179513150115da367bArun Murthy */ 265984edbeeab67c1575067335179513150115da367bArun Murthy di->regu = regulator_get(di->dev, "vddadc"); 266084edbeeab67c1575067335179513150115da367bArun Murthy if (IS_ERR(di->regu)) { 266184edbeeab67c1575067335179513150115da367bArun Murthy ret = PTR_ERR(di->regu); 266284edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to get vddadc regulator\n"); 266384edbeeab67c1575067335179513150115da367bArun Murthy goto free_charger_wq; 266484edbeeab67c1575067335179513150115da367bArun Murthy } 266584edbeeab67c1575067335179513150115da367bArun Murthy 266684edbeeab67c1575067335179513150115da367bArun Murthy 266784edbeeab67c1575067335179513150115da367bArun Murthy /* Initialize OVV, and other registers */ 266884edbeeab67c1575067335179513150115da367bArun Murthy ret = ab8500_charger_init_hw_registers(di); 266984edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 267084edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to initialize ABB registers\n"); 267184edbeeab67c1575067335179513150115da367bArun Murthy goto free_regulator; 267284edbeeab67c1575067335179513150115da367bArun Murthy } 267384edbeeab67c1575067335179513150115da367bArun Murthy 267484edbeeab67c1575067335179513150115da367bArun Murthy /* Register AC charger class */ 267584edbeeab67c1575067335179513150115da367bArun Murthy ret = power_supply_register(di->dev, &di->ac_chg.psy); 267684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 267784edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to register AC charger\n"); 267884edbeeab67c1575067335179513150115da367bArun Murthy goto free_regulator; 267984edbeeab67c1575067335179513150115da367bArun Murthy } 268084edbeeab67c1575067335179513150115da367bArun Murthy 268184edbeeab67c1575067335179513150115da367bArun Murthy /* Register USB charger class */ 268284edbeeab67c1575067335179513150115da367bArun Murthy ret = power_supply_register(di->dev, &di->usb_chg.psy); 268384edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 268484edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to register USB charger\n"); 268584edbeeab67c1575067335179513150115da367bArun Murthy goto free_ac; 268684edbeeab67c1575067335179513150115da367bArun Murthy } 268784edbeeab67c1575067335179513150115da367bArun Murthy 2688efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov di->usb_phy = usb_get_transceiver(); 2689efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov if (!di->usb_phy) { 2690efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov dev_err(di->dev, "failed to get usb transceiver\n"); 269184edbeeab67c1575067335179513150115da367bArun Murthy ret = -EINVAL; 269284edbeeab67c1575067335179513150115da367bArun Murthy goto free_usb; 269384edbeeab67c1575067335179513150115da367bArun Murthy } 269484edbeeab67c1575067335179513150115da367bArun Murthy di->nb.notifier_call = ab8500_charger_usb_notifier_call; 2695efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov ret = usb_register_notifier(di->usb_phy, &di->nb); 269684edbeeab67c1575067335179513150115da367bArun Murthy if (ret) { 2697efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov dev_err(di->dev, "failed to register usb notifier\n"); 2698efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov goto put_usb_phy; 269984edbeeab67c1575067335179513150115da367bArun Murthy } 270084edbeeab67c1575067335179513150115da367bArun Murthy 270184edbeeab67c1575067335179513150115da367bArun Murthy /* Identify the connected charger types during startup */ 270284edbeeab67c1575067335179513150115da367bArun Murthy charger_status = ab8500_charger_detect_chargers(di); 270384edbeeab67c1575067335179513150115da367bArun Murthy if (charger_status & AC_PW_CONN) { 270484edbeeab67c1575067335179513150115da367bArun Murthy di->ac.charger_connected = 1; 270584edbeeab67c1575067335179513150115da367bArun Murthy di->ac_conn = true; 270684edbeeab67c1575067335179513150115da367bArun Murthy ab8500_power_supply_changed(di, &di->ac_chg.psy); 270784edbeeab67c1575067335179513150115da367bArun Murthy sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); 270884edbeeab67c1575067335179513150115da367bArun Murthy } 270984edbeeab67c1575067335179513150115da367bArun Murthy 271084edbeeab67c1575067335179513150115da367bArun Murthy if (charger_status & USB_PW_CONN) { 271184edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "VBUS Detect during startup\n"); 271284edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected = true; 271384edbeeab67c1575067335179513150115da367bArun Murthy di->vbus_detected_start = true; 271484edbeeab67c1575067335179513150115da367bArun Murthy queue_work(di->charger_wq, 271584edbeeab67c1575067335179513150115da367bArun Murthy &di->detect_usb_type_work); 271684edbeeab67c1575067335179513150115da367bArun Murthy } 271784edbeeab67c1575067335179513150115da367bArun Murthy 271884edbeeab67c1575067335179513150115da367bArun Murthy /* Register interrupts */ 271984edbeeab67c1575067335179513150115da367bArun Murthy for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 272084edbeeab67c1575067335179513150115da367bArun Murthy irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 272184edbeeab67c1575067335179513150115da367bArun Murthy ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, 272284edbeeab67c1575067335179513150115da367bArun Murthy IRQF_SHARED | IRQF_NO_SUSPEND, 272384edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_irq[i].name, di); 272484edbeeab67c1575067335179513150115da367bArun Murthy 272584edbeeab67c1575067335179513150115da367bArun Murthy if (ret != 0) { 272684edbeeab67c1575067335179513150115da367bArun Murthy dev_err(di->dev, "failed to request %s IRQ %d: %d\n" 272784edbeeab67c1575067335179513150115da367bArun Murthy , ab8500_charger_irq[i].name, irq, ret); 272884edbeeab67c1575067335179513150115da367bArun Murthy goto free_irq; 272984edbeeab67c1575067335179513150115da367bArun Murthy } 273084edbeeab67c1575067335179513150115da367bArun Murthy dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", 273184edbeeab67c1575067335179513150115da367bArun Murthy ab8500_charger_irq[i].name, irq, ret); 273284edbeeab67c1575067335179513150115da367bArun Murthy } 273384edbeeab67c1575067335179513150115da367bArun Murthy 273484edbeeab67c1575067335179513150115da367bArun Murthy platform_set_drvdata(pdev, di); 273584edbeeab67c1575067335179513150115da367bArun Murthy 273684edbeeab67c1575067335179513150115da367bArun Murthy return ret; 273784edbeeab67c1575067335179513150115da367bArun Murthy 273884edbeeab67c1575067335179513150115da367bArun Murthyfree_irq: 2739efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov usb_unregister_notifier(di->usb_phy, &di->nb); 274084edbeeab67c1575067335179513150115da367bArun Murthy 274184edbeeab67c1575067335179513150115da367bArun Murthy /* We also have to free all successfully registered irqs */ 274284edbeeab67c1575067335179513150115da367bArun Murthy for (i = i - 1; i >= 0; i--) { 274384edbeeab67c1575067335179513150115da367bArun Murthy irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 274484edbeeab67c1575067335179513150115da367bArun Murthy free_irq(irq, di); 274584edbeeab67c1575067335179513150115da367bArun Murthy } 2746efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsovput_usb_phy: 2747efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov usb_put_transceiver(di->usb_phy); 274884edbeeab67c1575067335179513150115da367bArun Murthyfree_usb: 274984edbeeab67c1575067335179513150115da367bArun Murthy power_supply_unregister(&di->usb_chg.psy); 275084edbeeab67c1575067335179513150115da367bArun Murthyfree_ac: 275184edbeeab67c1575067335179513150115da367bArun Murthy power_supply_unregister(&di->ac_chg.psy); 275284edbeeab67c1575067335179513150115da367bArun Murthyfree_regulator: 275384edbeeab67c1575067335179513150115da367bArun Murthy regulator_put(di->regu); 275484edbeeab67c1575067335179513150115da367bArun Murthyfree_charger_wq: 275584edbeeab67c1575067335179513150115da367bArun Murthy destroy_workqueue(di->charger_wq); 275684edbeeab67c1575067335179513150115da367bArun Murthyfree_device_info: 275784edbeeab67c1575067335179513150115da367bArun Murthy kfree(di); 275884edbeeab67c1575067335179513150115da367bArun Murthy 275984edbeeab67c1575067335179513150115da367bArun Murthy return ret; 276084edbeeab67c1575067335179513150115da367bArun Murthy} 276184edbeeab67c1575067335179513150115da367bArun Murthy 276284edbeeab67c1575067335179513150115da367bArun Murthystatic struct platform_driver ab8500_charger_driver = { 276384edbeeab67c1575067335179513150115da367bArun Murthy .probe = ab8500_charger_probe, 276484edbeeab67c1575067335179513150115da367bArun Murthy .remove = __devexit_p(ab8500_charger_remove), 276584edbeeab67c1575067335179513150115da367bArun Murthy .suspend = ab8500_charger_suspend, 276684edbeeab67c1575067335179513150115da367bArun Murthy .resume = ab8500_charger_resume, 276784edbeeab67c1575067335179513150115da367bArun Murthy .driver = { 276884edbeeab67c1575067335179513150115da367bArun Murthy .name = "ab8500-charger", 276984edbeeab67c1575067335179513150115da367bArun Murthy .owner = THIS_MODULE, 277084edbeeab67c1575067335179513150115da367bArun Murthy }, 277184edbeeab67c1575067335179513150115da367bArun Murthy}; 277284edbeeab67c1575067335179513150115da367bArun Murthy 277384edbeeab67c1575067335179513150115da367bArun Murthystatic int __init ab8500_charger_init(void) 277484edbeeab67c1575067335179513150115da367bArun Murthy{ 277584edbeeab67c1575067335179513150115da367bArun Murthy return platform_driver_register(&ab8500_charger_driver); 277684edbeeab67c1575067335179513150115da367bArun Murthy} 277784edbeeab67c1575067335179513150115da367bArun Murthy 277884edbeeab67c1575067335179513150115da367bArun Murthystatic void __exit ab8500_charger_exit(void) 277984edbeeab67c1575067335179513150115da367bArun Murthy{ 278084edbeeab67c1575067335179513150115da367bArun Murthy platform_driver_unregister(&ab8500_charger_driver); 278184edbeeab67c1575067335179513150115da367bArun Murthy} 278284edbeeab67c1575067335179513150115da367bArun Murthy 278384edbeeab67c1575067335179513150115da367bArun Murthysubsys_initcall_sync(ab8500_charger_init); 278484edbeeab67c1575067335179513150115da367bArun Murthymodule_exit(ab8500_charger_exit); 278584edbeeab67c1575067335179513150115da367bArun Murthy 278684edbeeab67c1575067335179513150115da367bArun MurthyMODULE_LICENSE("GPL v2"); 278784edbeeab67c1575067335179513150115da367bArun MurthyMODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); 278884edbeeab67c1575067335179513150115da367bArun MurthyMODULE_ALIAS("platform:ab8500-charger"); 278984edbeeab67c1575067335179513150115da367bArun MurthyMODULE_DESCRIPTION("AB8500 charger management driver"); 2790