xref: /openbmc/linux/drivers/power/supply/ab8500_charger.c (revision 8f5b373960f976cf80e54636a60637cbe9718f66)
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 /**
174*8f5b3739SHong 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  */
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  */
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
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 
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 
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
1086*8f5b3739SHong 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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  **/
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  */
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 static int ab8500_external_charger_prepare(struct notifier_block *charger_nb,
17208c0984e5SSebastian Reichel 				unsigned long event, void *data)
17218c0984e5SSebastian Reichel {
17228c0984e5SSebastian Reichel 	int ret;
17238c0984e5SSebastian Reichel 	struct device *dev = data;
17248c0984e5SSebastian Reichel 	/*Toggle External charger control pin*/
17258c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
17268c0984e5SSebastian Reichel 				  AB8500_SYS_CHARGER_CONTROL_REG,
17278c0984e5SSebastian Reichel 				  EXTERNAL_CHARGER_DISABLE_REG_VAL);
17288c0984e5SSebastian Reichel 	if (ret < 0) {
17298c0984e5SSebastian Reichel 		dev_err(dev, "write reg failed %d\n", ret);
17308c0984e5SSebastian Reichel 		goto out;
17318c0984e5SSebastian Reichel 	}
17328c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
17338c0984e5SSebastian Reichel 				  AB8500_SYS_CHARGER_CONTROL_REG,
17348c0984e5SSebastian Reichel 				  EXTERNAL_CHARGER_ENABLE_REG_VAL);
17358c0984e5SSebastian Reichel 	if (ret < 0)
17368c0984e5SSebastian Reichel 		dev_err(dev, "Write reg failed %d\n", ret);
17378c0984e5SSebastian Reichel 
17388c0984e5SSebastian Reichel out:
17398c0984e5SSebastian Reichel 	return ret;
17408c0984e5SSebastian Reichel }
17418c0984e5SSebastian Reichel 
17428c0984e5SSebastian Reichel /**
17438c0984e5SSebastian Reichel  * ab8500_charger_usb_check_enable() - enable usb charging
17448c0984e5SSebastian Reichel  * @charger:	pointer to the ux500_charger structure
1745bc6e0287SLinus Walleij  * @vset_uv:	charging voltage in microvolt
174683e5aa77SLinus Walleij  * @iset_ua:	charger output current in microampere
17478c0984e5SSebastian Reichel  *
17488c0984e5SSebastian Reichel  * Check if the VBUS charger has been disconnected and reconnected without
17498c0984e5SSebastian Reichel  * AB8500 rising an interrupt. Returns 0 on success.
17508c0984e5SSebastian Reichel  */
17518c0984e5SSebastian Reichel static int ab8500_charger_usb_check_enable(struct ux500_charger *charger,
1752bc6e0287SLinus Walleij 	int vset_uv, int iset_ua)
17538c0984e5SSebastian Reichel {
17548c0984e5SSebastian Reichel 	u8 usbch_ctrl1 = 0;
17558c0984e5SSebastian Reichel 	int ret = 0;
17568c0984e5SSebastian Reichel 
17578c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
17588c0984e5SSebastian Reichel 
17598c0984e5SSebastian Reichel 	if (!di->usb.charger_connected)
17608c0984e5SSebastian Reichel 		return ret;
17618c0984e5SSebastian Reichel 
17628c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
17638c0984e5SSebastian Reichel 				AB8500_USBCH_CTRL1_REG, &usbch_ctrl1);
17648c0984e5SSebastian Reichel 	if (ret < 0) {
17658c0984e5SSebastian Reichel 		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
17668c0984e5SSebastian Reichel 		return ret;
17678c0984e5SSebastian Reichel 	}
17688c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1);
17698c0984e5SSebastian Reichel 
17708c0984e5SSebastian Reichel 	if (!(usbch_ctrl1 & USB_CH_ENA)) {
17718c0984e5SSebastian Reichel 		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
17728c0984e5SSebastian Reichel 
17738c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
17748c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_CHARGER_CTRL,
17758c0984e5SSebastian Reichel 					DROP_COUNT_RESET, DROP_COUNT_RESET);
17768c0984e5SSebastian Reichel 		if (ret < 0) {
17778c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
17788c0984e5SSebastian Reichel 			return ret;
17798c0984e5SSebastian Reichel 		}
17808c0984e5SSebastian Reichel 
1781bc6e0287SLinus Walleij 		ret = ab8500_charger_usb_en(&di->usb_chg, true, vset_uv, iset_ua);
17828c0984e5SSebastian Reichel 		if (ret < 0) {
17838c0984e5SSebastian Reichel 			dev_err(di->dev, "Failed to enable VBUS charger %d\n",
17848c0984e5SSebastian Reichel 					__LINE__);
17858c0984e5SSebastian Reichel 			return ret;
17868c0984e5SSebastian Reichel 		}
17878c0984e5SSebastian Reichel 	}
17888c0984e5SSebastian Reichel 	return ret;
17898c0984e5SSebastian Reichel }
17908c0984e5SSebastian Reichel 
17918c0984e5SSebastian Reichel /**
17928c0984e5SSebastian Reichel  * ab8500_charger_ac_check_enable() - enable usb charging
17938c0984e5SSebastian Reichel  * @charger:	pointer to the ux500_charger structure
1794bc6e0287SLinus Walleij  * @vset_uv:	charging voltage in microvolt
179583e5aa77SLinus Walleij  * @iset_ua:	charger output current in micrompere
17968c0984e5SSebastian Reichel  *
17978c0984e5SSebastian Reichel  * Check if the AC charger has been disconnected and reconnected without
17988c0984e5SSebastian Reichel  * AB8500 rising an interrupt. Returns 0 on success.
17998c0984e5SSebastian Reichel  */
18008c0984e5SSebastian Reichel static int ab8500_charger_ac_check_enable(struct ux500_charger *charger,
1801bc6e0287SLinus Walleij 	int vset_uv, int iset_ua)
18028c0984e5SSebastian Reichel {
18038c0984e5SSebastian Reichel 	u8 mainch_ctrl1 = 0;
18048c0984e5SSebastian Reichel 	int ret = 0;
18058c0984e5SSebastian Reichel 
18068c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
18078c0984e5SSebastian Reichel 
18088c0984e5SSebastian Reichel 	if (!di->ac.charger_connected)
18098c0984e5SSebastian Reichel 		return ret;
18108c0984e5SSebastian Reichel 
18118c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
18128c0984e5SSebastian Reichel 				AB8500_MCH_CTRL1, &mainch_ctrl1);
18138c0984e5SSebastian Reichel 	if (ret < 0) {
18148c0984e5SSebastian Reichel 		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
18158c0984e5SSebastian Reichel 		return ret;
18168c0984e5SSebastian Reichel 	}
18178c0984e5SSebastian Reichel 	dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1);
18188c0984e5SSebastian Reichel 
18198c0984e5SSebastian Reichel 	if (!(mainch_ctrl1 & MAIN_CH_ENA)) {
18208c0984e5SSebastian Reichel 		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
18218c0984e5SSebastian Reichel 
18228c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
18238c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_CHARGER_CTRL,
18248c0984e5SSebastian Reichel 					DROP_COUNT_RESET, DROP_COUNT_RESET);
18258c0984e5SSebastian Reichel 
18268c0984e5SSebastian Reichel 		if (ret < 0) {
18278c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
18288c0984e5SSebastian Reichel 			return ret;
18298c0984e5SSebastian Reichel 		}
18308c0984e5SSebastian Reichel 
1831bc6e0287SLinus Walleij 		ret = ab8500_charger_ac_en(&di->usb_chg, true, vset_uv, iset_ua);
18328c0984e5SSebastian Reichel 		if (ret < 0) {
18338c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to enable AC charger %d\n",
18348c0984e5SSebastian Reichel 				__LINE__);
18358c0984e5SSebastian Reichel 			return ret;
18368c0984e5SSebastian Reichel 		}
18378c0984e5SSebastian Reichel 	}
18388c0984e5SSebastian Reichel 	return ret;
18398c0984e5SSebastian Reichel }
18408c0984e5SSebastian Reichel 
18418c0984e5SSebastian Reichel /**
18428c0984e5SSebastian Reichel  * ab8500_charger_watchdog_kick() - kick charger watchdog
18438c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
18448c0984e5SSebastian Reichel  *
18458c0984e5SSebastian Reichel  * Kick charger watchdog
18468c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
18478c0984e5SSebastian Reichel  */
18488c0984e5SSebastian Reichel static int ab8500_charger_watchdog_kick(struct ux500_charger *charger)
18498c0984e5SSebastian Reichel {
18508c0984e5SSebastian Reichel 	int ret;
18518c0984e5SSebastian Reichel 	struct ab8500_charger *di;
18528c0984e5SSebastian Reichel 
18538c0984e5SSebastian Reichel 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
18548c0984e5SSebastian Reichel 		di = to_ab8500_charger_ac_device_info(charger);
18558c0984e5SSebastian Reichel 	else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
18568c0984e5SSebastian Reichel 		di = to_ab8500_charger_usb_device_info(charger);
18578c0984e5SSebastian Reichel 	else
18588c0984e5SSebastian Reichel 		return -ENXIO;
18598c0984e5SSebastian Reichel 
18608c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
18618c0984e5SSebastian Reichel 		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
18628c0984e5SSebastian Reichel 	if (ret)
18638c0984e5SSebastian Reichel 		dev_err(di->dev, "Failed to kick WD!\n");
18648c0984e5SSebastian Reichel 
18658c0984e5SSebastian Reichel 	return ret;
18668c0984e5SSebastian Reichel }
18678c0984e5SSebastian Reichel 
18688c0984e5SSebastian Reichel /**
18698c0984e5SSebastian Reichel  * ab8500_charger_update_charger_current() - update charger current
187083e5aa77SLinus Walleij  * @charger:		pointer to the ab8500_charger structure
187183e5aa77SLinus Walleij  * @ich_out_ua:		desired output current in microampere
18728c0984e5SSebastian Reichel  *
18738c0984e5SSebastian Reichel  * Update the charger output current for the specified charger
18748c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
18758c0984e5SSebastian Reichel  */
18768c0984e5SSebastian Reichel static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
187783e5aa77SLinus Walleij 		int ich_out_ua)
18788c0984e5SSebastian Reichel {
18798c0984e5SSebastian Reichel 	int ret;
18808c0984e5SSebastian Reichel 	struct ab8500_charger *di;
18818c0984e5SSebastian Reichel 
18828c0984e5SSebastian Reichel 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
18838c0984e5SSebastian Reichel 		di = to_ab8500_charger_ac_device_info(charger);
18848c0984e5SSebastian Reichel 	else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
18858c0984e5SSebastian Reichel 		di = to_ab8500_charger_usb_device_info(charger);
18868c0984e5SSebastian Reichel 	else
18878c0984e5SSebastian Reichel 		return -ENXIO;
18888c0984e5SSebastian Reichel 
188983e5aa77SLinus Walleij 	ret = ab8500_charger_set_output_curr(di, ich_out_ua);
18908c0984e5SSebastian Reichel 	if (ret) {
18918c0984e5SSebastian Reichel 		dev_err(di->dev, "%s "
18928c0984e5SSebastian Reichel 			"Failed to set ChOutputCurentLevel\n",
18938c0984e5SSebastian Reichel 			__func__);
18948c0984e5SSebastian Reichel 		return ret;
18958c0984e5SSebastian Reichel 	}
18968c0984e5SSebastian Reichel 
18978c0984e5SSebastian Reichel 	/* Reset the main and usb drop input current measurement counter */
18988c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
18998c0984e5SSebastian Reichel 				AB8500_CHARGER_CTRL, DROP_COUNT_RESET);
19008c0984e5SSebastian Reichel 	if (ret) {
19018c0984e5SSebastian Reichel 		dev_err(di->dev, "%s write failed\n", __func__);
19028c0984e5SSebastian Reichel 		return ret;
19038c0984e5SSebastian Reichel 	}
19048c0984e5SSebastian Reichel 
19058c0984e5SSebastian Reichel 	return ret;
19068c0984e5SSebastian Reichel }
19078c0984e5SSebastian Reichel 
19088c0984e5SSebastian Reichel static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
19098c0984e5SSebastian Reichel {
19108c0984e5SSebastian Reichel 	struct power_supply *psy;
19118c0984e5SSebastian Reichel 	struct power_supply *ext = dev_get_drvdata(dev);
19128c0984e5SSebastian Reichel 	const char **supplicants = (const char **)ext->supplied_to;
19138c0984e5SSebastian Reichel 	struct ab8500_charger *di;
19148c0984e5SSebastian Reichel 	union power_supply_propval ret;
19158c0984e5SSebastian Reichel 	int j;
19168c0984e5SSebastian Reichel 	struct ux500_charger *usb_chg;
19178c0984e5SSebastian Reichel 
19188c0984e5SSebastian Reichel 	usb_chg = (struct ux500_charger *)data;
19198c0984e5SSebastian Reichel 	psy = usb_chg->psy;
19208c0984e5SSebastian Reichel 
19218c0984e5SSebastian Reichel 	di = to_ab8500_charger_usb_device_info(usb_chg);
19228c0984e5SSebastian Reichel 
192321ad180dSLinus Walleij 	/*
192421ad180dSLinus Walleij 	 * For all psy where the driver name appears in any supplied_to
192521ad180dSLinus Walleij 	 * in practice what we will find will always be "ab8500_fg" as
192621ad180dSLinus Walleij 	 * the fuel gauge is responsible of keeping track of VBAT.
192721ad180dSLinus Walleij 	 */
19288c0984e5SSebastian Reichel 	j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
19298c0984e5SSebastian Reichel 	if (j < 0)
19308c0984e5SSebastian Reichel 		return 0;
19318c0984e5SSebastian Reichel 
19328c0984e5SSebastian Reichel 	/* Go through all properties for the psy */
19338c0984e5SSebastian Reichel 	for (j = 0; j < ext->desc->num_properties; j++) {
19348c0984e5SSebastian Reichel 		enum power_supply_property prop;
19358c0984e5SSebastian Reichel 		prop = ext->desc->properties[j];
19368c0984e5SSebastian Reichel 
19378c0984e5SSebastian Reichel 		if (power_supply_get_property(ext, prop, &ret))
19388c0984e5SSebastian Reichel 			continue;
19398c0984e5SSebastian Reichel 
19408c0984e5SSebastian Reichel 		switch (prop) {
19418c0984e5SSebastian Reichel 		case POWER_SUPPLY_PROP_VOLTAGE_NOW:
19428c0984e5SSebastian Reichel 			switch (ext->desc->type) {
19438c0984e5SSebastian Reichel 			case POWER_SUPPLY_TYPE_BATTERY:
194421ad180dSLinus Walleij 				/* This will always be "ab8500_fg" */
194521ad180dSLinus Walleij 				dev_dbg(di->dev, "get VBAT from %s\n",
194621ad180dSLinus Walleij 					dev_name(&ext->dev));
194721ad180dSLinus Walleij 				di->vbat = ret.intval;
19488c0984e5SSebastian Reichel 				break;
19498c0984e5SSebastian Reichel 			default:
19508c0984e5SSebastian Reichel 				break;
19518c0984e5SSebastian Reichel 			}
19528c0984e5SSebastian Reichel 			break;
19538c0984e5SSebastian Reichel 		default:
19548c0984e5SSebastian Reichel 			break;
19558c0984e5SSebastian Reichel 		}
19568c0984e5SSebastian Reichel 	}
19578c0984e5SSebastian Reichel 	return 0;
19588c0984e5SSebastian Reichel }
19598c0984e5SSebastian Reichel 
19608c0984e5SSebastian Reichel /**
19618c0984e5SSebastian Reichel  * ab8500_charger_check_vbat_work() - keep vbus current within spec
19628c0984e5SSebastian Reichel  * @work	pointer to the work_struct structure
19638c0984e5SSebastian Reichel  *
19648c0984e5SSebastian Reichel  * Due to a asic bug it is necessary to lower the input current to the vbus
19658c0984e5SSebastian Reichel  * charger when charging with at some specific levels. This issue is only valid
19668c0984e5SSebastian Reichel  * for below a certain battery voltage. This function makes sure that the
19678c0984e5SSebastian Reichel  * the allowed current limit isn't exceeded.
19688c0984e5SSebastian Reichel  */
19698c0984e5SSebastian Reichel static void ab8500_charger_check_vbat_work(struct work_struct *work)
19708c0984e5SSebastian Reichel {
19718c0984e5SSebastian Reichel 	int t = 10;
19728c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
19738c0984e5SSebastian Reichel 		struct ab8500_charger, check_vbat_work.work);
19748c0984e5SSebastian Reichel 
19758c0984e5SSebastian Reichel 	class_for_each_device(power_supply_class, NULL,
197621ad180dSLinus Walleij 			      &di->usb_chg, ab8500_charger_get_ext_psy_data);
19778c0984e5SSebastian Reichel 
19788c0984e5SSebastian Reichel 	/* First run old_vbat is 0. */
19798c0984e5SSebastian Reichel 	if (di->old_vbat == 0)
19808c0984e5SSebastian Reichel 		di->old_vbat = di->vbat;
19818c0984e5SSebastian Reichel 
19828c0984e5SSebastian Reichel 	if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED &&
19838c0984e5SSebastian Reichel 		di->vbat <= VBAT_TRESH_IP_CUR_RED) ||
19848c0984e5SSebastian Reichel 		(di->old_vbat > VBAT_TRESH_IP_CUR_RED &&
19858c0984e5SSebastian Reichel 		di->vbat > VBAT_TRESH_IP_CUR_RED))) {
19868c0984e5SSebastian Reichel 
19878c0984e5SSebastian Reichel 		dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d,"
198883e5aa77SLinus Walleij 			" old: %d\n", di->max_usb_in_curr.usb_type_max_ua,
19898c0984e5SSebastian Reichel 			di->vbat, di->old_vbat);
19908c0984e5SSebastian Reichel 		ab8500_charger_set_vbus_in_curr(di,
199183e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
19928c0984e5SSebastian Reichel 		power_supply_changed(di->usb_chg.psy);
19938c0984e5SSebastian Reichel 	}
19948c0984e5SSebastian Reichel 
19958c0984e5SSebastian Reichel 	di->old_vbat = di->vbat;
19968c0984e5SSebastian Reichel 
19978c0984e5SSebastian Reichel 	/*
19988c0984e5SSebastian Reichel 	 * No need to check the battery voltage every second when not close to
19998c0984e5SSebastian Reichel 	 * the threshold.
20008c0984e5SSebastian Reichel 	 */
200121ad180dSLinus Walleij 	if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100000) &&
200221ad180dSLinus Walleij 		(di->vbat > (VBAT_TRESH_IP_CUR_RED - 100000)))
20038c0984e5SSebastian Reichel 			t = 1;
20048c0984e5SSebastian Reichel 
20058c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ);
20068c0984e5SSebastian Reichel }
20078c0984e5SSebastian Reichel 
20088c0984e5SSebastian Reichel /**
20098c0984e5SSebastian Reichel  * ab8500_charger_check_hw_failure_work() - check main charger failure
20108c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20118c0984e5SSebastian Reichel  *
20128c0984e5SSebastian Reichel  * Work queue function for checking the main charger status
20138c0984e5SSebastian Reichel  */
20148c0984e5SSebastian Reichel static void ab8500_charger_check_hw_failure_work(struct work_struct *work)
20158c0984e5SSebastian Reichel {
20168c0984e5SSebastian Reichel 	int ret;
20178c0984e5SSebastian Reichel 	u8 reg_value;
20188c0984e5SSebastian Reichel 
20198c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20208c0984e5SSebastian Reichel 		struct ab8500_charger, check_hw_failure_work.work);
20218c0984e5SSebastian Reichel 
20228c0984e5SSebastian Reichel 	/* Check if the status bits for HW failure is still active */
20238c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok) {
20248c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
20258c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
20268c0984e5SSebastian Reichel 		if (ret < 0) {
20278c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
20288c0984e5SSebastian Reichel 			return;
20298c0984e5SSebastian Reichel 		}
20308c0984e5SSebastian Reichel 		if (!(reg_value & MAIN_CH_NOK)) {
20318c0984e5SSebastian Reichel 			di->flags.mainextchnotok = false;
20328c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->ac_chg.psy);
20338c0984e5SSebastian Reichel 		}
20348c0984e5SSebastian Reichel 	}
20358c0984e5SSebastian Reichel 	if (di->flags.vbus_ovv) {
20368c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
20378c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG,
20388c0984e5SSebastian Reichel 			&reg_value);
20398c0984e5SSebastian Reichel 		if (ret < 0) {
20408c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
20418c0984e5SSebastian Reichel 			return;
20428c0984e5SSebastian Reichel 		}
20438c0984e5SSebastian Reichel 		if (!(reg_value & VBUS_OVV_TH)) {
20448c0984e5SSebastian Reichel 			di->flags.vbus_ovv = false;
20458c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
20468c0984e5SSebastian Reichel 		}
20478c0984e5SSebastian Reichel 	}
20488c0984e5SSebastian Reichel 	/* If we still have a failure, schedule a new check */
20498c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
20508c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
20518c0984e5SSebastian Reichel 			&di->check_hw_failure_work, round_jiffies(HZ));
20528c0984e5SSebastian Reichel 	}
20538c0984e5SSebastian Reichel }
20548c0984e5SSebastian Reichel 
20558c0984e5SSebastian Reichel /**
20568c0984e5SSebastian Reichel  * ab8500_charger_kick_watchdog_work() - kick the watchdog
20578c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20588c0984e5SSebastian Reichel  *
20598c0984e5SSebastian Reichel  * Work queue function for kicking the charger watchdog.
20608c0984e5SSebastian Reichel  *
20618c0984e5SSebastian Reichel  * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
2062ddb74e98SAshish Chavan  * logic. That means we have to continuously kick the charger
20638c0984e5SSebastian Reichel  * watchdog even when no charger is connected. This is only
20648c0984e5SSebastian Reichel  * valid once the AC charger has been enabled. This is
20658c0984e5SSebastian Reichel  * a bug that is not handled by the algorithm and the
20668c0984e5SSebastian Reichel  * watchdog have to be kicked by the charger driver
20678c0984e5SSebastian Reichel  * when the AC charger is disabled
20688c0984e5SSebastian Reichel  */
20698c0984e5SSebastian Reichel static void ab8500_charger_kick_watchdog_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, kick_wd_work.work);
20758c0984e5SSebastian Reichel 
20768c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
20778c0984e5SSebastian Reichel 		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
20788c0984e5SSebastian Reichel 	if (ret)
20798c0984e5SSebastian Reichel 		dev_err(di->dev, "Failed to kick WD!\n");
20808c0984e5SSebastian Reichel 
20818c0984e5SSebastian Reichel 	/* Schedule a new watchdog kick */
20828c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
20838c0984e5SSebastian Reichel 		&di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL));
20848c0984e5SSebastian Reichel }
20858c0984e5SSebastian Reichel 
20868c0984e5SSebastian Reichel /**
20878c0984e5SSebastian Reichel  * ab8500_charger_ac_work() - work to get and set main charger status
20888c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20898c0984e5SSebastian Reichel  *
20908c0984e5SSebastian Reichel  * Work queue function for checking the main charger status
20918c0984e5SSebastian Reichel  */
20928c0984e5SSebastian Reichel static void ab8500_charger_ac_work(struct work_struct *work)
20938c0984e5SSebastian Reichel {
20948c0984e5SSebastian Reichel 	int ret;
20958c0984e5SSebastian Reichel 
20968c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20978c0984e5SSebastian Reichel 		struct ab8500_charger, ac_work);
20988c0984e5SSebastian Reichel 
20998c0984e5SSebastian Reichel 	/*
21008c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
21018c0984e5SSebastian Reichel 	 * synchronously, we have the check if the main charger is
21028c0984e5SSebastian Reichel 	 * connected by reading the status register
21038c0984e5SSebastian Reichel 	 */
21048c0984e5SSebastian Reichel 	ret = ab8500_charger_detect_chargers(di, false);
21058c0984e5SSebastian Reichel 	if (ret < 0)
21068c0984e5SSebastian Reichel 		return;
21078c0984e5SSebastian Reichel 
21088c0984e5SSebastian Reichel 	if (ret & AC_PW_CONN) {
21098c0984e5SSebastian Reichel 		di->ac.charger_connected = 1;
21108c0984e5SSebastian Reichel 		di->ac_conn = true;
21118c0984e5SSebastian Reichel 	} else {
21128c0984e5SSebastian Reichel 		di->ac.charger_connected = 0;
21138c0984e5SSebastian Reichel 	}
21148c0984e5SSebastian Reichel 
21158c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
21168c0984e5SSebastian Reichel 	sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
21178c0984e5SSebastian Reichel }
21188c0984e5SSebastian Reichel 
21198c0984e5SSebastian Reichel static void ab8500_charger_usb_attached_work(struct work_struct *work)
21208c0984e5SSebastian Reichel {
21218c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
21228c0984e5SSebastian Reichel 						 struct ab8500_charger,
21238c0984e5SSebastian Reichel 						 usb_charger_attached_work.work);
21248c0984e5SSebastian Reichel 	int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC);
21258c0984e5SSebastian Reichel 	int ret, i;
21268c0984e5SSebastian Reichel 	u8 statval;
21278c0984e5SSebastian Reichel 
21288c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
21298c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
21308c0984e5SSebastian Reichel 							AB8500_CHARGER,
21318c0984e5SSebastian Reichel 							AB8500_CH_USBCH_STAT1_REG,
21328c0984e5SSebastian Reichel 							&statval);
21338c0984e5SSebastian Reichel 		if (ret < 0) {
21348c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
21358c0984e5SSebastian Reichel 			goto reschedule;
21368c0984e5SSebastian Reichel 		}
21378c0984e5SSebastian Reichel 		if ((statval & usbch) != usbch)
21388c0984e5SSebastian Reichel 			goto reschedule;
21398c0984e5SSebastian Reichel 
21408c0984e5SSebastian Reichel 		msleep(CHARGER_STATUS_POLL);
21418c0984e5SSebastian Reichel 	}
21428c0984e5SSebastian Reichel 
21438c0984e5SSebastian Reichel 	ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0);
21448c0984e5SSebastian Reichel 
21458c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
21468c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
21478c0984e5SSebastian Reichel 
21488c0984e5SSebastian Reichel 	return;
21498c0984e5SSebastian Reichel 
21508c0984e5SSebastian Reichel reschedule:
21518c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
21528c0984e5SSebastian Reichel 			   &di->usb_charger_attached_work,
21538c0984e5SSebastian Reichel 			   HZ);
21548c0984e5SSebastian Reichel }
21558c0984e5SSebastian Reichel 
21568c0984e5SSebastian Reichel static void ab8500_charger_ac_attached_work(struct work_struct *work)
21578c0984e5SSebastian Reichel {
21588c0984e5SSebastian Reichel 
21598c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
21608c0984e5SSebastian Reichel 						 struct ab8500_charger,
21618c0984e5SSebastian Reichel 						 ac_charger_attached_work.work);
21628c0984e5SSebastian Reichel 	int mainch = (MAIN_CH_STATUS2_MAINCHGDROP |
21638c0984e5SSebastian Reichel 		      MAIN_CH_STATUS2_MAINCHARGERDETDBNC);
21648c0984e5SSebastian Reichel 	int ret, i;
21658c0984e5SSebastian Reichel 	u8 statval;
21668c0984e5SSebastian Reichel 
21678c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
21688c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
21698c0984e5SSebastian Reichel 							AB8500_CHARGER,
21708c0984e5SSebastian Reichel 							AB8500_CH_STATUS2_REG,
21718c0984e5SSebastian Reichel 							&statval);
21728c0984e5SSebastian Reichel 		if (ret < 0) {
21738c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
21748c0984e5SSebastian Reichel 			goto reschedule;
21758c0984e5SSebastian Reichel 		}
21768c0984e5SSebastian Reichel 
21778c0984e5SSebastian Reichel 		if ((statval & mainch) != mainch)
21788c0984e5SSebastian Reichel 			goto reschedule;
21798c0984e5SSebastian Reichel 
21808c0984e5SSebastian Reichel 		msleep(CHARGER_STATUS_POLL);
21818c0984e5SSebastian Reichel 	}
21828c0984e5SSebastian Reichel 
21838c0984e5SSebastian Reichel 	ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0);
21848c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
21858c0984e5SSebastian Reichel 
21868c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
21878c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
21888c0984e5SSebastian Reichel 
21898c0984e5SSebastian Reichel 	return;
21908c0984e5SSebastian Reichel 
21918c0984e5SSebastian Reichel reschedule:
21928c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
21938c0984e5SSebastian Reichel 			   &di->ac_charger_attached_work,
21948c0984e5SSebastian Reichel 			   HZ);
21958c0984e5SSebastian Reichel }
21968c0984e5SSebastian Reichel 
21978c0984e5SSebastian Reichel /**
21988c0984e5SSebastian Reichel  * ab8500_charger_detect_usb_type_work() - work to detect USB type
21998c0984e5SSebastian Reichel  * @work:	Pointer to the work_struct structure
22008c0984e5SSebastian Reichel  *
22018c0984e5SSebastian Reichel  * Detect the type of USB plugged
22028c0984e5SSebastian Reichel  */
22038c0984e5SSebastian Reichel static void ab8500_charger_detect_usb_type_work(struct work_struct *work)
22048c0984e5SSebastian Reichel {
22058c0984e5SSebastian Reichel 	int ret;
22068c0984e5SSebastian Reichel 
22078c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
22088c0984e5SSebastian Reichel 		struct ab8500_charger, detect_usb_type_work);
22098c0984e5SSebastian Reichel 
22108c0984e5SSebastian Reichel 	/*
22118c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
22128c0984e5SSebastian Reichel 	 * synchronously, we have the check if is
22138c0984e5SSebastian Reichel 	 * connected by reading the status register
22148c0984e5SSebastian Reichel 	 */
22158c0984e5SSebastian Reichel 	ret = ab8500_charger_detect_chargers(di, false);
22168c0984e5SSebastian Reichel 	if (ret < 0)
22178c0984e5SSebastian Reichel 		return;
22188c0984e5SSebastian Reichel 
22198c0984e5SSebastian Reichel 	if (!(ret & USB_PW_CONN)) {
22208c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__);
22218c0984e5SSebastian Reichel 		di->vbus_detected = false;
22228c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
22238c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
22248c0984e5SSebastian Reichel 	} else {
22258c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__);
22268c0984e5SSebastian Reichel 		di->vbus_detected = true;
22278c0984e5SSebastian Reichel 
22288c0984e5SSebastian Reichel 		if (is_ab8500_1p1_or_earlier(di->parent)) {
22298c0984e5SSebastian Reichel 			ret = ab8500_charger_detect_usb_type(di);
22308c0984e5SSebastian Reichel 			if (!ret) {
22318c0984e5SSebastian Reichel 				ab8500_charger_set_usb_connected(di, true);
22328c0984e5SSebastian Reichel 				ab8500_power_supply_changed(di,
22338c0984e5SSebastian Reichel 							    di->usb_chg.psy);
22348c0984e5SSebastian Reichel 			}
22358c0984e5SSebastian Reichel 		} else {
22368c0984e5SSebastian Reichel 			/*
22378c0984e5SSebastian Reichel 			 * For ABB cut2.0 and onwards we have an IRQ,
22388c0984e5SSebastian Reichel 			 * USB_LINK_STATUS that will be triggered when the USB
22398c0984e5SSebastian Reichel 			 * link status changes. The exception is USB connected
22408c0984e5SSebastian Reichel 			 * during startup. Then we don't get a
22418c0984e5SSebastian Reichel 			 * USB_LINK_STATUS IRQ
22428c0984e5SSebastian Reichel 			 */
22438c0984e5SSebastian Reichel 			if (di->vbus_detected_start) {
22448c0984e5SSebastian Reichel 				di->vbus_detected_start = false;
22458c0984e5SSebastian Reichel 				ret = ab8500_charger_detect_usb_type(di);
22468c0984e5SSebastian Reichel 				if (!ret) {
22478c0984e5SSebastian Reichel 					ab8500_charger_set_usb_connected(di,
22488c0984e5SSebastian Reichel 						true);
22498c0984e5SSebastian Reichel 					ab8500_power_supply_changed(di,
22508c0984e5SSebastian Reichel 						di->usb_chg.psy);
22518c0984e5SSebastian Reichel 				}
22528c0984e5SSebastian Reichel 			}
22538c0984e5SSebastian Reichel 		}
22548c0984e5SSebastian Reichel 	}
22558c0984e5SSebastian Reichel }
22568c0984e5SSebastian Reichel 
22578c0984e5SSebastian Reichel /**
22588c0984e5SSebastian Reichel  * ab8500_charger_usb_link_attach_work() - work to detect USB type
22598c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
22608c0984e5SSebastian Reichel  *
22618c0984e5SSebastian Reichel  * Detect the type of USB plugged
22628c0984e5SSebastian Reichel  */
22638c0984e5SSebastian Reichel static void ab8500_charger_usb_link_attach_work(struct work_struct *work)
22648c0984e5SSebastian Reichel {
22658c0984e5SSebastian Reichel 	struct ab8500_charger *di =
22668c0984e5SSebastian Reichel 		container_of(work, struct ab8500_charger, attach_work.work);
22678c0984e5SSebastian Reichel 	int ret;
22688c0984e5SSebastian Reichel 
22698c0984e5SSebastian Reichel 	/* Update maximum input current if USB enumeration is not detected */
22708c0984e5SSebastian Reichel 	if (!di->usb.charger_online) {
22718c0984e5SSebastian Reichel 		ret = ab8500_charger_set_vbus_in_curr(di,
227283e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
22738c0984e5SSebastian Reichel 		if (ret)
22748c0984e5SSebastian Reichel 			return;
22758c0984e5SSebastian Reichel 	}
22768c0984e5SSebastian Reichel 
22778c0984e5SSebastian Reichel 	ab8500_charger_set_usb_connected(di, true);
22788c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
22798c0984e5SSebastian Reichel }
22808c0984e5SSebastian Reichel 
22818c0984e5SSebastian Reichel /**
22828c0984e5SSebastian Reichel  * ab8500_charger_usb_link_status_work() - work to detect USB type
22838c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
22848c0984e5SSebastian Reichel  *
22858c0984e5SSebastian Reichel  * Detect the type of USB plugged
22868c0984e5SSebastian Reichel  */
22878c0984e5SSebastian Reichel static void ab8500_charger_usb_link_status_work(struct work_struct *work)
22888c0984e5SSebastian Reichel {
22898c0984e5SSebastian Reichel 	int detected_chargers;
22908c0984e5SSebastian Reichel 	int ret;
22918c0984e5SSebastian Reichel 	u8 val;
22928c0984e5SSebastian Reichel 	u8 link_status;
22938c0984e5SSebastian Reichel 
22948c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
22958c0984e5SSebastian Reichel 		struct ab8500_charger, usb_link_status_work);
22968c0984e5SSebastian Reichel 
22978c0984e5SSebastian Reichel 	/*
22988c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
22998c0984e5SSebastian Reichel 	 * synchronously, we have the check if  is
23008c0984e5SSebastian Reichel 	 * connected by reading the status register
23018c0984e5SSebastian Reichel 	 */
23028c0984e5SSebastian Reichel 	detected_chargers = ab8500_charger_detect_chargers(di, false);
23038c0984e5SSebastian Reichel 	if (detected_chargers < 0)
23048c0984e5SSebastian Reichel 		return;
23058c0984e5SSebastian Reichel 
23068c0984e5SSebastian Reichel 	/*
23078c0984e5SSebastian Reichel 	 * Some chargers that breaks the USB spec is
23088c0984e5SSebastian Reichel 	 * identified as invalid by AB8500 and it refuse
23098c0984e5SSebastian Reichel 	 * to start the charging process. but by jumping
2310ddb74e98SAshish Chavan 	 * through a few hoops it can be forced to start.
23118c0984e5SSebastian Reichel 	 */
23128c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
23138c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
23148c0984e5SSebastian Reichel 					AB8500_USB_LINE_STAT_REG, &val);
23158c0984e5SSebastian Reichel 	else
23168c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
23178c0984e5SSebastian Reichel 					AB8500_USB_LINK1_STAT_REG, &val);
23188c0984e5SSebastian Reichel 
23198c0984e5SSebastian Reichel 	if (ret >= 0)
23208c0984e5SSebastian Reichel 		dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val);
23218c0984e5SSebastian Reichel 	else
23228c0984e5SSebastian Reichel 		dev_dbg(di->dev, "Error reading USB link status\n");
23238c0984e5SSebastian Reichel 
23248c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
23258c0984e5SSebastian Reichel 		link_status = AB8500_USB_LINK_STATUS;
23268c0984e5SSebastian Reichel 	else
23278c0984e5SSebastian Reichel 		link_status = AB8505_USB_LINK_STATUS;
23288c0984e5SSebastian Reichel 
23298c0984e5SSebastian Reichel 	if (detected_chargers & USB_PW_CONN) {
23308c0984e5SSebastian Reichel 		if (((val & link_status) >> USB_LINK_STATUS_SHIFT) ==
23318c0984e5SSebastian Reichel 				USB_STAT_NOT_VALID_LINK &&
23328c0984e5SSebastian Reichel 				di->invalid_charger_detect_state == 0) {
23338c0984e5SSebastian Reichel 			dev_dbg(di->dev,
23348c0984e5SSebastian Reichel 					"Invalid charger detected, state= 0\n");
23358c0984e5SSebastian Reichel 			/*Enable charger*/
23368c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23378c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_USBCH_CTRL1_REG,
23388c0984e5SSebastian Reichel 					USB_CH_ENA, USB_CH_ENA);
23398c0984e5SSebastian Reichel 			/*Enable charger detection*/
23408c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23418c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
23428c0984e5SSebastian Reichel 					USB_CH_DET, USB_CH_DET);
23438c0984e5SSebastian Reichel 			di->invalid_charger_detect_state = 1;
23448c0984e5SSebastian Reichel 			/*exit and wait for new link status interrupt.*/
23458c0984e5SSebastian Reichel 			return;
23468c0984e5SSebastian Reichel 
23478c0984e5SSebastian Reichel 		}
23488c0984e5SSebastian Reichel 		if (di->invalid_charger_detect_state == 1) {
23498c0984e5SSebastian Reichel 			dev_dbg(di->dev,
23508c0984e5SSebastian Reichel 					"Invalid charger detected, state= 1\n");
23518c0984e5SSebastian Reichel 			/*Stop charger detection*/
23528c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23538c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
23548c0984e5SSebastian Reichel 					USB_CH_DET, 0x00);
23558c0984e5SSebastian Reichel 			/*Check link status*/
23568c0984e5SSebastian Reichel 			if (is_ab8500(di->parent))
23578c0984e5SSebastian Reichel 				ret = abx500_get_register_interruptible(di->dev,
23588c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_STAT_REG,
23598c0984e5SSebastian Reichel 					&val);
23608c0984e5SSebastian Reichel 			else
23618c0984e5SSebastian Reichel 				ret = abx500_get_register_interruptible(di->dev,
23628c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINK1_STAT_REG,
23638c0984e5SSebastian Reichel 					&val);
23648c0984e5SSebastian Reichel 
23658c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB link status= 0x%02x\n",
23668c0984e5SSebastian Reichel 				(val & link_status) >> USB_LINK_STATUS_SHIFT);
23678c0984e5SSebastian Reichel 			di->invalid_charger_detect_state = 2;
23688c0984e5SSebastian Reichel 		}
23698c0984e5SSebastian Reichel 	} else {
23708c0984e5SSebastian Reichel 		di->invalid_charger_detect_state = 0;
23718c0984e5SSebastian Reichel 	}
23728c0984e5SSebastian Reichel 
23738c0984e5SSebastian Reichel 	if (!(detected_chargers & USB_PW_CONN)) {
23748c0984e5SSebastian Reichel 		di->vbus_detected = false;
23758c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
23768c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
23778c0984e5SSebastian Reichel 		return;
23788c0984e5SSebastian Reichel 	}
23798c0984e5SSebastian Reichel 
23808c0984e5SSebastian Reichel 	dev_dbg(di->dev,"%s di->vbus_detected = true\n",__func__);
23818c0984e5SSebastian Reichel 	di->vbus_detected = true;
23828c0984e5SSebastian Reichel 	ret = ab8500_charger_read_usb_type(di);
23838c0984e5SSebastian Reichel 	if (ret) {
23848c0984e5SSebastian Reichel 		if (ret == -ENXIO) {
23858c0984e5SSebastian Reichel 			/* No valid charger type detected */
23868c0984e5SSebastian Reichel 			ab8500_charger_set_usb_connected(di, false);
23878c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
23888c0984e5SSebastian Reichel 		}
23898c0984e5SSebastian Reichel 		return;
23908c0984e5SSebastian Reichel 	}
23918c0984e5SSebastian Reichel 
23928c0984e5SSebastian Reichel 	if (di->usb_device_is_unrecognised) {
23938c0984e5SSebastian Reichel 		dev_dbg(di->dev,
23948c0984e5SSebastian Reichel 			"Potential Legacy Charger device. "
23958c0984e5SSebastian Reichel 			"Delay work for %d msec for USB enum "
23968c0984e5SSebastian Reichel 			"to finish",
23978c0984e5SSebastian Reichel 			WAIT_ACA_RID_ENUMERATION);
23988c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
23998c0984e5SSebastian Reichel 				   &di->attach_work,
24008c0984e5SSebastian Reichel 				   msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION));
24018c0984e5SSebastian Reichel 	} else if (di->is_aca_rid == 1) {
24028c0984e5SSebastian Reichel 		/* Only wait once */
24038c0984e5SSebastian Reichel 		di->is_aca_rid++;
24048c0984e5SSebastian Reichel 		dev_dbg(di->dev,
24058c0984e5SSebastian Reichel 			"%s Wait %d msec for USB enum to finish",
24068c0984e5SSebastian Reichel 			__func__, WAIT_ACA_RID_ENUMERATION);
24078c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
24088c0984e5SSebastian Reichel 				   &di->attach_work,
24098c0984e5SSebastian Reichel 				   msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION));
24108c0984e5SSebastian Reichel 	} else {
24118c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
24128c0984e5SSebastian Reichel 				   &di->attach_work,
24138c0984e5SSebastian Reichel 				   0);
24148c0984e5SSebastian Reichel 	}
24158c0984e5SSebastian Reichel }
24168c0984e5SSebastian Reichel 
24178c0984e5SSebastian Reichel static void ab8500_charger_usb_state_changed_work(struct work_struct *work)
24188c0984e5SSebastian Reichel {
24198c0984e5SSebastian Reichel 	int ret;
24208c0984e5SSebastian Reichel 	unsigned long flags;
24218c0984e5SSebastian Reichel 
24228c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
24238c0984e5SSebastian Reichel 		struct ab8500_charger, usb_state_changed_work.work);
24248c0984e5SSebastian Reichel 
24258c0984e5SSebastian Reichel 	if (!di->vbus_detected)	{
24268c0984e5SSebastian Reichel 		dev_dbg(di->dev,
24278c0984e5SSebastian Reichel 			"%s !di->vbus_detected\n",
24288c0984e5SSebastian Reichel 			__func__);
24298c0984e5SSebastian Reichel 		return;
24308c0984e5SSebastian Reichel 	}
24318c0984e5SSebastian Reichel 
24328c0984e5SSebastian Reichel 	spin_lock_irqsave(&di->usb_state.usb_lock, flags);
24338c0984e5SSebastian Reichel 	di->usb_state.state = di->usb_state.state_tmp;
243483e5aa77SLinus Walleij 	di->usb_state.usb_current_ua = di->usb_state.usb_current_tmp_ua;
24358c0984e5SSebastian Reichel 	spin_unlock_irqrestore(&di->usb_state.usb_lock, flags);
24368c0984e5SSebastian Reichel 
243783e5aa77SLinus Walleij 	dev_dbg(di->dev, "%s USB state: 0x%02x uA: %d\n",
243883e5aa77SLinus Walleij 		__func__, di->usb_state.state, di->usb_state.usb_current_ua);
24398c0984e5SSebastian Reichel 
24408c0984e5SSebastian Reichel 	switch (di->usb_state.state) {
24418c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESET_HS:
24428c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESET_FS:
24438c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_SUSPEND:
24448c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_MAX:
24458c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
24468c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
24478c0984e5SSebastian Reichel 		break;
24488c0984e5SSebastian Reichel 
24498c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESUME:
24508c0984e5SSebastian Reichel 		/*
24518c0984e5SSebastian Reichel 		 * when suspend->resume there should be delay
24528c0984e5SSebastian Reichel 		 * of 1sec for enabling charging
24538c0984e5SSebastian Reichel 		 */
24548c0984e5SSebastian Reichel 		msleep(1000);
2455df561f66SGustavo A. R. Silva 		fallthrough;
24568c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_CONFIGURED:
24578c0984e5SSebastian Reichel 		/*
24588c0984e5SSebastian Reichel 		 * USB is configured, enable charging with the charging
24598c0984e5SSebastian Reichel 		 * input current obtained from USB driver
24608c0984e5SSebastian Reichel 		 */
24618c0984e5SSebastian Reichel 		if (!ab8500_charger_get_usb_cur(di)) {
24628c0984e5SSebastian Reichel 			/* Update maximum input current */
24638c0984e5SSebastian Reichel 			ret = ab8500_charger_set_vbus_in_curr(di,
246483e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
24658c0984e5SSebastian Reichel 			if (ret)
24668c0984e5SSebastian Reichel 				return;
24678c0984e5SSebastian Reichel 
24688c0984e5SSebastian Reichel 			ab8500_charger_set_usb_connected(di, true);
24698c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
24708c0984e5SSebastian Reichel 		}
24718c0984e5SSebastian Reichel 		break;
24728c0984e5SSebastian Reichel 
24738c0984e5SSebastian Reichel 	default:
24748c0984e5SSebastian Reichel 		break;
2475e15c54d2SMa Feng 	}
24768c0984e5SSebastian Reichel }
24778c0984e5SSebastian Reichel 
24788c0984e5SSebastian Reichel /**
24798c0984e5SSebastian Reichel  * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status
24808c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
24818c0984e5SSebastian Reichel  *
24828c0984e5SSebastian Reichel  * Work queue function for checking the USB charger Not OK status
24838c0984e5SSebastian Reichel  */
24848c0984e5SSebastian Reichel static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work)
24858c0984e5SSebastian Reichel {
24868c0984e5SSebastian Reichel 	int ret;
24878c0984e5SSebastian Reichel 	u8 reg_value;
24888c0984e5SSebastian Reichel 	bool prev_status;
24898c0984e5SSebastian Reichel 
24908c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
24918c0984e5SSebastian Reichel 		struct ab8500_charger, check_usbchgnotok_work.work);
24928c0984e5SSebastian Reichel 
24938c0984e5SSebastian Reichel 	/* Check if the status bit for usbchargernotok is still active */
24948c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
24958c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
24968c0984e5SSebastian Reichel 	if (ret < 0) {
24978c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
24988c0984e5SSebastian Reichel 		return;
24998c0984e5SSebastian Reichel 	}
25008c0984e5SSebastian Reichel 	prev_status = di->flags.usbchargernotok;
25018c0984e5SSebastian Reichel 
25028c0984e5SSebastian Reichel 	if (reg_value & VBUS_CH_NOK) {
25038c0984e5SSebastian Reichel 		di->flags.usbchargernotok = true;
25048c0984e5SSebastian Reichel 		/* Check again in 1sec */
25058c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
25068c0984e5SSebastian Reichel 			&di->check_usbchgnotok_work, HZ);
25078c0984e5SSebastian Reichel 	} else {
25088c0984e5SSebastian Reichel 		di->flags.usbchargernotok = false;
25098c0984e5SSebastian Reichel 		di->flags.vbus_collapse = false;
25108c0984e5SSebastian Reichel 	}
25118c0984e5SSebastian Reichel 
25128c0984e5SSebastian Reichel 	if (prev_status != di->flags.usbchargernotok)
25138c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
25148c0984e5SSebastian Reichel }
25158c0984e5SSebastian Reichel 
25168c0984e5SSebastian Reichel /**
25178c0984e5SSebastian Reichel  * ab8500_charger_check_main_thermal_prot_work() - check main thermal status
25188c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
25198c0984e5SSebastian Reichel  *
25208c0984e5SSebastian Reichel  * Work queue function for checking the Main thermal prot status
25218c0984e5SSebastian Reichel  */
25228c0984e5SSebastian Reichel static void ab8500_charger_check_main_thermal_prot_work(
25238c0984e5SSebastian Reichel 	struct work_struct *work)
25248c0984e5SSebastian Reichel {
25258c0984e5SSebastian Reichel 	int ret;
25268c0984e5SSebastian Reichel 	u8 reg_value;
25278c0984e5SSebastian Reichel 
25288c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
25298c0984e5SSebastian Reichel 		struct ab8500_charger, check_main_thermal_prot_work);
25308c0984e5SSebastian Reichel 
25318c0984e5SSebastian Reichel 	/* Check if the status bit for main_thermal_prot is still active */
25328c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
25338c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
25348c0984e5SSebastian Reichel 	if (ret < 0) {
25358c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
25368c0984e5SSebastian Reichel 		return;
25378c0984e5SSebastian Reichel 	}
25388c0984e5SSebastian Reichel 	if (reg_value & MAIN_CH_TH_PROT)
25398c0984e5SSebastian Reichel 		di->flags.main_thermal_prot = true;
25408c0984e5SSebastian Reichel 	else
25418c0984e5SSebastian Reichel 		di->flags.main_thermal_prot = false;
25428c0984e5SSebastian Reichel 
25438c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
25448c0984e5SSebastian Reichel }
25458c0984e5SSebastian Reichel 
25468c0984e5SSebastian Reichel /**
25478c0984e5SSebastian Reichel  * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status
25488c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
25498c0984e5SSebastian Reichel  *
25508c0984e5SSebastian Reichel  * Work queue function for checking the USB thermal prot status
25518c0984e5SSebastian Reichel  */
25528c0984e5SSebastian Reichel static void ab8500_charger_check_usb_thermal_prot_work(
25538c0984e5SSebastian Reichel 	struct work_struct *work)
25548c0984e5SSebastian Reichel {
25558c0984e5SSebastian Reichel 	int ret;
25568c0984e5SSebastian Reichel 	u8 reg_value;
25578c0984e5SSebastian Reichel 
25588c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
25598c0984e5SSebastian Reichel 		struct ab8500_charger, check_usb_thermal_prot_work);
25608c0984e5SSebastian Reichel 
25618c0984e5SSebastian Reichel 	/* Check if the status bit for usb_thermal_prot is still active */
25628c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
25638c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
25648c0984e5SSebastian Reichel 	if (ret < 0) {
25658c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
25668c0984e5SSebastian Reichel 		return;
25678c0984e5SSebastian Reichel 	}
25688c0984e5SSebastian Reichel 	if (reg_value & USB_CH_TH_PROT)
25698c0984e5SSebastian Reichel 		di->flags.usb_thermal_prot = true;
25708c0984e5SSebastian Reichel 	else
25718c0984e5SSebastian Reichel 		di->flags.usb_thermal_prot = false;
25728c0984e5SSebastian Reichel 
25738c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
25748c0984e5SSebastian Reichel }
25758c0984e5SSebastian Reichel 
25768c0984e5SSebastian Reichel /**
25778c0984e5SSebastian Reichel  * ab8500_charger_mainchunplugdet_handler() - main charger unplugged
25788c0984e5SSebastian Reichel  * @irq:       interrupt number
25798c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
25808c0984e5SSebastian Reichel  *
25818c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
25828c0984e5SSebastian Reichel  */
25838c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di)
25848c0984e5SSebastian Reichel {
25858c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
25868c0984e5SSebastian Reichel 
25878c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger unplugged\n");
25888c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
25898c0984e5SSebastian Reichel 
25908c0984e5SSebastian Reichel 	cancel_delayed_work_sync(&di->ac_charger_attached_work);
25918c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
25928c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
25938c0984e5SSebastian Reichel 
25948c0984e5SSebastian Reichel 	return IRQ_HANDLED;
25958c0984e5SSebastian Reichel }
25968c0984e5SSebastian Reichel 
25978c0984e5SSebastian Reichel /**
25988c0984e5SSebastian Reichel  * ab8500_charger_mainchplugdet_handler() - main charger plugged
25998c0984e5SSebastian Reichel  * @irq:       interrupt number
26008c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26018c0984e5SSebastian Reichel  *
26028c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26038c0984e5SSebastian Reichel  */
26048c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di)
26058c0984e5SSebastian Reichel {
26068c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26078c0984e5SSebastian Reichel 
26088c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger plugged\n");
26098c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
26108c0984e5SSebastian Reichel 
26118c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
26128c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
26138c0984e5SSebastian Reichel 
26148c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
26158c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
26168c0984e5SSebastian Reichel 			   &di->ac_charger_attached_work,
26178c0984e5SSebastian Reichel 			   HZ);
26188c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26198c0984e5SSebastian Reichel }
26208c0984e5SSebastian Reichel 
26218c0984e5SSebastian Reichel /**
26228c0984e5SSebastian Reichel  * ab8500_charger_mainextchnotok_handler() - main charger not ok
26238c0984e5SSebastian Reichel  * @irq:       interrupt number
26248c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26258c0984e5SSebastian Reichel  *
26268c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26278c0984e5SSebastian Reichel  */
26288c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di)
26298c0984e5SSebastian Reichel {
26308c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26318c0984e5SSebastian Reichel 
26328c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger not ok\n");
26338c0984e5SSebastian Reichel 	di->flags.mainextchnotok = true;
26348c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
26358c0984e5SSebastian Reichel 
26368c0984e5SSebastian Reichel 	/* Schedule a new HW failure check */
26378c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
26388c0984e5SSebastian Reichel 
26398c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26408c0984e5SSebastian Reichel }
26418c0984e5SSebastian Reichel 
26428c0984e5SSebastian Reichel /**
26438c0984e5SSebastian Reichel  * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger
26448c0984e5SSebastian Reichel  * thermal protection threshold
26458c0984e5SSebastian Reichel  * @irq:       interrupt number
26468c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26478c0984e5SSebastian Reichel  *
26488c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26498c0984e5SSebastian Reichel  */
26508c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di)
26518c0984e5SSebastian Reichel {
26528c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26538c0984e5SSebastian Reichel 
26548c0984e5SSebastian Reichel 	dev_dbg(di->dev,
26558c0984e5SSebastian Reichel 		"Die temp above Main charger thermal protection threshold\n");
26568c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
26578c0984e5SSebastian Reichel 
26588c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26598c0984e5SSebastian Reichel }
26608c0984e5SSebastian Reichel 
26618c0984e5SSebastian Reichel /**
26628c0984e5SSebastian Reichel  * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger
26638c0984e5SSebastian Reichel  * thermal protection threshold
26648c0984e5SSebastian Reichel  * @irq:       interrupt number
26658c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26668c0984e5SSebastian Reichel  *
26678c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26688c0984e5SSebastian Reichel  */
26698c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di)
26708c0984e5SSebastian Reichel {
26718c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26728c0984e5SSebastian Reichel 
26738c0984e5SSebastian Reichel 	dev_dbg(di->dev,
26748c0984e5SSebastian Reichel 		"Die temp ok for Main charger thermal protection threshold\n");
26758c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
26768c0984e5SSebastian Reichel 
26778c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26788c0984e5SSebastian Reichel }
26798c0984e5SSebastian Reichel 
26808c0984e5SSebastian Reichel static void ab8500_charger_vbus_drop_end_work(struct work_struct *work)
26818c0984e5SSebastian Reichel {
26828c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
26838c0984e5SSebastian Reichel 		struct ab8500_charger, vbus_drop_end_work.work);
268483e5aa77SLinus Walleij 	int ret, curr_ua;
26858c0984e5SSebastian Reichel 	u8 reg_value;
26868c0984e5SSebastian Reichel 
26878c0984e5SSebastian Reichel 	di->flags.vbus_drop_end = false;
26888c0984e5SSebastian Reichel 
26898c0984e5SSebastian Reichel 	/* Reset the drop counter */
26908c0984e5SSebastian Reichel 	abx500_set_register_interruptible(di->dev,
26918c0984e5SSebastian Reichel 				  AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01);
26928c0984e5SSebastian Reichel 
26938c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
26948c0984e5SSebastian Reichel 			AB8500_CH_USBCH_STAT2_REG, &reg_value);
26958c0984e5SSebastian Reichel 	if (ret < 0) {
26968c0984e5SSebastian Reichel 		dev_err(di->dev, "%s read failed\n", __func__);
26978c0984e5SSebastian Reichel 		return;
26988c0984e5SSebastian Reichel 	}
26998c0984e5SSebastian Reichel 
270083e5aa77SLinus Walleij 	curr_ua = ab8500_charge_input_curr_map[
27018c0984e5SSebastian Reichel 		reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT];
27028c0984e5SSebastian Reichel 
270383e5aa77SLinus Walleij 	if (di->max_usb_in_curr.calculated_max_ua != curr_ua) {
27048c0984e5SSebastian Reichel 		/* USB source is collapsing */
270583e5aa77SLinus Walleij 		di->max_usb_in_curr.calculated_max_ua = curr_ua;
27068c0984e5SSebastian Reichel 		dev_dbg(di->dev,
270783e5aa77SLinus Walleij 			 "VBUS input current limiting to %d uA\n",
270883e5aa77SLinus Walleij 			 di->max_usb_in_curr.calculated_max_ua);
27098c0984e5SSebastian Reichel 	} else {
27108c0984e5SSebastian Reichel 		/*
27118c0984e5SSebastian Reichel 		 * USB source can not give more than this amount.
27128c0984e5SSebastian Reichel 		 * Taking more will collapse the source.
27138c0984e5SSebastian Reichel 		 */
271483e5aa77SLinus Walleij 		di->max_usb_in_curr.set_max_ua =
271583e5aa77SLinus Walleij 			di->max_usb_in_curr.calculated_max_ua;
27168c0984e5SSebastian Reichel 		dev_dbg(di->dev,
271783e5aa77SLinus Walleij 			 "VBUS input current limited to %d uA\n",
271883e5aa77SLinus Walleij 			 di->max_usb_in_curr.set_max_ua);
27198c0984e5SSebastian Reichel 	}
27208c0984e5SSebastian Reichel 
27218c0984e5SSebastian Reichel 	if (di->usb.charger_connected)
27228c0984e5SSebastian Reichel 		ab8500_charger_set_vbus_in_curr(di,
272383e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
27248c0984e5SSebastian Reichel }
27258c0984e5SSebastian Reichel 
27268c0984e5SSebastian Reichel /**
27278c0984e5SSebastian Reichel  * ab8500_charger_vbusdetf_handler() - VBUS falling detected
27288c0984e5SSebastian Reichel  * @irq:       interrupt number
27298c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27308c0984e5SSebastian Reichel  *
27318c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27328c0984e5SSebastian Reichel  */
27338c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di)
27348c0984e5SSebastian Reichel {
27358c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27368c0984e5SSebastian Reichel 
27378c0984e5SSebastian Reichel 	di->vbus_detected = false;
27388c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS falling detected\n");
27398c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->detect_usb_type_work);
27408c0984e5SSebastian Reichel 
27418c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27428c0984e5SSebastian Reichel }
27438c0984e5SSebastian Reichel 
27448c0984e5SSebastian Reichel /**
27458c0984e5SSebastian Reichel  * ab8500_charger_vbusdetr_handler() - VBUS rising detected
27468c0984e5SSebastian Reichel  * @irq:       interrupt number
27478c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27488c0984e5SSebastian Reichel  *
27498c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27508c0984e5SSebastian Reichel  */
27518c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di)
27528c0984e5SSebastian Reichel {
27538c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27548c0984e5SSebastian Reichel 
27558c0984e5SSebastian Reichel 	di->vbus_detected = true;
27568c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS rising detected\n");
27578c0984e5SSebastian Reichel 
27588c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->detect_usb_type_work);
27598c0984e5SSebastian Reichel 
27608c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27618c0984e5SSebastian Reichel }
27628c0984e5SSebastian Reichel 
27638c0984e5SSebastian Reichel /**
27648c0984e5SSebastian Reichel  * ab8500_charger_usblinkstatus_handler() - USB link status has changed
27658c0984e5SSebastian Reichel  * @irq:       interrupt number
27668c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27678c0984e5SSebastian Reichel  *
27688c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27698c0984e5SSebastian Reichel  */
27708c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di)
27718c0984e5SSebastian Reichel {
27728c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27738c0984e5SSebastian Reichel 
27748c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB link status changed\n");
27758c0984e5SSebastian Reichel 
27768c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->usb_link_status_work);
27778c0984e5SSebastian Reichel 
27788c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27798c0984e5SSebastian Reichel }
27808c0984e5SSebastian Reichel 
27818c0984e5SSebastian Reichel /**
27828c0984e5SSebastian Reichel  * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger
27838c0984e5SSebastian Reichel  * thermal protection threshold
27848c0984e5SSebastian Reichel  * @irq:       interrupt number
27858c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27868c0984e5SSebastian Reichel  *
27878c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27888c0984e5SSebastian Reichel  */
27898c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di)
27908c0984e5SSebastian Reichel {
27918c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27928c0984e5SSebastian Reichel 
27938c0984e5SSebastian Reichel 	dev_dbg(di->dev,
27948c0984e5SSebastian Reichel 		"Die temp above USB charger thermal protection threshold\n");
27958c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
27968c0984e5SSebastian Reichel 
27978c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27988c0984e5SSebastian Reichel }
27998c0984e5SSebastian Reichel 
28008c0984e5SSebastian Reichel /**
28018c0984e5SSebastian Reichel  * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger
28028c0984e5SSebastian Reichel  * thermal protection threshold
28038c0984e5SSebastian Reichel  * @irq:       interrupt number
28048c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28058c0984e5SSebastian Reichel  *
28068c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28078c0984e5SSebastian Reichel  */
28088c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di)
28098c0984e5SSebastian Reichel {
28108c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28118c0984e5SSebastian Reichel 
28128c0984e5SSebastian Reichel 	dev_dbg(di->dev,
28138c0984e5SSebastian Reichel 		"Die temp ok for USB charger thermal protection threshold\n");
28148c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
28158c0984e5SSebastian Reichel 
28168c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28178c0984e5SSebastian Reichel }
28188c0984e5SSebastian Reichel 
28198c0984e5SSebastian Reichel /**
28208c0984e5SSebastian Reichel  * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected
28218c0984e5SSebastian Reichel  * @irq:       interrupt number
28228c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28238c0984e5SSebastian Reichel  *
28248c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28258c0984e5SSebastian Reichel  */
28268c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di)
28278c0984e5SSebastian Reichel {
28288c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28298c0984e5SSebastian Reichel 
28308c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Not allowed USB charger detected\n");
28318c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0);
28328c0984e5SSebastian Reichel 
28338c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28348c0984e5SSebastian Reichel }
28358c0984e5SSebastian Reichel 
28368c0984e5SSebastian Reichel /**
28378c0984e5SSebastian Reichel  * ab8500_charger_chwdexp_handler() - Charger watchdog expired
28388c0984e5SSebastian Reichel  * @irq:       interrupt number
28398c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28408c0984e5SSebastian Reichel  *
28418c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28428c0984e5SSebastian Reichel  */
28438c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di)
28448c0984e5SSebastian Reichel {
28458c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28468c0984e5SSebastian Reichel 
28478c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Charger watchdog expired\n");
28488c0984e5SSebastian Reichel 
28498c0984e5SSebastian Reichel 	/*
28508c0984e5SSebastian Reichel 	 * The charger that was online when the watchdog expired
28518c0984e5SSebastian Reichel 	 * needs to be restarted for charging to start again
28528c0984e5SSebastian Reichel 	 */
28538c0984e5SSebastian Reichel 	if (di->ac.charger_online) {
28548c0984e5SSebastian Reichel 		di->ac.wd_expired = true;
28558c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->ac_chg.psy);
28568c0984e5SSebastian Reichel 	}
28578c0984e5SSebastian Reichel 	if (di->usb.charger_online) {
28588c0984e5SSebastian Reichel 		di->usb.wd_expired = true;
28598c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
28608c0984e5SSebastian Reichel 	}
28618c0984e5SSebastian Reichel 
28628c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28638c0984e5SSebastian Reichel }
28648c0984e5SSebastian Reichel 
28658c0984e5SSebastian Reichel /**
28668c0984e5SSebastian Reichel  * ab8500_charger_vbuschdropend_handler() - VBUS drop removed
28678c0984e5SSebastian Reichel  * @irq:       interrupt number
28688c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28698c0984e5SSebastian Reichel  *
28708c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28718c0984e5SSebastian Reichel  */
28728c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di)
28738c0984e5SSebastian Reichel {
28748c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28758c0984e5SSebastian Reichel 
28768c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS charger drop ended\n");
28778c0984e5SSebastian Reichel 	di->flags.vbus_drop_end = true;
28788c0984e5SSebastian Reichel 
28798c0984e5SSebastian Reichel 	/*
28808c0984e5SSebastian Reichel 	 * VBUS might have dropped due to bad connection.
28818c0984e5SSebastian Reichel 	 * Schedule a new input limit set to the value SW requests.
28828c0984e5SSebastian Reichel 	 */
28838c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work,
28848c0984e5SSebastian Reichel 			   round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ));
28858c0984e5SSebastian Reichel 
28868c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28878c0984e5SSebastian Reichel }
28888c0984e5SSebastian Reichel 
28898c0984e5SSebastian Reichel /**
28908c0984e5SSebastian Reichel  * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected
28918c0984e5SSebastian Reichel  * @irq:       interrupt number
28928c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28938c0984e5SSebastian Reichel  *
28948c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28958c0984e5SSebastian Reichel  */
28968c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di)
28978c0984e5SSebastian Reichel {
28988c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28998c0984e5SSebastian Reichel 
29008c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS overvoltage detected\n");
29018c0984e5SSebastian Reichel 	di->flags.vbus_ovv = true;
29028c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
29038c0984e5SSebastian Reichel 
29048c0984e5SSebastian Reichel 	/* Schedule a new HW failure check */
29058c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
29068c0984e5SSebastian Reichel 
29078c0984e5SSebastian Reichel 	return IRQ_HANDLED;
29088c0984e5SSebastian Reichel }
29098c0984e5SSebastian Reichel 
29108c0984e5SSebastian Reichel /**
29118c0984e5SSebastian Reichel  * ab8500_charger_ac_get_property() - get the ac/mains properties
29128c0984e5SSebastian Reichel  * @psy:       pointer to the power_supply structure
29138c0984e5SSebastian Reichel  * @psp:       pointer to the power_supply_property structure
29148c0984e5SSebastian Reichel  * @val:       pointer to the power_supply_propval union
29158c0984e5SSebastian Reichel  *
29168c0984e5SSebastian Reichel  * This function gets called when an application tries to get the ac/mains
29178c0984e5SSebastian Reichel  * properties by reading the sysfs files.
29188c0984e5SSebastian Reichel  * AC/Mains properties are online, present and voltage.
29198c0984e5SSebastian Reichel  * online:     ac/mains charging is in progress or not
29208c0984e5SSebastian Reichel  * present:    presence of the ac/mains
29218c0984e5SSebastian Reichel  * voltage:    AC/Mains voltage
29228c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
29238c0984e5SSebastian Reichel  */
29248c0984e5SSebastian Reichel static int ab8500_charger_ac_get_property(struct power_supply *psy,
29258c0984e5SSebastian Reichel 	enum power_supply_property psp,
29268c0984e5SSebastian Reichel 	union power_supply_propval *val)
29278c0984e5SSebastian Reichel {
29288c0984e5SSebastian Reichel 	struct ab8500_charger *di;
29298c0984e5SSebastian Reichel 	int ret;
29308c0984e5SSebastian Reichel 
29318c0984e5SSebastian Reichel 	di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy));
29328c0984e5SSebastian Reichel 
29338c0984e5SSebastian Reichel 	switch (psp) {
29348c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_HEALTH:
29358c0984e5SSebastian Reichel 		if (di->flags.mainextchnotok)
29368c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
29378c0984e5SSebastian Reichel 		else if (di->ac.wd_expired || di->usb.wd_expired)
29388c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
29398c0984e5SSebastian Reichel 		else if (di->flags.main_thermal_prot)
29408c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
29418c0984e5SSebastian Reichel 		else
29428c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
29438c0984e5SSebastian Reichel 		break;
29448c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_ONLINE:
29458c0984e5SSebastian Reichel 		val->intval = di->ac.charger_online;
29468c0984e5SSebastian Reichel 		break;
29478c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_PRESENT:
29488c0984e5SSebastian Reichel 		val->intval = di->ac.charger_connected;
29498c0984e5SSebastian Reichel 		break;
29508c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
29518c0984e5SSebastian Reichel 		ret = ab8500_charger_get_ac_voltage(di);
29528c0984e5SSebastian Reichel 		if (ret >= 0)
2953bc6e0287SLinus Walleij 			di->ac.charger_voltage_uv = ret;
29548c0984e5SSebastian Reichel 		/* On error, use previous value */
2955bc6e0287SLinus Walleij 		val->intval = di->ac.charger_voltage_uv;
29568c0984e5SSebastian Reichel 		break;
29578c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
29588c0984e5SSebastian Reichel 		/*
29598c0984e5SSebastian Reichel 		 * This property is used to indicate when CV mode is entered
29608c0984e5SSebastian Reichel 		 * for the AC charger
29618c0984e5SSebastian Reichel 		 */
29628c0984e5SSebastian Reichel 		di->ac.cv_active = ab8500_charger_ac_cv(di);
29638c0984e5SSebastian Reichel 		val->intval = di->ac.cv_active;
29648c0984e5SSebastian Reichel 		break;
29658c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_NOW:
29668c0984e5SSebastian Reichel 		ret = ab8500_charger_get_ac_current(di);
29678c0984e5SSebastian Reichel 		if (ret >= 0)
296883e5aa77SLinus Walleij 			di->ac.charger_current_ua = ret;
296983e5aa77SLinus Walleij 		val->intval = di->ac.charger_current_ua;
29708c0984e5SSebastian Reichel 		break;
29718c0984e5SSebastian Reichel 	default:
29728c0984e5SSebastian Reichel 		return -EINVAL;
29738c0984e5SSebastian Reichel 	}
29748c0984e5SSebastian Reichel 	return 0;
29758c0984e5SSebastian Reichel }
29768c0984e5SSebastian Reichel 
29778c0984e5SSebastian Reichel /**
29788c0984e5SSebastian Reichel  * ab8500_charger_usb_get_property() - get the usb properties
29798c0984e5SSebastian Reichel  * @psy:        pointer to the power_supply structure
29808c0984e5SSebastian Reichel  * @psp:        pointer to the power_supply_property structure
29818c0984e5SSebastian Reichel  * @val:        pointer to the power_supply_propval union
29828c0984e5SSebastian Reichel  *
29838c0984e5SSebastian Reichel  * This function gets called when an application tries to get the usb
29848c0984e5SSebastian Reichel  * properties by reading the sysfs files.
29858c0984e5SSebastian Reichel  * USB properties are online, present and voltage.
29868c0984e5SSebastian Reichel  * online:     usb charging is in progress or not
29878c0984e5SSebastian Reichel  * present:    presence of the usb
29888c0984e5SSebastian Reichel  * voltage:    vbus voltage
29898c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
29908c0984e5SSebastian Reichel  */
29918c0984e5SSebastian Reichel static int ab8500_charger_usb_get_property(struct power_supply *psy,
29928c0984e5SSebastian Reichel 	enum power_supply_property psp,
29938c0984e5SSebastian Reichel 	union power_supply_propval *val)
29948c0984e5SSebastian Reichel {
29958c0984e5SSebastian Reichel 	struct ab8500_charger *di;
29968c0984e5SSebastian Reichel 	int ret;
29978c0984e5SSebastian Reichel 
29988c0984e5SSebastian Reichel 	di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy));
29998c0984e5SSebastian Reichel 
30008c0984e5SSebastian Reichel 	switch (psp) {
30018c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_HEALTH:
30028c0984e5SSebastian Reichel 		if (di->flags.usbchargernotok)
30038c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
30048c0984e5SSebastian Reichel 		else if (di->ac.wd_expired || di->usb.wd_expired)
30058c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
30068c0984e5SSebastian Reichel 		else if (di->flags.usb_thermal_prot)
30078c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
30088c0984e5SSebastian Reichel 		else if (di->flags.vbus_ovv)
30098c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
30108c0984e5SSebastian Reichel 		else
30118c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
30128c0984e5SSebastian Reichel 		break;
30138c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_ONLINE:
30148c0984e5SSebastian Reichel 		val->intval = di->usb.charger_online;
30158c0984e5SSebastian Reichel 		break;
30168c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_PRESENT:
30178c0984e5SSebastian Reichel 		val->intval = di->usb.charger_connected;
30188c0984e5SSebastian Reichel 		break;
30198c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
30208c0984e5SSebastian Reichel 		ret = ab8500_charger_get_vbus_voltage(di);
30218c0984e5SSebastian Reichel 		if (ret >= 0)
3022bc6e0287SLinus Walleij 			di->usb.charger_voltage_uv = ret;
3023bc6e0287SLinus Walleij 		val->intval = di->usb.charger_voltage_uv;
30248c0984e5SSebastian Reichel 		break;
30258c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
30268c0984e5SSebastian Reichel 		/*
30278c0984e5SSebastian Reichel 		 * This property is used to indicate when CV mode is entered
30288c0984e5SSebastian Reichel 		 * for the USB charger
30298c0984e5SSebastian Reichel 		 */
30308c0984e5SSebastian Reichel 		di->usb.cv_active = ab8500_charger_usb_cv(di);
30318c0984e5SSebastian Reichel 		val->intval = di->usb.cv_active;
30328c0984e5SSebastian Reichel 		break;
30338c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_NOW:
30348c0984e5SSebastian Reichel 		ret = ab8500_charger_get_usb_current(di);
30358c0984e5SSebastian Reichel 		if (ret >= 0)
303683e5aa77SLinus Walleij 			di->usb.charger_current_ua = ret;
303783e5aa77SLinus Walleij 		val->intval = di->usb.charger_current_ua;
30388c0984e5SSebastian Reichel 		break;
30398c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_AVG:
30408c0984e5SSebastian Reichel 		/*
30418c0984e5SSebastian Reichel 		 * This property is used to indicate when VBUS has collapsed
30428c0984e5SSebastian Reichel 		 * due to too high output current from the USB charger
30438c0984e5SSebastian Reichel 		 */
30448c0984e5SSebastian Reichel 		if (di->flags.vbus_collapse)
30458c0984e5SSebastian Reichel 			val->intval = 1;
30468c0984e5SSebastian Reichel 		else
30478c0984e5SSebastian Reichel 			val->intval = 0;
30488c0984e5SSebastian Reichel 		break;
30498c0984e5SSebastian Reichel 	default:
30508c0984e5SSebastian Reichel 		return -EINVAL;
30518c0984e5SSebastian Reichel 	}
30528c0984e5SSebastian Reichel 	return 0;
30538c0984e5SSebastian Reichel }
30548c0984e5SSebastian Reichel 
30558c0984e5SSebastian Reichel /**
30568c0984e5SSebastian Reichel  * ab8500_charger_init_hw_registers() - Set up charger related registers
30578c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
30588c0984e5SSebastian Reichel  *
30598c0984e5SSebastian Reichel  * Set up charger OVV, watchdog and maximum voltage registers as well as
30608c0984e5SSebastian Reichel  * charging of the backup battery
30618c0984e5SSebastian Reichel  */
30628c0984e5SSebastian Reichel static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
30638c0984e5SSebastian Reichel {
30648c0984e5SSebastian Reichel 	int ret = 0;
30658c0984e5SSebastian Reichel 
30668c0984e5SSebastian Reichel 	/* Setup maximum charger current and voltage for ABB cut2.0 */
30678c0984e5SSebastian Reichel 	if (!is_ab8500_1p1_or_earlier(di->parent)) {
30688c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30698c0984e5SSebastian Reichel 			AB8500_CHARGER,
30708c0984e5SSebastian Reichel 			AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6);
30718c0984e5SSebastian Reichel 		if (ret) {
30728c0984e5SSebastian Reichel 			dev_err(di->dev,
30738c0984e5SSebastian Reichel 				"failed to set CH_VOLT_LVL_MAX_REG\n");
30748c0984e5SSebastian Reichel 			goto out;
30758c0984e5SSebastian Reichel 		}
30768c0984e5SSebastian Reichel 
30778c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30788c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG,
30798c0984e5SSebastian Reichel 			CH_OP_CUR_LVL_1P6);
30808c0984e5SSebastian Reichel 		if (ret) {
30818c0984e5SSebastian Reichel 			dev_err(di->dev,
30828c0984e5SSebastian Reichel 				"failed to set CH_OPT_CRNTLVL_MAX_REG\n");
30838c0984e5SSebastian Reichel 			goto out;
30848c0984e5SSebastian Reichel 		}
30858c0984e5SSebastian Reichel 	}
30868c0984e5SSebastian Reichel 
30874c4268dcSLinus Walleij 	if (is_ab8505_2p0(di->parent))
30888c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
30898c0984e5SSebastian Reichel 			AB8500_CHARGER,
30908c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL2_REG,
30918c0984e5SSebastian Reichel 			VBUS_AUTO_IN_CURR_LIM_ENA,
30928c0984e5SSebastian Reichel 			VBUS_AUTO_IN_CURR_LIM_ENA);
30938c0984e5SSebastian Reichel 	else
30948c0984e5SSebastian Reichel 		/*
30958c0984e5SSebastian Reichel 		 * VBUS OVV set to 6.3V and enable automatic current limitation
30968c0984e5SSebastian Reichel 		 */
30978c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30988c0984e5SSebastian Reichel 			AB8500_CHARGER,
30998c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL2_REG,
31008c0984e5SSebastian Reichel 			VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA);
31018c0984e5SSebastian Reichel 	if (ret) {
31028c0984e5SSebastian Reichel 		dev_err(di->dev,
31038c0984e5SSebastian Reichel 			"failed to set automatic current limitation\n");
31048c0984e5SSebastian Reichel 		goto out;
31058c0984e5SSebastian Reichel 	}
31068c0984e5SSebastian Reichel 
31078c0984e5SSebastian Reichel 	/* Enable main watchdog in OTP */
31088c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31098c0984e5SSebastian Reichel 		AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD);
31108c0984e5SSebastian Reichel 	if (ret) {
31118c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to enable main WD in OTP\n");
31128c0984e5SSebastian Reichel 		goto out;
31138c0984e5SSebastian Reichel 	}
31148c0984e5SSebastian Reichel 
31158c0984e5SSebastian Reichel 	/* Enable main watchdog */
31168c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31178c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31188c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA);
31198c0984e5SSebastian Reichel 	if (ret) {
3120b5e11cc1SColin Ian King 		dev_err(di->dev, "failed to enable main watchdog\n");
31218c0984e5SSebastian Reichel 		goto out;
31228c0984e5SSebastian Reichel 	}
31238c0984e5SSebastian Reichel 
31248c0984e5SSebastian Reichel 	/*
31258c0984e5SSebastian Reichel 	 * Due to internal synchronisation, Enable and Kick watchdog bits
31268c0984e5SSebastian Reichel 	 * cannot be enabled in a single write.
31278c0984e5SSebastian Reichel 	 * A minimum delay of 2*32 kHz period (62.5µs) must be inserted
31288c0984e5SSebastian Reichel 	 * between writing Enable then Kick bits.
31298c0984e5SSebastian Reichel 	 */
31308c0984e5SSebastian Reichel 	udelay(63);
31318c0984e5SSebastian Reichel 
31328c0984e5SSebastian Reichel 	/* Kick main watchdog */
31338c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31348c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31358c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG,
31368c0984e5SSebastian Reichel 		(MAIN_WDOG_ENA | MAIN_WDOG_KICK));
31378c0984e5SSebastian Reichel 	if (ret) {
31388c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to kick main watchdog\n");
31398c0984e5SSebastian Reichel 		goto out;
31408c0984e5SSebastian Reichel 	}
31418c0984e5SSebastian Reichel 
31428c0984e5SSebastian Reichel 	/* Disable main watchdog */
31438c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31448c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31458c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS);
31468c0984e5SSebastian Reichel 	if (ret) {
31478c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to disable main watchdog\n");
31488c0984e5SSebastian Reichel 		goto out;
31498c0984e5SSebastian Reichel 	}
31508c0984e5SSebastian Reichel 
31518c0984e5SSebastian Reichel 	/* Set watchdog timeout */
31528c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
31538c0984e5SSebastian Reichel 		AB8500_CH_WD_TIMER_REG, WD_TIMER);
31548c0984e5SSebastian Reichel 	if (ret) {
31558c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to set charger watchdog timeout\n");
31568c0984e5SSebastian Reichel 		goto out;
31578c0984e5SSebastian Reichel 	}
31588c0984e5SSebastian Reichel 
31598c0984e5SSebastian Reichel 	ret = ab8500_charger_led_en(di, false);
31608c0984e5SSebastian Reichel 	if (ret < 0) {
31618c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to disable LED\n");
31628c0984e5SSebastian Reichel 		goto out;
31638c0984e5SSebastian Reichel 	}
31648c0984e5SSebastian Reichel 
31658c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31668c0984e5SSebastian Reichel 		AB8500_RTC,
31678c0984e5SSebastian Reichel 		AB8500_RTC_BACKUP_CHG_REG,
31688c0984e5SSebastian Reichel 		(di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i);
31698c0984e5SSebastian Reichel 	if (ret) {
31708c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to setup backup battery charging\n");
31718c0984e5SSebastian Reichel 		goto out;
31728c0984e5SSebastian Reichel 	}
31738c0984e5SSebastian Reichel 
31748c0984e5SSebastian Reichel 	/* Enable backup battery charging */
3175bf59fdddSChristophe JAILLET 	ret = abx500_mask_and_set_register_interruptible(di->dev,
31768c0984e5SSebastian Reichel 		AB8500_RTC, AB8500_RTC_CTRL_REG,
31778c0984e5SSebastian Reichel 		RTC_BUP_CH_ENA, RTC_BUP_CH_ENA);
317809edcb64SChristophe JAILLET 	if (ret < 0) {
31798c0984e5SSebastian Reichel 		dev_err(di->dev, "%s mask and set failed\n", __func__);
318009edcb64SChristophe JAILLET 		goto out;
318109edcb64SChristophe JAILLET 	}
31828c0984e5SSebastian Reichel 
31838c0984e5SSebastian Reichel out:
31848c0984e5SSebastian Reichel 	return ret;
31858c0984e5SSebastian Reichel }
31868c0984e5SSebastian Reichel 
31878c0984e5SSebastian Reichel /*
31888c0984e5SSebastian Reichel  * ab8500 charger driver interrupts and their respective isr
31898c0984e5SSebastian Reichel  */
31908c0984e5SSebastian Reichel static struct ab8500_charger_interrupts ab8500_charger_irq[] = {
31918c0984e5SSebastian Reichel 	{"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler},
31928c0984e5SSebastian Reichel 	{"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler},
31938c0984e5SSebastian Reichel 	{"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler},
31948c0984e5SSebastian Reichel 	{"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler},
31958c0984e5SSebastian Reichel 	{"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler},
31968c0984e5SSebastian Reichel 	{"VBUS_DET_F", ab8500_charger_vbusdetf_handler},
31978c0984e5SSebastian Reichel 	{"VBUS_DET_R", ab8500_charger_vbusdetr_handler},
31988c0984e5SSebastian Reichel 	{"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler},
31998c0984e5SSebastian Reichel 	{"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler},
32008c0984e5SSebastian Reichel 	{"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler},
32018c0984e5SSebastian Reichel 	{"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler},
32028c0984e5SSebastian Reichel 	{"VBUS_OVV", ab8500_charger_vbusovv_handler},
32038c0984e5SSebastian Reichel 	{"CH_WD_EXP", ab8500_charger_chwdexp_handler},
32048c0984e5SSebastian Reichel 	{"VBUS_CH_DROP_END", ab8500_charger_vbuschdropend_handler},
32058c0984e5SSebastian Reichel };
32068c0984e5SSebastian Reichel 
32078c0984e5SSebastian Reichel static int ab8500_charger_usb_notifier_call(struct notifier_block *nb,
32088c0984e5SSebastian Reichel 		unsigned long event, void *power)
32098c0984e5SSebastian Reichel {
32108c0984e5SSebastian Reichel 	struct ab8500_charger *di =
32118c0984e5SSebastian Reichel 		container_of(nb, struct ab8500_charger, nb);
32128c0984e5SSebastian Reichel 	enum ab8500_usb_state bm_usb_state;
321383e5aa77SLinus Walleij 	/*
321483e5aa77SLinus Walleij 	 * FIXME: it appears the AB8500 PHY never sends what it should here.
321583e5aa77SLinus Walleij 	 * Fix the PHY driver to properly notify the desired current.
321683e5aa77SLinus Walleij 	 * Also broadcast microampere and not milliampere.
321783e5aa77SLinus Walleij 	 */
32188c0984e5SSebastian Reichel 	unsigned mA = *((unsigned *)power);
32198c0984e5SSebastian Reichel 
32208c0984e5SSebastian Reichel 	if (event != USB_EVENT_VBUS) {
32218c0984e5SSebastian Reichel 		dev_dbg(di->dev, "not a standard host, returning\n");
32228c0984e5SSebastian Reichel 		return NOTIFY_DONE;
32238c0984e5SSebastian Reichel 	}
32248c0984e5SSebastian Reichel 
32258c0984e5SSebastian Reichel 	/* TODO: State is fabricate  here. See if charger really needs USB
32268c0984e5SSebastian Reichel 	 * state or if mA is enough
32278c0984e5SSebastian Reichel 	 */
322883e5aa77SLinus Walleij 	if ((di->usb_state.usb_current_ua == 2000) && (mA > 2))
32298c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESUME;
32308c0984e5SSebastian Reichel 	else if (mA == 0)
32318c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESET_HS;
32328c0984e5SSebastian Reichel 	else if (mA == 2)
32338c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_SUSPEND;
32348c0984e5SSebastian Reichel 	else if (mA >= 8) /* 8, 100, 500 */
32358c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED;
32368c0984e5SSebastian Reichel 	else /* Should never occur */
32378c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESET_FS;
32388c0984e5SSebastian Reichel 
32398c0984e5SSebastian Reichel 	dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n",
32408c0984e5SSebastian Reichel 		__func__, bm_usb_state, mA);
32418c0984e5SSebastian Reichel 
32428c0984e5SSebastian Reichel 	spin_lock(&di->usb_state.usb_lock);
32438c0984e5SSebastian Reichel 	di->usb_state.state_tmp = bm_usb_state;
324483e5aa77SLinus Walleij 	/* FIXME: broadcast ua instead, see above */
324583e5aa77SLinus Walleij 	di->usb_state.usb_current_tmp_ua = mA * 1000;
32468c0984e5SSebastian Reichel 	spin_unlock(&di->usb_state.usb_lock);
32478c0984e5SSebastian Reichel 
32488c0984e5SSebastian Reichel 	/*
32498c0984e5SSebastian Reichel 	 * wait for some time until you get updates from the usb stack
32508c0984e5SSebastian Reichel 	 * and negotiations are completed
32518c0984e5SSebastian Reichel 	 */
32528c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->usb_state_changed_work, HZ/2);
32538c0984e5SSebastian Reichel 
32548c0984e5SSebastian Reichel 	return NOTIFY_OK;
32558c0984e5SSebastian Reichel }
32568c0984e5SSebastian Reichel 
3257f8efa0a8SLinus Walleij static int __maybe_unused ab8500_charger_resume(struct device *dev)
32588c0984e5SSebastian Reichel {
32598c0984e5SSebastian Reichel 	int ret;
3260f8efa0a8SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
32618c0984e5SSebastian Reichel 
32628c0984e5SSebastian Reichel 	/*
32638c0984e5SSebastian Reichel 	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
3264ddb74e98SAshish Chavan 	 * logic. That means we have to continuously kick the charger
32658c0984e5SSebastian Reichel 	 * watchdog even when no charger is connected. This is only
32668c0984e5SSebastian Reichel 	 * valid once the AC charger has been enabled. This is
32678c0984e5SSebastian Reichel 	 * a bug that is not handled by the algorithm and the
32688c0984e5SSebastian Reichel 	 * watchdog have to be kicked by the charger driver
32698c0984e5SSebastian Reichel 	 * when the AC charger is disabled
32708c0984e5SSebastian Reichel 	 */
32718c0984e5SSebastian Reichel 	if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) {
32728c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
32738c0984e5SSebastian Reichel 			AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
32748c0984e5SSebastian Reichel 		if (ret)
32758c0984e5SSebastian Reichel 			dev_err(di->dev, "Failed to kick WD!\n");
32768c0984e5SSebastian Reichel 
32778c0984e5SSebastian Reichel 		/* If not already pending start a new timer */
32788c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->kick_wd_work,
32798c0984e5SSebastian Reichel 				   round_jiffies(WD_KICK_INTERVAL));
32808c0984e5SSebastian Reichel 	}
32818c0984e5SSebastian Reichel 
32828c0984e5SSebastian Reichel 	/* If we still have a HW failure, schedule a new check */
32838c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
32848c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
32858c0984e5SSebastian Reichel 			&di->check_hw_failure_work, 0);
32868c0984e5SSebastian Reichel 	}
32878c0984e5SSebastian Reichel 
32888c0984e5SSebastian Reichel 	if (di->flags.vbus_drop_end)
32898c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 0);
32908c0984e5SSebastian Reichel 
32918c0984e5SSebastian Reichel 	return 0;
32928c0984e5SSebastian Reichel }
32938c0984e5SSebastian Reichel 
3294f8efa0a8SLinus Walleij static int __maybe_unused ab8500_charger_suspend(struct device *dev)
32958c0984e5SSebastian Reichel {
3296f8efa0a8SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
32978c0984e5SSebastian Reichel 
32988c0984e5SSebastian Reichel 	/* Cancel any pending jobs */
32998c0984e5SSebastian Reichel 	cancel_delayed_work(&di->check_hw_failure_work);
33008c0984e5SSebastian Reichel 	cancel_delayed_work(&di->vbus_drop_end_work);
33018c0984e5SSebastian Reichel 
33028c0984e5SSebastian Reichel 	flush_delayed_work(&di->attach_work);
33038c0984e5SSebastian Reichel 	flush_delayed_work(&di->usb_charger_attached_work);
33048c0984e5SSebastian Reichel 	flush_delayed_work(&di->ac_charger_attached_work);
33058c0984e5SSebastian Reichel 	flush_delayed_work(&di->check_usbchgnotok_work);
33068c0984e5SSebastian Reichel 	flush_delayed_work(&di->check_vbat_work);
33078c0984e5SSebastian Reichel 	flush_delayed_work(&di->kick_wd_work);
33088c0984e5SSebastian Reichel 
33098c0984e5SSebastian Reichel 	flush_work(&di->usb_link_status_work);
33108c0984e5SSebastian Reichel 	flush_work(&di->ac_work);
33118c0984e5SSebastian Reichel 	flush_work(&di->detect_usb_type_work);
33128c0984e5SSebastian Reichel 
33138c0984e5SSebastian Reichel 	if (atomic_read(&di->current_stepping_sessions))
33148c0984e5SSebastian Reichel 		return -EAGAIN;
33158c0984e5SSebastian Reichel 
33168c0984e5SSebastian Reichel 	return 0;
33178c0984e5SSebastian Reichel }
33188c0984e5SSebastian Reichel 
33198c0984e5SSebastian Reichel static struct notifier_block charger_nb = {
33208c0984e5SSebastian Reichel 	.notifier_call = ab8500_external_charger_prepare,
33218c0984e5SSebastian Reichel };
33228c0984e5SSebastian Reichel 
33238c0984e5SSebastian Reichel static char *supply_interface[] = {
33248c0984e5SSebastian Reichel 	"ab8500_chargalg",
33258c0984e5SSebastian Reichel 	"ab8500_fg",
33268c0984e5SSebastian Reichel 	"ab8500_btemp",
33278c0984e5SSebastian Reichel };
33288c0984e5SSebastian Reichel 
33298c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_ac_chg_desc = {
33308c0984e5SSebastian Reichel 	.name		= "ab8500_ac",
33318c0984e5SSebastian Reichel 	.type		= POWER_SUPPLY_TYPE_MAINS,
33328c0984e5SSebastian Reichel 	.properties	= ab8500_charger_ac_props,
33338c0984e5SSebastian Reichel 	.num_properties	= ARRAY_SIZE(ab8500_charger_ac_props),
33348c0984e5SSebastian Reichel 	.get_property	= ab8500_charger_ac_get_property,
33358c0984e5SSebastian Reichel };
33368c0984e5SSebastian Reichel 
33378c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_usb_chg_desc = {
33388c0984e5SSebastian Reichel 	.name		= "ab8500_usb",
33398c0984e5SSebastian Reichel 	.type		= POWER_SUPPLY_TYPE_USB,
33408c0984e5SSebastian Reichel 	.properties	= ab8500_charger_usb_props,
33418c0984e5SSebastian Reichel 	.num_properties	= ARRAY_SIZE(ab8500_charger_usb_props),
33428c0984e5SSebastian Reichel 	.get_property	= ab8500_charger_usb_get_property,
33438c0984e5SSebastian Reichel };
33448c0984e5SSebastian Reichel 
33451c1f13a0SLinus Walleij static int ab8500_charger_bind(struct device *dev)
33461c1f13a0SLinus Walleij {
33471c1f13a0SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
33481c1f13a0SLinus Walleij 	int ch_stat;
33491c1f13a0SLinus Walleij 	int ret;
33501c1f13a0SLinus Walleij 
33511c1f13a0SLinus Walleij 	/* Create a work queue for the charger */
33521c1f13a0SLinus Walleij 	di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq",
33531c1f13a0SLinus Walleij 						 WQ_MEM_RECLAIM);
33541c1f13a0SLinus Walleij 	if (di->charger_wq == NULL) {
33551c1f13a0SLinus Walleij 		dev_err(dev, "failed to create work queue\n");
33561c1f13a0SLinus Walleij 		return -ENOMEM;
33571c1f13a0SLinus Walleij 	}
33581c1f13a0SLinus Walleij 
33591c1f13a0SLinus Walleij 	ch_stat = ab8500_charger_detect_chargers(di, false);
33601c1f13a0SLinus Walleij 
33611c1f13a0SLinus Walleij 	if (ch_stat & AC_PW_CONN) {
33621c1f13a0SLinus Walleij 		if (is_ab8500(di->parent))
33631c1f13a0SLinus Walleij 			queue_delayed_work(di->charger_wq,
33641c1f13a0SLinus Walleij 					   &di->ac_charger_attached_work,
33651c1f13a0SLinus Walleij 					   HZ);
33661c1f13a0SLinus Walleij 	}
33671c1f13a0SLinus Walleij 	if (ch_stat & USB_PW_CONN) {
33681c1f13a0SLinus Walleij 		if (is_ab8500(di->parent))
33691c1f13a0SLinus Walleij 			queue_delayed_work(di->charger_wq,
33701c1f13a0SLinus Walleij 					   &di->usb_charger_attached_work,
33711c1f13a0SLinus Walleij 					   HZ);
33721c1f13a0SLinus Walleij 		di->vbus_detected = true;
33731c1f13a0SLinus Walleij 		di->vbus_detected_start = true;
33741c1f13a0SLinus Walleij 		queue_work(di->charger_wq,
33751c1f13a0SLinus Walleij 			   &di->detect_usb_type_work);
33761c1f13a0SLinus Walleij 	}
33771c1f13a0SLinus Walleij 
33781c1f13a0SLinus Walleij 	ret = component_bind_all(dev, di);
33791c1f13a0SLinus Walleij 	if (ret) {
33801c1f13a0SLinus Walleij 		dev_err(dev, "can't bind component devices\n");
33811c1f13a0SLinus Walleij 		return ret;
33821c1f13a0SLinus Walleij 	}
33831c1f13a0SLinus Walleij 
33841c1f13a0SLinus Walleij 	return 0;
33851c1f13a0SLinus Walleij }
33861c1f13a0SLinus Walleij 
33871c1f13a0SLinus Walleij static void ab8500_charger_unbind(struct device *dev)
33881c1f13a0SLinus Walleij {
33891c1f13a0SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
33901c1f13a0SLinus Walleij 	int ret;
33911c1f13a0SLinus Walleij 
33921c1f13a0SLinus Walleij 	/* Disable AC charging */
33931c1f13a0SLinus Walleij 	ab8500_charger_ac_en(&di->ac_chg, false, 0, 0);
33941c1f13a0SLinus Walleij 
33951c1f13a0SLinus Walleij 	/* Disable USB charging */
33961c1f13a0SLinus Walleij 	ab8500_charger_usb_en(&di->usb_chg, false, 0, 0);
33971c1f13a0SLinus Walleij 
33981c1f13a0SLinus Walleij 	/* Backup battery voltage and current disable */
33991c1f13a0SLinus Walleij 	ret = abx500_mask_and_set_register_interruptible(di->dev,
34001c1f13a0SLinus Walleij 		AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0);
34011c1f13a0SLinus Walleij 	if (ret < 0)
34021c1f13a0SLinus Walleij 		dev_err(di->dev, "%s mask and set failed\n", __func__);
34031c1f13a0SLinus Walleij 
34041c1f13a0SLinus Walleij 	/* Delete the work queue */
34051c1f13a0SLinus Walleij 	destroy_workqueue(di->charger_wq);
34061c1f13a0SLinus Walleij 
34071c1f13a0SLinus Walleij 	flush_scheduled_work();
34081c1f13a0SLinus Walleij 
34091c1f13a0SLinus Walleij 	/* Unbind fg, btemp, algorithm */
34101c1f13a0SLinus Walleij 	component_unbind_all(dev, di);
34111c1f13a0SLinus Walleij }
34121c1f13a0SLinus Walleij 
34131c1f13a0SLinus Walleij static const struct component_master_ops ab8500_charger_comp_ops = {
34141c1f13a0SLinus Walleij 	.bind = ab8500_charger_bind,
34151c1f13a0SLinus Walleij 	.unbind = ab8500_charger_unbind,
34161c1f13a0SLinus Walleij };
34171c1f13a0SLinus Walleij 
34181c1f13a0SLinus Walleij static struct platform_driver *const ab8500_charger_component_drivers[] = {
34191c1f13a0SLinus Walleij 	&ab8500_fg_driver,
34201c1f13a0SLinus Walleij 	&ab8500_btemp_driver,
3421c5b64a99SLinus Walleij 	&ab8500_chargalg_driver,
34221c1f13a0SLinus Walleij };
34231c1f13a0SLinus Walleij 
34241c1f13a0SLinus Walleij static int ab8500_charger_compare_dev(struct device *dev, void *data)
34251c1f13a0SLinus Walleij {
34261c1f13a0SLinus Walleij 	return dev == data;
34271c1f13a0SLinus Walleij }
34281c1f13a0SLinus Walleij 
34298c0984e5SSebastian Reichel static int ab8500_charger_probe(struct platform_device *pdev)
34308c0984e5SSebastian Reichel {
34311c1f13a0SLinus Walleij 	struct device *dev = &pdev->dev;
34321c1f13a0SLinus Walleij 	struct device_node *np = dev->of_node;
34331c1f13a0SLinus Walleij 	struct component_match *match = NULL;
34348c0984e5SSebastian Reichel 	struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {};
34358c0984e5SSebastian Reichel 	struct ab8500_charger *di;
34361c1f13a0SLinus Walleij 	int charger_status;
34371c1f13a0SLinus Walleij 	int i, irq;
34381c1f13a0SLinus Walleij 	int ret;
34398c0984e5SSebastian Reichel 
3440ad89cb5fSLinus Walleij 	di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
3441ad89cb5fSLinus Walleij 	if (!di)
34428c0984e5SSebastian Reichel 		return -ENOMEM;
34438c0984e5SSebastian Reichel 
3444417c0fc2SLinus Walleij 	di->bm = &ab8500_bm_data;
34458c0984e5SSebastian Reichel 
34468c0984e5SSebastian Reichel 	di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
34478c0984e5SSebastian Reichel 
34488c0984e5SSebastian Reichel 	/* get parent data */
3449ad89cb5fSLinus Walleij 	di->dev = dev;
34508c0984e5SSebastian Reichel 	di->parent = dev_get_drvdata(pdev->dev.parent);
345197ab78baSLinus Walleij 
345297ab78baSLinus Walleij 	/* Get ADC channels */
34530f6dad11SLinus Walleij 	if (!is_ab8505(di->parent)) {
345436f1de0dSLinus Walleij 		di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v");
345597ab78baSLinus Walleij 		if (IS_ERR(di->adc_main_charger_v)) {
345636f1de0dSLinus Walleij 			ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_v),
345736f1de0dSLinus Walleij 					    "failed to get ADC main charger voltage\n");
345836f1de0dSLinus Walleij 			return ret;
345997ab78baSLinus Walleij 		}
346036f1de0dSLinus Walleij 		di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c");
346197ab78baSLinus Walleij 		if (IS_ERR(di->adc_main_charger_c)) {
346236f1de0dSLinus Walleij 			ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_c),
346336f1de0dSLinus Walleij 					    "failed to get ADC main charger current\n");
346436f1de0dSLinus Walleij 			return ret;
346597ab78baSLinus Walleij 		}
34660f6dad11SLinus Walleij 	}
3467ad89cb5fSLinus Walleij 	di->adc_vbus_v = devm_iio_channel_get(dev, "vbus_v");
346897ab78baSLinus Walleij 	if (IS_ERR(di->adc_vbus_v)) {
346936f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_vbus_v),
347036f1de0dSLinus Walleij 				    "failed to get ADC USB charger voltage\n");
347136f1de0dSLinus Walleij 		return ret;
347297ab78baSLinus Walleij 	}
347336f1de0dSLinus Walleij 	di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c");
347497ab78baSLinus Walleij 	if (IS_ERR(di->adc_usb_charger_c)) {
347536f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_usb_charger_c),
347636f1de0dSLinus Walleij 				    "failed to get ADC USB charger current\n");
347736f1de0dSLinus Walleij 		return ret;
347897ab78baSLinus Walleij 	}
34798c0984e5SSebastian Reichel 
34801c1f13a0SLinus Walleij 	/*
34811c1f13a0SLinus Walleij 	 * VDD ADC supply needs to be enabled from this driver when there
34821c1f13a0SLinus Walleij 	 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
34831c1f13a0SLinus Walleij 	 * interrupts during charging
34841c1f13a0SLinus Walleij 	 */
34851c1f13a0SLinus Walleij 	di->regu = devm_regulator_get(dev, "vddadc");
34861c1f13a0SLinus Walleij 	if (IS_ERR(di->regu)) {
34871c1f13a0SLinus Walleij 		ret = PTR_ERR(di->regu);
34881c1f13a0SLinus Walleij 		dev_err(dev, "failed to get vddadc regulator\n");
34891c1f13a0SLinus Walleij 		return ret;
34901c1f13a0SLinus Walleij 	}
34911c1f13a0SLinus Walleij 
34921c1f13a0SLinus Walleij 	/* Request interrupts */
34931c1f13a0SLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
34941c1f13a0SLinus Walleij 		irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
34951c1f13a0SLinus Walleij 		if (irq < 0)
34961c1f13a0SLinus Walleij 			return irq;
34971c1f13a0SLinus Walleij 
34981c1f13a0SLinus Walleij 		ret = devm_request_threaded_irq(dev,
34991c1f13a0SLinus Walleij 			irq, NULL, ab8500_charger_irq[i].isr,
35001c1f13a0SLinus Walleij 			IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
35011c1f13a0SLinus Walleij 			ab8500_charger_irq[i].name, di);
35021c1f13a0SLinus Walleij 
35031c1f13a0SLinus Walleij 		if (ret != 0) {
35041c1f13a0SLinus Walleij 			dev_err(dev, "failed to request %s IRQ %d: %d\n"
35051c1f13a0SLinus Walleij 				, ab8500_charger_irq[i].name, irq, ret);
35061c1f13a0SLinus Walleij 			return ret;
35071c1f13a0SLinus Walleij 		}
35081c1f13a0SLinus Walleij 		dev_dbg(dev, "Requested %s IRQ %d: %d\n",
35091c1f13a0SLinus Walleij 			ab8500_charger_irq[i].name, irq, ret);
35101c1f13a0SLinus Walleij 	}
35111c1f13a0SLinus Walleij 
35128c0984e5SSebastian Reichel 	/* initialize lock */
35138c0984e5SSebastian Reichel 	spin_lock_init(&di->usb_state.usb_lock);
35148c0984e5SSebastian Reichel 	mutex_init(&di->usb_ipt_crnt_lock);
35158c0984e5SSebastian Reichel 
35168c0984e5SSebastian Reichel 	di->autopower = false;
35178c0984e5SSebastian Reichel 	di->invalid_charger_detect_state = 0;
35188c0984e5SSebastian Reichel 
35198c0984e5SSebastian Reichel 	/* AC and USB supply config */
352059f1b854SLinus Walleij 	ac_psy_cfg.of_node = np;
35218c0984e5SSebastian Reichel 	ac_psy_cfg.supplied_to = supply_interface;
35228c0984e5SSebastian Reichel 	ac_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
35238c0984e5SSebastian Reichel 	ac_psy_cfg.drv_data = &di->ac_chg;
352459f1b854SLinus Walleij 	usb_psy_cfg.of_node = np;
35258c0984e5SSebastian Reichel 	usb_psy_cfg.supplied_to = supply_interface;
35268c0984e5SSebastian Reichel 	usb_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
35278c0984e5SSebastian Reichel 	usb_psy_cfg.drv_data = &di->usb_chg;
35288c0984e5SSebastian Reichel 
35298c0984e5SSebastian Reichel 	/* AC supply */
35308c0984e5SSebastian Reichel 	/* ux500_charger sub-class */
35318c0984e5SSebastian Reichel 	di->ac_chg.ops.enable = &ab8500_charger_ac_en;
35328c0984e5SSebastian Reichel 	di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable;
35338c0984e5SSebastian Reichel 	di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
35348c0984e5SSebastian Reichel 	di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current;
3535bc6e0287SLinus Walleij 	di->ac_chg.max_out_volt_uv = ab8500_charger_voltage_map[
35368c0984e5SSebastian Reichel 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
353783e5aa77SLinus Walleij 	di->ac_chg.max_out_curr_ua =
35383aca6ecdSLinus Walleij 		ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
35398c0984e5SSebastian Reichel 	di->ac_chg.wdt_refresh = CHG_WD_INTERVAL;
3540f9184a22SLinus Walleij 	/*
3541f9184a22SLinus Walleij 	 * The AB8505 only supports USB charging. If we are not the
3542f9184a22SLinus Walleij 	 * AB8505, register an AC charger.
3543f9184a22SLinus Walleij 	 *
3544f9184a22SLinus Walleij 	 * TODO: if this should be opt-in, add DT properties for this.
3545f9184a22SLinus Walleij 	 */
3546f9184a22SLinus Walleij 	if (!is_ab8505(di->parent))
3547f9184a22SLinus Walleij 		di->ac_chg.enabled = true;
35488c0984e5SSebastian Reichel 	di->ac_chg.external = false;
35498c0984e5SSebastian Reichel 
35508c0984e5SSebastian Reichel 	/* USB supply */
35518c0984e5SSebastian Reichel 	/* ux500_charger sub-class */
35528c0984e5SSebastian Reichel 	di->usb_chg.ops.enable = &ab8500_charger_usb_en;
35538c0984e5SSebastian Reichel 	di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
35548c0984e5SSebastian Reichel 	di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
35558c0984e5SSebastian Reichel 	di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current;
3556bc6e0287SLinus Walleij 	di->usb_chg.max_out_volt_uv = ab8500_charger_voltage_map[
35578c0984e5SSebastian Reichel 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
355883e5aa77SLinus Walleij 	di->usb_chg.max_out_curr_ua =
35593aca6ecdSLinus Walleij 		ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
35608c0984e5SSebastian Reichel 	di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
35618c0984e5SSebastian Reichel 	di->usb_chg.external = false;
356283e5aa77SLinus Walleij 	di->usb_state.usb_current_ua = -1;
35638c0984e5SSebastian Reichel 
35648c0984e5SSebastian Reichel 	mutex_init(&di->charger_attached_mutex);
35658c0984e5SSebastian Reichel 
35668c0984e5SSebastian Reichel 	/* Init work for HW failure check */
35678c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_hw_failure_work,
35688c0984e5SSebastian Reichel 		ab8500_charger_check_hw_failure_work);
35698c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work,
35708c0984e5SSebastian Reichel 		ab8500_charger_check_usbchargernotok_work);
35718c0984e5SSebastian Reichel 
35728c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->ac_charger_attached_work,
35738c0984e5SSebastian Reichel 			  ab8500_charger_ac_attached_work);
35748c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->usb_charger_attached_work,
35758c0984e5SSebastian Reichel 			  ab8500_charger_usb_attached_work);
35768c0984e5SSebastian Reichel 
35778c0984e5SSebastian Reichel 	/*
35788c0984e5SSebastian Reichel 	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
3579ddb74e98SAshish Chavan 	 * logic. That means we have to continuously kick the charger
35808c0984e5SSebastian Reichel 	 * watchdog even when no charger is connected. This is only
35818c0984e5SSebastian Reichel 	 * valid once the AC charger has been enabled. This is
35828c0984e5SSebastian Reichel 	 * a bug that is not handled by the algorithm and the
35838c0984e5SSebastian Reichel 	 * watchdog have to be kicked by the charger driver
35848c0984e5SSebastian Reichel 	 * when the AC charger is disabled
35858c0984e5SSebastian Reichel 	 */
35868c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->kick_wd_work,
35878c0984e5SSebastian Reichel 		ab8500_charger_kick_watchdog_work);
35888c0984e5SSebastian Reichel 
35898c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_vbat_work,
35908c0984e5SSebastian Reichel 		ab8500_charger_check_vbat_work);
35918c0984e5SSebastian Reichel 
35928c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->attach_work,
35938c0984e5SSebastian Reichel 		ab8500_charger_usb_link_attach_work);
35948c0984e5SSebastian Reichel 
35958c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->usb_state_changed_work,
35968c0984e5SSebastian Reichel 		ab8500_charger_usb_state_changed_work);
35978c0984e5SSebastian Reichel 
35988c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->vbus_drop_end_work,
35998c0984e5SSebastian Reichel 		ab8500_charger_vbus_drop_end_work);
36008c0984e5SSebastian Reichel 
36018c0984e5SSebastian Reichel 	/* Init work for charger detection */
36028c0984e5SSebastian Reichel 	INIT_WORK(&di->usb_link_status_work,
36038c0984e5SSebastian Reichel 		ab8500_charger_usb_link_status_work);
36048c0984e5SSebastian Reichel 	INIT_WORK(&di->ac_work, ab8500_charger_ac_work);
36058c0984e5SSebastian Reichel 	INIT_WORK(&di->detect_usb_type_work,
36068c0984e5SSebastian Reichel 		ab8500_charger_detect_usb_type_work);
36078c0984e5SSebastian Reichel 
36088c0984e5SSebastian Reichel 	/* Init work for checking HW status */
36098c0984e5SSebastian Reichel 	INIT_WORK(&di->check_main_thermal_prot_work,
36108c0984e5SSebastian Reichel 		ab8500_charger_check_main_thermal_prot_work);
36118c0984e5SSebastian Reichel 	INIT_WORK(&di->check_usb_thermal_prot_work,
36128c0984e5SSebastian Reichel 		ab8500_charger_check_usb_thermal_prot_work);
36138c0984e5SSebastian Reichel 
36148c0984e5SSebastian Reichel 
36158c0984e5SSebastian Reichel 	/* Initialize OVV, and other registers */
36168c0984e5SSebastian Reichel 	ret = ab8500_charger_init_hw_registers(di);
36178c0984e5SSebastian Reichel 	if (ret) {
3618ad89cb5fSLinus Walleij 		dev_err(dev, "failed to initialize ABB registers\n");
36191c1f13a0SLinus Walleij 		return ret;
36208c0984e5SSebastian Reichel 	}
36218c0984e5SSebastian Reichel 
36228c0984e5SSebastian Reichel 	/* Register AC charger class */
36238c0984e5SSebastian Reichel 	if (di->ac_chg.enabled) {
36241c1f13a0SLinus Walleij 		di->ac_chg.psy = devm_power_supply_register(dev,
36258c0984e5SSebastian Reichel 						       &ab8500_ac_chg_desc,
36268c0984e5SSebastian Reichel 						       &ac_psy_cfg);
36278c0984e5SSebastian Reichel 		if (IS_ERR(di->ac_chg.psy)) {
3628ad89cb5fSLinus Walleij 			dev_err(dev, "failed to register AC charger\n");
36291c1f13a0SLinus Walleij 			return PTR_ERR(di->ac_chg.psy);
36308c0984e5SSebastian Reichel 		}
36318c0984e5SSebastian Reichel 	}
36328c0984e5SSebastian Reichel 
36338c0984e5SSebastian Reichel 	/* Register USB charger class */
36341c1f13a0SLinus Walleij 	di->usb_chg.psy = devm_power_supply_register(dev,
36358c0984e5SSebastian Reichel 						     &ab8500_usb_chg_desc,
36368c0984e5SSebastian Reichel 						     &usb_psy_cfg);
36378c0984e5SSebastian Reichel 	if (IS_ERR(di->usb_chg.psy)) {
3638ad89cb5fSLinus Walleij 		dev_err(dev, "failed to register USB charger\n");
36391c1f13a0SLinus Walleij 		return PTR_ERR(di->usb_chg.psy);
36408c0984e5SSebastian Reichel 	}
36418c0984e5SSebastian Reichel 
364259f1b854SLinus Walleij 	/*
364359f1b854SLinus Walleij 	 * Check what battery we have, since we always have the USB
364459f1b854SLinus Walleij 	 * psy, use that as a handle.
364559f1b854SLinus Walleij 	 */
364659f1b854SLinus Walleij 	ret = ab8500_bm_of_probe(di->usb_chg.psy, di->bm);
364759f1b854SLinus Walleij 	if (ret)
364859f1b854SLinus Walleij 		return dev_err_probe(dev, ret,
364959f1b854SLinus Walleij 				     "failed to get battery information\n");
365059f1b854SLinus Walleij 
36518c0984e5SSebastian Reichel 	/* Identify the connected charger types during startup */
36528c0984e5SSebastian Reichel 	charger_status = ab8500_charger_detect_chargers(di, true);
36538c0984e5SSebastian Reichel 	if (charger_status & AC_PW_CONN) {
36548c0984e5SSebastian Reichel 		di->ac.charger_connected = 1;
36558c0984e5SSebastian Reichel 		di->ac_conn = true;
36568c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->ac_chg.psy);
36578c0984e5SSebastian Reichel 		sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
36588c0984e5SSebastian Reichel 	}
36598c0984e5SSebastian Reichel 
36608c0984e5SSebastian Reichel 	platform_set_drvdata(pdev, di);
36618c0984e5SSebastian Reichel 
36621c1f13a0SLinus Walleij 	/* Create something that will match the subdrivers when we bind */
36631c1f13a0SLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) {
36641c1f13a0SLinus Walleij 		struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver;
36651c1f13a0SLinus Walleij 		struct device *p = NULL, *d;
36668c0984e5SSebastian Reichel 
36671c1f13a0SLinus Walleij 		while ((d = platform_find_device_by_driver(p, drv))) {
36681c1f13a0SLinus Walleij 			put_device(p);
36691c1f13a0SLinus Walleij 			component_match_add(dev, &match,
36701c1f13a0SLinus Walleij 					    ab8500_charger_compare_dev, d);
36711c1f13a0SLinus Walleij 			p = d;
36728c0984e5SSebastian Reichel 		}
36731c1f13a0SLinus Walleij 		put_device(p);
36741c1f13a0SLinus Walleij 	}
36751c1f13a0SLinus Walleij 	if (!match) {
36761c1f13a0SLinus Walleij 		dev_err(dev, "no matching components\n");
3677be2c0d54SChristophe JAILLET 		ret = -ENODEV;
3678be2c0d54SChristophe JAILLET 		goto remove_ab8500_bm;
36791c1f13a0SLinus Walleij 	}
36801c1f13a0SLinus Walleij 	if (IS_ERR(match)) {
36811c1f13a0SLinus Walleij 		dev_err(dev, "could not create component match\n");
3682be2c0d54SChristophe JAILLET 		ret = PTR_ERR(match);
3683be2c0d54SChristophe JAILLET 		goto remove_ab8500_bm;
36848c0984e5SSebastian Reichel 	}
36858c0984e5SSebastian Reichel 
36861c1f13a0SLinus Walleij 	/* Notifier for external charger enabling */
36871c1f13a0SLinus Walleij 	if (!di->ac_chg.enabled)
36881c1f13a0SLinus Walleij 		blocking_notifier_chain_register(
36891c1f13a0SLinus Walleij 			&charger_notifier_list, &charger_nb);
36908c0984e5SSebastian Reichel 
36918c0984e5SSebastian Reichel 
36921c1f13a0SLinus Walleij 	di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
36931c1f13a0SLinus Walleij 	if (IS_ERR_OR_NULL(di->usb_phy)) {
36941c1f13a0SLinus Walleij 		dev_err(dev, "failed to get usb transceiver\n");
36951c1f13a0SLinus Walleij 		ret = -EINVAL;
36961c1f13a0SLinus Walleij 		goto out_charger_notifier;
36971c1f13a0SLinus Walleij 	}
36981c1f13a0SLinus Walleij 	di->nb.notifier_call = ab8500_charger_usb_notifier_call;
36991c1f13a0SLinus Walleij 	ret = usb_register_notifier(di->usb_phy, &di->nb);
37001c1f13a0SLinus Walleij 	if (ret) {
37011c1f13a0SLinus Walleij 		dev_err(dev, "failed to register usb notifier\n");
37021c1f13a0SLinus Walleij 		goto put_usb_phy;
37031c1f13a0SLinus Walleij 	}
37041c1f13a0SLinus Walleij 
37051c1f13a0SLinus Walleij 
37061c1f13a0SLinus Walleij 	ret = component_master_add_with_match(&pdev->dev,
37071c1f13a0SLinus Walleij 					      &ab8500_charger_comp_ops,
37081c1f13a0SLinus Walleij 					      match);
37091c1f13a0SLinus Walleij 	if (ret) {
37101c1f13a0SLinus Walleij 		dev_err(dev, "failed to add component master\n");
37111c1f13a0SLinus Walleij 		goto free_notifier;
37121c1f13a0SLinus Walleij 	}
37131c1f13a0SLinus Walleij 
37141c1f13a0SLinus Walleij 	return 0;
37151c1f13a0SLinus Walleij 
37161c1f13a0SLinus Walleij free_notifier:
37178c0984e5SSebastian Reichel 	usb_unregister_notifier(di->usb_phy, &di->nb);
37188c0984e5SSebastian Reichel put_usb_phy:
37198c0984e5SSebastian Reichel 	usb_put_phy(di->usb_phy);
37201c1f13a0SLinus Walleij out_charger_notifier:
37211c1f13a0SLinus Walleij 	if (!di->ac_chg.enabled)
37221c1f13a0SLinus Walleij 		blocking_notifier_chain_unregister(
37231c1f13a0SLinus Walleij 			&charger_notifier_list, &charger_nb);
3724be2c0d54SChristophe JAILLET remove_ab8500_bm:
3725be2c0d54SChristophe JAILLET 	ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
37268c0984e5SSebastian Reichel 	return ret;
37278c0984e5SSebastian Reichel }
37288c0984e5SSebastian Reichel 
37291c1f13a0SLinus Walleij static int ab8500_charger_remove(struct platform_device *pdev)
37301c1f13a0SLinus Walleij {
37311c1f13a0SLinus Walleij 	struct ab8500_charger *di = platform_get_drvdata(pdev);
37321c1f13a0SLinus Walleij 
37331c1f13a0SLinus Walleij 	component_master_del(&pdev->dev, &ab8500_charger_comp_ops);
37341c1f13a0SLinus Walleij 
37351c1f13a0SLinus Walleij 	usb_unregister_notifier(di->usb_phy, &di->nb);
37366252c706SLinus Walleij 	ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
37371c1f13a0SLinus Walleij 	usb_put_phy(di->usb_phy);
37381c1f13a0SLinus Walleij 	if (!di->ac_chg.enabled)
37391c1f13a0SLinus Walleij 		blocking_notifier_chain_unregister(
37401c1f13a0SLinus Walleij 			&charger_notifier_list, &charger_nb);
37411c1f13a0SLinus Walleij 
37421c1f13a0SLinus Walleij 	return 0;
37431c1f13a0SLinus Walleij }
37441c1f13a0SLinus Walleij 
3745f8efa0a8SLinus Walleij static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume);
3746f8efa0a8SLinus Walleij 
37478c0984e5SSebastian Reichel static const struct of_device_id ab8500_charger_match[] = {
37488c0984e5SSebastian Reichel 	{ .compatible = "stericsson,ab8500-charger", },
37498c0984e5SSebastian Reichel 	{ },
37508c0984e5SSebastian Reichel };
3751dfe52db1SZou Wei MODULE_DEVICE_TABLE(of, ab8500_charger_match);
37528c0984e5SSebastian Reichel 
37538c0984e5SSebastian Reichel static struct platform_driver ab8500_charger_driver = {
37548c0984e5SSebastian Reichel 	.probe = ab8500_charger_probe,
37558c0984e5SSebastian Reichel 	.remove = ab8500_charger_remove,
37568c0984e5SSebastian Reichel 	.driver = {
37578c0984e5SSebastian Reichel 		.name = "ab8500-charger",
37588c0984e5SSebastian Reichel 		.of_match_table = ab8500_charger_match,
3759f8efa0a8SLinus Walleij 		.pm = &ab8500_charger_pm_ops,
37608c0984e5SSebastian Reichel 	},
37618c0984e5SSebastian Reichel };
37628c0984e5SSebastian Reichel 
37638c0984e5SSebastian Reichel static int __init ab8500_charger_init(void)
37648c0984e5SSebastian Reichel {
37651c1f13a0SLinus Walleij 	int ret;
37661c1f13a0SLinus Walleij 
37671c1f13a0SLinus Walleij 	ret = platform_register_drivers(ab8500_charger_component_drivers,
37681c1f13a0SLinus Walleij 			ARRAY_SIZE(ab8500_charger_component_drivers));
37691c1f13a0SLinus Walleij 	if (ret)
37701c1f13a0SLinus Walleij 		return ret;
37711c1f13a0SLinus Walleij 
37728c0984e5SSebastian Reichel 	return platform_driver_register(&ab8500_charger_driver);
37738c0984e5SSebastian Reichel }
37748c0984e5SSebastian Reichel 
37758c0984e5SSebastian Reichel static void __exit ab8500_charger_exit(void)
37768c0984e5SSebastian Reichel {
37771c1f13a0SLinus Walleij 	platform_unregister_drivers(ab8500_charger_component_drivers,
37781c1f13a0SLinus Walleij 			ARRAY_SIZE(ab8500_charger_component_drivers));
37798c0984e5SSebastian Reichel 	platform_driver_unregister(&ab8500_charger_driver);
37808c0984e5SSebastian Reichel }
37818c0984e5SSebastian Reichel 
37821c1f13a0SLinus Walleij module_init(ab8500_charger_init);
37838c0984e5SSebastian Reichel module_exit(ab8500_charger_exit);
37848c0984e5SSebastian Reichel 
37858c0984e5SSebastian Reichel MODULE_LICENSE("GPL v2");
37868c0984e5SSebastian Reichel MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
37878c0984e5SSebastian Reichel MODULE_ALIAS("platform:ab8500-charger");
37888c0984e5SSebastian Reichel MODULE_DESCRIPTION("AB8500 charger management driver");
3789