xref: /openbmc/linux/drivers/power/supply/ab8500_charger.c (revision 83e5aa77d1120fd38101f757c4aeb985e9305700)
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 
148*83e5aa77SLinus Walleij /* VBUS input current limits supported in AB8500 in uA */
149*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P05		50000
150*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P09		98000
151*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P19		193000
152*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P29		290000
153*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P38		380000
154*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P45		450000
155*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P5		500000
156*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P6		600000
157*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P7		700000
158*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P8		800000
159*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_0P9		900000
160*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P0		1000000
161*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P1		1100000
162*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P3		1300000
163*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P4		1400000
164*83e5aa77SLinus Walleij #define USB_CH_IP_CUR_LVL_1P5		1500000
1658c0984e5SSebastian Reichel 
1668c0984e5SSebastian Reichel #define VBAT_TRESH_IP_CUR_RED		3800
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 /**
1748c0984e5SSebastian Reichel  * struct ab8500_charger_interrupts - ab8500 interupts
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;
1868c0984e5SSebastian Reichel 	int charger_voltage;
1878c0984e5SSebastian Reichel 	int cv_active;
1888c0984e5SSebastian Reichel 	bool wd_expired;
189*83e5aa77SLinus 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 {
204*83e5aa77SLinus Walleij 	int usb_current_ua;
205*83e5aa77SLinus 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 {
212*83e5aa77SLinus Walleij 	int usb_type_max_ua;
213*83e5aa77SLinus Walleij 	int set_max_ua;
214*83e5aa77SLinus 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  *
4828c0984e5SSebastian Reichel  * Returns ac charger voltage (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 	}
4968c0984e5SSebastian Reichel 	return vch;
4978c0984e5SSebastian Reichel }
4988c0984e5SSebastian Reichel 
4998c0984e5SSebastian Reichel /**
5008c0984e5SSebastian Reichel  * ab8500_charger_ac_cv() - check if the main charger is in CV mode
5018c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5028c0984e5SSebastian Reichel  *
5038c0984e5SSebastian Reichel  * Returns ac charger CV mode (on success) else error code
5048c0984e5SSebastian Reichel  */
5058c0984e5SSebastian Reichel static int ab8500_charger_ac_cv(struct ab8500_charger *di)
5068c0984e5SSebastian Reichel {
5078c0984e5SSebastian Reichel 	u8 val;
5088c0984e5SSebastian Reichel 	int ret = 0;
5098c0984e5SSebastian Reichel 
5108c0984e5SSebastian Reichel 	/* Only check CV mode if the charger is online */
5118c0984e5SSebastian Reichel 	if (di->ac.charger_online) {
5128c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
5138c0984e5SSebastian Reichel 			AB8500_CH_STATUS1_REG, &val);
5148c0984e5SSebastian Reichel 		if (ret < 0) {
5158c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
5168c0984e5SSebastian Reichel 			return 0;
5178c0984e5SSebastian Reichel 		}
5188c0984e5SSebastian Reichel 
5198c0984e5SSebastian Reichel 		if (val & MAIN_CH_CV_ON)
5208c0984e5SSebastian Reichel 			ret = 1;
5218c0984e5SSebastian Reichel 		else
5228c0984e5SSebastian Reichel 			ret = 0;
5238c0984e5SSebastian Reichel 	}
5248c0984e5SSebastian Reichel 
5258c0984e5SSebastian Reichel 	return ret;
5268c0984e5SSebastian Reichel }
5278c0984e5SSebastian Reichel 
5288c0984e5SSebastian Reichel /**
5298c0984e5SSebastian Reichel  * ab8500_charger_get_vbus_voltage() - get vbus voltage
5308c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5318c0984e5SSebastian Reichel  *
5328c0984e5SSebastian Reichel  * This function returns the vbus voltage.
5338c0984e5SSebastian Reichel  * Returns vbus voltage (on success)
5348c0984e5SSebastian Reichel  */
5358c0984e5SSebastian Reichel static int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di)
5368c0984e5SSebastian Reichel {
53797ab78baSLinus Walleij 	int vch, ret;
5388c0984e5SSebastian Reichel 
5398c0984e5SSebastian Reichel 	/* Only measure voltage if the charger is connected */
5408c0984e5SSebastian Reichel 	if (di->usb.charger_connected) {
54197ab78baSLinus Walleij 		ret = iio_read_channel_processed(di->adc_vbus_v, &vch);
54297ab78baSLinus Walleij 		if (ret < 0)
54397ab78baSLinus Walleij 			dev_err(di->dev, "%s ADC conv failed,\n", __func__);
5448c0984e5SSebastian Reichel 	} else {
5458c0984e5SSebastian Reichel 		vch = 0;
5468c0984e5SSebastian Reichel 	}
5478c0984e5SSebastian Reichel 	return vch;
5488c0984e5SSebastian Reichel }
5498c0984e5SSebastian Reichel 
5508c0984e5SSebastian Reichel /**
5518c0984e5SSebastian Reichel  * ab8500_charger_get_usb_current() - get usb charger current
5528c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5538c0984e5SSebastian Reichel  *
5548c0984e5SSebastian Reichel  * This function returns the usb charger current.
555*83e5aa77SLinus Walleij  * Returns usb current in microamperes (on success) and error code on failure
5568c0984e5SSebastian Reichel  */
5578c0984e5SSebastian Reichel static int ab8500_charger_get_usb_current(struct ab8500_charger *di)
5588c0984e5SSebastian Reichel {
55997ab78baSLinus Walleij 	int ich, ret;
5608c0984e5SSebastian Reichel 
5618c0984e5SSebastian Reichel 	/* Only measure current if the charger is online */
5628c0984e5SSebastian Reichel 	if (di->usb.charger_online) {
56397ab78baSLinus Walleij 		ret = iio_read_channel_processed(di->adc_usb_charger_c, &ich);
56497ab78baSLinus Walleij 		if (ret < 0)
56597ab78baSLinus Walleij 			dev_err(di->dev, "%s ADC conv failed,\n", __func__);
5668c0984e5SSebastian Reichel 	} else {
5678c0984e5SSebastian Reichel 		ich = 0;
5688c0984e5SSebastian Reichel 	}
569*83e5aa77SLinus Walleij 	/* Return microamperes */
570*83e5aa77SLinus Walleij 	return ich * 1000;
5718c0984e5SSebastian Reichel }
5728c0984e5SSebastian Reichel 
5738c0984e5SSebastian Reichel /**
5748c0984e5SSebastian Reichel  * ab8500_charger_get_ac_current() - get ac charger current
5758c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5768c0984e5SSebastian Reichel  *
5778c0984e5SSebastian Reichel  * This function returns the ac charger current.
578*83e5aa77SLinus Walleij  * Returns ac current in microamperes (on success) and error code on failure.
5798c0984e5SSebastian Reichel  */
5808c0984e5SSebastian Reichel static int ab8500_charger_get_ac_current(struct ab8500_charger *di)
5818c0984e5SSebastian Reichel {
58297ab78baSLinus Walleij 	int ich, ret;
5838c0984e5SSebastian Reichel 
5848c0984e5SSebastian Reichel 	/* Only measure current if the charger is online */
5858c0984e5SSebastian Reichel 	if (di->ac.charger_online) {
58697ab78baSLinus Walleij 		ret = iio_read_channel_processed(di->adc_main_charger_c, &ich);
58797ab78baSLinus Walleij 		if (ret < 0)
58897ab78baSLinus Walleij 			dev_err(di->dev, "%s ADC conv failed,\n", __func__);
5898c0984e5SSebastian Reichel 	} else {
5908c0984e5SSebastian Reichel 		ich = 0;
5918c0984e5SSebastian Reichel 	}
592*83e5aa77SLinus Walleij 	/* Return microamperes */
593*83e5aa77SLinus Walleij 	return ich * 1000;
5948c0984e5SSebastian Reichel }
5958c0984e5SSebastian Reichel 
5968c0984e5SSebastian Reichel /**
5978c0984e5SSebastian Reichel  * ab8500_charger_usb_cv() - check if the usb charger is in CV mode
5988c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
5998c0984e5SSebastian Reichel  *
6008c0984e5SSebastian Reichel  * Returns ac charger CV mode (on success) else error code
6018c0984e5SSebastian Reichel  */
6028c0984e5SSebastian Reichel static int ab8500_charger_usb_cv(struct ab8500_charger *di)
6038c0984e5SSebastian Reichel {
6048c0984e5SSebastian Reichel 	int ret;
6058c0984e5SSebastian Reichel 	u8 val;
6068c0984e5SSebastian Reichel 
6078c0984e5SSebastian Reichel 	/* Only check CV mode if the charger is online */
6088c0984e5SSebastian Reichel 	if (di->usb.charger_online) {
6098c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
6108c0984e5SSebastian Reichel 			AB8500_CH_USBCH_STAT1_REG, &val);
6118c0984e5SSebastian Reichel 		if (ret < 0) {
6128c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
6138c0984e5SSebastian Reichel 			return 0;
6148c0984e5SSebastian Reichel 		}
6158c0984e5SSebastian Reichel 
6168c0984e5SSebastian Reichel 		if (val & USB_CH_CV_ON)
6178c0984e5SSebastian Reichel 			ret = 1;
6188c0984e5SSebastian Reichel 		else
6198c0984e5SSebastian Reichel 			ret = 0;
6208c0984e5SSebastian Reichel 	} else {
6218c0984e5SSebastian Reichel 		ret = 0;
6228c0984e5SSebastian Reichel 	}
6238c0984e5SSebastian Reichel 
6248c0984e5SSebastian Reichel 	return ret;
6258c0984e5SSebastian Reichel }
6268c0984e5SSebastian Reichel 
6278c0984e5SSebastian Reichel /**
6288c0984e5SSebastian Reichel  * ab8500_charger_detect_chargers() - Detect the connected chargers
6298c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
6308c0984e5SSebastian Reichel  * @probe:	if probe, don't delay and wait for HW
6318c0984e5SSebastian Reichel  *
6328c0984e5SSebastian Reichel  * Returns the type of charger connected.
6338c0984e5SSebastian Reichel  * For USB it will not mean we can actually charge from it
6348c0984e5SSebastian Reichel  * but that there is a USB cable connected that we have to
6358c0984e5SSebastian Reichel  * identify. This is used during startup when we don't get
6368c0984e5SSebastian Reichel  * interrupts of the charger detection
6378c0984e5SSebastian Reichel  *
6388c0984e5SSebastian Reichel  * Returns an integer value, that means,
6398c0984e5SSebastian Reichel  * NO_PW_CONN  no power supply is connected
6408c0984e5SSebastian Reichel  * AC_PW_CONN  if the AC power supply is connected
6418c0984e5SSebastian Reichel  * USB_PW_CONN  if the USB power supply is connected
6428c0984e5SSebastian Reichel  * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected
6438c0984e5SSebastian Reichel  */
6448c0984e5SSebastian Reichel static int ab8500_charger_detect_chargers(struct ab8500_charger *di, bool probe)
6458c0984e5SSebastian Reichel {
6468c0984e5SSebastian Reichel 	int result = NO_PW_CONN;
6478c0984e5SSebastian Reichel 	int ret;
6488c0984e5SSebastian Reichel 	u8 val;
6498c0984e5SSebastian Reichel 
6508c0984e5SSebastian Reichel 	/* Check for AC charger */
6518c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
6528c0984e5SSebastian Reichel 		AB8500_CH_STATUS1_REG, &val);
6538c0984e5SSebastian Reichel 	if (ret < 0) {
6548c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
6558c0984e5SSebastian Reichel 		return ret;
6568c0984e5SSebastian Reichel 	}
6578c0984e5SSebastian Reichel 
6588c0984e5SSebastian Reichel 	if (val & MAIN_CH_DET)
6598c0984e5SSebastian Reichel 		result = AC_PW_CONN;
6608c0984e5SSebastian Reichel 
6618c0984e5SSebastian Reichel 	/* Check for USB charger */
6628c0984e5SSebastian Reichel 
6638c0984e5SSebastian Reichel 	if (!probe) {
6648c0984e5SSebastian Reichel 		/*
6658c0984e5SSebastian Reichel 		 * AB8500 says VBUS_DET_DBNC1 & VBUS_DET_DBNC100
6668c0984e5SSebastian Reichel 		 * when disconnecting ACA even though no
6678c0984e5SSebastian Reichel 		 * charger was connected. Try waiting a little
6688c0984e5SSebastian Reichel 		 * longer than the 100 ms of VBUS_DET_DBNC100...
6698c0984e5SSebastian Reichel 		 */
6708c0984e5SSebastian Reichel 		msleep(110);
6718c0984e5SSebastian Reichel 	}
6728c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
6738c0984e5SSebastian Reichel 		AB8500_CH_USBCH_STAT1_REG, &val);
6748c0984e5SSebastian Reichel 	if (ret < 0) {
6758c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
6768c0984e5SSebastian Reichel 		return ret;
6778c0984e5SSebastian Reichel 	}
6788c0984e5SSebastian Reichel 	dev_dbg(di->dev,
6798c0984e5SSebastian Reichel 		"%s AB8500_CH_USBCH_STAT1_REG %x\n", __func__,
6808c0984e5SSebastian Reichel 		val);
6818c0984e5SSebastian Reichel 	if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100))
6828c0984e5SSebastian Reichel 		result |= USB_PW_CONN;
6838c0984e5SSebastian Reichel 
6848c0984e5SSebastian Reichel 	return result;
6858c0984e5SSebastian Reichel }
6868c0984e5SSebastian Reichel 
6878c0984e5SSebastian Reichel /**
6888c0984e5SSebastian Reichel  * ab8500_charger_max_usb_curr() - get the max curr for the USB type
6898c0984e5SSebastian Reichel  * @di:			pointer to the ab8500_charger structure
6908c0984e5SSebastian Reichel  * @link_status:	the identified USB type
6918c0984e5SSebastian Reichel  *
6928c0984e5SSebastian Reichel  * Get the maximum current that is allowed to be drawn from the host
6938c0984e5SSebastian Reichel  * based on the USB type.
6948c0984e5SSebastian Reichel  * Returns error code in case of failure else 0 on success
6958c0984e5SSebastian Reichel  */
6968c0984e5SSebastian Reichel static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
6978c0984e5SSebastian Reichel 		enum ab8500_charger_link_status link_status)
6988c0984e5SSebastian Reichel {
6998c0984e5SSebastian Reichel 	int ret = 0;
7008c0984e5SSebastian Reichel 
7018c0984e5SSebastian Reichel 	di->usb_device_is_unrecognised = false;
7028c0984e5SSebastian Reichel 
7038c0984e5SSebastian Reichel 	/*
7048c0984e5SSebastian Reichel 	 * Platform only supports USB 2.0.
7058c0984e5SSebastian Reichel 	 * This means that charging current from USB source
706ddb74e98SAshish Chavan 	 * is maximum 500 mA. Every occurrence of USB_STAT_*_HOST_*
7078c0984e5SSebastian Reichel 	 * should set USB_CH_IP_CUR_LVL_0P5.
7088c0984e5SSebastian Reichel 	 */
7098c0984e5SSebastian Reichel 
7108c0984e5SSebastian Reichel 	switch (link_status) {
7118c0984e5SSebastian Reichel 	case USB_STAT_STD_HOST_NC:
7128c0984e5SSebastian Reichel 	case USB_STAT_STD_HOST_C_NS:
7138c0984e5SSebastian Reichel 	case USB_STAT_STD_HOST_C_S:
7148c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB Type - Standard host is "
7158c0984e5SSebastian Reichel 			"detected through USB driver\n");
716*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7178c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7188c0984e5SSebastian Reichel 		break;
7198c0984e5SSebastian Reichel 	case USB_STAT_HOST_CHG_HS_CHIRP:
720*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7218c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7228c0984e5SSebastian Reichel 		break;
7238c0984e5SSebastian Reichel 	case USB_STAT_HOST_CHG_HS:
724*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7258c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7268c0984e5SSebastian Reichel 		break;
7278c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_C_HS:
728*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P9;
7298c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7308c0984e5SSebastian Reichel 		break;
7318c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_A:
7328c0984e5SSebastian Reichel 		/*
7338c0984e5SSebastian Reichel 		 * Dedicated charger level minus maximum current accessory
7348c0984e5SSebastian Reichel 		 * can consume (900mA). Closest level is 500mA
7358c0984e5SSebastian Reichel 		 */
7368c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n");
737*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7388c0984e5SSebastian Reichel 		di->is_aca_rid = 1;
7398c0984e5SSebastian Reichel 		break;
7408c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_B:
7418c0984e5SSebastian Reichel 		/*
7428c0984e5SSebastian Reichel 		 * Dedicated charger level minus 120mA (20mA for ACA and
7438c0984e5SSebastian Reichel 		 * 100mA for potential accessory). Closest level is 1300mA
7448c0984e5SSebastian Reichel 		 */
745*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_1P3;
7468c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
747*83e5aa77SLinus Walleij 				di->max_usb_in_curr.usb_type_max_ua);
7488c0984e5SSebastian Reichel 		di->is_aca_rid = 1;
7498c0984e5SSebastian Reichel 		break;
7508c0984e5SSebastian Reichel 	case USB_STAT_HOST_CHG_NM:
751*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7528c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7538c0984e5SSebastian Reichel 		break;
7548c0984e5SSebastian Reichel 	case USB_STAT_DEDICATED_CHG:
755*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_1P5;
7568c0984e5SSebastian Reichel 		di->is_aca_rid = 0;
7578c0984e5SSebastian Reichel 		break;
7588c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_C_HS_CHIRP:
7598c0984e5SSebastian Reichel 	case USB_STAT_ACA_RID_C_NM:
760*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_1P5;
7618c0984e5SSebastian Reichel 		di->is_aca_rid = 1;
7628c0984e5SSebastian Reichel 		break;
7638c0984e5SSebastian Reichel 	case USB_STAT_NOT_CONFIGURED:
7648c0984e5SSebastian Reichel 		if (di->vbus_detected) {
7658c0984e5SSebastian Reichel 			di->usb_device_is_unrecognised = true;
7668c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB Type - Legacy charger.\n");
767*83e5aa77SLinus Walleij 			di->max_usb_in_curr.usb_type_max_ua =
7688c0984e5SSebastian Reichel 						USB_CH_IP_CUR_LVL_1P5;
7698c0984e5SSebastian Reichel 			break;
7708c0984e5SSebastian Reichel 		}
771df561f66SGustavo A. R. Silva 		fallthrough;
7728c0984e5SSebastian Reichel 	case USB_STAT_HM_IDGND:
7738c0984e5SSebastian Reichel 		dev_err(di->dev, "USB Type - Charging not allowed\n");
774*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P05;
7758c0984e5SSebastian Reichel 		ret = -ENXIO;
7768c0984e5SSebastian Reichel 		break;
7778c0984e5SSebastian Reichel 	case USB_STAT_RESERVED:
7788c0984e5SSebastian Reichel 		if (is_ab8500(di->parent)) {
7798c0984e5SSebastian Reichel 			di->flags.vbus_collapse = true;
7808c0984e5SSebastian Reichel 			dev_err(di->dev, "USB Type - USB_STAT_RESERVED "
7818c0984e5SSebastian Reichel 						"VBUS has collapsed\n");
7828c0984e5SSebastian Reichel 			ret = -ENXIO;
7838c0984e5SSebastian Reichel 			break;
7848c0984e5SSebastian Reichel 		} else {
7858c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB Type - Charging not allowed\n");
786*83e5aa77SLinus Walleij 			di->max_usb_in_curr.usb_type_max_ua =
7878c0984e5SSebastian Reichel 						USB_CH_IP_CUR_LVL_0P05;
7888c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
7898c0984e5SSebastian Reichel 				link_status,
790*83e5aa77SLinus Walleij 				di->max_usb_in_curr.usb_type_max_ua);
7918c0984e5SSebastian Reichel 			ret = -ENXIO;
7928c0984e5SSebastian Reichel 			break;
7938c0984e5SSebastian Reichel 		}
7948c0984e5SSebastian Reichel 	case USB_STAT_CARKIT_1:
7958c0984e5SSebastian Reichel 	case USB_STAT_CARKIT_2:
7968c0984e5SSebastian Reichel 	case USB_STAT_ACA_DOCK_CHARGER:
7978c0984e5SSebastian Reichel 	case USB_STAT_CHARGER_LINE_1:
798*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
7998c0984e5SSebastian Reichel 		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
800*83e5aa77SLinus Walleij 				di->max_usb_in_curr.usb_type_max_ua);
8018c0984e5SSebastian Reichel 		break;
8028c0984e5SSebastian Reichel 	case USB_STAT_NOT_VALID_LINK:
8038c0984e5SSebastian Reichel 		dev_err(di->dev, "USB Type invalid - try charging anyway\n");
804*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
8058c0984e5SSebastian Reichel 		break;
8068c0984e5SSebastian Reichel 
8078c0984e5SSebastian Reichel 	default:
8088c0984e5SSebastian Reichel 		dev_err(di->dev, "USB Type - Unknown\n");
809*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P05;
8108c0984e5SSebastian Reichel 		ret = -ENXIO;
8118c0984e5SSebastian Reichel 		break;
812e15c54d2SMa Feng 	}
8138c0984e5SSebastian Reichel 
814*83e5aa77SLinus Walleij 	di->max_usb_in_curr.set_max_ua = di->max_usb_in_curr.usb_type_max_ua;
8158c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
816*83e5aa77SLinus Walleij 		link_status, di->max_usb_in_curr.set_max_ua);
8178c0984e5SSebastian Reichel 
8188c0984e5SSebastian Reichel 	return ret;
8198c0984e5SSebastian Reichel }
8208c0984e5SSebastian Reichel 
8218c0984e5SSebastian Reichel /**
8228c0984e5SSebastian Reichel  * ab8500_charger_read_usb_type() - read the type of usb connected
8238c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
8248c0984e5SSebastian Reichel  *
8258c0984e5SSebastian Reichel  * Detect the type of the plugged USB
8268c0984e5SSebastian Reichel  * Returns error code in case of failure else 0 on success
8278c0984e5SSebastian Reichel  */
8288c0984e5SSebastian Reichel static int ab8500_charger_read_usb_type(struct ab8500_charger *di)
8298c0984e5SSebastian Reichel {
8308c0984e5SSebastian Reichel 	int ret;
8318c0984e5SSebastian Reichel 	u8 val;
8328c0984e5SSebastian Reichel 
8338c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
8348c0984e5SSebastian Reichel 		AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val);
8358c0984e5SSebastian Reichel 	if (ret < 0) {
8368c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
8378c0984e5SSebastian Reichel 		return ret;
8388c0984e5SSebastian Reichel 	}
8398c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
8408c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
8418c0984e5SSebastian Reichel 			AB8500_USB_LINE_STAT_REG, &val);
8428c0984e5SSebastian Reichel 	else
8438c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
8448c0984e5SSebastian Reichel 			AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
8458c0984e5SSebastian Reichel 	if (ret < 0) {
8468c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
8478c0984e5SSebastian Reichel 		return ret;
8488c0984e5SSebastian Reichel 	}
8498c0984e5SSebastian Reichel 
8508c0984e5SSebastian Reichel 	/* get the USB type */
8518c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
8528c0984e5SSebastian Reichel 		val = (val & AB8500_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
8538c0984e5SSebastian Reichel 	else
8548c0984e5SSebastian Reichel 		val = (val & AB8505_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
8558c0984e5SSebastian Reichel 	ret = ab8500_charger_max_usb_curr(di,
8568c0984e5SSebastian Reichel 		(enum ab8500_charger_link_status) val);
8578c0984e5SSebastian Reichel 
8588c0984e5SSebastian Reichel 	return ret;
8598c0984e5SSebastian Reichel }
8608c0984e5SSebastian Reichel 
8618c0984e5SSebastian Reichel /**
8628c0984e5SSebastian Reichel  * ab8500_charger_detect_usb_type() - get the type of usb connected
8638c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
8648c0984e5SSebastian Reichel  *
8658c0984e5SSebastian Reichel  * Detect the type of the plugged USB
8668c0984e5SSebastian Reichel  * Returns error code in case of failure else 0 on success
8678c0984e5SSebastian Reichel  */
8688c0984e5SSebastian Reichel static int ab8500_charger_detect_usb_type(struct ab8500_charger *di)
8698c0984e5SSebastian Reichel {
8708c0984e5SSebastian Reichel 	int i, ret;
8718c0984e5SSebastian Reichel 	u8 val;
8728c0984e5SSebastian Reichel 
8738c0984e5SSebastian Reichel 	/*
8748c0984e5SSebastian Reichel 	 * On getting the VBUS rising edge detect interrupt there
8758c0984e5SSebastian Reichel 	 * is a 250ms delay after which the register UsbLineStatus
8768c0984e5SSebastian Reichel 	 * is filled with valid data.
8778c0984e5SSebastian Reichel 	 */
8788c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
8798c0984e5SSebastian Reichel 		msleep(250);
8808c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
8818c0984e5SSebastian Reichel 			AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG,
8828c0984e5SSebastian Reichel 			&val);
8838c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s AB8500_IT_SOURCE21_REG %x\n",
8848c0984e5SSebastian Reichel 			__func__, val);
8858c0984e5SSebastian Reichel 		if (ret < 0) {
8868c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
8878c0984e5SSebastian Reichel 			return ret;
8888c0984e5SSebastian Reichel 		}
8898c0984e5SSebastian Reichel 
8908c0984e5SSebastian Reichel 		if (is_ab8500(di->parent))
8918c0984e5SSebastian Reichel 			ret = abx500_get_register_interruptible(di->dev,
8928c0984e5SSebastian Reichel 				AB8500_USB, AB8500_USB_LINE_STAT_REG, &val);
8938c0984e5SSebastian Reichel 		else
8948c0984e5SSebastian Reichel 			ret = abx500_get_register_interruptible(di->dev,
8958c0984e5SSebastian Reichel 				AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
8968c0984e5SSebastian Reichel 		if (ret < 0) {
8978c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
8988c0984e5SSebastian Reichel 			return ret;
8998c0984e5SSebastian Reichel 		}
9008c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s AB8500_USB_LINE_STAT_REG %x\n", __func__,
9018c0984e5SSebastian Reichel 			val);
9028c0984e5SSebastian Reichel 		/*
9038c0984e5SSebastian Reichel 		 * Until the IT source register is read the UsbLineStatus
9048c0984e5SSebastian Reichel 		 * register is not updated, hence doing the same
9058c0984e5SSebastian Reichel 		 * Revisit this:
9068c0984e5SSebastian Reichel 		 */
9078c0984e5SSebastian Reichel 
9088c0984e5SSebastian Reichel 		/* get the USB type */
9098c0984e5SSebastian Reichel 		if (is_ab8500(di->parent))
9108c0984e5SSebastian Reichel 			val = (val & AB8500_USB_LINK_STATUS) >>
9118c0984e5SSebastian Reichel 							USB_LINK_STATUS_SHIFT;
9128c0984e5SSebastian Reichel 		else
9138c0984e5SSebastian Reichel 			val = (val & AB8505_USB_LINK_STATUS) >>
9148c0984e5SSebastian Reichel 							USB_LINK_STATUS_SHIFT;
9158c0984e5SSebastian Reichel 		if (val)
9168c0984e5SSebastian Reichel 			break;
9178c0984e5SSebastian Reichel 	}
9188c0984e5SSebastian Reichel 	ret = ab8500_charger_max_usb_curr(di,
9198c0984e5SSebastian Reichel 		(enum ab8500_charger_link_status) val);
9208c0984e5SSebastian Reichel 
9218c0984e5SSebastian Reichel 	return ret;
9228c0984e5SSebastian Reichel }
9238c0984e5SSebastian Reichel 
9248c0984e5SSebastian Reichel /*
9258c0984e5SSebastian Reichel  * This array maps the raw hex value to charger voltage used by the AB8500
9268c0984e5SSebastian Reichel  * Values taken from the UM0836
9278c0984e5SSebastian Reichel  */
9288c0984e5SSebastian Reichel static int ab8500_charger_voltage_map[] = {
9298c0984e5SSebastian Reichel 	3500 ,
9308c0984e5SSebastian Reichel 	3525 ,
9318c0984e5SSebastian Reichel 	3550 ,
9328c0984e5SSebastian Reichel 	3575 ,
9338c0984e5SSebastian Reichel 	3600 ,
9348c0984e5SSebastian Reichel 	3625 ,
9358c0984e5SSebastian Reichel 	3650 ,
9368c0984e5SSebastian Reichel 	3675 ,
9378c0984e5SSebastian Reichel 	3700 ,
9388c0984e5SSebastian Reichel 	3725 ,
9398c0984e5SSebastian Reichel 	3750 ,
9408c0984e5SSebastian Reichel 	3775 ,
9418c0984e5SSebastian Reichel 	3800 ,
9428c0984e5SSebastian Reichel 	3825 ,
9438c0984e5SSebastian Reichel 	3850 ,
9448c0984e5SSebastian Reichel 	3875 ,
9458c0984e5SSebastian Reichel 	3900 ,
9468c0984e5SSebastian Reichel 	3925 ,
9478c0984e5SSebastian Reichel 	3950 ,
9488c0984e5SSebastian Reichel 	3975 ,
9498c0984e5SSebastian Reichel 	4000 ,
9508c0984e5SSebastian Reichel 	4025 ,
9518c0984e5SSebastian Reichel 	4050 ,
9528c0984e5SSebastian Reichel 	4060 ,
9538c0984e5SSebastian Reichel 	4070 ,
9548c0984e5SSebastian Reichel 	4080 ,
9558c0984e5SSebastian Reichel 	4090 ,
9568c0984e5SSebastian Reichel 	4100 ,
9578c0984e5SSebastian Reichel 	4110 ,
9588c0984e5SSebastian Reichel 	4120 ,
9598c0984e5SSebastian Reichel 	4130 ,
9608c0984e5SSebastian Reichel 	4140 ,
9618c0984e5SSebastian Reichel 	4150 ,
9628c0984e5SSebastian Reichel 	4160 ,
9638c0984e5SSebastian Reichel 	4170 ,
9648c0984e5SSebastian Reichel 	4180 ,
9658c0984e5SSebastian Reichel 	4190 ,
9668c0984e5SSebastian Reichel 	4200 ,
9678c0984e5SSebastian Reichel 	4210 ,
9688c0984e5SSebastian Reichel 	4220 ,
9698c0984e5SSebastian Reichel 	4230 ,
9708c0984e5SSebastian Reichel 	4240 ,
9718c0984e5SSebastian Reichel 	4250 ,
9728c0984e5SSebastian Reichel 	4260 ,
9738c0984e5SSebastian Reichel 	4270 ,
9748c0984e5SSebastian Reichel 	4280 ,
9758c0984e5SSebastian Reichel 	4290 ,
9768c0984e5SSebastian Reichel 	4300 ,
9778c0984e5SSebastian Reichel 	4310 ,
9788c0984e5SSebastian Reichel 	4320 ,
9798c0984e5SSebastian Reichel 	4330 ,
9808c0984e5SSebastian Reichel 	4340 ,
9818c0984e5SSebastian Reichel 	4350 ,
9828c0984e5SSebastian Reichel 	4360 ,
9838c0984e5SSebastian Reichel 	4370 ,
9848c0984e5SSebastian Reichel 	4380 ,
9858c0984e5SSebastian Reichel 	4390 ,
9868c0984e5SSebastian Reichel 	4400 ,
9878c0984e5SSebastian Reichel 	4410 ,
9888c0984e5SSebastian Reichel 	4420 ,
9898c0984e5SSebastian Reichel 	4430 ,
9908c0984e5SSebastian Reichel 	4440 ,
9918c0984e5SSebastian Reichel 	4450 ,
9928c0984e5SSebastian Reichel 	4460 ,
9938c0984e5SSebastian Reichel 	4470 ,
9948c0984e5SSebastian Reichel 	4480 ,
9958c0984e5SSebastian Reichel 	4490 ,
9968c0984e5SSebastian Reichel 	4500 ,
9978c0984e5SSebastian Reichel 	4510 ,
9988c0984e5SSebastian Reichel 	4520 ,
9998c0984e5SSebastian Reichel 	4530 ,
10008c0984e5SSebastian Reichel 	4540 ,
10018c0984e5SSebastian Reichel 	4550 ,
10028c0984e5SSebastian Reichel 	4560 ,
10038c0984e5SSebastian Reichel 	4570 ,
10048c0984e5SSebastian Reichel 	4580 ,
10058c0984e5SSebastian Reichel 	4590 ,
10068c0984e5SSebastian Reichel 	4600 ,
10078c0984e5SSebastian Reichel };
10088c0984e5SSebastian Reichel 
10098c0984e5SSebastian Reichel static int ab8500_voltage_to_regval(int voltage)
10108c0984e5SSebastian Reichel {
10118c0984e5SSebastian Reichel 	int i;
10128c0984e5SSebastian Reichel 
10138c0984e5SSebastian Reichel 	/* Special case for voltage below 3.5V */
10148c0984e5SSebastian Reichel 	if (voltage < ab8500_charger_voltage_map[0])
10158c0984e5SSebastian Reichel 		return LOW_VOLT_REG;
10168c0984e5SSebastian Reichel 
10178c0984e5SSebastian Reichel 	for (i = 1; i < ARRAY_SIZE(ab8500_charger_voltage_map); i++) {
10188c0984e5SSebastian Reichel 		if (voltage < ab8500_charger_voltage_map[i])
10198c0984e5SSebastian Reichel 			return i - 1;
10208c0984e5SSebastian Reichel 	}
10218c0984e5SSebastian Reichel 
10228c0984e5SSebastian Reichel 	/* If not last element, return error */
10238c0984e5SSebastian Reichel 	i = ARRAY_SIZE(ab8500_charger_voltage_map) - 1;
10248c0984e5SSebastian Reichel 	if (voltage == ab8500_charger_voltage_map[i])
10258c0984e5SSebastian Reichel 		return i;
10268c0984e5SSebastian Reichel 	else
10278c0984e5SSebastian Reichel 		return -1;
10288c0984e5SSebastian Reichel }
10298c0984e5SSebastian Reichel 
10303aca6ecdSLinus Walleij /* This array maps the raw register value to charger input current */
10313aca6ecdSLinus Walleij static int ab8500_charge_input_curr_map[] = {
1032*83e5aa77SLinus Walleij 	50000, 98000, 193000, 290000, 380000, 450000, 500000, 600000,
1033*83e5aa77SLinus Walleij 	700000, 800000, 900000, 1000000, 1100000, 1300000, 1400000, 1500000,
10343aca6ecdSLinus Walleij };
10353aca6ecdSLinus Walleij 
10363aca6ecdSLinus Walleij /* This array maps the raw register value to charger output current */
10373aca6ecdSLinus Walleij static int ab8500_charge_output_curr_map[] = {
1038*83e5aa77SLinus Walleij 	100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000,
1039*83e5aa77SLinus Walleij 	900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1500000,
10403aca6ecdSLinus Walleij };
10413aca6ecdSLinus Walleij 
1042*83e5aa77SLinus Walleij static int ab8500_current_to_regval(struct ab8500_charger *di, int curr_ua)
10438c0984e5SSebastian Reichel {
10448c0984e5SSebastian Reichel 	int i;
10458c0984e5SSebastian Reichel 
1046*83e5aa77SLinus Walleij 	if (curr_ua < ab8500_charge_output_curr_map[0])
10478c0984e5SSebastian Reichel 		return 0;
10488c0984e5SSebastian Reichel 
10493aca6ecdSLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charge_output_curr_map); i++) {
1050*83e5aa77SLinus Walleij 		if (curr_ua < ab8500_charge_output_curr_map[i])
10518c0984e5SSebastian Reichel 			return i - 1;
10528c0984e5SSebastian Reichel 	}
10538c0984e5SSebastian Reichel 
10548c0984e5SSebastian Reichel 	/* If not last element, return error */
10553aca6ecdSLinus Walleij 	i =  ARRAY_SIZE(ab8500_charge_output_curr_map) - 1;
1056*83e5aa77SLinus Walleij 	if (curr_ua == ab8500_charge_output_curr_map[i])
10578c0984e5SSebastian Reichel 		return i;
10588c0984e5SSebastian Reichel 	else
10598c0984e5SSebastian Reichel 		return -1;
10608c0984e5SSebastian Reichel }
10618c0984e5SSebastian Reichel 
1062*83e5aa77SLinus Walleij static int ab8500_vbus_in_curr_to_regval(struct ab8500_charger *di, int curr_ua)
10638c0984e5SSebastian Reichel {
10648c0984e5SSebastian Reichel 	int i;
10658c0984e5SSebastian Reichel 
1066*83e5aa77SLinus Walleij 	if (curr_ua < ab8500_charge_input_curr_map[0])
10678c0984e5SSebastian Reichel 		return 0;
10688c0984e5SSebastian Reichel 
10693aca6ecdSLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charge_input_curr_map); i++) {
1070*83e5aa77SLinus Walleij 		if (curr_ua < ab8500_charge_input_curr_map[i])
10718c0984e5SSebastian Reichel 			return i - 1;
10728c0984e5SSebastian Reichel 	}
10738c0984e5SSebastian Reichel 
10748c0984e5SSebastian Reichel 	/* If not last element, return error */
10753aca6ecdSLinus Walleij 	i =  ARRAY_SIZE(ab8500_charge_input_curr_map) - 1;
1076*83e5aa77SLinus Walleij 	if (curr_ua == ab8500_charge_input_curr_map[i])
10778c0984e5SSebastian Reichel 		return i;
10788c0984e5SSebastian Reichel 	else
10798c0984e5SSebastian Reichel 		return -1;
10808c0984e5SSebastian Reichel }
10818c0984e5SSebastian Reichel 
10828c0984e5SSebastian Reichel /**
10838c0984e5SSebastian Reichel  * ab8500_charger_get_usb_cur() - get usb current
10848c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structre
10858c0984e5SSebastian Reichel  *
10868c0984e5SSebastian Reichel  * The usb stack provides the maximum current that can be drawn from
1087*83e5aa77SLinus Walleij  * the standard usb host. This will be in uA.
1088*83e5aa77SLinus Walleij  * This function converts current in uA to a value that can be written
10898c0984e5SSebastian Reichel  * to the register. Returns -1 if charging is not allowed
10908c0984e5SSebastian Reichel  */
10918c0984e5SSebastian Reichel static int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
10928c0984e5SSebastian Reichel {
10938c0984e5SSebastian Reichel 	int ret = 0;
1094*83e5aa77SLinus Walleij 	switch (di->usb_state.usb_current_ua) {
1095*83e5aa77SLinus Walleij 	case 100000:
1096*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P09;
10978c0984e5SSebastian Reichel 		break;
1098*83e5aa77SLinus Walleij 	case 200000:
1099*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P19;
11008c0984e5SSebastian Reichel 		break;
1101*83e5aa77SLinus Walleij 	case 300000:
1102*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P29;
11038c0984e5SSebastian Reichel 		break;
1104*83e5aa77SLinus Walleij 	case 400000:
1105*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P38;
11068c0984e5SSebastian Reichel 		break;
1107*83e5aa77SLinus Walleij 	case 500000:
1108*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P5;
11098c0984e5SSebastian Reichel 		break;
11108c0984e5SSebastian Reichel 	default:
1111*83e5aa77SLinus Walleij 		di->max_usb_in_curr.usb_type_max_ua = USB_CH_IP_CUR_LVL_0P05;
11128c0984e5SSebastian Reichel 		ret = -EPERM;
11138c0984e5SSebastian Reichel 		break;
1114e15c54d2SMa Feng 	}
1115*83e5aa77SLinus Walleij 	di->max_usb_in_curr.set_max_ua = di->max_usb_in_curr.usb_type_max_ua;
11168c0984e5SSebastian Reichel 	return ret;
11178c0984e5SSebastian Reichel }
11188c0984e5SSebastian Reichel 
11198c0984e5SSebastian Reichel /**
11208c0984e5SSebastian Reichel  * ab8500_charger_check_continue_stepping() - Check to allow stepping
11218c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
11228c0984e5SSebastian Reichel  * @reg:	select what charger register to check
11238c0984e5SSebastian Reichel  *
11248c0984e5SSebastian Reichel  * Check if current stepping should be allowed to continue.
11258c0984e5SSebastian Reichel  * Checks if charger source has not collapsed. If it has, further stepping
11268c0984e5SSebastian Reichel  * is not allowed.
11278c0984e5SSebastian Reichel  */
11288c0984e5SSebastian Reichel static bool ab8500_charger_check_continue_stepping(struct ab8500_charger *di,
11298c0984e5SSebastian Reichel 						   int reg)
11308c0984e5SSebastian Reichel {
11318c0984e5SSebastian Reichel 	if (reg == AB8500_USBCH_IPT_CRNTLVL_REG)
11328c0984e5SSebastian Reichel 		return !di->flags.vbus_drop_end;
11338c0984e5SSebastian Reichel 	else
11348c0984e5SSebastian Reichel 		return true;
11358c0984e5SSebastian Reichel }
11368c0984e5SSebastian Reichel 
11378c0984e5SSebastian Reichel /**
11388c0984e5SSebastian Reichel  * ab8500_charger_set_current() - set charger current
11398c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
1140*83e5aa77SLinus Walleij  * @ich_ua:	charger current, in uA
11418c0984e5SSebastian Reichel  * @reg:	select what charger register to set
11428c0984e5SSebastian Reichel  *
11438c0984e5SSebastian Reichel  * Set charger current.
11448c0984e5SSebastian Reichel  * There is no state machine in the AB to step up/down the charger
11458c0984e5SSebastian Reichel  * current to avoid dips and spikes on MAIN, VBUS and VBAT when
11468c0984e5SSebastian Reichel  * charging is started. Instead we need to implement
11478c0984e5SSebastian Reichel  * this charger current step-up/down here.
11488c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
11498c0984e5SSebastian Reichel  */
11508c0984e5SSebastian Reichel static int ab8500_charger_set_current(struct ab8500_charger *di,
1151*83e5aa77SLinus Walleij 	int ich_ua, int reg)
11528c0984e5SSebastian Reichel {
11538c0984e5SSebastian Reichel 	int ret = 0;
11548c0984e5SSebastian Reichel 	int curr_index, prev_curr_index, shift_value, i;
11558c0984e5SSebastian Reichel 	u8 reg_value;
11568c0984e5SSebastian Reichel 	u32 step_udelay;
11578c0984e5SSebastian Reichel 	bool no_stepping = false;
11588c0984e5SSebastian Reichel 
11598c0984e5SSebastian Reichel 	atomic_inc(&di->current_stepping_sessions);
11608c0984e5SSebastian Reichel 
11618c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
11628c0984e5SSebastian Reichel 		reg, &reg_value);
11638c0984e5SSebastian Reichel 	if (ret < 0) {
11648c0984e5SSebastian Reichel 		dev_err(di->dev, "%s read failed\n", __func__);
11658c0984e5SSebastian Reichel 		goto exit_set_current;
11668c0984e5SSebastian Reichel 	}
11678c0984e5SSebastian Reichel 
11688c0984e5SSebastian Reichel 	switch (reg) {
11698c0984e5SSebastian Reichel 	case AB8500_MCH_IPT_CURLVL_REG:
11708c0984e5SSebastian Reichel 		shift_value = MAIN_CH_INPUT_CURR_SHIFT;
11718c0984e5SSebastian Reichel 		prev_curr_index = (reg_value >> shift_value);
1172*83e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, ich_ua);
11738c0984e5SSebastian Reichel 		step_udelay = STEP_UDELAY;
11748c0984e5SSebastian Reichel 		if (!di->ac.charger_connected)
11758c0984e5SSebastian Reichel 			no_stepping = true;
11768c0984e5SSebastian Reichel 		break;
11778c0984e5SSebastian Reichel 	case AB8500_USBCH_IPT_CRNTLVL_REG:
11788c0984e5SSebastian Reichel 		shift_value = VBUS_IN_CURR_LIM_SHIFT;
11798c0984e5SSebastian Reichel 		prev_curr_index = (reg_value >> shift_value);
1180*83e5aa77SLinus Walleij 		curr_index = ab8500_vbus_in_curr_to_regval(di, ich_ua);
11818c0984e5SSebastian Reichel 		step_udelay = STEP_UDELAY * 100;
11828c0984e5SSebastian Reichel 
11838c0984e5SSebastian Reichel 		if (!di->usb.charger_connected)
11848c0984e5SSebastian Reichel 			no_stepping = true;
11858c0984e5SSebastian Reichel 		break;
11868c0984e5SSebastian Reichel 	case AB8500_CH_OPT_CRNTLVL_REG:
11878c0984e5SSebastian Reichel 		shift_value = 0;
11888c0984e5SSebastian Reichel 		prev_curr_index = (reg_value >> shift_value);
1189*83e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, ich_ua);
11908c0984e5SSebastian Reichel 		step_udelay = STEP_UDELAY;
11918c0984e5SSebastian Reichel 		if (curr_index && (curr_index - prev_curr_index) > 1)
11928c0984e5SSebastian Reichel 			step_udelay *= 100;
11938c0984e5SSebastian Reichel 
11948c0984e5SSebastian Reichel 		if (!di->usb.charger_connected && !di->ac.charger_connected)
11958c0984e5SSebastian Reichel 			no_stepping = true;
11968c0984e5SSebastian Reichel 
11978c0984e5SSebastian Reichel 		break;
11988c0984e5SSebastian Reichel 	default:
11998c0984e5SSebastian Reichel 		dev_err(di->dev, "%s current register not valid\n", __func__);
12008c0984e5SSebastian Reichel 		ret = -ENXIO;
12018c0984e5SSebastian Reichel 		goto exit_set_current;
12028c0984e5SSebastian Reichel 	}
12038c0984e5SSebastian Reichel 
12048c0984e5SSebastian Reichel 	if (curr_index < 0) {
12058c0984e5SSebastian Reichel 		dev_err(di->dev, "requested current limit out-of-range\n");
12068c0984e5SSebastian Reichel 		ret = -ENXIO;
12078c0984e5SSebastian Reichel 		goto exit_set_current;
12088c0984e5SSebastian Reichel 	}
12098c0984e5SSebastian Reichel 
12108c0984e5SSebastian Reichel 	/* only update current if it's been changed */
12118c0984e5SSebastian Reichel 	if (prev_curr_index == curr_index) {
12128c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s current not changed for reg: 0x%02x\n",
12138c0984e5SSebastian Reichel 			__func__, reg);
12148c0984e5SSebastian Reichel 		ret = 0;
12158c0984e5SSebastian Reichel 		goto exit_set_current;
12168c0984e5SSebastian Reichel 	}
12178c0984e5SSebastian Reichel 
1218*83e5aa77SLinus Walleij 	dev_dbg(di->dev, "%s set charger current: %d uA for reg: 0x%02x\n",
1219*83e5aa77SLinus Walleij 		__func__, ich_ua, reg);
12208c0984e5SSebastian Reichel 
12218c0984e5SSebastian Reichel 	if (no_stepping) {
12228c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
12238c0984e5SSebastian Reichel 					reg, (u8)curr_index << shift_value);
12248c0984e5SSebastian Reichel 		if (ret)
12258c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
12268c0984e5SSebastian Reichel 	} else if (prev_curr_index > curr_index) {
12278c0984e5SSebastian Reichel 		for (i = prev_curr_index - 1; i >= curr_index; i--) {
12288c0984e5SSebastian Reichel 			dev_dbg(di->dev, "curr change_1 to: %x for 0x%02x\n",
12298c0984e5SSebastian Reichel 				(u8) i << shift_value, reg);
12308c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
12318c0984e5SSebastian Reichel 				AB8500_CHARGER, reg, (u8)i << shift_value);
12328c0984e5SSebastian Reichel 			if (ret) {
12338c0984e5SSebastian Reichel 				dev_err(di->dev, "%s write failed\n", __func__);
12348c0984e5SSebastian Reichel 				goto exit_set_current;
12358c0984e5SSebastian Reichel 			}
12368c0984e5SSebastian Reichel 			if (i != curr_index)
12378c0984e5SSebastian Reichel 				usleep_range(step_udelay, step_udelay * 2);
12388c0984e5SSebastian Reichel 		}
12398c0984e5SSebastian Reichel 	} else {
12408c0984e5SSebastian Reichel 		bool allow = true;
12418c0984e5SSebastian Reichel 		for (i = prev_curr_index + 1; i <= curr_index && allow; i++) {
12428c0984e5SSebastian Reichel 			dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n",
12438c0984e5SSebastian Reichel 				(u8)i << shift_value, reg);
12448c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
12458c0984e5SSebastian Reichel 				AB8500_CHARGER, reg, (u8)i << shift_value);
12468c0984e5SSebastian Reichel 			if (ret) {
12478c0984e5SSebastian Reichel 				dev_err(di->dev, "%s write failed\n", __func__);
12488c0984e5SSebastian Reichel 				goto exit_set_current;
12498c0984e5SSebastian Reichel 			}
12508c0984e5SSebastian Reichel 			if (i != curr_index)
12518c0984e5SSebastian Reichel 				usleep_range(step_udelay, step_udelay * 2);
12528c0984e5SSebastian Reichel 
12538c0984e5SSebastian Reichel 			allow = ab8500_charger_check_continue_stepping(di, reg);
12548c0984e5SSebastian Reichel 		}
12558c0984e5SSebastian Reichel 	}
12568c0984e5SSebastian Reichel 
12578c0984e5SSebastian Reichel exit_set_current:
12588c0984e5SSebastian Reichel 	atomic_dec(&di->current_stepping_sessions);
12598c0984e5SSebastian Reichel 
12608c0984e5SSebastian Reichel 	return ret;
12618c0984e5SSebastian Reichel }
12628c0984e5SSebastian Reichel 
12638c0984e5SSebastian Reichel /**
12648c0984e5SSebastian Reichel  * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit
12658c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
1266*83e5aa77SLinus Walleij  * @ich_in_ua:	charger input current limit in microampere
12678c0984e5SSebastian Reichel  *
12688c0984e5SSebastian Reichel  * Sets the current that can be drawn from the USB host
12698c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
12708c0984e5SSebastian Reichel  */
12718c0984e5SSebastian Reichel static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
1272*83e5aa77SLinus Walleij 		int ich_in_ua)
12738c0984e5SSebastian Reichel {
12748c0984e5SSebastian Reichel 	int min_value;
12758c0984e5SSebastian Reichel 	int ret;
12768c0984e5SSebastian Reichel 
12778c0984e5SSebastian Reichel 	/* We should always use to lowest current limit */
1278*83e5aa77SLinus Walleij 	min_value = min(di->bm->chg_params->usb_curr_max_ua, ich_in_ua);
1279*83e5aa77SLinus Walleij 	if (di->max_usb_in_curr.set_max_ua > 0)
1280*83e5aa77SLinus Walleij 		min_value = min(di->max_usb_in_curr.set_max_ua, min_value);
12818c0984e5SSebastian Reichel 
1282*83e5aa77SLinus Walleij 	if (di->usb_state.usb_current_ua >= 0)
1283*83e5aa77SLinus Walleij 		min_value = min(di->usb_state.usb_current_ua, min_value);
12848c0984e5SSebastian Reichel 
12858c0984e5SSebastian Reichel 	switch (min_value) {
1286*83e5aa77SLinus Walleij 	case 100000:
12878c0984e5SSebastian Reichel 		if (di->vbat < VBAT_TRESH_IP_CUR_RED)
12888c0984e5SSebastian Reichel 			min_value = USB_CH_IP_CUR_LVL_0P05;
12898c0984e5SSebastian Reichel 		break;
1290*83e5aa77SLinus Walleij 	case 500000:
12918c0984e5SSebastian Reichel 		if (di->vbat < VBAT_TRESH_IP_CUR_RED)
12928c0984e5SSebastian Reichel 			min_value = USB_CH_IP_CUR_LVL_0P45;
12938c0984e5SSebastian Reichel 		break;
12948c0984e5SSebastian Reichel 	default:
12958c0984e5SSebastian Reichel 		break;
12968c0984e5SSebastian Reichel 	}
12978c0984e5SSebastian Reichel 
1298*83e5aa77SLinus Walleij 	dev_info(di->dev, "VBUS input current limit set to %d uA\n", min_value);
12998c0984e5SSebastian Reichel 
13008c0984e5SSebastian Reichel 	mutex_lock(&di->usb_ipt_crnt_lock);
13018c0984e5SSebastian Reichel 	ret = ab8500_charger_set_current(di, min_value,
13028c0984e5SSebastian Reichel 		AB8500_USBCH_IPT_CRNTLVL_REG);
13038c0984e5SSebastian Reichel 	mutex_unlock(&di->usb_ipt_crnt_lock);
13048c0984e5SSebastian Reichel 
13058c0984e5SSebastian Reichel 	return ret;
13068c0984e5SSebastian Reichel }
13078c0984e5SSebastian Reichel 
13088c0984e5SSebastian Reichel /**
13098c0984e5SSebastian Reichel  * ab8500_charger_set_main_in_curr() - set main charger input current
13108c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
1311*83e5aa77SLinus Walleij  * @ich_in_ua:	input charger current, in uA
13128c0984e5SSebastian Reichel  *
13138c0984e5SSebastian Reichel  * Set main charger input current.
13148c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
13158c0984e5SSebastian Reichel  */
13168c0984e5SSebastian Reichel static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di,
1317*83e5aa77SLinus Walleij 	int ich_in_ua)
13188c0984e5SSebastian Reichel {
1319*83e5aa77SLinus Walleij 	return ab8500_charger_set_current(di, ich_in_ua,
13208c0984e5SSebastian Reichel 		AB8500_MCH_IPT_CURLVL_REG);
13218c0984e5SSebastian Reichel }
13228c0984e5SSebastian Reichel 
13238c0984e5SSebastian Reichel /**
13248c0984e5SSebastian Reichel  * ab8500_charger_set_output_curr() - set charger output current
13258c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
1326*83e5aa77SLinus Walleij  * @ich_out_ua:	output charger current, in uA
13278c0984e5SSebastian Reichel  *
13288c0984e5SSebastian Reichel  * Set charger output current.
13298c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
13308c0984e5SSebastian Reichel  */
13318c0984e5SSebastian Reichel static int ab8500_charger_set_output_curr(struct ab8500_charger *di,
1332*83e5aa77SLinus Walleij 	int ich_out_ua)
13338c0984e5SSebastian Reichel {
1334*83e5aa77SLinus Walleij 	return ab8500_charger_set_current(di, ich_out_ua,
13358c0984e5SSebastian Reichel 		AB8500_CH_OPT_CRNTLVL_REG);
13368c0984e5SSebastian Reichel }
13378c0984e5SSebastian Reichel 
13388c0984e5SSebastian Reichel /**
13398c0984e5SSebastian Reichel  * ab8500_charger_led_en() - turn on/off chargign led
13408c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
13418c0984e5SSebastian Reichel  * @on:		flag to turn on/off the chargign led
13428c0984e5SSebastian Reichel  *
13438c0984e5SSebastian Reichel  * Power ON/OFF charging LED indication
13448c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
13458c0984e5SSebastian Reichel  */
13468c0984e5SSebastian Reichel static int ab8500_charger_led_en(struct ab8500_charger *di, int on)
13478c0984e5SSebastian Reichel {
13488c0984e5SSebastian Reichel 	int ret;
13498c0984e5SSebastian Reichel 
13508c0984e5SSebastian Reichel 	if (on) {
13518c0984e5SSebastian Reichel 		/* Power ON charging LED indicator, set LED current to 5mA */
13528c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
13538c0984e5SSebastian Reichel 			AB8500_LED_INDICATOR_PWM_CTRL,
13548c0984e5SSebastian Reichel 			(LED_IND_CUR_5MA | LED_INDICATOR_PWM_ENA));
13558c0984e5SSebastian Reichel 		if (ret) {
13568c0984e5SSebastian Reichel 			dev_err(di->dev, "Power ON LED failed\n");
13578c0984e5SSebastian Reichel 			return ret;
13588c0984e5SSebastian Reichel 		}
13598c0984e5SSebastian Reichel 		/* LED indicator PWM duty cycle 252/256 */
13608c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
13618c0984e5SSebastian Reichel 			AB8500_LED_INDICATOR_PWM_DUTY,
13628c0984e5SSebastian Reichel 			LED_INDICATOR_PWM_DUTY_252_256);
13638c0984e5SSebastian Reichel 		if (ret) {
13648c0984e5SSebastian Reichel 			dev_err(di->dev, "Set LED PWM duty cycle failed\n");
13658c0984e5SSebastian Reichel 			return ret;
13668c0984e5SSebastian Reichel 		}
13678c0984e5SSebastian Reichel 	} else {
13688c0984e5SSebastian Reichel 		/* Power off charging LED indicator */
13698c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
13708c0984e5SSebastian Reichel 			AB8500_LED_INDICATOR_PWM_CTRL,
13718c0984e5SSebastian Reichel 			LED_INDICATOR_PWM_DIS);
13728c0984e5SSebastian Reichel 		if (ret) {
13738c0984e5SSebastian Reichel 			dev_err(di->dev, "Power-off LED failed\n");
13748c0984e5SSebastian Reichel 			return ret;
13758c0984e5SSebastian Reichel 		}
13768c0984e5SSebastian Reichel 	}
13778c0984e5SSebastian Reichel 
13788c0984e5SSebastian Reichel 	return ret;
13798c0984e5SSebastian Reichel }
13808c0984e5SSebastian Reichel 
13818c0984e5SSebastian Reichel /**
13828c0984e5SSebastian Reichel  * ab8500_charger_ac_en() - enable or disable ac charging
13838c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
13848c0984e5SSebastian Reichel  * @enable:	enable/disable flag
13858c0984e5SSebastian Reichel  * @vset:	charging voltage
1386*83e5aa77SLinus Walleij  * @iset_ua:	charging current in microampere
13878c0984e5SSebastian Reichel  *
13888c0984e5SSebastian Reichel  * Enable/Disable AC/Mains charging and turns on/off the charging led
13898c0984e5SSebastian Reichel  * respectively.
13908c0984e5SSebastian Reichel  **/
13918c0984e5SSebastian Reichel static int ab8500_charger_ac_en(struct ux500_charger *charger,
1392*83e5aa77SLinus Walleij 	int enable, int vset, int iset_ua)
13938c0984e5SSebastian Reichel {
13948c0984e5SSebastian Reichel 	int ret;
13958c0984e5SSebastian Reichel 	int volt_index;
13968c0984e5SSebastian Reichel 	int curr_index;
13978c0984e5SSebastian Reichel 	int input_curr_index;
13988c0984e5SSebastian Reichel 	u8 overshoot = 0;
13998c0984e5SSebastian Reichel 
14008c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
14018c0984e5SSebastian Reichel 
14028c0984e5SSebastian Reichel 	if (enable) {
14038c0984e5SSebastian Reichel 		/* Check if AC is connected */
14048c0984e5SSebastian Reichel 		if (!di->ac.charger_connected) {
14058c0984e5SSebastian Reichel 			dev_err(di->dev, "AC charger not connected\n");
14068c0984e5SSebastian Reichel 			return -ENXIO;
14078c0984e5SSebastian Reichel 		}
14088c0984e5SSebastian Reichel 
14098c0984e5SSebastian Reichel 		/* Enable AC charging */
1410*83e5aa77SLinus Walleij 		dev_dbg(di->dev, "Enable AC: %dmV %duA\n", vset, iset_ua);
14118c0984e5SSebastian Reichel 
14128c0984e5SSebastian Reichel 		/*
14138c0984e5SSebastian Reichel 		 * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
14148c0984e5SSebastian Reichel 		 * will be triggered every time we enable the VDD ADC supply.
14158c0984e5SSebastian Reichel 		 * This will turn off charging for a short while.
14168c0984e5SSebastian Reichel 		 * It can be avoided by having the supply on when
14178c0984e5SSebastian Reichel 		 * there is a charger enabled. Normally the VDD ADC supply
1418ddb74e98SAshish Chavan 		 * is enabled every time a GPADC conversion is triggered.
1419ddb74e98SAshish Chavan 		 * We will force it to be enabled from this driver to have
1420ddb74e98SAshish Chavan 		 * the GPADC module independent of the AB8500 chargers
14218c0984e5SSebastian Reichel 		 */
14228c0984e5SSebastian Reichel 		if (!di->vddadc_en_ac) {
14238c0984e5SSebastian Reichel 			ret = regulator_enable(di->regu);
14248c0984e5SSebastian Reichel 			if (ret)
14258c0984e5SSebastian Reichel 				dev_warn(di->dev,
14268c0984e5SSebastian Reichel 					"Failed to enable regulator\n");
14278c0984e5SSebastian Reichel 			else
14288c0984e5SSebastian Reichel 				di->vddadc_en_ac = true;
14298c0984e5SSebastian Reichel 		}
14308c0984e5SSebastian Reichel 
14318c0984e5SSebastian Reichel 		/* Check if the requested voltage or current is valid */
14328c0984e5SSebastian Reichel 		volt_index = ab8500_voltage_to_regval(vset);
1433*83e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, iset_ua);
14348c0984e5SSebastian Reichel 		input_curr_index = ab8500_current_to_regval(di,
1435*83e5aa77SLinus Walleij 			di->bm->chg_params->ac_curr_max_ua);
14368c0984e5SSebastian Reichel 		if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) {
14378c0984e5SSebastian Reichel 			dev_err(di->dev,
14388c0984e5SSebastian Reichel 				"Charger voltage or current too high, "
14398c0984e5SSebastian Reichel 				"charging not started\n");
14408c0984e5SSebastian Reichel 			return -ENXIO;
14418c0984e5SSebastian Reichel 		}
14428c0984e5SSebastian Reichel 
14438c0984e5SSebastian Reichel 		/* ChVoltLevel: maximum battery charging voltage */
14448c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
14458c0984e5SSebastian Reichel 			AB8500_CH_VOLT_LVL_REG, (u8) volt_index);
14468c0984e5SSebastian Reichel 		if (ret) {
14478c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
14488c0984e5SSebastian Reichel 			return ret;
14498c0984e5SSebastian Reichel 		}
14508c0984e5SSebastian Reichel 		/* MainChInputCurr: current that can be drawn from the charger*/
14518c0984e5SSebastian Reichel 		ret = ab8500_charger_set_main_in_curr(di,
1452*83e5aa77SLinus Walleij 			di->bm->chg_params->ac_curr_max_ua);
14538c0984e5SSebastian Reichel 		if (ret) {
14548c0984e5SSebastian Reichel 			dev_err(di->dev, "%s Failed to set MainChInputCurr\n",
14558c0984e5SSebastian Reichel 				__func__);
14568c0984e5SSebastian Reichel 			return ret;
14578c0984e5SSebastian Reichel 		}
14588c0984e5SSebastian Reichel 		/* ChOutputCurentLevel: protected output current */
1459*83e5aa77SLinus Walleij 		ret = ab8500_charger_set_output_curr(di, iset_ua);
14608c0984e5SSebastian Reichel 		if (ret) {
14618c0984e5SSebastian Reichel 			dev_err(di->dev, "%s "
14628c0984e5SSebastian Reichel 				"Failed to set ChOutputCurentLevel\n",
14638c0984e5SSebastian Reichel 				__func__);
14648c0984e5SSebastian Reichel 			return ret;
14658c0984e5SSebastian Reichel 		}
14668c0984e5SSebastian Reichel 
14678c0984e5SSebastian Reichel 		/* Check if VBAT overshoot control should be enabled */
14688c0984e5SSebastian Reichel 		if (!di->bm->enable_overshoot)
14698c0984e5SSebastian Reichel 			overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N;
14708c0984e5SSebastian Reichel 
14718c0984e5SSebastian Reichel 		/* Enable Main Charger */
14728c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
14738c0984e5SSebastian Reichel 			AB8500_MCH_CTRL1, MAIN_CH_ENA | overshoot);
14748c0984e5SSebastian Reichel 		if (ret) {
14758c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
14768c0984e5SSebastian Reichel 			return ret;
14778c0984e5SSebastian Reichel 		}
14788c0984e5SSebastian Reichel 
14798c0984e5SSebastian Reichel 		/* Power on charging LED indication */
14808c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, true);
14818c0984e5SSebastian Reichel 		if (ret < 0)
14828c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to enable LED\n");
14838c0984e5SSebastian Reichel 
14848c0984e5SSebastian Reichel 		di->ac.charger_online = 1;
14858c0984e5SSebastian Reichel 	} else {
14868c0984e5SSebastian Reichel 		/* Disable AC charging */
14878c0984e5SSebastian Reichel 		if (is_ab8500_1p1_or_earlier(di->parent)) {
14888c0984e5SSebastian Reichel 			/*
14898c0984e5SSebastian Reichel 			 * For ABB revision 1.0 and 1.1 there is a bug in the
1490ddb74e98SAshish Chavan 			 * watchdog logic. That means we have to continuously
14918c0984e5SSebastian Reichel 			 * kick the charger watchdog even when no charger is
14928c0984e5SSebastian Reichel 			 * connected. This is only valid once the AC charger
14938c0984e5SSebastian Reichel 			 * has been enabled. This is a bug that is not handled
14948c0984e5SSebastian Reichel 			 * by the algorithm and the watchdog have to be kicked
14958c0984e5SSebastian Reichel 			 * by the charger driver when the AC charger
14968c0984e5SSebastian Reichel 			 * is disabled
14978c0984e5SSebastian Reichel 			 */
14988c0984e5SSebastian Reichel 			if (di->ac_conn) {
14998c0984e5SSebastian Reichel 				queue_delayed_work(di->charger_wq,
15008c0984e5SSebastian Reichel 					&di->kick_wd_work,
15018c0984e5SSebastian Reichel 					round_jiffies(WD_KICK_INTERVAL));
15028c0984e5SSebastian Reichel 			}
15038c0984e5SSebastian Reichel 
15048c0984e5SSebastian Reichel 			/*
15058c0984e5SSebastian Reichel 			 * We can't turn off charging completely
15068c0984e5SSebastian Reichel 			 * due to a bug in AB8500 cut1.
15078c0984e5SSebastian Reichel 			 * If we do, charging will not start again.
15088c0984e5SSebastian Reichel 			 * That is why we set the lowest voltage
15098c0984e5SSebastian Reichel 			 * and current possible
15108c0984e5SSebastian Reichel 			 */
15118c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
15128c0984e5SSebastian Reichel 				AB8500_CHARGER,
15138c0984e5SSebastian Reichel 				AB8500_CH_VOLT_LVL_REG, CH_VOL_LVL_3P5);
15148c0984e5SSebastian Reichel 			if (ret) {
15158c0984e5SSebastian Reichel 				dev_err(di->dev,
15168c0984e5SSebastian Reichel 					"%s write failed\n", __func__);
15178c0984e5SSebastian Reichel 				return ret;
15188c0984e5SSebastian Reichel 			}
15198c0984e5SSebastian Reichel 
15208c0984e5SSebastian Reichel 			ret = ab8500_charger_set_output_curr(di, 0);
15218c0984e5SSebastian Reichel 			if (ret) {
15228c0984e5SSebastian Reichel 				dev_err(di->dev, "%s "
15238c0984e5SSebastian Reichel 					"Failed to set ChOutputCurentLevel\n",
15248c0984e5SSebastian Reichel 					__func__);
15258c0984e5SSebastian Reichel 				return ret;
15268c0984e5SSebastian Reichel 			}
15278c0984e5SSebastian Reichel 		} else {
15288c0984e5SSebastian Reichel 			ret = abx500_set_register_interruptible(di->dev,
15298c0984e5SSebastian Reichel 				AB8500_CHARGER,
15308c0984e5SSebastian Reichel 				AB8500_MCH_CTRL1, 0);
15318c0984e5SSebastian Reichel 			if (ret) {
15328c0984e5SSebastian Reichel 				dev_err(di->dev,
15338c0984e5SSebastian Reichel 					"%s write failed\n", __func__);
15348c0984e5SSebastian Reichel 				return ret;
15358c0984e5SSebastian Reichel 			}
15368c0984e5SSebastian Reichel 		}
15378c0984e5SSebastian Reichel 
15388c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, false);
15398c0984e5SSebastian Reichel 		if (ret < 0)
15408c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to disable LED\n");
15418c0984e5SSebastian Reichel 
15428c0984e5SSebastian Reichel 		di->ac.charger_online = 0;
15438c0984e5SSebastian Reichel 		di->ac.wd_expired = false;
15448c0984e5SSebastian Reichel 
15458c0984e5SSebastian Reichel 		/* Disable regulator if enabled */
15468c0984e5SSebastian Reichel 		if (di->vddadc_en_ac) {
15478c0984e5SSebastian Reichel 			regulator_disable(di->regu);
15488c0984e5SSebastian Reichel 			di->vddadc_en_ac = false;
15498c0984e5SSebastian Reichel 		}
15508c0984e5SSebastian Reichel 
15518c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s Disabled AC charging\n", __func__);
15528c0984e5SSebastian Reichel 	}
15538c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
15548c0984e5SSebastian Reichel 
15558c0984e5SSebastian Reichel 	return ret;
15568c0984e5SSebastian Reichel }
15578c0984e5SSebastian Reichel 
15588c0984e5SSebastian Reichel /**
15598c0984e5SSebastian Reichel  * ab8500_charger_usb_en() - enable usb charging
15608c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
15618c0984e5SSebastian Reichel  * @enable:	enable/disable flag
15628c0984e5SSebastian Reichel  * @vset:	charging voltage
1563*83e5aa77SLinus Walleij  * @ich_out_ua:	charger output current in microampere
15648c0984e5SSebastian Reichel  *
15658c0984e5SSebastian Reichel  * Enable/Disable USB charging and turns on/off the charging led respectively.
15668c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
15678c0984e5SSebastian Reichel  */
15688c0984e5SSebastian Reichel static int ab8500_charger_usb_en(struct ux500_charger *charger,
1569*83e5aa77SLinus Walleij 	int enable, int vset, int ich_out_ua)
15708c0984e5SSebastian Reichel {
15718c0984e5SSebastian Reichel 	int ret;
15728c0984e5SSebastian Reichel 	int volt_index;
15738c0984e5SSebastian Reichel 	int curr_index;
15748c0984e5SSebastian Reichel 	u8 overshoot = 0;
15758c0984e5SSebastian Reichel 
15768c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
15778c0984e5SSebastian Reichel 
15788c0984e5SSebastian Reichel 	if (enable) {
15798c0984e5SSebastian Reichel 		/* Check if USB is connected */
15808c0984e5SSebastian Reichel 		if (!di->usb.charger_connected) {
15818c0984e5SSebastian Reichel 			dev_err(di->dev, "USB charger not connected\n");
15828c0984e5SSebastian Reichel 			return -ENXIO;
15838c0984e5SSebastian Reichel 		}
15848c0984e5SSebastian Reichel 
15858c0984e5SSebastian Reichel 		/*
15868c0984e5SSebastian Reichel 		 * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
15878c0984e5SSebastian Reichel 		 * will be triggered every time we enable the VDD ADC supply.
15888c0984e5SSebastian Reichel 		 * This will turn off charging for a short while.
15898c0984e5SSebastian Reichel 		 * It can be avoided by having the supply on when
15908c0984e5SSebastian Reichel 		 * there is a charger enabled. Normally the VDD ADC supply
1591ddb74e98SAshish Chavan 		 * is enabled every time a GPADC conversion is triggered.
1592ddb74e98SAshish Chavan 		 * We will force it to be enabled from this driver to have
1593ddb74e98SAshish Chavan 		 * the GPADC module independent of the AB8500 chargers
15948c0984e5SSebastian Reichel 		 */
15958c0984e5SSebastian Reichel 		if (!di->vddadc_en_usb) {
15968c0984e5SSebastian Reichel 			ret = regulator_enable(di->regu);
15978c0984e5SSebastian Reichel 			if (ret)
15988c0984e5SSebastian Reichel 				dev_warn(di->dev,
15998c0984e5SSebastian Reichel 					"Failed to enable regulator\n");
16008c0984e5SSebastian Reichel 			else
16018c0984e5SSebastian Reichel 				di->vddadc_en_usb = true;
16028c0984e5SSebastian Reichel 		}
16038c0984e5SSebastian Reichel 
16048c0984e5SSebastian Reichel 		/* Enable USB charging */
1605*83e5aa77SLinus Walleij 		dev_dbg(di->dev, "Enable USB: %d mV %d uA\n", vset, ich_out_ua);
16068c0984e5SSebastian Reichel 
16078c0984e5SSebastian Reichel 		/* Check if the requested voltage or current is valid */
16088c0984e5SSebastian Reichel 		volt_index = ab8500_voltage_to_regval(vset);
1609*83e5aa77SLinus Walleij 		curr_index = ab8500_current_to_regval(di, ich_out_ua);
16108c0984e5SSebastian Reichel 		if (volt_index < 0 || curr_index < 0) {
16118c0984e5SSebastian Reichel 			dev_err(di->dev,
16128c0984e5SSebastian Reichel 				"Charger voltage or current too high, "
16138c0984e5SSebastian Reichel 				"charging not started\n");
16148c0984e5SSebastian Reichel 			return -ENXIO;
16158c0984e5SSebastian Reichel 		}
16168c0984e5SSebastian Reichel 
1617ddb74e98SAshish Chavan 		/*
1618ddb74e98SAshish Chavan 		 * ChVoltLevel: max voltage up to which battery can be
1619ddb74e98SAshish Chavan 		 * charged
1620ddb74e98SAshish Chavan 		 */
16218c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
16228c0984e5SSebastian Reichel 			AB8500_CH_VOLT_LVL_REG, (u8) volt_index);
16238c0984e5SSebastian Reichel 		if (ret) {
16248c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
16258c0984e5SSebastian Reichel 			return ret;
16268c0984e5SSebastian Reichel 		}
16278c0984e5SSebastian Reichel 		/* Check if VBAT overshoot control should be enabled */
16288c0984e5SSebastian Reichel 		if (!di->bm->enable_overshoot)
16298c0984e5SSebastian Reichel 			overshoot = USB_CHG_NO_OVERSHOOT_ENA_N;
16308c0984e5SSebastian Reichel 
16318c0984e5SSebastian Reichel 		/* Enable USB Charger */
16328c0984e5SSebastian Reichel 		dev_dbg(di->dev,
16338c0984e5SSebastian Reichel 			"Enabling USB with write to AB8500_USBCH_CTRL1_REG\n");
16348c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
16358c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot);
16368c0984e5SSebastian Reichel 		if (ret) {
16378c0984e5SSebastian Reichel 			dev_err(di->dev, "%s write failed\n", __func__);
16388c0984e5SSebastian Reichel 			return ret;
16398c0984e5SSebastian Reichel 		}
16408c0984e5SSebastian Reichel 
16418c0984e5SSebastian Reichel 		/* If success power on charging LED indication */
16428c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, true);
16438c0984e5SSebastian Reichel 		if (ret < 0)
16448c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to enable LED\n");
16458c0984e5SSebastian Reichel 
16468c0984e5SSebastian Reichel 		di->usb.charger_online = 1;
16478c0984e5SSebastian Reichel 
16488c0984e5SSebastian Reichel 		/* USBChInputCurr: current that can be drawn from the usb */
16498c0984e5SSebastian Reichel 		ret = ab8500_charger_set_vbus_in_curr(di,
1650*83e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
16518c0984e5SSebastian Reichel 		if (ret) {
16528c0984e5SSebastian Reichel 			dev_err(di->dev, "setting USBChInputCurr failed\n");
16538c0984e5SSebastian Reichel 			return ret;
16548c0984e5SSebastian Reichel 		}
16558c0984e5SSebastian Reichel 
16568c0984e5SSebastian Reichel 		/* ChOutputCurentLevel: protected output current */
1657*83e5aa77SLinus Walleij 		ret = ab8500_charger_set_output_curr(di, ich_out_ua);
16588c0984e5SSebastian Reichel 		if (ret) {
16598c0984e5SSebastian Reichel 			dev_err(di->dev, "%s "
16608c0984e5SSebastian Reichel 				"Failed to set ChOutputCurentLevel\n",
16618c0984e5SSebastian Reichel 				__func__);
16628c0984e5SSebastian Reichel 			return ret;
16638c0984e5SSebastian Reichel 		}
16648c0984e5SSebastian Reichel 
16658c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ);
16668c0984e5SSebastian Reichel 
16678c0984e5SSebastian Reichel 	} else {
16688c0984e5SSebastian Reichel 		/* Disable USB charging */
16698c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s Disabled USB charging\n", __func__);
16708c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
16718c0984e5SSebastian Reichel 			AB8500_CHARGER,
16728c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL1_REG, 0);
16738c0984e5SSebastian Reichel 		if (ret) {
16748c0984e5SSebastian Reichel 			dev_err(di->dev,
16758c0984e5SSebastian Reichel 				"%s write failed\n", __func__);
16768c0984e5SSebastian Reichel 			return ret;
16778c0984e5SSebastian Reichel 		}
16788c0984e5SSebastian Reichel 
16798c0984e5SSebastian Reichel 		ret = ab8500_charger_led_en(di, false);
16808c0984e5SSebastian Reichel 		if (ret < 0)
16818c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to disable LED\n");
16828c0984e5SSebastian Reichel 		/* USBChInputCurr: current that can be drawn from the usb */
16838c0984e5SSebastian Reichel 		ret = ab8500_charger_set_vbus_in_curr(di, 0);
16848c0984e5SSebastian Reichel 		if (ret) {
16858c0984e5SSebastian Reichel 			dev_err(di->dev, "setting USBChInputCurr failed\n");
16868c0984e5SSebastian Reichel 			return ret;
16878c0984e5SSebastian Reichel 		}
16888c0984e5SSebastian Reichel 
16898c0984e5SSebastian Reichel 		/* ChOutputCurentLevel: protected output current */
16908c0984e5SSebastian Reichel 		ret = ab8500_charger_set_output_curr(di, 0);
16918c0984e5SSebastian Reichel 		if (ret) {
16928c0984e5SSebastian Reichel 			dev_err(di->dev, "%s "
16938c0984e5SSebastian Reichel 				"Failed to reset ChOutputCurentLevel\n",
16948c0984e5SSebastian Reichel 				__func__);
16958c0984e5SSebastian Reichel 			return ret;
16968c0984e5SSebastian Reichel 		}
16978c0984e5SSebastian Reichel 		di->usb.charger_online = 0;
16988c0984e5SSebastian Reichel 		di->usb.wd_expired = false;
16998c0984e5SSebastian Reichel 
17008c0984e5SSebastian Reichel 		/* Disable regulator if enabled */
17018c0984e5SSebastian Reichel 		if (di->vddadc_en_usb) {
17028c0984e5SSebastian Reichel 			regulator_disable(di->regu);
17038c0984e5SSebastian Reichel 			di->vddadc_en_usb = false;
17048c0984e5SSebastian Reichel 		}
17058c0984e5SSebastian Reichel 
17068c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s Disabled USB charging\n", __func__);
17078c0984e5SSebastian Reichel 
17088c0984e5SSebastian Reichel 		/* Cancel any pending Vbat check work */
17098c0984e5SSebastian Reichel 		cancel_delayed_work(&di->check_vbat_work);
17108c0984e5SSebastian Reichel 
17118c0984e5SSebastian Reichel 	}
17128c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
17138c0984e5SSebastian Reichel 
17148c0984e5SSebastian Reichel 	return ret;
17158c0984e5SSebastian Reichel }
17168c0984e5SSebastian Reichel 
17178c0984e5SSebastian Reichel static int ab8500_external_charger_prepare(struct notifier_block *charger_nb,
17188c0984e5SSebastian Reichel 				unsigned long event, void *data)
17198c0984e5SSebastian Reichel {
17208c0984e5SSebastian Reichel 	int ret;
17218c0984e5SSebastian Reichel 	struct device *dev = data;
17228c0984e5SSebastian Reichel 	/*Toggle External charger control pin*/
17238c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
17248c0984e5SSebastian Reichel 				  AB8500_SYS_CHARGER_CONTROL_REG,
17258c0984e5SSebastian Reichel 				  EXTERNAL_CHARGER_DISABLE_REG_VAL);
17268c0984e5SSebastian Reichel 	if (ret < 0) {
17278c0984e5SSebastian Reichel 		dev_err(dev, "write reg failed %d\n", ret);
17288c0984e5SSebastian Reichel 		goto out;
17298c0984e5SSebastian Reichel 	}
17308c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
17318c0984e5SSebastian Reichel 				  AB8500_SYS_CHARGER_CONTROL_REG,
17328c0984e5SSebastian Reichel 				  EXTERNAL_CHARGER_ENABLE_REG_VAL);
17338c0984e5SSebastian Reichel 	if (ret < 0)
17348c0984e5SSebastian Reichel 		dev_err(dev, "Write reg failed %d\n", ret);
17358c0984e5SSebastian Reichel 
17368c0984e5SSebastian Reichel out:
17378c0984e5SSebastian Reichel 	return ret;
17388c0984e5SSebastian Reichel }
17398c0984e5SSebastian Reichel 
17408c0984e5SSebastian Reichel /**
17418c0984e5SSebastian Reichel  * ab8500_charger_usb_check_enable() - enable usb charging
17428c0984e5SSebastian Reichel  * @charger:	pointer to the ux500_charger structure
17438c0984e5SSebastian Reichel  * @vset:	charging voltage
1744*83e5aa77SLinus Walleij  * @iset_ua:	charger output current in microampere
17458c0984e5SSebastian Reichel  *
17468c0984e5SSebastian Reichel  * Check if the VBUS charger has been disconnected and reconnected without
17478c0984e5SSebastian Reichel  * AB8500 rising an interrupt. Returns 0 on success.
17488c0984e5SSebastian Reichel  */
17498c0984e5SSebastian Reichel static int ab8500_charger_usb_check_enable(struct ux500_charger *charger,
1750*83e5aa77SLinus Walleij 	int vset, int iset_ua)
17518c0984e5SSebastian Reichel {
17528c0984e5SSebastian Reichel 	u8 usbch_ctrl1 = 0;
17538c0984e5SSebastian Reichel 	int ret = 0;
17548c0984e5SSebastian Reichel 
17558c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
17568c0984e5SSebastian Reichel 
17578c0984e5SSebastian Reichel 	if (!di->usb.charger_connected)
17588c0984e5SSebastian Reichel 		return ret;
17598c0984e5SSebastian Reichel 
17608c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
17618c0984e5SSebastian Reichel 				AB8500_USBCH_CTRL1_REG, &usbch_ctrl1);
17628c0984e5SSebastian Reichel 	if (ret < 0) {
17638c0984e5SSebastian Reichel 		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
17648c0984e5SSebastian Reichel 		return ret;
17658c0984e5SSebastian Reichel 	}
17668c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1);
17678c0984e5SSebastian Reichel 
17688c0984e5SSebastian Reichel 	if (!(usbch_ctrl1 & USB_CH_ENA)) {
17698c0984e5SSebastian Reichel 		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
17708c0984e5SSebastian Reichel 
17718c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
17728c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_CHARGER_CTRL,
17738c0984e5SSebastian Reichel 					DROP_COUNT_RESET, DROP_COUNT_RESET);
17748c0984e5SSebastian Reichel 		if (ret < 0) {
17758c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
17768c0984e5SSebastian Reichel 			return ret;
17778c0984e5SSebastian Reichel 		}
17788c0984e5SSebastian Reichel 
1779*83e5aa77SLinus Walleij 		ret = ab8500_charger_usb_en(&di->usb_chg, true, vset, iset_ua);
17808c0984e5SSebastian Reichel 		if (ret < 0) {
17818c0984e5SSebastian Reichel 			dev_err(di->dev, "Failed to enable VBUS charger %d\n",
17828c0984e5SSebastian Reichel 					__LINE__);
17838c0984e5SSebastian Reichel 			return ret;
17848c0984e5SSebastian Reichel 		}
17858c0984e5SSebastian Reichel 	}
17868c0984e5SSebastian Reichel 	return ret;
17878c0984e5SSebastian Reichel }
17888c0984e5SSebastian Reichel 
17898c0984e5SSebastian Reichel /**
17908c0984e5SSebastian Reichel  * ab8500_charger_ac_check_enable() - enable usb charging
17918c0984e5SSebastian Reichel  * @charger:	pointer to the ux500_charger structure
17928c0984e5SSebastian Reichel  * @vset:	charging voltage
1793*83e5aa77SLinus Walleij  * @iset_ua:	charger output current in micrompere
17948c0984e5SSebastian Reichel  *
17958c0984e5SSebastian Reichel  * Check if the AC charger has been disconnected and reconnected without
17968c0984e5SSebastian Reichel  * AB8500 rising an interrupt. Returns 0 on success.
17978c0984e5SSebastian Reichel  */
17988c0984e5SSebastian Reichel static int ab8500_charger_ac_check_enable(struct ux500_charger *charger,
1799*83e5aa77SLinus Walleij 	int vset, int iset_ua)
18008c0984e5SSebastian Reichel {
18018c0984e5SSebastian Reichel 	u8 mainch_ctrl1 = 0;
18028c0984e5SSebastian Reichel 	int ret = 0;
18038c0984e5SSebastian Reichel 
18048c0984e5SSebastian Reichel 	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
18058c0984e5SSebastian Reichel 
18068c0984e5SSebastian Reichel 	if (!di->ac.charger_connected)
18078c0984e5SSebastian Reichel 		return ret;
18088c0984e5SSebastian Reichel 
18098c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
18108c0984e5SSebastian Reichel 				AB8500_MCH_CTRL1, &mainch_ctrl1);
18118c0984e5SSebastian Reichel 	if (ret < 0) {
18128c0984e5SSebastian Reichel 		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
18138c0984e5SSebastian Reichel 		return ret;
18148c0984e5SSebastian Reichel 	}
18158c0984e5SSebastian Reichel 	dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1);
18168c0984e5SSebastian Reichel 
18178c0984e5SSebastian Reichel 	if (!(mainch_ctrl1 & MAIN_CH_ENA)) {
18188c0984e5SSebastian Reichel 		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
18198c0984e5SSebastian Reichel 
18208c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
18218c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_CHARGER_CTRL,
18228c0984e5SSebastian Reichel 					DROP_COUNT_RESET, DROP_COUNT_RESET);
18238c0984e5SSebastian Reichel 
18248c0984e5SSebastian Reichel 		if (ret < 0) {
18258c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
18268c0984e5SSebastian Reichel 			return ret;
18278c0984e5SSebastian Reichel 		}
18288c0984e5SSebastian Reichel 
1829*83e5aa77SLinus Walleij 		ret = ab8500_charger_ac_en(&di->usb_chg, true, vset, iset_ua);
18308c0984e5SSebastian Reichel 		if (ret < 0) {
18318c0984e5SSebastian Reichel 			dev_err(di->dev, "failed to enable AC charger %d\n",
18328c0984e5SSebastian Reichel 				__LINE__);
18338c0984e5SSebastian Reichel 			return ret;
18348c0984e5SSebastian Reichel 		}
18358c0984e5SSebastian Reichel 	}
18368c0984e5SSebastian Reichel 	return ret;
18378c0984e5SSebastian Reichel }
18388c0984e5SSebastian Reichel 
18398c0984e5SSebastian Reichel /**
18408c0984e5SSebastian Reichel  * ab8500_charger_watchdog_kick() - kick charger watchdog
18418c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
18428c0984e5SSebastian Reichel  *
18438c0984e5SSebastian Reichel  * Kick charger watchdog
18448c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
18458c0984e5SSebastian Reichel  */
18468c0984e5SSebastian Reichel static int ab8500_charger_watchdog_kick(struct ux500_charger *charger)
18478c0984e5SSebastian Reichel {
18488c0984e5SSebastian Reichel 	int ret;
18498c0984e5SSebastian Reichel 	struct ab8500_charger *di;
18508c0984e5SSebastian Reichel 
18518c0984e5SSebastian Reichel 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
18528c0984e5SSebastian Reichel 		di = to_ab8500_charger_ac_device_info(charger);
18538c0984e5SSebastian Reichel 	else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
18548c0984e5SSebastian Reichel 		di = to_ab8500_charger_usb_device_info(charger);
18558c0984e5SSebastian Reichel 	else
18568c0984e5SSebastian Reichel 		return -ENXIO;
18578c0984e5SSebastian Reichel 
18588c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
18598c0984e5SSebastian Reichel 		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
18608c0984e5SSebastian Reichel 	if (ret)
18618c0984e5SSebastian Reichel 		dev_err(di->dev, "Failed to kick WD!\n");
18628c0984e5SSebastian Reichel 
18638c0984e5SSebastian Reichel 	return ret;
18648c0984e5SSebastian Reichel }
18658c0984e5SSebastian Reichel 
18668c0984e5SSebastian Reichel /**
18678c0984e5SSebastian Reichel  * ab8500_charger_update_charger_current() - update charger current
1868*83e5aa77SLinus Walleij  * @charger:		pointer to the ab8500_charger structure
1869*83e5aa77SLinus Walleij  * @ich_out_ua:		desired output current in microampere
18708c0984e5SSebastian Reichel  *
18718c0984e5SSebastian Reichel  * Update the charger output current for the specified charger
18728c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
18738c0984e5SSebastian Reichel  */
18748c0984e5SSebastian Reichel static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
1875*83e5aa77SLinus Walleij 		int ich_out_ua)
18768c0984e5SSebastian Reichel {
18778c0984e5SSebastian Reichel 	int ret;
18788c0984e5SSebastian Reichel 	struct ab8500_charger *di;
18798c0984e5SSebastian Reichel 
18808c0984e5SSebastian Reichel 	if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
18818c0984e5SSebastian Reichel 		di = to_ab8500_charger_ac_device_info(charger);
18828c0984e5SSebastian Reichel 	else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
18838c0984e5SSebastian Reichel 		di = to_ab8500_charger_usb_device_info(charger);
18848c0984e5SSebastian Reichel 	else
18858c0984e5SSebastian Reichel 		return -ENXIO;
18868c0984e5SSebastian Reichel 
1887*83e5aa77SLinus Walleij 	ret = ab8500_charger_set_output_curr(di, ich_out_ua);
18888c0984e5SSebastian Reichel 	if (ret) {
18898c0984e5SSebastian Reichel 		dev_err(di->dev, "%s "
18908c0984e5SSebastian Reichel 			"Failed to set ChOutputCurentLevel\n",
18918c0984e5SSebastian Reichel 			__func__);
18928c0984e5SSebastian Reichel 		return ret;
18938c0984e5SSebastian Reichel 	}
18948c0984e5SSebastian Reichel 
18958c0984e5SSebastian Reichel 	/* Reset the main and usb drop input current measurement counter */
18968c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
18978c0984e5SSebastian Reichel 				AB8500_CHARGER_CTRL, DROP_COUNT_RESET);
18988c0984e5SSebastian Reichel 	if (ret) {
18998c0984e5SSebastian Reichel 		dev_err(di->dev, "%s write failed\n", __func__);
19008c0984e5SSebastian Reichel 		return ret;
19018c0984e5SSebastian Reichel 	}
19028c0984e5SSebastian Reichel 
19038c0984e5SSebastian Reichel 	return ret;
19048c0984e5SSebastian Reichel }
19058c0984e5SSebastian Reichel 
19068c0984e5SSebastian Reichel static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
19078c0984e5SSebastian Reichel {
19088c0984e5SSebastian Reichel 	struct power_supply *psy;
19098c0984e5SSebastian Reichel 	struct power_supply *ext = dev_get_drvdata(dev);
19108c0984e5SSebastian Reichel 	const char **supplicants = (const char **)ext->supplied_to;
19118c0984e5SSebastian Reichel 	struct ab8500_charger *di;
19128c0984e5SSebastian Reichel 	union power_supply_propval ret;
19138c0984e5SSebastian Reichel 	int j;
19148c0984e5SSebastian Reichel 	struct ux500_charger *usb_chg;
19158c0984e5SSebastian Reichel 
19168c0984e5SSebastian Reichel 	usb_chg = (struct ux500_charger *)data;
19178c0984e5SSebastian Reichel 	psy = usb_chg->psy;
19188c0984e5SSebastian Reichel 
19198c0984e5SSebastian Reichel 	di = to_ab8500_charger_usb_device_info(usb_chg);
19208c0984e5SSebastian Reichel 
19218c0984e5SSebastian Reichel 	/* For all psy where the driver name appears in any supplied_to */
19228c0984e5SSebastian Reichel 	j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
19238c0984e5SSebastian Reichel 	if (j < 0)
19248c0984e5SSebastian Reichel 		return 0;
19258c0984e5SSebastian Reichel 
19268c0984e5SSebastian Reichel 	/* Go through all properties for the psy */
19278c0984e5SSebastian Reichel 	for (j = 0; j < ext->desc->num_properties; j++) {
19288c0984e5SSebastian Reichel 		enum power_supply_property prop;
19298c0984e5SSebastian Reichel 		prop = ext->desc->properties[j];
19308c0984e5SSebastian Reichel 
19318c0984e5SSebastian Reichel 		if (power_supply_get_property(ext, prop, &ret))
19328c0984e5SSebastian Reichel 			continue;
19338c0984e5SSebastian Reichel 
19348c0984e5SSebastian Reichel 		switch (prop) {
19358c0984e5SSebastian Reichel 		case POWER_SUPPLY_PROP_VOLTAGE_NOW:
19368c0984e5SSebastian Reichel 			switch (ext->desc->type) {
19378c0984e5SSebastian Reichel 			case POWER_SUPPLY_TYPE_BATTERY:
19388c0984e5SSebastian Reichel 				di->vbat = ret.intval / 1000;
19398c0984e5SSebastian Reichel 				break;
19408c0984e5SSebastian Reichel 			default:
19418c0984e5SSebastian Reichel 				break;
19428c0984e5SSebastian Reichel 			}
19438c0984e5SSebastian Reichel 			break;
19448c0984e5SSebastian Reichel 		default:
19458c0984e5SSebastian Reichel 			break;
19468c0984e5SSebastian Reichel 		}
19478c0984e5SSebastian Reichel 	}
19488c0984e5SSebastian Reichel 	return 0;
19498c0984e5SSebastian Reichel }
19508c0984e5SSebastian Reichel 
19518c0984e5SSebastian Reichel /**
19528c0984e5SSebastian Reichel  * ab8500_charger_check_vbat_work() - keep vbus current within spec
19538c0984e5SSebastian Reichel  * @work	pointer to the work_struct structure
19548c0984e5SSebastian Reichel  *
19558c0984e5SSebastian Reichel  * Due to a asic bug it is necessary to lower the input current to the vbus
19568c0984e5SSebastian Reichel  * charger when charging with at some specific levels. This issue is only valid
19578c0984e5SSebastian Reichel  * for below a certain battery voltage. This function makes sure that the
19588c0984e5SSebastian Reichel  * the allowed current limit isn't exceeded.
19598c0984e5SSebastian Reichel  */
19608c0984e5SSebastian Reichel static void ab8500_charger_check_vbat_work(struct work_struct *work)
19618c0984e5SSebastian Reichel {
19628c0984e5SSebastian Reichel 	int t = 10;
19638c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
19648c0984e5SSebastian Reichel 		struct ab8500_charger, check_vbat_work.work);
19658c0984e5SSebastian Reichel 
19668c0984e5SSebastian Reichel 	class_for_each_device(power_supply_class, NULL,
19678c0984e5SSebastian Reichel 		di->usb_chg.psy, ab8500_charger_get_ext_psy_data);
19688c0984e5SSebastian Reichel 
19698c0984e5SSebastian Reichel 	/* First run old_vbat is 0. */
19708c0984e5SSebastian Reichel 	if (di->old_vbat == 0)
19718c0984e5SSebastian Reichel 		di->old_vbat = di->vbat;
19728c0984e5SSebastian Reichel 
19738c0984e5SSebastian Reichel 	if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED &&
19748c0984e5SSebastian Reichel 		di->vbat <= VBAT_TRESH_IP_CUR_RED) ||
19758c0984e5SSebastian Reichel 		(di->old_vbat > VBAT_TRESH_IP_CUR_RED &&
19768c0984e5SSebastian Reichel 		di->vbat > VBAT_TRESH_IP_CUR_RED))) {
19778c0984e5SSebastian Reichel 
19788c0984e5SSebastian Reichel 		dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d,"
1979*83e5aa77SLinus Walleij 			" old: %d\n", di->max_usb_in_curr.usb_type_max_ua,
19808c0984e5SSebastian Reichel 			di->vbat, di->old_vbat);
19818c0984e5SSebastian Reichel 		ab8500_charger_set_vbus_in_curr(di,
1982*83e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
19838c0984e5SSebastian Reichel 		power_supply_changed(di->usb_chg.psy);
19848c0984e5SSebastian Reichel 	}
19858c0984e5SSebastian Reichel 
19868c0984e5SSebastian Reichel 	di->old_vbat = di->vbat;
19878c0984e5SSebastian Reichel 
19888c0984e5SSebastian Reichel 	/*
19898c0984e5SSebastian Reichel 	 * No need to check the battery voltage every second when not close to
19908c0984e5SSebastian Reichel 	 * the threshold.
19918c0984e5SSebastian Reichel 	 */
19928c0984e5SSebastian Reichel 	if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) &&
19938c0984e5SSebastian Reichel 		(di->vbat > (VBAT_TRESH_IP_CUR_RED - 100)))
19948c0984e5SSebastian Reichel 			t = 1;
19958c0984e5SSebastian Reichel 
19968c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ);
19978c0984e5SSebastian Reichel }
19988c0984e5SSebastian Reichel 
19998c0984e5SSebastian Reichel /**
20008c0984e5SSebastian Reichel  * ab8500_charger_check_hw_failure_work() - check main charger failure
20018c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20028c0984e5SSebastian Reichel  *
20038c0984e5SSebastian Reichel  * Work queue function for checking the main charger status
20048c0984e5SSebastian Reichel  */
20058c0984e5SSebastian Reichel static void ab8500_charger_check_hw_failure_work(struct work_struct *work)
20068c0984e5SSebastian Reichel {
20078c0984e5SSebastian Reichel 	int ret;
20088c0984e5SSebastian Reichel 	u8 reg_value;
20098c0984e5SSebastian Reichel 
20108c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20118c0984e5SSebastian Reichel 		struct ab8500_charger, check_hw_failure_work.work);
20128c0984e5SSebastian Reichel 
20138c0984e5SSebastian Reichel 	/* Check if the status bits for HW failure is still active */
20148c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok) {
20158c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
20168c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
20178c0984e5SSebastian Reichel 		if (ret < 0) {
20188c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
20198c0984e5SSebastian Reichel 			return;
20208c0984e5SSebastian Reichel 		}
20218c0984e5SSebastian Reichel 		if (!(reg_value & MAIN_CH_NOK)) {
20228c0984e5SSebastian Reichel 			di->flags.mainextchnotok = false;
20238c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->ac_chg.psy);
20248c0984e5SSebastian Reichel 		}
20258c0984e5SSebastian Reichel 	}
20268c0984e5SSebastian Reichel 	if (di->flags.vbus_ovv) {
20278c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
20288c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG,
20298c0984e5SSebastian Reichel 			&reg_value);
20308c0984e5SSebastian Reichel 		if (ret < 0) {
20318c0984e5SSebastian Reichel 			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
20328c0984e5SSebastian Reichel 			return;
20338c0984e5SSebastian Reichel 		}
20348c0984e5SSebastian Reichel 		if (!(reg_value & VBUS_OVV_TH)) {
20358c0984e5SSebastian Reichel 			di->flags.vbus_ovv = false;
20368c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
20378c0984e5SSebastian Reichel 		}
20388c0984e5SSebastian Reichel 	}
20398c0984e5SSebastian Reichel 	/* If we still have a failure, schedule a new check */
20408c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
20418c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
20428c0984e5SSebastian Reichel 			&di->check_hw_failure_work, round_jiffies(HZ));
20438c0984e5SSebastian Reichel 	}
20448c0984e5SSebastian Reichel }
20458c0984e5SSebastian Reichel 
20468c0984e5SSebastian Reichel /**
20478c0984e5SSebastian Reichel  * ab8500_charger_kick_watchdog_work() - kick the watchdog
20488c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20498c0984e5SSebastian Reichel  *
20508c0984e5SSebastian Reichel  * Work queue function for kicking the charger watchdog.
20518c0984e5SSebastian Reichel  *
20528c0984e5SSebastian Reichel  * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
2053ddb74e98SAshish Chavan  * logic. That means we have to continuously kick the charger
20548c0984e5SSebastian Reichel  * watchdog even when no charger is connected. This is only
20558c0984e5SSebastian Reichel  * valid once the AC charger has been enabled. This is
20568c0984e5SSebastian Reichel  * a bug that is not handled by the algorithm and the
20578c0984e5SSebastian Reichel  * watchdog have to be kicked by the charger driver
20588c0984e5SSebastian Reichel  * when the AC charger is disabled
20598c0984e5SSebastian Reichel  */
20608c0984e5SSebastian Reichel static void ab8500_charger_kick_watchdog_work(struct work_struct *work)
20618c0984e5SSebastian Reichel {
20628c0984e5SSebastian Reichel 	int ret;
20638c0984e5SSebastian Reichel 
20648c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20658c0984e5SSebastian Reichel 		struct ab8500_charger, kick_wd_work.work);
20668c0984e5SSebastian Reichel 
20678c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
20688c0984e5SSebastian Reichel 		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
20698c0984e5SSebastian Reichel 	if (ret)
20708c0984e5SSebastian Reichel 		dev_err(di->dev, "Failed to kick WD!\n");
20718c0984e5SSebastian Reichel 
20728c0984e5SSebastian Reichel 	/* Schedule a new watchdog kick */
20738c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
20748c0984e5SSebastian Reichel 		&di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL));
20758c0984e5SSebastian Reichel }
20768c0984e5SSebastian Reichel 
20778c0984e5SSebastian Reichel /**
20788c0984e5SSebastian Reichel  * ab8500_charger_ac_work() - work to get and set main charger status
20798c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
20808c0984e5SSebastian Reichel  *
20818c0984e5SSebastian Reichel  * Work queue function for checking the main charger status
20828c0984e5SSebastian Reichel  */
20838c0984e5SSebastian Reichel static void ab8500_charger_ac_work(struct work_struct *work)
20848c0984e5SSebastian Reichel {
20858c0984e5SSebastian Reichel 	int ret;
20868c0984e5SSebastian Reichel 
20878c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
20888c0984e5SSebastian Reichel 		struct ab8500_charger, ac_work);
20898c0984e5SSebastian Reichel 
20908c0984e5SSebastian Reichel 	/*
20918c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
20928c0984e5SSebastian Reichel 	 * synchronously, we have the check if the main charger is
20938c0984e5SSebastian Reichel 	 * connected by reading the status register
20948c0984e5SSebastian Reichel 	 */
20958c0984e5SSebastian Reichel 	ret = ab8500_charger_detect_chargers(di, false);
20968c0984e5SSebastian Reichel 	if (ret < 0)
20978c0984e5SSebastian Reichel 		return;
20988c0984e5SSebastian Reichel 
20998c0984e5SSebastian Reichel 	if (ret & AC_PW_CONN) {
21008c0984e5SSebastian Reichel 		di->ac.charger_connected = 1;
21018c0984e5SSebastian Reichel 		di->ac_conn = true;
21028c0984e5SSebastian Reichel 	} else {
21038c0984e5SSebastian Reichel 		di->ac.charger_connected = 0;
21048c0984e5SSebastian Reichel 	}
21058c0984e5SSebastian Reichel 
21068c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
21078c0984e5SSebastian Reichel 	sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
21088c0984e5SSebastian Reichel }
21098c0984e5SSebastian Reichel 
21108c0984e5SSebastian Reichel static void ab8500_charger_usb_attached_work(struct work_struct *work)
21118c0984e5SSebastian Reichel {
21128c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
21138c0984e5SSebastian Reichel 						 struct ab8500_charger,
21148c0984e5SSebastian Reichel 						 usb_charger_attached_work.work);
21158c0984e5SSebastian Reichel 	int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC);
21168c0984e5SSebastian Reichel 	int ret, i;
21178c0984e5SSebastian Reichel 	u8 statval;
21188c0984e5SSebastian Reichel 
21198c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
21208c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
21218c0984e5SSebastian Reichel 							AB8500_CHARGER,
21228c0984e5SSebastian Reichel 							AB8500_CH_USBCH_STAT1_REG,
21238c0984e5SSebastian Reichel 							&statval);
21248c0984e5SSebastian Reichel 		if (ret < 0) {
21258c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
21268c0984e5SSebastian Reichel 			goto reschedule;
21278c0984e5SSebastian Reichel 		}
21288c0984e5SSebastian Reichel 		if ((statval & usbch) != usbch)
21298c0984e5SSebastian Reichel 			goto reschedule;
21308c0984e5SSebastian Reichel 
21318c0984e5SSebastian Reichel 		msleep(CHARGER_STATUS_POLL);
21328c0984e5SSebastian Reichel 	}
21338c0984e5SSebastian Reichel 
21348c0984e5SSebastian Reichel 	ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0);
21358c0984e5SSebastian Reichel 
21368c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
21378c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
21388c0984e5SSebastian Reichel 
21398c0984e5SSebastian Reichel 	return;
21408c0984e5SSebastian Reichel 
21418c0984e5SSebastian Reichel reschedule:
21428c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
21438c0984e5SSebastian Reichel 			   &di->usb_charger_attached_work,
21448c0984e5SSebastian Reichel 			   HZ);
21458c0984e5SSebastian Reichel }
21468c0984e5SSebastian Reichel 
21478c0984e5SSebastian Reichel static void ab8500_charger_ac_attached_work(struct work_struct *work)
21488c0984e5SSebastian Reichel {
21498c0984e5SSebastian Reichel 
21508c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
21518c0984e5SSebastian Reichel 						 struct ab8500_charger,
21528c0984e5SSebastian Reichel 						 ac_charger_attached_work.work);
21538c0984e5SSebastian Reichel 	int mainch = (MAIN_CH_STATUS2_MAINCHGDROP |
21548c0984e5SSebastian Reichel 		      MAIN_CH_STATUS2_MAINCHARGERDETDBNC);
21558c0984e5SSebastian Reichel 	int ret, i;
21568c0984e5SSebastian Reichel 	u8 statval;
21578c0984e5SSebastian Reichel 
21588c0984e5SSebastian Reichel 	for (i = 0; i < 10; i++) {
21598c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev,
21608c0984e5SSebastian Reichel 							AB8500_CHARGER,
21618c0984e5SSebastian Reichel 							AB8500_CH_STATUS2_REG,
21628c0984e5SSebastian Reichel 							&statval);
21638c0984e5SSebastian Reichel 		if (ret < 0) {
21648c0984e5SSebastian Reichel 			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
21658c0984e5SSebastian Reichel 			goto reschedule;
21668c0984e5SSebastian Reichel 		}
21678c0984e5SSebastian Reichel 
21688c0984e5SSebastian Reichel 		if ((statval & mainch) != mainch)
21698c0984e5SSebastian Reichel 			goto reschedule;
21708c0984e5SSebastian Reichel 
21718c0984e5SSebastian Reichel 		msleep(CHARGER_STATUS_POLL);
21728c0984e5SSebastian Reichel 	}
21738c0984e5SSebastian Reichel 
21748c0984e5SSebastian Reichel 	ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0);
21758c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
21768c0984e5SSebastian Reichel 
21778c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
21788c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
21798c0984e5SSebastian Reichel 
21808c0984e5SSebastian Reichel 	return;
21818c0984e5SSebastian Reichel 
21828c0984e5SSebastian Reichel reschedule:
21838c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq,
21848c0984e5SSebastian Reichel 			   &di->ac_charger_attached_work,
21858c0984e5SSebastian Reichel 			   HZ);
21868c0984e5SSebastian Reichel }
21878c0984e5SSebastian Reichel 
21888c0984e5SSebastian Reichel /**
21898c0984e5SSebastian Reichel  * ab8500_charger_detect_usb_type_work() - work to detect USB type
21908c0984e5SSebastian Reichel  * @work:	Pointer to the work_struct structure
21918c0984e5SSebastian Reichel  *
21928c0984e5SSebastian Reichel  * Detect the type of USB plugged
21938c0984e5SSebastian Reichel  */
21948c0984e5SSebastian Reichel static void ab8500_charger_detect_usb_type_work(struct work_struct *work)
21958c0984e5SSebastian Reichel {
21968c0984e5SSebastian Reichel 	int ret;
21978c0984e5SSebastian Reichel 
21988c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
21998c0984e5SSebastian Reichel 		struct ab8500_charger, detect_usb_type_work);
22008c0984e5SSebastian Reichel 
22018c0984e5SSebastian Reichel 	/*
22028c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
22038c0984e5SSebastian Reichel 	 * synchronously, we have the check if is
22048c0984e5SSebastian Reichel 	 * connected by reading the status register
22058c0984e5SSebastian Reichel 	 */
22068c0984e5SSebastian Reichel 	ret = ab8500_charger_detect_chargers(di, false);
22078c0984e5SSebastian Reichel 	if (ret < 0)
22088c0984e5SSebastian Reichel 		return;
22098c0984e5SSebastian Reichel 
22108c0984e5SSebastian Reichel 	if (!(ret & USB_PW_CONN)) {
22118c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__);
22128c0984e5SSebastian Reichel 		di->vbus_detected = false;
22138c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
22148c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
22158c0984e5SSebastian Reichel 	} else {
22168c0984e5SSebastian Reichel 		dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__);
22178c0984e5SSebastian Reichel 		di->vbus_detected = true;
22188c0984e5SSebastian Reichel 
22198c0984e5SSebastian Reichel 		if (is_ab8500_1p1_or_earlier(di->parent)) {
22208c0984e5SSebastian Reichel 			ret = ab8500_charger_detect_usb_type(di);
22218c0984e5SSebastian Reichel 			if (!ret) {
22228c0984e5SSebastian Reichel 				ab8500_charger_set_usb_connected(di, true);
22238c0984e5SSebastian Reichel 				ab8500_power_supply_changed(di,
22248c0984e5SSebastian Reichel 							    di->usb_chg.psy);
22258c0984e5SSebastian Reichel 			}
22268c0984e5SSebastian Reichel 		} else {
22278c0984e5SSebastian Reichel 			/*
22288c0984e5SSebastian Reichel 			 * For ABB cut2.0 and onwards we have an IRQ,
22298c0984e5SSebastian Reichel 			 * USB_LINK_STATUS that will be triggered when the USB
22308c0984e5SSebastian Reichel 			 * link status changes. The exception is USB connected
22318c0984e5SSebastian Reichel 			 * during startup. Then we don't get a
22328c0984e5SSebastian Reichel 			 * USB_LINK_STATUS IRQ
22338c0984e5SSebastian Reichel 			 */
22348c0984e5SSebastian Reichel 			if (di->vbus_detected_start) {
22358c0984e5SSebastian Reichel 				di->vbus_detected_start = false;
22368c0984e5SSebastian Reichel 				ret = ab8500_charger_detect_usb_type(di);
22378c0984e5SSebastian Reichel 				if (!ret) {
22388c0984e5SSebastian Reichel 					ab8500_charger_set_usb_connected(di,
22398c0984e5SSebastian Reichel 						true);
22408c0984e5SSebastian Reichel 					ab8500_power_supply_changed(di,
22418c0984e5SSebastian Reichel 						di->usb_chg.psy);
22428c0984e5SSebastian Reichel 				}
22438c0984e5SSebastian Reichel 			}
22448c0984e5SSebastian Reichel 		}
22458c0984e5SSebastian Reichel 	}
22468c0984e5SSebastian Reichel }
22478c0984e5SSebastian Reichel 
22488c0984e5SSebastian Reichel /**
22498c0984e5SSebastian Reichel  * ab8500_charger_usb_link_attach_work() - work to detect USB type
22508c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
22518c0984e5SSebastian Reichel  *
22528c0984e5SSebastian Reichel  * Detect the type of USB plugged
22538c0984e5SSebastian Reichel  */
22548c0984e5SSebastian Reichel static void ab8500_charger_usb_link_attach_work(struct work_struct *work)
22558c0984e5SSebastian Reichel {
22568c0984e5SSebastian Reichel 	struct ab8500_charger *di =
22578c0984e5SSebastian Reichel 		container_of(work, struct ab8500_charger, attach_work.work);
22588c0984e5SSebastian Reichel 	int ret;
22598c0984e5SSebastian Reichel 
22608c0984e5SSebastian Reichel 	/* Update maximum input current if USB enumeration is not detected */
22618c0984e5SSebastian Reichel 	if (!di->usb.charger_online) {
22628c0984e5SSebastian Reichel 		ret = ab8500_charger_set_vbus_in_curr(di,
2263*83e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
22648c0984e5SSebastian Reichel 		if (ret)
22658c0984e5SSebastian Reichel 			return;
22668c0984e5SSebastian Reichel 	}
22678c0984e5SSebastian Reichel 
22688c0984e5SSebastian Reichel 	ab8500_charger_set_usb_connected(di, true);
22698c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
22708c0984e5SSebastian Reichel }
22718c0984e5SSebastian Reichel 
22728c0984e5SSebastian Reichel /**
22738c0984e5SSebastian Reichel  * ab8500_charger_usb_link_status_work() - work to detect USB type
22748c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
22758c0984e5SSebastian Reichel  *
22768c0984e5SSebastian Reichel  * Detect the type of USB plugged
22778c0984e5SSebastian Reichel  */
22788c0984e5SSebastian Reichel static void ab8500_charger_usb_link_status_work(struct work_struct *work)
22798c0984e5SSebastian Reichel {
22808c0984e5SSebastian Reichel 	int detected_chargers;
22818c0984e5SSebastian Reichel 	int ret;
22828c0984e5SSebastian Reichel 	u8 val;
22838c0984e5SSebastian Reichel 	u8 link_status;
22848c0984e5SSebastian Reichel 
22858c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
22868c0984e5SSebastian Reichel 		struct ab8500_charger, usb_link_status_work);
22878c0984e5SSebastian Reichel 
22888c0984e5SSebastian Reichel 	/*
22898c0984e5SSebastian Reichel 	 * Since we can't be sure that the events are received
22908c0984e5SSebastian Reichel 	 * synchronously, we have the check if  is
22918c0984e5SSebastian Reichel 	 * connected by reading the status register
22928c0984e5SSebastian Reichel 	 */
22938c0984e5SSebastian Reichel 	detected_chargers = ab8500_charger_detect_chargers(di, false);
22948c0984e5SSebastian Reichel 	if (detected_chargers < 0)
22958c0984e5SSebastian Reichel 		return;
22968c0984e5SSebastian Reichel 
22978c0984e5SSebastian Reichel 	/*
22988c0984e5SSebastian Reichel 	 * Some chargers that breaks the USB spec is
22998c0984e5SSebastian Reichel 	 * identified as invalid by AB8500 and it refuse
23008c0984e5SSebastian Reichel 	 * to start the charging process. but by jumping
2301ddb74e98SAshish Chavan 	 * through a few hoops it can be forced to start.
23028c0984e5SSebastian Reichel 	 */
23038c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
23048c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
23058c0984e5SSebastian Reichel 					AB8500_USB_LINE_STAT_REG, &val);
23068c0984e5SSebastian Reichel 	else
23078c0984e5SSebastian Reichel 		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
23088c0984e5SSebastian Reichel 					AB8500_USB_LINK1_STAT_REG, &val);
23098c0984e5SSebastian Reichel 
23108c0984e5SSebastian Reichel 	if (ret >= 0)
23118c0984e5SSebastian Reichel 		dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val);
23128c0984e5SSebastian Reichel 	else
23138c0984e5SSebastian Reichel 		dev_dbg(di->dev, "Error reading USB link status\n");
23148c0984e5SSebastian Reichel 
23158c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
23168c0984e5SSebastian Reichel 		link_status = AB8500_USB_LINK_STATUS;
23178c0984e5SSebastian Reichel 	else
23188c0984e5SSebastian Reichel 		link_status = AB8505_USB_LINK_STATUS;
23198c0984e5SSebastian Reichel 
23208c0984e5SSebastian Reichel 	if (detected_chargers & USB_PW_CONN) {
23218c0984e5SSebastian Reichel 		if (((val & link_status) >> USB_LINK_STATUS_SHIFT) ==
23228c0984e5SSebastian Reichel 				USB_STAT_NOT_VALID_LINK &&
23238c0984e5SSebastian Reichel 				di->invalid_charger_detect_state == 0) {
23248c0984e5SSebastian Reichel 			dev_dbg(di->dev,
23258c0984e5SSebastian Reichel 					"Invalid charger detected, state= 0\n");
23268c0984e5SSebastian Reichel 			/*Enable charger*/
23278c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23288c0984e5SSebastian Reichel 					AB8500_CHARGER, AB8500_USBCH_CTRL1_REG,
23298c0984e5SSebastian Reichel 					USB_CH_ENA, USB_CH_ENA);
23308c0984e5SSebastian Reichel 			/*Enable charger detection*/
23318c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23328c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
23338c0984e5SSebastian Reichel 					USB_CH_DET, USB_CH_DET);
23348c0984e5SSebastian Reichel 			di->invalid_charger_detect_state = 1;
23358c0984e5SSebastian Reichel 			/*exit and wait for new link status interrupt.*/
23368c0984e5SSebastian Reichel 			return;
23378c0984e5SSebastian Reichel 
23388c0984e5SSebastian Reichel 		}
23398c0984e5SSebastian Reichel 		if (di->invalid_charger_detect_state == 1) {
23408c0984e5SSebastian Reichel 			dev_dbg(di->dev,
23418c0984e5SSebastian Reichel 					"Invalid charger detected, state= 1\n");
23428c0984e5SSebastian Reichel 			/*Stop charger detection*/
23438c0984e5SSebastian Reichel 			abx500_mask_and_set_register_interruptible(di->dev,
23448c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
23458c0984e5SSebastian Reichel 					USB_CH_DET, 0x00);
23468c0984e5SSebastian Reichel 			/*Check link status*/
23478c0984e5SSebastian Reichel 			if (is_ab8500(di->parent))
23488c0984e5SSebastian Reichel 				ret = abx500_get_register_interruptible(di->dev,
23498c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINE_STAT_REG,
23508c0984e5SSebastian Reichel 					&val);
23518c0984e5SSebastian Reichel 			else
23528c0984e5SSebastian Reichel 				ret = abx500_get_register_interruptible(di->dev,
23538c0984e5SSebastian Reichel 					AB8500_USB, AB8500_USB_LINK1_STAT_REG,
23548c0984e5SSebastian Reichel 					&val);
23558c0984e5SSebastian Reichel 
23568c0984e5SSebastian Reichel 			dev_dbg(di->dev, "USB link status= 0x%02x\n",
23578c0984e5SSebastian Reichel 				(val & link_status) >> USB_LINK_STATUS_SHIFT);
23588c0984e5SSebastian Reichel 			di->invalid_charger_detect_state = 2;
23598c0984e5SSebastian Reichel 		}
23608c0984e5SSebastian Reichel 	} else {
23618c0984e5SSebastian Reichel 		di->invalid_charger_detect_state = 0;
23628c0984e5SSebastian Reichel 	}
23638c0984e5SSebastian Reichel 
23648c0984e5SSebastian Reichel 	if (!(detected_chargers & USB_PW_CONN)) {
23658c0984e5SSebastian Reichel 		di->vbus_detected = false;
23668c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
23678c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
23688c0984e5SSebastian Reichel 		return;
23698c0984e5SSebastian Reichel 	}
23708c0984e5SSebastian Reichel 
23718c0984e5SSebastian Reichel 	dev_dbg(di->dev,"%s di->vbus_detected = true\n",__func__);
23728c0984e5SSebastian Reichel 	di->vbus_detected = true;
23738c0984e5SSebastian Reichel 	ret = ab8500_charger_read_usb_type(di);
23748c0984e5SSebastian Reichel 	if (ret) {
23758c0984e5SSebastian Reichel 		if (ret == -ENXIO) {
23768c0984e5SSebastian Reichel 			/* No valid charger type detected */
23778c0984e5SSebastian Reichel 			ab8500_charger_set_usb_connected(di, false);
23788c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
23798c0984e5SSebastian Reichel 		}
23808c0984e5SSebastian Reichel 		return;
23818c0984e5SSebastian Reichel 	}
23828c0984e5SSebastian Reichel 
23838c0984e5SSebastian Reichel 	if (di->usb_device_is_unrecognised) {
23848c0984e5SSebastian Reichel 		dev_dbg(di->dev,
23858c0984e5SSebastian Reichel 			"Potential Legacy Charger device. "
23868c0984e5SSebastian Reichel 			"Delay work for %d msec for USB enum "
23878c0984e5SSebastian Reichel 			"to finish",
23888c0984e5SSebastian Reichel 			WAIT_ACA_RID_ENUMERATION);
23898c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
23908c0984e5SSebastian Reichel 				   &di->attach_work,
23918c0984e5SSebastian Reichel 				   msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION));
23928c0984e5SSebastian Reichel 	} else if (di->is_aca_rid == 1) {
23938c0984e5SSebastian Reichel 		/* Only wait once */
23948c0984e5SSebastian Reichel 		di->is_aca_rid++;
23958c0984e5SSebastian Reichel 		dev_dbg(di->dev,
23968c0984e5SSebastian Reichel 			"%s Wait %d msec for USB enum to finish",
23978c0984e5SSebastian Reichel 			__func__, 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 {
24028c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
24038c0984e5SSebastian Reichel 				   &di->attach_work,
24048c0984e5SSebastian Reichel 				   0);
24058c0984e5SSebastian Reichel 	}
24068c0984e5SSebastian Reichel }
24078c0984e5SSebastian Reichel 
24088c0984e5SSebastian Reichel static void ab8500_charger_usb_state_changed_work(struct work_struct *work)
24098c0984e5SSebastian Reichel {
24108c0984e5SSebastian Reichel 	int ret;
24118c0984e5SSebastian Reichel 	unsigned long flags;
24128c0984e5SSebastian Reichel 
24138c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
24148c0984e5SSebastian Reichel 		struct ab8500_charger, usb_state_changed_work.work);
24158c0984e5SSebastian Reichel 
24168c0984e5SSebastian Reichel 	if (!di->vbus_detected)	{
24178c0984e5SSebastian Reichel 		dev_dbg(di->dev,
24188c0984e5SSebastian Reichel 			"%s !di->vbus_detected\n",
24198c0984e5SSebastian Reichel 			__func__);
24208c0984e5SSebastian Reichel 		return;
24218c0984e5SSebastian Reichel 	}
24228c0984e5SSebastian Reichel 
24238c0984e5SSebastian Reichel 	spin_lock_irqsave(&di->usb_state.usb_lock, flags);
24248c0984e5SSebastian Reichel 	di->usb_state.state = di->usb_state.state_tmp;
2425*83e5aa77SLinus Walleij 	di->usb_state.usb_current_ua = di->usb_state.usb_current_tmp_ua;
24268c0984e5SSebastian Reichel 	spin_unlock_irqrestore(&di->usb_state.usb_lock, flags);
24278c0984e5SSebastian Reichel 
2428*83e5aa77SLinus Walleij 	dev_dbg(di->dev, "%s USB state: 0x%02x uA: %d\n",
2429*83e5aa77SLinus Walleij 		__func__, di->usb_state.state, di->usb_state.usb_current_ua);
24308c0984e5SSebastian Reichel 
24318c0984e5SSebastian Reichel 	switch (di->usb_state.state) {
24328c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESET_HS:
24338c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESET_FS:
24348c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_SUSPEND:
24358c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_MAX:
24368c0984e5SSebastian Reichel 		ab8500_charger_set_usb_connected(di, false);
24378c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
24388c0984e5SSebastian Reichel 		break;
24398c0984e5SSebastian Reichel 
24408c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_RESUME:
24418c0984e5SSebastian Reichel 		/*
24428c0984e5SSebastian Reichel 		 * when suspend->resume there should be delay
24438c0984e5SSebastian Reichel 		 * of 1sec for enabling charging
24448c0984e5SSebastian Reichel 		 */
24458c0984e5SSebastian Reichel 		msleep(1000);
2446df561f66SGustavo A. R. Silva 		fallthrough;
24478c0984e5SSebastian Reichel 	case AB8500_BM_USB_STATE_CONFIGURED:
24488c0984e5SSebastian Reichel 		/*
24498c0984e5SSebastian Reichel 		 * USB is configured, enable charging with the charging
24508c0984e5SSebastian Reichel 		 * input current obtained from USB driver
24518c0984e5SSebastian Reichel 		 */
24528c0984e5SSebastian Reichel 		if (!ab8500_charger_get_usb_cur(di)) {
24538c0984e5SSebastian Reichel 			/* Update maximum input current */
24548c0984e5SSebastian Reichel 			ret = ab8500_charger_set_vbus_in_curr(di,
2455*83e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
24568c0984e5SSebastian Reichel 			if (ret)
24578c0984e5SSebastian Reichel 				return;
24588c0984e5SSebastian Reichel 
24598c0984e5SSebastian Reichel 			ab8500_charger_set_usb_connected(di, true);
24608c0984e5SSebastian Reichel 			ab8500_power_supply_changed(di, di->usb_chg.psy);
24618c0984e5SSebastian Reichel 		}
24628c0984e5SSebastian Reichel 		break;
24638c0984e5SSebastian Reichel 
24648c0984e5SSebastian Reichel 	default:
24658c0984e5SSebastian Reichel 		break;
2466e15c54d2SMa Feng 	}
24678c0984e5SSebastian Reichel }
24688c0984e5SSebastian Reichel 
24698c0984e5SSebastian Reichel /**
24708c0984e5SSebastian Reichel  * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status
24718c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
24728c0984e5SSebastian Reichel  *
24738c0984e5SSebastian Reichel  * Work queue function for checking the USB charger Not OK status
24748c0984e5SSebastian Reichel  */
24758c0984e5SSebastian Reichel static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work)
24768c0984e5SSebastian Reichel {
24778c0984e5SSebastian Reichel 	int ret;
24788c0984e5SSebastian Reichel 	u8 reg_value;
24798c0984e5SSebastian Reichel 	bool prev_status;
24808c0984e5SSebastian Reichel 
24818c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
24828c0984e5SSebastian Reichel 		struct ab8500_charger, check_usbchgnotok_work.work);
24838c0984e5SSebastian Reichel 
24848c0984e5SSebastian Reichel 	/* Check if the status bit for usbchargernotok is still active */
24858c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
24868c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
24878c0984e5SSebastian Reichel 	if (ret < 0) {
24888c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
24898c0984e5SSebastian Reichel 		return;
24908c0984e5SSebastian Reichel 	}
24918c0984e5SSebastian Reichel 	prev_status = di->flags.usbchargernotok;
24928c0984e5SSebastian Reichel 
24938c0984e5SSebastian Reichel 	if (reg_value & VBUS_CH_NOK) {
24948c0984e5SSebastian Reichel 		di->flags.usbchargernotok = true;
24958c0984e5SSebastian Reichel 		/* Check again in 1sec */
24968c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
24978c0984e5SSebastian Reichel 			&di->check_usbchgnotok_work, HZ);
24988c0984e5SSebastian Reichel 	} else {
24998c0984e5SSebastian Reichel 		di->flags.usbchargernotok = false;
25008c0984e5SSebastian Reichel 		di->flags.vbus_collapse = false;
25018c0984e5SSebastian Reichel 	}
25028c0984e5SSebastian Reichel 
25038c0984e5SSebastian Reichel 	if (prev_status != di->flags.usbchargernotok)
25048c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
25058c0984e5SSebastian Reichel }
25068c0984e5SSebastian Reichel 
25078c0984e5SSebastian Reichel /**
25088c0984e5SSebastian Reichel  * ab8500_charger_check_main_thermal_prot_work() - check main thermal status
25098c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
25108c0984e5SSebastian Reichel  *
25118c0984e5SSebastian Reichel  * Work queue function for checking the Main thermal prot status
25128c0984e5SSebastian Reichel  */
25138c0984e5SSebastian Reichel static void ab8500_charger_check_main_thermal_prot_work(
25148c0984e5SSebastian Reichel 	struct work_struct *work)
25158c0984e5SSebastian Reichel {
25168c0984e5SSebastian Reichel 	int ret;
25178c0984e5SSebastian Reichel 	u8 reg_value;
25188c0984e5SSebastian Reichel 
25198c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
25208c0984e5SSebastian Reichel 		struct ab8500_charger, check_main_thermal_prot_work);
25218c0984e5SSebastian Reichel 
25228c0984e5SSebastian Reichel 	/* Check if the status bit for main_thermal_prot is still active */
25238c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
25248c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
25258c0984e5SSebastian Reichel 	if (ret < 0) {
25268c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
25278c0984e5SSebastian Reichel 		return;
25288c0984e5SSebastian Reichel 	}
25298c0984e5SSebastian Reichel 	if (reg_value & MAIN_CH_TH_PROT)
25308c0984e5SSebastian Reichel 		di->flags.main_thermal_prot = true;
25318c0984e5SSebastian Reichel 	else
25328c0984e5SSebastian Reichel 		di->flags.main_thermal_prot = false;
25338c0984e5SSebastian Reichel 
25348c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
25358c0984e5SSebastian Reichel }
25368c0984e5SSebastian Reichel 
25378c0984e5SSebastian Reichel /**
25388c0984e5SSebastian Reichel  * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status
25398c0984e5SSebastian Reichel  * @work:	pointer to the work_struct structure
25408c0984e5SSebastian Reichel  *
25418c0984e5SSebastian Reichel  * Work queue function for checking the USB thermal prot status
25428c0984e5SSebastian Reichel  */
25438c0984e5SSebastian Reichel static void ab8500_charger_check_usb_thermal_prot_work(
25448c0984e5SSebastian Reichel 	struct work_struct *work)
25458c0984e5SSebastian Reichel {
25468c0984e5SSebastian Reichel 	int ret;
25478c0984e5SSebastian Reichel 	u8 reg_value;
25488c0984e5SSebastian Reichel 
25498c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
25508c0984e5SSebastian Reichel 		struct ab8500_charger, check_usb_thermal_prot_work);
25518c0984e5SSebastian Reichel 
25528c0984e5SSebastian Reichel 	/* Check if the status bit for usb_thermal_prot is still active */
25538c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev,
25548c0984e5SSebastian Reichel 		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
25558c0984e5SSebastian Reichel 	if (ret < 0) {
25568c0984e5SSebastian Reichel 		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
25578c0984e5SSebastian Reichel 		return;
25588c0984e5SSebastian Reichel 	}
25598c0984e5SSebastian Reichel 	if (reg_value & USB_CH_TH_PROT)
25608c0984e5SSebastian Reichel 		di->flags.usb_thermal_prot = true;
25618c0984e5SSebastian Reichel 	else
25628c0984e5SSebastian Reichel 		di->flags.usb_thermal_prot = false;
25638c0984e5SSebastian Reichel 
25648c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
25658c0984e5SSebastian Reichel }
25668c0984e5SSebastian Reichel 
25678c0984e5SSebastian Reichel /**
25688c0984e5SSebastian Reichel  * ab8500_charger_mainchunplugdet_handler() - main charger unplugged
25698c0984e5SSebastian Reichel  * @irq:       interrupt number
25708c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
25718c0984e5SSebastian Reichel  *
25728c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
25738c0984e5SSebastian Reichel  */
25748c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di)
25758c0984e5SSebastian Reichel {
25768c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
25778c0984e5SSebastian Reichel 
25788c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger unplugged\n");
25798c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
25808c0984e5SSebastian Reichel 
25818c0984e5SSebastian Reichel 	cancel_delayed_work_sync(&di->ac_charger_attached_work);
25828c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
25838c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
25848c0984e5SSebastian Reichel 
25858c0984e5SSebastian Reichel 	return IRQ_HANDLED;
25868c0984e5SSebastian Reichel }
25878c0984e5SSebastian Reichel 
25888c0984e5SSebastian Reichel /**
25898c0984e5SSebastian Reichel  * ab8500_charger_mainchplugdet_handler() - main charger plugged
25908c0984e5SSebastian Reichel  * @irq:       interrupt number
25918c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
25928c0984e5SSebastian Reichel  *
25938c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
25948c0984e5SSebastian Reichel  */
25958c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di)
25968c0984e5SSebastian Reichel {
25978c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
25988c0984e5SSebastian Reichel 
25998c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger plugged\n");
26008c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->ac_work);
26018c0984e5SSebastian Reichel 
26028c0984e5SSebastian Reichel 	mutex_lock(&di->charger_attached_mutex);
26038c0984e5SSebastian Reichel 	mutex_unlock(&di->charger_attached_mutex);
26048c0984e5SSebastian Reichel 
26058c0984e5SSebastian Reichel 	if (is_ab8500(di->parent))
26068c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
26078c0984e5SSebastian Reichel 			   &di->ac_charger_attached_work,
26088c0984e5SSebastian Reichel 			   HZ);
26098c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26108c0984e5SSebastian Reichel }
26118c0984e5SSebastian Reichel 
26128c0984e5SSebastian Reichel /**
26138c0984e5SSebastian Reichel  * ab8500_charger_mainextchnotok_handler() - main charger not ok
26148c0984e5SSebastian Reichel  * @irq:       interrupt number
26158c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26168c0984e5SSebastian Reichel  *
26178c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26188c0984e5SSebastian Reichel  */
26198c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di)
26208c0984e5SSebastian Reichel {
26218c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26228c0984e5SSebastian Reichel 
26238c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Main charger not ok\n");
26248c0984e5SSebastian Reichel 	di->flags.mainextchnotok = true;
26258c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->ac_chg.psy);
26268c0984e5SSebastian Reichel 
26278c0984e5SSebastian Reichel 	/* Schedule a new HW failure check */
26288c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
26298c0984e5SSebastian Reichel 
26308c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26318c0984e5SSebastian Reichel }
26328c0984e5SSebastian Reichel 
26338c0984e5SSebastian Reichel /**
26348c0984e5SSebastian Reichel  * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger
26358c0984e5SSebastian Reichel  * thermal protection threshold
26368c0984e5SSebastian Reichel  * @irq:       interrupt number
26378c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26388c0984e5SSebastian Reichel  *
26398c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26408c0984e5SSebastian Reichel  */
26418c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di)
26428c0984e5SSebastian Reichel {
26438c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26448c0984e5SSebastian Reichel 
26458c0984e5SSebastian Reichel 	dev_dbg(di->dev,
26468c0984e5SSebastian Reichel 		"Die temp above Main charger thermal protection threshold\n");
26478c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
26488c0984e5SSebastian Reichel 
26498c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26508c0984e5SSebastian Reichel }
26518c0984e5SSebastian Reichel 
26528c0984e5SSebastian Reichel /**
26538c0984e5SSebastian Reichel  * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger
26548c0984e5SSebastian Reichel  * thermal protection threshold
26558c0984e5SSebastian Reichel  * @irq:       interrupt number
26568c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
26578c0984e5SSebastian Reichel  *
26588c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
26598c0984e5SSebastian Reichel  */
26608c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di)
26618c0984e5SSebastian Reichel {
26628c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
26638c0984e5SSebastian Reichel 
26648c0984e5SSebastian Reichel 	dev_dbg(di->dev,
26658c0984e5SSebastian Reichel 		"Die temp ok for Main charger thermal protection threshold\n");
26668c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
26678c0984e5SSebastian Reichel 
26688c0984e5SSebastian Reichel 	return IRQ_HANDLED;
26698c0984e5SSebastian Reichel }
26708c0984e5SSebastian Reichel 
26718c0984e5SSebastian Reichel static void ab8500_charger_vbus_drop_end_work(struct work_struct *work)
26728c0984e5SSebastian Reichel {
26738c0984e5SSebastian Reichel 	struct ab8500_charger *di = container_of(work,
26748c0984e5SSebastian Reichel 		struct ab8500_charger, vbus_drop_end_work.work);
2675*83e5aa77SLinus Walleij 	int ret, curr_ua;
26768c0984e5SSebastian Reichel 	u8 reg_value;
26778c0984e5SSebastian Reichel 
26788c0984e5SSebastian Reichel 	di->flags.vbus_drop_end = false;
26798c0984e5SSebastian Reichel 
26808c0984e5SSebastian Reichel 	/* Reset the drop counter */
26818c0984e5SSebastian Reichel 	abx500_set_register_interruptible(di->dev,
26828c0984e5SSebastian Reichel 				  AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01);
26838c0984e5SSebastian Reichel 
26848c0984e5SSebastian Reichel 	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
26858c0984e5SSebastian Reichel 			AB8500_CH_USBCH_STAT2_REG, &reg_value);
26868c0984e5SSebastian Reichel 	if (ret < 0) {
26878c0984e5SSebastian Reichel 		dev_err(di->dev, "%s read failed\n", __func__);
26888c0984e5SSebastian Reichel 		return;
26898c0984e5SSebastian Reichel 	}
26908c0984e5SSebastian Reichel 
2691*83e5aa77SLinus Walleij 	curr_ua = ab8500_charge_input_curr_map[
26928c0984e5SSebastian Reichel 		reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT];
26938c0984e5SSebastian Reichel 
2694*83e5aa77SLinus Walleij 	if (di->max_usb_in_curr.calculated_max_ua != curr_ua) {
26958c0984e5SSebastian Reichel 		/* USB source is collapsing */
2696*83e5aa77SLinus Walleij 		di->max_usb_in_curr.calculated_max_ua = curr_ua;
26978c0984e5SSebastian Reichel 		dev_dbg(di->dev,
2698*83e5aa77SLinus Walleij 			 "VBUS input current limiting to %d uA\n",
2699*83e5aa77SLinus Walleij 			 di->max_usb_in_curr.calculated_max_ua);
27008c0984e5SSebastian Reichel 	} else {
27018c0984e5SSebastian Reichel 		/*
27028c0984e5SSebastian Reichel 		 * USB source can not give more than this amount.
27038c0984e5SSebastian Reichel 		 * Taking more will collapse the source.
27048c0984e5SSebastian Reichel 		 */
2705*83e5aa77SLinus Walleij 		di->max_usb_in_curr.set_max_ua =
2706*83e5aa77SLinus Walleij 			di->max_usb_in_curr.calculated_max_ua;
27078c0984e5SSebastian Reichel 		dev_dbg(di->dev,
2708*83e5aa77SLinus Walleij 			 "VBUS input current limited to %d uA\n",
2709*83e5aa77SLinus Walleij 			 di->max_usb_in_curr.set_max_ua);
27108c0984e5SSebastian Reichel 	}
27118c0984e5SSebastian Reichel 
27128c0984e5SSebastian Reichel 	if (di->usb.charger_connected)
27138c0984e5SSebastian Reichel 		ab8500_charger_set_vbus_in_curr(di,
2714*83e5aa77SLinus Walleij 					di->max_usb_in_curr.usb_type_max_ua);
27158c0984e5SSebastian Reichel }
27168c0984e5SSebastian Reichel 
27178c0984e5SSebastian Reichel /**
27188c0984e5SSebastian Reichel  * ab8500_charger_vbusdetf_handler() - VBUS falling detected
27198c0984e5SSebastian Reichel  * @irq:       interrupt number
27208c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27218c0984e5SSebastian Reichel  *
27228c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27238c0984e5SSebastian Reichel  */
27248c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di)
27258c0984e5SSebastian Reichel {
27268c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27278c0984e5SSebastian Reichel 
27288c0984e5SSebastian Reichel 	di->vbus_detected = false;
27298c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS falling detected\n");
27308c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->detect_usb_type_work);
27318c0984e5SSebastian Reichel 
27328c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27338c0984e5SSebastian Reichel }
27348c0984e5SSebastian Reichel 
27358c0984e5SSebastian Reichel /**
27368c0984e5SSebastian Reichel  * ab8500_charger_vbusdetr_handler() - VBUS rising detected
27378c0984e5SSebastian Reichel  * @irq:       interrupt number
27388c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27398c0984e5SSebastian Reichel  *
27408c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27418c0984e5SSebastian Reichel  */
27428c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di)
27438c0984e5SSebastian Reichel {
27448c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27458c0984e5SSebastian Reichel 
27468c0984e5SSebastian Reichel 	di->vbus_detected = true;
27478c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS rising detected\n");
27488c0984e5SSebastian Reichel 
27498c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->detect_usb_type_work);
27508c0984e5SSebastian Reichel 
27518c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27528c0984e5SSebastian Reichel }
27538c0984e5SSebastian Reichel 
27548c0984e5SSebastian Reichel /**
27558c0984e5SSebastian Reichel  * ab8500_charger_usblinkstatus_handler() - USB link status has changed
27568c0984e5SSebastian Reichel  * @irq:       interrupt number
27578c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27588c0984e5SSebastian Reichel  *
27598c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27608c0984e5SSebastian Reichel  */
27618c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di)
27628c0984e5SSebastian Reichel {
27638c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27648c0984e5SSebastian Reichel 
27658c0984e5SSebastian Reichel 	dev_dbg(di->dev, "USB link status changed\n");
27668c0984e5SSebastian Reichel 
27678c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->usb_link_status_work);
27688c0984e5SSebastian Reichel 
27698c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27708c0984e5SSebastian Reichel }
27718c0984e5SSebastian Reichel 
27728c0984e5SSebastian Reichel /**
27738c0984e5SSebastian Reichel  * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger
27748c0984e5SSebastian Reichel  * thermal protection threshold
27758c0984e5SSebastian Reichel  * @irq:       interrupt number
27768c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27778c0984e5SSebastian Reichel  *
27788c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27798c0984e5SSebastian Reichel  */
27808c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di)
27818c0984e5SSebastian Reichel {
27828c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
27838c0984e5SSebastian Reichel 
27848c0984e5SSebastian Reichel 	dev_dbg(di->dev,
27858c0984e5SSebastian Reichel 		"Die temp above USB charger thermal protection threshold\n");
27868c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
27878c0984e5SSebastian Reichel 
27888c0984e5SSebastian Reichel 	return IRQ_HANDLED;
27898c0984e5SSebastian Reichel }
27908c0984e5SSebastian Reichel 
27918c0984e5SSebastian Reichel /**
27928c0984e5SSebastian Reichel  * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger
27938c0984e5SSebastian Reichel  * thermal protection threshold
27948c0984e5SSebastian Reichel  * @irq:       interrupt number
27958c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
27968c0984e5SSebastian Reichel  *
27978c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
27988c0984e5SSebastian Reichel  */
27998c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di)
28008c0984e5SSebastian Reichel {
28018c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28028c0984e5SSebastian Reichel 
28038c0984e5SSebastian Reichel 	dev_dbg(di->dev,
28048c0984e5SSebastian Reichel 		"Die temp ok for USB charger thermal protection threshold\n");
28058c0984e5SSebastian Reichel 	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
28068c0984e5SSebastian Reichel 
28078c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28088c0984e5SSebastian Reichel }
28098c0984e5SSebastian Reichel 
28108c0984e5SSebastian Reichel /**
28118c0984e5SSebastian Reichel  * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected
28128c0984e5SSebastian Reichel  * @irq:       interrupt number
28138c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28148c0984e5SSebastian Reichel  *
28158c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28168c0984e5SSebastian Reichel  */
28178c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di)
28188c0984e5SSebastian Reichel {
28198c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28208c0984e5SSebastian Reichel 
28218c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Not allowed USB charger detected\n");
28228c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0);
28238c0984e5SSebastian Reichel 
28248c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28258c0984e5SSebastian Reichel }
28268c0984e5SSebastian Reichel 
28278c0984e5SSebastian Reichel /**
28288c0984e5SSebastian Reichel  * ab8500_charger_chwdexp_handler() - Charger watchdog expired
28298c0984e5SSebastian Reichel  * @irq:       interrupt number
28308c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28318c0984e5SSebastian Reichel  *
28328c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28338c0984e5SSebastian Reichel  */
28348c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di)
28358c0984e5SSebastian Reichel {
28368c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28378c0984e5SSebastian Reichel 
28388c0984e5SSebastian Reichel 	dev_dbg(di->dev, "Charger watchdog expired\n");
28398c0984e5SSebastian Reichel 
28408c0984e5SSebastian Reichel 	/*
28418c0984e5SSebastian Reichel 	 * The charger that was online when the watchdog expired
28428c0984e5SSebastian Reichel 	 * needs to be restarted for charging to start again
28438c0984e5SSebastian Reichel 	 */
28448c0984e5SSebastian Reichel 	if (di->ac.charger_online) {
28458c0984e5SSebastian Reichel 		di->ac.wd_expired = true;
28468c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->ac_chg.psy);
28478c0984e5SSebastian Reichel 	}
28488c0984e5SSebastian Reichel 	if (di->usb.charger_online) {
28498c0984e5SSebastian Reichel 		di->usb.wd_expired = true;
28508c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->usb_chg.psy);
28518c0984e5SSebastian Reichel 	}
28528c0984e5SSebastian Reichel 
28538c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28548c0984e5SSebastian Reichel }
28558c0984e5SSebastian Reichel 
28568c0984e5SSebastian Reichel /**
28578c0984e5SSebastian Reichel  * ab8500_charger_vbuschdropend_handler() - VBUS drop removed
28588c0984e5SSebastian Reichel  * @irq:       interrupt number
28598c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28608c0984e5SSebastian Reichel  *
28618c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28628c0984e5SSebastian Reichel  */
28638c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di)
28648c0984e5SSebastian Reichel {
28658c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28668c0984e5SSebastian Reichel 
28678c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS charger drop ended\n");
28688c0984e5SSebastian Reichel 	di->flags.vbus_drop_end = true;
28698c0984e5SSebastian Reichel 
28708c0984e5SSebastian Reichel 	/*
28718c0984e5SSebastian Reichel 	 * VBUS might have dropped due to bad connection.
28728c0984e5SSebastian Reichel 	 * Schedule a new input limit set to the value SW requests.
28738c0984e5SSebastian Reichel 	 */
28748c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work,
28758c0984e5SSebastian Reichel 			   round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ));
28768c0984e5SSebastian Reichel 
28778c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28788c0984e5SSebastian Reichel }
28798c0984e5SSebastian Reichel 
28808c0984e5SSebastian Reichel /**
28818c0984e5SSebastian Reichel  * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected
28828c0984e5SSebastian Reichel  * @irq:       interrupt number
28838c0984e5SSebastian Reichel  * @_di:       pointer to the ab8500_charger structure
28848c0984e5SSebastian Reichel  *
28858c0984e5SSebastian Reichel  * Returns IRQ status(IRQ_HANDLED)
28868c0984e5SSebastian Reichel  */
28878c0984e5SSebastian Reichel static irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di)
28888c0984e5SSebastian Reichel {
28898c0984e5SSebastian Reichel 	struct ab8500_charger *di = _di;
28908c0984e5SSebastian Reichel 
28918c0984e5SSebastian Reichel 	dev_dbg(di->dev, "VBUS overvoltage detected\n");
28928c0984e5SSebastian Reichel 	di->flags.vbus_ovv = true;
28938c0984e5SSebastian Reichel 	ab8500_power_supply_changed(di, di->usb_chg.psy);
28948c0984e5SSebastian Reichel 
28958c0984e5SSebastian Reichel 	/* Schedule a new HW failure check */
28968c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
28978c0984e5SSebastian Reichel 
28988c0984e5SSebastian Reichel 	return IRQ_HANDLED;
28998c0984e5SSebastian Reichel }
29008c0984e5SSebastian Reichel 
29018c0984e5SSebastian Reichel /**
29028c0984e5SSebastian Reichel  * ab8500_charger_ac_get_property() - get the ac/mains properties
29038c0984e5SSebastian Reichel  * @psy:       pointer to the power_supply structure
29048c0984e5SSebastian Reichel  * @psp:       pointer to the power_supply_property structure
29058c0984e5SSebastian Reichel  * @val:       pointer to the power_supply_propval union
29068c0984e5SSebastian Reichel  *
29078c0984e5SSebastian Reichel  * This function gets called when an application tries to get the ac/mains
29088c0984e5SSebastian Reichel  * properties by reading the sysfs files.
29098c0984e5SSebastian Reichel  * AC/Mains properties are online, present and voltage.
29108c0984e5SSebastian Reichel  * online:     ac/mains charging is in progress or not
29118c0984e5SSebastian Reichel  * present:    presence of the ac/mains
29128c0984e5SSebastian Reichel  * voltage:    AC/Mains voltage
29138c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
29148c0984e5SSebastian Reichel  */
29158c0984e5SSebastian Reichel static int ab8500_charger_ac_get_property(struct power_supply *psy,
29168c0984e5SSebastian Reichel 	enum power_supply_property psp,
29178c0984e5SSebastian Reichel 	union power_supply_propval *val)
29188c0984e5SSebastian Reichel {
29198c0984e5SSebastian Reichel 	struct ab8500_charger *di;
29208c0984e5SSebastian Reichel 	int ret;
29218c0984e5SSebastian Reichel 
29228c0984e5SSebastian Reichel 	di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy));
29238c0984e5SSebastian Reichel 
29248c0984e5SSebastian Reichel 	switch (psp) {
29258c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_HEALTH:
29268c0984e5SSebastian Reichel 		if (di->flags.mainextchnotok)
29278c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
29288c0984e5SSebastian Reichel 		else if (di->ac.wd_expired || di->usb.wd_expired)
29298c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
29308c0984e5SSebastian Reichel 		else if (di->flags.main_thermal_prot)
29318c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
29328c0984e5SSebastian Reichel 		else
29338c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
29348c0984e5SSebastian Reichel 		break;
29358c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_ONLINE:
29368c0984e5SSebastian Reichel 		val->intval = di->ac.charger_online;
29378c0984e5SSebastian Reichel 		break;
29388c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_PRESENT:
29398c0984e5SSebastian Reichel 		val->intval = di->ac.charger_connected;
29408c0984e5SSebastian Reichel 		break;
29418c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
29428c0984e5SSebastian Reichel 		ret = ab8500_charger_get_ac_voltage(di);
29438c0984e5SSebastian Reichel 		if (ret >= 0)
29448c0984e5SSebastian Reichel 			di->ac.charger_voltage = ret;
29458c0984e5SSebastian Reichel 		/* On error, use previous value */
29468c0984e5SSebastian Reichel 		val->intval = di->ac.charger_voltage * 1000;
29478c0984e5SSebastian Reichel 		break;
29488c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
29498c0984e5SSebastian Reichel 		/*
29508c0984e5SSebastian Reichel 		 * This property is used to indicate when CV mode is entered
29518c0984e5SSebastian Reichel 		 * for the AC charger
29528c0984e5SSebastian Reichel 		 */
29538c0984e5SSebastian Reichel 		di->ac.cv_active = ab8500_charger_ac_cv(di);
29548c0984e5SSebastian Reichel 		val->intval = di->ac.cv_active;
29558c0984e5SSebastian Reichel 		break;
29568c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_NOW:
29578c0984e5SSebastian Reichel 		ret = ab8500_charger_get_ac_current(di);
29588c0984e5SSebastian Reichel 		if (ret >= 0)
2959*83e5aa77SLinus Walleij 			di->ac.charger_current_ua = ret;
2960*83e5aa77SLinus Walleij 		val->intval = di->ac.charger_current_ua;
29618c0984e5SSebastian Reichel 		break;
29628c0984e5SSebastian Reichel 	default:
29638c0984e5SSebastian Reichel 		return -EINVAL;
29648c0984e5SSebastian Reichel 	}
29658c0984e5SSebastian Reichel 	return 0;
29668c0984e5SSebastian Reichel }
29678c0984e5SSebastian Reichel 
29688c0984e5SSebastian Reichel /**
29698c0984e5SSebastian Reichel  * ab8500_charger_usb_get_property() - get the usb properties
29708c0984e5SSebastian Reichel  * @psy:        pointer to the power_supply structure
29718c0984e5SSebastian Reichel  * @psp:        pointer to the power_supply_property structure
29728c0984e5SSebastian Reichel  * @val:        pointer to the power_supply_propval union
29738c0984e5SSebastian Reichel  *
29748c0984e5SSebastian Reichel  * This function gets called when an application tries to get the usb
29758c0984e5SSebastian Reichel  * properties by reading the sysfs files.
29768c0984e5SSebastian Reichel  * USB properties are online, present and voltage.
29778c0984e5SSebastian Reichel  * online:     usb charging is in progress or not
29788c0984e5SSebastian Reichel  * present:    presence of the usb
29798c0984e5SSebastian Reichel  * voltage:    vbus voltage
29808c0984e5SSebastian Reichel  * Returns error code in case of failure else 0(on success)
29818c0984e5SSebastian Reichel  */
29828c0984e5SSebastian Reichel static int ab8500_charger_usb_get_property(struct power_supply *psy,
29838c0984e5SSebastian Reichel 	enum power_supply_property psp,
29848c0984e5SSebastian Reichel 	union power_supply_propval *val)
29858c0984e5SSebastian Reichel {
29868c0984e5SSebastian Reichel 	struct ab8500_charger *di;
29878c0984e5SSebastian Reichel 	int ret;
29888c0984e5SSebastian Reichel 
29898c0984e5SSebastian Reichel 	di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy));
29908c0984e5SSebastian Reichel 
29918c0984e5SSebastian Reichel 	switch (psp) {
29928c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_HEALTH:
29938c0984e5SSebastian Reichel 		if (di->flags.usbchargernotok)
29948c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
29958c0984e5SSebastian Reichel 		else if (di->ac.wd_expired || di->usb.wd_expired)
29968c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_DEAD;
29978c0984e5SSebastian Reichel 		else if (di->flags.usb_thermal_prot)
29988c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
29998c0984e5SSebastian Reichel 		else if (di->flags.vbus_ovv)
30008c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
30018c0984e5SSebastian Reichel 		else
30028c0984e5SSebastian Reichel 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
30038c0984e5SSebastian Reichel 		break;
30048c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_ONLINE:
30058c0984e5SSebastian Reichel 		val->intval = di->usb.charger_online;
30068c0984e5SSebastian Reichel 		break;
30078c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_PRESENT:
30088c0984e5SSebastian Reichel 		val->intval = di->usb.charger_connected;
30098c0984e5SSebastian Reichel 		break;
30108c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
30118c0984e5SSebastian Reichel 		ret = ab8500_charger_get_vbus_voltage(di);
30128c0984e5SSebastian Reichel 		if (ret >= 0)
30138c0984e5SSebastian Reichel 			di->usb.charger_voltage = ret;
30148c0984e5SSebastian Reichel 		val->intval = di->usb.charger_voltage * 1000;
30158c0984e5SSebastian Reichel 		break;
30168c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
30178c0984e5SSebastian Reichel 		/*
30188c0984e5SSebastian Reichel 		 * This property is used to indicate when CV mode is entered
30198c0984e5SSebastian Reichel 		 * for the USB charger
30208c0984e5SSebastian Reichel 		 */
30218c0984e5SSebastian Reichel 		di->usb.cv_active = ab8500_charger_usb_cv(di);
30228c0984e5SSebastian Reichel 		val->intval = di->usb.cv_active;
30238c0984e5SSebastian Reichel 		break;
30248c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_NOW:
30258c0984e5SSebastian Reichel 		ret = ab8500_charger_get_usb_current(di);
30268c0984e5SSebastian Reichel 		if (ret >= 0)
3027*83e5aa77SLinus Walleij 			di->usb.charger_current_ua = ret;
3028*83e5aa77SLinus Walleij 		val->intval = di->usb.charger_current_ua;
30298c0984e5SSebastian Reichel 		break;
30308c0984e5SSebastian Reichel 	case POWER_SUPPLY_PROP_CURRENT_AVG:
30318c0984e5SSebastian Reichel 		/*
30328c0984e5SSebastian Reichel 		 * This property is used to indicate when VBUS has collapsed
30338c0984e5SSebastian Reichel 		 * due to too high output current from the USB charger
30348c0984e5SSebastian Reichel 		 */
30358c0984e5SSebastian Reichel 		if (di->flags.vbus_collapse)
30368c0984e5SSebastian Reichel 			val->intval = 1;
30378c0984e5SSebastian Reichel 		else
30388c0984e5SSebastian Reichel 			val->intval = 0;
30398c0984e5SSebastian Reichel 		break;
30408c0984e5SSebastian Reichel 	default:
30418c0984e5SSebastian Reichel 		return -EINVAL;
30428c0984e5SSebastian Reichel 	}
30438c0984e5SSebastian Reichel 	return 0;
30448c0984e5SSebastian Reichel }
30458c0984e5SSebastian Reichel 
30468c0984e5SSebastian Reichel /**
30478c0984e5SSebastian Reichel  * ab8500_charger_init_hw_registers() - Set up charger related registers
30488c0984e5SSebastian Reichel  * @di:		pointer to the ab8500_charger structure
30498c0984e5SSebastian Reichel  *
30508c0984e5SSebastian Reichel  * Set up charger OVV, watchdog and maximum voltage registers as well as
30518c0984e5SSebastian Reichel  * charging of the backup battery
30528c0984e5SSebastian Reichel  */
30538c0984e5SSebastian Reichel static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
30548c0984e5SSebastian Reichel {
30558c0984e5SSebastian Reichel 	int ret = 0;
30568c0984e5SSebastian Reichel 
30578c0984e5SSebastian Reichel 	/* Setup maximum charger current and voltage for ABB cut2.0 */
30588c0984e5SSebastian Reichel 	if (!is_ab8500_1p1_or_earlier(di->parent)) {
30598c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30608c0984e5SSebastian Reichel 			AB8500_CHARGER,
30618c0984e5SSebastian Reichel 			AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6);
30628c0984e5SSebastian Reichel 		if (ret) {
30638c0984e5SSebastian Reichel 			dev_err(di->dev,
30648c0984e5SSebastian Reichel 				"failed to set CH_VOLT_LVL_MAX_REG\n");
30658c0984e5SSebastian Reichel 			goto out;
30668c0984e5SSebastian Reichel 		}
30678c0984e5SSebastian Reichel 
30688c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30698c0984e5SSebastian Reichel 			AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG,
30708c0984e5SSebastian Reichel 			CH_OP_CUR_LVL_1P6);
30718c0984e5SSebastian Reichel 		if (ret) {
30728c0984e5SSebastian Reichel 			dev_err(di->dev,
30738c0984e5SSebastian Reichel 				"failed to set CH_OPT_CRNTLVL_MAX_REG\n");
30748c0984e5SSebastian Reichel 			goto out;
30758c0984e5SSebastian Reichel 		}
30768c0984e5SSebastian Reichel 	}
30778c0984e5SSebastian Reichel 
30784c4268dcSLinus Walleij 	if (is_ab8505_2p0(di->parent))
30798c0984e5SSebastian Reichel 		ret = abx500_mask_and_set_register_interruptible(di->dev,
30808c0984e5SSebastian Reichel 			AB8500_CHARGER,
30818c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL2_REG,
30828c0984e5SSebastian Reichel 			VBUS_AUTO_IN_CURR_LIM_ENA,
30838c0984e5SSebastian Reichel 			VBUS_AUTO_IN_CURR_LIM_ENA);
30848c0984e5SSebastian Reichel 	else
30858c0984e5SSebastian Reichel 		/*
30868c0984e5SSebastian Reichel 		 * VBUS OVV set to 6.3V and enable automatic current limitation
30878c0984e5SSebastian Reichel 		 */
30888c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev,
30898c0984e5SSebastian Reichel 			AB8500_CHARGER,
30908c0984e5SSebastian Reichel 			AB8500_USBCH_CTRL2_REG,
30918c0984e5SSebastian Reichel 			VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA);
30928c0984e5SSebastian Reichel 	if (ret) {
30938c0984e5SSebastian Reichel 		dev_err(di->dev,
30948c0984e5SSebastian Reichel 			"failed to set automatic current limitation\n");
30958c0984e5SSebastian Reichel 		goto out;
30968c0984e5SSebastian Reichel 	}
30978c0984e5SSebastian Reichel 
30988c0984e5SSebastian Reichel 	/* Enable main watchdog in OTP */
30998c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31008c0984e5SSebastian Reichel 		AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD);
31018c0984e5SSebastian Reichel 	if (ret) {
31028c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to enable main WD in OTP\n");
31038c0984e5SSebastian Reichel 		goto out;
31048c0984e5SSebastian Reichel 	}
31058c0984e5SSebastian Reichel 
31068c0984e5SSebastian Reichel 	/* Enable main watchdog */
31078c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31088c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31098c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA);
31108c0984e5SSebastian Reichel 	if (ret) {
3111b5e11cc1SColin Ian King 		dev_err(di->dev, "failed to enable main watchdog\n");
31128c0984e5SSebastian Reichel 		goto out;
31138c0984e5SSebastian Reichel 	}
31148c0984e5SSebastian Reichel 
31158c0984e5SSebastian Reichel 	/*
31168c0984e5SSebastian Reichel 	 * Due to internal synchronisation, Enable and Kick watchdog bits
31178c0984e5SSebastian Reichel 	 * cannot be enabled in a single write.
31188c0984e5SSebastian Reichel 	 * A minimum delay of 2*32 kHz period (62.5µs) must be inserted
31198c0984e5SSebastian Reichel 	 * between writing Enable then Kick bits.
31208c0984e5SSebastian Reichel 	 */
31218c0984e5SSebastian Reichel 	udelay(63);
31228c0984e5SSebastian Reichel 
31238c0984e5SSebastian Reichel 	/* Kick main watchdog */
31248c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31258c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31268c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG,
31278c0984e5SSebastian Reichel 		(MAIN_WDOG_ENA | MAIN_WDOG_KICK));
31288c0984e5SSebastian Reichel 	if (ret) {
31298c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to kick main watchdog\n");
31308c0984e5SSebastian Reichel 		goto out;
31318c0984e5SSebastian Reichel 	}
31328c0984e5SSebastian Reichel 
31338c0984e5SSebastian Reichel 	/* Disable main watchdog */
31348c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31358c0984e5SSebastian Reichel 		AB8500_SYS_CTRL2_BLOCK,
31368c0984e5SSebastian Reichel 		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS);
31378c0984e5SSebastian Reichel 	if (ret) {
31388c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to disable main watchdog\n");
31398c0984e5SSebastian Reichel 		goto out;
31408c0984e5SSebastian Reichel 	}
31418c0984e5SSebastian Reichel 
31428c0984e5SSebastian Reichel 	/* Set watchdog timeout */
31438c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
31448c0984e5SSebastian Reichel 		AB8500_CH_WD_TIMER_REG, WD_TIMER);
31458c0984e5SSebastian Reichel 	if (ret) {
31468c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to set charger watchdog timeout\n");
31478c0984e5SSebastian Reichel 		goto out;
31488c0984e5SSebastian Reichel 	}
31498c0984e5SSebastian Reichel 
31508c0984e5SSebastian Reichel 	ret = ab8500_charger_led_en(di, false);
31518c0984e5SSebastian Reichel 	if (ret < 0) {
31528c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to disable LED\n");
31538c0984e5SSebastian Reichel 		goto out;
31548c0984e5SSebastian Reichel 	}
31558c0984e5SSebastian Reichel 
31568c0984e5SSebastian Reichel 	ret = abx500_set_register_interruptible(di->dev,
31578c0984e5SSebastian Reichel 		AB8500_RTC,
31588c0984e5SSebastian Reichel 		AB8500_RTC_BACKUP_CHG_REG,
31598c0984e5SSebastian Reichel 		(di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i);
31608c0984e5SSebastian Reichel 	if (ret) {
31618c0984e5SSebastian Reichel 		dev_err(di->dev, "failed to setup backup battery charging\n");
31628c0984e5SSebastian Reichel 		goto out;
31638c0984e5SSebastian Reichel 	}
31648c0984e5SSebastian Reichel 
31658c0984e5SSebastian Reichel 	/* Enable backup battery charging */
3166bf59fdddSChristophe JAILLET 	ret = abx500_mask_and_set_register_interruptible(di->dev,
31678c0984e5SSebastian Reichel 		AB8500_RTC, AB8500_RTC_CTRL_REG,
31688c0984e5SSebastian Reichel 		RTC_BUP_CH_ENA, RTC_BUP_CH_ENA);
316909edcb64SChristophe JAILLET 	if (ret < 0) {
31708c0984e5SSebastian Reichel 		dev_err(di->dev, "%s mask and set failed\n", __func__);
317109edcb64SChristophe JAILLET 		goto out;
317209edcb64SChristophe JAILLET 	}
31738c0984e5SSebastian Reichel 
31748c0984e5SSebastian Reichel out:
31758c0984e5SSebastian Reichel 	return ret;
31768c0984e5SSebastian Reichel }
31778c0984e5SSebastian Reichel 
31788c0984e5SSebastian Reichel /*
31798c0984e5SSebastian Reichel  * ab8500 charger driver interrupts and their respective isr
31808c0984e5SSebastian Reichel  */
31818c0984e5SSebastian Reichel static struct ab8500_charger_interrupts ab8500_charger_irq[] = {
31828c0984e5SSebastian Reichel 	{"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler},
31838c0984e5SSebastian Reichel 	{"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler},
31848c0984e5SSebastian Reichel 	{"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler},
31858c0984e5SSebastian Reichel 	{"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler},
31868c0984e5SSebastian Reichel 	{"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler},
31878c0984e5SSebastian Reichel 	{"VBUS_DET_F", ab8500_charger_vbusdetf_handler},
31888c0984e5SSebastian Reichel 	{"VBUS_DET_R", ab8500_charger_vbusdetr_handler},
31898c0984e5SSebastian Reichel 	{"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler},
31908c0984e5SSebastian Reichel 	{"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler},
31918c0984e5SSebastian Reichel 	{"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler},
31928c0984e5SSebastian Reichel 	{"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler},
31938c0984e5SSebastian Reichel 	{"VBUS_OVV", ab8500_charger_vbusovv_handler},
31948c0984e5SSebastian Reichel 	{"CH_WD_EXP", ab8500_charger_chwdexp_handler},
31958c0984e5SSebastian Reichel 	{"VBUS_CH_DROP_END", ab8500_charger_vbuschdropend_handler},
31968c0984e5SSebastian Reichel };
31978c0984e5SSebastian Reichel 
31988c0984e5SSebastian Reichel static int ab8500_charger_usb_notifier_call(struct notifier_block *nb,
31998c0984e5SSebastian Reichel 		unsigned long event, void *power)
32008c0984e5SSebastian Reichel {
32018c0984e5SSebastian Reichel 	struct ab8500_charger *di =
32028c0984e5SSebastian Reichel 		container_of(nb, struct ab8500_charger, nb);
32038c0984e5SSebastian Reichel 	enum ab8500_usb_state bm_usb_state;
3204*83e5aa77SLinus Walleij 	/*
3205*83e5aa77SLinus Walleij 	 * FIXME: it appears the AB8500 PHY never sends what it should here.
3206*83e5aa77SLinus Walleij 	 * Fix the PHY driver to properly notify the desired current.
3207*83e5aa77SLinus Walleij 	 * Also broadcast microampere and not milliampere.
3208*83e5aa77SLinus Walleij 	 */
32098c0984e5SSebastian Reichel 	unsigned mA = *((unsigned *)power);
32108c0984e5SSebastian Reichel 
32118c0984e5SSebastian Reichel 	if (event != USB_EVENT_VBUS) {
32128c0984e5SSebastian Reichel 		dev_dbg(di->dev, "not a standard host, returning\n");
32138c0984e5SSebastian Reichel 		return NOTIFY_DONE;
32148c0984e5SSebastian Reichel 	}
32158c0984e5SSebastian Reichel 
32168c0984e5SSebastian Reichel 	/* TODO: State is fabricate  here. See if charger really needs USB
32178c0984e5SSebastian Reichel 	 * state or if mA is enough
32188c0984e5SSebastian Reichel 	 */
3219*83e5aa77SLinus Walleij 	if ((di->usb_state.usb_current_ua == 2000) && (mA > 2))
32208c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESUME;
32218c0984e5SSebastian Reichel 	else if (mA == 0)
32228c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESET_HS;
32238c0984e5SSebastian Reichel 	else if (mA == 2)
32248c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_SUSPEND;
32258c0984e5SSebastian Reichel 	else if (mA >= 8) /* 8, 100, 500 */
32268c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED;
32278c0984e5SSebastian Reichel 	else /* Should never occur */
32288c0984e5SSebastian Reichel 		bm_usb_state = AB8500_BM_USB_STATE_RESET_FS;
32298c0984e5SSebastian Reichel 
32308c0984e5SSebastian Reichel 	dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n",
32318c0984e5SSebastian Reichel 		__func__, bm_usb_state, mA);
32328c0984e5SSebastian Reichel 
32338c0984e5SSebastian Reichel 	spin_lock(&di->usb_state.usb_lock);
32348c0984e5SSebastian Reichel 	di->usb_state.state_tmp = bm_usb_state;
3235*83e5aa77SLinus Walleij 	/* FIXME: broadcast ua instead, see above */
3236*83e5aa77SLinus Walleij 	di->usb_state.usb_current_tmp_ua = mA * 1000;
32378c0984e5SSebastian Reichel 	spin_unlock(&di->usb_state.usb_lock);
32388c0984e5SSebastian Reichel 
32398c0984e5SSebastian Reichel 	/*
32408c0984e5SSebastian Reichel 	 * wait for some time until you get updates from the usb stack
32418c0984e5SSebastian Reichel 	 * and negotiations are completed
32428c0984e5SSebastian Reichel 	 */
32438c0984e5SSebastian Reichel 	queue_delayed_work(di->charger_wq, &di->usb_state_changed_work, HZ/2);
32448c0984e5SSebastian Reichel 
32458c0984e5SSebastian Reichel 	return NOTIFY_OK;
32468c0984e5SSebastian Reichel }
32478c0984e5SSebastian Reichel 
3248f8efa0a8SLinus Walleij static int __maybe_unused ab8500_charger_resume(struct device *dev)
32498c0984e5SSebastian Reichel {
32508c0984e5SSebastian Reichel 	int ret;
3251f8efa0a8SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
32528c0984e5SSebastian Reichel 
32538c0984e5SSebastian Reichel 	/*
32548c0984e5SSebastian Reichel 	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
3255ddb74e98SAshish Chavan 	 * logic. That means we have to continuously kick the charger
32568c0984e5SSebastian Reichel 	 * watchdog even when no charger is connected. This is only
32578c0984e5SSebastian Reichel 	 * valid once the AC charger has been enabled. This is
32588c0984e5SSebastian Reichel 	 * a bug that is not handled by the algorithm and the
32598c0984e5SSebastian Reichel 	 * watchdog have to be kicked by the charger driver
32608c0984e5SSebastian Reichel 	 * when the AC charger is disabled
32618c0984e5SSebastian Reichel 	 */
32628c0984e5SSebastian Reichel 	if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) {
32638c0984e5SSebastian Reichel 		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
32648c0984e5SSebastian Reichel 			AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
32658c0984e5SSebastian Reichel 		if (ret)
32668c0984e5SSebastian Reichel 			dev_err(di->dev, "Failed to kick WD!\n");
32678c0984e5SSebastian Reichel 
32688c0984e5SSebastian Reichel 		/* If not already pending start a new timer */
32698c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->kick_wd_work,
32708c0984e5SSebastian Reichel 				   round_jiffies(WD_KICK_INTERVAL));
32718c0984e5SSebastian Reichel 	}
32728c0984e5SSebastian Reichel 
32738c0984e5SSebastian Reichel 	/* If we still have a HW failure, schedule a new check */
32748c0984e5SSebastian Reichel 	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
32758c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq,
32768c0984e5SSebastian Reichel 			&di->check_hw_failure_work, 0);
32778c0984e5SSebastian Reichel 	}
32788c0984e5SSebastian Reichel 
32798c0984e5SSebastian Reichel 	if (di->flags.vbus_drop_end)
32808c0984e5SSebastian Reichel 		queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 0);
32818c0984e5SSebastian Reichel 
32828c0984e5SSebastian Reichel 	return 0;
32838c0984e5SSebastian Reichel }
32848c0984e5SSebastian Reichel 
3285f8efa0a8SLinus Walleij static int __maybe_unused ab8500_charger_suspend(struct device *dev)
32868c0984e5SSebastian Reichel {
3287f8efa0a8SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
32888c0984e5SSebastian Reichel 
32898c0984e5SSebastian Reichel 	/* Cancel any pending jobs */
32908c0984e5SSebastian Reichel 	cancel_delayed_work(&di->check_hw_failure_work);
32918c0984e5SSebastian Reichel 	cancel_delayed_work(&di->vbus_drop_end_work);
32928c0984e5SSebastian Reichel 
32938c0984e5SSebastian Reichel 	flush_delayed_work(&di->attach_work);
32948c0984e5SSebastian Reichel 	flush_delayed_work(&di->usb_charger_attached_work);
32958c0984e5SSebastian Reichel 	flush_delayed_work(&di->ac_charger_attached_work);
32968c0984e5SSebastian Reichel 	flush_delayed_work(&di->check_usbchgnotok_work);
32978c0984e5SSebastian Reichel 	flush_delayed_work(&di->check_vbat_work);
32988c0984e5SSebastian Reichel 	flush_delayed_work(&di->kick_wd_work);
32998c0984e5SSebastian Reichel 
33008c0984e5SSebastian Reichel 	flush_work(&di->usb_link_status_work);
33018c0984e5SSebastian Reichel 	flush_work(&di->ac_work);
33028c0984e5SSebastian Reichel 	flush_work(&di->detect_usb_type_work);
33038c0984e5SSebastian Reichel 
33048c0984e5SSebastian Reichel 	if (atomic_read(&di->current_stepping_sessions))
33058c0984e5SSebastian Reichel 		return -EAGAIN;
33068c0984e5SSebastian Reichel 
33078c0984e5SSebastian Reichel 	return 0;
33088c0984e5SSebastian Reichel }
33098c0984e5SSebastian Reichel 
33108c0984e5SSebastian Reichel static struct notifier_block charger_nb = {
33118c0984e5SSebastian Reichel 	.notifier_call = ab8500_external_charger_prepare,
33128c0984e5SSebastian Reichel };
33138c0984e5SSebastian Reichel 
33148c0984e5SSebastian Reichel static char *supply_interface[] = {
33158c0984e5SSebastian Reichel 	"ab8500_chargalg",
33168c0984e5SSebastian Reichel 	"ab8500_fg",
33178c0984e5SSebastian Reichel 	"ab8500_btemp",
33188c0984e5SSebastian Reichel };
33198c0984e5SSebastian Reichel 
33208c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_ac_chg_desc = {
33218c0984e5SSebastian Reichel 	.name		= "ab8500_ac",
33228c0984e5SSebastian Reichel 	.type		= POWER_SUPPLY_TYPE_MAINS,
33238c0984e5SSebastian Reichel 	.properties	= ab8500_charger_ac_props,
33248c0984e5SSebastian Reichel 	.num_properties	= ARRAY_SIZE(ab8500_charger_ac_props),
33258c0984e5SSebastian Reichel 	.get_property	= ab8500_charger_ac_get_property,
33268c0984e5SSebastian Reichel };
33278c0984e5SSebastian Reichel 
33288c0984e5SSebastian Reichel static const struct power_supply_desc ab8500_usb_chg_desc = {
33298c0984e5SSebastian Reichel 	.name		= "ab8500_usb",
33308c0984e5SSebastian Reichel 	.type		= POWER_SUPPLY_TYPE_USB,
33318c0984e5SSebastian Reichel 	.properties	= ab8500_charger_usb_props,
33328c0984e5SSebastian Reichel 	.num_properties	= ARRAY_SIZE(ab8500_charger_usb_props),
33338c0984e5SSebastian Reichel 	.get_property	= ab8500_charger_usb_get_property,
33348c0984e5SSebastian Reichel };
33358c0984e5SSebastian Reichel 
33361c1f13a0SLinus Walleij static int ab8500_charger_bind(struct device *dev)
33371c1f13a0SLinus Walleij {
33381c1f13a0SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
33391c1f13a0SLinus Walleij 	int ch_stat;
33401c1f13a0SLinus Walleij 	int ret;
33411c1f13a0SLinus Walleij 
33421c1f13a0SLinus Walleij 	/* Create a work queue for the charger */
33431c1f13a0SLinus Walleij 	di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq",
33441c1f13a0SLinus Walleij 						 WQ_MEM_RECLAIM);
33451c1f13a0SLinus Walleij 	if (di->charger_wq == NULL) {
33461c1f13a0SLinus Walleij 		dev_err(dev, "failed to create work queue\n");
33471c1f13a0SLinus Walleij 		return -ENOMEM;
33481c1f13a0SLinus Walleij 	}
33491c1f13a0SLinus Walleij 
33501c1f13a0SLinus Walleij 	ch_stat = ab8500_charger_detect_chargers(di, false);
33511c1f13a0SLinus Walleij 
33521c1f13a0SLinus Walleij 	if (ch_stat & AC_PW_CONN) {
33531c1f13a0SLinus Walleij 		if (is_ab8500(di->parent))
33541c1f13a0SLinus Walleij 			queue_delayed_work(di->charger_wq,
33551c1f13a0SLinus Walleij 					   &di->ac_charger_attached_work,
33561c1f13a0SLinus Walleij 					   HZ);
33571c1f13a0SLinus Walleij 	}
33581c1f13a0SLinus Walleij 	if (ch_stat & USB_PW_CONN) {
33591c1f13a0SLinus Walleij 		if (is_ab8500(di->parent))
33601c1f13a0SLinus Walleij 			queue_delayed_work(di->charger_wq,
33611c1f13a0SLinus Walleij 					   &di->usb_charger_attached_work,
33621c1f13a0SLinus Walleij 					   HZ);
33631c1f13a0SLinus Walleij 		di->vbus_detected = true;
33641c1f13a0SLinus Walleij 		di->vbus_detected_start = true;
33651c1f13a0SLinus Walleij 		queue_work(di->charger_wq,
33661c1f13a0SLinus Walleij 			   &di->detect_usb_type_work);
33671c1f13a0SLinus Walleij 	}
33681c1f13a0SLinus Walleij 
33691c1f13a0SLinus Walleij 	ret = component_bind_all(dev, di);
33701c1f13a0SLinus Walleij 	if (ret) {
33711c1f13a0SLinus Walleij 		dev_err(dev, "can't bind component devices\n");
33721c1f13a0SLinus Walleij 		return ret;
33731c1f13a0SLinus Walleij 	}
33741c1f13a0SLinus Walleij 
33751c1f13a0SLinus Walleij 	return 0;
33761c1f13a0SLinus Walleij }
33771c1f13a0SLinus Walleij 
33781c1f13a0SLinus Walleij static void ab8500_charger_unbind(struct device *dev)
33791c1f13a0SLinus Walleij {
33801c1f13a0SLinus Walleij 	struct ab8500_charger *di = dev_get_drvdata(dev);
33811c1f13a0SLinus Walleij 	int ret;
33821c1f13a0SLinus Walleij 
33831c1f13a0SLinus Walleij 	/* Disable AC charging */
33841c1f13a0SLinus Walleij 	ab8500_charger_ac_en(&di->ac_chg, false, 0, 0);
33851c1f13a0SLinus Walleij 
33861c1f13a0SLinus Walleij 	/* Disable USB charging */
33871c1f13a0SLinus Walleij 	ab8500_charger_usb_en(&di->usb_chg, false, 0, 0);
33881c1f13a0SLinus Walleij 
33891c1f13a0SLinus Walleij 	/* Backup battery voltage and current disable */
33901c1f13a0SLinus Walleij 	ret = abx500_mask_and_set_register_interruptible(di->dev,
33911c1f13a0SLinus Walleij 		AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0);
33921c1f13a0SLinus Walleij 	if (ret < 0)
33931c1f13a0SLinus Walleij 		dev_err(di->dev, "%s mask and set failed\n", __func__);
33941c1f13a0SLinus Walleij 
33951c1f13a0SLinus Walleij 	/* Delete the work queue */
33961c1f13a0SLinus Walleij 	destroy_workqueue(di->charger_wq);
33971c1f13a0SLinus Walleij 
33981c1f13a0SLinus Walleij 	flush_scheduled_work();
33991c1f13a0SLinus Walleij 
34001c1f13a0SLinus Walleij 	/* Unbind fg, btemp, algorithm */
34011c1f13a0SLinus Walleij 	component_unbind_all(dev, di);
34021c1f13a0SLinus Walleij }
34031c1f13a0SLinus Walleij 
34041c1f13a0SLinus Walleij static const struct component_master_ops ab8500_charger_comp_ops = {
34051c1f13a0SLinus Walleij 	.bind = ab8500_charger_bind,
34061c1f13a0SLinus Walleij 	.unbind = ab8500_charger_unbind,
34071c1f13a0SLinus Walleij };
34081c1f13a0SLinus Walleij 
34091c1f13a0SLinus Walleij static struct platform_driver *const ab8500_charger_component_drivers[] = {
34101c1f13a0SLinus Walleij 	&ab8500_fg_driver,
34111c1f13a0SLinus Walleij 	&ab8500_btemp_driver,
3412c5b64a99SLinus Walleij 	&ab8500_chargalg_driver,
34131c1f13a0SLinus Walleij };
34141c1f13a0SLinus Walleij 
34151c1f13a0SLinus Walleij static int ab8500_charger_compare_dev(struct device *dev, void *data)
34161c1f13a0SLinus Walleij {
34171c1f13a0SLinus Walleij 	return dev == data;
34181c1f13a0SLinus Walleij }
34191c1f13a0SLinus Walleij 
34208c0984e5SSebastian Reichel static int ab8500_charger_probe(struct platform_device *pdev)
34218c0984e5SSebastian Reichel {
34221c1f13a0SLinus Walleij 	struct device *dev = &pdev->dev;
34231c1f13a0SLinus Walleij 	struct device_node *np = dev->of_node;
34241c1f13a0SLinus Walleij 	struct component_match *match = NULL;
34258c0984e5SSebastian Reichel 	struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {};
34268c0984e5SSebastian Reichel 	struct ab8500_charger *di;
34271c1f13a0SLinus Walleij 	int charger_status;
34281c1f13a0SLinus Walleij 	int i, irq;
34291c1f13a0SLinus Walleij 	int ret;
34308c0984e5SSebastian Reichel 
3431ad89cb5fSLinus Walleij 	di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
3432ad89cb5fSLinus Walleij 	if (!di)
34338c0984e5SSebastian Reichel 		return -ENOMEM;
34348c0984e5SSebastian Reichel 
3435417c0fc2SLinus Walleij 	di->bm = &ab8500_bm_data;
34368c0984e5SSebastian Reichel 
34378c0984e5SSebastian Reichel 	di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
34388c0984e5SSebastian Reichel 
34398c0984e5SSebastian Reichel 	/* get parent data */
3440ad89cb5fSLinus Walleij 	di->dev = dev;
34418c0984e5SSebastian Reichel 	di->parent = dev_get_drvdata(pdev->dev.parent);
344297ab78baSLinus Walleij 
344397ab78baSLinus Walleij 	/* Get ADC channels */
344436f1de0dSLinus Walleij 	di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v");
344597ab78baSLinus Walleij 	if (IS_ERR(di->adc_main_charger_v)) {
344636f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_v),
344736f1de0dSLinus Walleij 				    "failed to get ADC main charger voltage\n");
344836f1de0dSLinus Walleij 		return ret;
344997ab78baSLinus Walleij 	}
345036f1de0dSLinus Walleij 	di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c");
345197ab78baSLinus Walleij 	if (IS_ERR(di->adc_main_charger_c)) {
345236f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_c),
345336f1de0dSLinus Walleij 				    "failed to get ADC main charger current\n");
345436f1de0dSLinus Walleij 		return ret;
345597ab78baSLinus Walleij 	}
3456ad89cb5fSLinus Walleij 	di->adc_vbus_v = devm_iio_channel_get(dev, "vbus_v");
345797ab78baSLinus Walleij 	if (IS_ERR(di->adc_vbus_v)) {
345836f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_vbus_v),
345936f1de0dSLinus Walleij 				    "failed to get ADC USB charger voltage\n");
346036f1de0dSLinus Walleij 		return ret;
346197ab78baSLinus Walleij 	}
346236f1de0dSLinus Walleij 	di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c");
346397ab78baSLinus Walleij 	if (IS_ERR(di->adc_usb_charger_c)) {
346436f1de0dSLinus Walleij 		ret = dev_err_probe(dev, PTR_ERR(di->adc_usb_charger_c),
346536f1de0dSLinus Walleij 				    "failed to get ADC USB charger current\n");
346636f1de0dSLinus Walleij 		return ret;
346797ab78baSLinus Walleij 	}
34688c0984e5SSebastian Reichel 
34691c1f13a0SLinus Walleij 	/*
34701c1f13a0SLinus Walleij 	 * VDD ADC supply needs to be enabled from this driver when there
34711c1f13a0SLinus Walleij 	 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
34721c1f13a0SLinus Walleij 	 * interrupts during charging
34731c1f13a0SLinus Walleij 	 */
34741c1f13a0SLinus Walleij 	di->regu = devm_regulator_get(dev, "vddadc");
34751c1f13a0SLinus Walleij 	if (IS_ERR(di->regu)) {
34761c1f13a0SLinus Walleij 		ret = PTR_ERR(di->regu);
34771c1f13a0SLinus Walleij 		dev_err(dev, "failed to get vddadc regulator\n");
34781c1f13a0SLinus Walleij 		return ret;
34791c1f13a0SLinus Walleij 	}
34801c1f13a0SLinus Walleij 
34811c1f13a0SLinus Walleij 	/* Request interrupts */
34821c1f13a0SLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
34831c1f13a0SLinus Walleij 		irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
34841c1f13a0SLinus Walleij 		if (irq < 0)
34851c1f13a0SLinus Walleij 			return irq;
34861c1f13a0SLinus Walleij 
34871c1f13a0SLinus Walleij 		ret = devm_request_threaded_irq(dev,
34881c1f13a0SLinus Walleij 			irq, NULL, ab8500_charger_irq[i].isr,
34891c1f13a0SLinus Walleij 			IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
34901c1f13a0SLinus Walleij 			ab8500_charger_irq[i].name, di);
34911c1f13a0SLinus Walleij 
34921c1f13a0SLinus Walleij 		if (ret != 0) {
34931c1f13a0SLinus Walleij 			dev_err(dev, "failed to request %s IRQ %d: %d\n"
34941c1f13a0SLinus Walleij 				, ab8500_charger_irq[i].name, irq, ret);
34951c1f13a0SLinus Walleij 			return ret;
34961c1f13a0SLinus Walleij 		}
34971c1f13a0SLinus Walleij 		dev_dbg(dev, "Requested %s IRQ %d: %d\n",
34981c1f13a0SLinus Walleij 			ab8500_charger_irq[i].name, irq, ret);
34991c1f13a0SLinus Walleij 	}
35001c1f13a0SLinus Walleij 
35018c0984e5SSebastian Reichel 	/* initialize lock */
35028c0984e5SSebastian Reichel 	spin_lock_init(&di->usb_state.usb_lock);
35038c0984e5SSebastian Reichel 	mutex_init(&di->usb_ipt_crnt_lock);
35048c0984e5SSebastian Reichel 
35058c0984e5SSebastian Reichel 	di->autopower = false;
35068c0984e5SSebastian Reichel 	di->invalid_charger_detect_state = 0;
35078c0984e5SSebastian Reichel 
35088c0984e5SSebastian Reichel 	/* AC and USB supply config */
350959f1b854SLinus Walleij 	ac_psy_cfg.of_node = np;
35108c0984e5SSebastian Reichel 	ac_psy_cfg.supplied_to = supply_interface;
35118c0984e5SSebastian Reichel 	ac_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
35128c0984e5SSebastian Reichel 	ac_psy_cfg.drv_data = &di->ac_chg;
351359f1b854SLinus Walleij 	usb_psy_cfg.of_node = np;
35148c0984e5SSebastian Reichel 	usb_psy_cfg.supplied_to = supply_interface;
35158c0984e5SSebastian Reichel 	usb_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
35168c0984e5SSebastian Reichel 	usb_psy_cfg.drv_data = &di->usb_chg;
35178c0984e5SSebastian Reichel 
35188c0984e5SSebastian Reichel 	/* AC supply */
35198c0984e5SSebastian Reichel 	/* ux500_charger sub-class */
35208c0984e5SSebastian Reichel 	di->ac_chg.ops.enable = &ab8500_charger_ac_en;
35218c0984e5SSebastian Reichel 	di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable;
35228c0984e5SSebastian Reichel 	di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
35238c0984e5SSebastian Reichel 	di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current;
35248c0984e5SSebastian Reichel 	di->ac_chg.max_out_volt = ab8500_charger_voltage_map[
35258c0984e5SSebastian Reichel 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
3526*83e5aa77SLinus Walleij 	di->ac_chg.max_out_curr_ua =
35273aca6ecdSLinus Walleij 		ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
35288c0984e5SSebastian Reichel 	di->ac_chg.wdt_refresh = CHG_WD_INTERVAL;
3529f9184a22SLinus Walleij 	/*
3530f9184a22SLinus Walleij 	 * The AB8505 only supports USB charging. If we are not the
3531f9184a22SLinus Walleij 	 * AB8505, register an AC charger.
3532f9184a22SLinus Walleij 	 *
3533f9184a22SLinus Walleij 	 * TODO: if this should be opt-in, add DT properties for this.
3534f9184a22SLinus Walleij 	 */
3535f9184a22SLinus Walleij 	if (!is_ab8505(di->parent))
3536f9184a22SLinus Walleij 		di->ac_chg.enabled = true;
35378c0984e5SSebastian Reichel 	di->ac_chg.external = false;
35388c0984e5SSebastian Reichel 
35398c0984e5SSebastian Reichel 	/* USB supply */
35408c0984e5SSebastian Reichel 	/* ux500_charger sub-class */
35418c0984e5SSebastian Reichel 	di->usb_chg.ops.enable = &ab8500_charger_usb_en;
35428c0984e5SSebastian Reichel 	di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
35438c0984e5SSebastian Reichel 	di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
35448c0984e5SSebastian Reichel 	di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current;
35458c0984e5SSebastian Reichel 	di->usb_chg.max_out_volt = ab8500_charger_voltage_map[
35468c0984e5SSebastian Reichel 		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
3547*83e5aa77SLinus Walleij 	di->usb_chg.max_out_curr_ua =
35483aca6ecdSLinus Walleij 		ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
35498c0984e5SSebastian Reichel 	di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
35508c0984e5SSebastian Reichel 	di->usb_chg.external = false;
3551*83e5aa77SLinus Walleij 	di->usb_state.usb_current_ua = -1;
35528c0984e5SSebastian Reichel 
35538c0984e5SSebastian Reichel 	mutex_init(&di->charger_attached_mutex);
35548c0984e5SSebastian Reichel 
35558c0984e5SSebastian Reichel 	/* Init work for HW failure check */
35568c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_hw_failure_work,
35578c0984e5SSebastian Reichel 		ab8500_charger_check_hw_failure_work);
35588c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work,
35598c0984e5SSebastian Reichel 		ab8500_charger_check_usbchargernotok_work);
35608c0984e5SSebastian Reichel 
35618c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->ac_charger_attached_work,
35628c0984e5SSebastian Reichel 			  ab8500_charger_ac_attached_work);
35638c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->usb_charger_attached_work,
35648c0984e5SSebastian Reichel 			  ab8500_charger_usb_attached_work);
35658c0984e5SSebastian Reichel 
35668c0984e5SSebastian Reichel 	/*
35678c0984e5SSebastian Reichel 	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
3568ddb74e98SAshish Chavan 	 * logic. That means we have to continuously kick the charger
35698c0984e5SSebastian Reichel 	 * watchdog even when no charger is connected. This is only
35708c0984e5SSebastian Reichel 	 * valid once the AC charger has been enabled. This is
35718c0984e5SSebastian Reichel 	 * a bug that is not handled by the algorithm and the
35728c0984e5SSebastian Reichel 	 * watchdog have to be kicked by the charger driver
35738c0984e5SSebastian Reichel 	 * when the AC charger is disabled
35748c0984e5SSebastian Reichel 	 */
35758c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->kick_wd_work,
35768c0984e5SSebastian Reichel 		ab8500_charger_kick_watchdog_work);
35778c0984e5SSebastian Reichel 
35788c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&di->check_vbat_work,
35798c0984e5SSebastian Reichel 		ab8500_charger_check_vbat_work);
35808c0984e5SSebastian Reichel 
35818c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->attach_work,
35828c0984e5SSebastian Reichel 		ab8500_charger_usb_link_attach_work);
35838c0984e5SSebastian Reichel 
35848c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->usb_state_changed_work,
35858c0984e5SSebastian Reichel 		ab8500_charger_usb_state_changed_work);
35868c0984e5SSebastian Reichel 
35878c0984e5SSebastian Reichel 	INIT_DELAYED_WORK(&di->vbus_drop_end_work,
35888c0984e5SSebastian Reichel 		ab8500_charger_vbus_drop_end_work);
35898c0984e5SSebastian Reichel 
35908c0984e5SSebastian Reichel 	/* Init work for charger detection */
35918c0984e5SSebastian Reichel 	INIT_WORK(&di->usb_link_status_work,
35928c0984e5SSebastian Reichel 		ab8500_charger_usb_link_status_work);
35938c0984e5SSebastian Reichel 	INIT_WORK(&di->ac_work, ab8500_charger_ac_work);
35948c0984e5SSebastian Reichel 	INIT_WORK(&di->detect_usb_type_work,
35958c0984e5SSebastian Reichel 		ab8500_charger_detect_usb_type_work);
35968c0984e5SSebastian Reichel 
35978c0984e5SSebastian Reichel 	/* Init work for checking HW status */
35988c0984e5SSebastian Reichel 	INIT_WORK(&di->check_main_thermal_prot_work,
35998c0984e5SSebastian Reichel 		ab8500_charger_check_main_thermal_prot_work);
36008c0984e5SSebastian Reichel 	INIT_WORK(&di->check_usb_thermal_prot_work,
36018c0984e5SSebastian Reichel 		ab8500_charger_check_usb_thermal_prot_work);
36028c0984e5SSebastian Reichel 
36038c0984e5SSebastian Reichel 
36048c0984e5SSebastian Reichel 	/* Initialize OVV, and other registers */
36058c0984e5SSebastian Reichel 	ret = ab8500_charger_init_hw_registers(di);
36068c0984e5SSebastian Reichel 	if (ret) {
3607ad89cb5fSLinus Walleij 		dev_err(dev, "failed to initialize ABB registers\n");
36081c1f13a0SLinus Walleij 		return ret;
36098c0984e5SSebastian Reichel 	}
36108c0984e5SSebastian Reichel 
36118c0984e5SSebastian Reichel 	/* Register AC charger class */
36128c0984e5SSebastian Reichel 	if (di->ac_chg.enabled) {
36131c1f13a0SLinus Walleij 		di->ac_chg.psy = devm_power_supply_register(dev,
36148c0984e5SSebastian Reichel 						       &ab8500_ac_chg_desc,
36158c0984e5SSebastian Reichel 						       &ac_psy_cfg);
36168c0984e5SSebastian Reichel 		if (IS_ERR(di->ac_chg.psy)) {
3617ad89cb5fSLinus Walleij 			dev_err(dev, "failed to register AC charger\n");
36181c1f13a0SLinus Walleij 			return PTR_ERR(di->ac_chg.psy);
36198c0984e5SSebastian Reichel 		}
36208c0984e5SSebastian Reichel 	}
36218c0984e5SSebastian Reichel 
36228c0984e5SSebastian Reichel 	/* Register USB charger class */
36231c1f13a0SLinus Walleij 	di->usb_chg.psy = devm_power_supply_register(dev,
36248c0984e5SSebastian Reichel 						     &ab8500_usb_chg_desc,
36258c0984e5SSebastian Reichel 						     &usb_psy_cfg);
36268c0984e5SSebastian Reichel 	if (IS_ERR(di->usb_chg.psy)) {
3627ad89cb5fSLinus Walleij 		dev_err(dev, "failed to register USB charger\n");
36281c1f13a0SLinus Walleij 		return PTR_ERR(di->usb_chg.psy);
36298c0984e5SSebastian Reichel 	}
36308c0984e5SSebastian Reichel 
363159f1b854SLinus Walleij 	/*
363259f1b854SLinus Walleij 	 * Check what battery we have, since we always have the USB
363359f1b854SLinus Walleij 	 * psy, use that as a handle.
363459f1b854SLinus Walleij 	 */
363559f1b854SLinus Walleij 	ret = ab8500_bm_of_probe(di->usb_chg.psy, di->bm);
363659f1b854SLinus Walleij 	if (ret)
363759f1b854SLinus Walleij 		return dev_err_probe(dev, ret,
363859f1b854SLinus Walleij 				     "failed to get battery information\n");
363959f1b854SLinus Walleij 
36408c0984e5SSebastian Reichel 	/* Identify the connected charger types during startup */
36418c0984e5SSebastian Reichel 	charger_status = ab8500_charger_detect_chargers(di, true);
36428c0984e5SSebastian Reichel 	if (charger_status & AC_PW_CONN) {
36438c0984e5SSebastian Reichel 		di->ac.charger_connected = 1;
36448c0984e5SSebastian Reichel 		di->ac_conn = true;
36458c0984e5SSebastian Reichel 		ab8500_power_supply_changed(di, di->ac_chg.psy);
36468c0984e5SSebastian Reichel 		sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
36478c0984e5SSebastian Reichel 	}
36488c0984e5SSebastian Reichel 
36498c0984e5SSebastian Reichel 	platform_set_drvdata(pdev, di);
36508c0984e5SSebastian Reichel 
36511c1f13a0SLinus Walleij 	/* Create something that will match the subdrivers when we bind */
36521c1f13a0SLinus Walleij 	for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) {
36531c1f13a0SLinus Walleij 		struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver;
36541c1f13a0SLinus Walleij 		struct device *p = NULL, *d;
36558c0984e5SSebastian Reichel 
36561c1f13a0SLinus Walleij 		while ((d = platform_find_device_by_driver(p, drv))) {
36571c1f13a0SLinus Walleij 			put_device(p);
36581c1f13a0SLinus Walleij 			component_match_add(dev, &match,
36591c1f13a0SLinus Walleij 					    ab8500_charger_compare_dev, d);
36601c1f13a0SLinus Walleij 			p = d;
36618c0984e5SSebastian Reichel 		}
36621c1f13a0SLinus Walleij 		put_device(p);
36631c1f13a0SLinus Walleij 	}
36641c1f13a0SLinus Walleij 	if (!match) {
36651c1f13a0SLinus Walleij 		dev_err(dev, "no matching components\n");
36661c1f13a0SLinus Walleij 		return -ENODEV;
36671c1f13a0SLinus Walleij 	}
36681c1f13a0SLinus Walleij 	if (IS_ERR(match)) {
36691c1f13a0SLinus Walleij 		dev_err(dev, "could not create component match\n");
36701c1f13a0SLinus Walleij 		return PTR_ERR(match);
36718c0984e5SSebastian Reichel 	}
36728c0984e5SSebastian Reichel 
36731c1f13a0SLinus Walleij 	/* Notifier for external charger enabling */
36741c1f13a0SLinus Walleij 	if (!di->ac_chg.enabled)
36751c1f13a0SLinus Walleij 		blocking_notifier_chain_register(
36761c1f13a0SLinus Walleij 			&charger_notifier_list, &charger_nb);
36778c0984e5SSebastian Reichel 
36788c0984e5SSebastian Reichel 
36791c1f13a0SLinus Walleij 	di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
36801c1f13a0SLinus Walleij 	if (IS_ERR_OR_NULL(di->usb_phy)) {
36811c1f13a0SLinus Walleij 		dev_err(dev, "failed to get usb transceiver\n");
36821c1f13a0SLinus Walleij 		ret = -EINVAL;
36831c1f13a0SLinus Walleij 		goto out_charger_notifier;
36841c1f13a0SLinus Walleij 	}
36851c1f13a0SLinus Walleij 	di->nb.notifier_call = ab8500_charger_usb_notifier_call;
36861c1f13a0SLinus Walleij 	ret = usb_register_notifier(di->usb_phy, &di->nb);
36871c1f13a0SLinus Walleij 	if (ret) {
36881c1f13a0SLinus Walleij 		dev_err(dev, "failed to register usb notifier\n");
36891c1f13a0SLinus Walleij 		goto put_usb_phy;
36901c1f13a0SLinus Walleij 	}
36911c1f13a0SLinus Walleij 
36921c1f13a0SLinus Walleij 
36931c1f13a0SLinus Walleij 	ret = component_master_add_with_match(&pdev->dev,
36941c1f13a0SLinus Walleij 					      &ab8500_charger_comp_ops,
36951c1f13a0SLinus Walleij 					      match);
36961c1f13a0SLinus Walleij 	if (ret) {
36971c1f13a0SLinus Walleij 		dev_err(dev, "failed to add component master\n");
36981c1f13a0SLinus Walleij 		goto free_notifier;
36991c1f13a0SLinus Walleij 	}
37001c1f13a0SLinus Walleij 
37011c1f13a0SLinus Walleij 	return 0;
37021c1f13a0SLinus Walleij 
37031c1f13a0SLinus Walleij free_notifier:
37048c0984e5SSebastian Reichel 	usb_unregister_notifier(di->usb_phy, &di->nb);
37058c0984e5SSebastian Reichel put_usb_phy:
37068c0984e5SSebastian Reichel 	usb_put_phy(di->usb_phy);
37071c1f13a0SLinus Walleij out_charger_notifier:
37081c1f13a0SLinus Walleij 	if (!di->ac_chg.enabled)
37091c1f13a0SLinus Walleij 		blocking_notifier_chain_unregister(
37101c1f13a0SLinus Walleij 			&charger_notifier_list, &charger_nb);
37118c0984e5SSebastian Reichel 	return ret;
37128c0984e5SSebastian Reichel }
37138c0984e5SSebastian Reichel 
37141c1f13a0SLinus Walleij static int ab8500_charger_remove(struct platform_device *pdev)
37151c1f13a0SLinus Walleij {
37161c1f13a0SLinus Walleij 	struct ab8500_charger *di = platform_get_drvdata(pdev);
37171c1f13a0SLinus Walleij 
37181c1f13a0SLinus Walleij 	component_master_del(&pdev->dev, &ab8500_charger_comp_ops);
37191c1f13a0SLinus Walleij 
37201c1f13a0SLinus Walleij 	usb_unregister_notifier(di->usb_phy, &di->nb);
37216252c706SLinus Walleij 	ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
37221c1f13a0SLinus Walleij 	usb_put_phy(di->usb_phy);
37231c1f13a0SLinus Walleij 	if (!di->ac_chg.enabled)
37241c1f13a0SLinus Walleij 		blocking_notifier_chain_unregister(
37251c1f13a0SLinus Walleij 			&charger_notifier_list, &charger_nb);
37261c1f13a0SLinus Walleij 
37271c1f13a0SLinus Walleij 	return 0;
37281c1f13a0SLinus Walleij }
37291c1f13a0SLinus Walleij 
3730f8efa0a8SLinus Walleij static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume);
3731f8efa0a8SLinus Walleij 
37328c0984e5SSebastian Reichel static const struct of_device_id ab8500_charger_match[] = {
37338c0984e5SSebastian Reichel 	{ .compatible = "stericsson,ab8500-charger", },
37348c0984e5SSebastian Reichel 	{ },
37358c0984e5SSebastian Reichel };
3736dfe52db1SZou Wei MODULE_DEVICE_TABLE(of, ab8500_charger_match);
37378c0984e5SSebastian Reichel 
37388c0984e5SSebastian Reichel static struct platform_driver ab8500_charger_driver = {
37398c0984e5SSebastian Reichel 	.probe = ab8500_charger_probe,
37408c0984e5SSebastian Reichel 	.remove = ab8500_charger_remove,
37418c0984e5SSebastian Reichel 	.driver = {
37428c0984e5SSebastian Reichel 		.name = "ab8500-charger",
37438c0984e5SSebastian Reichel 		.of_match_table = ab8500_charger_match,
3744f8efa0a8SLinus Walleij 		.pm = &ab8500_charger_pm_ops,
37458c0984e5SSebastian Reichel 	},
37468c0984e5SSebastian Reichel };
37478c0984e5SSebastian Reichel 
37488c0984e5SSebastian Reichel static int __init ab8500_charger_init(void)
37498c0984e5SSebastian Reichel {
37501c1f13a0SLinus Walleij 	int ret;
37511c1f13a0SLinus Walleij 
37521c1f13a0SLinus Walleij 	ret = platform_register_drivers(ab8500_charger_component_drivers,
37531c1f13a0SLinus Walleij 			ARRAY_SIZE(ab8500_charger_component_drivers));
37541c1f13a0SLinus Walleij 	if (ret)
37551c1f13a0SLinus Walleij 		return ret;
37561c1f13a0SLinus Walleij 
37578c0984e5SSebastian Reichel 	return platform_driver_register(&ab8500_charger_driver);
37588c0984e5SSebastian Reichel }
37598c0984e5SSebastian Reichel 
37608c0984e5SSebastian Reichel static void __exit ab8500_charger_exit(void)
37618c0984e5SSebastian Reichel {
37621c1f13a0SLinus Walleij 	platform_unregister_drivers(ab8500_charger_component_drivers,
37631c1f13a0SLinus Walleij 			ARRAY_SIZE(ab8500_charger_component_drivers));
37648c0984e5SSebastian Reichel 	platform_driver_unregister(&ab8500_charger_driver);
37658c0984e5SSebastian Reichel }
37668c0984e5SSebastian Reichel 
37671c1f13a0SLinus Walleij module_init(ab8500_charger_init);
37688c0984e5SSebastian Reichel module_exit(ab8500_charger_exit);
37698c0984e5SSebastian Reichel 
37708c0984e5SSebastian Reichel MODULE_LICENSE("GPL v2");
37718c0984e5SSebastian Reichel MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
37728c0984e5SSebastian Reichel MODULE_ALIAS("platform:ab8500-charger");
37738c0984e5SSebastian Reichel MODULE_DESCRIPTION("AB8500 charger management driver");
3774