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