10376148fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28c0984e5SSebastian Reichel /*
38c0984e5SSebastian Reichel  * Copyright (C) ST-Ericsson SA 2012
48c0984e5SSebastian Reichel  *
58c0984e5SSebastian Reichel  * Charger driver for AB8500
68c0984e5SSebastian Reichel  *
78c0984e5SSebastian Reichel  * Author:
88c0984e5SSebastian Reichel  *	Johan Palsson <johan.palsson@stericsson.com>
98c0984e5SSebastian Reichel  *	Karl Komierowski <karl.komierowski@stericsson.com>
108c0984e5SSebastian Reichel  *	Arun R Murthy <arun.murthy@stericsson.com>
118c0984e5SSebastian Reichel  */
128c0984e5SSebastian Reichel 
138c0984e5SSebastian Reichel #include <linux/init.h>
148c0984e5SSebastian Reichel #include <linux/module.h>
158c0984e5SSebastian Reichel #include <linux/device.h>
161c1f13a0SLinus Walleij #include <linux/component.h>
178c0984e5SSebastian Reichel #include <linux/interrupt.h>
188c0984e5SSebastian Reichel #include <linux/delay.h>
198c0984e5SSebastian Reichel #include <linux/notifier.h>
208c0984e5SSebastian Reichel #include <linux/slab.h>
218c0984e5SSebastian Reichel #include <linux/platform_device.h>
228c0984e5SSebastian Reichel #include <linux/power_supply.h>
238c0984e5SSebastian Reichel #include <linux/completion.h>
248c0984e5SSebastian Reichel #include <linux/regulator/consumer.h>
258c0984e5SSebastian Reichel #include <linux/err.h>
268c0984e5SSebastian Reichel #include <linux/workqueue.h>
278c0984e5SSebastian Reichel #include <linux/kobject.h>
288c0984e5SSebastian Reichel #include <linux/of.h>
298c0984e5SSebastian Reichel #include <linux/mfd/core.h>
308c0984e5SSebastian Reichel #include <linux/mfd/abx500/ab8500.h>
318c0984e5SSebastian Reichel #include <linux/mfd/abx500.h>
328c0984e5SSebastian Reichel #include <linux/usb/otg.h>
338c0984e5SSebastian Reichel #include <linux/mutex.h>
3497ab78baSLinus Walleij #include <linux/iio/consumer.h>
358c0984e5SSebastian Reichel 
36417c0fc2SLinus Walleij #include "ab8500-bm.h"
37a65aa0ceSLinus Walleij #include "ab8500-chargalg.h"
38417c0fc2SLinus Walleij 
398c0984e5SSebastian Reichel /* Charger constants */
408c0984e5SSebastian Reichel #define NO_PW_CONN			0
418c0984e5SSebastian Reichel #define AC_PW_CONN			1
428c0984e5SSebastian Reichel #define USB_PW_CONN			2
438c0984e5SSebastian Reichel 
448c0984e5SSebastian Reichel #define MAIN_WDOG_ENA			0x01
458c0984e5SSebastian Reichel #define MAIN_WDOG_KICK			0x02
468c0984e5SSebastian Reichel #define MAIN_WDOG_DIS			0x00
478c0984e5SSebastian Reichel #define CHARG_WD_KICK			0x01
488c0984e5SSebastian Reichel #define MAIN_CH_ENA			0x01
498c0984e5SSebastian Reichel #define MAIN_CH_NO_OVERSHOOT_ENA_N	0x02
508c0984e5SSebastian Reichel #define USB_CH_ENA			0x01
518c0984e5SSebastian Reichel #define USB_CHG_NO_OVERSHOOT_ENA_N	0x02
528c0984e5SSebastian Reichel #define MAIN_CH_DET			0x01
538c0984e5SSebastian Reichel #define MAIN_CH_CV_ON			0x04
548c0984e5SSebastian Reichel #define USB_CH_CV_ON			0x08
558c0984e5SSebastian Reichel #define VBUS_DET_DBNC100		0x02
568c0984e5SSebastian Reichel #define VBUS_DET_DBNC1			0x01
578c0984e5SSebastian Reichel #define OTP_ENABLE_WD			0x01
588c0984e5SSebastian Reichel #define DROP_COUNT_RESET		0x01
598c0984e5SSebastian Reichel #define USB_CH_DET			0x01
608c0984e5SSebastian Reichel 
618c0984e5SSebastian Reichel #define MAIN_CH_INPUT_CURR_SHIFT	4
628c0984e5SSebastian Reichel #define VBUS_IN_CURR_LIM_SHIFT		4
638c0984e5SSebastian Reichel #define AUTO_VBUS_IN_CURR_LIM_SHIFT	4
648c0984e5SSebastian Reichel #define VBUS_IN_CURR_LIM_RETRY_SET_TIME	30 /* seconds */
658c0984e5SSebastian Reichel 
668c0984e5SSebastian Reichel #define LED_INDICATOR_PWM_ENA		0x01
678c0984e5SSebastian Reichel #define LED_INDICATOR_PWM_DIS		0x00
688c0984e5SSebastian Reichel #define LED_IND_CUR_5MA			0x04
698c0984e5SSebastian Reichel #define LED_INDICATOR_PWM_DUTY_252_256	0xBF
708c0984e5SSebastian Reichel 
718c0984e5SSebastian Reichel /* HW failure constants */
728c0984e5SSebastian Reichel #define MAIN_CH_TH_PROT			0x02
738c0984e5SSebastian Reichel #define VBUS_CH_NOK			0x08
748c0984e5SSebastian Reichel #define USB_CH_TH_PROT			0x02
758c0984e5SSebastian Reichel #define VBUS_OVV_TH			0x01
768c0984e5SSebastian Reichel #define MAIN_CH_NOK			0x01
778c0984e5SSebastian Reichel #define VBUS_DET			0x80
788c0984e5SSebastian Reichel 
798c0984e5SSebastian Reichel #define MAIN_CH_STATUS2_MAINCHGDROP		0x80
808c0984e5SSebastian Reichel #define MAIN_CH_STATUS2_MAINCHARGERDETDBNC	0x40
818c0984e5SSebastian Reichel #define USB_CH_VBUSDROP				0x40
828c0984e5SSebastian Reichel #define USB_CH_VBUSDETDBNC			0x01
838c0984e5SSebastian Reichel 
848c0984e5SSebastian Reichel /* UsbLineStatus register bit masks */
858c0984e5SSebastian Reichel #define AB8500_USB_LINK_STATUS		0x78
868c0984e5SSebastian Reichel #define AB8505_USB_LINK_STATUS		0xF8
878c0984e5SSebastian Reichel #define AB8500_STD_HOST_SUSP		0x18
888c0984e5SSebastian Reichel #define USB_LINK_STATUS_SHIFT		3
898c0984e5SSebastian Reichel 
908c0984e5SSebastian Reichel /* Watchdog timeout constant */
918c0984e5SSebastian Reichel #define WD_TIMER			0x30 /* 4min */
928c0984e5SSebastian Reichel #define WD_KICK_INTERVAL		(60 * HZ)
938c0984e5SSebastian Reichel 
948c0984e5SSebastian Reichel /* Lowest charger voltage is 3.39V -> 0x4E */
958c0984e5SSebastian Reichel #define LOW_VOLT_REG			0x4E
968c0984e5SSebastian Reichel 
978c0984e5SSebastian Reichel /* Step up/down delay in us */
988c0984e5SSebastian Reichel #define STEP_UDELAY			1000
998c0984e5SSebastian Reichel 
1008c0984e5SSebastian Reichel #define CHARGER_STATUS_POLL 10 /* in ms */
1018c0984e5SSebastian Reichel 
1028c0984e5SSebastian Reichel #define CHG_WD_INTERVAL			(60 * HZ)
1038c0984e5SSebastian Reichel 
1048c0984e5SSebastian Reichel #define AB8500_SW_CONTROL_FALLBACK	0x03
1058c0984e5SSebastian Reichel /* Wait for enumeration before charing in us */
1068c0984e5SSebastian Reichel #define WAIT_ACA_RID_ENUMERATION	(5 * 1000)
1078c0984e5SSebastian Reichel /*External charger control*/
1088c0984e5SSebastian Reichel #define AB8500_SYS_CHARGER_CONTROL_REG		0x52
1098c0984e5SSebastian Reichel #define EXTERNAL_CHARGER_DISABLE_REG_VAL	0x03
1108c0984e5SSebastian Reichel #define EXTERNAL_CHARGER_ENABLE_REG_VAL		0x07
1118c0984e5SSebastian Reichel 
1128c0984e5SSebastian Reichel /* UsbLineStatus register - usb types */
1138c0984e5SSebastian Reichel enum ab8500_charger_link_status {
1148c0984e5SSebastian Reichel 	USB_STAT_NOT_CONFIGURED,
1158c0984e5SSebastian Reichel 	USB_STAT_STD_HOST_NC,
1168c0984e5SSebastian Reichel 	USB_STAT_STD_HOST_C_NS,
1178c0984e5SSebastian Reichel 	USB_STAT_STD_HOST_C_S,
1188c0984e5SSebastian Reichel 	USB_STAT_HOST_CHG_NM,
1198c0984e5SSebastian Reichel 	USB_STAT_HOST_CHG_HS,
1208c0984e5SSebastian Reichel 	USB_STAT_HOST_CHG_HS_CHIRP,
1218c0984e5SSebastian Reichel 	USB_STAT_DEDICATED_CHG,
1228c0984e5SSebastian Reichel 	USB_STAT_ACA_RID_A,
1238c0984e5SSebastian Reichel 	USB_STAT_ACA_RID_B,
1248c0984e5SSebastian Reichel 	USB_STAT_ACA_RID_C_NM,
1258c0984e5SSebastian Reichel 	USB_STAT_ACA_RID_C_HS,
1268c0984e5SSebastian Reichel 	USB_STAT_ACA_RID_C_HS_CHIRP,
1278c0984e5SSebastian Reichel 	USB_STAT_HM_IDGND,
1288c0984e5SSebastian Reichel 	USB_STAT_RESERVED,
1298c0984e5SSebastian Reichel 	USB_STAT_NOT_VALID_LINK,
1308c0984e5SSebastian Reichel 	USB_STAT_PHY_EN,
1318c0984e5SSebastian Reichel 	USB_STAT_SUP_NO_IDGND_VBUS,
1328c0984e5SSebastian Reichel 	USB_STAT_SUP_IDGND_VBUS,
1338c0984e5SSebastian Reichel 	USB_STAT_CHARGER_LINE_1,
1348c0984e5SSebastian Reichel 	USB_STAT_CARKIT_1,
1358c0984e5SSebastian Reichel 	USB_STAT_CARKIT_2,
1368c0984e5SSebastian Reichel 	USB_STAT_ACA_DOCK_CHARGER,
1378c0984e5SSebastian Reichel };
1388c0984e5SSebastian Reichel 
1398c0984e5SSebastian Reichel enum ab8500_usb_state {
1408c0984e5SSebastian Reichel 	AB8500_BM_USB_STATE_RESET_HS,	/* HighSpeed Reset */
1418c0984e5SSebastian Reichel 	AB8500_BM_USB_STATE_RESET_FS,	/* FullSpeed/LowSpeed Reset */
1428c0984e5SSebastian Reichel 	AB8500_BM_USB_STATE_CONFIGURED,
1438c0984e5SSebastian Reichel 	AB8500_BM_USB_STATE_SUSPEND,
1448c0984e5SSebastian Reichel 	AB8500_BM_USB_STATE_RESUME,
1458c0984e5SSebastian Reichel 	AB8500_BM_USB_STATE_MAX,
1468c0984e5SSebastian Reichel };
1478c0984e5SSebastian Reichel 
14883e5aa77SLinus Walleij /* VBUS input current limits supported in AB8500 in uA */
14983e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P05		50000
15083e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P09		98000
15183e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P19		193000
15283e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P29		290000
15383e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P38		380000
15483e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P45		450000
15583e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P5		500000
15683e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P6		600000
15783e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P7		700000
15883e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P8		800000
15983e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P9		900000
16083e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P0		1000000
16183e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P1		1100000
16283e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P3		1300000
16383e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P4		1400000
16483e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P5		1500000
1658c0984e5SSebastian Reichel 
16621ad180dSLinus Walleij #define VBAT_TRESH_IP_CUR_RED		3800000
1678c0984e5SSebastian Reichel 
1688c0984e5SSebastian Reichel #define to_ab8500_charger_usb_device_info(x) container_of((x), \
1698c0984e5SSebastian Reichel 	struct ab8500_charger, usb_chg)
1708c0984e5SSebastian Reichel #define to_ab8500_charger_ac_device_info(x) container_of((x), \
1718c0984e5SSebastian Reichel 	struct ab8500_charger, ac_chg)
1728c0984e5SSebastian Reichel 
1738c0984e5SSebastian Reichel /**
1748f5b3739SHong Peng  * struct ab8500_charger_interrupts - ab8500 interrupts
1758c0984e5SSebastian Reichel  * @name:	name of the interrupt
1768c0984e5SSebastian Reichel  * @isr		function pointer to the isr
1778c0984e5SSebastian Reichel  */
1788c0984e5SSebastian Reichel struct ab8500_charger_interrupts {
1798c0984e5SSebastian Reichel 	char *name;
1808c0984e5SSebastian Reichel 	irqreturn_t (*isr)(int irq, void *data);
1818c0984e5SSebastian Reichel };
1828c0984e5SSebastian Reichel 
1838c0984e5SSebastian Reichel struct ab8500_charger_info {
1848c0984e5SSebastian Reichel 	int charger_connected;
1858c0984e5SSebastian Reichel 	int charger_online;
186bc6e0287SLinus Walleij 	int charger_voltage_uv;
1878c0984e5SSebastian Reichel 	int cv_active;
1888c0984e5SSebastian Reichel 	bool wd_expired;
18983e5aa77SLinus Walleij 	int charger_current_ua;
1908c0984e5SSebastian Reichel };
1918c0984e5SSebastian Reichel 
1928c0984e5SSebastian Reichel struct ab8500_charger_event_flags {
1938c0984e5SSebastian Reichel 	bool mainextchnotok;
1948c0984e5SSebastian Reichel 	bool main_thermal_prot;
1958c0984e5SSebastian Reichel 	bool usb_thermal_prot;
1968c0984e5SSebastian Reichel 	bool vbus_ovv;
1978c0984e5SSebastian Reichel 	bool usbchargernotok;
1988c0984e5SSebastian Reichel 	bool chgwdexp;
1998c0984e5SSebastian Reichel 	bool vbus_collapse;
2008c0984e5SSebastian Reichel 	bool vbus_drop_end;
2018c0984e5SSebastian Reichel };
2028c0984e5SSebastian Reichel 
2038c0984e5SSebastian Reichel struct ab8500_charger_usb_state {
20483e5aa77SLinus Walleij 	int usb_current_ua;
20583e5aa77SLinus Walleij 	int usb_current_tmp_ua;
2068c0984e5SSebastian Reichel 	enum ab8500_usb_state state;
2078c0984e5SSebastian Reichel 	enum ab8500_usb_state state_tmp;
2088c0984e5SSebastian Reichel 	spinlock_t usb_lock;
2098c0984e5SSebastian Reichel };
2108c0984e5SSebastian Reichel 
2118c0984e5SSebastian Reichel struct ab8500_charger_max_usb_in_curr {
21283e5aa77SLinus Walleij 	int usb_type_max_ua;
21383e5aa77SLinus Walleij 	int set_max_ua;
21483e5aa77SLinus Walleij 	int calculated_max_ua;
2158c0984e5SSebastian Reichel };
2168c0984e5SSebastian Reichel 
2178c0984e5SSebastian Reichel /**
2188c0984e5SSebastian Reichel  * struct ab8500_charger - ab8500 Charger device information
2198c0984e5SSebastian Reichel  * @dev:		Pointer to the structure device
2208c0984e5SSebastian Reichel  * @vbus_detected:	VBUS detected
2218c0984e5SSebastian Reichel  * @vbus_detected_start:
2228c0984e5SSebastian Reichel  *			VBUS detected during startup
2238c0984e5SSebastian Reichel  * @ac_conn:		This will be true when the AC charger has been plugged
2248c0984e5SSebastian Reichel  * @vddadc_en_ac:	Indicate if VDD ADC supply is enabled because AC
2258c0984e5SSebastian Reichel  *			charger is enabled
2268c0984e5SSebastian Reichel  * @vddadc_en_usb:	Indicate if VDD ADC supply is enabled because USB
2278c0984e5SSebastian Reichel  *			charger is enabled
2288c0984e5SSebastian Reichel  * @vbat		Battery voltage
2298c0984e5SSebastian Reichel  * @old_vbat		Previously measured battery voltage
2308c0984e5SSebastian Reichel  * @usb_device_is_unrecognised	USB device is unrecognised by the hardware
2318c0984e5SSebastian Reichel  * @autopower		Indicate if we should have automatic pwron after pwrloss
2328c0984e5SSebastian Reichel  * @autopower_cfg	platform specific power config support for "pwron after pwrloss"
2338c0984e5SSebastian Reichel  * @invalid_charger_detect_state State when forcing AB to use invalid charger
2348c0984e5SSebastian Reichel  * @is_aca_rid:		Incicate if accessory is ACA type
2358c0984e5SSebastian Reichel  * @current_stepping_sessions:
2368c0984e5SSebastian Reichel  *			Counter for current stepping sessions
2378c0984e5SSebastian Reichel  * @parent:		Pointer to the struct ab8500
23897ab78baSLinus Walleij  * @adc_main_charger_v	ADC channel for main charger voltage
23997ab78baSLinus Walleij  * @adc_main_charger_c	ADC channel for main charger current
24097ab78baSLinus Walleij  * @adc_vbus_v		ADC channel for USB charger voltage
24197ab78baSLinus Walleij  * @adc_usb_charger_c	ADC channel for USB charger current
2428c0984e5SSebastian Reichel  * @bm:           	Platform specific battery management information
2438c0984e5SSebastian Reichel  * @flags:		Structure for information about events triggered
2448c0984e5SSebastian Reichel  * @usb_state:		Structure for usb stack information
2458c0984e5SSebastian Reichel  * @max_usb_in_curr:	Max USB charger input current
2468c0984e5SSebastian Reichel  * @ac_chg:		AC charger power supply
2478c0984e5SSebastian Reichel  * @usb_chg:		USB charger power supply
2488c0984e5SSebastian Reichel  * @ac:			Structure that holds the AC charger properties
2498c0984e5SSebastian Reichel  * @usb:		Structure that holds the USB charger properties
2508c0984e5SSebastian Reichel  * @regu:		Pointer to the struct regulator
2518c0984e5SSebastian Reichel  * @charger_wq:		Work queue for the IRQs and checking HW state
2528c0984e5SSebastian Reichel  * @usb_ipt_crnt_lock:	Lock to protect VBUS input current setting from mutuals
2538c0984e5SSebastian Reichel  * @pm_lock:		Lock to prevent system to suspend
2548c0984e5SSebastian Reichel  * @check_vbat_work	Work for checking vbat threshold to adjust vbus current
2558c0984e5SSebastian Reichel  * @check_hw_failure_work:	Work for checking HW state
2568c0984e5SSebastian Reichel  * @check_usbchgnotok_work:	Work for checking USB charger not ok status
2578c0984e5SSebastian Reichel  * @kick_wd_work:		Work for kicking the charger watchdog in case
2588c0984e5SSebastian Reichel  *				of ABB rev 1.* due to the watchog logic bug
2598c0984e5SSebastian Reichel  * @ac_charger_attached_work:	Work for checking if AC charger is still
2608c0984e5SSebastian Reichel  *				connected
2618c0984e5SSebastian Reichel  * @usb_charger_attached_work:	Work for checking if USB charger is still
2628c0984e5SSebastian Reichel  *				connected
2638c0984e5SSebastian Reichel  * @ac_work:			Work for checking AC charger connection
2648c0984e5SSebastian Reichel  * @detect_usb_type_work:	Work for detecting the USB type connected
2658c0984e5SSebastian Reichel  * @usb_link_status_work:	Work for checking the new USB link status
2668c0984e5SSebastian Reichel  * @usb_state_changed_work:	Work for checking USB state
2678c0984e5SSebastian Reichel  * @attach_work:		Work for detecting USB type
2688c0984e5SSebastian Reichel  * @vbus_drop_end_work:		Work for detecting VBUS drop end
2698c0984e5SSebastian Reichel  * @check_main_thermal_prot_work:
2708c0984e5SSebastian Reichel  *				Work for checking Main thermal status
2718c0984e5SSebastian Reichel  * @check_usb_thermal_prot_work:
2728c0984e5SSebastian Reichel  *				Work for checking USB thermal status
2738c0984e5SSebastian Reichel  * @charger_attached_mutex:	For controlling the wakelock
2748c0984e5SSebastian Reichel  */
2758c0984e5SSebastian Reichel struct ab8500_charger {
2768c0984e5SSebastian Reichel 	struct device *dev;
2778c0984e5SSebastian Reichel 	bool vbus_detected;
2788c0984e5SSebastian Reichel 	bool vbus_detected_start;
2798c0984e5SSebastian Reichel 	bool ac_conn;
2808c0984e5SSebastian Reichel 	bool vddadc_en_ac;
2818c0984e5SSebastian Reichel 	bool vddadc_en_usb;
2828c0984e5SSebastian Reichel 	int vbat;
2838c0984e5SSebastian Reichel 	int old_vbat;
2848c0984e5SSebastian Reichel 	bool usb_device_is_unrecognised;
2858c0984e5SSebastian Reichel 	bool autopower;
2868c0984e5SSebastian Reichel 	bool autopower_cfg;
2878c0984e5SSebastian Reichel 	int invalid_charger_detect_state;
2888c0984e5SSebastian Reichel 	int is_aca_rid;
2898c0984e5SSebastian Reichel 	atomic_t current_stepping_sessions;
2908c0984e5SSebastian Reichel 	struct ab8500 *parent;
29197ab78baSLinus Walleij 	struct iio_channel *adc_main_charger_v;
29297ab78baSLinus Walleij 	struct iio_channel *adc_main_charger_c;
29397ab78baSLinus Walleij 	struct iio_channel *adc_vbus_v;
29497ab78baSLinus Walleij 	struct iio_channel *adc_usb_charger_c;
295484a9cc3SLinus Walleij 	struct ab8500_bm_data *bm;
2968c0984e5SSebastian Reichel 	struct ab8500_charger_event_flags flags;
2978c0984e5SSebastian Reichel 	struct ab8500_charger_usb_state usb_state;
2988c0984e5SSebastian Reichel 	struct ab8500_charger_max_usb_in_curr max_usb_in_curr;
2998c0984e5SSebastian Reichel 	struct ux500_charger ac_chg;
3008c0984e5SSebastian Reichel 	struct ux500_charger usb_chg;
3018c0984e5SSebastian Reichel 	struct ab8500_charger_info ac;
3028c0984e5SSebastian Reichel 	struct ab8500_charger_info usb;
3038c0984e5SSebastian Reichel 	struct regulator *regu;
3048c0984e5SSebastian Reichel 	struct workqueue_struct *charger_wq;
3058c0984e5SSebastian Reichel 	struct mutex usb_ipt_crnt_lock;
3068c0984e5SSebastian Reichel 	struct delayed_work check_vbat_work;
3078c0984e5SSebastian Reichel 	struct delayed_work check_hw_failure_work;
3088c0984e5SSebastian Reichel 	struct delayed_work check_usbchgnotok_work;
3098c0984e5SSebastian Reichel 	struct delayed_work kick_wd_work;
3108c0984e5SSebastian Reichel 	struct delayed_work usb_state_changed_work;
3118c0984e5SSebastian Reichel 	struct delayed_work attach_work;
3128c0984e5SSebastian Reichel 	struct delayed_work ac_charger_attached_work;
3138c0984e5SSebastian Reichel 	struct delayed_work usb_charger_attached_work;
3148c0984e5SSebastian Reichel 	struct delayed_work vbus_drop_end_work;
3158c0984e5SSebastian Reichel 	struct work_struct ac_work;
3168c0984e5SSebastian Reichel 	struct work_struct detect_usb_type_work;
3178c0984e5SSebastian Reichel 	struct work_struct usb_link_status_work;
3188c0984e5SSebastian Reichel 	struct work_struct check_main_thermal_prot_work;
3198c0984e5SSebastian Reichel 	struct work_struct check_usb_thermal_prot_work;
3208c0984e5SSebastian Reichel 	struct usb_phy *usb_phy;
3218c0984e5SSebastian Reichel 	struct notifier_block nb;
3228c0984e5SSebastian Reichel 	struct mutex charger_attached_mutex;
3238c0984e5SSebastian Reichel };
3248c0984e5SSebastian Reichel 
3258c0984e5SSebastian Reichel /* AC properties */
3268c0984e5SSebastian Reichel static enum power_supply_property ab8500_charger_ac_props[] = {
3278c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_HEALTH,
3288c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_PRESENT,
3298c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_ONLINE,
3308c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
3318c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_VOLTAGE_AVG,
3328c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_CURRENT_NOW,
3338c0984e5SSebastian Reichel };
3348c0984e5SSebastian Reichel 
3358c0984e5SSebastian Reichel /* USB properties */
3368c0984e5SSebastian Reichel static enum power_supply_property ab8500_charger_usb_props[] = {
3378c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_HEALTH,
3388c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_CURRENT_AVG,
3398c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_PRESENT,
3408c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_ONLINE,
3418c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
3428c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_VOLTAGE_AVG,
3438c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_CURRENT_NOW,
3448c0984e5SSebastian Reichel };
3458c0984e5SSebastian Reichel 
3468c0984e5SSebastian Reichel /*
3478c0984e5SSebastian Reichel  * Function for enabling and disabling sw fallback mode
3488c0984e5SSebastian Reichel  * should always be disabled when no charger is connected.
3498c0984e5SSebastian Reichel  */
ab8500_enable_disable_sw_fallback(struct ab8500_charger * di,bool fallback)3508c0984e5SSebastian Reichel static void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di,
3518c0984e5SSebastian Reichel 		bool fallback)
3528c0984e5SSebastian Reichel {
3538c0984e5SSebastian Reichel 	u8 val;
3548c0984e5SSebastian Reichel 	u8 reg;
3558c0984e5SSebastian Reichel 	u8 bank;
3568c0984e5SSebastian Reichel 	u8 bit;
3578c0984e5SSebastian Reichel 	int ret;
3588c0984e5SSebastian Reichel 
3598c0984e5SSebastian Reichel 	dev_dbg(di->dev, "SW Fallback: %d\n", fallback);
3608c0984e5SSebastian Reichel 
3618c0984e5SSebastian Reichel 	if (is_ab8500(di->parent)) {
3628c0984e5SSebastian Reichel 		bank = 0x15;
3638c0984e5SSebastian Reichel 		reg = 0x0;
3648c0984e5SSebastian Reichel 		bit = 3;
3658c0984e5SSebastian Reichel 	} else {
3668c0984e5SSebastian Reichel 		bank = AB8500_SYS_CTRL1_BLOCK;
3678c0984e5SSebastian Reichel 		reg = AB8500_SW_CONTROL_FALLBACK;
3688c0984e5SSebastian Reichel 		bit = 0;
3698c0984e5SSebastian Reichel 	}
3708c0984e5SSebastian Reichel 
3718c0984e5SSebastian Reichel 	/* read the register containing fallback bit */
3728c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, bank, reg, &val);
3738c0984e5SSebastian Reichel 	if (ret < 0) {
3748c0984e5SSebastian Reichel 		dev_err(di->dev, "%d read failed\n", __LINE__);
3758c0984e5SSebastian Reichel 		return;
3768c0984e5SSebastian Reichel 	}
3778c0984e5SSebastian Reichel 
3788c0984e5SSebastian Reichel 	if (is_ab8500(di->parent)) {
3798c0984e5SSebastian Reichel 		/* enable the OPT emulation registers */
3808c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2);
3818c0984e5SSebastian Reichel 		if (ret) {
3828c0984e5SSebastian Reichel 			dev_err(di->dev, "%d write failed\n", __LINE__);
3838c0984e5SSebastian Reichel 			goto disable_otp;
3848c0984e5SSebastian Reichel 		}
3858c0984e5SSebastian Reichel 	}
3868c0984e5SSebastian Reichel 
3878c0984e5SSebastian Reichel 	if (fallback)
3888c0984e5SSebastian Reichel 		val |= (1 << bit);
3898c0984e5SSebastian Reichel 	else
3908c0984e5SSebastian Reichel 		val &= ~(1 << bit);
3918c0984e5SSebastian Reichel 
3928c0984e5SSebastian Reichel 	/* write back the changed fallback bit value to register */
3938c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, bank, reg, val);
3948c0984e5SSebastian Reichel 	if (ret) {
3958c0984e5SSebastian Reichel 		dev_err(di->dev, "%d write failed\n", __LINE__);
3968c0984e5SSebastian Reichel 	}
3978c0984e5SSebastian Reichel 
3988c0984e5SSebastian Reichel disable_otp:
3998c0984e5SSebastian Reichel 	if (is_ab8500(di->parent)) {
4008c0984e5SSebastian Reichel 		/* disable the set OTP registers again */
4018c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0);
4028c0984e5SSebastian Reichel 		if (ret) {
4038c0984e5SSebastian Reichel 			dev_err(di->dev, "%d write failed\n", __LINE__);
4048c0984e5SSebastian Reichel 		}
4058c0984e5SSebastian Reichel 	}
4068c0984e5SSebastian Reichel }
4078c0984e5SSebastian Reichel 
4088c0984e5SSebastian Reichel /**
409ddb74e98SAshish Chavan  * ab8500_power_supply_changed - a wrapper with local extensions for
4108c0984e5SSebastian Reichel  * power_supply_changed
4118c0984e5SSebastian Reichel  * @di:	  pointer to the ab8500_charger structure
4128c0984e5SSebastian Reichel  * @psy:  pointer to power_supply_that have changed.
4138c0984e5SSebastian Reichel  *
4148c0984e5SSebastian Reichel  */
ab8500_power_supply_changed(struct ab8500_charger * di,struct power_supply * psy)4158c0984e5SSebastian Reichel static void ab8500_power_supply_changed(struct ab8500_charger *di,
4168c0984e5SSebastian Reichel 					struct power_supply *psy)
4178c0984e5SSebastian Reichel {
4185bcb5087SLinus Walleij 	/*
4195bcb5087SLinus Walleij 	 * This happens if we get notifications or interrupts and
4205bcb5087SLinus Walleij 	 * the platform has been configured not to support one or
4215bcb5087SLinus Walleij 	 * other type of charging.
4225bcb5087SLinus Walleij 	 */
4235bcb5087SLinus Walleij 	if (!psy)
4245bcb5087SLinus Walleij 		return;
4255bcb5087SLinus Walleij 
4268c0984e5SSebastian Reichel 	if (di->autopower_cfg) {
4278c0984e5SSebastian Reichel 		if (!di->usb.charger_connected &&
4288c0984e5SSebastian Reichel 		    !di->ac.charger_connected &&
4298c0984e5SSebastian Reichel 		    di->autopower) {
4308c0984e5SSebastian Reichel 			di->autopower = false;
4318c0984e5SSebastian Reichel 			ab8500_enable_disable_sw_fallback(di, false);
4328c0984e5SSebastian Reichel 		} else if (!di->autopower &&
4338c0984e5SSebastian Reichel 			   (di->ac.charger_connected ||
4348c0984e5SSebastian Reichel 			    di->usb.charger_connected)) {
4358c0984e5SSebastian Reichel 			di->autopower = true;
4368c0984e5SSebastian Reichel 			ab8500_enable_disable_sw_fallback(di, true);
4378c0984e5SSebastian Reichel 		}
4388c0984e5SSebastian Reichel 	}
4398c0984e5SSebastian Reichel 	power_supply_changed(psy);
4408c0984e5SSebastian Reichel }
4418c0984e5SSebastian Reichel 
ab8500_charger_set_usb_connected(struct ab8500_charger * di,bool connected)4428c0984e5SSebastian Reichel static void ab8500_charger_set_usb_connected(struct ab8500_charger *di,
4438c0984e5SSebastian Reichel 	bool connected)
4448c0984e5SSebastian Reichel {
4458c0984e5SSebastian Reichel 	if (connected != di->usb.charger_connected) {
4468c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB connected:%i\n", connected);
4478c0984e5SSebastian Reichel 		di->usb.charger_connected = connected;
4488c0984e5SSebastian Reichel 
4498c0984e5SSebastian Reichel 		if (!connected)
4508c0984e5SSebastian Reichel 			di->flags.vbus_drop_end = false;
4518c0984e5SSebastian Reichel 
4525bcb5087SLinus Walleij 		/*
4535bcb5087SLinus Walleij 		 * Sometimes the platform is configured not to support
4545bcb5087SLinus Walleij 		 * USB charging and no psy has been created, but we still
4555bcb5087SLinus Walleij 		 * will get these notifications.
4565bcb5087SLinus Walleij 		 */
4575bcb5087SLinus Walleij 		if (di->usb_chg.psy) {
4585bcb5087SLinus Walleij 			sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL,
4595bcb5087SLinus Walleij 				     "present");
4605bcb5087SLinus Walleij 		}
4618c0984e5SSebastian Reichel 
4628c0984e5SSebastian Reichel 		if (connected) {
4638c0984e5SSebastian Reichel 			mutex_lock(&di->charger_attached_mutex);
4648c0984e5SSebastian Reichel 			mutex_unlock(&di->charger_attached_mutex);
4658c0984e5SSebastian Reichel 
4668c0984e5SSebastian Reichel 			if (is_ab8500(di->parent))
4678c0984e5SSebastian Reichel 				queue_delayed_work(di->charger_wq,
4688c0984e5SSebastian Reichel 					   &di->usb_charger_attached_work,
4698c0984e5SSebastian Reichel 					   HZ);
4708c0984e5SSebastian Reichel 		} else {
4718c0984e5SSebastian Reichel 			cancel_delayed_work_sync(&di->usb_charger_attached_work);
4728c0984e5SSebastian Reichel 			mutex_lock(&di->charger_attached_mutex);
4738c0984e5SSebastian Reichel 			mutex_unlock(&di->charger_attached_mutex);
4748c0984e5SSebastian Reichel 		}
4758c0984e5SSebastian Reichel 	}
4768c0984e5SSebastian Reichel }
4778c0984e5SSebastian Reichel 
4788c0984e5SSebastian Reichel /**
4798c0984e5SSebastian Reichel  * ab8500_charger_get_ac_voltage() - get ac charger voltage
4808c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
4818c0984e5SSebastian Reichel  *
482bc6e0287SLinus Walleij  * Returns ac charger voltage in microvolt (on success)
4838c0984e5SSebastian Reichel  */
ab8500_charger_get_ac_voltage(struct ab8500_charger * di)4848c0984e5SSebastian Reichel static int ab8500_charger_get_ac_voltage(struct ab8500_charger *di)
4858c0984e5SSebastian Reichel {
48697ab78baSLinus Walleij 	int vch, ret;
4878c0984e5SSebastian Reichel 
4888c0984e5SSebastian Reichel 	/* Only measure voltage if the charger is connected */
4898c0984e5SSebastian Reichel 	if (di->ac.charger_connected) {
49097ab78baSLinus Walleij 		ret = iio_read_channel_processed(di->adc_main_charger_v, &vch);
49197ab78baSLinus Walleij 		if (ret < 0)
49297ab78baSLinus Walleij 			dev_err(di->dev, "%s ADC conv failed,\n", __func__);
4938c0984e5SSebastian Reichel 	} else {
4948c0984e5SSebastian Reichel 		vch = 0;
4958c0984e5SSebastian Reichel 	}
496bc6e0287SLinus Walleij 	/* Convert to microvolt, IIO returns millivolt */
497bc6e0287SLinus Walleij 	return vch * 1000;
4988c0984e5SSebastian Reichel }
4998c0984e5SSebastian Reichel 
5008c0984e5SSebastian Reichel /**
5018c0984e5SSebastian Reichel  * ab8500_charger_ac_cv() - check if the main charger is in CV mode
5028c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5038c0984e5SSebastian Reichel  *
5048c0984e5SSebastian Reichel  * Returns ac charger CV mode (on success) else error code
5058c0984e5SSebastian Reichel  */
ab8500_charger_ac_cv(struct ab8500_charger * di)5068c0984e5SSebastian Reichel static int ab8500_charger_ac_cv(struct ab8500_charger *di)
5078c0984e5SSebastian Reichel {
5088c0984e5SSebastian Reichel 	u8 val;
5098c0984e5SSebastian Reichel 	int ret = 0;
5108c0984e5SSebastian Reichel 
5118c0984e5SSebastian Reichel 	/* Only check CV mode if the charger is online */
5128c0984e5SSebastian Reichel 	if (di->ac.charger_online) {
5138c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
5148c0984e5SSebastian Reichel 			AB8500_CH_STATUS1_REG, &val);
5158c0984e5SSebastian Reichel 		if (ret < 0) {
5168c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
5178c0984e5SSebastian Reichel 			return 0;
5188c0984e5SSebastian Reichel 		}
5198c0984e5SSebastian Reichel 
5208c0984e5SSebastian Reichel 		if (val & MAIN_CH_CV_ON)
5218c0984e5SSebastian Reichel 			ret = 1;
5228c0984e5SSebastian Reichel 		else
5238c0984e5SSebastian Reichel 			ret = 0;
5248c0984e5SSebastian Reichel 	}
5258c0984e5SSebastian Reichel 
5268c0984e5SSebastian Reichel 	return ret;
5278c0984e5SSebastian Reichel }
5288c0984e5SSebastian Reichel 
5298c0984e5SSebastian Reichel /**
5308c0984e5SSebastian Reichel  * ab8500_charger_get_vbus_voltage() - get vbus voltage
5318c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5328c0984e5SSebastian Reichel  *
5338c0984e5SSebastian Reichel  * This function returns the vbus voltage.
534bc6e0287SLinus Walleij  * Returns vbus voltage in microvolt (on success)
5358c0984e5SSebastian Reichel  */
ab8500_charger_get_vbus_voltage(struct ab8500_charger * di)5368c0984e5SSebastian Reichel static int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di)
5378c0984e5SSebastian Reichel {
53897ab78baSLinus Walleij 	int vch, ret;
5398c0984e5SSebastian Reichel 
5408c0984e5SSebastian Reichel 	/* Only measure voltage if the charger is connected */
5418c0984e5SSebastian Reichel 	if (di->usb.charger_connected) {
54297ab78baSLinus Walleij 		ret = iio_read_channel_processed(di->adc_vbus_v, &vch);
54397ab78baSLinus Walleij 		if (ret < 0)
54497ab78baSLinus Walleij 			dev_err(di->dev, "%s ADC conv failed,\n", __func__);
5458c0984e5SSebastian Reichel 	} else {
5468c0984e5SSebastian Reichel 		vch = 0;
5478c0984e5SSebastian Reichel 	}
548bc6e0287SLinus Walleij 	/* Convert to microvolt, IIO returns millivolt */
549bc6e0287SLinus Walleij 	return vch * 1000;
5508c0984e5SSebastian Reichel }
5518c0984e5SSebastian Reichel 
5528c0984e5SSebastian Reichel /**
5538c0984e5SSebastian Reichel  * ab8500_charger_get_usb_current() - get usb charger current
5548c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5558c0984e5SSebastian Reichel  *
5568c0984e5SSebastian Reichel  * This function returns the usb charger current.
55783e5aa77SLinus Walleij  * Returns usb current in microamperes (on success) and error code on failure
5588c0984e5SSebastian Reichel  */
ab8500_charger_get_usb_current(struct ab8500_charger * di)5598c0984e5SSebastian Reichel static int ab8500_charger_get_usb_current(struct ab8500_charger *di)
5608c0984e5SSebastian Reichel {
56197ab78baSLinus Walleij 	int ich, ret;
5628c0984e5SSebastian Reichel 
5638c0984e5SSebastian Reichel 	/* Only measure current if the charger is online */
5648c0984e5SSebastian Reichel 	if (di->usb.charger_online) {
56597ab78baSLinus Walleij 		ret = iio_read_channel_processed(di->adc_usb_charger_c, &ich);
56697ab78baSLinus Walleij 		if (ret < 0)
56797ab78baSLinus Walleij 			dev_err(di->dev, "%s ADC conv failed,\n", __func__);
5688c0984e5SSebastian Reichel 	} else {
5698c0984e5SSebastian Reichel 		ich = 0;
5708c0984e5SSebastian Reichel 	}
57183e5aa77SLinus Walleij 	/* Return microamperes */
57283e5aa77SLinus Walleij 	return ich * 1000;
5738c0984e5SSebastian Reichel }
5748c0984e5SSebastian Reichel 
5758c0984e5SSebastian Reichel /**
5768c0984e5SSebastian Reichel  * ab8500_charger_get_ac_current() - get ac charger current
5778c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5788c0984e5SSebastian Reichel  *
5798c0984e5SSebastian Reichel  * This function returns the ac charger current.
58083e5aa77SLinus Walleij  * Returns ac current in microamperes (on success) and error code on failure.
5818c0984e5SSebastian Reichel  */
ab8500_charger_get_ac_current(struct ab8500_charger * di)5828c0984e5SSebastian Reichel static int ab8500_charger_get_ac_current(struct ab8500_charger *di)
5838c0984e5SSebastian Reichel {
58497ab78baSLinus Walleij 	int ich, ret;
5858c0984e5SSebastian Reichel 
5868c0984e5SSebastian Reichel 	/* Only measure current if the charger is online */
5878c0984e5SSebastian Reichel 	if (di->ac.charger_online) {
58897ab78baSLinus Walleij 		ret = iio_read_channel_processed(di->adc_main_charger_c, &ich);
58997ab78baSLinus Walleij 		if (ret < 0)
59097ab78baSLinus Walleij 			dev_err(di->dev, "%s ADC conv failed,\n", __func__);
5918c0984e5SSebastian Reichel 	} else {
5928c0984e5SSebastian Reichel 		ich = 0;
5938c0984e5SSebastian Reichel 	}
59483e5aa77SLinus Walleij 	/* Return microamperes */
59583e5aa77SLinus Walleij 	return ich * 1000;
5968c0984e5SSebastian Reichel }
5978c0984e5SSebastian Reichel 
5988c0984e5SSebastian Reichel /**
5998c0984e5SSebastian Reichel  * ab8500_charger_usb_cv() - check if the usb charger is in CV mode
6008c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
6018c0984e5SSebastian Reichel  *
6028c0984e5SSebastian Reichel  * Returns ac charger CV mode (on success) else error code
6038c0984e5SSebastian Reichel  */
ab8500_charger_usb_cv(struct ab8500_charger * di)6048c0984e5SSebastian Reichel static int ab8500_charger_usb_cv(struct ab8500_charger *di)
6058c0984e5SSebastian Reichel {
6068c0984e5SSebastian Reichel 	int ret;
6078c0984e5SSebastian Reichel 	u8 val;
6088c0984e5SSebastian Reichel 
6098c0984e5SSebastian Reichel 	/* Only check CV mode if the charger is online */
6108c0984e5SSebastian Reichel 	if (di->usb.charger_online) {
6118c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
6128c0984e5SSebastian Reichel 			AB8500_CH_USBCH_STAT1_REG, &val);
6138c0984e5SSebastian Reichel 		if (ret < 0) {
6148c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
6158c0984e5SSebastian Reichel 			return 0;
6168c0984e5SSebastian Reichel 		}
6178c0984e5SSebastian Reichel 
6188c0984e5SSebastian Reichel 		if (val & USB_CH_CV_ON)
6198c0984e5SSebastian Reichel 			ret = 1;
6208c0984e5SSebastian Reichel 		else
6218c0984e5SSebastian Reichel 			ret = 0;
6228c0984e5SSebastian Reichel 	} else {
6238c0984e5SSebastian Reichel 		ret = 0;
6248c0984e5SSebastian Reichel 	}
6258c0984e5SSebastian Reichel 
6268c0984e5SSebastian Reichel 	return ret;
6278c0984e5SSebastian Reichel }
6288c0984e5SSebastian Reichel 
6298c0984e5SSebastian Reichel /**
6308c0984e5SSebastian Reichel  * ab8500_charger_detect_chargers() - Detect the connected chargers
6318c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
6328c0984e5SSebastian Reichel  * @probe:	if probe, don't delay and wait for HW
6338c0984e5SSebastian Reichel  *
6348c0984e5SSebastian Reichel  * Returns the type of charger connected.
6358c0984e5SSebastian Reichel  * For USB it will not mean we can actually charge from it
6368c0984e5SSebastian Reichel  * but that there is a USB cable connected that we have to
6378c0984e5SSebastian Reichel  * identify. This is used during startup when we don't get
6388c0984e5SSebastian Reichel  * interrupts of the charger detection
6398c0984e5SSebastian Reichel  *
6408c0984e5SSebastian Reichel  * Returns an integer value, that means,
6418c0984e5SSebastian Reichel  * NO_PW_CONN  no power supply is connected
6428c0984e5SSebastian Reichel  * AC_PW_CONN  if the AC power supply is connected
6438c0984e5SSebastian Reichel  * USB_PW_CONN  if the USB power supply is connected
6448c0984e5SSebastian Reichel  * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected
6458c0984e5SSebastian Reichel  */
ab8500_charger_detect_chargers(struct ab8500_charger * di,bool probe)6468c0984e5SSebastian Reichel static int ab8500_charger_detect_chargers(struct ab8500_charger *di, bool probe)
6478c0984e5SSebastian Reichel {
6488c0984e5SSebastian Reichel 	int result = NO_PW_CONN;
6498c0984e5SSebastian Reichel 	int ret;
6508c0984e5SSebastian Reichel 	u8 val;
6518c0984e5SSebastian Reichel 
6528c0984e5SSebastian Reichel 	/* Check for AC charger */
6538c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
6548c0984e5SSebastian Reichel 		AB8500_CH_STATUS1_REG, &val);
6558c0984e5SSebastian Reichel 	if (ret < 0) {
6568c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
6578c0984e5SSebastian Reichel 		return ret;
6588c0984e5SSebastian Reichel 	}
6598c0984e5SSebastian Reichel 
6608c0984e5SSebastian Reichel 	if (val & MAIN_CH_DET)
6618c0984e5SSebastian Reichel 		result = AC_PW_CONN;
6628c0984e5SSebastian Reichel 
6638c0984e5SSebastian Reichel 	/* Check for USB charger */
6648c0984e5SSebastian Reichel 
6658c0984e5SSebastian Reichel 	if (!probe) {
6668c0984e5SSebastian Reichel 		/*
6678c0984e5SSebastian Reichel 		 * AB8500 says VBUS_DET_DBNC1 & VBUS_DET_DBNC100
6688c0984e5SSebastian Reichel 		 * when disconnecting ACA even though no
6698c0984e5SSebastian Reichel 		 * charger was connected. Try waiting a little
6708c0984e5SSebastian Reichel 		 * longer than the 100 ms of VBUS_DET_DBNC100...
6718c0984e5SSebastian Reichel 		 */
6728c0984e5SSebastian Reichel 		msleep(110);
6738c0984e5SSebastian Reichel 	}
6748c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
6758c0984e5SSebastian Reichel 		AB8500_CH_USBCH_STAT1_REG, &val);
6768c0984e5SSebastian Reichel 	if (ret < 0) {
6778c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
6788c0984e5SSebastian Reichel 		return ret;
6798c0984e5SSebastian Reichel 	}
6808c0984e5SSebastian Reichel 	dev_dbg(di->dev,
6818c0984e5SSebastian Reichel 		"%s AB8500_CH_USBCH_STAT1_REG %x\n", __func__,
6828c0984e5SSebastian Reichel 		val);
6838c0984e5SSebastian Reichel 	if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100))
6848c0984e5SSebastian Reichel 		result |= USB_PW_CONN;
6858c0984e5SSebastian Reichel 
6868c0984e5SSebastian Reichel 	return result;
6878c0984e5SSebastian Reichel }
6888c0984e5SSebastian Reichel 
6898c0984e5SSebastian Reichel /**
6908c0984e5SSebastian Reichel  * ab8500_charger_max_usb_curr() - get the max curr for the USB type
6918c0984e5SSebastian Reichel  * @di:			pointer to the ab8500_charger structure
6928c0984e5SSebastian Reichel  * @link_status:	the identified USB type
6938c0984e5SSebastian Reichel  *
6948c0984e5SSebastian Reichel  * Get the maximum current that is allowed to be drawn from the host
6958c0984e5SSebastian Reichel  * based on the USB type.
6968c0984e5SSebastian Reichel  * Returns error code in case of failure else 0 on success
6978c0984e5SSebastian Reichel  */
ab8500_charger_max_usb_curr(struct ab8500_charger * di,enum ab8500_charger_link_status link_status)6988c0984e5SSebastian Reichel static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
6998c0984e5SSebastian Reichel 		enum ab8500_charger_link_status link_status)
7008c0984e5SSebastian Reichel {
7018c0984e5SSebastian Reichel 	int ret = 0;
7028c0984e5SSebastian Reichel 
7038c0984e5SSebastian Reichel 	di->usb_device_is_unrecognised = false;
7048c0984e5SSebastian Reichel 
7058c0984e5SSebastian Reichel 	/*
7068c0984e5SSebastian Reichel 	 * Platform only supports USB 2.0.
7078c0984e5SSebastian Reichel 	 * This means that charging current from USB source
708ddb74e98SAshish Chavan 	 * is maximum 500 mA. Every occurrence of USB_STAT_*_HOST_*
7098c0984e5SSebastian Reichel 	 * should set USB_CH_IP_CUR_LVL_0P5.
7108c0984e5SSebastian Reichel 	 */
7118c0984e5SSebastian Reichel 
7128c0984e5SSebastian Reichel 	switch (link_status) {
7138c0984e5SSebastian Reichel 	case USB_STAT_STD_HOST_NC:
7148c0984e5SSebastian Reichel 	case USB_STAT_STD_HOST_C_NS:
7158c0984e5SSebastian Reichel 	case USB_STAT_STD_HOST_C_S:
7168c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB Type - Standard host is "
7178c0984e5SSebastian Reichel 			"detected through USB driver\n");
71883e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7198c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7208c0984e5SSebastian Reichel 		break;
7218c0984e5SSebastian Reichel 	case USB_STAT_HOST_CHG_HS_CHIRP:
72283e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7238c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7248c0984e5SSebastian Reichel 		break;
7258c0984e5SSebastian Reichel 	case USB_STAT_HOST_CHG_HS:
72683e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7278c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7288c0984e5SSebastian Reichel 		break;
7298c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_C_HS:
73083e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P9;
7318c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7328c0984e5SSebastian Reichel 		break;
7338c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_A:
7348c0984e5SSebastian Reichel 		/*
7358c0984e5SSebastian Reichel 		 * Dedicated charger level minus maximum current accessory
7368c0984e5SSebastian Reichel 		 * can consume (900mA). Closest level is 500mA
7378c0984e5SSebastian Reichel 		 */
7388c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n");
73983e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7408c0984e5SSebastian Reichel 		di->is_aca_rid = 1;
7418c0984e5SSebastian Reichel 		break;
7428c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_B:
7438c0984e5SSebastian Reichel 		/*
7448c0984e5SSebastian Reichel 		 * Dedicated charger level minus 120mA (20mA for ACA and
7458c0984e5SSebastian Reichel 		 * 100mA for potential accessory). Closest level is 1300mA
7468c0984e5SSebastian Reichel 		 */
74783e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_1P3;
7488c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
74983e5aa77SLinus Walleij 				di->max_usb_in_curr.usb_type_max_ua);
7508c0984e5SSebastian Reichel 		di->is_aca_rid = 1;
7518c0984e5SSebastian Reichel 		break;
7528c0984e5SSebastian Reichel 	case USB_STAT_HOST_CHG_NM:
75383e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7548c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7558c0984e5SSebastian Reichel 		break;
7568c0984e5SSebastian Reichel 	case USB_STAT_DEDICATED_CHG:
75783e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_1P5;
7588c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7598c0984e5SSebastian Reichel 		break;
7608c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_C_HS_CHIRP:
7618c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_C_NM:
76283e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_1P5;
7638c0984e5SSebastian Reichel 		di->is_aca_rid = 1;
7648c0984e5SSebastian Reichel 		break;
7658c0984e5SSebastian Reichel 	case USB_STAT_NOT_CONFIGURED:
7668c0984e5SSebastian Reichel 		if (di->vbus_detected) {
7678c0984e5SSebastian Reichel 			di->usb_device_is_unrecognised = true;
7688c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB Type - Legacy charger.\n");
76983e5aa77SLinus Walleij 			di->max_usb_in_curr.usb_type_max_ua =
7708c0984e5SSebastian Reichel 						USB_CH_IP_CUR_LVL_1P5;
7718c0984e5SSebastian Reichel 			break;
7728c0984e5SSebastian Reichel 		}
773df561f66SGustavo A. R. Silva 		fallthrough;
7748c0984e5SSebastian Reichel 	case USB_STAT_HM_IDGND:
7758c0984e5SSebastian Reichel 		dev_err(di->dev, "USB Type - Charging not allowed\n");
77683e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P05;
7778c0984e5SSebastian Reichel 		ret = -ENXIO;
7788c0984e5SSebastian Reichel 		break;
7798c0984e5SSebastian Reichel 	case USB_STAT_RESERVED:
7808c0984e5SSebastian Reichel 		if (is_ab8500(di->parent)) {
7818c0984e5SSebastian Reichel 			di->flags.vbus_collapse = true;
7828c0984e5SSebastian Reichel 			dev_err(di->dev, "USB Type - USB_STAT_RESERVED "
7838c0984e5SSebastian Reichel 						"VBUS has collapsed\n");
7848c0984e5SSebastian Reichel 			ret = -ENXIO;
7858c0984e5SSebastian Reichel 			break;
7868c0984e5SSebastian Reichel 		} else {
7878c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB Type - Charging not allowed\n");
78883e5aa77SLinus Walleij 			di->max_usb_in_curr.usb_type_max_ua =
7898c0984e5SSebastian Reichel 						USB_CH_IP_CUR_LVL_0P05;
7908c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
7918c0984e5SSebastian Reichel 				link_status,
79283e5aa77SLinus Walleij 				di->max_usb_in_curr.usb_type_max_ua);
7938c0984e5SSebastian Reichel 			ret = -ENXIO;
7948c0984e5SSebastian Reichel 			break;
7958c0984e5SSebastian Reichel 		}
7968c0984e5SSebastian Reichel 	case USB_STAT_CARKIT_1:
7978c0984e5SSebastian Reichel 	case USB_STAT_CARKIT_2:
7988c0984e5SSebastian Reichel 	case USB_STAT_ACA_DOCK_CHARGER:
7998c0984e5SSebastian Reichel 	case USB_STAT_CHARGER_LINE_1:
80083e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
8018c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
80283e5aa77SLinus Walleij 				di->max_usb_in_curr.usb_type_max_ua);
8038c0984e5SSebastian Reichel 		break;
8048c0984e5SSebastian Reichel 	case USB_STAT_NOT_VALID_LINK:
8058c0984e5SSebastian Reichel 		dev_err(di->dev, "USB Type invalid - try charging anyway\n");
80683e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
8078c0984e5SSebastian Reichel 		break;
8088c0984e5SSebastian Reichel 
8098c0984e5SSebastian Reichel 	default:
8108c0984e5SSebastian Reichel 		dev_err(di->dev, "USB Type - Unknown\n");
81183e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P05;
8128c0984e5SSebastian Reichel 		ret = -ENXIO;
8138c0984e5SSebastian Reichel 		break;
814e15c54d2SMa Feng 	}
8158c0984e5SSebastian Reichel 
81683e5aa77SLinus Walleij 	di->max_usb_in_curr.set_max_ua = di->max_usb_in_curr.usb_type_max_ua;
8178c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
81883e5aa77SLinus Walleij 		link_status, di->max_usb_in_curr.set_max_ua);
8198c0984e5SSebastian Reichel 
8208c0984e5SSebastian Reichel 	return ret;
8218c0984e5SSebastian Reichel }
8228c0984e5SSebastian Reichel 
8238c0984e5SSebastian Reichel /**
8248c0984e5SSebastian Reichel  * ab8500_charger_read_usb_type() - read the type of usb connected
8258c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
8268c0984e5SSebastian Reichel  *
8278c0984e5SSebastian Reichel  * Detect the type of the plugged USB
8288c0984e5SSebastian Reichel  * Returns error code in case of failure else 0 on success
8298c0984e5SSebastian Reichel  */
ab8500_charger_read_usb_type(struct ab8500_charger * di)8308c0984e5SSebastian Reichel static int ab8500_charger_read_usb_type(struct ab8500_charger *di)
8318c0984e5SSebastian Reichel {
8328c0984e5SSebastian Reichel 	int ret;
8338c0984e5SSebastian Reichel 	u8 val;
8348c0984e5SSebastian Reichel 
8358c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
8368c0984e5SSebastian Reichel 		AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val);
8378c0984e5SSebastian Reichel 	if (ret < 0) {
8388c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
8398c0984e5SSebastian Reichel 		return ret;
8408c0984e5SSebastian Reichel 	}
8418c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
8428c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
8438c0984e5SSebastian Reichel 			AB8500_USB_LINE_STAT_REG, &val);
8448c0984e5SSebastian Reichel 	else
8458c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
8468c0984e5SSebastian Reichel 			AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
8478c0984e5SSebastian Reichel 	if (ret < 0) {
8488c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
8498c0984e5SSebastian Reichel 		return ret;
8508c0984e5SSebastian Reichel 	}
8518c0984e5SSebastian Reichel 
8528c0984e5SSebastian Reichel 	/* get the USB type */
8538c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
8548c0984e5SSebastian Reichel 		val = (val & AB8500_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
8558c0984e5SSebastian Reichel 	else
8568c0984e5SSebastian Reichel 		val = (val & AB8505_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
8578c0984e5SSebastian Reichel 	ret = ab8500_charger_max_usb_curr(di,
8588c0984e5SSebastian Reichel 		(enum ab8500_charger_link_status) val);
8598c0984e5SSebastian Reichel 
8608c0984e5SSebastian Reichel 	return ret;
8618c0984e5SSebastian Reichel }
8628c0984e5SSebastian Reichel 
8638c0984e5SSebastian Reichel /**
8648c0984e5SSebastian Reichel  * ab8500_charger_detect_usb_type() - get the type of usb connected
8658c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
8668c0984e5SSebastian Reichel  *
8678c0984e5SSebastian Reichel  * Detect the type of the plugged USB
8688c0984e5SSebastian Reichel  * Returns error code in case of failure else 0 on success
8698c0984e5SSebastian Reichel  */
ab8500_charger_detect_usb_type(struct ab8500_charger * di)8708c0984e5SSebastian Reichel static int ab8500_charger_detect_usb_type(struct ab8500_charger *di)
8718c0984e5SSebastian Reichel {
8728c0984e5SSebastian Reichel 	int i, ret;
8738c0984e5SSebastian Reichel 	u8 val;
8748c0984e5SSebastian Reichel 
8758c0984e5SSebastian Reichel 	/*
8768c0984e5SSebastian Reichel 	 * On getting the VBUS rising edge detect interrupt there
8778c0984e5SSebastian Reichel 	 * is a 250ms delay after which the register UsbLineStatus
8788c0984e5SSebastian Reichel 	 * is filled with valid data.
8798c0984e5SSebastian Reichel 	 */
8808c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
8818c0984e5SSebastian Reichel 		msleep(250);
8828c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
8838c0984e5SSebastian Reichel 			AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG,
8848c0984e5SSebastian Reichel 			&val);
8858c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s AB8500_IT_SOURCE21_REG %x\n",
8868c0984e5SSebastian Reichel 			__func__, val);
8878c0984e5SSebastian Reichel 		if (ret < 0) {
8888c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
8898c0984e5SSebastian Reichel 			return ret;
8908c0984e5SSebastian Reichel 		}
8918c0984e5SSebastian Reichel 
8928c0984e5SSebastian Reichel 		if (is_ab8500(di->parent))
8938c0984e5SSebastian Reichel 			ret = abx500_get_register_interruptible(di->dev,
8948c0984e5SSebastian Reichel 				AB8500_USB, AB8500_USB_LINE_STAT_REG, &val);
8958c0984e5SSebastian Reichel 		else
8968c0984e5SSebastian Reichel 			ret = abx500_get_register_interruptible(di->dev,
8978c0984e5SSebastian Reichel 				AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
8988c0984e5SSebastian Reichel 		if (ret < 0) {
8998c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
9008c0984e5SSebastian Reichel 			return ret;
9018c0984e5SSebastian Reichel 		}
9028c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s AB8500_USB_LINE_STAT_REG %x\n", __func__,
9038c0984e5SSebastian Reichel 			val);
9048c0984e5SSebastian Reichel 		/*
9058c0984e5SSebastian Reichel 		 * Until the IT source register is read the UsbLineStatus
9068c0984e5SSebastian Reichel 		 * register is not updated, hence doing the same
9078c0984e5SSebastian Reichel 		 * Revisit this:
9088c0984e5SSebastian Reichel 		 */
9098c0984e5SSebastian Reichel 
9108c0984e5SSebastian Reichel 		/* get the USB type */
9118c0984e5SSebastian Reichel 		if (is_ab8500(di->parent))
9128c0984e5SSebastian Reichel 			val = (val & AB8500_USB_LINK_STATUS) >>
9138c0984e5SSebastian Reichel 							USB_LINK_STATUS_SHIFT;
9148c0984e5SSebastian Reichel 		else
9158c0984e5SSebastian Reichel 			val = (val & AB8505_USB_LINK_STATUS) >>
9168c0984e5SSebastian Reichel 							USB_LINK_STATUS_SHIFT;
9178c0984e5SSebastian Reichel 		if (val)
9188c0984e5SSebastian Reichel 			break;
9198c0984e5SSebastian Reichel 	}
9208c0984e5SSebastian Reichel 	ret = ab8500_charger_max_usb_curr(di,
9218c0984e5SSebastian Reichel 		(enum ab8500_charger_link_status) val);
9228c0984e5SSebastian Reichel 
9238c0984e5SSebastian Reichel 	return ret;
9248c0984e5SSebastian Reichel }
9258c0984e5SSebastian Reichel 
9268c0984e5SSebastian Reichel /*
9278c0984e5SSebastian Reichel  * This array maps the raw hex value to charger voltage used by the AB8500
928bc6e0287SLinus Walleij  * Values taken from the UM0836, in microvolt.
9298c0984e5SSebastian Reichel  */
9308c0984e5SSebastian Reichel static int ab8500_charger_voltage_map[] = {
931bc6e0287SLinus Walleij 	3500000,
932bc6e0287SLinus Walleij 	3525000,
933bc6e0287SLinus Walleij 	3550000,
934bc6e0287SLinus Walleij 	3575000,
935bc6e0287SLinus Walleij 	3600000,
936bc6e0287SLinus Walleij 	3625000,
937bc6e0287SLinus Walleij 	3650000,
938bc6e0287SLinus Walleij 	3675000,
939bc6e0287SLinus Walleij 	3700000,
940bc6e0287SLinus Walleij 	3725000,
941bc6e0287SLinus Walleij 	3750000,
942bc6e0287SLinus Walleij 	3775000,
943bc6e0287SLinus Walleij 	3800000,
944bc6e0287SLinus Walleij 	3825000,
945bc6e0287SLinus Walleij 	3850000,
946bc6e0287SLinus Walleij 	3875000,
947bc6e0287SLinus Walleij 	3900000,
948bc6e0287SLinus Walleij 	3925000,
949bc6e0287SLinus Walleij 	3950000,
950bc6e0287SLinus Walleij 	3975000,
951bc6e0287SLinus Walleij 	4000000,
952bc6e0287SLinus Walleij 	4025000,
953bc6e0287SLinus Walleij 	4050000,
954bc6e0287SLinus Walleij 	4060000,
955bc6e0287SLinus Walleij 	4070000,
956bc6e0287SLinus Walleij 	4080000,
957bc6e0287SLinus Walleij 	4090000,
958bc6e0287SLinus Walleij 	4100000,
959bc6e0287SLinus Walleij 	4110000,
960bc6e0287SLinus Walleij 	4120000,
961bc6e0287SLinus Walleij 	4130000,
962bc6e0287SLinus Walleij 	4140000,
963bc6e0287SLinus Walleij 	4150000,
964bc6e0287SLinus Walleij 	4160000,
965bc6e0287SLinus Walleij 	4170000,
966bc6e0287SLinus Walleij 	4180000,
967bc6e0287SLinus Walleij 	4190000,
968bc6e0287SLinus Walleij 	4200000,
969bc6e0287SLinus Walleij 	4210000,
970bc6e0287SLinus Walleij 	4220000,
971bc6e0287SLinus Walleij 	4230000,
972bc6e0287SLinus Walleij 	4240000,
973bc6e0287SLinus Walleij 	4250000,
974bc6e0287SLinus Walleij 	4260000,
975bc6e0287SLinus Walleij 	4270000,
976bc6e0287SLinus Walleij 	4280000,
977bc6e0287SLinus Walleij 	4290000,
978bc6e0287SLinus Walleij 	4300000,
979bc6e0287SLinus Walleij 	4310000,
980bc6e0287SLinus Walleij 	4320000,
981bc6e0287SLinus Walleij 	4330000,
982bc6e0287SLinus Walleij 	4340000,
983bc6e0287SLinus Walleij 	4350000,
984bc6e0287SLinus Walleij 	4360000,
985bc6e0287SLinus Walleij 	4370000,
986bc6e0287SLinus Walleij 	4380000,
987bc6e0287SLinus Walleij 	4390000,
988bc6e0287SLinus Walleij 	4400000,
989bc6e0287SLinus Walleij 	4410000,
990bc6e0287SLinus Walleij 	4420000,
991bc6e0287SLinus Walleij 	4430000,
992bc6e0287SLinus Walleij 	4440000,
993bc6e0287SLinus Walleij 	4450000,
994bc6e0287SLinus Walleij 	4460000,
995bc6e0287SLinus Walleij 	4470000,
996bc6e0287SLinus Walleij 	4480000,
997bc6e0287SLinus Walleij 	4490000,
998bc6e0287SLinus Walleij 	4500000,
999bc6e0287SLinus Walleij 	4510000,
1000bc6e0287SLinus Walleij 	4520000,
1001bc6e0287SLinus Walleij 	4530000,
1002bc6e0287SLinus Walleij 	4540000,
1003bc6e0287SLinus Walleij 	4550000,
1004bc6e0287SLinus Walleij 	4560000,
1005bc6e0287SLinus Walleij 	4570000,
1006bc6e0287SLinus Walleij 	4580000,
1007bc6e0287SLinus Walleij 	4590000,
1008bc6e0287SLinus Walleij 	4600000,
10098c0984e5SSebastian Reichel };
10108c0984e5SSebastian Reichel 
ab8500_voltage_to_regval(int voltage_uv)1011bc6e0287SLinus Walleij static int ab8500_voltage_to_regval(int voltage_uv)
10128c0984e5SSebastian Reichel {
10138c0984e5SSebastian Reichel 	int i;
10148c0984e5SSebastian Reichel 
10158c0984e5SSebastian Reichel 	/* Special case for voltage below 3.5V */
1016bc6e0287SLinus Walleij 	if (voltage_uv < ab8500_charger_voltage_map[0])
10178c0984e5SSebastian Reichel 		return LOW_VOLT_REG;
10188c0984e5SSebastian Reichel 
10198c0984e5SSebastian Reichel 	for (i = 1; i < ARRAY_SIZE(ab8500_charger_voltage_map); i++) {
1020bc6e0287SLinus Walleij 		if (voltage_uv < ab8500_charger_voltage_map[i])
10218c0984e5SSebastian Reichel 			return i - 1;
10228c0984e5SSebastian Reichel 	}
10238c0984e5SSebastian Reichel 
10248c0984e5SSebastian Reichel 	/* If not last element, return error */
10258c0984e5SSebastian Reichel 	i = ARRAY_SIZE(ab8500_charger_voltage_map) - 1;
1026bc6e0287SLinus Walleij 	if (voltage_uv == ab8500_charger_voltage_map[i])
10278c0984e5SSebastian Reichel 		return i;
10288c0984e5SSebastian Reichel 	else
10298c0984e5SSebastian Reichel 		return -1;
10308c0984e5SSebastian Reichel }
10318c0984e5SSebastian Reichel 
10323aca6ecdSLinus Walleij /* This array maps the raw register value to charger input current */
10333aca6ecdSLinus Walleij static int ab8500_charge_input_curr_map[] = {
103483e5aa77SLinus Walleij 	50000, 98000, 193000, 290000, 380000, 450000, 500000, 600000,
103583e5aa77SLinus Walleij 	700000, 800000, 900000, 1000000, 1100000, 1300000, 1400000, 1500000,
10363aca6ecdSLinus Walleij };
10373aca6ecdSLinus Walleij 
10383aca6ecdSLinus Walleij /* This array maps the raw register value to charger output current */
10393aca6ecdSLinus Walleij static int ab8500_charge_output_curr_map[] = {
104083e5aa77SLinus Walleij 	100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000,
104183e5aa77SLinus Walleij 	900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1500000,
10423aca6ecdSLinus Walleij };
10433aca6ecdSLinus Walleij 
ab8500_current_to_regval(struct ab8500_charger * di,int curr_ua)104483e5aa77SLinus Walleij static int ab8500_current_to_regval(struct ab8500_charger *di, int curr_ua)
10458c0984e5SSebastian Reichel {
10468c0984e5SSebastian Reichel 	int i;
10478c0984e5SSebastian Reichel 
104883e5aa77SLinus Walleij 	if (curr_ua < ab8500_charge_output_curr_map[0])
10498c0984e5SSebastian Reichel 		return 0;
10508c0984e5SSebastian Reichel 
10513aca6ecdSLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charge_output_curr_map); i++) {
105283e5aa77SLinus Walleij 		if (curr_ua < ab8500_charge_output_curr_map[i])
10538c0984e5SSebastian Reichel 			return i - 1;
10548c0984e5SSebastian Reichel 	}
10558c0984e5SSebastian Reichel 
10568c0984e5SSebastian Reichel 	/* If not last element, return error */
10573aca6ecdSLinus Walleij 	i =  ARRAY_SIZE(ab8500_charge_output_curr_map) - 1;
105883e5aa77SLinus Walleij 	if (curr_ua == ab8500_charge_output_curr_map[i])
10598c0984e5SSebastian Reichel 		return i;
10608c0984e5SSebastian Reichel 	else
10618c0984e5SSebastian Reichel 		return -1;
10628c0984e5SSebastian Reichel }
10638c0984e5SSebastian Reichel 
ab8500_vbus_in_curr_to_regval(struct ab8500_charger * di,int curr_ua)106483e5aa77SLinus Walleij static int ab8500_vbus_in_curr_to_regval(struct ab8500_charger *di, int curr_ua)
10658c0984e5SSebastian Reichel {
10668c0984e5SSebastian Reichel 	int i;
10678c0984e5SSebastian Reichel 
106883e5aa77SLinus Walleij 	if (curr_ua < ab8500_charge_input_curr_map[0])
10698c0984e5SSebastian Reichel 		return 0;
10708c0984e5SSebastian Reichel 
10713aca6ecdSLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charge_input_curr_map); i++) {
107283e5aa77SLinus Walleij 		if (curr_ua < ab8500_charge_input_curr_map[i])
10738c0984e5SSebastian Reichel 			return i - 1;
10748c0984e5SSebastian Reichel 	}
10758c0984e5SSebastian Reichel 
10768c0984e5SSebastian Reichel 	/* If not last element, return error */
10773aca6ecdSLinus Walleij 	i =  ARRAY_SIZE(ab8500_charge_input_curr_map) - 1;
107883e5aa77SLinus Walleij 	if (curr_ua == ab8500_charge_input_curr_map[i])
10798c0984e5SSebastian Reichel 		return i;
10808c0984e5SSebastian Reichel 	else
10818c0984e5SSebastian Reichel 		return -1;
10828c0984e5SSebastian Reichel }
10838c0984e5SSebastian Reichel 
10848c0984e5SSebastian Reichel /**
10858c0984e5SSebastian Reichel  * ab8500_charger_get_usb_cur() - get usb current
10868f5b3739SHong Peng  * @di:		pointer to the ab8500_charger structure
10878c0984e5SSebastian Reichel  *
10888c0984e5SSebastian Reichel  * The usb stack provides the maximum current that can be drawn from
108983e5aa77SLinus Walleij  * the standard usb host. This will be in uA.
109083e5aa77SLinus Walleij  * This function converts current in uA to a value that can be written
10918c0984e5SSebastian Reichel  * to the register. Returns -1 if charging is not allowed
10928c0984e5SSebastian Reichel  */
ab8500_charger_get_usb_cur(struct ab8500_charger * di)10938c0984e5SSebastian Reichel static int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
10948c0984e5SSebastian Reichel {
10958c0984e5SSebastian Reichel 	int ret = 0;
109683e5aa77SLinus Walleij 	switch (di->usb_state.usb_current_ua) {
109783e5aa77SLinus Walleij 	case 100000:
109883e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P09;
10998c0984e5SSebastian Reichel 		break;
110083e5aa77SLinus Walleij 	case 200000:
110183e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P19;
11028c0984e5SSebastian Reichel 		break;
110383e5aa77SLinus Walleij 	case 300000:
110483e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P29;
11058c0984e5SSebastian Reichel 		break;
110683e5aa77SLinus Walleij 	case 400000:
110783e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P38;
11088c0984e5SSebastian Reichel 		break;
110983e5aa77SLinus Walleij 	case 500000:
111083e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
11118c0984e5SSebastian Reichel 		break;
11128c0984e5SSebastian Reichel 	default:
111383e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P05;
11148c0984e5SSebastian Reichel 		ret = -EPERM;
11158c0984e5SSebastian Reichel 		break;
1116e15c54d2SMa Feng 	}
111783e5aa77SLinus Walleij 	di->max_usb_in_curr.set_max_ua = di->max_usb_in_curr.usb_type_max_ua;
11188c0984e5SSebastian Reichel 	return ret;
11198c0984e5SSebastian Reichel }
11208c0984e5SSebastian Reichel 
11218c0984e5SSebastian Reichel /**
11228c0984e5SSebastian Reichel  * ab8500_charger_check_continue_stepping() - Check to allow stepping
11238c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
11248c0984e5SSebastian Reichel  * @reg:	select what charger register to check
11258c0984e5SSebastian Reichel  *
11268c0984e5SSebastian Reichel  * Check if current stepping should be allowed to continue.
11278c0984e5SSebastian Reichel  * Checks if charger source has not collapsed. If it has, further stepping
11288c0984e5SSebastian Reichel  * is not allowed.
11298c0984e5SSebastian Reichel  */
ab8500_charger_check_continue_stepping(struct ab8500_charger * di,int reg)11308c0984e5SSebastian Reichel static bool ab8500_charger_check_continue_stepping(struct ab8500_charger *di,
11318c0984e5SSebastian Reichel 						   int reg)
11328c0984e5SSebastian Reichel {
11338c0984e5SSebastian Reichel 	if (reg == AB8500_USBCH_IPT_CRNTLVL_REG)
11348c0984e5SSebastian Reichel 		return !di->flags.vbus_drop_end;
11358c0984e5SSebastian Reichel 	else
11368c0984e5SSebastian Reichel 		return true;
11378c0984e5SSebastian Reichel }
11388c0984e5SSebastian Reichel 
11398c0984e5SSebastian Reichel /**
11408c0984e5SSebastian Reichel  * ab8500_charger_set_current() - set charger current
11418c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
114283e5aa77SLinus Walleij  * @ich_ua:	charger current, in uA
11438c0984e5SSebastian Reichel  * @reg:	select what charger register to set
11448c0984e5SSebastian Reichel  *
11458c0984e5SSebastian Reichel  * Set charger current.
11468c0984e5SSebastian Reichel  * There is no state machine in the AB to step up/down the charger
11478c0984e5SSebastian Reichel  * current to avoid dips and spikes on MAIN, VBUS and VBAT when
11488c0984e5SSebastian Reichel  * charging is started. Instead we need to implement
11498c0984e5SSebastian Reichel  * this charger current step-up/down here.
11508c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
11518c0984e5SSebastian Reichel  */
ab8500_charger_set_current(struct ab8500_charger * di,int ich_ua,int reg)11528c0984e5SSebastian Reichel static int ab8500_charger_set_current(struct ab8500_charger *di,
115383e5aa77SLinus Walleij 	int ich_ua, int reg)
11548c0984e5SSebastian Reichel {
11558c0984e5SSebastian Reichel 	int ret = 0;
11568c0984e5SSebastian Reichel 	int curr_index, prev_curr_index, shift_value, i;
11578c0984e5SSebastian Reichel 	u8 reg_value;
11588c0984e5SSebastian Reichel 	u32 step_udelay;
11598c0984e5SSebastian Reichel 	bool no_stepping = false;
11608c0984e5SSebastian Reichel 
11618c0984e5SSebastian Reichel 	atomic_inc(&di->current_stepping_sessions);
11628c0984e5SSebastian Reichel 
11638c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
11648c0984e5SSebastian Reichel 		reg, &reg_value);
11658c0984e5SSebastian Reichel 	if (ret < 0) {
11668c0984e5SSebastian Reichel 		dev_err(di->dev, "%s read failed\n", __func__);
11678c0984e5SSebastian Reichel 		goto exit_set_current;
11688c0984e5SSebastian Reichel 	}
11698c0984e5SSebastian Reichel 
11708c0984e5SSebastian Reichel 	switch (reg) {
11718c0984e5SSebastian Reichel 	case AB8500_MCH_IPT_CURLVL_REG:
11728c0984e5SSebastian Reichel 		shift_value = MAIN_CH_INPUT_CURR_SHIFT;
11738c0984e5SSebastian Reichel 		prev_curr_index = (reg_value >> shift_value);
117483e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, ich_ua);
11758c0984e5SSebastian Reichel 		step_udelay = STEP_UDELAY;
11768c0984e5SSebastian Reichel 		if (!di->ac.charger_connected)
11778c0984e5SSebastian Reichel 			no_stepping = true;
11788c0984e5SSebastian Reichel 		break;
11798c0984e5SSebastian Reichel 	case AB8500_USBCH_IPT_CRNTLVL_REG:
11808c0984e5SSebastian Reichel 		shift_value = VBUS_IN_CURR_LIM_SHIFT;
11818c0984e5SSebastian Reichel 		prev_curr_index = (reg_value >> shift_value);
118283e5aa77SLinus Walleij 		curr_index = ab8500_vbus_in_curr_to_regval(di, ich_ua);
11838c0984e5SSebastian Reichel 		step_udelay = STEP_UDELAY * 100;
11848c0984e5SSebastian Reichel 
11858c0984e5SSebastian Reichel 		if (!di->usb.charger_connected)
11868c0984e5SSebastian Reichel 			no_stepping = true;
11878c0984e5SSebastian Reichel 		break;
11888c0984e5SSebastian Reichel 	case AB8500_CH_OPT_CRNTLVL_REG:
11898c0984e5SSebastian Reichel 		shift_value = 0;
11908c0984e5SSebastian Reichel 		prev_curr_index = (reg_value >> shift_value);
119183e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, ich_ua);
11928c0984e5SSebastian Reichel 		step_udelay = STEP_UDELAY;
11938c0984e5SSebastian Reichel 		if (curr_index && (curr_index - prev_curr_index) > 1)
11948c0984e5SSebastian Reichel 			step_udelay *= 100;
11958c0984e5SSebastian Reichel 
11968c0984e5SSebastian Reichel 		if (!di->usb.charger_connected && !di->ac.charger_connected)
11978c0984e5SSebastian Reichel 			no_stepping = true;
11988c0984e5SSebastian Reichel 
11998c0984e5SSebastian Reichel 		break;
12008c0984e5SSebastian Reichel 	default:
12018c0984e5SSebastian Reichel 		dev_err(di->dev, "%s current register not valid\n", __func__);
12028c0984e5SSebastian Reichel 		ret = -ENXIO;
12038c0984e5SSebastian Reichel 		goto exit_set_current;
12048c0984e5SSebastian Reichel 	}
12058c0984e5SSebastian Reichel 
12068c0984e5SSebastian Reichel 	if (curr_index < 0) {
12078c0984e5SSebastian Reichel 		dev_err(di->dev, "requested current limit out-of-range\n");
12088c0984e5SSebastian Reichel 		ret = -ENXIO;
12098c0984e5SSebastian Reichel 		goto exit_set_current;
12108c0984e5SSebastian Reichel 	}
12118c0984e5SSebastian Reichel 
12128c0984e5SSebastian Reichel 	/* only update current if it's been changed */
12138c0984e5SSebastian Reichel 	if (prev_curr_index == curr_index) {
12148c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s current not changed for reg: 0x%02x\n",
12158c0984e5SSebastian Reichel 			__func__, reg);
12168c0984e5SSebastian Reichel 		ret = 0;
12178c0984e5SSebastian Reichel 		goto exit_set_current;
12188c0984e5SSebastian Reichel 	}
12198c0984e5SSebastian Reichel 
122083e5aa77SLinus Walleij 	dev_dbg(di->dev, "%s set charger current: %d uA for reg: 0x%02x\n",
122183e5aa77SLinus Walleij 		__func__, ich_ua, reg);
12228c0984e5SSebastian Reichel 
12238c0984e5SSebastian Reichel 	if (no_stepping) {
12248c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
12258c0984e5SSebastian Reichel 					reg, (u8)curr_index << shift_value);
12268c0984e5SSebastian Reichel 		if (ret)
12278c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
12288c0984e5SSebastian Reichel 	} else if (prev_curr_index > curr_index) {
12298c0984e5SSebastian Reichel 		for (i = prev_curr_index - 1; i >= curr_index; i--) {
12308c0984e5SSebastian Reichel 			dev_dbg(di->dev, "curr change_1 to: %x for 0x%02x\n",
12318c0984e5SSebastian Reichel 				(u8) i << shift_value, reg);
12328c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
12338c0984e5SSebastian Reichel 				AB8500_CHARGER, reg, (u8)i << shift_value);
12348c0984e5SSebastian Reichel 			if (ret) {
12358c0984e5SSebastian Reichel 				dev_err(di->dev, "%s write failed\n", __func__);
12368c0984e5SSebastian Reichel 				goto exit_set_current;
12378c0984e5SSebastian Reichel 			}
12388c0984e5SSebastian Reichel 			if (i != curr_index)
12398c0984e5SSebastian Reichel 				usleep_range(step_udelay, step_udelay * 2);
12408c0984e5SSebastian Reichel 		}
12418c0984e5SSebastian Reichel 	} else {
12428c0984e5SSebastian Reichel 		bool allow = true;
12438c0984e5SSebastian Reichel 		for (i = prev_curr_index + 1; i <= curr_index && allow; i++) {
12448c0984e5SSebastian Reichel 			dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n",
12458c0984e5SSebastian Reichel 				(u8)i << shift_value, reg);
12468c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
12478c0984e5SSebastian Reichel 				AB8500_CHARGER, reg, (u8)i << shift_value);
12488c0984e5SSebastian Reichel 			if (ret) {
12498c0984e5SSebastian Reichel 				dev_err(di->dev, "%s write failed\n", __func__);
12508c0984e5SSebastian Reichel 				goto exit_set_current;
12518c0984e5SSebastian Reichel 			}
12528c0984e5SSebastian Reichel 			if (i != curr_index)
12538c0984e5SSebastian Reichel 				usleep_range(step_udelay, step_udelay * 2);
12548c0984e5SSebastian Reichel 
12558c0984e5SSebastian Reichel 			allow = ab8500_charger_check_continue_stepping(di, reg);
12568c0984e5SSebastian Reichel 		}
12578c0984e5SSebastian Reichel 	}
12588c0984e5SSebastian Reichel 
12598c0984e5SSebastian Reichel exit_set_current:
12608c0984e5SSebastian Reichel 	atomic_dec(&di->current_stepping_sessions);
12618c0984e5SSebastian Reichel 
12628c0984e5SSebastian Reichel 	return ret;
12638c0984e5SSebastian Reichel }
12648c0984e5SSebastian Reichel 
12658c0984e5SSebastian Reichel /**
12668c0984e5SSebastian Reichel  * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit
12678c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
126883e5aa77SLinus Walleij  * @ich_in_ua:	charger input current limit in microampere
12698c0984e5SSebastian Reichel  *
12708c0984e5SSebastian Reichel  * Sets the current that can be drawn from the USB host
12718c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
12728c0984e5SSebastian Reichel  */
ab8500_charger_set_vbus_in_curr(struct ab8500_charger * di,int ich_in_ua)12738c0984e5SSebastian Reichel static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
127483e5aa77SLinus Walleij 		int ich_in_ua)
12758c0984e5SSebastian Reichel {
12768c0984e5SSebastian Reichel 	int min_value;
12778c0984e5SSebastian Reichel 	int ret;
12788c0984e5SSebastian Reichel 
12798c0984e5SSebastian Reichel 	/* We should always use to lowest current limit */
128083e5aa77SLinus Walleij 	min_value = min(di->bm->chg_params->usb_curr_max_ua, ich_in_ua);
128183e5aa77SLinus Walleij 	if (di->max_usb_in_curr.set_max_ua > 0)
128283e5aa77SLinus Walleij 		min_value = min(di->max_usb_in_curr.set_max_ua, min_value);
12838c0984e5SSebastian Reichel 
128483e5aa77SLinus Walleij 	if (di->usb_state.usb_current_ua >= 0)
128583e5aa77SLinus Walleij 		min_value = min(di->usb_state.usb_current_ua, min_value);
12868c0984e5SSebastian Reichel 
12878c0984e5SSebastian Reichel 	switch (min_value) {
128883e5aa77SLinus Walleij 	case 100000:
12898c0984e5SSebastian Reichel 		if (di->vbat < VBAT_TRESH_IP_CUR_RED)
12908c0984e5SSebastian Reichel 			min_value = USB_CH_IP_CUR_LVL_0P05;
12918c0984e5SSebastian Reichel 		break;
129283e5aa77SLinus Walleij 	case 500000:
12938c0984e5SSebastian Reichel 		if (di->vbat < VBAT_TRESH_IP_CUR_RED)
12948c0984e5SSebastian Reichel 			min_value = USB_CH_IP_CUR_LVL_0P45;
12958c0984e5SSebastian Reichel 		break;
12968c0984e5SSebastian Reichel 	default:
12978c0984e5SSebastian Reichel 		break;
12988c0984e5SSebastian Reichel 	}
12998c0984e5SSebastian Reichel 
130083e5aa77SLinus Walleij 	dev_info(di->dev, "VBUS input current limit set to %d uA\n", min_value);
13018c0984e5SSebastian Reichel 
13028c0984e5SSebastian Reichel 	mutex_lock(&di->usb_ipt_crnt_lock);
13038c0984e5SSebastian Reichel 	ret = ab8500_charger_set_current(di, min_value,
13048c0984e5SSebastian Reichel 		AB8500_USBCH_IPT_CRNTLVL_REG);
13058c0984e5SSebastian Reichel 	mutex_unlock(&di->usb_ipt_crnt_lock);
13068c0984e5SSebastian Reichel 
13078c0984e5SSebastian Reichel 	return ret;
13088c0984e5SSebastian Reichel }
13098c0984e5SSebastian Reichel 
13108c0984e5SSebastian Reichel /**
13118c0984e5SSebastian Reichel  * ab8500_charger_set_main_in_curr() - set main charger input current
13128c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
131383e5aa77SLinus Walleij  * @ich_in_ua:	input charger current, in uA
13148c0984e5SSebastian Reichel  *
13158c0984e5SSebastian Reichel  * Set main charger input current.
13168c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
13178c0984e5SSebastian Reichel  */
ab8500_charger_set_main_in_curr(struct ab8500_charger * di,int ich_in_ua)13188c0984e5SSebastian Reichel static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di,
131983e5aa77SLinus Walleij 	int ich_in_ua)
13208c0984e5SSebastian Reichel {
132183e5aa77SLinus Walleij 	return ab8500_charger_set_current(di, ich_in_ua,
13228c0984e5SSebastian Reichel 		AB8500_MCH_IPT_CURLVL_REG);
13238c0984e5SSebastian Reichel }
13248c0984e5SSebastian Reichel 
13258c0984e5SSebastian Reichel /**
13268c0984e5SSebastian Reichel  * ab8500_charger_set_output_curr() - set charger output current
13278c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
132883e5aa77SLinus Walleij  * @ich_out_ua:	output charger current, in uA
13298c0984e5SSebastian Reichel  *
13308c0984e5SSebastian Reichel  * Set charger output current.
13318c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
13328c0984e5SSebastian Reichel  */
ab8500_charger_set_output_curr(struct ab8500_charger * di,int ich_out_ua)13338c0984e5SSebastian Reichel static int ab8500_charger_set_output_curr(struct ab8500_charger *di,
133483e5aa77SLinus Walleij 	int ich_out_ua)
13358c0984e5SSebastian Reichel {
133683e5aa77SLinus Walleij 	return ab8500_charger_set_current(di, ich_out_ua,
13378c0984e5SSebastian Reichel 		AB8500_CH_OPT_CRNTLVL_REG);
13388c0984e5SSebastian Reichel }
13398c0984e5SSebastian Reichel 
13408c0984e5SSebastian Reichel /**
13418c0984e5SSebastian Reichel  * ab8500_charger_led_en() - turn on/off chargign led
13428c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
13438c0984e5SSebastian Reichel  * @on:		flag to turn on/off the chargign led
13448c0984e5SSebastian Reichel  *
13458c0984e5SSebastian Reichel  * Power ON/OFF charging LED indication
13468c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
13478c0984e5SSebastian Reichel  */
ab8500_charger_led_en(struct ab8500_charger * di,int on)13488c0984e5SSebastian Reichel static int ab8500_charger_led_en(struct ab8500_charger *di, int on)
13498c0984e5SSebastian Reichel {
13508c0984e5SSebastian Reichel 	int ret;
13518c0984e5SSebastian Reichel 
13528c0984e5SSebastian Reichel 	if (on) {
13538c0984e5SSebastian Reichel 		/* Power ON charging LED indicator, set LED current to 5mA */
13548c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
13558c0984e5SSebastian Reichel 			AB8500_LED_INDICATOR_PWM_CTRL,
13568c0984e5SSebastian Reichel 			(LED_IND_CUR_5MA | LED_INDICATOR_PWM_ENA));
13578c0984e5SSebastian Reichel 		if (ret) {
13588c0984e5SSebastian Reichel 			dev_err(di->dev, "Power ON LED failed\n");
13598c0984e5SSebastian Reichel 			return ret;
13608c0984e5SSebastian Reichel 		}
13618c0984e5SSebastian Reichel 		/* LED indicator PWM duty cycle 252/256 */
13628c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
13638c0984e5SSebastian Reichel 			AB8500_LED_INDICATOR_PWM_DUTY,
13648c0984e5SSebastian Reichel 			LED_INDICATOR_PWM_DUTY_252_256);
13658c0984e5SSebastian Reichel 		if (ret) {
13668c0984e5SSebastian Reichel 			dev_err(di->dev, "Set LED PWM duty cycle failed\n");
13678c0984e5SSebastian Reichel 			return ret;
13688c0984e5SSebastian Reichel 		}
13698c0984e5SSebastian Reichel 	} else {
13708c0984e5SSebastian Reichel 		/* Power off charging LED indicator */
13718c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
13728c0984e5SSebastian Reichel 			AB8500_LED_INDICATOR_PWM_CTRL,
13738c0984e5SSebastian Reichel 			LED_INDICATOR_PWM_DIS);
13748c0984e5SSebastian Reichel 		if (ret) {
13758c0984e5SSebastian Reichel 			dev_err(di->dev, "Power-off LED failed\n");
13768c0984e5SSebastian Reichel 			return ret;
13778c0984e5SSebastian Reichel 		}
13788c0984e5SSebastian Reichel 	}
13798c0984e5SSebastian Reichel 
13808c0984e5SSebastian Reichel 	return ret;
13818c0984e5SSebastian Reichel }
13828c0984e5SSebastian Reichel 
13838c0984e5SSebastian Reichel /**
13848c0984e5SSebastian Reichel  * ab8500_charger_ac_en() - enable or disable ac charging
13858c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
13868c0984e5SSebastian Reichel  * @enable:	enable/disable flag
1387bc6e0287SLinus Walleij  * @vset_uv:	charging voltage in microvolt
138883e5aa77SLinus Walleij  * @iset_ua:	charging current in microampere
13898c0984e5SSebastian Reichel  *
13908c0984e5SSebastian Reichel  * Enable/Disable AC/Mains charging and turns on/off the charging led
13918c0984e5SSebastian Reichel  * respectively.
13928c0984e5SSebastian Reichel  **/
ab8500_charger_ac_en(struct ux500_charger * charger,int enable,int vset_uv,int iset_ua)13938c0984e5SSebastian Reichel static int ab8500_charger_ac_en(struct ux500_charger *charger,
1394bc6e0287SLinus Walleij 	int enable, int vset_uv, int iset_ua)
13958c0984e5SSebastian Reichel {
13968c0984e5SSebastian Reichel 	int ret;
13978c0984e5SSebastian Reichel 	int volt_index;
13988c0984e5SSebastian Reichel 	int curr_index;
13998c0984e5SSebastian Reichel 	int input_curr_index;
14008c0984e5SSebastian Reichel 	u8 overshoot = 0;
14018c0984e5SSebastian Reichel 
14028c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
14038c0984e5SSebastian Reichel 
14048c0984e5SSebastian Reichel 	if (enable) {
14058c0984e5SSebastian Reichel 		/* Check if AC is connected */
14068c0984e5SSebastian Reichel 		if (!di->ac.charger_connected) {
14078c0984e5SSebastian Reichel 			dev_err(di->dev, "AC charger not connected\n");
14088c0984e5SSebastian Reichel 			return -ENXIO;
14098c0984e5SSebastian Reichel 		}
14108c0984e5SSebastian Reichel 
14118c0984e5SSebastian Reichel 		/* Enable AC charging */
1412bc6e0287SLinus Walleij 		dev_dbg(di->dev, "Enable AC: %duV %duA\n", vset_uv, iset_ua);
14138c0984e5SSebastian Reichel 
14148c0984e5SSebastian Reichel 		/*
14158c0984e5SSebastian Reichel 		 * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
14168c0984e5SSebastian Reichel 		 * will be triggered every time we enable the VDD ADC supply.
14178c0984e5SSebastian Reichel 		 * This will turn off charging for a short while.
14188c0984e5SSebastian Reichel 		 * It can be avoided by having the supply on when
14198c0984e5SSebastian Reichel 		 * there is a charger enabled. Normally the VDD ADC supply
1420ddb74e98SAshish Chavan 		 * is enabled every time a GPADC conversion is triggered.
1421ddb74e98SAshish Chavan 		 * We will force it to be enabled from this driver to have
1422ddb74e98SAshish Chavan 		 * the GPADC module independent of the AB8500 chargers
14238c0984e5SSebastian Reichel 		 */
14248c0984e5SSebastian Reichel 		if (!di->vddadc_en_ac) {
14258c0984e5SSebastian Reichel 			ret = regulator_enable(di->regu);
14268c0984e5SSebastian Reichel 			if (ret)
14278c0984e5SSebastian Reichel 				dev_warn(di->dev,
14288c0984e5SSebastian Reichel 					"Failed to enable regulator\n");
14298c0984e5SSebastian Reichel 			else
14308c0984e5SSebastian Reichel 				di->vddadc_en_ac = true;
14318c0984e5SSebastian Reichel 		}
14328c0984e5SSebastian Reichel 
14338c0984e5SSebastian Reichel 		/* Check if the requested voltage or current is valid */
1434bc6e0287SLinus Walleij 		volt_index = ab8500_voltage_to_regval(vset_uv);
143583e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, iset_ua);
14368c0984e5SSebastian Reichel 		input_curr_index = ab8500_current_to_regval(di,
143783e5aa77SLinus Walleij 			di->bm->chg_params->ac_curr_max_ua);
14388c0984e5SSebastian Reichel 		if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) {
14398c0984e5SSebastian Reichel 			dev_err(di->dev,
14408c0984e5SSebastian Reichel 				"Charger voltage or current too high, "
14418c0984e5SSebastian Reichel 				"charging not started\n");
14428c0984e5SSebastian Reichel 			return -ENXIO;
14438c0984e5SSebastian Reichel 		}
14448c0984e5SSebastian Reichel 
14458c0984e5SSebastian Reichel 		/* ChVoltLevel: maximum battery charging voltage */
14468c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
14478c0984e5SSebastian Reichel 			AB8500_CH_VOLT_LVL_REG, (u8) volt_index);
14488c0984e5SSebastian Reichel 		if (ret) {
14498c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
14508c0984e5SSebastian Reichel 			return ret;
14518c0984e5SSebastian Reichel 		}
14528c0984e5SSebastian Reichel 		/* MainChInputCurr: current that can be drawn from the charger*/
14538c0984e5SSebastian Reichel 		ret = ab8500_charger_set_main_in_curr(di,
145483e5aa77SLinus Walleij 			di->bm->chg_params->ac_curr_max_ua);
14558c0984e5SSebastian Reichel 		if (ret) {
14568c0984e5SSebastian Reichel 			dev_err(di->dev, "%s Failed to set MainChInputCurr\n",
14578c0984e5SSebastian Reichel 				__func__);
14588c0984e5SSebastian Reichel 			return ret;
14598c0984e5SSebastian Reichel 		}
14608c0984e5SSebastian Reichel 		/* ChOutputCurentLevel: protected output current */
146183e5aa77SLinus Walleij 		ret = ab8500_charger_set_output_curr(di, iset_ua);
14628c0984e5SSebastian Reichel 		if (ret) {
14638c0984e5SSebastian Reichel 			dev_err(di->dev, "%s "
14648c0984e5SSebastian Reichel 				"Failed to set ChOutputCurentLevel\n",
14658c0984e5SSebastian Reichel 				__func__);
14668c0984e5SSebastian Reichel 			return ret;
14678c0984e5SSebastian Reichel 		}
14688c0984e5SSebastian Reichel 
14698c0984e5SSebastian Reichel 		/* Check if VBAT overshoot control should be enabled */
14708c0984e5SSebastian Reichel 		if (!di->bm->enable_overshoot)
14718c0984e5SSebastian Reichel 			overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N;
14728c0984e5SSebastian Reichel 
14738c0984e5SSebastian Reichel 		/* Enable Main Charger */
14748c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
14758c0984e5SSebastian Reichel 			AB8500_MCH_CTRL1, MAIN_CH_ENA | overshoot);
14768c0984e5SSebastian Reichel 		if (ret) {
14778c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
14788c0984e5SSebastian Reichel 			return ret;
14798c0984e5SSebastian Reichel 		}
14808c0984e5SSebastian Reichel 
14818c0984e5SSebastian Reichel 		/* Power on charging LED indication */
14828c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, true);
14838c0984e5SSebastian Reichel 		if (ret < 0)
14848c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to enable LED\n");
14858c0984e5SSebastian Reichel 
14868c0984e5SSebastian Reichel 		di->ac.charger_online = 1;
14878c0984e5SSebastian Reichel 	} else {
14888c0984e5SSebastian Reichel 		/* Disable AC charging */
14898c0984e5SSebastian Reichel 		if (is_ab8500_1p1_or_earlier(di->parent)) {
14908c0984e5SSebastian Reichel 			/*
14918c0984e5SSebastian Reichel 			 * For ABB revision 1.0 and 1.1 there is a bug in the
1492ddb74e98SAshish Chavan 			 * watchdog logic. That means we have to continuously
14938c0984e5SSebastian Reichel 			 * kick the charger watchdog even when no charger is
14948c0984e5SSebastian Reichel 			 * connected. This is only valid once the AC charger
14958c0984e5SSebastian Reichel 			 * has been enabled. This is a bug that is not handled
14968c0984e5SSebastian Reichel 			 * by the algorithm and the watchdog have to be kicked
14978c0984e5SSebastian Reichel 			 * by the charger driver when the AC charger
14988c0984e5SSebastian Reichel 			 * is disabled
14998c0984e5SSebastian Reichel 			 */
15008c0984e5SSebastian Reichel 			if (di->ac_conn) {
15018c0984e5SSebastian Reichel 				queue_delayed_work(di->charger_wq,
15028c0984e5SSebastian Reichel 					&di->kick_wd_work,
15038c0984e5SSebastian Reichel 					round_jiffies(WD_KICK_INTERVAL));
15048c0984e5SSebastian Reichel 			}
15058c0984e5SSebastian Reichel 
15068c0984e5SSebastian Reichel 			/*
15078c0984e5SSebastian Reichel 			 * We can't turn off charging completely
15088c0984e5SSebastian Reichel 			 * due to a bug in AB8500 cut1.
15098c0984e5SSebastian Reichel 			 * If we do, charging will not start again.
15108c0984e5SSebastian Reichel 			 * That is why we set the lowest voltage
15118c0984e5SSebastian Reichel 			 * and current possible
15128c0984e5SSebastian Reichel 			 */
15138c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
15148c0984e5SSebastian Reichel 				AB8500_CHARGER,
15158c0984e5SSebastian Reichel 				AB8500_CH_VOLT_LVL_REG, CH_VOL_LVL_3P5);
15168c0984e5SSebastian Reichel 			if (ret) {
15178c0984e5SSebastian Reichel 				dev_err(di->dev,
15188c0984e5SSebastian Reichel 					"%s write failed\n", __func__);
15198c0984e5SSebastian Reichel 				return ret;
15208c0984e5SSebastian Reichel 			}
15218c0984e5SSebastian Reichel 
15228c0984e5SSebastian Reichel 			ret = ab8500_charger_set_output_curr(di, 0);
15238c0984e5SSebastian Reichel 			if (ret) {
15248c0984e5SSebastian Reichel 				dev_err(di->dev, "%s "
15258c0984e5SSebastian Reichel 					"Failed to set ChOutputCurentLevel\n",
15268c0984e5SSebastian Reichel 					__func__);
15278c0984e5SSebastian Reichel 				return ret;
15288c0984e5SSebastian Reichel 			}
15298c0984e5SSebastian Reichel 		} else {
15308c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
15318c0984e5SSebastian Reichel 				AB8500_CHARGER,
15328c0984e5SSebastian Reichel 				AB8500_MCH_CTRL1, 0);
15338c0984e5SSebastian Reichel 			if (ret) {
15348c0984e5SSebastian Reichel 				dev_err(di->dev,
15358c0984e5SSebastian Reichel 					"%s write failed\n", __func__);
15368c0984e5SSebastian Reichel 				return ret;
15378c0984e5SSebastian Reichel 			}
15388c0984e5SSebastian Reichel 		}
15398c0984e5SSebastian Reichel 
15408c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, false);
15418c0984e5SSebastian Reichel 		if (ret < 0)
15428c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to disable LED\n");
15438c0984e5SSebastian Reichel 
15448c0984e5SSebastian Reichel 		di->ac.charger_online = 0;
15458c0984e5SSebastian Reichel 		di->ac.wd_expired = false;
15468c0984e5SSebastian Reichel 
15478c0984e5SSebastian Reichel 		/* Disable regulator if enabled */
15488c0984e5SSebastian Reichel 		if (di->vddadc_en_ac) {
15498c0984e5SSebastian Reichel 			regulator_disable(di->regu);
15508c0984e5SSebastian Reichel 			di->vddadc_en_ac = false;
15518c0984e5SSebastian Reichel 		}
15528c0984e5SSebastian Reichel 
15538c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s Disabled AC charging\n", __func__);
15548c0984e5SSebastian Reichel 	}
15558c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
15568c0984e5SSebastian Reichel 
15578c0984e5SSebastian Reichel 	return ret;
15588c0984e5SSebastian Reichel }
15598c0984e5SSebastian Reichel 
15608c0984e5SSebastian Reichel /**
15618c0984e5SSebastian Reichel  * ab8500_charger_usb_en() - enable usb charging
15628c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
15638c0984e5SSebastian Reichel  * @enable:	enable/disable flag
1564bc6e0287SLinus Walleij  * @vset_uv:	charging voltage in microvolt
156583e5aa77SLinus Walleij  * @ich_out_ua:	charger output current in microampere
15668c0984e5SSebastian Reichel  *
15678c0984e5SSebastian Reichel  * Enable/Disable USB charging and turns on/off the charging led respectively.
15688c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
15698c0984e5SSebastian Reichel  */
ab8500_charger_usb_en(struct ux500_charger * charger,int enable,int vset_uv,int ich_out_ua)15708c0984e5SSebastian Reichel static int ab8500_charger_usb_en(struct ux500_charger *charger,
1571bc6e0287SLinus Walleij 	int enable, int vset_uv, int ich_out_ua)
15728c0984e5SSebastian Reichel {
15738c0984e5SSebastian Reichel 	int ret;
15748c0984e5SSebastian Reichel 	int volt_index;
15758c0984e5SSebastian Reichel 	int curr_index;
15768c0984e5SSebastian Reichel 	u8 overshoot = 0;
15778c0984e5SSebastian Reichel 
15788c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
15798c0984e5SSebastian Reichel 
15808c0984e5SSebastian Reichel 	if (enable) {
15818c0984e5SSebastian Reichel 		/* Check if USB is connected */
15828c0984e5SSebastian Reichel 		if (!di->usb.charger_connected) {
15838c0984e5SSebastian Reichel 			dev_err(di->dev, "USB charger not connected\n");
15848c0984e5SSebastian Reichel 			return -ENXIO;
15858c0984e5SSebastian Reichel 		}
15868c0984e5SSebastian Reichel 
15878c0984e5SSebastian Reichel 		/*
15888c0984e5SSebastian Reichel 		 * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
15898c0984e5SSebastian Reichel 		 * will be triggered every time we enable the VDD ADC supply.
15908c0984e5SSebastian Reichel 		 * This will turn off charging for a short while.
15918c0984e5SSebastian Reichel 		 * It can be avoided by having the supply on when
15928c0984e5SSebastian Reichel 		 * there is a charger enabled. Normally the VDD ADC supply
1593ddb74e98SAshish Chavan 		 * is enabled every time a GPADC conversion is triggered.
1594ddb74e98SAshish Chavan 		 * We will force it to be enabled from this driver to have
1595ddb74e98SAshish Chavan 		 * the GPADC module independent of the AB8500 chargers
15968c0984e5SSebastian Reichel 		 */
15978c0984e5SSebastian Reichel 		if (!di->vddadc_en_usb) {
15988c0984e5SSebastian Reichel 			ret = regulator_enable(di->regu);
15998c0984e5SSebastian Reichel 			if (ret)
16008c0984e5SSebastian Reichel 				dev_warn(di->dev,
16018c0984e5SSebastian Reichel 					"Failed to enable regulator\n");
16028c0984e5SSebastian Reichel 			else
16038c0984e5SSebastian Reichel 				di->vddadc_en_usb = true;
16048c0984e5SSebastian Reichel 		}
16058c0984e5SSebastian Reichel 
16068c0984e5SSebastian Reichel 		/* Enable USB charging */
1607bc6e0287SLinus Walleij 		dev_dbg(di->dev, "Enable USB: %d uV %d uA\n", vset_uv, ich_out_ua);
16088c0984e5SSebastian Reichel 
16098c0984e5SSebastian Reichel 		/* Check if the requested voltage or current is valid */
1610bc6e0287SLinus Walleij 		volt_index = ab8500_voltage_to_regval(vset_uv);
161183e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, ich_out_ua);
16128c0984e5SSebastian Reichel 		if (volt_index < 0 || curr_index < 0) {
16138c0984e5SSebastian Reichel 			dev_err(di->dev,
16148c0984e5SSebastian Reichel 				"Charger voltage or current too high, "
16158c0984e5SSebastian Reichel 				"charging not started\n");
16168c0984e5SSebastian Reichel 			return -ENXIO;
16178c0984e5SSebastian Reichel 		}
16188c0984e5SSebastian Reichel 
1619ddb74e98SAshish Chavan 		/*
1620ddb74e98SAshish Chavan 		 * ChVoltLevel: max voltage up to which battery can be
1621ddb74e98SAshish Chavan 		 * charged
1622ddb74e98SAshish Chavan 		 */
16238c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
16248c0984e5SSebastian Reichel 			AB8500_CH_VOLT_LVL_REG, (u8) volt_index);
16258c0984e5SSebastian Reichel 		if (ret) {
16268c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
16278c0984e5SSebastian Reichel 			return ret;
16288c0984e5SSebastian Reichel 		}
16298c0984e5SSebastian Reichel 		/* Check if VBAT overshoot control should be enabled */
16308c0984e5SSebastian Reichel 		if (!di->bm->enable_overshoot)
16318c0984e5SSebastian Reichel 			overshoot = USB_CHG_NO_OVERSHOOT_ENA_N;
16328c0984e5SSebastian Reichel 
16338c0984e5SSebastian Reichel 		/* Enable USB Charger */
16348c0984e5SSebastian Reichel 		dev_dbg(di->dev,
16358c0984e5SSebastian Reichel 			"Enabling USB with write to AB8500_USBCH_CTRL1_REG\n");
16368c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
16378c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot);
16388c0984e5SSebastian Reichel 		if (ret) {
16398c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
16408c0984e5SSebastian Reichel 			return ret;
16418c0984e5SSebastian Reichel 		}
16428c0984e5SSebastian Reichel 
16438c0984e5SSebastian Reichel 		/* If success power on charging LED indication */
16448c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, true);
16458c0984e5SSebastian Reichel 		if (ret < 0)
16468c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to enable LED\n");
16478c0984e5SSebastian Reichel 
16488c0984e5SSebastian Reichel 		di->usb.charger_online = 1;
16498c0984e5SSebastian Reichel 
16508c0984e5SSebastian Reichel 		/* USBChInputCurr: current that can be drawn from the usb */
16518c0984e5SSebastian Reichel 		ret = ab8500_charger_set_vbus_in_curr(di,
165283e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
16538c0984e5SSebastian Reichel 		if (ret) {
16548c0984e5SSebastian Reichel 			dev_err(di->dev, "setting USBChInputCurr failed\n");
16558c0984e5SSebastian Reichel 			return ret;
16568c0984e5SSebastian Reichel 		}
16578c0984e5SSebastian Reichel 
16588c0984e5SSebastian Reichel 		/* ChOutputCurentLevel: protected output current */
165983e5aa77SLinus Walleij 		ret = ab8500_charger_set_output_curr(di, ich_out_ua);
16608c0984e5SSebastian Reichel 		if (ret) {
16618c0984e5SSebastian Reichel 			dev_err(di->dev, "%s "
16628c0984e5SSebastian Reichel 				"Failed to set ChOutputCurentLevel\n",
16638c0984e5SSebastian Reichel 				__func__);
16648c0984e5SSebastian Reichel 			return ret;
16658c0984e5SSebastian Reichel 		}
16668c0984e5SSebastian Reichel 
16678c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ);
16688c0984e5SSebastian Reichel 
16698c0984e5SSebastian Reichel 	} else {
16708c0984e5SSebastian Reichel 		/* Disable USB charging */
16718c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s Disabled USB charging\n", __func__);
16728c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
16738c0984e5SSebastian Reichel 			AB8500_CHARGER,
16748c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL1_REG, 0);
16758c0984e5SSebastian Reichel 		if (ret) {
16768c0984e5SSebastian Reichel 			dev_err(di->dev,
16778c0984e5SSebastian Reichel 				"%s write failed\n", __func__);
16788c0984e5SSebastian Reichel 			return ret;
16798c0984e5SSebastian Reichel 		}
16808c0984e5SSebastian Reichel 
16818c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, false);
16828c0984e5SSebastian Reichel 		if (ret < 0)
16838c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to disable LED\n");
16848c0984e5SSebastian Reichel 		/* USBChInputCurr: current that can be drawn from the usb */
16858c0984e5SSebastian Reichel 		ret = ab8500_charger_set_vbus_in_curr(di, 0);
16868c0984e5SSebastian Reichel 		if (ret) {
16878c0984e5SSebastian Reichel 			dev_err(di->dev, "setting USBChInputCurr failed\n");
16888c0984e5SSebastian Reichel 			return ret;
16898c0984e5SSebastian Reichel 		}
16908c0984e5SSebastian Reichel 
16918c0984e5SSebastian Reichel 		/* ChOutputCurentLevel: protected output current */
16928c0984e5SSebastian Reichel 		ret = ab8500_charger_set_output_curr(di, 0);
16938c0984e5SSebastian Reichel 		if (ret) {
16948c0984e5SSebastian Reichel 			dev_err(di->dev, "%s "
16958c0984e5SSebastian Reichel 				"Failed to reset ChOutputCurentLevel\n",
16968c0984e5SSebastian Reichel 				__func__);
16978c0984e5SSebastian Reichel 			return ret;
16988c0984e5SSebastian Reichel 		}
16998c0984e5SSebastian Reichel 		di->usb.charger_online = 0;
17008c0984e5SSebastian Reichel 		di->usb.wd_expired = false;
17018c0984e5SSebastian Reichel 
17028c0984e5SSebastian Reichel 		/* Disable regulator if enabled */
17038c0984e5SSebastian Reichel 		if (di->vddadc_en_usb) {
17048c0984e5SSebastian Reichel 			regulator_disable(di->regu);
17058c0984e5SSebastian Reichel 			di->vddadc_en_usb = false;
17068c0984e5SSebastian Reichel 		}
17078c0984e5SSebastian Reichel 
17088c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s Disabled USB charging\n", __func__);
17098c0984e5SSebastian Reichel 
17108c0984e5SSebastian Reichel 		/* Cancel any pending Vbat check work */
17118c0984e5SSebastian Reichel 		cancel_delayed_work(&di->check_vbat_work);
17128c0984e5SSebastian Reichel 
17138c0984e5SSebastian Reichel 	}
17148c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
17158c0984e5SSebastian Reichel 
17168c0984e5SSebastian Reichel 	return ret;
17178c0984e5SSebastian Reichel }
17188c0984e5SSebastian Reichel 
17198c0984e5SSebastian Reichel /**
17208c0984e5SSebastian Reichel  * ab8500_charger_usb_check_enable() - enable usb charging
17218c0984e5SSebastian Reichel  * @charger:	pointer to the ux500_charger structure
1722bc6e0287SLinus Walleij  * @vset_uv:	charging voltage in microvolt
172383e5aa77SLinus Walleij  * @iset_ua:	charger output current in microampere
17248c0984e5SSebastian Reichel  *
17258c0984e5SSebastian Reichel  * Check if the VBUS charger has been disconnected and reconnected without
17268c0984e5SSebastian Reichel  * AB8500 rising an interrupt. Returns 0 on success.
17278c0984e5SSebastian Reichel  */
ab8500_charger_usb_check_enable(struct ux500_charger * charger,int vset_uv,int iset_ua)17288c0984e5SSebastian Reichel static int ab8500_charger_usb_check_enable(struct ux500_charger *charger,
1729bc6e0287SLinus Walleij 	int vset_uv, int iset_ua)
17308c0984e5SSebastian Reichel {
17318c0984e5SSebastian Reichel 	u8 usbch_ctrl1 = 0;
17328c0984e5SSebastian Reichel 	int ret = 0;
17338c0984e5SSebastian Reichel 
17348c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
17358c0984e5SSebastian Reichel 
17368c0984e5SSebastian Reichel 	if (!di->usb.charger_connected)
17378c0984e5SSebastian Reichel 		return ret;
17388c0984e5SSebastian Reichel 
17398c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
17408c0984e5SSebastian Reichel 				AB8500_USBCH_CTRL1_REG, &usbch_ctrl1);
17418c0984e5SSebastian Reichel 	if (ret < 0) {
17428c0984e5SSebastian Reichel 		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
17438c0984e5SSebastian Reichel 		return ret;
17448c0984e5SSebastian Reichel 	}
17458c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1);
17468c0984e5SSebastian Reichel 
17478c0984e5SSebastian Reichel 	if (!(usbch_ctrl1 & USB_CH_ENA)) {
17488c0984e5SSebastian Reichel 		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
17498c0984e5SSebastian Reichel 
17508c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
17518c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_CHARGER_CTRL,
17528c0984e5SSebastian Reichel 					DROP_COUNT_RESET, DROP_COUNT_RESET);
17538c0984e5SSebastian Reichel 		if (ret < 0) {
17548c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
17558c0984e5SSebastian Reichel 			return ret;
17568c0984e5SSebastian Reichel 		}
17578c0984e5SSebastian Reichel 
1758bc6e0287SLinus Walleij 		ret = ab8500_charger_usb_en(&di->usb_chg, true, vset_uv, iset_ua);
17598c0984e5SSebastian Reichel 		if (ret < 0) {
17608c0984e5SSebastian Reichel 			dev_err(di->dev, "Failed to enable VBUS charger %d\n",
17618c0984e5SSebastian Reichel 					__LINE__);
17628c0984e5SSebastian Reichel 			return ret;
17638c0984e5SSebastian Reichel 		}
17648c0984e5SSebastian Reichel 	}
17658c0984e5SSebastian Reichel 	return ret;
17668c0984e5SSebastian Reichel }
17678c0984e5SSebastian Reichel 
17688c0984e5SSebastian Reichel /**
17698c0984e5SSebastian Reichel  * ab8500_charger_ac_check_enable() - enable usb charging
17708c0984e5SSebastian Reichel  * @charger:	pointer to the ux500_charger structure
1771bc6e0287SLinus Walleij  * @vset_uv:	charging voltage in microvolt
177283e5aa77SLinus Walleij  * @iset_ua:	charger output current in micrompere
17738c0984e5SSebastian Reichel  *
17748c0984e5SSebastian Reichel  * Check if the AC charger has been disconnected and reconnected without
17758c0984e5SSebastian Reichel  * AB8500 rising an interrupt. Returns 0 on success.
17768c0984e5SSebastian Reichel  */
ab8500_charger_ac_check_enable(struct ux500_charger * charger,int vset_uv,int iset_ua)17778c0984e5SSebastian Reichel static int ab8500_charger_ac_check_enable(struct ux500_charger *charger,
1778bc6e0287SLinus Walleij 	int vset_uv, int iset_ua)
17798c0984e5SSebastian Reichel {
17808c0984e5SSebastian Reichel 	u8 mainch_ctrl1 = 0;
17818c0984e5SSebastian Reichel 	int ret = 0;
17828c0984e5SSebastian Reichel 
17838c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
17848c0984e5SSebastian Reichel 
17858c0984e5SSebastian Reichel 	if (!di->ac.charger_connected)
17868c0984e5SSebastian Reichel 		return ret;
17878c0984e5SSebastian Reichel 
17888c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
17898c0984e5SSebastian Reichel 				AB8500_MCH_CTRL1, &mainch_ctrl1);
17908c0984e5SSebastian Reichel 	if (ret < 0) {
17918c0984e5SSebastian Reichel 		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
17928c0984e5SSebastian Reichel 		return ret;
17938c0984e5SSebastian Reichel 	}
17948c0984e5SSebastian Reichel 	dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1);
17958c0984e5SSebastian Reichel 
17968c0984e5SSebastian Reichel 	if (!(mainch_ctrl1 & MAIN_CH_ENA)) {
17978c0984e5SSebastian Reichel 		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
17988c0984e5SSebastian Reichel 
17998c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
18008c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_CHARGER_CTRL,
18018c0984e5SSebastian Reichel 					DROP_COUNT_RESET, DROP_COUNT_RESET);
18028c0984e5SSebastian Reichel 
18038c0984e5SSebastian Reichel 		if (ret < 0) {
18048c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
18058c0984e5SSebastian Reichel 			return ret;
18068c0984e5SSebastian Reichel 		}
18078c0984e5SSebastian Reichel 
1808bc6e0287SLinus Walleij 		ret = ab8500_charger_ac_en(&di->usb_chg, true, vset_uv, iset_ua);
18098c0984e5SSebastian Reichel 		if (ret < 0) {
18108c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to enable AC charger %d\n",
18118c0984e5SSebastian Reichel 				__LINE__);
18128c0984e5SSebastian Reichel 			return ret;
18138c0984e5SSebastian Reichel 		}
18148c0984e5SSebastian Reichel 	}
18158c0984e5SSebastian Reichel 	return ret;
18168c0984e5SSebastian Reichel }
18178c0984e5SSebastian Reichel 
18188c0984e5SSebastian Reichel /**
18198c0984e5SSebastian Reichel  * ab8500_charger_watchdog_kick() - kick charger watchdog
18208c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
18218c0984e5SSebastian Reichel  *
18228c0984e5SSebastian Reichel  * Kick charger watchdog
18238c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
18248c0984e5SSebastian Reichel  */
ab8500_charger_watchdog_kick(struct ux500_charger * charger)18258c0984e5SSebastian Reichel static int ab8500_charger_watchdog_kick(struct ux500_charger *charger)
18268c0984e5SSebastian Reichel {
18278c0984e5SSebastian Reichel 	int ret;
18288c0984e5SSebastian Reichel 	struct ab8500_charger *di;
18298c0984e5SSebastian Reichel 
18308c0984e5SSebastian Reichel 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
18318c0984e5SSebastian Reichel 		di = to_ab8500_charger_ac_device_info(charger);
18328c0984e5SSebastian Reichel 	else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
18338c0984e5SSebastian Reichel 		di = to_ab8500_charger_usb_device_info(charger);
18348c0984e5SSebastian Reichel 	else
18358c0984e5SSebastian Reichel 		return -ENXIO;
18368c0984e5SSebastian Reichel 
18378c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
18388c0984e5SSebastian Reichel 		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
18398c0984e5SSebastian Reichel 	if (ret)
18408c0984e5SSebastian Reichel 		dev_err(di->dev, "Failed to kick WD!\n");
18418c0984e5SSebastian Reichel 
18428c0984e5SSebastian Reichel 	return ret;
18438c0984e5SSebastian Reichel }
18448c0984e5SSebastian Reichel 
18458c0984e5SSebastian Reichel /**
18468c0984e5SSebastian Reichel  * ab8500_charger_update_charger_current() - update charger current
184783e5aa77SLinus Walleij  * @charger:		pointer to the ab8500_charger structure
184883e5aa77SLinus Walleij  * @ich_out_ua:		desired output current in microampere
18498c0984e5SSebastian Reichel  *
18508c0984e5SSebastian Reichel  * Update the charger output current for the specified charger
18518c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
18528c0984e5SSebastian Reichel  */
ab8500_charger_update_charger_current(struct ux500_charger * charger,int ich_out_ua)18538c0984e5SSebastian Reichel static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
185483e5aa77SLinus Walleij 		int ich_out_ua)
18558c0984e5SSebastian Reichel {
18568c0984e5SSebastian Reichel 	int ret;
18578c0984e5SSebastian Reichel 	struct ab8500_charger *di;
18588c0984e5SSebastian Reichel 
18598c0984e5SSebastian Reichel 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
18608c0984e5SSebastian Reichel 		di = to_ab8500_charger_ac_device_info(charger);
18618c0984e5SSebastian Reichel 	else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
18628c0984e5SSebastian Reichel 		di = to_ab8500_charger_usb_device_info(charger);
18638c0984e5SSebastian Reichel 	else
18648c0984e5SSebastian Reichel 		return -ENXIO;
18658c0984e5SSebastian Reichel 
186683e5aa77SLinus Walleij 	ret = ab8500_charger_set_output_curr(di, ich_out_ua);
18678c0984e5SSebastian Reichel 	if (ret) {
18688c0984e5SSebastian Reichel 		dev_err(di->dev, "%s "
18698c0984e5SSebastian Reichel 			"Failed to set ChOutputCurentLevel\n",
18708c0984e5SSebastian Reichel 			__func__);
18718c0984e5SSebastian Reichel 		return ret;
18728c0984e5SSebastian Reichel 	}
18738c0984e5SSebastian Reichel 
18748c0984e5SSebastian Reichel 	/* Reset the main and usb drop input current measurement counter */
18758c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
18768c0984e5SSebastian Reichel 				AB8500_CHARGER_CTRL, DROP_COUNT_RESET);
18778c0984e5SSebastian Reichel 	if (ret) {
18788c0984e5SSebastian Reichel 		dev_err(di->dev, "%s write failed\n", __func__);
18798c0984e5SSebastian Reichel 		return ret;
18808c0984e5SSebastian Reichel 	}
18818c0984e5SSebastian Reichel 
18828c0984e5SSebastian Reichel 	return ret;
18838c0984e5SSebastian Reichel }
18848c0984e5SSebastian Reichel 
ab8500_charger_get_ext_psy_data(struct device * dev,void * data)18858c0984e5SSebastian Reichel static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
18868c0984e5SSebastian Reichel {
18878c0984e5SSebastian Reichel 	struct power_supply *psy;
18888c0984e5SSebastian Reichel 	struct power_supply *ext = dev_get_drvdata(dev);
18898c0984e5SSebastian Reichel 	const char **supplicants = (const char **)ext->supplied_to;
18908c0984e5SSebastian Reichel 	struct ab8500_charger *di;
18918c0984e5SSebastian Reichel 	union power_supply_propval ret;
18928c0984e5SSebastian Reichel 	int j;
18938c0984e5SSebastian Reichel 	struct ux500_charger *usb_chg;
18948c0984e5SSebastian Reichel 
18958c0984e5SSebastian Reichel 	usb_chg = (struct ux500_charger *)data;
18968c0984e5SSebastian Reichel 	psy = usb_chg->psy;
18978c0984e5SSebastian Reichel 
18988c0984e5SSebastian Reichel 	di = to_ab8500_charger_usb_device_info(usb_chg);
18998c0984e5SSebastian Reichel 
190021ad180dSLinus Walleij 	/*
190121ad180dSLinus Walleij 	 * For all psy where the driver name appears in any supplied_to
190221ad180dSLinus Walleij 	 * in practice what we will find will always be "ab8500_fg" as
190321ad180dSLinus Walleij 	 * the fuel gauge is responsible of keeping track of VBAT.
190421ad180dSLinus Walleij 	 */
19058c0984e5SSebastian Reichel 	j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
19068c0984e5SSebastian Reichel 	if (j < 0)
19078c0984e5SSebastian Reichel 		return 0;
19088c0984e5SSebastian Reichel 
19098c0984e5SSebastian Reichel 	/* Go through all properties for the psy */
19108c0984e5SSebastian Reichel 	for (j = 0; j < ext->desc->num_properties; j++) {
19118c0984e5SSebastian Reichel 		enum power_supply_property prop;
19128c0984e5SSebastian Reichel 		prop = ext->desc->properties[j];
19138c0984e5SSebastian Reichel 
19148c0984e5SSebastian Reichel 		if (power_supply_get_property(ext, prop, &ret))
19158c0984e5SSebastian Reichel 			continue;
19168c0984e5SSebastian Reichel 
19178c0984e5SSebastian Reichel 		switch (prop) {
19188c0984e5SSebastian Reichel 		case POWER_SUPPLY_PROP_VOLTAGE_NOW:
19198c0984e5SSebastian Reichel 			switch (ext->desc->type) {
19208c0984e5SSebastian Reichel 			case POWER_SUPPLY_TYPE_BATTERY:
192121ad180dSLinus Walleij 				/* This will always be "ab8500_fg" */
192221ad180dSLinus Walleij 				dev_dbg(di->dev, "get VBAT from %s\n",
192321ad180dSLinus Walleij 					dev_name(&ext->dev));
192421ad180dSLinus Walleij 				di->vbat = ret.intval;
19258c0984e5SSebastian Reichel 				break;
19268c0984e5SSebastian Reichel 			default:
19278c0984e5SSebastian Reichel 				break;
19288c0984e5SSebastian Reichel 			}
19298c0984e5SSebastian Reichel 			break;
19308c0984e5SSebastian Reichel 		default:
19318c0984e5SSebastian Reichel 			break;
19328c0984e5SSebastian Reichel 		}
19338c0984e5SSebastian Reichel 	}
19348c0984e5SSebastian Reichel 	return 0;
19358c0984e5SSebastian Reichel }
19368c0984e5SSebastian Reichel 
19378c0984e5SSebastian Reichel /**
19388c0984e5SSebastian Reichel  * ab8500_charger_check_vbat_work() - keep vbus current within spec
19398c0984e5SSebastian Reichel  * @work	pointer to the work_struct structure
19408c0984e5SSebastian Reichel  *
19418c0984e5SSebastian Reichel  * Due to a asic bug it is necessary to lower the input current to the vbus
19428c0984e5SSebastian Reichel  * charger when charging with at some specific levels. This issue is only valid
194303b33d4aSwangjianli  * for below a certain battery voltage. This function makes sure that
19448c0984e5SSebastian Reichel  * the allowed current limit isn't exceeded.
19458c0984e5SSebastian Reichel  */
ab8500_charger_check_vbat_work(struct work_struct * work)19468c0984e5SSebastian Reichel static void ab8500_charger_check_vbat_work(struct work_struct *work)
19478c0984e5SSebastian Reichel {
19488c0984e5SSebastian Reichel 	int t = 10;
19498c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
19508c0984e5SSebastian Reichel 		struct ab8500_charger, check_vbat_work.work);
19518c0984e5SSebastian Reichel 
19528c0984e5SSebastian Reichel 	class_for_each_device(power_supply_class, NULL,
195321ad180dSLinus Walleij 			      &di->usb_chg, ab8500_charger_get_ext_psy_data);
19548c0984e5SSebastian Reichel 
19558c0984e5SSebastian Reichel 	/* First run old_vbat is 0. */
19568c0984e5SSebastian Reichel 	if (di->old_vbat == 0)
19578c0984e5SSebastian Reichel 		di->old_vbat = di->vbat;
19588c0984e5SSebastian Reichel 
19598c0984e5SSebastian Reichel 	if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED &&
19608c0984e5SSebastian Reichel 		di->vbat <= VBAT_TRESH_IP_CUR_RED) ||
19618c0984e5SSebastian Reichel 		(di->old_vbat > VBAT_TRESH_IP_CUR_RED &&
19628c0984e5SSebastian Reichel 		di->vbat > VBAT_TRESH_IP_CUR_RED))) {
19638c0984e5SSebastian Reichel 
19648c0984e5SSebastian Reichel 		dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d,"
196583e5aa77SLinus Walleij 			" old: %d\n", di->max_usb_in_curr.usb_type_max_ua,
19668c0984e5SSebastian Reichel 			di->vbat, di->old_vbat);
19678c0984e5SSebastian Reichel 		ab8500_charger_set_vbus_in_curr(di,
196883e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
19698c0984e5SSebastian Reichel 		power_supply_changed(di->usb_chg.psy);
19708c0984e5SSebastian Reichel 	}
19718c0984e5SSebastian Reichel 
19728c0984e5SSebastian Reichel 	di->old_vbat = di->vbat;
19738c0984e5SSebastian Reichel 
19748c0984e5SSebastian Reichel 	/*
19758c0984e5SSebastian Reichel 	 * No need to check the battery voltage every second when not close to
19768c0984e5SSebastian Reichel 	 * the threshold.
19778c0984e5SSebastian Reichel 	 */
197821ad180dSLinus Walleij 	if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100000) &&
197921ad180dSLinus Walleij 		(di->vbat > (VBAT_TRESH_IP_CUR_RED - 100000)))
19808c0984e5SSebastian Reichel 			t = 1;
19818c0984e5SSebastian Reichel 
19828c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ);
19838c0984e5SSebastian Reichel }
19848c0984e5SSebastian Reichel 
19858c0984e5SSebastian Reichel /**
19868c0984e5SSebastian Reichel  * ab8500_charger_check_hw_failure_work() - check main charger failure
19878c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
19888c0984e5SSebastian Reichel  *
19898c0984e5SSebastian Reichel  * Work queue function for checking the main charger status
19908c0984e5SSebastian Reichel  */
ab8500_charger_check_hw_failure_work(struct work_struct * work)19918c0984e5SSebastian Reichel static void ab8500_charger_check_hw_failure_work(struct work_struct *work)
19928c0984e5SSebastian Reichel {
19938c0984e5SSebastian Reichel 	int ret;
19948c0984e5SSebastian Reichel 	u8 reg_value;
19958c0984e5SSebastian Reichel 
19968c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
19978c0984e5SSebastian Reichel 		struct ab8500_charger, check_hw_failure_work.work);
19988c0984e5SSebastian Reichel 
19998c0984e5SSebastian Reichel 	/* Check if the status bits for HW failure is still active */
20008c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok) {
20018c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
20028c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
20038c0984e5SSebastian Reichel 		if (ret < 0) {
20048c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
20058c0984e5SSebastian Reichel 			return;
20068c0984e5SSebastian Reichel 		}
20078c0984e5SSebastian Reichel 		if (!(reg_value & MAIN_CH_NOK)) {
20088c0984e5SSebastian Reichel 			di->flags.mainextchnotok = false;
20098c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->ac_chg.psy);
20108c0984e5SSebastian Reichel 		}
20118c0984e5SSebastian Reichel 	}
20128c0984e5SSebastian Reichel 	if (di->flags.vbus_ovv) {
20138c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
20148c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG,
20158c0984e5SSebastian Reichel 			&reg_value);
20168c0984e5SSebastian Reichel 		if (ret < 0) {
20178c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
20188c0984e5SSebastian Reichel 			return;
20198c0984e5SSebastian Reichel 		}
20208c0984e5SSebastian Reichel 		if (!(reg_value & VBUS_OVV_TH)) {
20218c0984e5SSebastian Reichel 			di->flags.vbus_ovv = false;
20228c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
20238c0984e5SSebastian Reichel 		}
20248c0984e5SSebastian Reichel 	}
20258c0984e5SSebastian Reichel 	/* If we still have a failure, schedule a new check */
20268c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
20278c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
20288c0984e5SSebastian Reichel 			&di->check_hw_failure_work, round_jiffies(HZ));
20298c0984e5SSebastian Reichel 	}
20308c0984e5SSebastian Reichel }
20318c0984e5SSebastian Reichel 
20328c0984e5SSebastian Reichel /**
20338c0984e5SSebastian Reichel  * ab8500_charger_kick_watchdog_work() - kick the watchdog
20348c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20358c0984e5SSebastian Reichel  *
20368c0984e5SSebastian Reichel  * Work queue function for kicking the charger watchdog.
20378c0984e5SSebastian Reichel  *
20388c0984e5SSebastian Reichel  * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
2039ddb74e98SAshish Chavan  * logic. That means we have to continuously kick the charger
20408c0984e5SSebastian Reichel  * watchdog even when no charger is connected. This is only
20418c0984e5SSebastian Reichel  * valid once the AC charger has been enabled. This is
20428c0984e5SSebastian Reichel  * a bug that is not handled by the algorithm and the
20438c0984e5SSebastian Reichel  * watchdog have to be kicked by the charger driver
20448c0984e5SSebastian Reichel  * when the AC charger is disabled
20458c0984e5SSebastian Reichel  */
ab8500_charger_kick_watchdog_work(struct work_struct * work)20468c0984e5SSebastian Reichel static void ab8500_charger_kick_watchdog_work(struct work_struct *work)
20478c0984e5SSebastian Reichel {
20488c0984e5SSebastian Reichel 	int ret;
20498c0984e5SSebastian Reichel 
20508c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20518c0984e5SSebastian Reichel 		struct ab8500_charger, kick_wd_work.work);
20528c0984e5SSebastian Reichel 
20538c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
20548c0984e5SSebastian Reichel 		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
20558c0984e5SSebastian Reichel 	if (ret)
20568c0984e5SSebastian Reichel 		dev_err(di->dev, "Failed to kick WD!\n");
20578c0984e5SSebastian Reichel 
20588c0984e5SSebastian Reichel 	/* Schedule a new watchdog kick */
20598c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
20608c0984e5SSebastian Reichel 		&di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL));
20618c0984e5SSebastian Reichel }
20628c0984e5SSebastian Reichel 
20638c0984e5SSebastian Reichel /**
20648c0984e5SSebastian Reichel  * ab8500_charger_ac_work() - work to get and set main charger status
20658c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20668c0984e5SSebastian Reichel  *
20678c0984e5SSebastian Reichel  * Work queue function for checking the main charger status
20688c0984e5SSebastian Reichel  */
ab8500_charger_ac_work(struct work_struct * work)20698c0984e5SSebastian Reichel static void ab8500_charger_ac_work(struct work_struct *work)
20708c0984e5SSebastian Reichel {
20718c0984e5SSebastian Reichel 	int ret;
20728c0984e5SSebastian Reichel 
20738c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20748c0984e5SSebastian Reichel 		struct ab8500_charger, ac_work);
20758c0984e5SSebastian Reichel 
20768c0984e5SSebastian Reichel 	/*
20778c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
20788c0984e5SSebastian Reichel 	 * synchronously, we have the check if the main charger is
20798c0984e5SSebastian Reichel 	 * connected by reading the status register
20808c0984e5SSebastian Reichel 	 */
20818c0984e5SSebastian Reichel 	ret = ab8500_charger_detect_chargers(di, false);
20828c0984e5SSebastian Reichel 	if (ret < 0)
20838c0984e5SSebastian Reichel 		return;
20848c0984e5SSebastian Reichel 
20858c0984e5SSebastian Reichel 	if (ret & AC_PW_CONN) {
20868c0984e5SSebastian Reichel 		di->ac.charger_connected = 1;
20878c0984e5SSebastian Reichel 		di->ac_conn = true;
20888c0984e5SSebastian Reichel 	} else {
20898c0984e5SSebastian Reichel 		di->ac.charger_connected = 0;
20908c0984e5SSebastian Reichel 	}
20918c0984e5SSebastian Reichel 
20928c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
20938c0984e5SSebastian Reichel 	sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
20948c0984e5SSebastian Reichel }
20958c0984e5SSebastian Reichel 
ab8500_charger_usb_attached_work(struct work_struct * work)20968c0984e5SSebastian Reichel static void ab8500_charger_usb_attached_work(struct work_struct *work)
20978c0984e5SSebastian Reichel {
20988c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20998c0984e5SSebastian Reichel 						 struct ab8500_charger,
21008c0984e5SSebastian Reichel 						 usb_charger_attached_work.work);
21018c0984e5SSebastian Reichel 	int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC);
21028c0984e5SSebastian Reichel 	int ret, i;
21038c0984e5SSebastian Reichel 	u8 statval;
21048c0984e5SSebastian Reichel 
21058c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
21068c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
21078c0984e5SSebastian Reichel 							AB8500_CHARGER,
21088c0984e5SSebastian Reichel 							AB8500_CH_USBCH_STAT1_REG,
21098c0984e5SSebastian Reichel 							&statval);
21108c0984e5SSebastian Reichel 		if (ret < 0) {
21118c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
21128c0984e5SSebastian Reichel 			goto reschedule;
21138c0984e5SSebastian Reichel 		}
21148c0984e5SSebastian Reichel 		if ((statval & usbch) != usbch)
21158c0984e5SSebastian Reichel 			goto reschedule;
21168c0984e5SSebastian Reichel 
21178c0984e5SSebastian Reichel 		msleep(CHARGER_STATUS_POLL);
21188c0984e5SSebastian Reichel 	}
21198c0984e5SSebastian Reichel 
21208c0984e5SSebastian Reichel 	ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0);
21218c0984e5SSebastian Reichel 
21228c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
21238c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
21248c0984e5SSebastian Reichel 
21258c0984e5SSebastian Reichel 	return;
21268c0984e5SSebastian Reichel 
21278c0984e5SSebastian Reichel reschedule:
21288c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
21298c0984e5SSebastian Reichel 			   &di->usb_charger_attached_work,
21308c0984e5SSebastian Reichel 			   HZ);
21318c0984e5SSebastian Reichel }
21328c0984e5SSebastian Reichel 
ab8500_charger_ac_attached_work(struct work_struct * work)21338c0984e5SSebastian Reichel static void ab8500_charger_ac_attached_work(struct work_struct *work)
21348c0984e5SSebastian Reichel {
21358c0984e5SSebastian Reichel 
21368c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
21378c0984e5SSebastian Reichel 						 struct ab8500_charger,
21388c0984e5SSebastian Reichel 						 ac_charger_attached_work.work);
21398c0984e5SSebastian Reichel 	int mainch = (MAIN_CH_STATUS2_MAINCHGDROP |
21408c0984e5SSebastian Reichel 		      MAIN_CH_STATUS2_MAINCHARGERDETDBNC);
21418c0984e5SSebastian Reichel 	int ret, i;
21428c0984e5SSebastian Reichel 	u8 statval;
21438c0984e5SSebastian Reichel 
21448c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
21458c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
21468c0984e5SSebastian Reichel 							AB8500_CHARGER,
21478c0984e5SSebastian Reichel 							AB8500_CH_STATUS2_REG,
21488c0984e5SSebastian Reichel 							&statval);
21498c0984e5SSebastian Reichel 		if (ret < 0) {
21508c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
21518c0984e5SSebastian Reichel 			goto reschedule;
21528c0984e5SSebastian Reichel 		}
21538c0984e5SSebastian Reichel 
21548c0984e5SSebastian Reichel 		if ((statval & mainch) != mainch)
21558c0984e5SSebastian Reichel 			goto reschedule;
21568c0984e5SSebastian Reichel 
21578c0984e5SSebastian Reichel 		msleep(CHARGER_STATUS_POLL);
21588c0984e5SSebastian Reichel 	}
21598c0984e5SSebastian Reichel 
21608c0984e5SSebastian Reichel 	ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0);
21618c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
21628c0984e5SSebastian Reichel 
21638c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
21648c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
21658c0984e5SSebastian Reichel 
21668c0984e5SSebastian Reichel 	return;
21678c0984e5SSebastian Reichel 
21688c0984e5SSebastian Reichel reschedule:
21698c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
21708c0984e5SSebastian Reichel 			   &di->ac_charger_attached_work,
21718c0984e5SSebastian Reichel 			   HZ);
21728c0984e5SSebastian Reichel }
21738c0984e5SSebastian Reichel 
21748c0984e5SSebastian Reichel /**
21758c0984e5SSebastian Reichel  * ab8500_charger_detect_usb_type_work() - work to detect USB type
21768c0984e5SSebastian Reichel  * @work:	Pointer to the work_struct structure
21778c0984e5SSebastian Reichel  *
21788c0984e5SSebastian Reichel  * Detect the type of USB plugged
21798c0984e5SSebastian Reichel  */
ab8500_charger_detect_usb_type_work(struct work_struct * work)21808c0984e5SSebastian Reichel static void ab8500_charger_detect_usb_type_work(struct work_struct *work)
21818c0984e5SSebastian Reichel {
21828c0984e5SSebastian Reichel 	int ret;
21838c0984e5SSebastian Reichel 
21848c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
21858c0984e5SSebastian Reichel 		struct ab8500_charger, detect_usb_type_work);
21868c0984e5SSebastian Reichel 
21878c0984e5SSebastian Reichel 	/*
21888c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
21898c0984e5SSebastian Reichel 	 * synchronously, we have the check if is
21908c0984e5SSebastian Reichel 	 * connected by reading the status register
21918c0984e5SSebastian Reichel 	 */
21928c0984e5SSebastian Reichel 	ret = ab8500_charger_detect_chargers(di, false);
21938c0984e5SSebastian Reichel 	if (ret < 0)
21948c0984e5SSebastian Reichel 		return;
21958c0984e5SSebastian Reichel 
21968c0984e5SSebastian Reichel 	if (!(ret & USB_PW_CONN)) {
21978c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__);
21988c0984e5SSebastian Reichel 		di->vbus_detected = false;
21998c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
22008c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
22018c0984e5SSebastian Reichel 	} else {
22028c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__);
22038c0984e5SSebastian Reichel 		di->vbus_detected = true;
22048c0984e5SSebastian Reichel 
22058c0984e5SSebastian Reichel 		if (is_ab8500_1p1_or_earlier(di->parent)) {
22068c0984e5SSebastian Reichel 			ret = ab8500_charger_detect_usb_type(di);
22078c0984e5SSebastian Reichel 			if (!ret) {
22088c0984e5SSebastian Reichel 				ab8500_charger_set_usb_connected(di, true);
22098c0984e5SSebastian Reichel 				ab8500_power_supply_changed(di,
22108c0984e5SSebastian Reichel 							    di->usb_chg.psy);
22118c0984e5SSebastian Reichel 			}
22128c0984e5SSebastian Reichel 		} else {
22138c0984e5SSebastian Reichel 			/*
22148c0984e5SSebastian Reichel 			 * For ABB cut2.0 and onwards we have an IRQ,
22158c0984e5SSebastian Reichel 			 * USB_LINK_STATUS that will be triggered when the USB
22168c0984e5SSebastian Reichel 			 * link status changes. The exception is USB connected
22178c0984e5SSebastian Reichel 			 * during startup. Then we don't get a
22188c0984e5SSebastian Reichel 			 * USB_LINK_STATUS IRQ
22198c0984e5SSebastian Reichel 			 */
22208c0984e5SSebastian Reichel 			if (di->vbus_detected_start) {
22218c0984e5SSebastian Reichel 				di->vbus_detected_start = false;
22228c0984e5SSebastian Reichel 				ret = ab8500_charger_detect_usb_type(di);
22238c0984e5SSebastian Reichel 				if (!ret) {
22248c0984e5SSebastian Reichel 					ab8500_charger_set_usb_connected(di,
22258c0984e5SSebastian Reichel 						true);
22268c0984e5SSebastian Reichel 					ab8500_power_supply_changed(di,
22278c0984e5SSebastian Reichel 						di->usb_chg.psy);
22288c0984e5SSebastian Reichel 				}
22298c0984e5SSebastian Reichel 			}
22308c0984e5SSebastian Reichel 		}
22318c0984e5SSebastian Reichel 	}
22328c0984e5SSebastian Reichel }
22338c0984e5SSebastian Reichel 
22348c0984e5SSebastian Reichel /**
22358c0984e5SSebastian Reichel  * ab8500_charger_usb_link_attach_work() - work to detect USB type
22368c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
22378c0984e5SSebastian Reichel  *
22388c0984e5SSebastian Reichel  * Detect the type of USB plugged
22398c0984e5SSebastian Reichel  */
ab8500_charger_usb_link_attach_work(struct work_struct * work)22408c0984e5SSebastian Reichel static void ab8500_charger_usb_link_attach_work(struct work_struct *work)
22418c0984e5SSebastian Reichel {
22428c0984e5SSebastian Reichel 	struct ab8500_charger *di =
22438c0984e5SSebastian Reichel 		container_of(work, struct ab8500_charger, attach_work.work);
22448c0984e5SSebastian Reichel 	int ret;
22458c0984e5SSebastian Reichel 
22468c0984e5SSebastian Reichel 	/* Update maximum input current if USB enumeration is not detected */
22478c0984e5SSebastian Reichel 	if (!di->usb.charger_online) {
22488c0984e5SSebastian Reichel 		ret = ab8500_charger_set_vbus_in_curr(di,
224983e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
22508c0984e5SSebastian Reichel 		if (ret)
22518c0984e5SSebastian Reichel 			return;
22528c0984e5SSebastian Reichel 	}
22538c0984e5SSebastian Reichel 
22548c0984e5SSebastian Reichel 	ab8500_charger_set_usb_connected(di, true);
22558c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
22568c0984e5SSebastian Reichel }
22578c0984e5SSebastian Reichel 
22588c0984e5SSebastian Reichel /**
22598c0984e5SSebastian Reichel  * ab8500_charger_usb_link_status_work() - work to detect USB type
22608c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
22618c0984e5SSebastian Reichel  *
22628c0984e5SSebastian Reichel  * Detect the type of USB plugged
22638c0984e5SSebastian Reichel  */
ab8500_charger_usb_link_status_work(struct work_struct * work)22648c0984e5SSebastian Reichel static void ab8500_charger_usb_link_status_work(struct work_struct *work)
22658c0984e5SSebastian Reichel {
22668c0984e5SSebastian Reichel 	int detected_chargers;
22678c0984e5SSebastian Reichel 	int ret;
22688c0984e5SSebastian Reichel 	u8 val;
22698c0984e5SSebastian Reichel 	u8 link_status;
22708c0984e5SSebastian Reichel 
22718c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
22728c0984e5SSebastian Reichel 		struct ab8500_charger, usb_link_status_work);
22738c0984e5SSebastian Reichel 
22748c0984e5SSebastian Reichel 	/*
22758c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
22768c0984e5SSebastian Reichel 	 * synchronously, we have the check if  is
22778c0984e5SSebastian Reichel 	 * connected by reading the status register
22788c0984e5SSebastian Reichel 	 */
22798c0984e5SSebastian Reichel 	detected_chargers = ab8500_charger_detect_chargers(di, false);
22808c0984e5SSebastian Reichel 	if (detected_chargers < 0)
22818c0984e5SSebastian Reichel 		return;
22828c0984e5SSebastian Reichel 
22838c0984e5SSebastian Reichel 	/*
22848c0984e5SSebastian Reichel 	 * Some chargers that breaks the USB spec is
22858c0984e5SSebastian Reichel 	 * identified as invalid by AB8500 and it refuse
22868c0984e5SSebastian Reichel 	 * to start the charging process. but by jumping
2287ddb74e98SAshish Chavan 	 * through a few hoops it can be forced to start.
22888c0984e5SSebastian Reichel 	 */
22898c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
22908c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
22918c0984e5SSebastian Reichel 					AB8500_USB_LINE_STAT_REG, &val);
22928c0984e5SSebastian Reichel 	else
22938c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
22948c0984e5SSebastian Reichel 					AB8500_USB_LINK1_STAT_REG, &val);
22958c0984e5SSebastian Reichel 
22968c0984e5SSebastian Reichel 	if (ret >= 0)
22978c0984e5SSebastian Reichel 		dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val);
22988c0984e5SSebastian Reichel 	else
22998c0984e5SSebastian Reichel 		dev_dbg(di->dev, "Error reading USB link status\n");
23008c0984e5SSebastian Reichel 
23018c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
23028c0984e5SSebastian Reichel 		link_status = AB8500_USB_LINK_STATUS;
23038c0984e5SSebastian Reichel 	else
23048c0984e5SSebastian Reichel 		link_status = AB8505_USB_LINK_STATUS;
23058c0984e5SSebastian Reichel 
23068c0984e5SSebastian Reichel 	if (detected_chargers & USB_PW_CONN) {
23078c0984e5SSebastian Reichel 		if (((val & link_status) >> USB_LINK_STATUS_SHIFT) ==
23088c0984e5SSebastian Reichel 				USB_STAT_NOT_VALID_LINK &&
23098c0984e5SSebastian Reichel 				di->invalid_charger_detect_state == 0) {
23108c0984e5SSebastian Reichel 			dev_dbg(di->dev,
23118c0984e5SSebastian Reichel 					"Invalid charger detected, state= 0\n");
23128c0984e5SSebastian Reichel 			/*Enable charger*/
23138c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23148c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_USBCH_CTRL1_REG,
23158c0984e5SSebastian Reichel 					USB_CH_ENA, USB_CH_ENA);
23168c0984e5SSebastian Reichel 			/*Enable charger detection*/
23178c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23188c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
23198c0984e5SSebastian Reichel 					USB_CH_DET, USB_CH_DET);
23208c0984e5SSebastian Reichel 			di->invalid_charger_detect_state = 1;
23218c0984e5SSebastian Reichel 			/*exit and wait for new link status interrupt.*/
23228c0984e5SSebastian Reichel 			return;
23238c0984e5SSebastian Reichel 
23248c0984e5SSebastian Reichel 		}
23258c0984e5SSebastian Reichel 		if (di->invalid_charger_detect_state == 1) {
23268c0984e5SSebastian Reichel 			dev_dbg(di->dev,
23278c0984e5SSebastian Reichel 					"Invalid charger detected, state= 1\n");
23288c0984e5SSebastian Reichel 			/*Stop charger detection*/
23298c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23308c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
23318c0984e5SSebastian Reichel 					USB_CH_DET, 0x00);
23328c0984e5SSebastian Reichel 			/*Check link status*/
23338c0984e5SSebastian Reichel 			if (is_ab8500(di->parent))
23348c0984e5SSebastian Reichel 				ret = abx500_get_register_interruptible(di->dev,
23358c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_STAT_REG,
23368c0984e5SSebastian Reichel 					&val);
23378c0984e5SSebastian Reichel 			else
23388c0984e5SSebastian Reichel 				ret = abx500_get_register_interruptible(di->dev,
23398c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINK1_STAT_REG,
23408c0984e5SSebastian Reichel 					&val);
23418c0984e5SSebastian Reichel 
23428c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB link status= 0x%02x\n",
23438c0984e5SSebastian Reichel 				(val & link_status) >> USB_LINK_STATUS_SHIFT);
23448c0984e5SSebastian Reichel 			di->invalid_charger_detect_state = 2;
23458c0984e5SSebastian Reichel 		}
23468c0984e5SSebastian Reichel 	} else {
23478c0984e5SSebastian Reichel 		di->invalid_charger_detect_state = 0;
23488c0984e5SSebastian Reichel 	}
23498c0984e5SSebastian Reichel 
23508c0984e5SSebastian Reichel 	if (!(detected_chargers & USB_PW_CONN)) {
23518c0984e5SSebastian Reichel 		di->vbus_detected = false;
23528c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
23538c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
23548c0984e5SSebastian Reichel 		return;
23558c0984e5SSebastian Reichel 	}
23568c0984e5SSebastian Reichel 
23578c0984e5SSebastian Reichel 	dev_dbg(di->dev,"%s di->vbus_detected = true\n",__func__);
23588c0984e5SSebastian Reichel 	di->vbus_detected = true;
23598c0984e5SSebastian Reichel 	ret = ab8500_charger_read_usb_type(di);
23608c0984e5SSebastian Reichel 	if (ret) {
23618c0984e5SSebastian Reichel 		if (ret == -ENXIO) {
23628c0984e5SSebastian Reichel 			/* No valid charger type detected */
23638c0984e5SSebastian Reichel 			ab8500_charger_set_usb_connected(di, false);
23648c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
23658c0984e5SSebastian Reichel 		}
23668c0984e5SSebastian Reichel 		return;
23678c0984e5SSebastian Reichel 	}
23688c0984e5SSebastian Reichel 
23698c0984e5SSebastian Reichel 	if (di->usb_device_is_unrecognised) {
23708c0984e5SSebastian Reichel 		dev_dbg(di->dev,
23718c0984e5SSebastian Reichel 			"Potential Legacy Charger device. "
23728c0984e5SSebastian Reichel 			"Delay work for %d msec for USB enum "
23738c0984e5SSebastian Reichel 			"to finish",
23748c0984e5SSebastian Reichel 			WAIT_ACA_RID_ENUMERATION);
23758c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
23768c0984e5SSebastian Reichel 				   &di->attach_work,
23778c0984e5SSebastian Reichel 				   msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION));
23788c0984e5SSebastian Reichel 	} else if (di->is_aca_rid == 1) {
23798c0984e5SSebastian Reichel 		/* Only wait once */
23808c0984e5SSebastian Reichel 		di->is_aca_rid++;
23818c0984e5SSebastian Reichel 		dev_dbg(di->dev,
23828c0984e5SSebastian Reichel 			"%s Wait %d msec for USB enum to finish",
23838c0984e5SSebastian Reichel 			__func__, WAIT_ACA_RID_ENUMERATION);
23848c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
23858c0984e5SSebastian Reichel 				   &di->attach_work,
23868c0984e5SSebastian Reichel 				   msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION));
23878c0984e5SSebastian Reichel 	} else {
23888c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
23898c0984e5SSebastian Reichel 				   &di->attach_work,
23908c0984e5SSebastian Reichel 				   0);
23918c0984e5SSebastian Reichel 	}
23928c0984e5SSebastian Reichel }
23938c0984e5SSebastian Reichel 
ab8500_charger_usb_state_changed_work(struct work_struct * work)23948c0984e5SSebastian Reichel static void ab8500_charger_usb_state_changed_work(struct work_struct *work)
23958c0984e5SSebastian Reichel {
23968c0984e5SSebastian Reichel 	int ret;
23978c0984e5SSebastian Reichel 	unsigned long flags;
23988c0984e5SSebastian Reichel 
23998c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
24008c0984e5SSebastian Reichel 		struct ab8500_charger, usb_state_changed_work.work);
24018c0984e5SSebastian Reichel 
24028c0984e5SSebastian Reichel 	if (!di->vbus_detected)	{
24038c0984e5SSebastian Reichel 		dev_dbg(di->dev,
24048c0984e5SSebastian Reichel 			"%s !di->vbus_detected\n",
24058c0984e5SSebastian Reichel 			__func__);
24068c0984e5SSebastian Reichel 		return;
24078c0984e5SSebastian Reichel 	}
24088c0984e5SSebastian Reichel 
24098c0984e5SSebastian Reichel 	spin_lock_irqsave(&di->usb_state.usb_lock, flags);
24108c0984e5SSebastian Reichel 	di->usb_state.state = di->usb_state.state_tmp;
241183e5aa77SLinus Walleij 	di->usb_state.usb_current_ua = di->usb_state.usb_current_tmp_ua;
24128c0984e5SSebastian Reichel 	spin_unlock_irqrestore(&di->usb_state.usb_lock, flags);
24138c0984e5SSebastian Reichel 
241483e5aa77SLinus Walleij 	dev_dbg(di->dev, "%s USB state: 0x%02x uA: %d\n",
241583e5aa77SLinus Walleij 		__func__, di->usb_state.state, di->usb_state.usb_current_ua);
24168c0984e5SSebastian Reichel 
24178c0984e5SSebastian Reichel 	switch (di->usb_state.state) {
24188c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESET_HS:
24198c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESET_FS:
24208c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_SUSPEND:
24218c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_MAX:
24228c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
24238c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
24248c0984e5SSebastian Reichel 		break;
24258c0984e5SSebastian Reichel 
24268c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESUME:
24278c0984e5SSebastian Reichel 		/*
24288c0984e5SSebastian Reichel 		 * when suspend->resume there should be delay
24298c0984e5SSebastian Reichel 		 * of 1sec for enabling charging
24308c0984e5SSebastian Reichel 		 */
24318c0984e5SSebastian Reichel 		msleep(1000);
2432df561f66SGustavo A. R. Silva 		fallthrough;
24338c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_CONFIGURED:
24348c0984e5SSebastian Reichel 		/*
24358c0984e5SSebastian Reichel 		 * USB is configured, enable charging with the charging
24368c0984e5SSebastian Reichel 		 * input current obtained from USB driver
24378c0984e5SSebastian Reichel 		 */
24388c0984e5SSebastian Reichel 		if (!ab8500_charger_get_usb_cur(di)) {
24398c0984e5SSebastian Reichel 			/* Update maximum input current */
24408c0984e5SSebastian Reichel 			ret = ab8500_charger_set_vbus_in_curr(di,
244183e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
24428c0984e5SSebastian Reichel 			if (ret)
24438c0984e5SSebastian Reichel 				return;
24448c0984e5SSebastian Reichel 
24458c0984e5SSebastian Reichel 			ab8500_charger_set_usb_connected(di, true);
24468c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
24478c0984e5SSebastian Reichel 		}
24488c0984e5SSebastian Reichel 		break;
24498c0984e5SSebastian Reichel 
24508c0984e5SSebastian Reichel 	default:
24518c0984e5SSebastian Reichel 		break;
2452e15c54d2SMa Feng 	}
24538c0984e5SSebastian Reichel }
24548c0984e5SSebastian Reichel 
24558c0984e5SSebastian Reichel /**
24568c0984e5SSebastian Reichel  * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status
24578c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
24588c0984e5SSebastian Reichel  *
24598c0984e5SSebastian Reichel  * Work queue function for checking the USB charger Not OK status
24608c0984e5SSebastian Reichel  */
ab8500_charger_check_usbchargernotok_work(struct work_struct * work)24618c0984e5SSebastian Reichel static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work)
24628c0984e5SSebastian Reichel {
24638c0984e5SSebastian Reichel 	int ret;
24648c0984e5SSebastian Reichel 	u8 reg_value;
24658c0984e5SSebastian Reichel 	bool prev_status;
24668c0984e5SSebastian Reichel 
24678c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
24688c0984e5SSebastian Reichel 		struct ab8500_charger, check_usbchgnotok_work.work);
24698c0984e5SSebastian Reichel 
24708c0984e5SSebastian Reichel 	/* Check if the status bit for usbchargernotok is still active */
24718c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
24728c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
24738c0984e5SSebastian Reichel 	if (ret < 0) {
24748c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
24758c0984e5SSebastian Reichel 		return;
24768c0984e5SSebastian Reichel 	}
24778c0984e5SSebastian Reichel 	prev_status = di->flags.usbchargernotok;
24788c0984e5SSebastian Reichel 
24798c0984e5SSebastian Reichel 	if (reg_value & VBUS_CH_NOK) {
24808c0984e5SSebastian Reichel 		di->flags.usbchargernotok = true;
24818c0984e5SSebastian Reichel 		/* Check again in 1sec */
24828c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
24838c0984e5SSebastian Reichel 			&di->check_usbchgnotok_work, HZ);
24848c0984e5SSebastian Reichel 	} else {
24858c0984e5SSebastian Reichel 		di->flags.usbchargernotok = false;
24868c0984e5SSebastian Reichel 		di->flags.vbus_collapse = false;
24878c0984e5SSebastian Reichel 	}
24888c0984e5SSebastian Reichel 
24898c0984e5SSebastian Reichel 	if (prev_status != di->flags.usbchargernotok)
24908c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
24918c0984e5SSebastian Reichel }
24928c0984e5SSebastian Reichel 
24938c0984e5SSebastian Reichel /**
24948c0984e5SSebastian Reichel  * ab8500_charger_check_main_thermal_prot_work() - check main thermal status
24958c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
24968c0984e5SSebastian Reichel  *
24978c0984e5SSebastian Reichel  * Work queue function for checking the Main thermal prot status
24988c0984e5SSebastian Reichel  */
ab8500_charger_check_main_thermal_prot_work(struct work_struct * work)24998c0984e5SSebastian Reichel static void ab8500_charger_check_main_thermal_prot_work(
25008c0984e5SSebastian Reichel 	struct work_struct *work)
25018c0984e5SSebastian Reichel {
25028c0984e5SSebastian Reichel 	int ret;
25038c0984e5SSebastian Reichel 	u8 reg_value;
25048c0984e5SSebastian Reichel 
25058c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
25068c0984e5SSebastian Reichel 		struct ab8500_charger, check_main_thermal_prot_work);
25078c0984e5SSebastian Reichel 
25088c0984e5SSebastian Reichel 	/* Check if the status bit for main_thermal_prot is still active */
25098c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
25108c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
25118c0984e5SSebastian Reichel 	if (ret < 0) {
25128c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
25138c0984e5SSebastian Reichel 		return;
25148c0984e5SSebastian Reichel 	}
25158c0984e5SSebastian Reichel 	if (reg_value & MAIN_CH_TH_PROT)
25168c0984e5SSebastian Reichel 		di->flags.main_thermal_prot = true;
25178c0984e5SSebastian Reichel 	else
25188c0984e5SSebastian Reichel 		di->flags.main_thermal_prot = false;
25198c0984e5SSebastian Reichel 
25208c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
25218c0984e5SSebastian Reichel }
25228c0984e5SSebastian Reichel 
25238c0984e5SSebastian Reichel /**
25248c0984e5SSebastian Reichel  * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status
25258c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
25268c0984e5SSebastian Reichel  *
25278c0984e5SSebastian Reichel  * Work queue function for checking the USB thermal prot status
25288c0984e5SSebastian Reichel  */
ab8500_charger_check_usb_thermal_prot_work(struct work_struct * work)25298c0984e5SSebastian Reichel static void ab8500_charger_check_usb_thermal_prot_work(
25308c0984e5SSebastian Reichel 	struct work_struct *work)
25318c0984e5SSebastian Reichel {
25328c0984e5SSebastian Reichel 	int ret;
25338c0984e5SSebastian Reichel 	u8 reg_value;
25348c0984e5SSebastian Reichel 
25358c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
25368c0984e5SSebastian Reichel 		struct ab8500_charger, check_usb_thermal_prot_work);
25378c0984e5SSebastian Reichel 
25388c0984e5SSebastian Reichel 	/* Check if the status bit for usb_thermal_prot is still active */
25398c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
25408c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
25418c0984e5SSebastian Reichel 	if (ret < 0) {
25428c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
25438c0984e5SSebastian Reichel 		return;
25448c0984e5SSebastian Reichel 	}
25458c0984e5SSebastian Reichel 	if (reg_value & USB_CH_TH_PROT)
25468c0984e5SSebastian Reichel 		di->flags.usb_thermal_prot = true;
25478c0984e5SSebastian Reichel 	else
25488c0984e5SSebastian Reichel 		di->flags.usb_thermal_prot = false;
25498c0984e5SSebastian Reichel 
25508c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
25518c0984e5SSebastian Reichel }
25528c0984e5SSebastian Reichel 
25538c0984e5SSebastian Reichel /**
25548c0984e5SSebastian Reichel  * ab8500_charger_mainchunplugdet_handler() - main charger unplugged
25558c0984e5SSebastian Reichel  * @irq:       interrupt number
25568c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
25578c0984e5SSebastian Reichel  *
25588c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
25598c0984e5SSebastian Reichel  */
ab8500_charger_mainchunplugdet_handler(int irq,void * _di)25608c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di)
25618c0984e5SSebastian Reichel {
25628c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
25638c0984e5SSebastian Reichel 
25648c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger unplugged\n");
25658c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
25668c0984e5SSebastian Reichel 
25678c0984e5SSebastian Reichel 	cancel_delayed_work_sync(&di->ac_charger_attached_work);
25688c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
25698c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
25708c0984e5SSebastian Reichel 
25718c0984e5SSebastian Reichel 	return IRQ_HANDLED;
25728c0984e5SSebastian Reichel }
25738c0984e5SSebastian Reichel 
25748c0984e5SSebastian Reichel /**
25758c0984e5SSebastian Reichel  * ab8500_charger_mainchplugdet_handler() - main charger plugged
25768c0984e5SSebastian Reichel  * @irq:       interrupt number
25778c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
25788c0984e5SSebastian Reichel  *
25798c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
25808c0984e5SSebastian Reichel  */
ab8500_charger_mainchplugdet_handler(int irq,void * _di)25818c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di)
25828c0984e5SSebastian Reichel {
25838c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
25848c0984e5SSebastian Reichel 
25858c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger plugged\n");
25868c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
25878c0984e5SSebastian Reichel 
25888c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
25898c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
25908c0984e5SSebastian Reichel 
25918c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
25928c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
25938c0984e5SSebastian Reichel 			   &di->ac_charger_attached_work,
25948c0984e5SSebastian Reichel 			   HZ);
25958c0984e5SSebastian Reichel 	return IRQ_HANDLED;
25968c0984e5SSebastian Reichel }
25978c0984e5SSebastian Reichel 
25988c0984e5SSebastian Reichel /**
25998c0984e5SSebastian Reichel  * ab8500_charger_mainextchnotok_handler() - main charger not ok
26008c0984e5SSebastian Reichel  * @irq:       interrupt number
26018c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26028c0984e5SSebastian Reichel  *
26038c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26048c0984e5SSebastian Reichel  */
ab8500_charger_mainextchnotok_handler(int irq,void * _di)26058c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di)
26068c0984e5SSebastian Reichel {
26078c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26088c0984e5SSebastian Reichel 
26098c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger not ok\n");
26108c0984e5SSebastian Reichel 	di->flags.mainextchnotok = true;
26118c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
26128c0984e5SSebastian Reichel 
26138c0984e5SSebastian Reichel 	/* Schedule a new HW failure check */
26148c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
26158c0984e5SSebastian Reichel 
26168c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26178c0984e5SSebastian Reichel }
26188c0984e5SSebastian Reichel 
26198c0984e5SSebastian Reichel /**
26208c0984e5SSebastian Reichel  * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger
26218c0984e5SSebastian Reichel  * thermal protection threshold
26228c0984e5SSebastian Reichel  * @irq:       interrupt number
26238c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26248c0984e5SSebastian Reichel  *
26258c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26268c0984e5SSebastian Reichel  */
ab8500_charger_mainchthprotr_handler(int irq,void * _di)26278c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di)
26288c0984e5SSebastian Reichel {
26298c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26308c0984e5SSebastian Reichel 
26318c0984e5SSebastian Reichel 	dev_dbg(di->dev,
26328c0984e5SSebastian Reichel 		"Die temp above Main charger thermal protection threshold\n");
26338c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
26348c0984e5SSebastian Reichel 
26358c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26368c0984e5SSebastian Reichel }
26378c0984e5SSebastian Reichel 
26388c0984e5SSebastian Reichel /**
26398c0984e5SSebastian Reichel  * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger
26408c0984e5SSebastian Reichel  * thermal protection threshold
26418c0984e5SSebastian Reichel  * @irq:       interrupt number
26428c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26438c0984e5SSebastian Reichel  *
26448c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26458c0984e5SSebastian Reichel  */
ab8500_charger_mainchthprotf_handler(int irq,void * _di)26468c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di)
26478c0984e5SSebastian Reichel {
26488c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26498c0984e5SSebastian Reichel 
26508c0984e5SSebastian Reichel 	dev_dbg(di->dev,
26518c0984e5SSebastian Reichel 		"Die temp ok for Main charger thermal protection threshold\n");
26528c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
26538c0984e5SSebastian Reichel 
26548c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26558c0984e5SSebastian Reichel }
26568c0984e5SSebastian Reichel 
ab8500_charger_vbus_drop_end_work(struct work_struct * work)26578c0984e5SSebastian Reichel static void ab8500_charger_vbus_drop_end_work(struct work_struct *work)
26588c0984e5SSebastian Reichel {
26598c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
26608c0984e5SSebastian Reichel 		struct ab8500_charger, vbus_drop_end_work.work);
266183e5aa77SLinus Walleij 	int ret, curr_ua;
26628c0984e5SSebastian Reichel 	u8 reg_value;
26638c0984e5SSebastian Reichel 
26648c0984e5SSebastian Reichel 	di->flags.vbus_drop_end = false;
26658c0984e5SSebastian Reichel 
26668c0984e5SSebastian Reichel 	/* Reset the drop counter */
26678c0984e5SSebastian Reichel 	abx500_set_register_interruptible(di->dev,
26688c0984e5SSebastian Reichel 				  AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01);
26698c0984e5SSebastian Reichel 
26708c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
26718c0984e5SSebastian Reichel 			AB8500_CH_USBCH_STAT2_REG, &reg_value);
26728c0984e5SSebastian Reichel 	if (ret < 0) {
26738c0984e5SSebastian Reichel 		dev_err(di->dev, "%s read failed\n", __func__);
26748c0984e5SSebastian Reichel 		return;
26758c0984e5SSebastian Reichel 	}
26768c0984e5SSebastian Reichel 
267783e5aa77SLinus Walleij 	curr_ua = ab8500_charge_input_curr_map[
26788c0984e5SSebastian Reichel 		reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT];
26798c0984e5SSebastian Reichel 
268083e5aa77SLinus Walleij 	if (di->max_usb_in_curr.calculated_max_ua != curr_ua) {
26818c0984e5SSebastian Reichel 		/* USB source is collapsing */
268283e5aa77SLinus Walleij 		di->max_usb_in_curr.calculated_max_ua = curr_ua;
26838c0984e5SSebastian Reichel 		dev_dbg(di->dev,
268483e5aa77SLinus Walleij 			 "VBUS input current limiting to %d uA\n",
268583e5aa77SLinus Walleij 			 di->max_usb_in_curr.calculated_max_ua);
26868c0984e5SSebastian Reichel 	} else {
26878c0984e5SSebastian Reichel 		/*
26888c0984e5SSebastian Reichel 		 * USB source can not give more than this amount.
26898c0984e5SSebastian Reichel 		 * Taking more will collapse the source.
26908c0984e5SSebastian Reichel 		 */
269183e5aa77SLinus Walleij 		di->max_usb_in_curr.set_max_ua =
269283e5aa77SLinus Walleij 			di->max_usb_in_curr.calculated_max_ua;
26938c0984e5SSebastian Reichel 		dev_dbg(di->dev,
269483e5aa77SLinus Walleij 			 "VBUS input current limited to %d uA\n",
269583e5aa77SLinus Walleij 			 di->max_usb_in_curr.set_max_ua);
26968c0984e5SSebastian Reichel 	}
26978c0984e5SSebastian Reichel 
26988c0984e5SSebastian Reichel 	if (di->usb.charger_connected)
26998c0984e5SSebastian Reichel 		ab8500_charger_set_vbus_in_curr(di,
270083e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
27018c0984e5SSebastian Reichel }
27028c0984e5SSebastian Reichel 
27038c0984e5SSebastian Reichel /**
27048c0984e5SSebastian Reichel  * ab8500_charger_vbusdetf_handler() - VBUS falling detected
27058c0984e5SSebastian Reichel  * @irq:       interrupt number
27068c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27078c0984e5SSebastian Reichel  *
27088c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27098c0984e5SSebastian Reichel  */
ab8500_charger_vbusdetf_handler(int irq,void * _di)27108c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di)
27118c0984e5SSebastian Reichel {
27128c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27138c0984e5SSebastian Reichel 
27148c0984e5SSebastian Reichel 	di->vbus_detected = false;
27158c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS falling detected\n");
27168c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->detect_usb_type_work);
27178c0984e5SSebastian Reichel 
27188c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27198c0984e5SSebastian Reichel }
27208c0984e5SSebastian Reichel 
27218c0984e5SSebastian Reichel /**
27228c0984e5SSebastian Reichel  * ab8500_charger_vbusdetr_handler() - VBUS rising detected
27238c0984e5SSebastian Reichel  * @irq:       interrupt number
27248c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27258c0984e5SSebastian Reichel  *
27268c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27278c0984e5SSebastian Reichel  */
ab8500_charger_vbusdetr_handler(int irq,void * _di)27288c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di)
27298c0984e5SSebastian Reichel {
27308c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27318c0984e5SSebastian Reichel 
27328c0984e5SSebastian Reichel 	di->vbus_detected = true;
27338c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS rising detected\n");
27348c0984e5SSebastian Reichel 
27358c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->detect_usb_type_work);
27368c0984e5SSebastian Reichel 
27378c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27388c0984e5SSebastian Reichel }
27398c0984e5SSebastian Reichel 
27408c0984e5SSebastian Reichel /**
27418c0984e5SSebastian Reichel  * ab8500_charger_usblinkstatus_handler() - USB link status has changed
27428c0984e5SSebastian Reichel  * @irq:       interrupt number
27438c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27448c0984e5SSebastian Reichel  *
27458c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27468c0984e5SSebastian Reichel  */
ab8500_charger_usblinkstatus_handler(int irq,void * _di)27478c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di)
27488c0984e5SSebastian Reichel {
27498c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27508c0984e5SSebastian Reichel 
27518c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB link status changed\n");
27528c0984e5SSebastian Reichel 
27538c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->usb_link_status_work);
27548c0984e5SSebastian Reichel 
27558c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27568c0984e5SSebastian Reichel }
27578c0984e5SSebastian Reichel 
27588c0984e5SSebastian Reichel /**
27598c0984e5SSebastian Reichel  * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger
27608c0984e5SSebastian Reichel  * thermal protection threshold
27618c0984e5SSebastian Reichel  * @irq:       interrupt number
27628c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27638c0984e5SSebastian Reichel  *
27648c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27658c0984e5SSebastian Reichel  */
ab8500_charger_usbchthprotr_handler(int irq,void * _di)27668c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di)
27678c0984e5SSebastian Reichel {
27688c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27698c0984e5SSebastian Reichel 
27708c0984e5SSebastian Reichel 	dev_dbg(di->dev,
27718c0984e5SSebastian Reichel 		"Die temp above USB charger thermal protection threshold\n");
27728c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
27738c0984e5SSebastian Reichel 
27748c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27758c0984e5SSebastian Reichel }
27768c0984e5SSebastian Reichel 
27778c0984e5SSebastian Reichel /**
27788c0984e5SSebastian Reichel  * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger
27798c0984e5SSebastian Reichel  * thermal protection threshold
27808c0984e5SSebastian Reichel  * @irq:       interrupt number
27818c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27828c0984e5SSebastian Reichel  *
27838c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27848c0984e5SSebastian Reichel  */
ab8500_charger_usbchthprotf_handler(int irq,void * _di)27858c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di)
27868c0984e5SSebastian Reichel {
27878c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27888c0984e5SSebastian Reichel 
27898c0984e5SSebastian Reichel 	dev_dbg(di->dev,
27908c0984e5SSebastian Reichel 		"Die temp ok for USB charger thermal protection threshold\n");
27918c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
27928c0984e5SSebastian Reichel 
27938c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27948c0984e5SSebastian Reichel }
27958c0984e5SSebastian Reichel 
27968c0984e5SSebastian Reichel /**
27978c0984e5SSebastian Reichel  * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected
27988c0984e5SSebastian Reichel  * @irq:       interrupt number
27998c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28008c0984e5SSebastian Reichel  *
28018c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28028c0984e5SSebastian Reichel  */
ab8500_charger_usbchargernotokr_handler(int irq,void * _di)28038c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di)
28048c0984e5SSebastian Reichel {
28058c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28068c0984e5SSebastian Reichel 
28078c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Not allowed USB charger detected\n");
28088c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0);
28098c0984e5SSebastian Reichel 
28108c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28118c0984e5SSebastian Reichel }
28128c0984e5SSebastian Reichel 
28138c0984e5SSebastian Reichel /**
28148c0984e5SSebastian Reichel  * ab8500_charger_chwdexp_handler() - Charger watchdog expired
28158c0984e5SSebastian Reichel  * @irq:       interrupt number
28168c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28178c0984e5SSebastian Reichel  *
28188c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28198c0984e5SSebastian Reichel  */
ab8500_charger_chwdexp_handler(int irq,void * _di)28208c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di)
28218c0984e5SSebastian Reichel {
28228c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28238c0984e5SSebastian Reichel 
28248c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Charger watchdog expired\n");
28258c0984e5SSebastian Reichel 
28268c0984e5SSebastian Reichel 	/*
28278c0984e5SSebastian Reichel 	 * The charger that was online when the watchdog expired
28288c0984e5SSebastian Reichel 	 * needs to be restarted for charging to start again
28298c0984e5SSebastian Reichel 	 */
28308c0984e5SSebastian Reichel 	if (di->ac.charger_online) {
28318c0984e5SSebastian Reichel 		di->ac.wd_expired = true;
28328c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->ac_chg.psy);
28338c0984e5SSebastian Reichel 	}
28348c0984e5SSebastian Reichel 	if (di->usb.charger_online) {
28358c0984e5SSebastian Reichel 		di->usb.wd_expired = true;
28368c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
28378c0984e5SSebastian Reichel 	}
28388c0984e5SSebastian Reichel 
28398c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28408c0984e5SSebastian Reichel }
28418c0984e5SSebastian Reichel 
28428c0984e5SSebastian Reichel /**
28438c0984e5SSebastian Reichel  * ab8500_charger_vbuschdropend_handler() - VBUS drop removed
28448c0984e5SSebastian Reichel  * @irq:       interrupt number
28458c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28468c0984e5SSebastian Reichel  *
28478c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28488c0984e5SSebastian Reichel  */
ab8500_charger_vbuschdropend_handler(int irq,void * _di)28498c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di)
28508c0984e5SSebastian Reichel {
28518c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28528c0984e5SSebastian Reichel 
28538c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS charger drop ended\n");
28548c0984e5SSebastian Reichel 	di->flags.vbus_drop_end = true;
28558c0984e5SSebastian Reichel 
28568c0984e5SSebastian Reichel 	/*
28578c0984e5SSebastian Reichel 	 * VBUS might have dropped due to bad connection.
28588c0984e5SSebastian Reichel 	 * Schedule a new input limit set to the value SW requests.
28598c0984e5SSebastian Reichel 	 */
28608c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work,
28618c0984e5SSebastian Reichel 			   round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ));
28628c0984e5SSebastian Reichel 
28638c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28648c0984e5SSebastian Reichel }
28658c0984e5SSebastian Reichel 
28668c0984e5SSebastian Reichel /**
28678c0984e5SSebastian Reichel  * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected
28688c0984e5SSebastian Reichel  * @irq:       interrupt number
28698c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28708c0984e5SSebastian Reichel  *
28718c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28728c0984e5SSebastian Reichel  */
ab8500_charger_vbusovv_handler(int irq,void * _di)28738c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di)
28748c0984e5SSebastian Reichel {
28758c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28768c0984e5SSebastian Reichel 
28778c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS overvoltage detected\n");
28788c0984e5SSebastian Reichel 	di->flags.vbus_ovv = true;
28798c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
28808c0984e5SSebastian Reichel 
28818c0984e5SSebastian Reichel 	/* Schedule a new HW failure check */
28828c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
28838c0984e5SSebastian Reichel 
28848c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28858c0984e5SSebastian Reichel }
28868c0984e5SSebastian Reichel 
28878c0984e5SSebastian Reichel /**
28888c0984e5SSebastian Reichel  * ab8500_charger_ac_get_property() - get the ac/mains properties
28898c0984e5SSebastian Reichel  * @psy:       pointer to the power_supply structure
28908c0984e5SSebastian Reichel  * @psp:       pointer to the power_supply_property structure
28918c0984e5SSebastian Reichel  * @val:       pointer to the power_supply_propval union
28928c0984e5SSebastian Reichel  *
28938c0984e5SSebastian Reichel  * This function gets called when an application tries to get the ac/mains
28948c0984e5SSebastian Reichel  * properties by reading the sysfs files.
28958c0984e5SSebastian Reichel  * AC/Mains properties are online, present and voltage.
28968c0984e5SSebastian Reichel  * online:     ac/mains charging is in progress or not
28978c0984e5SSebastian Reichel  * present:    presence of the ac/mains
28988c0984e5SSebastian Reichel  * voltage:    AC/Mains voltage
28998c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
29008c0984e5SSebastian Reichel  */
ab8500_charger_ac_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)29018c0984e5SSebastian Reichel static int ab8500_charger_ac_get_property(struct power_supply *psy,
29028c0984e5SSebastian Reichel 	enum power_supply_property psp,
29038c0984e5SSebastian Reichel 	union power_supply_propval *val)
29048c0984e5SSebastian Reichel {
29058c0984e5SSebastian Reichel 	struct ab8500_charger *di;
29068c0984e5SSebastian Reichel 	int ret;
29078c0984e5SSebastian Reichel 
29088c0984e5SSebastian Reichel 	di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy));
29098c0984e5SSebastian Reichel 
29108c0984e5SSebastian Reichel 	switch (psp) {
29118c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_HEALTH:
29128c0984e5SSebastian Reichel 		if (di->flags.mainextchnotok)
29138c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
29148c0984e5SSebastian Reichel 		else if (di->ac.wd_expired || di->usb.wd_expired)
29158c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
29168c0984e5SSebastian Reichel 		else if (di->flags.main_thermal_prot)
29178c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
29188c0984e5SSebastian Reichel 		else
29198c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
29208c0984e5SSebastian Reichel 		break;
29218c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_ONLINE:
29228c0984e5SSebastian Reichel 		val->intval = di->ac.charger_online;
29238c0984e5SSebastian Reichel 		break;
29248c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_PRESENT:
29258c0984e5SSebastian Reichel 		val->intval = di->ac.charger_connected;
29268c0984e5SSebastian Reichel 		break;
29278c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
29288c0984e5SSebastian Reichel 		ret = ab8500_charger_get_ac_voltage(di);
29298c0984e5SSebastian Reichel 		if (ret >= 0)
2930bc6e0287SLinus Walleij 			di->ac.charger_voltage_uv = ret;
29318c0984e5SSebastian Reichel 		/* On error, use previous value */
2932bc6e0287SLinus Walleij 		val->intval = di->ac.charger_voltage_uv;
29338c0984e5SSebastian Reichel 		break;
29348c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
29358c0984e5SSebastian Reichel 		/*
29368c0984e5SSebastian Reichel 		 * This property is used to indicate when CV mode is entered
29378c0984e5SSebastian Reichel 		 * for the AC charger
29388c0984e5SSebastian Reichel 		 */
29398c0984e5SSebastian Reichel 		di->ac.cv_active = ab8500_charger_ac_cv(di);
29408c0984e5SSebastian Reichel 		val->intval = di->ac.cv_active;
29418c0984e5SSebastian Reichel 		break;
29428c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_NOW:
29438c0984e5SSebastian Reichel 		ret = ab8500_charger_get_ac_current(di);
29448c0984e5SSebastian Reichel 		if (ret >= 0)
294583e5aa77SLinus Walleij 			di->ac.charger_current_ua = ret;
294683e5aa77SLinus Walleij 		val->intval = di->ac.charger_current_ua;
29478c0984e5SSebastian Reichel 		break;
29488c0984e5SSebastian Reichel 	default:
29498c0984e5SSebastian Reichel 		return -EINVAL;
29508c0984e5SSebastian Reichel 	}
29518c0984e5SSebastian Reichel 	return 0;
29528c0984e5SSebastian Reichel }
29538c0984e5SSebastian Reichel 
29548c0984e5SSebastian Reichel /**
29558c0984e5SSebastian Reichel  * ab8500_charger_usb_get_property() - get the usb properties
29568c0984e5SSebastian Reichel  * @psy:        pointer to the power_supply structure
29578c0984e5SSebastian Reichel  * @psp:        pointer to the power_supply_property structure
29588c0984e5SSebastian Reichel  * @val:        pointer to the power_supply_propval union
29598c0984e5SSebastian Reichel  *
29608c0984e5SSebastian Reichel  * This function gets called when an application tries to get the usb
29618c0984e5SSebastian Reichel  * properties by reading the sysfs files.
29628c0984e5SSebastian Reichel  * USB properties are online, present and voltage.
29638c0984e5SSebastian Reichel  * online:     usb charging is in progress or not
29648c0984e5SSebastian Reichel  * present:    presence of the usb
29658c0984e5SSebastian Reichel  * voltage:    vbus voltage
29668c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
29678c0984e5SSebastian Reichel  */
ab8500_charger_usb_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)29688c0984e5SSebastian Reichel static int ab8500_charger_usb_get_property(struct power_supply *psy,
29698c0984e5SSebastian Reichel 	enum power_supply_property psp,
29708c0984e5SSebastian Reichel 	union power_supply_propval *val)
29718c0984e5SSebastian Reichel {
29728c0984e5SSebastian Reichel 	struct ab8500_charger *di;
29738c0984e5SSebastian Reichel 	int ret;
29748c0984e5SSebastian Reichel 
29758c0984e5SSebastian Reichel 	di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy));
29768c0984e5SSebastian Reichel 
29778c0984e5SSebastian Reichel 	switch (psp) {
29788c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_HEALTH:
29798c0984e5SSebastian Reichel 		if (di->flags.usbchargernotok)
29808c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
29818c0984e5SSebastian Reichel 		else if (di->ac.wd_expired || di->usb.wd_expired)
29828c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
29838c0984e5SSebastian Reichel 		else if (di->flags.usb_thermal_prot)
29848c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
29858c0984e5SSebastian Reichel 		else if (di->flags.vbus_ovv)
29868c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
29878c0984e5SSebastian Reichel 		else
29888c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
29898c0984e5SSebastian Reichel 		break;
29908c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_ONLINE:
29918c0984e5SSebastian Reichel 		val->intval = di->usb.charger_online;
29928c0984e5SSebastian Reichel 		break;
29938c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_PRESENT:
29948c0984e5SSebastian Reichel 		val->intval = di->usb.charger_connected;
29958c0984e5SSebastian Reichel 		break;
29968c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
29978c0984e5SSebastian Reichel 		ret = ab8500_charger_get_vbus_voltage(di);
29988c0984e5SSebastian Reichel 		if (ret >= 0)
2999bc6e0287SLinus Walleij 			di->usb.charger_voltage_uv = ret;
3000bc6e0287SLinus Walleij 		val->intval = di->usb.charger_voltage_uv;
30018c0984e5SSebastian Reichel 		break;
30028c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
30038c0984e5SSebastian Reichel 		/*
30048c0984e5SSebastian Reichel 		 * This property is used to indicate when CV mode is entered
30058c0984e5SSebastian Reichel 		 * for the USB charger
30068c0984e5SSebastian Reichel 		 */
30078c0984e5SSebastian Reichel 		di->usb.cv_active = ab8500_charger_usb_cv(di);
30088c0984e5SSebastian Reichel 		val->intval = di->usb.cv_active;
30098c0984e5SSebastian Reichel 		break;
30108c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_NOW:
30118c0984e5SSebastian Reichel 		ret = ab8500_charger_get_usb_current(di);
30128c0984e5SSebastian Reichel 		if (ret >= 0)
301383e5aa77SLinus Walleij 			di->usb.charger_current_ua = ret;
301483e5aa77SLinus Walleij 		val->intval = di->usb.charger_current_ua;
30158c0984e5SSebastian Reichel 		break;
30168c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_AVG:
30178c0984e5SSebastian Reichel 		/*
30188c0984e5SSebastian Reichel 		 * This property is used to indicate when VBUS has collapsed
30198c0984e5SSebastian Reichel 		 * due to too high output current from the USB charger
30208c0984e5SSebastian Reichel 		 */
30218c0984e5SSebastian Reichel 		if (di->flags.vbus_collapse)
30228c0984e5SSebastian Reichel 			val->intval = 1;
30238c0984e5SSebastian Reichel 		else
30248c0984e5SSebastian Reichel 			val->intval = 0;
30258c0984e5SSebastian Reichel 		break;
30268c0984e5SSebastian Reichel 	default:
30278c0984e5SSebastian Reichel 		return -EINVAL;
30288c0984e5SSebastian Reichel 	}
30298c0984e5SSebastian Reichel 	return 0;
30308c0984e5SSebastian Reichel }
30318c0984e5SSebastian Reichel 
30328c0984e5SSebastian Reichel /**
30338c0984e5SSebastian Reichel  * ab8500_charger_init_hw_registers() - Set up charger related registers
30348c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
30358c0984e5SSebastian Reichel  *
30368c0984e5SSebastian Reichel  * Set up charger OVV, watchdog and maximum voltage registers as well as
30378c0984e5SSebastian Reichel  * charging of the backup battery
30388c0984e5SSebastian Reichel  */
ab8500_charger_init_hw_registers(struct ab8500_charger * di)30398c0984e5SSebastian Reichel static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
30408c0984e5SSebastian Reichel {
30418c0984e5SSebastian Reichel 	int ret = 0;
30428c0984e5SSebastian Reichel 
30438c0984e5SSebastian Reichel 	/* Setup maximum charger current and voltage for ABB cut2.0 */
30448c0984e5SSebastian Reichel 	if (!is_ab8500_1p1_or_earlier(di->parent)) {
30458c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30468c0984e5SSebastian Reichel 			AB8500_CHARGER,
30478c0984e5SSebastian Reichel 			AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6);
30488c0984e5SSebastian Reichel 		if (ret) {
30498c0984e5SSebastian Reichel 			dev_err(di->dev,
30508c0984e5SSebastian Reichel 				"failed to set CH_VOLT_LVL_MAX_REG\n");
30518c0984e5SSebastian Reichel 			goto out;
30528c0984e5SSebastian Reichel 		}
30538c0984e5SSebastian Reichel 
30548c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30558c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG,
30568c0984e5SSebastian Reichel 			CH_OP_CUR_LVL_1P6);
30578c0984e5SSebastian Reichel 		if (ret) {
30588c0984e5SSebastian Reichel 			dev_err(di->dev,
30598c0984e5SSebastian Reichel 				"failed to set CH_OPT_CRNTLVL_MAX_REG\n");
30608c0984e5SSebastian Reichel 			goto out;
30618c0984e5SSebastian Reichel 		}
30628c0984e5SSebastian Reichel 	}
30638c0984e5SSebastian Reichel 
30644c4268dcSLinus Walleij 	if (is_ab8505_2p0(di->parent))
30658c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
30668c0984e5SSebastian Reichel 			AB8500_CHARGER,
30678c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL2_REG,
30688c0984e5SSebastian Reichel 			VBUS_AUTO_IN_CURR_LIM_ENA,
30698c0984e5SSebastian Reichel 			VBUS_AUTO_IN_CURR_LIM_ENA);
30708c0984e5SSebastian Reichel 	else
30718c0984e5SSebastian Reichel 		/*
30728c0984e5SSebastian Reichel 		 * VBUS OVV set to 6.3V and enable automatic current limitation
30738c0984e5SSebastian Reichel 		 */
30748c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30758c0984e5SSebastian Reichel 			AB8500_CHARGER,
30768c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL2_REG,
30778c0984e5SSebastian Reichel 			VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA);
30788c0984e5SSebastian Reichel 	if (ret) {
30798c0984e5SSebastian Reichel 		dev_err(di->dev,
30808c0984e5SSebastian Reichel 			"failed to set automatic current limitation\n");
30818c0984e5SSebastian Reichel 		goto out;
30828c0984e5SSebastian Reichel 	}
30838c0984e5SSebastian Reichel 
30848c0984e5SSebastian Reichel 	/* Enable main watchdog in OTP */
30858c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
30868c0984e5SSebastian Reichel 		AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD);
30878c0984e5SSebastian Reichel 	if (ret) {
30888c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to enable main WD in OTP\n");
30898c0984e5SSebastian Reichel 		goto out;
30908c0984e5SSebastian Reichel 	}
30918c0984e5SSebastian Reichel 
30928c0984e5SSebastian Reichel 	/* Enable main watchdog */
30938c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
30948c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
30958c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA);
30968c0984e5SSebastian Reichel 	if (ret) {
3097b5e11cc1SColin Ian King 		dev_err(di->dev, "failed to enable main watchdog\n");
30988c0984e5SSebastian Reichel 		goto out;
30998c0984e5SSebastian Reichel 	}
31008c0984e5SSebastian Reichel 
31018c0984e5SSebastian Reichel 	/*
31028c0984e5SSebastian Reichel 	 * Due to internal synchronisation, Enable and Kick watchdog bits
31038c0984e5SSebastian Reichel 	 * cannot be enabled in a single write.
31048c0984e5SSebastian Reichel 	 * A minimum delay of 2*32 kHz period (62.5µs) must be inserted
31058c0984e5SSebastian Reichel 	 * between writing Enable then Kick bits.
31068c0984e5SSebastian Reichel 	 */
31078c0984e5SSebastian Reichel 	udelay(63);
31088c0984e5SSebastian Reichel 
31098c0984e5SSebastian Reichel 	/* Kick main watchdog */
31108c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31118c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31128c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG,
31138c0984e5SSebastian Reichel 		(MAIN_WDOG_ENA | MAIN_WDOG_KICK));
31148c0984e5SSebastian Reichel 	if (ret) {
31158c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to kick main watchdog\n");
31168c0984e5SSebastian Reichel 		goto out;
31178c0984e5SSebastian Reichel 	}
31188c0984e5SSebastian Reichel 
31198c0984e5SSebastian Reichel 	/* Disable main watchdog */
31208c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31218c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31228c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS);
31238c0984e5SSebastian Reichel 	if (ret) {
31248c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to disable main watchdog\n");
31258c0984e5SSebastian Reichel 		goto out;
31268c0984e5SSebastian Reichel 	}
31278c0984e5SSebastian Reichel 
31288c0984e5SSebastian Reichel 	/* Set watchdog timeout */
31298c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
31308c0984e5SSebastian Reichel 		AB8500_CH_WD_TIMER_REG, WD_TIMER);
31318c0984e5SSebastian Reichel 	if (ret) {
31328c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to set charger watchdog timeout\n");
31338c0984e5SSebastian Reichel 		goto out;
31348c0984e5SSebastian Reichel 	}
31358c0984e5SSebastian Reichel 
31368c0984e5SSebastian Reichel 	ret = ab8500_charger_led_en(di, false);
31378c0984e5SSebastian Reichel 	if (ret < 0) {
31388c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to disable LED\n");
31398c0984e5SSebastian Reichel 		goto out;
31408c0984e5SSebastian Reichel 	}
31418c0984e5SSebastian Reichel 
31428c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31438c0984e5SSebastian Reichel 		AB8500_RTC,
31448c0984e5SSebastian Reichel 		AB8500_RTC_BACKUP_CHG_REG,
31458c0984e5SSebastian Reichel 		(di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i);
31468c0984e5SSebastian Reichel 	if (ret) {
31478c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to setup backup battery charging\n");
31488c0984e5SSebastian Reichel 		goto out;
31498c0984e5SSebastian Reichel 	}
31508c0984e5SSebastian Reichel 
31518c0984e5SSebastian Reichel 	/* Enable backup battery charging */
3152bf59fdddSChristophe JAILLET 	ret = abx500_mask_and_set_register_interruptible(di->dev,
31538c0984e5SSebastian Reichel 		AB8500_RTC, AB8500_RTC_CTRL_REG,
31548c0984e5SSebastian Reichel 		RTC_BUP_CH_ENA, RTC_BUP_CH_ENA);
315509edcb64SChristophe JAILLET 	if (ret < 0) {
31568c0984e5SSebastian Reichel 		dev_err(di->dev, "%s mask and set failed\n", __func__);
315709edcb64SChristophe JAILLET 		goto out;
315809edcb64SChristophe JAILLET 	}
31598c0984e5SSebastian Reichel 
31608c0984e5SSebastian Reichel out:
31618c0984e5SSebastian Reichel 	return ret;
31628c0984e5SSebastian Reichel }
31638c0984e5SSebastian Reichel 
31648c0984e5SSebastian Reichel /*
31658c0984e5SSebastian Reichel  * ab8500 charger driver interrupts and their respective isr
31668c0984e5SSebastian Reichel  */
31678c0984e5SSebastian Reichel static struct ab8500_charger_interrupts ab8500_charger_irq[] = {
31688c0984e5SSebastian Reichel 	{"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler},
31698c0984e5SSebastian Reichel 	{"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler},
31708c0984e5SSebastian Reichel 	{"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler},
31718c0984e5SSebastian Reichel 	{"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler},
31728c0984e5SSebastian Reichel 	{"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler},
31738c0984e5SSebastian Reichel 	{"VBUS_DET_F", ab8500_charger_vbusdetf_handler},
31748c0984e5SSebastian Reichel 	{"VBUS_DET_R", ab8500_charger_vbusdetr_handler},
31758c0984e5SSebastian Reichel 	{"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler},
31768c0984e5SSebastian Reichel 	{"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler},
31778c0984e5SSebastian Reichel 	{"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler},
31788c0984e5SSebastian Reichel 	{"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler},
31798c0984e5SSebastian Reichel 	{"VBUS_OVV", ab8500_charger_vbusovv_handler},
31808c0984e5SSebastian Reichel 	{"CH_WD_EXP", ab8500_charger_chwdexp_handler},
31818c0984e5SSebastian Reichel 	{"VBUS_CH_DROP_END", ab8500_charger_vbuschdropend_handler},
31828c0984e5SSebastian Reichel };
31838c0984e5SSebastian Reichel 
ab8500_charger_usb_notifier_call(struct notifier_block * nb,unsigned long event,void * power)31848c0984e5SSebastian Reichel static int ab8500_charger_usb_notifier_call(struct notifier_block *nb,
31858c0984e5SSebastian Reichel 		unsigned long event, void *power)
31868c0984e5SSebastian Reichel {
31878c0984e5SSebastian Reichel 	struct ab8500_charger *di =
31888c0984e5SSebastian Reichel 		container_of(nb, struct ab8500_charger, nb);
31898c0984e5SSebastian Reichel 	enum ab8500_usb_state bm_usb_state;
319083e5aa77SLinus Walleij 	/*
319183e5aa77SLinus Walleij 	 * FIXME: it appears the AB8500 PHY never sends what it should here.
319283e5aa77SLinus Walleij 	 * Fix the PHY driver to properly notify the desired current.
319383e5aa77SLinus Walleij 	 * Also broadcast microampere and not milliampere.
319483e5aa77SLinus Walleij 	 */
31958c0984e5SSebastian Reichel 	unsigned mA = *((unsigned *)power);
31968c0984e5SSebastian Reichel 
31978c0984e5SSebastian Reichel 	if (event != USB_EVENT_VBUS) {
31988c0984e5SSebastian Reichel 		dev_dbg(di->dev, "not a standard host, returning\n");
31998c0984e5SSebastian Reichel 		return NOTIFY_DONE;
32008c0984e5SSebastian Reichel 	}
32018c0984e5SSebastian Reichel 
32028c0984e5SSebastian Reichel 	/* TODO: State is fabricate  here. See if charger really needs USB
32038c0984e5SSebastian Reichel 	 * state or if mA is enough
32048c0984e5SSebastian Reichel 	 */
320583e5aa77SLinus Walleij 	if ((di->usb_state.usb_current_ua == 2000) && (mA > 2))
32068c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESUME;
32078c0984e5SSebastian Reichel 	else if (mA == 0)
32088c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESET_HS;
32098c0984e5SSebastian Reichel 	else if (mA == 2)
32108c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_SUSPEND;
32118c0984e5SSebastian Reichel 	else if (mA >= 8) /* 8, 100, 500 */
32128c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED;
32138c0984e5SSebastian Reichel 	else /* Should never occur */
32148c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESET_FS;
32158c0984e5SSebastian Reichel 
32168c0984e5SSebastian Reichel 	dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n",
32178c0984e5SSebastian Reichel 		__func__, bm_usb_state, mA);
32188c0984e5SSebastian Reichel 
32198c0984e5SSebastian Reichel 	spin_lock(&di->usb_state.usb_lock);
32208c0984e5SSebastian Reichel 	di->usb_state.state_tmp = bm_usb_state;
322183e5aa77SLinus Walleij 	/* FIXME: broadcast ua instead, see above */
322283e5aa77SLinus Walleij 	di->usb_state.usb_current_tmp_ua = mA * 1000;
32238c0984e5SSebastian Reichel 	spin_unlock(&di->usb_state.usb_lock);
32248c0984e5SSebastian Reichel 
32258c0984e5SSebastian Reichel 	/*
32268c0984e5SSebastian Reichel 	 * wait for some time until you get updates from the usb stack
32278c0984e5SSebastian Reichel 	 * and negotiations are completed
32288c0984e5SSebastian Reichel 	 */
32298c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->usb_state_changed_work, HZ/2);
32308c0984e5SSebastian Reichel 
32318c0984e5SSebastian Reichel 	return NOTIFY_OK;
32328c0984e5SSebastian Reichel }
32338c0984e5SSebastian Reichel 
ab8500_charger_resume(struct device * dev)3234f8efa0a8SLinus Walleij static int __maybe_unused ab8500_charger_resume(struct device *dev)
32358c0984e5SSebastian Reichel {
32368c0984e5SSebastian Reichel 	int ret;
3237f8efa0a8SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
32388c0984e5SSebastian Reichel 
32398c0984e5SSebastian Reichel 	/*
32408c0984e5SSebastian Reichel 	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
3241ddb74e98SAshish Chavan 	 * logic. That means we have to continuously kick the charger
32428c0984e5SSebastian Reichel 	 * watchdog even when no charger is connected. This is only
32438c0984e5SSebastian Reichel 	 * valid once the AC charger has been enabled. This is
32448c0984e5SSebastian Reichel 	 * a bug that is not handled by the algorithm and the
32458c0984e5SSebastian Reichel 	 * watchdog have to be kicked by the charger driver
32468c0984e5SSebastian Reichel 	 * when the AC charger is disabled
32478c0984e5SSebastian Reichel 	 */
32488c0984e5SSebastian Reichel 	if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) {
32498c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
32508c0984e5SSebastian Reichel 			AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
32518c0984e5SSebastian Reichel 		if (ret)
32528c0984e5SSebastian Reichel 			dev_err(di->dev, "Failed to kick WD!\n");
32538c0984e5SSebastian Reichel 
32548c0984e5SSebastian Reichel 		/* If not already pending start a new timer */
32558c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->kick_wd_work,
32568c0984e5SSebastian Reichel 				   round_jiffies(WD_KICK_INTERVAL));
32578c0984e5SSebastian Reichel 	}
32588c0984e5SSebastian Reichel 
32598c0984e5SSebastian Reichel 	/* If we still have a HW failure, schedule a new check */
32608c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
32618c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
32628c0984e5SSebastian Reichel 			&di->check_hw_failure_work, 0);
32638c0984e5SSebastian Reichel 	}
32648c0984e5SSebastian Reichel 
32658c0984e5SSebastian Reichel 	if (di->flags.vbus_drop_end)
32668c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 0);
32678c0984e5SSebastian Reichel 
32688c0984e5SSebastian Reichel 	return 0;
32698c0984e5SSebastian Reichel }
32708c0984e5SSebastian Reichel 
ab8500_charger_suspend(struct device * dev)3271f8efa0a8SLinus Walleij static int __maybe_unused ab8500_charger_suspend(struct device *dev)
32728c0984e5SSebastian Reichel {
3273f8efa0a8SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
32748c0984e5SSebastian Reichel 
32758c0984e5SSebastian Reichel 	/* Cancel any pending jobs */
32768c0984e5SSebastian Reichel 	cancel_delayed_work(&di->check_hw_failure_work);
32778c0984e5SSebastian Reichel 	cancel_delayed_work(&di->vbus_drop_end_work);
32788c0984e5SSebastian Reichel 
32798c0984e5SSebastian Reichel 	flush_delayed_work(&di->attach_work);
32808c0984e5SSebastian Reichel 	flush_delayed_work(&di->usb_charger_attached_work);
32818c0984e5SSebastian Reichel 	flush_delayed_work(&di->ac_charger_attached_work);
32828c0984e5SSebastian Reichel 	flush_delayed_work(&di->check_usbchgnotok_work);
32838c0984e5SSebastian Reichel 	flush_delayed_work(&di->check_vbat_work);
32848c0984e5SSebastian Reichel 	flush_delayed_work(&di->kick_wd_work);
32858c0984e5SSebastian Reichel 
32868c0984e5SSebastian Reichel 	flush_work(&di->usb_link_status_work);
32878c0984e5SSebastian Reichel 	flush_work(&di->ac_work);
32888c0984e5SSebastian Reichel 	flush_work(&di->detect_usb_type_work);
32898c0984e5SSebastian Reichel 
32908c0984e5SSebastian Reichel 	if (atomic_read(&di->current_stepping_sessions))
32918c0984e5SSebastian Reichel 		return -EAGAIN;
32928c0984e5SSebastian Reichel 
32938c0984e5SSebastian Reichel 	return 0;
32948c0984e5SSebastian Reichel }
32958c0984e5SSebastian Reichel 
32968c0984e5SSebastian Reichel static char *supply_interface[] = {
32978c0984e5SSebastian Reichel 	"ab8500_chargalg",
32988c0984e5SSebastian Reichel 	"ab8500_fg",
32998c0984e5SSebastian Reichel 	"ab8500_btemp",
33008c0984e5SSebastian Reichel };
33018c0984e5SSebastian Reichel 
33028c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_ac_chg_desc = {
33038c0984e5SSebastian Reichel 	.name		= "ab8500_ac",
33048c0984e5SSebastian Reichel 	.type		= POWER_SUPPLY_TYPE_MAINS,
33058c0984e5SSebastian Reichel 	.properties	= ab8500_charger_ac_props,
33068c0984e5SSebastian Reichel 	.num_properties	= ARRAY_SIZE(ab8500_charger_ac_props),
33078c0984e5SSebastian Reichel 	.get_property	= ab8500_charger_ac_get_property,
33088c0984e5SSebastian Reichel };
33098c0984e5SSebastian Reichel 
33108c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_usb_chg_desc = {
33118c0984e5SSebastian Reichel 	.name		= "ab8500_usb",
33128c0984e5SSebastian Reichel 	.type		= POWER_SUPPLY_TYPE_USB,
33138c0984e5SSebastian Reichel 	.properties	= ab8500_charger_usb_props,
33148c0984e5SSebastian Reichel 	.num_properties	= ARRAY_SIZE(ab8500_charger_usb_props),
33158c0984e5SSebastian Reichel 	.get_property	= ab8500_charger_usb_get_property,
33168c0984e5SSebastian Reichel };
33178c0984e5SSebastian Reichel 
ab8500_charger_bind(struct device * dev)33181c1f13a0SLinus Walleij static int ab8500_charger_bind(struct device *dev)
33191c1f13a0SLinus Walleij {
33201c1f13a0SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
33211c1f13a0SLinus Walleij 	int ch_stat;
33221c1f13a0SLinus Walleij 	int ret;
33231c1f13a0SLinus Walleij 
33241c1f13a0SLinus Walleij 	/* Create a work queue for the charger */
33251c1f13a0SLinus Walleij 	di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq",
33261c1f13a0SLinus Walleij 						 WQ_MEM_RECLAIM);
33271c1f13a0SLinus Walleij 	if (di->charger_wq == NULL) {
33281c1f13a0SLinus Walleij 		dev_err(dev, "failed to create work queue\n");
33291c1f13a0SLinus Walleij 		return -ENOMEM;
33301c1f13a0SLinus Walleij 	}
33311c1f13a0SLinus Walleij 
33321c1f13a0SLinus Walleij 	ch_stat = ab8500_charger_detect_chargers(di, false);
33331c1f13a0SLinus Walleij 
33341c1f13a0SLinus Walleij 	if (ch_stat & AC_PW_CONN) {
33351c1f13a0SLinus Walleij 		if (is_ab8500(di->parent))
33361c1f13a0SLinus Walleij 			queue_delayed_work(di->charger_wq,
33371c1f13a0SLinus Walleij 					   &di->ac_charger_attached_work,
33381c1f13a0SLinus Walleij 					   HZ);
33391c1f13a0SLinus Walleij 	}
33401c1f13a0SLinus Walleij 	if (ch_stat & USB_PW_CONN) {
33411c1f13a0SLinus Walleij 		if (is_ab8500(di->parent))
33421c1f13a0SLinus Walleij 			queue_delayed_work(di->charger_wq,
33431c1f13a0SLinus Walleij 					   &di->usb_charger_attached_work,
33441c1f13a0SLinus Walleij 					   HZ);
33451c1f13a0SLinus Walleij 		di->vbus_detected = true;
33461c1f13a0SLinus Walleij 		di->vbus_detected_start = true;
33471c1f13a0SLinus Walleij 		queue_work(di->charger_wq,
33481c1f13a0SLinus Walleij 			   &di->detect_usb_type_work);
33491c1f13a0SLinus Walleij 	}
33501c1f13a0SLinus Walleij 
33511c1f13a0SLinus Walleij 	ret = component_bind_all(dev, di);
33521c1f13a0SLinus Walleij 	if (ret) {
33531c1f13a0SLinus Walleij 		dev_err(dev, "can't bind component devices\n");
335438d45444SZheng Bin 		destroy_workqueue(di->charger_wq);
33551c1f13a0SLinus Walleij 		return ret;
33561c1f13a0SLinus Walleij 	}
33571c1f13a0SLinus Walleij 
33581c1f13a0SLinus Walleij 	return 0;
33591c1f13a0SLinus Walleij }
33601c1f13a0SLinus Walleij 
ab8500_charger_unbind(struct device * dev)33611c1f13a0SLinus Walleij static void ab8500_charger_unbind(struct device *dev)
33621c1f13a0SLinus Walleij {
33631c1f13a0SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
33641c1f13a0SLinus Walleij 	int ret;
33651c1f13a0SLinus Walleij 
33661c1f13a0SLinus Walleij 	/* Disable AC charging */
33671c1f13a0SLinus Walleij 	ab8500_charger_ac_en(&di->ac_chg, false, 0, 0);
33681c1f13a0SLinus Walleij 
33691c1f13a0SLinus Walleij 	/* Disable USB charging */
33701c1f13a0SLinus Walleij 	ab8500_charger_usb_en(&di->usb_chg, false, 0, 0);
33711c1f13a0SLinus Walleij 
33721c1f13a0SLinus Walleij 	/* Backup battery voltage and current disable */
33731c1f13a0SLinus Walleij 	ret = abx500_mask_and_set_register_interruptible(di->dev,
33741c1f13a0SLinus Walleij 		AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0);
33751c1f13a0SLinus Walleij 	if (ret < 0)
33761c1f13a0SLinus Walleij 		dev_err(di->dev, "%s mask and set failed\n", __func__);
33771c1f13a0SLinus Walleij 
33781c1f13a0SLinus Walleij 	/* Delete the work queue */
33791c1f13a0SLinus Walleij 	destroy_workqueue(di->charger_wq);
33801c1f13a0SLinus Walleij 
33811c1f13a0SLinus Walleij 	/* Unbind fg, btemp, algorithm */
33821c1f13a0SLinus Walleij 	component_unbind_all(dev, di);
33831c1f13a0SLinus Walleij }
33841c1f13a0SLinus Walleij 
33851c1f13a0SLinus Walleij static const struct component_master_ops ab8500_charger_comp_ops = {
33861c1f13a0SLinus Walleij 	.bind = ab8500_charger_bind,
33871c1f13a0SLinus Walleij 	.unbind = ab8500_charger_unbind,
33881c1f13a0SLinus Walleij };
33891c1f13a0SLinus Walleij 
33901c1f13a0SLinus Walleij static struct platform_driver *const ab8500_charger_component_drivers[] = {
33911c1f13a0SLinus Walleij 	&ab8500_fg_driver,
33921c1f13a0SLinus Walleij 	&ab8500_btemp_driver,
3393c5b64a99SLinus Walleij 	&ab8500_chargalg_driver,
33941c1f13a0SLinus Walleij };
33951c1f13a0SLinus Walleij 
ab8500_charger_probe(struct platform_device * pdev)33968c0984e5SSebastian Reichel static int ab8500_charger_probe(struct platform_device *pdev)
33978c0984e5SSebastian Reichel {
33981c1f13a0SLinus Walleij 	struct device *dev = &pdev->dev;
33991c1f13a0SLinus Walleij 	struct device_node *np = dev->of_node;
34001c1f13a0SLinus Walleij 	struct component_match *match = NULL;
34018c0984e5SSebastian Reichel 	struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {};
34028c0984e5SSebastian Reichel 	struct ab8500_charger *di;
34031c1f13a0SLinus Walleij 	int charger_status;
34041c1f13a0SLinus Walleij 	int i, irq;
34051c1f13a0SLinus Walleij 	int ret;
34068c0984e5SSebastian Reichel 
3407ad89cb5fSLinus Walleij 	di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
3408ad89cb5fSLinus Walleij 	if (!di)
34098c0984e5SSebastian Reichel 		return -ENOMEM;
34108c0984e5SSebastian Reichel 
3411417c0fc2SLinus Walleij 	di->bm = &ab8500_bm_data;
34128c0984e5SSebastian Reichel 
34138c0984e5SSebastian Reichel 	di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
34148c0984e5SSebastian Reichel 
34158c0984e5SSebastian Reichel 	/* get parent data */
3416ad89cb5fSLinus Walleij 	di->dev = dev;
34178c0984e5SSebastian Reichel 	di->parent = dev_get_drvdata(pdev->dev.parent);
341897ab78baSLinus Walleij 
341997ab78baSLinus Walleij 	/* Get ADC channels */
34200f6dad11SLinus Walleij 	if (!is_ab8505(di->parent)) {
342136f1de0dSLinus Walleij 		di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v");
342297ab78baSLinus Walleij 		if (IS_ERR(di->adc_main_charger_v)) {
342336f1de0dSLinus Walleij 			ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_v),
342436f1de0dSLinus Walleij 					    "failed to get ADC main charger voltage\n");
342536f1de0dSLinus Walleij 			return ret;
342697ab78baSLinus Walleij 		}
342736f1de0dSLinus Walleij 		di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c");
342897ab78baSLinus Walleij 		if (IS_ERR(di->adc_main_charger_c)) {
342936f1de0dSLinus Walleij 			ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_c),
343036f1de0dSLinus Walleij 					    "failed to get ADC main charger current\n");
343136f1de0dSLinus Walleij 			return ret;
343297ab78baSLinus Walleij 		}
34330f6dad11SLinus Walleij 	}
3434ad89cb5fSLinus Walleij 	di->adc_vbus_v = devm_iio_channel_get(dev, "vbus_v");
343597ab78baSLinus Walleij 	if (IS_ERR(di->adc_vbus_v)) {
343636f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_vbus_v),
343736f1de0dSLinus Walleij 				    "failed to get ADC USB charger voltage\n");
343836f1de0dSLinus Walleij 		return ret;
343997ab78baSLinus Walleij 	}
344036f1de0dSLinus Walleij 	di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c");
344197ab78baSLinus Walleij 	if (IS_ERR(di->adc_usb_charger_c)) {
344236f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_usb_charger_c),
344336f1de0dSLinus Walleij 				    "failed to get ADC USB charger current\n");
344436f1de0dSLinus Walleij 		return ret;
344597ab78baSLinus Walleij 	}
34468c0984e5SSebastian Reichel 
34471c1f13a0SLinus Walleij 	/*
34481c1f13a0SLinus Walleij 	 * VDD ADC supply needs to be enabled from this driver when there
34491c1f13a0SLinus Walleij 	 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
34501c1f13a0SLinus Walleij 	 * interrupts during charging
34511c1f13a0SLinus Walleij 	 */
34521c1f13a0SLinus Walleij 	di->regu = devm_regulator_get(dev, "vddadc");
34531c1f13a0SLinus Walleij 	if (IS_ERR(di->regu)) {
34541c1f13a0SLinus Walleij 		ret = PTR_ERR(di->regu);
34551c1f13a0SLinus Walleij 		dev_err(dev, "failed to get vddadc regulator\n");
34561c1f13a0SLinus Walleij 		return ret;
34571c1f13a0SLinus Walleij 	}
34581c1f13a0SLinus Walleij 
34591c1f13a0SLinus Walleij 	/* Request interrupts */
34601c1f13a0SLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
34611c1f13a0SLinus Walleij 		irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
34621c1f13a0SLinus Walleij 		if (irq < 0)
34631c1f13a0SLinus Walleij 			return irq;
34641c1f13a0SLinus Walleij 
34651c1f13a0SLinus Walleij 		ret = devm_request_threaded_irq(dev,
34661c1f13a0SLinus Walleij 			irq, NULL, ab8500_charger_irq[i].isr,
34671c1f13a0SLinus Walleij 			IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
34681c1f13a0SLinus Walleij 			ab8500_charger_irq[i].name, di);
34691c1f13a0SLinus Walleij 
34701c1f13a0SLinus Walleij 		if (ret != 0) {
34711c1f13a0SLinus Walleij 			dev_err(dev, "failed to request %s IRQ %d: %d\n"
34721c1f13a0SLinus Walleij 				, ab8500_charger_irq[i].name, irq, ret);
34731c1f13a0SLinus Walleij 			return ret;
34741c1f13a0SLinus Walleij 		}
34751c1f13a0SLinus Walleij 		dev_dbg(dev, "Requested %s IRQ %d: %d\n",
34761c1f13a0SLinus Walleij 			ab8500_charger_irq[i].name, irq, ret);
34771c1f13a0SLinus Walleij 	}
34781c1f13a0SLinus Walleij 
34798c0984e5SSebastian Reichel 	/* initialize lock */
34808c0984e5SSebastian Reichel 	spin_lock_init(&di->usb_state.usb_lock);
34818c0984e5SSebastian Reichel 	mutex_init(&di->usb_ipt_crnt_lock);
34828c0984e5SSebastian Reichel 
34838c0984e5SSebastian Reichel 	di->autopower = false;
34848c0984e5SSebastian Reichel 	di->invalid_charger_detect_state = 0;
34858c0984e5SSebastian Reichel 
34868c0984e5SSebastian Reichel 	/* AC and USB supply config */
348759f1b854SLinus Walleij 	ac_psy_cfg.of_node = np;
34888c0984e5SSebastian Reichel 	ac_psy_cfg.supplied_to = supply_interface;
34898c0984e5SSebastian Reichel 	ac_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
34908c0984e5SSebastian Reichel 	ac_psy_cfg.drv_data = &di->ac_chg;
349159f1b854SLinus Walleij 	usb_psy_cfg.of_node = np;
34928c0984e5SSebastian Reichel 	usb_psy_cfg.supplied_to = supply_interface;
34938c0984e5SSebastian Reichel 	usb_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
34948c0984e5SSebastian Reichel 	usb_psy_cfg.drv_data = &di->usb_chg;
34958c0984e5SSebastian Reichel 
34968c0984e5SSebastian Reichel 	/* AC supply */
34978c0984e5SSebastian Reichel 	/* ux500_charger sub-class */
34988c0984e5SSebastian Reichel 	di->ac_chg.ops.enable = &ab8500_charger_ac_en;
34998c0984e5SSebastian Reichel 	di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable;
35008c0984e5SSebastian Reichel 	di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
35018c0984e5SSebastian Reichel 	di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current;
3502bc6e0287SLinus Walleij 	di->ac_chg.max_out_volt_uv = ab8500_charger_voltage_map[
35038c0984e5SSebastian Reichel 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
350483e5aa77SLinus Walleij 	di->ac_chg.max_out_curr_ua =
35053aca6ecdSLinus Walleij 		ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
35068c0984e5SSebastian Reichel 	di->ac_chg.wdt_refresh = CHG_WD_INTERVAL;
3507f9184a22SLinus Walleij 	/*
3508f9184a22SLinus Walleij 	 * The AB8505 only supports USB charging. If we are not the
3509f9184a22SLinus Walleij 	 * AB8505, register an AC charger.
3510f9184a22SLinus Walleij 	 *
3511f9184a22SLinus Walleij 	 * TODO: if this should be opt-in, add DT properties for this.
3512f9184a22SLinus Walleij 	 */
3513f9184a22SLinus Walleij 	if (!is_ab8505(di->parent))
3514f9184a22SLinus Walleij 		di->ac_chg.enabled = true;
35158c0984e5SSebastian Reichel 
35168c0984e5SSebastian Reichel 	/* USB supply */
35178c0984e5SSebastian Reichel 	/* ux500_charger sub-class */
35188c0984e5SSebastian Reichel 	di->usb_chg.ops.enable = &ab8500_charger_usb_en;
35198c0984e5SSebastian Reichel 	di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
35208c0984e5SSebastian Reichel 	di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
35218c0984e5SSebastian Reichel 	di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current;
3522bc6e0287SLinus Walleij 	di->usb_chg.max_out_volt_uv = ab8500_charger_voltage_map[
35238c0984e5SSebastian Reichel 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
352483e5aa77SLinus Walleij 	di->usb_chg.max_out_curr_ua =
35253aca6ecdSLinus Walleij 		ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
35268c0984e5SSebastian Reichel 	di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
352783e5aa77SLinus Walleij 	di->usb_state.usb_current_ua = -1;
35288c0984e5SSebastian Reichel 
35298c0984e5SSebastian Reichel 	mutex_init(&di->charger_attached_mutex);
35308c0984e5SSebastian Reichel 
35318c0984e5SSebastian Reichel 	/* Init work for HW failure check */
35328c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_hw_failure_work,
35338c0984e5SSebastian Reichel 		ab8500_charger_check_hw_failure_work);
35348c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work,
35358c0984e5SSebastian Reichel 		ab8500_charger_check_usbchargernotok_work);
35368c0984e5SSebastian Reichel 
35378c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->ac_charger_attached_work,
35388c0984e5SSebastian Reichel 			  ab8500_charger_ac_attached_work);
35398c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->usb_charger_attached_work,
35408c0984e5SSebastian Reichel 			  ab8500_charger_usb_attached_work);
35418c0984e5SSebastian Reichel 
35428c0984e5SSebastian Reichel 	/*
35438c0984e5SSebastian Reichel 	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
3544ddb74e98SAshish Chavan 	 * logic. That means we have to continuously kick the charger
35458c0984e5SSebastian Reichel 	 * watchdog even when no charger is connected. This is only
35468c0984e5SSebastian Reichel 	 * valid once the AC charger has been enabled. This is
35478c0984e5SSebastian Reichel 	 * a bug that is not handled by the algorithm and the
35488c0984e5SSebastian Reichel 	 * watchdog have to be kicked by the charger driver
35498c0984e5SSebastian Reichel 	 * when the AC charger is disabled
35508c0984e5SSebastian Reichel 	 */
35518c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->kick_wd_work,
35528c0984e5SSebastian Reichel 		ab8500_charger_kick_watchdog_work);
35538c0984e5SSebastian Reichel 
35548c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_vbat_work,
35558c0984e5SSebastian Reichel 		ab8500_charger_check_vbat_work);
35568c0984e5SSebastian Reichel 
35578c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->attach_work,
35588c0984e5SSebastian Reichel 		ab8500_charger_usb_link_attach_work);
35598c0984e5SSebastian Reichel 
35608c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->usb_state_changed_work,
35618c0984e5SSebastian Reichel 		ab8500_charger_usb_state_changed_work);
35628c0984e5SSebastian Reichel 
35638c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->vbus_drop_end_work,
35648c0984e5SSebastian Reichel 		ab8500_charger_vbus_drop_end_work);
35658c0984e5SSebastian Reichel 
35668c0984e5SSebastian Reichel 	/* Init work for charger detection */
35678c0984e5SSebastian Reichel 	INIT_WORK(&di->usb_link_status_work,
35688c0984e5SSebastian Reichel 		ab8500_charger_usb_link_status_work);
35698c0984e5SSebastian Reichel 	INIT_WORK(&di->ac_work, ab8500_charger_ac_work);
35708c0984e5SSebastian Reichel 	INIT_WORK(&di->detect_usb_type_work,
35718c0984e5SSebastian Reichel 		ab8500_charger_detect_usb_type_work);
35728c0984e5SSebastian Reichel 
35738c0984e5SSebastian Reichel 	/* Init work for checking HW status */
35748c0984e5SSebastian Reichel 	INIT_WORK(&di->check_main_thermal_prot_work,
35758c0984e5SSebastian Reichel 		ab8500_charger_check_main_thermal_prot_work);
35768c0984e5SSebastian Reichel 	INIT_WORK(&di->check_usb_thermal_prot_work,
35778c0984e5SSebastian Reichel 		ab8500_charger_check_usb_thermal_prot_work);
35788c0984e5SSebastian Reichel 
35798c0984e5SSebastian Reichel 
35808c0984e5SSebastian Reichel 	/* Initialize OVV, and other registers */
35818c0984e5SSebastian Reichel 	ret = ab8500_charger_init_hw_registers(di);
35828c0984e5SSebastian Reichel 	if (ret) {
3583ad89cb5fSLinus Walleij 		dev_err(dev, "failed to initialize ABB registers\n");
35841c1f13a0SLinus Walleij 		return ret;
35858c0984e5SSebastian Reichel 	}
35868c0984e5SSebastian Reichel 
35878c0984e5SSebastian Reichel 	/* Register AC charger class */
35888c0984e5SSebastian Reichel 	if (di->ac_chg.enabled) {
35891c1f13a0SLinus Walleij 		di->ac_chg.psy = devm_power_supply_register(dev,
35908c0984e5SSebastian Reichel 						       &ab8500_ac_chg_desc,
35918c0984e5SSebastian Reichel 						       &ac_psy_cfg);
35928c0984e5SSebastian Reichel 		if (IS_ERR(di->ac_chg.psy)) {
3593ad89cb5fSLinus Walleij 			dev_err(dev, "failed to register AC charger\n");
35941c1f13a0SLinus Walleij 			return PTR_ERR(di->ac_chg.psy);
35958c0984e5SSebastian Reichel 		}
35968c0984e5SSebastian Reichel 	}
35978c0984e5SSebastian Reichel 
35988c0984e5SSebastian Reichel 	/* Register USB charger class */
35991c1f13a0SLinus Walleij 	di->usb_chg.psy = devm_power_supply_register(dev,
36008c0984e5SSebastian Reichel 						     &ab8500_usb_chg_desc,
36018c0984e5SSebastian Reichel 						     &usb_psy_cfg);
36028c0984e5SSebastian Reichel 	if (IS_ERR(di->usb_chg.psy)) {
3603ad89cb5fSLinus Walleij 		dev_err(dev, "failed to register USB charger\n");
36041c1f13a0SLinus Walleij 		return PTR_ERR(di->usb_chg.psy);
36058c0984e5SSebastian Reichel 	}
36068c0984e5SSebastian Reichel 
360759f1b854SLinus Walleij 	/*
360859f1b854SLinus Walleij 	 * Check what battery we have, since we always have the USB
360959f1b854SLinus Walleij 	 * psy, use that as a handle.
361059f1b854SLinus Walleij 	 */
361159f1b854SLinus Walleij 	ret = ab8500_bm_of_probe(di->usb_chg.psy, di->bm);
361259f1b854SLinus Walleij 	if (ret)
361359f1b854SLinus Walleij 		return dev_err_probe(dev, ret,
361459f1b854SLinus Walleij 				     "failed to get battery information\n");
361559f1b854SLinus Walleij 
36168c0984e5SSebastian Reichel 	/* Identify the connected charger types during startup */
36178c0984e5SSebastian Reichel 	charger_status = ab8500_charger_detect_chargers(di, true);
36188c0984e5SSebastian Reichel 	if (charger_status & AC_PW_CONN) {
36198c0984e5SSebastian Reichel 		di->ac.charger_connected = 1;
36208c0984e5SSebastian Reichel 		di->ac_conn = true;
36218c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->ac_chg.psy);
36228c0984e5SSebastian Reichel 		sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
36238c0984e5SSebastian Reichel 	}
36248c0984e5SSebastian Reichel 
36258c0984e5SSebastian Reichel 	platform_set_drvdata(pdev, di);
36268c0984e5SSebastian Reichel 
36271c1f13a0SLinus Walleij 	/* Create something that will match the subdrivers when we bind */
36281c1f13a0SLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) {
36291c1f13a0SLinus Walleij 		struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver;
36301c1f13a0SLinus Walleij 		struct device *p = NULL, *d;
36318c0984e5SSebastian Reichel 
36321c1f13a0SLinus Walleij 		while ((d = platform_find_device_by_driver(p, drv))) {
36331c1f13a0SLinus Walleij 			put_device(p);
36345730c81dSYong Wu 			component_match_add(dev, &match, component_compare_dev, d);
36351c1f13a0SLinus Walleij 			p = d;
36368c0984e5SSebastian Reichel 		}
36371c1f13a0SLinus Walleij 		put_device(p);
36381c1f13a0SLinus Walleij 	}
36391c1f13a0SLinus Walleij 	if (!match) {
36401c1f13a0SLinus Walleij 		dev_err(dev, "no matching components\n");
3641be2c0d54SChristophe JAILLET 		ret = -ENODEV;
3642be2c0d54SChristophe JAILLET 		goto remove_ab8500_bm;
36431c1f13a0SLinus Walleij 	}
36441c1f13a0SLinus Walleij 	if (IS_ERR(match)) {
36451c1f13a0SLinus Walleij 		dev_err(dev, "could not create component match\n");
3646be2c0d54SChristophe JAILLET 		ret = PTR_ERR(match);
3647be2c0d54SChristophe JAILLET 		goto remove_ab8500_bm;
36488c0984e5SSebastian Reichel 	}
36498c0984e5SSebastian Reichel 
36501c1f13a0SLinus Walleij 	di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
36511c1f13a0SLinus Walleij 	if (IS_ERR_OR_NULL(di->usb_phy)) {
36521c1f13a0SLinus Walleij 		dev_err(dev, "failed to get usb transceiver\n");
36531c1f13a0SLinus Walleij 		ret = -EINVAL;
36546c50a08dSLinus Walleij 		goto remove_ab8500_bm;
36551c1f13a0SLinus Walleij 	}
36561c1f13a0SLinus Walleij 	di->nb.notifier_call = ab8500_charger_usb_notifier_call;
36571c1f13a0SLinus Walleij 	ret = usb_register_notifier(di->usb_phy, &di->nb);
36581c1f13a0SLinus Walleij 	if (ret) {
36591c1f13a0SLinus Walleij 		dev_err(dev, "failed to register usb notifier\n");
36601c1f13a0SLinus Walleij 		goto put_usb_phy;
36611c1f13a0SLinus Walleij 	}
36621c1f13a0SLinus Walleij 
36631c1f13a0SLinus Walleij 	ret = component_master_add_with_match(&pdev->dev,
36641c1f13a0SLinus Walleij 					      &ab8500_charger_comp_ops,
36651c1f13a0SLinus Walleij 					      match);
36661c1f13a0SLinus Walleij 	if (ret) {
36671c1f13a0SLinus Walleij 		dev_err(dev, "failed to add component master\n");
36681c1f13a0SLinus Walleij 		goto free_notifier;
36691c1f13a0SLinus Walleij 	}
36701c1f13a0SLinus Walleij 
36711c1f13a0SLinus Walleij 	return 0;
36721c1f13a0SLinus Walleij 
36731c1f13a0SLinus Walleij free_notifier:
36748c0984e5SSebastian Reichel 	usb_unregister_notifier(di->usb_phy, &di->nb);
36758c0984e5SSebastian Reichel put_usb_phy:
36768c0984e5SSebastian Reichel 	usb_put_phy(di->usb_phy);
3677be2c0d54SChristophe JAILLET remove_ab8500_bm:
3678be2c0d54SChristophe JAILLET 	ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
36798c0984e5SSebastian Reichel 	return ret;
36808c0984e5SSebastian Reichel }
36818c0984e5SSebastian Reichel 
ab8500_charger_remove(struct platform_device * pdev)36821c1f13a0SLinus Walleij static int ab8500_charger_remove(struct platform_device *pdev)
36831c1f13a0SLinus Walleij {
36841c1f13a0SLinus Walleij 	struct ab8500_charger *di = platform_get_drvdata(pdev);
36851c1f13a0SLinus Walleij 
36861c1f13a0SLinus Walleij 	component_master_del(&pdev->dev, &ab8500_charger_comp_ops);
36871c1f13a0SLinus Walleij 
36881c1f13a0SLinus Walleij 	usb_unregister_notifier(di->usb_phy, &di->nb);
36896252c706SLinus Walleij 	ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
36901c1f13a0SLinus Walleij 	usb_put_phy(di->usb_phy);
36911c1f13a0SLinus Walleij 
36921c1f13a0SLinus Walleij 	return 0;
36931c1f13a0SLinus Walleij }
36941c1f13a0SLinus Walleij 
3695f8efa0a8SLinus Walleij static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume);
3696f8efa0a8SLinus Walleij 
36978c0984e5SSebastian Reichel static const struct of_device_id ab8500_charger_match[] = {
36988c0984e5SSebastian Reichel 	{ .compatible = "stericsson,ab8500-charger", },
36998c0984e5SSebastian Reichel 	{ },
37008c0984e5SSebastian Reichel };
3701dfe52db1SZou Wei MODULE_DEVICE_TABLE(of, ab8500_charger_match);
37028c0984e5SSebastian Reichel 
37038c0984e5SSebastian Reichel static struct platform_driver ab8500_charger_driver = {
37048c0984e5SSebastian Reichel 	.probe = ab8500_charger_probe,
37058c0984e5SSebastian Reichel 	.remove = ab8500_charger_remove,
37068c0984e5SSebastian Reichel 	.driver = {
37078c0984e5SSebastian Reichel 		.name = "ab8500-charger",
37088c0984e5SSebastian Reichel 		.of_match_table = ab8500_charger_match,
3709f8efa0a8SLinus Walleij 		.pm = &ab8500_charger_pm_ops,
37108c0984e5SSebastian Reichel 	},
37118c0984e5SSebastian Reichel };
37128c0984e5SSebastian Reichel 
ab8500_charger_init(void)37138c0984e5SSebastian Reichel static int __init ab8500_charger_init(void)
37148c0984e5SSebastian Reichel {
37151c1f13a0SLinus Walleij 	int ret;
37161c1f13a0SLinus Walleij 
37171c1f13a0SLinus Walleij 	ret = platform_register_drivers(ab8500_charger_component_drivers,
37181c1f13a0SLinus Walleij 			ARRAY_SIZE(ab8500_charger_component_drivers));
37191c1f13a0SLinus Walleij 	if (ret)
37201c1f13a0SLinus Walleij 		return ret;
37211c1f13a0SLinus Walleij 
3722*c4d33381SYuan Can 	ret = platform_driver_register(&ab8500_charger_driver);
3723*c4d33381SYuan Can 	if (ret) {
3724*c4d33381SYuan Can 		platform_unregister_drivers(ab8500_charger_component_drivers,
3725*c4d33381SYuan Can 				ARRAY_SIZE(ab8500_charger_component_drivers));
3726*c4d33381SYuan Can 		return ret;
3727*c4d33381SYuan Can 	}
3728*c4d33381SYuan Can 
3729*c4d33381SYuan Can 	return 0;
37308c0984e5SSebastian Reichel }
37318c0984e5SSebastian Reichel 
ab8500_charger_exit(void)37328c0984e5SSebastian Reichel static void __exit ab8500_charger_exit(void)
37338c0984e5SSebastian Reichel {
37341c1f13a0SLinus Walleij 	platform_unregister_drivers(ab8500_charger_component_drivers,
37351c1f13a0SLinus Walleij 			ARRAY_SIZE(ab8500_charger_component_drivers));
37368c0984e5SSebastian Reichel 	platform_driver_unregister(&ab8500_charger_driver);
37378c0984e5SSebastian Reichel }
37388c0984e5SSebastian Reichel 
37391c1f13a0SLinus Walleij module_init(ab8500_charger_init);
37408c0984e5SSebastian Reichel module_exit(ab8500_charger_exit);
37418c0984e5SSebastian Reichel 
37428c0984e5SSebastian Reichel MODULE_LICENSE("GPL v2");
37438c0984e5SSebastian Reichel MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
37448c0984e5SSebastian Reichel MODULE_ALIAS("platform:ab8500-charger");
37458c0984e5SSebastian Reichel MODULE_DESCRIPTION("AB8500 charger management driver");
3746