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>
188891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#include <linux/notifier.h>
1984edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/slab.h>
2084edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/platform_device.h>
2184edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/power_supply.h>
2284edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/completion.h>
2384edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/regulator/consumer.h>
2484edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/err.h>
2584edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/workqueue.h>
2684edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/kobject.h>
274aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V#include <linux/of.h>
284aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V#include <linux/mfd/core.h>
2984edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500.h>
3084edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500.h>
3184edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500-bm.h>
3284edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ab8500-gpadc.h>
3384edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/mfd/abx500/ux500_chargalg.h>
3484edbeeab67c1575067335179513150115da367bArun Murthy#include <linux/usb/otg.h>
35b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#include <linux/mutex.h>
3684edbeeab67c1575067335179513150115da367bArun Murthy
3784edbeeab67c1575067335179513150115da367bArun Murthy/* Charger constants */
3884edbeeab67c1575067335179513150115da367bArun Murthy#define NO_PW_CONN			0
3984edbeeab67c1575067335179513150115da367bArun Murthy#define AC_PW_CONN			1
4084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_PW_CONN			2
4184edbeeab67c1575067335179513150115da367bArun Murthy
4284edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_ENA			0x01
4384edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_KICK			0x02
4484edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_WDOG_DIS			0x00
4584edbeeab67c1575067335179513150115da367bArun Murthy#define CHARG_WD_KICK			0x01
4684edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_ENA			0x01
4784edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_NO_OVERSHOOT_ENA_N	0x02
4884edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_ENA			0x01
4984edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CHG_NO_OVERSHOOT_ENA_N	0x02
5084edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_DET			0x01
5184edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_CV_ON			0x04
5284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_CV_ON			0x08
5384edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET_DBNC100		0x02
5484edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET_DBNC1			0x01
5584edbeeab67c1575067335179513150115da367bArun Murthy#define OTP_ENABLE_WD			0x01
564dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones#define DROP_COUNT_RESET		0x01
57b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper#define USB_CH_DET			0x01
5884edbeeab67c1575067335179513150115da367bArun Murthy
5984edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_INPUT_CURR_SHIFT	4
6084edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_IN_CURR_LIM_SHIFT		4
61861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones#define AB8540_VBUS_IN_CURR_LIM_SHIFT	2
6234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson#define AUTO_VBUS_IN_CURR_LIM_SHIFT	4
63861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones#define AB8540_AUTO_VBUS_IN_CURR_MASK	0x3F
64f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones#define VBUS_IN_CURR_LIM_RETRY_SET_TIME	30 /* seconds */
6584edbeeab67c1575067335179513150115da367bArun Murthy
6684edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_ENA		0x01
6784edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_DIS		0x00
6884edbeeab67c1575067335179513150115da367bArun Murthy#define LED_IND_CUR_5MA			0x04
6984edbeeab67c1575067335179513150115da367bArun Murthy#define LED_INDICATOR_PWM_DUTY_252_256	0xBF
7084edbeeab67c1575067335179513150115da367bArun Murthy
7184edbeeab67c1575067335179513150115da367bArun Murthy/* HW failure constants */
7284edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_TH_PROT			0x02
7384edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_CH_NOK			0x08
7484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_TH_PROT			0x02
7584edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_OVV_TH			0x01
7684edbeeab67c1575067335179513150115da367bArun Murthy#define MAIN_CH_NOK			0x01
7784edbeeab67c1575067335179513150115da367bArun Murthy#define VBUS_DET			0x80
7884edbeeab67c1575067335179513150115da367bArun Murthy
79b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define MAIN_CH_STATUS2_MAINCHGDROP		0x80
80b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define MAIN_CH_STATUS2_MAINCHARGERDETDBNC	0x40
81b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define USB_CH_VBUSDROP				0x40
82b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define USB_CH_VBUSDETDBNC			0x01
83b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
8484edbeeab67c1575067335179513150115da367bArun Murthy/* UsbLineStatus register bit masks */
8584edbeeab67c1575067335179513150115da367bArun Murthy#define AB8500_USB_LINK_STATUS		0x78
86d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg#define AB8505_USB_LINK_STATUS		0xF8
8784edbeeab67c1575067335179513150115da367bArun Murthy#define AB8500_STD_HOST_SUSP		0x18
88861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones#define USB_LINK_STATUS_SHIFT		3
8984edbeeab67c1575067335179513150115da367bArun Murthy
9084edbeeab67c1575067335179513150115da367bArun Murthy/* Watchdog timeout constant */
9184edbeeab67c1575067335179513150115da367bArun Murthy#define WD_TIMER			0x30 /* 4min */
9284edbeeab67c1575067335179513150115da367bArun Murthy#define WD_KICK_INTERVAL		(60 * HZ)
9384edbeeab67c1575067335179513150115da367bArun Murthy
9484edbeeab67c1575067335179513150115da367bArun Murthy/* Lowest charger voltage is 3.39V -> 0x4E */
9584edbeeab67c1575067335179513150115da367bArun Murthy#define LOW_VOLT_REG			0x4E
9684edbeeab67c1575067335179513150115da367bArun Murthy
97f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/* Step up/down delay in us */
98f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt#define STEP_UDELAY			1000
99f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt
100b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones#define CHARGER_STATUS_POLL 10 /* in ms */
101b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
102e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy#define CHG_WD_INTERVAL			(60 * HZ)
103e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy
104b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion#define AB8500_SW_CONTROL_FALLBACK	0x03
10534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson/* Wait for enumeration before charing in us */
10634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson#define WAIT_ACA_RID_ENUMERATION	(5 * 1000)
1078891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones/*External charger control*/
1088891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#define AB8500_SYS_CHARGER_CONTROL_REG		0x52
1098891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#define EXTERNAL_CHARGER_DISABLE_REG_VAL	0x03
1108891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones#define EXTERNAL_CHARGER_ENABLE_REG_VAL		0x07
111b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion
11284edbeeab67c1575067335179513150115da367bArun Murthy/* UsbLineStatus register - usb types */
11384edbeeab67c1575067335179513150115da367bArun Murthyenum ab8500_charger_link_status {
11484edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_NOT_CONFIGURED,
11584edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_STD_HOST_NC,
11684edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_STD_HOST_C_NS,
11784edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_STD_HOST_C_S,
11884edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_HOST_CHG_NM,
11984edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_HOST_CHG_HS,
12084edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_HOST_CHG_HS_CHIRP,
12184edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_DEDICATED_CHG,
12284edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_ACA_RID_A,
12384edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_ACA_RID_B,
12484edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_ACA_RID_C_NM,
12584edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_ACA_RID_C_HS,
12684edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_ACA_RID_C_HS_CHIRP,
12784edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_HM_IDGND,
12884edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_RESERVED,
12984edbeeab67c1575067335179513150115da367bArun Murthy	USB_STAT_NOT_VALID_LINK,
13074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	USB_STAT_PHY_EN,
13174a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	USB_STAT_SUP_NO_IDGND_VBUS,
13274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	USB_STAT_SUP_IDGND_VBUS,
13374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	USB_STAT_CHARGER_LINE_1,
13474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	USB_STAT_CARKIT_1,
13574a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	USB_STAT_CARKIT_2,
13674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	USB_STAT_ACA_DOCK_CHARGER,
13784edbeeab67c1575067335179513150115da367bArun Murthy};
13884edbeeab67c1575067335179513150115da367bArun Murthy
13984edbeeab67c1575067335179513150115da367bArun Murthyenum ab8500_usb_state {
14084edbeeab67c1575067335179513150115da367bArun Murthy	AB8500_BM_USB_STATE_RESET_HS,	/* HighSpeed Reset */
14184edbeeab67c1575067335179513150115da367bArun Murthy	AB8500_BM_USB_STATE_RESET_FS,	/* FullSpeed/LowSpeed Reset */
14284edbeeab67c1575067335179513150115da367bArun Murthy	AB8500_BM_USB_STATE_CONFIGURED,
14384edbeeab67c1575067335179513150115da367bArun Murthy	AB8500_BM_USB_STATE_SUSPEND,
14484edbeeab67c1575067335179513150115da367bArun Murthy	AB8500_BM_USB_STATE_RESUME,
14584edbeeab67c1575067335179513150115da367bArun Murthy	AB8500_BM_USB_STATE_MAX,
14684edbeeab67c1575067335179513150115da367bArun Murthy};
14784edbeeab67c1575067335179513150115da367bArun Murthy
14884edbeeab67c1575067335179513150115da367bArun Murthy/* VBUS input current limits supported in AB8500 in mA */
14984edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P05		50
15084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P09		98
15184edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P19		193
15284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P29		290
15384edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P38		380
15484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P45		450
15584edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P5		500
15684edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P6		600
15784edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P7		700
15884edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P8		800
15984edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_0P9		900
16084edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P0		1000
16184edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P1		1100
16284edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P3		1300
16384edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P4		1400
16484edbeeab67c1575067335179513150115da367bArun Murthy#define USB_CH_IP_CUR_LVL_1P5		1500
16584edbeeab67c1575067335179513150115da367bArun Murthy
16684edbeeab67c1575067335179513150115da367bArun Murthy#define VBAT_TRESH_IP_CUR_RED		3800
16784edbeeab67c1575067335179513150115da367bArun Murthy
16884edbeeab67c1575067335179513150115da367bArun Murthy#define to_ab8500_charger_usb_device_info(x) container_of((x), \
16984edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger, usb_chg)
17084edbeeab67c1575067335179513150115da367bArun Murthy#define to_ab8500_charger_ac_device_info(x) container_of((x), \
17184edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger, ac_chg)
17284edbeeab67c1575067335179513150115da367bArun Murthy
17384edbeeab67c1575067335179513150115da367bArun Murthy/**
17484edbeeab67c1575067335179513150115da367bArun Murthy * struct ab8500_charger_interrupts - ab8500 interupts
17584edbeeab67c1575067335179513150115da367bArun Murthy * @name:	name of the interrupt
17684edbeeab67c1575067335179513150115da367bArun Murthy * @isr		function pointer to the isr
17784edbeeab67c1575067335179513150115da367bArun Murthy */
17884edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_interrupts {
17984edbeeab67c1575067335179513150115da367bArun Murthy	char *name;
18084edbeeab67c1575067335179513150115da367bArun Murthy	irqreturn_t (*isr)(int irq, void *data);
18184edbeeab67c1575067335179513150115da367bArun Murthy};
18284edbeeab67c1575067335179513150115da367bArun Murthy
18384edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_info {
18484edbeeab67c1575067335179513150115da367bArun Murthy	int charger_connected;
18584edbeeab67c1575067335179513150115da367bArun Murthy	int charger_online;
18684edbeeab67c1575067335179513150115da367bArun Murthy	int charger_voltage;
18784edbeeab67c1575067335179513150115da367bArun Murthy	int cv_active;
18884edbeeab67c1575067335179513150115da367bArun Murthy	bool wd_expired;
189a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg	int charger_current;
19084edbeeab67c1575067335179513150115da367bArun Murthy};
19184edbeeab67c1575067335179513150115da367bArun Murthy
19284edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_event_flags {
19384edbeeab67c1575067335179513150115da367bArun Murthy	bool mainextchnotok;
19484edbeeab67c1575067335179513150115da367bArun Murthy	bool main_thermal_prot;
19584edbeeab67c1575067335179513150115da367bArun Murthy	bool usb_thermal_prot;
19684edbeeab67c1575067335179513150115da367bArun Murthy	bool vbus_ovv;
19784edbeeab67c1575067335179513150115da367bArun Murthy	bool usbchargernotok;
19884edbeeab67c1575067335179513150115da367bArun Murthy	bool chgwdexp;
19984edbeeab67c1575067335179513150115da367bArun Murthy	bool vbus_collapse;
20034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	bool vbus_drop_end;
20184edbeeab67c1575067335179513150115da367bArun Murthy};
20284edbeeab67c1575067335179513150115da367bArun Murthy
20384edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger_usb_state {
20484edbeeab67c1575067335179513150115da367bArun Murthy	int usb_current;
20534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	int usb_current_tmp;
20684edbeeab67c1575067335179513150115da367bArun Murthy	enum ab8500_usb_state state;
20734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	enum ab8500_usb_state state_tmp;
20884edbeeab67c1575067335179513150115da367bArun Murthy	spinlock_t usb_lock;
20984edbeeab67c1575067335179513150115da367bArun Murthy};
21084edbeeab67c1575067335179513150115da367bArun Murthy
211f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jonesstruct ab8500_charger_max_usb_in_curr {
212f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	int usb_type_max;
213f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	int set_max;
214f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	int calculated_max;
215f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones};
216f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones
21784edbeeab67c1575067335179513150115da367bArun Murthy/**
21884edbeeab67c1575067335179513150115da367bArun Murthy * struct ab8500_charger - ab8500 Charger device information
21984edbeeab67c1575067335179513150115da367bArun Murthy * @dev:		Pointer to the structure device
22084edbeeab67c1575067335179513150115da367bArun Murthy * @vbus_detected:	VBUS detected
22184edbeeab67c1575067335179513150115da367bArun Murthy * @vbus_detected_start:
22284edbeeab67c1575067335179513150115da367bArun Murthy *			VBUS detected during startup
22384edbeeab67c1575067335179513150115da367bArun Murthy * @ac_conn:		This will be true when the AC charger has been plugged
22484edbeeab67c1575067335179513150115da367bArun Murthy * @vddadc_en_ac:	Indicate if VDD ADC supply is enabled because AC
22584edbeeab67c1575067335179513150115da367bArun Murthy *			charger is enabled
22684edbeeab67c1575067335179513150115da367bArun Murthy * @vddadc_en_usb:	Indicate if VDD ADC supply is enabled because USB
22784edbeeab67c1575067335179513150115da367bArun Murthy *			charger is enabled
22884edbeeab67c1575067335179513150115da367bArun Murthy * @vbat		Battery voltage
22984edbeeab67c1575067335179513150115da367bArun Murthy * @old_vbat		Previously measured battery voltage
2304b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper * @usb_device_is_unrecognised	USB device is unrecognised by the hardware
23184edbeeab67c1575067335179513150115da367bArun Murthy * @autopower		Indicate if we should have automatic pwron after pwrloss
2324aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V * @autopower_cfg	platform specific power config support for "pwron after pwrloss"
233ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver * @invalid_charger_detect_state State when forcing AB to use invalid charger
23434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @is_aca_rid:		Incicate if accessory is ACA type
23534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @current_stepping_sessions:
23634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson *			Counter for current stepping sessions
23784edbeeab67c1575067335179513150115da367bArun Murthy * @parent:		Pointer to the struct ab8500
23884edbeeab67c1575067335179513150115da367bArun Murthy * @gpadc:		Pointer to the struct gpadc
239b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones * @bm:           	Platform specific battery management information
24084edbeeab67c1575067335179513150115da367bArun Murthy * @flags:		Structure for information about events triggered
24184edbeeab67c1575067335179513150115da367bArun Murthy * @usb_state:		Structure for usb stack information
242f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * @max_usb_in_curr:	Max USB charger input current
24384edbeeab67c1575067335179513150115da367bArun Murthy * @ac_chg:		AC charger power supply
24484edbeeab67c1575067335179513150115da367bArun Murthy * @usb_chg:		USB charger power supply
24584edbeeab67c1575067335179513150115da367bArun Murthy * @ac:			Structure that holds the AC charger properties
24684edbeeab67c1575067335179513150115da367bArun Murthy * @usb:		Structure that holds the USB charger properties
24784edbeeab67c1575067335179513150115da367bArun Murthy * @regu:		Pointer to the struct regulator
24884edbeeab67c1575067335179513150115da367bArun Murthy * @charger_wq:		Work queue for the IRQs and checking HW state
24934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @usb_ipt_crnt_lock:	Lock to protect VBUS input current setting from mutuals
25034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @pm_lock:		Lock to prevent system to suspend
25184edbeeab67c1575067335179513150115da367bArun Murthy * @check_vbat_work	Work for checking vbat threshold to adjust vbus current
25284edbeeab67c1575067335179513150115da367bArun Murthy * @check_hw_failure_work:	Work for checking HW state
25384edbeeab67c1575067335179513150115da367bArun Murthy * @check_usbchgnotok_work:	Work for checking USB charger not ok status
25484edbeeab67c1575067335179513150115da367bArun Murthy * @kick_wd_work:		Work for kicking the charger watchdog in case
25584edbeeab67c1575067335179513150115da367bArun Murthy *				of ABB rev 1.* due to the watchog logic bug
256b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * @ac_charger_attached_work:	Work for checking if AC charger is still
257b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones *				connected
258b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * @usb_charger_attached_work:	Work for checking if USB charger is still
259b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones *				connected
26084edbeeab67c1575067335179513150115da367bArun Murthy * @ac_work:			Work for checking AC charger connection
26184edbeeab67c1575067335179513150115da367bArun Murthy * @detect_usb_type_work:	Work for detecting the USB type connected
26284edbeeab67c1575067335179513150115da367bArun Murthy * @usb_link_status_work:	Work for checking the new USB link status
26384edbeeab67c1575067335179513150115da367bArun Murthy * @usb_state_changed_work:	Work for checking USB state
26434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @attach_work:		Work for detecting USB type
26534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @vbus_drop_end_work:		Work for detecting VBUS drop end
26684edbeeab67c1575067335179513150115da367bArun Murthy * @check_main_thermal_prot_work:
26784edbeeab67c1575067335179513150115da367bArun Murthy *				Work for checking Main thermal status
26884edbeeab67c1575067335179513150115da367bArun Murthy * @check_usb_thermal_prot_work:
26984edbeeab67c1575067335179513150115da367bArun Murthy *				Work for checking USB thermal status
270b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones * @charger_attached_mutex:	For controlling the wakelock
27184edbeeab67c1575067335179513150115da367bArun Murthy */
27284edbeeab67c1575067335179513150115da367bArun Murthystruct ab8500_charger {
27384edbeeab67c1575067335179513150115da367bArun Murthy	struct device *dev;
27484edbeeab67c1575067335179513150115da367bArun Murthy	bool vbus_detected;
27584edbeeab67c1575067335179513150115da367bArun Murthy	bool vbus_detected_start;
27684edbeeab67c1575067335179513150115da367bArun Murthy	bool ac_conn;
27784edbeeab67c1575067335179513150115da367bArun Murthy	bool vddadc_en_ac;
27884edbeeab67c1575067335179513150115da367bArun Murthy	bool vddadc_en_usb;
27984edbeeab67c1575067335179513150115da367bArun Murthy	int vbat;
28084edbeeab67c1575067335179513150115da367bArun Murthy	int old_vbat;
2814b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	bool usb_device_is_unrecognised;
28284edbeeab67c1575067335179513150115da367bArun Murthy	bool autopower;
2834aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	bool autopower_cfg;
284ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	int invalid_charger_detect_state;
28534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	int is_aca_rid;
28634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	atomic_t current_stepping_sessions;
28784edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500 *parent;
28884edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_gpadc *gpadc;
289b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones	struct abx500_bm_data *bm;
29084edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger_event_flags flags;
29184edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger_usb_state usb_state;
292f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	struct ab8500_charger_max_usb_in_curr max_usb_in_curr;
29384edbeeab67c1575067335179513150115da367bArun Murthy	struct ux500_charger ac_chg;
29484edbeeab67c1575067335179513150115da367bArun Murthy	struct ux500_charger usb_chg;
29584edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger_info ac;
29684edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger_info usb;
29784edbeeab67c1575067335179513150115da367bArun Murthy	struct regulator *regu;
29884edbeeab67c1575067335179513150115da367bArun Murthy	struct workqueue_struct *charger_wq;
29934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	struct mutex usb_ipt_crnt_lock;
30084edbeeab67c1575067335179513150115da367bArun Murthy	struct delayed_work check_vbat_work;
30184edbeeab67c1575067335179513150115da367bArun Murthy	struct delayed_work check_hw_failure_work;
30284edbeeab67c1575067335179513150115da367bArun Murthy	struct delayed_work check_usbchgnotok_work;
30384edbeeab67c1575067335179513150115da367bArun Murthy	struct delayed_work kick_wd_work;
30434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	struct delayed_work usb_state_changed_work;
3054b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	struct delayed_work attach_work;
306b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	struct delayed_work ac_charger_attached_work;
307b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	struct delayed_work usb_charger_attached_work;
30834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	struct delayed_work vbus_drop_end_work;
30984edbeeab67c1575067335179513150115da367bArun Murthy	struct work_struct ac_work;
31084edbeeab67c1575067335179513150115da367bArun Murthy	struct work_struct detect_usb_type_work;
31184edbeeab67c1575067335179513150115da367bArun Murthy	struct work_struct usb_link_status_work;
31284edbeeab67c1575067335179513150115da367bArun Murthy	struct work_struct check_main_thermal_prot_work;
31384edbeeab67c1575067335179513150115da367bArun Murthy	struct work_struct check_usb_thermal_prot_work;
314efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov	struct usb_phy *usb_phy;
31584edbeeab67c1575067335179513150115da367bArun Murthy	struct notifier_block nb;
316b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	struct mutex charger_attached_mutex;
31784edbeeab67c1575067335179513150115da367bArun Murthy};
31884edbeeab67c1575067335179513150115da367bArun Murthy
31984edbeeab67c1575067335179513150115da367bArun Murthy/* AC properties */
32084edbeeab67c1575067335179513150115da367bArun Murthystatic enum power_supply_property ab8500_charger_ac_props[] = {
32184edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_HEALTH,
32284edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_PRESENT,
32384edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_ONLINE,
32484edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_VOLTAGE_NOW,
32584edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_VOLTAGE_AVG,
32684edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_CURRENT_NOW,
32784edbeeab67c1575067335179513150115da367bArun Murthy};
32884edbeeab67c1575067335179513150115da367bArun Murthy
32984edbeeab67c1575067335179513150115da367bArun Murthy/* USB properties */
33084edbeeab67c1575067335179513150115da367bArun Murthystatic enum power_supply_property ab8500_charger_usb_props[] = {
33184edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_HEALTH,
33284edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_CURRENT_AVG,
33384edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_PRESENT,
33484edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_ONLINE,
33584edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_VOLTAGE_NOW,
33684edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_VOLTAGE_AVG,
33784edbeeab67c1575067335179513150115da367bArun Murthy	POWER_SUPPLY_PROP_CURRENT_NOW,
33884edbeeab67c1575067335179513150115da367bArun Murthy};
33984edbeeab67c1575067335179513150115da367bArun Murthy
340defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson/*
341defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson * Function for enabling and disabling sw fallback mode
342defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson * should always be disabled when no charger is connected.
34384edbeeab67c1575067335179513150115da367bArun Murthy */
344defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakanssonstatic void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di,
345defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson		bool fallback)
34684edbeeab67c1575067335179513150115da367bArun Murthy{
347b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	u8 val;
34884edbeeab67c1575067335179513150115da367bArun Murthy	u8 reg;
349b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	u8 bank;
350b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	u8 bit;
35184edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
35284edbeeab67c1575067335179513150115da367bArun Murthy
353defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson	dev_dbg(di->dev, "SW Fallback: %d\n", fallback);
35484edbeeab67c1575067335179513150115da367bArun Murthy
355b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	if (is_ab8500(di->parent)) {
356b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		bank = 0x15;
357b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		reg = 0x0;
358b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		bit = 3;
359b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	} else {
360b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		bank = AB8500_SYS_CTRL1_BLOCK;
361b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		reg = AB8500_SW_CONTROL_FALLBACK;
362b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		bit = 0;
363b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	}
364b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion
365defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson	/* read the register containing fallback bit */
366b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	ret = abx500_get_register_interruptible(di->dev, bank, reg, &val);
367b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	if (ret < 0) {
368b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		dev_err(di->dev, "%d read failed\n", __LINE__);
36984edbeeab67c1575067335179513150115da367bArun Murthy		return;
37084edbeeab67c1575067335179513150115da367bArun Murthy	}
37184edbeeab67c1575067335179513150115da367bArun Murthy
372b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	if (is_ab8500(di->parent)) {
373b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		/* enable the OPT emulation registers */
374b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2);
375b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		if (ret) {
376b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion			dev_err(di->dev, "%d write failed\n", __LINE__);
377b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion			goto disable_otp;
378b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		}
37984edbeeab67c1575067335179513150115da367bArun Murthy	}
38084edbeeab67c1575067335179513150115da367bArun Murthy
381defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson	if (fallback)
382b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		val |= (1 << bit);
38384edbeeab67c1575067335179513150115da367bArun Murthy	else
384b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		val &= ~(1 << bit);
38584edbeeab67c1575067335179513150115da367bArun Murthy
386defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson	/* write back the changed fallback bit value to register */
387b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	ret = abx500_set_register_interruptible(di->dev, bank, reg, val);
38884edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
38984edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%d write failed\n", __LINE__);
39084edbeeab67c1575067335179513150115da367bArun Murthy	}
39184edbeeab67c1575067335179513150115da367bArun Murthy
392b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guiondisable_otp:
393b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion	if (is_ab8500(di->parent)) {
394b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		/* disable the set OTP registers again */
395b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0);
396b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		if (ret) {
397b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion			dev_err(di->dev, "%d write failed\n", __LINE__);
398b016322293c7e3b7efb1835603d149c03d00b0dfNicolas Guion		}
39984edbeeab67c1575067335179513150115da367bArun Murthy	}
40084edbeeab67c1575067335179513150115da367bArun Murthy}
40184edbeeab67c1575067335179513150115da367bArun Murthy
40284edbeeab67c1575067335179513150115da367bArun Murthy/**
40384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_power_supply_changed - a wrapper with local extentions for
40484edbeeab67c1575067335179513150115da367bArun Murthy * power_supply_changed
40584edbeeab67c1575067335179513150115da367bArun Murthy * @di:	  pointer to the ab8500_charger structure
40684edbeeab67c1575067335179513150115da367bArun Murthy * @psy:  pointer to power_supply_that have changed.
40784edbeeab67c1575067335179513150115da367bArun Murthy *
40884edbeeab67c1575067335179513150115da367bArun Murthy */
40984edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_power_supply_changed(struct ab8500_charger *di,
41084edbeeab67c1575067335179513150115da367bArun Murthy					struct power_supply *psy)
41184edbeeab67c1575067335179513150115da367bArun Murthy{
4124aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	if (di->autopower_cfg) {
41384edbeeab67c1575067335179513150115da367bArun Murthy		if (!di->usb.charger_connected &&
41484edbeeab67c1575067335179513150115da367bArun Murthy		    !di->ac.charger_connected &&
41584edbeeab67c1575067335179513150115da367bArun Murthy		    di->autopower) {
41684edbeeab67c1575067335179513150115da367bArun Murthy			di->autopower = false;
417defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson			ab8500_enable_disable_sw_fallback(di, false);
41884edbeeab67c1575067335179513150115da367bArun Murthy		} else if (!di->autopower &&
41984edbeeab67c1575067335179513150115da367bArun Murthy			   (di->ac.charger_connected ||
42084edbeeab67c1575067335179513150115da367bArun Murthy			    di->usb.charger_connected)) {
42184edbeeab67c1575067335179513150115da367bArun Murthy			di->autopower = true;
422defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34Paer-Olof Haakansson			ab8500_enable_disable_sw_fallback(di, true);
42384edbeeab67c1575067335179513150115da367bArun Murthy		}
42484edbeeab67c1575067335179513150115da367bArun Murthy	}
42584edbeeab67c1575067335179513150115da367bArun Murthy	power_supply_changed(psy);
42684edbeeab67c1575067335179513150115da367bArun Murthy}
42784edbeeab67c1575067335179513150115da367bArun Murthy
42884edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_set_usb_connected(struct ab8500_charger *di,
42984edbeeab67c1575067335179513150115da367bArun Murthy	bool connected)
43084edbeeab67c1575067335179513150115da367bArun Murthy{
43184edbeeab67c1575067335179513150115da367bArun Murthy	if (connected != di->usb.charger_connected) {
43284edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "USB connected:%i\n", connected);
43384edbeeab67c1575067335179513150115da367bArun Murthy		di->usb.charger_connected = connected;
434f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones
435f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		if (!connected)
436f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			di->flags.vbus_drop_end = false;
437f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones
43884edbeeab67c1575067335179513150115da367bArun Murthy		sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present");
439b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
440b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		if (connected) {
441b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			mutex_lock(&di->charger_attached_mutex);
442b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			mutex_unlock(&di->charger_attached_mutex);
443b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
444261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent			if (is_ab8500(di->parent))
445261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent				queue_delayed_work(di->charger_wq,
446b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones					   &di->usb_charger_attached_work,
447b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones					   HZ);
448b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		} else {
449b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			cancel_delayed_work_sync(&di->usb_charger_attached_work);
450b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			mutex_lock(&di->charger_attached_mutex);
451b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			mutex_unlock(&di->charger_attached_mutex);
452b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		}
45384edbeeab67c1575067335179513150115da367bArun Murthy	}
45484edbeeab67c1575067335179513150115da367bArun Murthy}
45584edbeeab67c1575067335179513150115da367bArun Murthy
45684edbeeab67c1575067335179513150115da367bArun Murthy/**
45784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_ac_voltage() - get ac charger voltage
45884edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
45984edbeeab67c1575067335179513150115da367bArun Murthy *
46084edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger voltage (on success)
46184edbeeab67c1575067335179513150115da367bArun Murthy */
46284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ac_voltage(struct ab8500_charger *di)
46384edbeeab67c1575067335179513150115da367bArun Murthy{
46484edbeeab67c1575067335179513150115da367bArun Murthy	int vch;
46584edbeeab67c1575067335179513150115da367bArun Murthy
46684edbeeab67c1575067335179513150115da367bArun Murthy	/* Only measure voltage if the charger is connected */
46784edbeeab67c1575067335179513150115da367bArun Murthy	if (di->ac.charger_connected) {
46884edbeeab67c1575067335179513150115da367bArun Murthy		vch = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_V);
46984edbeeab67c1575067335179513150115da367bArun Murthy		if (vch < 0)
47084edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s gpadc conv failed,\n", __func__);
47184edbeeab67c1575067335179513150115da367bArun Murthy	} else {
47284edbeeab67c1575067335179513150115da367bArun Murthy		vch = 0;
47384edbeeab67c1575067335179513150115da367bArun Murthy	}
47484edbeeab67c1575067335179513150115da367bArun Murthy	return vch;
47584edbeeab67c1575067335179513150115da367bArun Murthy}
47684edbeeab67c1575067335179513150115da367bArun Murthy
47784edbeeab67c1575067335179513150115da367bArun Murthy/**
47884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_cv() - check if the main charger is in CV mode
47984edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
48084edbeeab67c1575067335179513150115da367bArun Murthy *
48184edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger CV mode (on success) else error code
48284edbeeab67c1575067335179513150115da367bArun Murthy */
48384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_cv(struct ab8500_charger *di)
48484edbeeab67c1575067335179513150115da367bArun Murthy{
48584edbeeab67c1575067335179513150115da367bArun Murthy	u8 val;
48684edbeeab67c1575067335179513150115da367bArun Murthy	int ret = 0;
48784edbeeab67c1575067335179513150115da367bArun Murthy
48884edbeeab67c1575067335179513150115da367bArun Murthy	/* Only check CV mode if the charger is online */
48984edbeeab67c1575067335179513150115da367bArun Murthy	if (di->ac.charger_online) {
49084edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
49184edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CH_STATUS1_REG, &val);
49284edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0) {
49384edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
49484edbeeab67c1575067335179513150115da367bArun Murthy			return 0;
49584edbeeab67c1575067335179513150115da367bArun Murthy		}
49684edbeeab67c1575067335179513150115da367bArun Murthy
49784edbeeab67c1575067335179513150115da367bArun Murthy		if (val & MAIN_CH_CV_ON)
49884edbeeab67c1575067335179513150115da367bArun Murthy			ret = 1;
49984edbeeab67c1575067335179513150115da367bArun Murthy		else
50084edbeeab67c1575067335179513150115da367bArun Murthy			ret = 0;
50184edbeeab67c1575067335179513150115da367bArun Murthy	}
50284edbeeab67c1575067335179513150115da367bArun Murthy
50384edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
50484edbeeab67c1575067335179513150115da367bArun Murthy}
50584edbeeab67c1575067335179513150115da367bArun Murthy
50684edbeeab67c1575067335179513150115da367bArun Murthy/**
50784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_vbus_voltage() - get vbus voltage
50884edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
50984edbeeab67c1575067335179513150115da367bArun Murthy *
51084edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the vbus voltage.
51184edbeeab67c1575067335179513150115da367bArun Murthy * Returns vbus voltage (on success)
51284edbeeab67c1575067335179513150115da367bArun Murthy */
51384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di)
51484edbeeab67c1575067335179513150115da367bArun Murthy{
51584edbeeab67c1575067335179513150115da367bArun Murthy	int vch;
51684edbeeab67c1575067335179513150115da367bArun Murthy
51784edbeeab67c1575067335179513150115da367bArun Murthy	/* Only measure voltage if the charger is connected */
51884edbeeab67c1575067335179513150115da367bArun Murthy	if (di->usb.charger_connected) {
51984edbeeab67c1575067335179513150115da367bArun Murthy		vch = ab8500_gpadc_convert(di->gpadc, VBUS_V);
52084edbeeab67c1575067335179513150115da367bArun Murthy		if (vch < 0)
52184edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s gpadc conv failed\n", __func__);
52284edbeeab67c1575067335179513150115da367bArun Murthy	} else {
52384edbeeab67c1575067335179513150115da367bArun Murthy		vch = 0;
52484edbeeab67c1575067335179513150115da367bArun Murthy	}
52584edbeeab67c1575067335179513150115da367bArun Murthy	return vch;
52684edbeeab67c1575067335179513150115da367bArun Murthy}
52784edbeeab67c1575067335179513150115da367bArun Murthy
52884edbeeab67c1575067335179513150115da367bArun Murthy/**
52984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_usb_current() - get usb charger current
53084edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
53184edbeeab67c1575067335179513150115da367bArun Murthy *
53284edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the usb charger current.
53384edbeeab67c1575067335179513150115da367bArun Murthy * Returns usb current (on success) and error code on failure
53484edbeeab67c1575067335179513150115da367bArun Murthy */
53584edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_usb_current(struct ab8500_charger *di)
53684edbeeab67c1575067335179513150115da367bArun Murthy{
53784edbeeab67c1575067335179513150115da367bArun Murthy	int ich;
53884edbeeab67c1575067335179513150115da367bArun Murthy
53984edbeeab67c1575067335179513150115da367bArun Murthy	/* Only measure current if the charger is online */
54084edbeeab67c1575067335179513150115da367bArun Murthy	if (di->usb.charger_online) {
54184edbeeab67c1575067335179513150115da367bArun Murthy		ich = ab8500_gpadc_convert(di->gpadc, USB_CHARGER_C);
54284edbeeab67c1575067335179513150115da367bArun Murthy		if (ich < 0)
54384edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s gpadc conv failed\n", __func__);
54484edbeeab67c1575067335179513150115da367bArun Murthy	} else {
54584edbeeab67c1575067335179513150115da367bArun Murthy		ich = 0;
54684edbeeab67c1575067335179513150115da367bArun Murthy	}
54784edbeeab67c1575067335179513150115da367bArun Murthy	return ich;
54884edbeeab67c1575067335179513150115da367bArun Murthy}
54984edbeeab67c1575067335179513150115da367bArun Murthy
55084edbeeab67c1575067335179513150115da367bArun Murthy/**
55184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_ac_current() - get ac charger current
55284edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
55384edbeeab67c1575067335179513150115da367bArun Murthy *
55484edbeeab67c1575067335179513150115da367bArun Murthy * This function returns the ac charger current.
55584edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac current (on success) and error code on failure.
55684edbeeab67c1575067335179513150115da367bArun Murthy */
55784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ac_current(struct ab8500_charger *di)
55884edbeeab67c1575067335179513150115da367bArun Murthy{
55984edbeeab67c1575067335179513150115da367bArun Murthy	int ich;
56084edbeeab67c1575067335179513150115da367bArun Murthy
56184edbeeab67c1575067335179513150115da367bArun Murthy	/* Only measure current if the charger is online */
56284edbeeab67c1575067335179513150115da367bArun Murthy	if (di->ac.charger_online) {
56384edbeeab67c1575067335179513150115da367bArun Murthy		ich = ab8500_gpadc_convert(di->gpadc, MAIN_CHARGER_C);
56484edbeeab67c1575067335179513150115da367bArun Murthy		if (ich < 0)
56584edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s gpadc conv failed\n", __func__);
56684edbeeab67c1575067335179513150115da367bArun Murthy	} else {
56784edbeeab67c1575067335179513150115da367bArun Murthy		ich = 0;
56884edbeeab67c1575067335179513150115da367bArun Murthy	}
56984edbeeab67c1575067335179513150115da367bArun Murthy	return ich;
57084edbeeab67c1575067335179513150115da367bArun Murthy}
57184edbeeab67c1575067335179513150115da367bArun Murthy
57284edbeeab67c1575067335179513150115da367bArun Murthy/**
57384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_cv() - check if the usb charger is in CV mode
57484edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
57584edbeeab67c1575067335179513150115da367bArun Murthy *
57684edbeeab67c1575067335179513150115da367bArun Murthy * Returns ac charger CV mode (on success) else error code
57784edbeeab67c1575067335179513150115da367bArun Murthy */
57884edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_cv(struct ab8500_charger *di)
57984edbeeab67c1575067335179513150115da367bArun Murthy{
58084edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
58184edbeeab67c1575067335179513150115da367bArun Murthy	u8 val;
58284edbeeab67c1575067335179513150115da367bArun Murthy
58384edbeeab67c1575067335179513150115da367bArun Murthy	/* Only check CV mode if the charger is online */
58484edbeeab67c1575067335179513150115da367bArun Murthy	if (di->usb.charger_online) {
58584edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
58684edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CH_USBCH_STAT1_REG, &val);
58784edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0) {
58884edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
58984edbeeab67c1575067335179513150115da367bArun Murthy			return 0;
59084edbeeab67c1575067335179513150115da367bArun Murthy		}
59184edbeeab67c1575067335179513150115da367bArun Murthy
59284edbeeab67c1575067335179513150115da367bArun Murthy		if (val & USB_CH_CV_ON)
59384edbeeab67c1575067335179513150115da367bArun Murthy			ret = 1;
59484edbeeab67c1575067335179513150115da367bArun Murthy		else
59584edbeeab67c1575067335179513150115da367bArun Murthy			ret = 0;
59684edbeeab67c1575067335179513150115da367bArun Murthy	} else {
59784edbeeab67c1575067335179513150115da367bArun Murthy		ret = 0;
59884edbeeab67c1575067335179513150115da367bArun Murthy	}
59984edbeeab67c1575067335179513150115da367bArun Murthy
60084edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
60184edbeeab67c1575067335179513150115da367bArun Murthy}
60284edbeeab67c1575067335179513150115da367bArun Murthy
60384edbeeab67c1575067335179513150115da367bArun Murthy/**
60484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_chargers() - Detect the connected chargers
60584edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
60634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @probe:	if probe, don't delay and wait for HW
60784edbeeab67c1575067335179513150115da367bArun Murthy *
60884edbeeab67c1575067335179513150115da367bArun Murthy * Returns the type of charger connected.
60984edbeeab67c1575067335179513150115da367bArun Murthy * For USB it will not mean we can actually charge from it
61084edbeeab67c1575067335179513150115da367bArun Murthy * but that there is a USB cable connected that we have to
61184edbeeab67c1575067335179513150115da367bArun Murthy * identify. This is used during startup when we don't get
61284edbeeab67c1575067335179513150115da367bArun Murthy * interrupts of the charger detection
61384edbeeab67c1575067335179513150115da367bArun Murthy *
61484edbeeab67c1575067335179513150115da367bArun Murthy * Returns an integer value, that means,
61584edbeeab67c1575067335179513150115da367bArun Murthy * NO_PW_CONN  no power supply is connected
61684edbeeab67c1575067335179513150115da367bArun Murthy * AC_PW_CONN  if the AC power supply is connected
61784edbeeab67c1575067335179513150115da367bArun Murthy * USB_PW_CONN  if the USB power supply is connected
61884edbeeab67c1575067335179513150115da367bArun Murthy * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected
61984edbeeab67c1575067335179513150115da367bArun Murthy */
62034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonstatic int ab8500_charger_detect_chargers(struct ab8500_charger *di, bool probe)
62184edbeeab67c1575067335179513150115da367bArun Murthy{
62284edbeeab67c1575067335179513150115da367bArun Murthy	int result = NO_PW_CONN;
62384edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
62484edbeeab67c1575067335179513150115da367bArun Murthy	u8 val;
62584edbeeab67c1575067335179513150115da367bArun Murthy
62684edbeeab67c1575067335179513150115da367bArun Murthy	/* Check for AC charger */
62784edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
62884edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CH_STATUS1_REG, &val);
62984edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0) {
63084edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
63184edbeeab67c1575067335179513150115da367bArun Murthy		return ret;
63284edbeeab67c1575067335179513150115da367bArun Murthy	}
63384edbeeab67c1575067335179513150115da367bArun Murthy
63484edbeeab67c1575067335179513150115da367bArun Murthy	if (val & MAIN_CH_DET)
63584edbeeab67c1575067335179513150115da367bArun Murthy		result = AC_PW_CONN;
63684edbeeab67c1575067335179513150115da367bArun Murthy
63784edbeeab67c1575067335179513150115da367bArun Murthy	/* Check for USB charger */
63834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
63934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (!probe) {
64034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		/*
64134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		 * AB8500 says VBUS_DET_DBNC1 & VBUS_DET_DBNC100
64234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		 * when disconnecting ACA even though no
64334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		 * charger was connected. Try waiting a little
64434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		 * longer than the 100 ms of VBUS_DET_DBNC100...
64534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		 */
64634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		msleep(110);
64734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	}
64884edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
64984edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CH_USBCH_STAT1_REG, &val);
65084edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0) {
65184edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
65284edbeeab67c1575067335179513150115da367bArun Murthy		return ret;
65384edbeeab67c1575067335179513150115da367bArun Murthy	}
65434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	dev_dbg(di->dev,
65534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		"%s AB8500_CH_USBCH_STAT1_REG %x\n", __func__,
65634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		val);
65784edbeeab67c1575067335179513150115da367bArun Murthy	if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100))
65884edbeeab67c1575067335179513150115da367bArun Murthy		result |= USB_PW_CONN;
65984edbeeab67c1575067335179513150115da367bArun Murthy
66084edbeeab67c1575067335179513150115da367bArun Murthy	return result;
66184edbeeab67c1575067335179513150115da367bArun Murthy}
66284edbeeab67c1575067335179513150115da367bArun Murthy
66384edbeeab67c1575067335179513150115da367bArun Murthy/**
66484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_max_usb_curr() - get the max curr for the USB type
66584edbeeab67c1575067335179513150115da367bArun Murthy * @di:			pointer to the ab8500_charger structure
66684edbeeab67c1575067335179513150115da367bArun Murthy * @link_status:	the identified USB type
66784edbeeab67c1575067335179513150115da367bArun Murthy *
66884edbeeab67c1575067335179513150115da367bArun Murthy * Get the maximum current that is allowed to be drawn from the host
66984edbeeab67c1575067335179513150115da367bArun Murthy * based on the USB type.
67084edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success
67184edbeeab67c1575067335179513150115da367bArun Murthy */
67284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
67374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg		enum ab8500_charger_link_status link_status)
67484edbeeab67c1575067335179513150115da367bArun Murthy{
67584edbeeab67c1575067335179513150115da367bArun Murthy	int ret = 0;
67684edbeeab67c1575067335179513150115da367bArun Murthy
6774b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	di->usb_device_is_unrecognised = false;
6784b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper
67934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	/*
68034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 * Platform only supports USB 2.0.
68134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 * This means that charging current from USB source
68234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 * is maximum 500 mA. Every occurence of USB_STAT_*_HOST_*
68334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 * should set USB_CH_IP_CUR_LVL_0P5.
68434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 */
68534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
68684edbeeab67c1575067335179513150115da367bArun Murthy	switch (link_status) {
68784edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_STD_HOST_NC:
68884edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_STD_HOST_C_NS:
68984edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_STD_HOST_C_S:
69084edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "USB Type - Standard host is "
69134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			"detected through USB driver\n");
692f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
69334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 0;
69484edbeeab67c1575067335179513150115da367bArun Murthy		break;
69584edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_HOST_CHG_HS_CHIRP:
696f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
69734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 0;
69884edbeeab67c1575067335179513150115da367bArun Murthy		break;
69984edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_HOST_CHG_HS:
700f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
70134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 0;
70234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		break;
70384edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_ACA_RID_C_HS:
704f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P9;
70534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 0;
70684edbeeab67c1575067335179513150115da367bArun Murthy		break;
70784edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_ACA_RID_A:
70884edbeeab67c1575067335179513150115da367bArun Murthy		/*
70984edbeeab67c1575067335179513150115da367bArun Murthy		 * Dedicated charger level minus maximum current accessory
71034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		 * can consume (900mA). Closest level is 500mA
71184edbeeab67c1575067335179513150115da367bArun Murthy		 */
71234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n");
713f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
71434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 1;
71584edbeeab67c1575067335179513150115da367bArun Murthy		break;
71684edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_ACA_RID_B:
71784edbeeab67c1575067335179513150115da367bArun Murthy		/*
71884edbeeab67c1575067335179513150115da367bArun Murthy		 * Dedicated charger level minus 120mA (20mA for ACA and
71984edbeeab67c1575067335179513150115da367bArun Murthy		 * 100mA for potential accessory). Closest level is 1300mA
72084edbeeab67c1575067335179513150115da367bArun Murthy		 */
721f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P3;
72274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
723f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones				di->max_usb_in_curr.usb_type_max);
72434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 1;
72584edbeeab67c1575067335179513150115da367bArun Murthy		break;
72684edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_HOST_CHG_NM:
727f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
72834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 0;
72934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		break;
73074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	case USB_STAT_DEDICATED_CHG:
731f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5;
73234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 0;
73334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		break;
73474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	case USB_STAT_ACA_RID_C_HS_CHIRP:
73534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	case USB_STAT_ACA_RID_C_NM:
736f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_1P5;
73734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid = 1;
73884edbeeab67c1575067335179513150115da367bArun Murthy		break;
7394b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	case USB_STAT_NOT_CONFIGURED:
7404b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper		if (di->vbus_detected) {
7414b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper			di->usb_device_is_unrecognised = true;
7424b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper			dev_dbg(di->dev, "USB Type - Legacy charger.\n");
743f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			di->max_usb_in_curr.usb_type_max =
744f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones						USB_CH_IP_CUR_LVL_1P5;
7454b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper			break;
7464b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper		}
74784edbeeab67c1575067335179513150115da367bArun Murthy	case USB_STAT_HM_IDGND:
74884edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "USB Type - Charging not allowed\n");
749f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
75084edbeeab67c1575067335179513150115da367bArun Murthy		ret = -ENXIO;
75184edbeeab67c1575067335179513150115da367bArun Murthy		break;
75274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	case USB_STAT_RESERVED:
75374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg		if (is_ab8500(di->parent)) {
75474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			di->flags.vbus_collapse = true;
75574a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			dev_err(di->dev, "USB Type - USB_STAT_RESERVED "
75674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg						"VBUS has collapsed\n");
75774a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			ret = -ENXIO;
75874a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			break;
759861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		} else {
76074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			dev_dbg(di->dev, "USB Type - Charging not allowed\n");
761f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			di->max_usb_in_curr.usb_type_max =
762f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones						USB_CH_IP_CUR_LVL_0P05;
76374a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
764f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones				link_status,
765f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones				di->max_usb_in_curr.usb_type_max);
76674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			ret = -ENXIO;
76774a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			break;
76874a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg		}
76974a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	case USB_STAT_CARKIT_1:
77074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	case USB_STAT_CARKIT_2:
77174a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	case USB_STAT_ACA_DOCK_CHARGER:
77274a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg	case USB_STAT_CHARGER_LINE_1:
773f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
77474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg		dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status,
775f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones				di->max_usb_in_curr.usb_type_max);
776ed5243f8ab2470e988dce0e416eaaddb4d7d2cccDan Carpenter		break;
777ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	case USB_STAT_NOT_VALID_LINK:
778ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver		dev_err(di->dev, "USB Type invalid - try charging anyway\n");
779f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
78074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg		break;
78174a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg
78284edbeeab67c1575067335179513150115da367bArun Murthy	default:
78384edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "USB Type - Unknown\n");
784f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
78584edbeeab67c1575067335179513150115da367bArun Murthy		ret = -ENXIO;
78684edbeeab67c1575067335179513150115da367bArun Murthy		break;
78784edbeeab67c1575067335179513150115da367bArun Murthy	};
78884edbeeab67c1575067335179513150115da367bArun Murthy
789f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max;
79084edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d",
791f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		link_status, di->max_usb_in_curr.set_max);
79284edbeeab67c1575067335179513150115da367bArun Murthy
79384edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
79484edbeeab67c1575067335179513150115da367bArun Murthy}
79584edbeeab67c1575067335179513150115da367bArun Murthy
79684edbeeab67c1575067335179513150115da367bArun Murthy/**
79784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_read_usb_type() - read the type of usb connected
79884edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
79984edbeeab67c1575067335179513150115da367bArun Murthy *
80084edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of the plugged USB
80184edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success
80284edbeeab67c1575067335179513150115da367bArun Murthy */
80384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_read_usb_type(struct ab8500_charger *di)
80484edbeeab67c1575067335179513150115da367bArun Murthy{
80584edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
80684edbeeab67c1575067335179513150115da367bArun Murthy	u8 val;
80784edbeeab67c1575067335179513150115da367bArun Murthy
80884edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_get_register_interruptible(di->dev,
80984edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, &val);
81084edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0) {
81184edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
81284edbeeab67c1575067335179513150115da367bArun Murthy		return ret;
81384edbeeab67c1575067335179513150115da367bArun Murthy	}
814861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (is_ab8500(di->parent))
81574a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
816861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			AB8500_USB_LINE_STAT_REG, &val);
817861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	else
818861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		ret = abx500_get_register_interruptible(di->dev,
819861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
82084edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0) {
82184edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
82284edbeeab67c1575067335179513150115da367bArun Murthy		return ret;
82384edbeeab67c1575067335179513150115da367bArun Murthy	}
82484edbeeab67c1575067335179513150115da367bArun Murthy
82584edbeeab67c1575067335179513150115da367bArun Murthy	/* get the USB type */
826861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (is_ab8500(di->parent))
827861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		val = (val & AB8500_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
828861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	else
829861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		val = (val & AB8505_USB_LINK_STATUS) >> USB_LINK_STATUS_SHIFT;
83084edbeeab67c1575067335179513150115da367bArun Murthy	ret = ab8500_charger_max_usb_curr(di,
83184edbeeab67c1575067335179513150115da367bArun Murthy		(enum ab8500_charger_link_status) val);
83284edbeeab67c1575067335179513150115da367bArun Murthy
83384edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
83484edbeeab67c1575067335179513150115da367bArun Murthy}
83584edbeeab67c1575067335179513150115da367bArun Murthy
83684edbeeab67c1575067335179513150115da367bArun Murthy/**
83784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_usb_type() - get the type of usb connected
83884edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
83984edbeeab67c1575067335179513150115da367bArun Murthy *
84084edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of the plugged USB
84184edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0 on success
84284edbeeab67c1575067335179513150115da367bArun Murthy */
84384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_detect_usb_type(struct ab8500_charger *di)
84484edbeeab67c1575067335179513150115da367bArun Murthy{
84584edbeeab67c1575067335179513150115da367bArun Murthy	int i, ret;
84684edbeeab67c1575067335179513150115da367bArun Murthy	u8 val;
84784edbeeab67c1575067335179513150115da367bArun Murthy
84884edbeeab67c1575067335179513150115da367bArun Murthy	/*
84984edbeeab67c1575067335179513150115da367bArun Murthy	 * On getting the VBUS rising edge detect interrupt there
85084edbeeab67c1575067335179513150115da367bArun Murthy	 * is a 250ms delay after which the register UsbLineStatus
85184edbeeab67c1575067335179513150115da367bArun Murthy	 * is filled with valid data.
85284edbeeab67c1575067335179513150115da367bArun Murthy	 */
85384edbeeab67c1575067335179513150115da367bArun Murthy	for (i = 0; i < 10; i++) {
85484edbeeab67c1575067335179513150115da367bArun Murthy		msleep(250);
85584edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_get_register_interruptible(di->dev,
85684edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG,
85784edbeeab67c1575067335179513150115da367bArun Murthy			&val);
85834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev, "%s AB8500_IT_SOURCE21_REG %x\n",
85934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			__func__, val);
86084edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0) {
86184edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
86284edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
86384edbeeab67c1575067335179513150115da367bArun Murthy		}
86474a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg
865861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		if (is_ab8500(di->parent))
86674a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			ret = abx500_get_register_interruptible(di->dev,
86774a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg				AB8500_USB, AB8500_USB_LINE_STAT_REG, &val);
868861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		else
86974a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg			ret = abx500_get_register_interruptible(di->dev,
87074a8e349b1c882e34419877207ae850ed87dddf7Hakan Berg				AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val);
87184edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0) {
87284edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
87384edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
87484edbeeab67c1575067335179513150115da367bArun Murthy		}
87534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev, "%s AB8500_USB_LINE_STAT_REG %x\n", __func__,
87634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			val);
87784edbeeab67c1575067335179513150115da367bArun Murthy		/*
87884edbeeab67c1575067335179513150115da367bArun Murthy		 * Until the IT source register is read the UsbLineStatus
87984edbeeab67c1575067335179513150115da367bArun Murthy		 * register is not updated, hence doing the same
88084edbeeab67c1575067335179513150115da367bArun Murthy		 * Revisit this:
88184edbeeab67c1575067335179513150115da367bArun Murthy		 */
88284edbeeab67c1575067335179513150115da367bArun Murthy
88384edbeeab67c1575067335179513150115da367bArun Murthy		/* get the USB type */
884861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		if (is_ab8500(di->parent))
885861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			val = (val & AB8500_USB_LINK_STATUS) >>
886861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones							USB_LINK_STATUS_SHIFT;
887861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		else
888861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			val = (val & AB8505_USB_LINK_STATUS) >>
889861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones							USB_LINK_STATUS_SHIFT;
89084edbeeab67c1575067335179513150115da367bArun Murthy		if (val)
89184edbeeab67c1575067335179513150115da367bArun Murthy			break;
89284edbeeab67c1575067335179513150115da367bArun Murthy	}
89384edbeeab67c1575067335179513150115da367bArun Murthy	ret = ab8500_charger_max_usb_curr(di,
89484edbeeab67c1575067335179513150115da367bArun Murthy		(enum ab8500_charger_link_status) val);
89584edbeeab67c1575067335179513150115da367bArun Murthy
89684edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
89784edbeeab67c1575067335179513150115da367bArun Murthy}
89884edbeeab67c1575067335179513150115da367bArun Murthy
89984edbeeab67c1575067335179513150115da367bArun Murthy/*
90084edbeeab67c1575067335179513150115da367bArun Murthy * This array maps the raw hex value to charger voltage used by the AB8500
90184edbeeab67c1575067335179513150115da367bArun Murthy * Values taken from the UM0836
90284edbeeab67c1575067335179513150115da367bArun Murthy */
90384edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_voltage_map[] = {
90484edbeeab67c1575067335179513150115da367bArun Murthy	3500 ,
90584edbeeab67c1575067335179513150115da367bArun Murthy	3525 ,
90684edbeeab67c1575067335179513150115da367bArun Murthy	3550 ,
90784edbeeab67c1575067335179513150115da367bArun Murthy	3575 ,
90884edbeeab67c1575067335179513150115da367bArun Murthy	3600 ,
90984edbeeab67c1575067335179513150115da367bArun Murthy	3625 ,
91084edbeeab67c1575067335179513150115da367bArun Murthy	3650 ,
91184edbeeab67c1575067335179513150115da367bArun Murthy	3675 ,
91284edbeeab67c1575067335179513150115da367bArun Murthy	3700 ,
91384edbeeab67c1575067335179513150115da367bArun Murthy	3725 ,
91484edbeeab67c1575067335179513150115da367bArun Murthy	3750 ,
91584edbeeab67c1575067335179513150115da367bArun Murthy	3775 ,
91684edbeeab67c1575067335179513150115da367bArun Murthy	3800 ,
91784edbeeab67c1575067335179513150115da367bArun Murthy	3825 ,
91884edbeeab67c1575067335179513150115da367bArun Murthy	3850 ,
91984edbeeab67c1575067335179513150115da367bArun Murthy	3875 ,
92084edbeeab67c1575067335179513150115da367bArun Murthy	3900 ,
92184edbeeab67c1575067335179513150115da367bArun Murthy	3925 ,
92284edbeeab67c1575067335179513150115da367bArun Murthy	3950 ,
92384edbeeab67c1575067335179513150115da367bArun Murthy	3975 ,
92484edbeeab67c1575067335179513150115da367bArun Murthy	4000 ,
92584edbeeab67c1575067335179513150115da367bArun Murthy	4025 ,
92684edbeeab67c1575067335179513150115da367bArun Murthy	4050 ,
92784edbeeab67c1575067335179513150115da367bArun Murthy	4060 ,
92884edbeeab67c1575067335179513150115da367bArun Murthy	4070 ,
92984edbeeab67c1575067335179513150115da367bArun Murthy	4080 ,
93084edbeeab67c1575067335179513150115da367bArun Murthy	4090 ,
93184edbeeab67c1575067335179513150115da367bArun Murthy	4100 ,
93284edbeeab67c1575067335179513150115da367bArun Murthy	4110 ,
93384edbeeab67c1575067335179513150115da367bArun Murthy	4120 ,
93484edbeeab67c1575067335179513150115da367bArun Murthy	4130 ,
93584edbeeab67c1575067335179513150115da367bArun Murthy	4140 ,
93684edbeeab67c1575067335179513150115da367bArun Murthy	4150 ,
93784edbeeab67c1575067335179513150115da367bArun Murthy	4160 ,
93884edbeeab67c1575067335179513150115da367bArun Murthy	4170 ,
93984edbeeab67c1575067335179513150115da367bArun Murthy	4180 ,
94084edbeeab67c1575067335179513150115da367bArun Murthy	4190 ,
94184edbeeab67c1575067335179513150115da367bArun Murthy	4200 ,
94284edbeeab67c1575067335179513150115da367bArun Murthy	4210 ,
94384edbeeab67c1575067335179513150115da367bArun Murthy	4220 ,
94484edbeeab67c1575067335179513150115da367bArun Murthy	4230 ,
94584edbeeab67c1575067335179513150115da367bArun Murthy	4240 ,
94684edbeeab67c1575067335179513150115da367bArun Murthy	4250 ,
94784edbeeab67c1575067335179513150115da367bArun Murthy	4260 ,
94884edbeeab67c1575067335179513150115da367bArun Murthy	4270 ,
94984edbeeab67c1575067335179513150115da367bArun Murthy	4280 ,
95084edbeeab67c1575067335179513150115da367bArun Murthy	4290 ,
95184edbeeab67c1575067335179513150115da367bArun Murthy	4300 ,
95284edbeeab67c1575067335179513150115da367bArun Murthy	4310 ,
95384edbeeab67c1575067335179513150115da367bArun Murthy	4320 ,
95484edbeeab67c1575067335179513150115da367bArun Murthy	4330 ,
95584edbeeab67c1575067335179513150115da367bArun Murthy	4340 ,
95684edbeeab67c1575067335179513150115da367bArun Murthy	4350 ,
95784edbeeab67c1575067335179513150115da367bArun Murthy	4360 ,
95884edbeeab67c1575067335179513150115da367bArun Murthy	4370 ,
95984edbeeab67c1575067335179513150115da367bArun Murthy	4380 ,
96084edbeeab67c1575067335179513150115da367bArun Murthy	4390 ,
96184edbeeab67c1575067335179513150115da367bArun Murthy	4400 ,
96284edbeeab67c1575067335179513150115da367bArun Murthy	4410 ,
96384edbeeab67c1575067335179513150115da367bArun Murthy	4420 ,
96484edbeeab67c1575067335179513150115da367bArun Murthy	4430 ,
96584edbeeab67c1575067335179513150115da367bArun Murthy	4440 ,
96684edbeeab67c1575067335179513150115da367bArun Murthy	4450 ,
96784edbeeab67c1575067335179513150115da367bArun Murthy	4460 ,
96884edbeeab67c1575067335179513150115da367bArun Murthy	4470 ,
96984edbeeab67c1575067335179513150115da367bArun Murthy	4480 ,
97084edbeeab67c1575067335179513150115da367bArun Murthy	4490 ,
97184edbeeab67c1575067335179513150115da367bArun Murthy	4500 ,
97284edbeeab67c1575067335179513150115da367bArun Murthy	4510 ,
97384edbeeab67c1575067335179513150115da367bArun Murthy	4520 ,
97484edbeeab67c1575067335179513150115da367bArun Murthy	4530 ,
97584edbeeab67c1575067335179513150115da367bArun Murthy	4540 ,
97684edbeeab67c1575067335179513150115da367bArun Murthy	4550 ,
97784edbeeab67c1575067335179513150115da367bArun Murthy	4560 ,
97884edbeeab67c1575067335179513150115da367bArun Murthy	4570 ,
97984edbeeab67c1575067335179513150115da367bArun Murthy	4580 ,
98084edbeeab67c1575067335179513150115da367bArun Murthy	4590 ,
98184edbeeab67c1575067335179513150115da367bArun Murthy	4600 ,
98284edbeeab67c1575067335179513150115da367bArun Murthy};
98384edbeeab67c1575067335179513150115da367bArun Murthy
98484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_voltage_to_regval(int voltage)
98584edbeeab67c1575067335179513150115da367bArun Murthy{
98684edbeeab67c1575067335179513150115da367bArun Murthy	int i;
98784edbeeab67c1575067335179513150115da367bArun Murthy
98884edbeeab67c1575067335179513150115da367bArun Murthy	/* Special case for voltage below 3.5V */
98984edbeeab67c1575067335179513150115da367bArun Murthy	if (voltage < ab8500_charger_voltage_map[0])
99084edbeeab67c1575067335179513150115da367bArun Murthy		return LOW_VOLT_REG;
99184edbeeab67c1575067335179513150115da367bArun Murthy
99284edbeeab67c1575067335179513150115da367bArun Murthy	for (i = 1; i < ARRAY_SIZE(ab8500_charger_voltage_map); i++) {
99384edbeeab67c1575067335179513150115da367bArun Murthy		if (voltage < ab8500_charger_voltage_map[i])
99484edbeeab67c1575067335179513150115da367bArun Murthy			return i - 1;
99584edbeeab67c1575067335179513150115da367bArun Murthy	}
99684edbeeab67c1575067335179513150115da367bArun Murthy
99784edbeeab67c1575067335179513150115da367bArun Murthy	/* If not last element, return error */
99884edbeeab67c1575067335179513150115da367bArun Murthy	i = ARRAY_SIZE(ab8500_charger_voltage_map) - 1;
99984edbeeab67c1575067335179513150115da367bArun Murthy	if (voltage == ab8500_charger_voltage_map[i])
100084edbeeab67c1575067335179513150115da367bArun Murthy		return i;
100184edbeeab67c1575067335179513150115da367bArun Murthy	else
100284edbeeab67c1575067335179513150115da367bArun Murthy		return -1;
100384edbeeab67c1575067335179513150115da367bArun Murthy}
100484edbeeab67c1575067335179513150115da367bArun Murthy
1005861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jonesstatic int ab8500_current_to_regval(struct ab8500_charger *di, int curr)
100684edbeeab67c1575067335179513150115da367bArun Murthy{
100784edbeeab67c1575067335179513150115da367bArun Murthy	int i;
100884edbeeab67c1575067335179513150115da367bArun Murthy
1009861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (curr < di->bm->chg_output_curr[0])
101084edbeeab67c1575067335179513150115da367bArun Murthy		return 0;
101184edbeeab67c1575067335179513150115da367bArun Murthy
1012861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	for (i = 0; i < di->bm->n_chg_out_curr; i++) {
1013861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		if (curr < di->bm->chg_output_curr[i])
101484edbeeab67c1575067335179513150115da367bArun Murthy			return i - 1;
101584edbeeab67c1575067335179513150115da367bArun Murthy	}
101684edbeeab67c1575067335179513150115da367bArun Murthy
101784edbeeab67c1575067335179513150115da367bArun Murthy	/* If not last element, return error */
1018861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	i = di->bm->n_chg_out_curr - 1;
1019861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (curr == di->bm->chg_output_curr[i])
102084edbeeab67c1575067335179513150115da367bArun Murthy		return i;
102184edbeeab67c1575067335179513150115da367bArun Murthy	else
102284edbeeab67c1575067335179513150115da367bArun Murthy		return -1;
102384edbeeab67c1575067335179513150115da367bArun Murthy}
102484edbeeab67c1575067335179513150115da367bArun Murthy
1025861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jonesstatic int ab8500_vbus_in_curr_to_regval(struct ab8500_charger *di, int curr)
102684edbeeab67c1575067335179513150115da367bArun Murthy{
102784edbeeab67c1575067335179513150115da367bArun Murthy	int i;
102884edbeeab67c1575067335179513150115da367bArun Murthy
1029861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (curr < di->bm->chg_input_curr[0])
103084edbeeab67c1575067335179513150115da367bArun Murthy		return 0;
103184edbeeab67c1575067335179513150115da367bArun Murthy
1032861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	for (i = 0; i < di->bm->n_chg_in_curr; i++) {
1033861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		if (curr < di->bm->chg_input_curr[i])
103484edbeeab67c1575067335179513150115da367bArun Murthy			return i - 1;
103584edbeeab67c1575067335179513150115da367bArun Murthy	}
103684edbeeab67c1575067335179513150115da367bArun Murthy
103784edbeeab67c1575067335179513150115da367bArun Murthy	/* If not last element, return error */
1038861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	i = di->bm->n_chg_in_curr - 1;
1039861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (curr == di->bm->chg_input_curr[i])
104084edbeeab67c1575067335179513150115da367bArun Murthy		return i;
104184edbeeab67c1575067335179513150115da367bArun Murthy	else
104284edbeeab67c1575067335179513150115da367bArun Murthy		return -1;
104384edbeeab67c1575067335179513150115da367bArun Murthy}
104484edbeeab67c1575067335179513150115da367bArun Murthy
104584edbeeab67c1575067335179513150115da367bArun Murthy/**
104684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_get_usb_cur() - get usb current
104784edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structre
104884edbeeab67c1575067335179513150115da367bArun Murthy *
104984edbeeab67c1575067335179513150115da367bArun Murthy * The usb stack provides the maximum current that can be drawn from
105084edbeeab67c1575067335179513150115da367bArun Murthy * the standard usb host. This will be in mA.
105184edbeeab67c1575067335179513150115da367bArun Murthy * This function converts current in mA to a value that can be written
105284edbeeab67c1575067335179513150115da367bArun Murthy * to the register. Returns -1 if charging is not allowed
105384edbeeab67c1575067335179513150115da367bArun Murthy */
105484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_usb_cur(struct ab8500_charger *di)
105584edbeeab67c1575067335179513150115da367bArun Murthy{
1056f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	int ret = 0;
105784edbeeab67c1575067335179513150115da367bArun Murthy	switch (di->usb_state.usb_current) {
105884edbeeab67c1575067335179513150115da367bArun Murthy	case 100:
1059f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P09;
106084edbeeab67c1575067335179513150115da367bArun Murthy		break;
106184edbeeab67c1575067335179513150115da367bArun Murthy	case 200:
1062f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P19;
106384edbeeab67c1575067335179513150115da367bArun Murthy		break;
106484edbeeab67c1575067335179513150115da367bArun Murthy	case 300:
1065f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P29;
106684edbeeab67c1575067335179513150115da367bArun Murthy		break;
106784edbeeab67c1575067335179513150115da367bArun Murthy	case 400:
1068f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P38;
106984edbeeab67c1575067335179513150115da367bArun Murthy		break;
107084edbeeab67c1575067335179513150115da367bArun Murthy	case 500:
1071f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P5;
107284edbeeab67c1575067335179513150115da367bArun Murthy		break;
107384edbeeab67c1575067335179513150115da367bArun Murthy	default:
1074f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
1075f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		ret = -EPERM;
107684edbeeab67c1575067335179513150115da367bArun Murthy		break;
107784edbeeab67c1575067335179513150115da367bArun Murthy	};
1078f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	di->max_usb_in_curr.set_max = di->max_usb_in_curr.usb_type_max;
1079f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	return ret;
1080f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones}
1081f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones
1082f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones/**
1083f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * ab8500_charger_check_continue_stepping() - Check to allow stepping
1084f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * @di:		pointer to the ab8500_charger structure
1085f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * @reg:	select what charger register to check
1086f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones *
1087f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * Check if current stepping should be allowed to continue.
1088f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * Checks if charger source has not collapsed. If it has, further stepping
1089f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones * is not allowed.
1090f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones */
1091f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jonesstatic bool ab8500_charger_check_continue_stepping(struct ab8500_charger *di,
1092f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones						   int reg)
1093f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones{
1094f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	if (reg == AB8500_USBCH_IPT_CRNTLVL_REG)
1095f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		return !di->flags.vbus_drop_end;
1096f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	else
1097f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		return true;
109884edbeeab67c1575067335179513150115da367bArun Murthy}
109984edbeeab67c1575067335179513150115da367bArun Murthy
110084edbeeab67c1575067335179513150115da367bArun Murthy/**
1101f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * ab8500_charger_set_current() - set charger current
1102f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @di:		pointer to the ab8500_charger structure
1103f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @ich:	charger current, in mA
1104f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @reg:	select what charger register to set
1105f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt *
1106f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Set charger current.
1107f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * There is no state machine in the AB to step up/down the charger
1108f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * current to avoid dips and spikes on MAIN, VBUS and VBAT when
1109f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * charging is started. Instead we need to implement
1110f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * this charger current step-up/down here.
1111f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Returns error code in case of failure else 0(on success)
1112f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt */
1113f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedtstatic int ab8500_charger_set_current(struct ab8500_charger *di,
1114f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	int ich, int reg)
1115f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt{
111634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	int ret = 0;
1117861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	int curr_index, prev_curr_index, shift_value, i;
1118f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	u8 reg_value;
111934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	u32 step_udelay;
112034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	bool no_stepping = false;
112134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
112234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	atomic_inc(&di->current_stepping_sessions);
112334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
112434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
112534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		reg, &reg_value);
112634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (ret < 0) {
112734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_err(di->dev, "%s read failed\n", __func__);
112834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		goto exit_set_current;
112934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	}
1130f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt
1131f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	switch (reg) {
1132f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	case AB8500_MCH_IPT_CURLVL_REG:
1133f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		shift_value = MAIN_CH_INPUT_CURR_SHIFT;
113434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		prev_curr_index = (reg_value >> shift_value);
1135861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		curr_index = ab8500_current_to_regval(di, ich);
113634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		step_udelay = STEP_UDELAY;
113734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (!di->ac.charger_connected)
113834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			no_stepping = true;
1139f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		break;
1140f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	case AB8500_USBCH_IPT_CRNTLVL_REG:
1141861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		if (is_ab8540(di->parent))
1142861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			shift_value = AB8540_VBUS_IN_CURR_LIM_SHIFT;
1143861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		else
1144861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			shift_value = VBUS_IN_CURR_LIM_SHIFT;
114534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		prev_curr_index = (reg_value >> shift_value);
1146861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		curr_index = ab8500_vbus_in_curr_to_regval(di, ich);
114734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		step_udelay = STEP_UDELAY * 100;
114834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
114934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (!di->usb.charger_connected)
115034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			no_stepping = true;
1151f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		break;
1152f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	case AB8500_CH_OPT_CRNTLVL_REG:
1153f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		shift_value = 0;
115434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		prev_curr_index = (reg_value >> shift_value);
1155861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		curr_index = ab8500_current_to_regval(di, ich);
115634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		step_udelay = STEP_UDELAY;
115734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (curr_index && (curr_index - prev_curr_index) > 1)
115834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			step_udelay *= 100;
115934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
116034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (!di->usb.charger_connected && !di->ac.charger_connected)
116134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			no_stepping = true;
116234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
1163f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		break;
1164f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	default:
1165f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		dev_err(di->dev, "%s current register not valid\n", __func__);
116634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ret = -ENXIO;
116734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		goto exit_set_current;
1168f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	}
1169f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt
1170f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	if (curr_index < 0) {
1171f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		dev_err(di->dev, "requested current limit out-of-range\n");
117234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ret = -ENXIO;
117334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		goto exit_set_current;
1174f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	}
1175f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt
1176f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	/* only update current if it's been changed */
117734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (prev_curr_index == curr_index) {
117834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev, "%s current not changed for reg: 0x%02x\n",
117934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			__func__, reg);
118034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ret = 0;
118134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		goto exit_set_current;
118234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	}
1183f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt
1184f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n",
1185f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		__func__, ich, reg);
1186f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt
118734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (no_stepping) {
118834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
118934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson					reg, (u8)curr_index << shift_value);
119034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (ret)
119134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			dev_err(di->dev, "%s write failed\n", __func__);
119234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	} else if (prev_curr_index > curr_index) {
1193f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		for (i = prev_curr_index - 1; i >= curr_index; i--) {
119434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			dev_dbg(di->dev, "curr change_1 to: %x for 0x%02x\n",
119534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				(u8) i << shift_value, reg);
1196f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			ret = abx500_set_register_interruptible(di->dev,
119734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				AB8500_CHARGER, reg, (u8)i << shift_value);
1198f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			if (ret) {
1199f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt				dev_err(di->dev, "%s write failed\n", __func__);
120034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				goto exit_set_current;
1201f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			}
120234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			if (i != curr_index)
120334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				usleep_range(step_udelay, step_udelay * 2);
1204f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		}
1205f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	} else {
1206f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		bool allow = true;
1207f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		for (i = prev_curr_index + 1; i <= curr_index && allow; i++) {
120834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n",
120934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				(u8)i << shift_value, reg);
1210f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			ret = abx500_set_register_interruptible(di->dev,
121134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				AB8500_CHARGER, reg, (u8)i << shift_value);
1212f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			if (ret) {
1213f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt				dev_err(di->dev, "%s write failed\n", __func__);
121434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				goto exit_set_current;
1215f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			}
121634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			if (i != curr_index)
121734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				usleep_range(step_udelay, step_udelay * 2);
1218f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones
1219f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			allow = ab8500_charger_check_continue_stepping(di, reg);
1220f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		}
1221f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	}
122234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
122334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonexit_set_current:
122434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	atomic_dec(&di->current_stepping_sessions);
122534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
1226f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	return ret;
1227f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt}
1228f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt
1229f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/**
123084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit
123184edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
123284edbeeab67c1575067335179513150115da367bArun Murthy * @ich_in:	charger input current limit
123384edbeeab67c1575067335179513150115da367bArun Murthy *
123484edbeeab67c1575067335179513150115da367bArun Murthy * Sets the current that can be drawn from the USB host
123584edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success)
123684edbeeab67c1575067335179513150115da367bArun Murthy */
123784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di,
123884edbeeab67c1575067335179513150115da367bArun Murthy		int ich_in)
123984edbeeab67c1575067335179513150115da367bArun Murthy{
124084edbeeab67c1575067335179513150115da367bArun Murthy	int min_value;
124134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	int ret;
124284edbeeab67c1575067335179513150115da367bArun Murthy
124384edbeeab67c1575067335179513150115da367bArun Murthy	/* We should always use to lowest current limit */
1244b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones	min_value = min(di->bm->chg_params->usb_curr_max, ich_in);
1245f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	if (di->max_usb_in_curr.set_max > 0)
1246f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		min_value = min(di->max_usb_in_curr.set_max, min_value);
1247f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones
1248f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	if (di->usb_state.usb_current >= 0)
1249f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		min_value = min(di->usb_state.usb_current, min_value);
125084edbeeab67c1575067335179513150115da367bArun Murthy
125184edbeeab67c1575067335179513150115da367bArun Murthy	switch (min_value) {
125284edbeeab67c1575067335179513150115da367bArun Murthy	case 100:
125384edbeeab67c1575067335179513150115da367bArun Murthy		if (di->vbat < VBAT_TRESH_IP_CUR_RED)
125484edbeeab67c1575067335179513150115da367bArun Murthy			min_value = USB_CH_IP_CUR_LVL_0P05;
125584edbeeab67c1575067335179513150115da367bArun Murthy		break;
125684edbeeab67c1575067335179513150115da367bArun Murthy	case 500:
125784edbeeab67c1575067335179513150115da367bArun Murthy		if (di->vbat < VBAT_TRESH_IP_CUR_RED)
125884edbeeab67c1575067335179513150115da367bArun Murthy			min_value = USB_CH_IP_CUR_LVL_0P45;
125984edbeeab67c1575067335179513150115da367bArun Murthy		break;
126084edbeeab67c1575067335179513150115da367bArun Murthy	default:
126184edbeeab67c1575067335179513150115da367bArun Murthy		break;
126284edbeeab67c1575067335179513150115da367bArun Murthy	}
126384edbeeab67c1575067335179513150115da367bArun Murthy
126434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	dev_info(di->dev, "VBUS input current limit set to %d mA\n", min_value);
126534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
126634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	mutex_lock(&di->usb_ipt_crnt_lock);
126734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	ret = ab8500_charger_set_current(di, min_value,
1268f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		AB8500_USBCH_IPT_CRNTLVL_REG);
126934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	mutex_unlock(&di->usb_ipt_crnt_lock);
127034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
127134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	return ret;
1272f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt}
127384edbeeab67c1575067335179513150115da367bArun Murthy
1274f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/**
1275f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * ab8500_charger_set_main_in_curr() - set main charger input current
1276f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @di:		pointer to the ab8500_charger structure
1277f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @ich_in:	input charger current, in mA
1278f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt *
1279f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Set main charger input current.
1280f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Returns error code in case of failure else 0(on success)
1281f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt */
1282f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedtstatic int ab8500_charger_set_main_in_curr(struct ab8500_charger *di,
1283f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	int ich_in)
1284f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt{
1285f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	return ab8500_charger_set_current(di, ich_in,
1286f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		AB8500_MCH_IPT_CURLVL_REG);
1287f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt}
128884edbeeab67c1575067335179513150115da367bArun Murthy
1289f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt/**
1290f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * ab8500_charger_set_output_curr() - set charger output current
1291f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @di:		pointer to the ab8500_charger structure
1292f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * @ich_out:	output charger current, in mA
1293f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt *
1294f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Set charger output current.
1295f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt * Returns error code in case of failure else 0(on success)
1296f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt */
1297f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedtstatic int ab8500_charger_set_output_curr(struct ab8500_charger *di,
1298f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	int ich_out)
1299f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt{
1300f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	return ab8500_charger_set_current(di, ich_out,
1301f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		AB8500_CH_OPT_CRNTLVL_REG);
130284edbeeab67c1575067335179513150115da367bArun Murthy}
130384edbeeab67c1575067335179513150115da367bArun Murthy
130484edbeeab67c1575067335179513150115da367bArun Murthy/**
130584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_led_en() - turn on/off chargign led
130684edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
130784edbeeab67c1575067335179513150115da367bArun Murthy * @on:		flag to turn on/off the chargign led
130884edbeeab67c1575067335179513150115da367bArun Murthy *
130984edbeeab67c1575067335179513150115da367bArun Murthy * Power ON/OFF charging LED indication
131084edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success)
131184edbeeab67c1575067335179513150115da367bArun Murthy */
131284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_led_en(struct ab8500_charger *di, int on)
131384edbeeab67c1575067335179513150115da367bArun Murthy{
131484edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
131584edbeeab67c1575067335179513150115da367bArun Murthy
131684edbeeab67c1575067335179513150115da367bArun Murthy	if (on) {
131784edbeeab67c1575067335179513150115da367bArun Murthy		/* Power ON charging LED indicator, set LED current to 5mA */
131884edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
131984edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_LED_INDICATOR_PWM_CTRL,
132084edbeeab67c1575067335179513150115da367bArun Murthy			(LED_IND_CUR_5MA | LED_INDICATOR_PWM_ENA));
132184edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
132284edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "Power ON LED failed\n");
132384edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
132484edbeeab67c1575067335179513150115da367bArun Murthy		}
132584edbeeab67c1575067335179513150115da367bArun Murthy		/* LED indicator PWM duty cycle 252/256 */
132684edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
132784edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_LED_INDICATOR_PWM_DUTY,
132884edbeeab67c1575067335179513150115da367bArun Murthy			LED_INDICATOR_PWM_DUTY_252_256);
132984edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
133084edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "Set LED PWM duty cycle failed\n");
133184edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
133284edbeeab67c1575067335179513150115da367bArun Murthy		}
133384edbeeab67c1575067335179513150115da367bArun Murthy	} else {
133484edbeeab67c1575067335179513150115da367bArun Murthy		/* Power off charging LED indicator */
133584edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
133684edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_LED_INDICATOR_PWM_CTRL,
133784edbeeab67c1575067335179513150115da367bArun Murthy			LED_INDICATOR_PWM_DIS);
133884edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
133984edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "Power-off LED failed\n");
134084edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
134184edbeeab67c1575067335179513150115da367bArun Murthy		}
134284edbeeab67c1575067335179513150115da367bArun Murthy	}
134384edbeeab67c1575067335179513150115da367bArun Murthy
134484edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
134584edbeeab67c1575067335179513150115da367bArun Murthy}
134684edbeeab67c1575067335179513150115da367bArun Murthy
134784edbeeab67c1575067335179513150115da367bArun Murthy/**
134884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_en() - enable or disable ac charging
134984edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
135084edbeeab67c1575067335179513150115da367bArun Murthy * @enable:	enable/disable flag
135184edbeeab67c1575067335179513150115da367bArun Murthy * @vset:	charging voltage
135284edbeeab67c1575067335179513150115da367bArun Murthy * @iset:	charging current
135384edbeeab67c1575067335179513150115da367bArun Murthy *
135484edbeeab67c1575067335179513150115da367bArun Murthy * Enable/Disable AC/Mains charging and turns on/off the charging led
135584edbeeab67c1575067335179513150115da367bArun Murthy * respectively.
135684edbeeab67c1575067335179513150115da367bArun Murthy **/
135784edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_en(struct ux500_charger *charger,
135884edbeeab67c1575067335179513150115da367bArun Murthy	int enable, int vset, int iset)
135984edbeeab67c1575067335179513150115da367bArun Murthy{
136084edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
136184edbeeab67c1575067335179513150115da367bArun Murthy	int volt_index;
136284edbeeab67c1575067335179513150115da367bArun Murthy	int curr_index;
136384edbeeab67c1575067335179513150115da367bArun Murthy	int input_curr_index;
136484edbeeab67c1575067335179513150115da367bArun Murthy	u8 overshoot = 0;
136584edbeeab67c1575067335179513150115da367bArun Murthy
136684edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
136784edbeeab67c1575067335179513150115da367bArun Murthy
136884edbeeab67c1575067335179513150115da367bArun Murthy	if (enable) {
136984edbeeab67c1575067335179513150115da367bArun Murthy		/* Check if AC is connected */
137084edbeeab67c1575067335179513150115da367bArun Murthy		if (!di->ac.charger_connected) {
137184edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "AC charger not connected\n");
137284edbeeab67c1575067335179513150115da367bArun Murthy			return -ENXIO;
137384edbeeab67c1575067335179513150115da367bArun Murthy		}
137484edbeeab67c1575067335179513150115da367bArun Murthy
137584edbeeab67c1575067335179513150115da367bArun Murthy		/* Enable AC charging */
137684edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "Enable AC: %dmV %dmA\n", vset, iset);
137784edbeeab67c1575067335179513150115da367bArun Murthy
137884edbeeab67c1575067335179513150115da367bArun Murthy		/*
137984edbeeab67c1575067335179513150115da367bArun Murthy		 * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
138084edbeeab67c1575067335179513150115da367bArun Murthy		 * will be triggered everytime we enable the VDD ADC supply.
138184edbeeab67c1575067335179513150115da367bArun Murthy		 * This will turn off charging for a short while.
138284edbeeab67c1575067335179513150115da367bArun Murthy		 * It can be avoided by having the supply on when
138384edbeeab67c1575067335179513150115da367bArun Murthy		 * there is a charger enabled. Normally the VDD ADC supply
138484edbeeab67c1575067335179513150115da367bArun Murthy		 * is enabled everytime a GPADC conversion is triggered. We will
138584edbeeab67c1575067335179513150115da367bArun Murthy		 * force it to be enabled from this driver to have
138684edbeeab67c1575067335179513150115da367bArun Murthy		 * the GPADC module independant of the AB8500 chargers
138784edbeeab67c1575067335179513150115da367bArun Murthy		 */
138884edbeeab67c1575067335179513150115da367bArun Murthy		if (!di->vddadc_en_ac) {
13896de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat			ret = regulator_enable(di->regu);
13906de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat			if (ret)
13916de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat				dev_warn(di->dev,
13926de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat					"Failed to enable regulator\n");
13936de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat			else
13946de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat				di->vddadc_en_ac = true;
139584edbeeab67c1575067335179513150115da367bArun Murthy		}
139684edbeeab67c1575067335179513150115da367bArun Murthy
139784edbeeab67c1575067335179513150115da367bArun Murthy		/* Check if the requested voltage or current is valid */
139884edbeeab67c1575067335179513150115da367bArun Murthy		volt_index = ab8500_voltage_to_regval(vset);
1399861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		curr_index = ab8500_current_to_regval(di, iset);
1400861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		input_curr_index = ab8500_current_to_regval(di,
1401b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones			di->bm->chg_params->ac_curr_max);
140284edbeeab67c1575067335179513150115da367bArun Murthy		if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) {
140384edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev,
140484edbeeab67c1575067335179513150115da367bArun Murthy				"Charger voltage or current too high, "
140584edbeeab67c1575067335179513150115da367bArun Murthy				"charging not started\n");
140684edbeeab67c1575067335179513150115da367bArun Murthy			return -ENXIO;
140784edbeeab67c1575067335179513150115da367bArun Murthy		}
140884edbeeab67c1575067335179513150115da367bArun Murthy
140984edbeeab67c1575067335179513150115da367bArun Murthy		/* ChVoltLevel: maximum battery charging voltage */
141084edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
141184edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CH_VOLT_LVL_REG, (u8) volt_index);
141284edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
141384edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s write failed\n", __func__);
141484edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
141584edbeeab67c1575067335179513150115da367bArun Murthy		}
141684edbeeab67c1575067335179513150115da367bArun Murthy		/* MainChInputCurr: current that can be drawn from the charger*/
1417f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		ret = ab8500_charger_set_main_in_curr(di,
1418b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones			di->bm->chg_params->ac_curr_max);
141984edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
1420f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			dev_err(di->dev, "%s Failed to set MainChInputCurr\n",
1421f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt				__func__);
142284edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
142384edbeeab67c1575067335179513150115da367bArun Murthy		}
142484edbeeab67c1575067335179513150115da367bArun Murthy		/* ChOutputCurentLevel: protected output current */
1425f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		ret = ab8500_charger_set_output_curr(di, iset);
142684edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
1427f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			dev_err(di->dev, "%s "
1428f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt				"Failed to set ChOutputCurentLevel\n",
1429f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt				__func__);
143084edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
143184edbeeab67c1575067335179513150115da367bArun Murthy		}
143284edbeeab67c1575067335179513150115da367bArun Murthy
143384edbeeab67c1575067335179513150115da367bArun Murthy		/* Check if VBAT overshoot control should be enabled */
1434b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones		if (!di->bm->enable_overshoot)
143584edbeeab67c1575067335179513150115da367bArun Murthy			overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N;
143684edbeeab67c1575067335179513150115da367bArun Murthy
143784edbeeab67c1575067335179513150115da367bArun Murthy		/* Enable Main Charger */
143884edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
143984edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_MCH_CTRL1, MAIN_CH_ENA | overshoot);
144084edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
144184edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s write failed\n", __func__);
144284edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
144384edbeeab67c1575067335179513150115da367bArun Murthy		}
144484edbeeab67c1575067335179513150115da367bArun Murthy
144584edbeeab67c1575067335179513150115da367bArun Murthy		/* Power on charging LED indication */
144684edbeeab67c1575067335179513150115da367bArun Murthy		ret = ab8500_charger_led_en(di, true);
144784edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0)
144884edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "failed to enable LED\n");
144984edbeeab67c1575067335179513150115da367bArun Murthy
145084edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.charger_online = 1;
145184edbeeab67c1575067335179513150115da367bArun Murthy	} else {
145284edbeeab67c1575067335179513150115da367bArun Murthy		/* Disable AC charging */
145384edbeeab67c1575067335179513150115da367bArun Murthy		if (is_ab8500_1p1_or_earlier(di->parent)) {
145484edbeeab67c1575067335179513150115da367bArun Murthy			/*
145584edbeeab67c1575067335179513150115da367bArun Murthy			 * For ABB revision 1.0 and 1.1 there is a bug in the
145684edbeeab67c1575067335179513150115da367bArun Murthy			 * watchdog logic. That means we have to continously
145784edbeeab67c1575067335179513150115da367bArun Murthy			 * kick the charger watchdog even when no charger is
145884edbeeab67c1575067335179513150115da367bArun Murthy			 * connected. This is only valid once the AC charger
145984edbeeab67c1575067335179513150115da367bArun Murthy			 * has been enabled. This is a bug that is not handled
146084edbeeab67c1575067335179513150115da367bArun Murthy			 * by the algorithm and the watchdog have to be kicked
146184edbeeab67c1575067335179513150115da367bArun Murthy			 * by the charger driver when the AC charger
146284edbeeab67c1575067335179513150115da367bArun Murthy			 * is disabled
146384edbeeab67c1575067335179513150115da367bArun Murthy			 */
146484edbeeab67c1575067335179513150115da367bArun Murthy			if (di->ac_conn) {
146584edbeeab67c1575067335179513150115da367bArun Murthy				queue_delayed_work(di->charger_wq,
146684edbeeab67c1575067335179513150115da367bArun Murthy					&di->kick_wd_work,
146784edbeeab67c1575067335179513150115da367bArun Murthy					round_jiffies(WD_KICK_INTERVAL));
146884edbeeab67c1575067335179513150115da367bArun Murthy			}
146984edbeeab67c1575067335179513150115da367bArun Murthy
147084edbeeab67c1575067335179513150115da367bArun Murthy			/*
147184edbeeab67c1575067335179513150115da367bArun Murthy			 * We can't turn off charging completely
147284edbeeab67c1575067335179513150115da367bArun Murthy			 * due to a bug in AB8500 cut1.
147384edbeeab67c1575067335179513150115da367bArun Murthy			 * If we do, charging will not start again.
147484edbeeab67c1575067335179513150115da367bArun Murthy			 * That is why we set the lowest voltage
147584edbeeab67c1575067335179513150115da367bArun Murthy			 * and current possible
147684edbeeab67c1575067335179513150115da367bArun Murthy			 */
147784edbeeab67c1575067335179513150115da367bArun Murthy			ret = abx500_set_register_interruptible(di->dev,
147884edbeeab67c1575067335179513150115da367bArun Murthy				AB8500_CHARGER,
147984edbeeab67c1575067335179513150115da367bArun Murthy				AB8500_CH_VOLT_LVL_REG, CH_VOL_LVL_3P5);
148084edbeeab67c1575067335179513150115da367bArun Murthy			if (ret) {
148184edbeeab67c1575067335179513150115da367bArun Murthy				dev_err(di->dev,
148284edbeeab67c1575067335179513150115da367bArun Murthy					"%s write failed\n", __func__);
148384edbeeab67c1575067335179513150115da367bArun Murthy				return ret;
148484edbeeab67c1575067335179513150115da367bArun Murthy			}
148584edbeeab67c1575067335179513150115da367bArun Murthy
1486f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			ret = ab8500_charger_set_output_curr(di, 0);
148784edbeeab67c1575067335179513150115da367bArun Murthy			if (ret) {
1488f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt				dev_err(di->dev, "%s "
1489f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt					"Failed to set ChOutputCurentLevel\n",
1490f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt					__func__);
149184edbeeab67c1575067335179513150115da367bArun Murthy				return ret;
149284edbeeab67c1575067335179513150115da367bArun Murthy			}
149384edbeeab67c1575067335179513150115da367bArun Murthy		} else {
149484edbeeab67c1575067335179513150115da367bArun Murthy			ret = abx500_set_register_interruptible(di->dev,
149584edbeeab67c1575067335179513150115da367bArun Murthy				AB8500_CHARGER,
149684edbeeab67c1575067335179513150115da367bArun Murthy				AB8500_MCH_CTRL1, 0);
149784edbeeab67c1575067335179513150115da367bArun Murthy			if (ret) {
149884edbeeab67c1575067335179513150115da367bArun Murthy				dev_err(di->dev,
149984edbeeab67c1575067335179513150115da367bArun Murthy					"%s write failed\n", __func__);
150084edbeeab67c1575067335179513150115da367bArun Murthy				return ret;
150184edbeeab67c1575067335179513150115da367bArun Murthy			}
150284edbeeab67c1575067335179513150115da367bArun Murthy		}
150384edbeeab67c1575067335179513150115da367bArun Murthy
150484edbeeab67c1575067335179513150115da367bArun Murthy		ret = ab8500_charger_led_en(di, false);
150584edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0)
150684edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "failed to disable LED\n");
150784edbeeab67c1575067335179513150115da367bArun Murthy
150884edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.charger_online = 0;
150984edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.wd_expired = false;
151084edbeeab67c1575067335179513150115da367bArun Murthy
151184edbeeab67c1575067335179513150115da367bArun Murthy		/* Disable regulator if enabled */
151284edbeeab67c1575067335179513150115da367bArun Murthy		if (di->vddadc_en_ac) {
151384edbeeab67c1575067335179513150115da367bArun Murthy			regulator_disable(di->regu);
151484edbeeab67c1575067335179513150115da367bArun Murthy			di->vddadc_en_ac = false;
151584edbeeab67c1575067335179513150115da367bArun Murthy		}
151684edbeeab67c1575067335179513150115da367bArun Murthy
151784edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "%s Disabled AC charging\n", __func__);
151884edbeeab67c1575067335179513150115da367bArun Murthy	}
151984edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_power_supply_changed(di, &di->ac_chg.psy);
152084edbeeab67c1575067335179513150115da367bArun Murthy
152184edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
152284edbeeab67c1575067335179513150115da367bArun Murthy}
152384edbeeab67c1575067335179513150115da367bArun Murthy
152484edbeeab67c1575067335179513150115da367bArun Murthy/**
152584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_en() - enable usb charging
152684edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
152784edbeeab67c1575067335179513150115da367bArun Murthy * @enable:	enable/disable flag
152884edbeeab67c1575067335179513150115da367bArun Murthy * @vset:	charging voltage
152984edbeeab67c1575067335179513150115da367bArun Murthy * @ich_out:	charger output current
153084edbeeab67c1575067335179513150115da367bArun Murthy *
153184edbeeab67c1575067335179513150115da367bArun Murthy * Enable/Disable USB charging and turns on/off the charging led respectively.
153284edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success)
153384edbeeab67c1575067335179513150115da367bArun Murthy */
153484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_en(struct ux500_charger *charger,
153584edbeeab67c1575067335179513150115da367bArun Murthy	int enable, int vset, int ich_out)
153684edbeeab67c1575067335179513150115da367bArun Murthy{
153784edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
153884edbeeab67c1575067335179513150115da367bArun Murthy	int volt_index;
153984edbeeab67c1575067335179513150115da367bArun Murthy	int curr_index;
154084edbeeab67c1575067335179513150115da367bArun Murthy	u8 overshoot = 0;
154184edbeeab67c1575067335179513150115da367bArun Murthy
154284edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
154384edbeeab67c1575067335179513150115da367bArun Murthy
154484edbeeab67c1575067335179513150115da367bArun Murthy	if (enable) {
154584edbeeab67c1575067335179513150115da367bArun Murthy		/* Check if USB is connected */
154684edbeeab67c1575067335179513150115da367bArun Murthy		if (!di->usb.charger_connected) {
154784edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "USB charger not connected\n");
154884edbeeab67c1575067335179513150115da367bArun Murthy			return -ENXIO;
154984edbeeab67c1575067335179513150115da367bArun Murthy		}
155084edbeeab67c1575067335179513150115da367bArun Murthy
155184edbeeab67c1575067335179513150115da367bArun Murthy		/*
155284edbeeab67c1575067335179513150115da367bArun Murthy		 * Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
155384edbeeab67c1575067335179513150115da367bArun Murthy		 * will be triggered everytime we enable the VDD ADC supply.
155484edbeeab67c1575067335179513150115da367bArun Murthy		 * This will turn off charging for a short while.
155584edbeeab67c1575067335179513150115da367bArun Murthy		 * It can be avoided by having the supply on when
155684edbeeab67c1575067335179513150115da367bArun Murthy		 * there is a charger enabled. Normally the VDD ADC supply
155784edbeeab67c1575067335179513150115da367bArun Murthy		 * is enabled everytime a GPADC conversion is triggered. We will
155884edbeeab67c1575067335179513150115da367bArun Murthy		 * force it to be enabled from this driver to have
155984edbeeab67c1575067335179513150115da367bArun Murthy		 * the GPADC module independant of the AB8500 chargers
156084edbeeab67c1575067335179513150115da367bArun Murthy		 */
156184edbeeab67c1575067335179513150115da367bArun Murthy		if (!di->vddadc_en_usb) {
15626de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat			ret = regulator_enable(di->regu);
15636de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat			if (ret)
15646de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat				dev_warn(di->dev,
15656de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat					"Failed to enable regulator\n");
15666de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat			else
15676de7ef3e309acb1e55ae122b85a2665064832b0cSachin Kamat				di->vddadc_en_usb = true;
156884edbeeab67c1575067335179513150115da367bArun Murthy		}
156984edbeeab67c1575067335179513150115da367bArun Murthy
157084edbeeab67c1575067335179513150115da367bArun Murthy		/* Enable USB charging */
157184edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "Enable USB: %dmV %dmA\n", vset, ich_out);
157284edbeeab67c1575067335179513150115da367bArun Murthy
157384edbeeab67c1575067335179513150115da367bArun Murthy		/* Check if the requested voltage or current is valid */
157484edbeeab67c1575067335179513150115da367bArun Murthy		volt_index = ab8500_voltage_to_regval(vset);
1575861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		curr_index = ab8500_current_to_regval(di, ich_out);
157684edbeeab67c1575067335179513150115da367bArun Murthy		if (volt_index < 0 || curr_index < 0) {
157784edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev,
157884edbeeab67c1575067335179513150115da367bArun Murthy				"Charger voltage or current too high, "
157984edbeeab67c1575067335179513150115da367bArun Murthy				"charging not started\n");
158084edbeeab67c1575067335179513150115da367bArun Murthy			return -ENXIO;
158184edbeeab67c1575067335179513150115da367bArun Murthy		}
158284edbeeab67c1575067335179513150115da367bArun Murthy
158384edbeeab67c1575067335179513150115da367bArun Murthy		/* ChVoltLevel: max voltage upto which battery can be charged */
158484edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
158584edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CH_VOLT_LVL_REG, (u8) volt_index);
158684edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
158784edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s write failed\n", __func__);
158884edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
158984edbeeab67c1575067335179513150115da367bArun Murthy		}
159084edbeeab67c1575067335179513150115da367bArun Murthy		/* Check if VBAT overshoot control should be enabled */
1591b0284de05e07d56ff7de154d0c9263788755f5ebLee Jones		if (!di->bm->enable_overshoot)
159284edbeeab67c1575067335179513150115da367bArun Murthy			overshoot = USB_CHG_NO_OVERSHOOT_ENA_N;
159384edbeeab67c1575067335179513150115da367bArun Murthy
159484edbeeab67c1575067335179513150115da367bArun Murthy		/* Enable USB Charger */
159534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev,
159634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			"Enabling USB with write to AB8500_USBCH_CTRL1_REG\n");
159784edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
159884edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot);
159984edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
160084edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s write failed\n", __func__);
160184edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
160284edbeeab67c1575067335179513150115da367bArun Murthy		}
160384edbeeab67c1575067335179513150115da367bArun Murthy
160484edbeeab67c1575067335179513150115da367bArun Murthy		/* If success power on charging LED indication */
160584edbeeab67c1575067335179513150115da367bArun Murthy		ret = ab8500_charger_led_en(di, true);
160684edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0)
160784edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "failed to enable LED\n");
160884edbeeab67c1575067335179513150115da367bArun Murthy
160934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->usb.charger_online = 1;
161034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
161134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		/* USBChInputCurr: current that can be drawn from the usb */
1612f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		ret = ab8500_charger_set_vbus_in_curr(di,
1613f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones					di->max_usb_in_curr.usb_type_max);
161434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (ret) {
161534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			dev_err(di->dev, "setting USBChInputCurr failed\n");
161634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			return ret;
161734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		}
161834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
161934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		/* ChOutputCurentLevel: protected output current */
162034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ret = ab8500_charger_set_output_curr(di, ich_out);
162134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (ret) {
162234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			dev_err(di->dev, "%s "
162334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				"Failed to set ChOutputCurentLevel\n",
162434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				__func__);
162534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			return ret;
162634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		}
162734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
162884edbeeab67c1575067335179513150115da367bArun Murthy		queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ);
162984edbeeab67c1575067335179513150115da367bArun Murthy
163084edbeeab67c1575067335179513150115da367bArun Murthy	} else {
163184edbeeab67c1575067335179513150115da367bArun Murthy		/* Disable USB charging */
163234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev, "%s Disabled USB charging\n", __func__);
163384edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev,
163484edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CHARGER,
163584edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_USBCH_CTRL1_REG, 0);
163684edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
163784edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev,
163884edbeeab67c1575067335179513150115da367bArun Murthy				"%s write failed\n", __func__);
163984edbeeab67c1575067335179513150115da367bArun Murthy			return ret;
164084edbeeab67c1575067335179513150115da367bArun Murthy		}
164184edbeeab67c1575067335179513150115da367bArun Murthy
164284edbeeab67c1575067335179513150115da367bArun Murthy		ret = ab8500_charger_led_en(di, false);
164384edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0)
164484edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "failed to disable LED\n");
164534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		/* USBChInputCurr: current that can be drawn from the usb */
164634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ret = ab8500_charger_set_vbus_in_curr(di, 0);
164734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (ret) {
164834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			dev_err(di->dev, "setting USBChInputCurr failed\n");
164934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			return ret;
165034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		}
165184edbeeab67c1575067335179513150115da367bArun Murthy
165234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		/* ChOutputCurentLevel: protected output current */
165334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ret = ab8500_charger_set_output_curr(di, 0);
165434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (ret) {
165534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			dev_err(di->dev, "%s "
165634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				"Failed to reset ChOutputCurentLevel\n",
165734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				__func__);
165834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			return ret;
165934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		}
166084edbeeab67c1575067335179513150115da367bArun Murthy		di->usb.charger_online = 0;
166184edbeeab67c1575067335179513150115da367bArun Murthy		di->usb.wd_expired = false;
166284edbeeab67c1575067335179513150115da367bArun Murthy
166384edbeeab67c1575067335179513150115da367bArun Murthy		/* Disable regulator if enabled */
166484edbeeab67c1575067335179513150115da367bArun Murthy		if (di->vddadc_en_usb) {
166584edbeeab67c1575067335179513150115da367bArun Murthy			regulator_disable(di->regu);
166684edbeeab67c1575067335179513150115da367bArun Murthy			di->vddadc_en_usb = false;
166784edbeeab67c1575067335179513150115da367bArun Murthy		}
166884edbeeab67c1575067335179513150115da367bArun Murthy
166984edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "%s Disabled USB charging\n", __func__);
167084edbeeab67c1575067335179513150115da367bArun Murthy
167184edbeeab67c1575067335179513150115da367bArun Murthy		/* Cancel any pending Vbat check work */
1672b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones		cancel_delayed_work(&di->check_vbat_work);
167384edbeeab67c1575067335179513150115da367bArun Murthy
167484edbeeab67c1575067335179513150115da367bArun Murthy	}
167584edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_power_supply_changed(di, &di->usb_chg.psy);
167684edbeeab67c1575067335179513150115da367bArun Murthy
167784edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
167884edbeeab67c1575067335179513150115da367bArun Murthy}
167984edbeeab67c1575067335179513150115da367bArun Murthy
16808891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jonesstatic int ab8500_external_charger_prepare(struct notifier_block *charger_nb,
16818891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones				unsigned long event, void *data)
16828891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones{
16838891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	int ret;
16848891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	struct device *dev = data;
16858891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	/*Toggle External charger control pin*/
16868891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
16878891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones				  AB8500_SYS_CHARGER_CONTROL_REG,
16888891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones				  EXTERNAL_CHARGER_DISABLE_REG_VAL);
16898891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	if (ret < 0) {
16908891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones		dev_err(dev, "write reg failed %d\n", ret);
16918891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones		goto out;
16928891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	}
16938891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
16948891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones				  AB8500_SYS_CHARGER_CONTROL_REG,
16958891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones				  EXTERNAL_CHARGER_ENABLE_REG_VAL);
16968891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	if (ret < 0)
16978891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones		dev_err(dev, "Write reg failed %d\n", ret);
16988891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones
16998891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jonesout:
17008891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	return ret;
17018891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones}
17028891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones
170384edbeeab67c1575067335179513150115da367bArun Murthy/**
17044dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * ab8500_charger_usb_check_enable() - enable usb charging
17054dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @charger:	pointer to the ux500_charger structure
17064dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @vset:	charging voltage
17074dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @iset:	charger output current
17084dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones *
17094dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * Check if the VBUS charger has been disconnected and reconnected without
17104dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * AB8500 rising an interrupt. Returns 0 on success.
17114dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones */
17124dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jonesstatic int ab8500_charger_usb_check_enable(struct ux500_charger *charger,
17134dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	int vset, int iset)
17144dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones{
17154dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	u8 usbch_ctrl1 = 0;
17164dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	int ret = 0;
17174dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17184dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	struct ab8500_charger *di = to_ab8500_charger_usb_device_info(charger);
17194dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17204dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	if (!di->usb.charger_connected)
17214dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		return ret;
17224dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17234dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
17244dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones				AB8500_USBCH_CTRL1_REG, &usbch_ctrl1);
17254dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	if (ret < 0) {
17264dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
17274dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		return ret;
17284dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	}
17294dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	dev_dbg(di->dev, "USB charger ctrl: 0x%02x\n", usbch_ctrl1);
17304dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17314dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	if (!(usbch_ctrl1 & USB_CH_ENA)) {
17324dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
17334dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17344dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		ret = abx500_mask_and_set_register_interruptible(di->dev,
17354dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones					AB8500_CHARGER, AB8500_CHARGER_CTRL,
17364dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones					DROP_COUNT_RESET, DROP_COUNT_RESET);
17374dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		if (ret < 0) {
17384dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
17394dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			return ret;
17404dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		}
17414dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17424dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		ret = ab8500_charger_usb_en(&di->usb_chg, true, vset, iset);
17434dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		if (ret < 0) {
17444dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			dev_err(di->dev, "Failed to enable VBUS charger %d\n",
17454dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones					__LINE__);
17464dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			return ret;
17474dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		}
17484dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	}
17494dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	return ret;
17504dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones}
17514dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17524dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones/**
17534dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * ab8500_charger_ac_check_enable() - enable usb charging
17544dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @charger:	pointer to the ux500_charger structure
17554dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @vset:	charging voltage
17564dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * @iset:	charger output current
17574dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones *
17584dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * Check if the AC charger has been disconnected and reconnected without
17594dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones * AB8500 rising an interrupt. Returns 0 on success.
17604dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones */
17614dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jonesstatic int ab8500_charger_ac_check_enable(struct ux500_charger *charger,
17624dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	int vset, int iset)
17634dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones{
17644dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	u8 mainch_ctrl1 = 0;
17654dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	int ret = 0;
17664dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17674dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	struct ab8500_charger *di = to_ab8500_charger_ac_device_info(charger);
17684dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17694dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	if (!di->ac.charger_connected)
17704dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		return ret;
17714dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17724dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
17734dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones				AB8500_MCH_CTRL1, &mainch_ctrl1);
17744dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	if (ret < 0) {
17754dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
17764dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		return ret;
17774dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	}
17784dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	dev_dbg(di->dev, "AC charger ctrl: 0x%02x\n", mainch_ctrl1);
17794dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17804dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	if (!(mainch_ctrl1 & MAIN_CH_ENA)) {
17814dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		dev_info(di->dev, "Charging has been disabled abnormally and will be re-enabled\n");
17824dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17834dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		ret = abx500_mask_and_set_register_interruptible(di->dev,
17844dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones					AB8500_CHARGER, AB8500_CHARGER_CTRL,
17854dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones					DROP_COUNT_RESET, DROP_COUNT_RESET);
17864dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17874dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		if (ret < 0) {
17884dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			dev_err(di->dev, "ab8500 write failed %d\n", __LINE__);
17894dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			return ret;
17904dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		}
17914dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
17924dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		ret = ab8500_charger_ac_en(&di->usb_chg, true, vset, iset);
17934dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		if (ret < 0) {
17944dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			dev_err(di->dev, "failed to enable AC charger %d\n",
17954dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones				__LINE__);
17964dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones			return ret;
17974dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones		}
17984dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	}
17994dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	return ret;
18004dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones}
18014dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones
18024dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones/**
180384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_watchdog_kick() - kick charger watchdog
180484edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
180584edbeeab67c1575067335179513150115da367bArun Murthy *
180684edbeeab67c1575067335179513150115da367bArun Murthy * Kick charger watchdog
180784edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success)
180884edbeeab67c1575067335179513150115da367bArun Murthy */
180984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_watchdog_kick(struct ux500_charger *charger)
181084edbeeab67c1575067335179513150115da367bArun Murthy{
181184edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
181284edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di;
181384edbeeab67c1575067335179513150115da367bArun Murthy
181484edbeeab67c1575067335179513150115da367bArun Murthy	if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
181584edbeeab67c1575067335179513150115da367bArun Murthy		di = to_ab8500_charger_ac_device_info(charger);
181684edbeeab67c1575067335179513150115da367bArun Murthy	else if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
181784edbeeab67c1575067335179513150115da367bArun Murthy		di = to_ab8500_charger_usb_device_info(charger);
181884edbeeab67c1575067335179513150115da367bArun Murthy	else
181984edbeeab67c1575067335179513150115da367bArun Murthy		return -ENXIO;
182084edbeeab67c1575067335179513150115da367bArun Murthy
182184edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
182284edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
182384edbeeab67c1575067335179513150115da367bArun Murthy	if (ret)
182484edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "Failed to kick WD!\n");
182584edbeeab67c1575067335179513150115da367bArun Murthy
182684edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
182784edbeeab67c1575067335179513150115da367bArun Murthy}
182884edbeeab67c1575067335179513150115da367bArun Murthy
182984edbeeab67c1575067335179513150115da367bArun Murthy/**
183084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_update_charger_current() - update charger current
183184edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
183284edbeeab67c1575067335179513150115da367bArun Murthy *
183384edbeeab67c1575067335179513150115da367bArun Murthy * Update the charger output current for the specified charger
183484edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success)
183584edbeeab67c1575067335179513150115da367bArun Murthy */
183684edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_update_charger_current(struct ux500_charger *charger,
183784edbeeab67c1575067335179513150115da367bArun Murthy		int ich_out)
183884edbeeab67c1575067335179513150115da367bArun Murthy{
183984edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
184084edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di;
184184edbeeab67c1575067335179513150115da367bArun Murthy
184284edbeeab67c1575067335179513150115da367bArun Murthy	if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
184384edbeeab67c1575067335179513150115da367bArun Murthy		di = to_ab8500_charger_ac_device_info(charger);
184484edbeeab67c1575067335179513150115da367bArun Murthy	else if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
184584edbeeab67c1575067335179513150115da367bArun Murthy		di = to_ab8500_charger_usb_device_info(charger);
184684edbeeab67c1575067335179513150115da367bArun Murthy	else
184784edbeeab67c1575067335179513150115da367bArun Murthy		return -ENXIO;
184884edbeeab67c1575067335179513150115da367bArun Murthy
1849f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt	ret = ab8500_charger_set_output_curr(di, ich_out);
185084edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
1851f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt		dev_err(di->dev, "%s "
1852f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			"Failed to set ChOutputCurentLevel\n",
1853f8e96dff240982c1433d447bae533acc36b5cf8fJohan Bjornstedt			__func__);
185484edbeeab67c1575067335179513150115da367bArun Murthy		return ret;
185584edbeeab67c1575067335179513150115da367bArun Murthy	}
185684edbeeab67c1575067335179513150115da367bArun Murthy
185784edbeeab67c1575067335179513150115da367bArun Murthy	/* Reset the main and usb drop input current measurement counter */
185884edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
18594dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones				AB8500_CHARGER_CTRL, DROP_COUNT_RESET);
186084edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
186184edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s write failed\n", __func__);
186284edbeeab67c1575067335179513150115da367bArun Murthy		return ret;
186384edbeeab67c1575067335179513150115da367bArun Murthy	}
186484edbeeab67c1575067335179513150115da367bArun Murthy
186584edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
186684edbeeab67c1575067335179513150115da367bArun Murthy}
186784edbeeab67c1575067335179513150115da367bArun Murthy
1868db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones/**
1869db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * ab8540_charger_power_path_enable() - enable usb power path mode
1870db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @charger:	pointer to the ux500_charger structure
1871db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @enable:	enable/disable flag
1872db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones *
1873db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Enable or disable the power path for usb mode
1874db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Returns error code in case of failure else 0(on success)
1875db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones */
1876db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jonesstatic int ab8540_charger_power_path_enable(struct ux500_charger *charger,
1877db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		bool enable)
1878db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones{
1879db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	int ret;
1880db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	struct ab8500_charger *di;
1881db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1882db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
1883db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		di = to_ab8500_charger_usb_device_info(charger);
1884db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	else
1885db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		return -ENXIO;
1886db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1887db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	ret = abx500_mask_and_set_register_interruptible(di->dev,
1888db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones				AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
1889db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones				BUS_POWER_PATH_MODE_ENA, enable);
1890db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	if (ret) {
1891db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		dev_err(di->dev, "%s write failed\n", __func__);
1892db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		return ret;
1893db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	}
1894db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1895db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	return ret;
1896db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones}
1897db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1898db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1899db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones/**
1900db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * ab8540_charger_usb_pre_chg_enable() - enable usb pre change
1901db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @charger:	pointer to the ux500_charger structure
1902db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * @enable:	enable/disable flag
1903db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones *
1904db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Enable or disable the pre-chage for usb mode
1905db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones * Returns error code in case of failure else 0(on success)
1906db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones */
1907db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jonesstatic int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger,
1908db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		bool enable)
1909db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones{
1910db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	int ret;
1911db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	struct ab8500_charger *di;
1912db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1913db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
1914db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		di = to_ab8500_charger_usb_device_info(charger);
1915db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	else
1916db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		return -ENXIO;
1917db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1918db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	ret = abx500_mask_and_set_register_interruptible(di->dev,
1919db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones				AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
1920db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones				BUS_POWER_PATH_PRECHG_ENA, enable);
1921db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	if (ret) {
1922db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		dev_err(di->dev, "%s write failed\n", __func__);
1923db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		return ret;
1924db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	}
1925db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
1926db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	return ret;
1927db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones}
1928db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
192984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
193084edbeeab67c1575067335179513150115da367bArun Murthy{
193184edbeeab67c1575067335179513150115da367bArun Murthy	struct power_supply *psy;
193284edbeeab67c1575067335179513150115da367bArun Murthy	struct power_supply *ext;
193384edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di;
193484edbeeab67c1575067335179513150115da367bArun Murthy	union power_supply_propval ret;
193584edbeeab67c1575067335179513150115da367bArun Murthy	int i, j;
193684edbeeab67c1575067335179513150115da367bArun Murthy	bool psy_found = false;
193784edbeeab67c1575067335179513150115da367bArun Murthy	struct ux500_charger *usb_chg;
193884edbeeab67c1575067335179513150115da367bArun Murthy
193984edbeeab67c1575067335179513150115da367bArun Murthy	usb_chg = (struct ux500_charger *)data;
194084edbeeab67c1575067335179513150115da367bArun Murthy	psy = &usb_chg->psy;
194184edbeeab67c1575067335179513150115da367bArun Murthy
194284edbeeab67c1575067335179513150115da367bArun Murthy	di = to_ab8500_charger_usb_device_info(usb_chg);
194384edbeeab67c1575067335179513150115da367bArun Murthy
194484edbeeab67c1575067335179513150115da367bArun Murthy	ext = dev_get_drvdata(dev);
194584edbeeab67c1575067335179513150115da367bArun Murthy
194684edbeeab67c1575067335179513150115da367bArun Murthy	/* For all psy where the driver name appears in any supplied_to */
194784edbeeab67c1575067335179513150115da367bArun Murthy	for (i = 0; i < ext->num_supplicants; i++) {
194884edbeeab67c1575067335179513150115da367bArun Murthy		if (!strcmp(ext->supplied_to[i], psy->name))
194984edbeeab67c1575067335179513150115da367bArun Murthy			psy_found = true;
195084edbeeab67c1575067335179513150115da367bArun Murthy	}
195184edbeeab67c1575067335179513150115da367bArun Murthy
195284edbeeab67c1575067335179513150115da367bArun Murthy	if (!psy_found)
195384edbeeab67c1575067335179513150115da367bArun Murthy		return 0;
195484edbeeab67c1575067335179513150115da367bArun Murthy
195584edbeeab67c1575067335179513150115da367bArun Murthy	/* Go through all properties for the psy */
195684edbeeab67c1575067335179513150115da367bArun Murthy	for (j = 0; j < ext->num_properties; j++) {
195784edbeeab67c1575067335179513150115da367bArun Murthy		enum power_supply_property prop;
195884edbeeab67c1575067335179513150115da367bArun Murthy		prop = ext->properties[j];
195984edbeeab67c1575067335179513150115da367bArun Murthy
196084edbeeab67c1575067335179513150115da367bArun Murthy		if (ext->get_property(ext, prop, &ret))
196184edbeeab67c1575067335179513150115da367bArun Murthy			continue;
196284edbeeab67c1575067335179513150115da367bArun Murthy
196384edbeeab67c1575067335179513150115da367bArun Murthy		switch (prop) {
196484edbeeab67c1575067335179513150115da367bArun Murthy		case POWER_SUPPLY_PROP_VOLTAGE_NOW:
196584edbeeab67c1575067335179513150115da367bArun Murthy			switch (ext->type) {
196684edbeeab67c1575067335179513150115da367bArun Murthy			case POWER_SUPPLY_TYPE_BATTERY:
196784edbeeab67c1575067335179513150115da367bArun Murthy				di->vbat = ret.intval / 1000;
196884edbeeab67c1575067335179513150115da367bArun Murthy				break;
196984edbeeab67c1575067335179513150115da367bArun Murthy			default:
197084edbeeab67c1575067335179513150115da367bArun Murthy				break;
197184edbeeab67c1575067335179513150115da367bArun Murthy			}
197284edbeeab67c1575067335179513150115da367bArun Murthy			break;
197384edbeeab67c1575067335179513150115da367bArun Murthy		default:
197484edbeeab67c1575067335179513150115da367bArun Murthy			break;
197584edbeeab67c1575067335179513150115da367bArun Murthy		}
197684edbeeab67c1575067335179513150115da367bArun Murthy	}
197784edbeeab67c1575067335179513150115da367bArun Murthy	return 0;
197884edbeeab67c1575067335179513150115da367bArun Murthy}
197984edbeeab67c1575067335179513150115da367bArun Murthy
198084edbeeab67c1575067335179513150115da367bArun Murthy/**
198184edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_vbat_work() - keep vbus current within spec
198284edbeeab67c1575067335179513150115da367bArun Murthy * @work	pointer to the work_struct structure
198384edbeeab67c1575067335179513150115da367bArun Murthy *
198484edbeeab67c1575067335179513150115da367bArun Murthy * Due to a asic bug it is necessary to lower the input current to the vbus
198584edbeeab67c1575067335179513150115da367bArun Murthy * charger when charging with at some specific levels. This issue is only valid
198684edbeeab67c1575067335179513150115da367bArun Murthy * for below a certain battery voltage. This function makes sure that the
198784edbeeab67c1575067335179513150115da367bArun Murthy * the allowed current limit isn't exceeded.
198884edbeeab67c1575067335179513150115da367bArun Murthy */
198984edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_vbat_work(struct work_struct *work)
199084edbeeab67c1575067335179513150115da367bArun Murthy{
199184edbeeab67c1575067335179513150115da367bArun Murthy	int t = 10;
199284edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
199384edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, check_vbat_work.work);
199484edbeeab67c1575067335179513150115da367bArun Murthy
199584edbeeab67c1575067335179513150115da367bArun Murthy	class_for_each_device(power_supply_class, NULL,
199684edbeeab67c1575067335179513150115da367bArun Murthy		&di->usb_chg.psy, ab8500_charger_get_ext_psy_data);
199784edbeeab67c1575067335179513150115da367bArun Murthy
199884edbeeab67c1575067335179513150115da367bArun Murthy	/* First run old_vbat is 0. */
199984edbeeab67c1575067335179513150115da367bArun Murthy	if (di->old_vbat == 0)
200084edbeeab67c1575067335179513150115da367bArun Murthy		di->old_vbat = di->vbat;
200184edbeeab67c1575067335179513150115da367bArun Murthy
200284edbeeab67c1575067335179513150115da367bArun Murthy	if (!((di->old_vbat <= VBAT_TRESH_IP_CUR_RED &&
200384edbeeab67c1575067335179513150115da367bArun Murthy		di->vbat <= VBAT_TRESH_IP_CUR_RED) ||
200484edbeeab67c1575067335179513150115da367bArun Murthy		(di->old_vbat > VBAT_TRESH_IP_CUR_RED &&
200584edbeeab67c1575067335179513150115da367bArun Murthy		di->vbat > VBAT_TRESH_IP_CUR_RED))) {
200684edbeeab67c1575067335179513150115da367bArun Murthy
200784edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "Vbat did cross threshold, curr: %d, new: %d,"
2008f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			" old: %d\n", di->max_usb_in_curr.usb_type_max,
2009f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			di->vbat, di->old_vbat);
2010f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		ab8500_charger_set_vbus_in_curr(di,
2011f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones					di->max_usb_in_curr.usb_type_max);
201284edbeeab67c1575067335179513150115da367bArun Murthy		power_supply_changed(&di->usb_chg.psy);
201384edbeeab67c1575067335179513150115da367bArun Murthy	}
201484edbeeab67c1575067335179513150115da367bArun Murthy
201584edbeeab67c1575067335179513150115da367bArun Murthy	di->old_vbat = di->vbat;
201684edbeeab67c1575067335179513150115da367bArun Murthy
201784edbeeab67c1575067335179513150115da367bArun Murthy	/*
201884edbeeab67c1575067335179513150115da367bArun Murthy	 * No need to check the battery voltage every second when not close to
201984edbeeab67c1575067335179513150115da367bArun Murthy	 * the threshold.
202084edbeeab67c1575067335179513150115da367bArun Murthy	 */
202184edbeeab67c1575067335179513150115da367bArun Murthy	if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) &&
202284edbeeab67c1575067335179513150115da367bArun Murthy		(di->vbat > (VBAT_TRESH_IP_CUR_RED - 100)))
202384edbeeab67c1575067335179513150115da367bArun Murthy			t = 1;
202484edbeeab67c1575067335179513150115da367bArun Murthy
202584edbeeab67c1575067335179513150115da367bArun Murthy	queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ);
202684edbeeab67c1575067335179513150115da367bArun Murthy}
202784edbeeab67c1575067335179513150115da367bArun Murthy
202884edbeeab67c1575067335179513150115da367bArun Murthy/**
202984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_hw_failure_work() - check main charger failure
203084edbeeab67c1575067335179513150115da367bArun Murthy * @work:	pointer to the work_struct structure
203184edbeeab67c1575067335179513150115da367bArun Murthy *
203284edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the main charger status
203384edbeeab67c1575067335179513150115da367bArun Murthy */
203484edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_hw_failure_work(struct work_struct *work)
203584edbeeab67c1575067335179513150115da367bArun Murthy{
203684edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
203784edbeeab67c1575067335179513150115da367bArun Murthy	u8 reg_value;
203884edbeeab67c1575067335179513150115da367bArun Murthy
203984edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
204084edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, check_hw_failure_work.work);
204184edbeeab67c1575067335179513150115da367bArun Murthy
204284edbeeab67c1575067335179513150115da367bArun Murthy	/* Check if the status bits for HW failure is still active */
204384edbeeab67c1575067335179513150115da367bArun Murthy	if (di->flags.mainextchnotok) {
204484edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_get_register_interruptible(di->dev,
204584edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
204684edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0) {
204784edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
204884edbeeab67c1575067335179513150115da367bArun Murthy			return;
204984edbeeab67c1575067335179513150115da367bArun Murthy		}
205084edbeeab67c1575067335179513150115da367bArun Murthy		if (!(reg_value & MAIN_CH_NOK)) {
205184edbeeab67c1575067335179513150115da367bArun Murthy			di->flags.mainextchnotok = false;
205284edbeeab67c1575067335179513150115da367bArun Murthy			ab8500_power_supply_changed(di, &di->ac_chg.psy);
205384edbeeab67c1575067335179513150115da367bArun Murthy		}
205484edbeeab67c1575067335179513150115da367bArun Murthy	}
205584edbeeab67c1575067335179513150115da367bArun Murthy	if (di->flags.vbus_ovv) {
205684edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_get_register_interruptible(di->dev,
205784edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG,
205884edbeeab67c1575067335179513150115da367bArun Murthy			&reg_value);
205984edbeeab67c1575067335179513150115da367bArun Murthy		if (ret < 0) {
206084edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "%s ab8500 read failed\n", __func__);
206184edbeeab67c1575067335179513150115da367bArun Murthy			return;
206284edbeeab67c1575067335179513150115da367bArun Murthy		}
206384edbeeab67c1575067335179513150115da367bArun Murthy		if (!(reg_value & VBUS_OVV_TH)) {
206484edbeeab67c1575067335179513150115da367bArun Murthy			di->flags.vbus_ovv = false;
206584edbeeab67c1575067335179513150115da367bArun Murthy			ab8500_power_supply_changed(di, &di->usb_chg.psy);
206684edbeeab67c1575067335179513150115da367bArun Murthy		}
206784edbeeab67c1575067335179513150115da367bArun Murthy	}
206884edbeeab67c1575067335179513150115da367bArun Murthy	/* If we still have a failure, schedule a new check */
206984edbeeab67c1575067335179513150115da367bArun Murthy	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
207084edbeeab67c1575067335179513150115da367bArun Murthy		queue_delayed_work(di->charger_wq,
207184edbeeab67c1575067335179513150115da367bArun Murthy			&di->check_hw_failure_work, round_jiffies(HZ));
207284edbeeab67c1575067335179513150115da367bArun Murthy	}
207384edbeeab67c1575067335179513150115da367bArun Murthy}
207484edbeeab67c1575067335179513150115da367bArun Murthy
207584edbeeab67c1575067335179513150115da367bArun Murthy/**
207684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_kick_watchdog_work() - kick the watchdog
207784edbeeab67c1575067335179513150115da367bArun Murthy * @work:	pointer to the work_struct structure
207884edbeeab67c1575067335179513150115da367bArun Murthy *
207984edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for kicking the charger watchdog.
208084edbeeab67c1575067335179513150115da367bArun Murthy *
208184edbeeab67c1575067335179513150115da367bArun Murthy * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
208284edbeeab67c1575067335179513150115da367bArun Murthy * logic. That means we have to continously kick the charger
208384edbeeab67c1575067335179513150115da367bArun Murthy * watchdog even when no charger is connected. This is only
208484edbeeab67c1575067335179513150115da367bArun Murthy * valid once the AC charger has been enabled. This is
208584edbeeab67c1575067335179513150115da367bArun Murthy * a bug that is not handled by the algorithm and the
208684edbeeab67c1575067335179513150115da367bArun Murthy * watchdog have to be kicked by the charger driver
208784edbeeab67c1575067335179513150115da367bArun Murthy * when the AC charger is disabled
208884edbeeab67c1575067335179513150115da367bArun Murthy */
208984edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_kick_watchdog_work(struct work_struct *work)
209084edbeeab67c1575067335179513150115da367bArun Murthy{
209184edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
209284edbeeab67c1575067335179513150115da367bArun Murthy
209384edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
209484edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, kick_wd_work.work);
209584edbeeab67c1575067335179513150115da367bArun Murthy
209684edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
209784edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
209884edbeeab67c1575067335179513150115da367bArun Murthy	if (ret)
209984edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "Failed to kick WD!\n");
210084edbeeab67c1575067335179513150115da367bArun Murthy
210184edbeeab67c1575067335179513150115da367bArun Murthy	/* Schedule a new watchdog kick */
210284edbeeab67c1575067335179513150115da367bArun Murthy	queue_delayed_work(di->charger_wq,
210384edbeeab67c1575067335179513150115da367bArun Murthy		&di->kick_wd_work, round_jiffies(WD_KICK_INTERVAL));
210484edbeeab67c1575067335179513150115da367bArun Murthy}
210584edbeeab67c1575067335179513150115da367bArun Murthy
210684edbeeab67c1575067335179513150115da367bArun Murthy/**
210784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_work() - work to get and set main charger status
210884edbeeab67c1575067335179513150115da367bArun Murthy * @work:	pointer to the work_struct structure
210984edbeeab67c1575067335179513150115da367bArun Murthy *
211084edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the main charger status
211184edbeeab67c1575067335179513150115da367bArun Murthy */
211284edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_ac_work(struct work_struct *work)
211384edbeeab67c1575067335179513150115da367bArun Murthy{
211484edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
211584edbeeab67c1575067335179513150115da367bArun Murthy
211684edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
211784edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, ac_work);
211884edbeeab67c1575067335179513150115da367bArun Murthy
211984edbeeab67c1575067335179513150115da367bArun Murthy	/*
212084edbeeab67c1575067335179513150115da367bArun Murthy	 * Since we can't be sure that the events are received
212184edbeeab67c1575067335179513150115da367bArun Murthy	 * synchronously, we have the check if the main charger is
212284edbeeab67c1575067335179513150115da367bArun Murthy	 * connected by reading the status register
212384edbeeab67c1575067335179513150115da367bArun Murthy	 */
212434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	ret = ab8500_charger_detect_chargers(di, false);
212584edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0)
212684edbeeab67c1575067335179513150115da367bArun Murthy		return;
212784edbeeab67c1575067335179513150115da367bArun Murthy
212884edbeeab67c1575067335179513150115da367bArun Murthy	if (ret & AC_PW_CONN) {
212984edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.charger_connected = 1;
213084edbeeab67c1575067335179513150115da367bArun Murthy		di->ac_conn = true;
213184edbeeab67c1575067335179513150115da367bArun Murthy	} else {
213284edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.charger_connected = 0;
213384edbeeab67c1575067335179513150115da367bArun Murthy	}
213484edbeeab67c1575067335179513150115da367bArun Murthy
213584edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_power_supply_changed(di, &di->ac_chg.psy);
213684edbeeab67c1575067335179513150115da367bArun Murthy	sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present");
213784edbeeab67c1575067335179513150115da367bArun Murthy}
213884edbeeab67c1575067335179513150115da367bArun Murthy
2139b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesstatic void ab8500_charger_usb_attached_work(struct work_struct *work)
2140b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones{
2141b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	struct ab8500_charger *di = container_of(work,
2142b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones						 struct ab8500_charger,
2143b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones						 usb_charger_attached_work.work);
2144b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC);
2145b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	int ret, i;
2146b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	u8 statval;
2147b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2148b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	for (i = 0; i < 10; i++) {
2149b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		ret = abx500_get_register_interruptible(di->dev,
2150b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones							AB8500_CHARGER,
2151b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones							AB8500_CH_USBCH_STAT1_REG,
2152b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones							&statval);
2153b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		if (ret < 0) {
2154b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
2155b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			goto reschedule;
2156b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		}
2157b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		if ((statval & usbch) != usbch)
2158b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			goto reschedule;
2159b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2160b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		msleep(CHARGER_STATUS_POLL);
2161b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	}
2162b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2163b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0);
2164b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2165b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_lock(&di->charger_attached_mutex);
2166b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_unlock(&di->charger_attached_mutex);
2167b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2168b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	return;
2169b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2170b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesreschedule:
2171b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	queue_delayed_work(di->charger_wq,
2172b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			   &di->usb_charger_attached_work,
2173b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			   HZ);
2174b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones}
2175b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2176b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesstatic void ab8500_charger_ac_attached_work(struct work_struct *work)
2177b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones{
2178b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2179b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	struct ab8500_charger *di = container_of(work,
2180b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones						 struct ab8500_charger,
2181b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones						 ac_charger_attached_work.work);
2182b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	int mainch = (MAIN_CH_STATUS2_MAINCHGDROP |
2183b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		      MAIN_CH_STATUS2_MAINCHARGERDETDBNC);
2184b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	int ret, i;
2185b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	u8 statval;
2186b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2187b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	for (i = 0; i < 10; i++) {
2188b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		ret = abx500_get_register_interruptible(di->dev,
2189b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones							AB8500_CHARGER,
2190b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones							AB8500_CH_STATUS2_REG,
2191b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones							&statval);
2192b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		if (ret < 0) {
2193b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			dev_err(di->dev, "ab8500 read failed %d\n", __LINE__);
2194b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			goto reschedule;
2195b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		}
2196b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2197b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		if ((statval & mainch) != mainch)
2198b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			goto reschedule;
2199b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2200b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones		msleep(CHARGER_STATUS_POLL);
2201b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	}
2202b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2203b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0);
2204b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	queue_work(di->charger_wq, &di->ac_work);
2205b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2206b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_lock(&di->charger_attached_mutex);
2207b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_unlock(&di->charger_attached_mutex);
2208b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2209b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	return;
2210b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
2211b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jonesreschedule:
2212b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	queue_delayed_work(di->charger_wq,
2213b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			   &di->ac_charger_attached_work,
2214b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			   HZ);
2215b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones}
2216b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
221784edbeeab67c1575067335179513150115da367bArun Murthy/**
221884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_detect_usb_type_work() - work to detect USB type
221984edbeeab67c1575067335179513150115da367bArun Murthy * @work:	Pointer to the work_struct structure
222084edbeeab67c1575067335179513150115da367bArun Murthy *
222184edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of USB plugged
222284edbeeab67c1575067335179513150115da367bArun Murthy */
222364eb9b02bfbbc2a53b6092cc12c1f42cc3261dbcAnton Vorontsovstatic void ab8500_charger_detect_usb_type_work(struct work_struct *work)
222484edbeeab67c1575067335179513150115da367bArun Murthy{
222584edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
222684edbeeab67c1575067335179513150115da367bArun Murthy
222784edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
222884edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, detect_usb_type_work);
222984edbeeab67c1575067335179513150115da367bArun Murthy
223084edbeeab67c1575067335179513150115da367bArun Murthy	/*
223184edbeeab67c1575067335179513150115da367bArun Murthy	 * Since we can't be sure that the events are received
223284edbeeab67c1575067335179513150115da367bArun Murthy	 * synchronously, we have the check if is
223384edbeeab67c1575067335179513150115da367bArun Murthy	 * connected by reading the status register
223484edbeeab67c1575067335179513150115da367bArun Murthy	 */
223534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	ret = ab8500_charger_detect_chargers(di, false);
223684edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0)
223784edbeeab67c1575067335179513150115da367bArun Murthy		return;
223884edbeeab67c1575067335179513150115da367bArun Murthy
223984edbeeab67c1575067335179513150115da367bArun Murthy	if (!(ret & USB_PW_CONN)) {
224034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__);
224134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->vbus_detected = false;
224284edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_set_usb_connected(di, false);
224384edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_power_supply_changed(di, &di->usb_chg.psy);
224484edbeeab67c1575067335179513150115da367bArun Murthy	} else {
224534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__);
224634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->vbus_detected = true;
224784edbeeab67c1575067335179513150115da367bArun Murthy
224884edbeeab67c1575067335179513150115da367bArun Murthy		if (is_ab8500_1p1_or_earlier(di->parent)) {
224984edbeeab67c1575067335179513150115da367bArun Murthy			ret = ab8500_charger_detect_usb_type(di);
225084edbeeab67c1575067335179513150115da367bArun Murthy			if (!ret) {
225184edbeeab67c1575067335179513150115da367bArun Murthy				ab8500_charger_set_usb_connected(di, true);
225284edbeeab67c1575067335179513150115da367bArun Murthy				ab8500_power_supply_changed(di,
225384edbeeab67c1575067335179513150115da367bArun Murthy							    &di->usb_chg.psy);
225484edbeeab67c1575067335179513150115da367bArun Murthy			}
225584edbeeab67c1575067335179513150115da367bArun Murthy		} else {
225634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			/*
225734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			 * For ABB cut2.0 and onwards we have an IRQ,
225884edbeeab67c1575067335179513150115da367bArun Murthy			 * USB_LINK_STATUS that will be triggered when the USB
225984edbeeab67c1575067335179513150115da367bArun Murthy			 * link status changes. The exception is USB connected
226084edbeeab67c1575067335179513150115da367bArun Murthy			 * during startup. Then we don't get a
226184edbeeab67c1575067335179513150115da367bArun Murthy			 * USB_LINK_STATUS IRQ
226284edbeeab67c1575067335179513150115da367bArun Murthy			 */
226384edbeeab67c1575067335179513150115da367bArun Murthy			if (di->vbus_detected_start) {
226484edbeeab67c1575067335179513150115da367bArun Murthy				di->vbus_detected_start = false;
226584edbeeab67c1575067335179513150115da367bArun Murthy				ret = ab8500_charger_detect_usb_type(di);
226684edbeeab67c1575067335179513150115da367bArun Murthy				if (!ret) {
226784edbeeab67c1575067335179513150115da367bArun Murthy					ab8500_charger_set_usb_connected(di,
226884edbeeab67c1575067335179513150115da367bArun Murthy						true);
226984edbeeab67c1575067335179513150115da367bArun Murthy					ab8500_power_supply_changed(di,
227084edbeeab67c1575067335179513150115da367bArun Murthy						&di->usb_chg.psy);
227184edbeeab67c1575067335179513150115da367bArun Murthy				}
227284edbeeab67c1575067335179513150115da367bArun Murthy			}
227384edbeeab67c1575067335179513150115da367bArun Murthy		}
227484edbeeab67c1575067335179513150115da367bArun Murthy	}
227584edbeeab67c1575067335179513150115da367bArun Murthy}
227684edbeeab67c1575067335179513150115da367bArun Murthy
227784edbeeab67c1575067335179513150115da367bArun Murthy/**
227834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * ab8500_charger_usb_link_attach_work() - work to detect USB type
22794b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper * @work:	pointer to the work_struct structure
22804b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper *
22814b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper * Detect the type of USB plugged
22824b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper */
22834b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooperstatic void ab8500_charger_usb_link_attach_work(struct work_struct *work)
22844b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper{
22854b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	struct ab8500_charger *di =
22864b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper		container_of(work, struct ab8500_charger, attach_work.work);
22874b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	int ret;
22884b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper
22894b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	/* Update maximum input current if USB enumeration is not detected */
22904b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	if (!di->usb.charger_online) {
2291f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		ret = ab8500_charger_set_vbus_in_curr(di,
2292f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones					di->max_usb_in_curr.usb_type_max);
22934b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper		if (ret)
22944b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper			return;
22954b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	}
22964b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper
22974b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	ab8500_charger_set_usb_connected(di, true);
22984b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	ab8500_power_supply_changed(di, &di->usb_chg.psy);
22994b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper}
23004b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper
23014b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper/**
230284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_link_status_work() - work to detect USB type
230384edbeeab67c1575067335179513150115da367bArun Murthy * @work:	pointer to the work_struct structure
230484edbeeab67c1575067335179513150115da367bArun Murthy *
230584edbeeab67c1575067335179513150115da367bArun Murthy * Detect the type of USB plugged
230684edbeeab67c1575067335179513150115da367bArun Murthy */
230784edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_usb_link_status_work(struct work_struct *work)
230884edbeeab67c1575067335179513150115da367bArun Murthy{
2309ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	int detected_chargers;
231084edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
2311ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	u8 val;
2312d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg	u8 link_status;
231384edbeeab67c1575067335179513150115da367bArun Murthy
231484edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
231584edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, usb_link_status_work);
231684edbeeab67c1575067335179513150115da367bArun Murthy
231784edbeeab67c1575067335179513150115da367bArun Murthy	/*
231884edbeeab67c1575067335179513150115da367bArun Murthy	 * Since we can't be sure that the events are received
231984edbeeab67c1575067335179513150115da367bArun Murthy	 * synchronously, we have the check if  is
232084edbeeab67c1575067335179513150115da367bArun Murthy	 * connected by reading the status register
232184edbeeab67c1575067335179513150115da367bArun Murthy	 */
232234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	detected_chargers = ab8500_charger_detect_chargers(di, false);
2323ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	if (detected_chargers < 0)
232484edbeeab67c1575067335179513150115da367bArun Murthy		return;
232584edbeeab67c1575067335179513150115da367bArun Murthy
2326ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	/*
2327ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	 * Some chargers that breaks the USB spec is
2328ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	 * identified as invalid by AB8500 and it refuse
2329ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	 * to start the charging process. but by jumping
2330ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	 * thru a few hoops it can be forced to start.
2331ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	 */
233288efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper	if (is_ab8500(di->parent))
233388efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
233488efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper					AB8500_USB_LINE_STAT_REG, &val);
233588efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper	else
233688efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper		ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
233788efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper					AB8500_USB_LINK1_STAT_REG, &val);
233888efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper
2339ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	if (ret >= 0)
2340ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver		dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val);
2341ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	else
2342ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver		dev_dbg(di->dev, "Error reading USB link status\n");
2343ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver
2344861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (is_ab8500(di->parent))
2345d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg		link_status = AB8500_USB_LINK_STATUS;
2346861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	else
2347861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		link_status = AB8505_USB_LINK_STATUS;
2348d4337660d06945c9772182b5b8e72443ae3e475dHakan Berg
2349ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	if (detected_chargers & USB_PW_CONN) {
2350861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		if (((val & link_status) >> USB_LINK_STATUS_SHIFT) ==
2351861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				USB_STAT_NOT_VALID_LINK &&
2352ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver				di->invalid_charger_detect_state == 0) {
2353861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			dev_dbg(di->dev,
2354861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones					"Invalid charger detected, state= 0\n");
2355ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			/*Enable charger*/
2356ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			abx500_mask_and_set_register_interruptible(di->dev,
2357861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones					AB8500_CHARGER, AB8500_USBCH_CTRL1_REG,
2358861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones					USB_CH_ENA, USB_CH_ENA);
2359ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			/*Enable charger detection*/
2360b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper			abx500_mask_and_set_register_interruptible(di->dev,
2361b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
2362b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper					USB_CH_DET, USB_CH_DET);
2363ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			di->invalid_charger_detect_state = 1;
2364ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			/*exit and wait for new link status interrupt.*/
2365ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			return;
2366ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver
2367ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver		}
2368ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver		if (di->invalid_charger_detect_state == 1) {
2369861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			dev_dbg(di->dev,
2370861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones					"Invalid charger detected, state= 1\n");
2371ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			/*Stop charger detection*/
2372b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper			abx500_mask_and_set_register_interruptible(di->dev,
2373b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper					AB8500_USB, AB8500_USB_LINE_CTRL2_REG,
2374b3ea5f451e4e435b650e34142f8552002dc21297Marcus Cooper					USB_CH_DET, 0x00);
2375ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			/*Check link status*/
237688efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper			if (is_ab8500(di->parent))
237788efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper				ret = abx500_get_register_interruptible(di->dev,
237888efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper					AB8500_USB, AB8500_USB_LINE_STAT_REG,
237988efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper					&val);
238088efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper			else
238188efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper				ret = abx500_get_register_interruptible(di->dev,
238288efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper					AB8500_USB, AB8500_USB_LINK1_STAT_REG,
238388efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper					&val);
238488efdb8022f13c198fe4459e6e278f9b559cff3bMarcus Cooper
2385ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			dev_dbg(di->dev, "USB link status= 0x%02x\n",
2386861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				(val & link_status) >> USB_LINK_STATUS_SHIFT);
2387ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver			di->invalid_charger_detect_state = 2;
2388ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver		}
2389ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	} else {
2390ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver		di->invalid_charger_detect_state = 0;
2391ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	}
2392ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver
2393ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	if (!(detected_chargers & USB_PW_CONN)) {
239434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->vbus_detected = false;
239584edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_set_usb_connected(di, false);
239684edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_power_supply_changed(di, &di->usb_chg.psy);
23974b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper		return;
23984b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	}
239984edbeeab67c1575067335179513150115da367bArun Murthy
240034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	dev_dbg(di->dev,"%s di->vbus_detected = true\n",__func__);
240134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->vbus_detected = true;
24024b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	ret = ab8500_charger_read_usb_type(di);
240334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (ret) {
240434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		if (ret == -ENXIO) {
240534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			/* No valid charger type detected */
240634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			ab8500_charger_set_usb_connected(di, false);
240734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			ab8500_power_supply_changed(di, &di->usb_chg.psy);
240884edbeeab67c1575067335179513150115da367bArun Murthy		}
240934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		return;
241034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	}
241134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
241234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (di->usb_device_is_unrecognised) {
241334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev,
241434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			"Potential Legacy Charger device. "
241534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			"Delay work for %d msec for USB enum "
241634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			"to finish",
241734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			WAIT_ACA_RID_ENUMERATION);
241834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		queue_delayed_work(di->charger_wq,
241934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				   &di->attach_work,
242034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				   msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION));
242134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	} else if (di->is_aca_rid == 1) {
242234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		/* Only wait once */
242334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		di->is_aca_rid++;
242434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev,
242534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			"%s Wait %d msec for USB enum to finish",
242634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			__func__, WAIT_ACA_RID_ENUMERATION);
242734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		queue_delayed_work(di->charger_wq,
242834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				   &di->attach_work,
242934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				   msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION));
243034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	} else {
243134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		queue_delayed_work(di->charger_wq,
243234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				   &di->attach_work,
243334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				   0);
243484edbeeab67c1575067335179513150115da367bArun Murthy	}
243584edbeeab67c1575067335179513150115da367bArun Murthy}
243684edbeeab67c1575067335179513150115da367bArun Murthy
243784edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_usb_state_changed_work(struct work_struct *work)
243884edbeeab67c1575067335179513150115da367bArun Murthy{
243984edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
244084edbeeab67c1575067335179513150115da367bArun Murthy	unsigned long flags;
244184edbeeab67c1575067335179513150115da367bArun Murthy
244284edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
244334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		struct ab8500_charger, usb_state_changed_work.work);
244484edbeeab67c1575067335179513150115da367bArun Murthy
244534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (!di->vbus_detected)	{
244634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_dbg(di->dev,
244734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			"%s !di->vbus_detected\n",
244834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson			__func__);
244984edbeeab67c1575067335179513150115da367bArun Murthy		return;
245034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	}
245184edbeeab67c1575067335179513150115da367bArun Murthy
245284edbeeab67c1575067335179513150115da367bArun Murthy	spin_lock_irqsave(&di->usb_state.usb_lock, flags);
245334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->usb_state.state = di->usb_state.state_tmp;
245434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->usb_state.usb_current = di->usb_state.usb_current_tmp;
245584edbeeab67c1575067335179513150115da367bArun Murthy	spin_unlock_irqrestore(&di->usb_state.usb_lock, flags);
245684edbeeab67c1575067335179513150115da367bArun Murthy
245784edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n",
245884edbeeab67c1575067335179513150115da367bArun Murthy		__func__, di->usb_state.state, di->usb_state.usb_current);
245984edbeeab67c1575067335179513150115da367bArun Murthy
246084edbeeab67c1575067335179513150115da367bArun Murthy	switch (di->usb_state.state) {
246184edbeeab67c1575067335179513150115da367bArun Murthy	case AB8500_BM_USB_STATE_RESET_HS:
246284edbeeab67c1575067335179513150115da367bArun Murthy	case AB8500_BM_USB_STATE_RESET_FS:
246384edbeeab67c1575067335179513150115da367bArun Murthy	case AB8500_BM_USB_STATE_SUSPEND:
246484edbeeab67c1575067335179513150115da367bArun Murthy	case AB8500_BM_USB_STATE_MAX:
246584edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_set_usb_connected(di, false);
246684edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_power_supply_changed(di, &di->usb_chg.psy);
246784edbeeab67c1575067335179513150115da367bArun Murthy		break;
246884edbeeab67c1575067335179513150115da367bArun Murthy
246984edbeeab67c1575067335179513150115da367bArun Murthy	case AB8500_BM_USB_STATE_RESUME:
247084edbeeab67c1575067335179513150115da367bArun Murthy		/*
247184edbeeab67c1575067335179513150115da367bArun Murthy		 * when suspend->resume there should be delay
247284edbeeab67c1575067335179513150115da367bArun Murthy		 * of 1sec for enabling charging
247384edbeeab67c1575067335179513150115da367bArun Murthy		 */
247484edbeeab67c1575067335179513150115da367bArun Murthy		msleep(1000);
247584edbeeab67c1575067335179513150115da367bArun Murthy		/* Intentional fall through */
247684edbeeab67c1575067335179513150115da367bArun Murthy	case AB8500_BM_USB_STATE_CONFIGURED:
247784edbeeab67c1575067335179513150115da367bArun Murthy		/*
247884edbeeab67c1575067335179513150115da367bArun Murthy		 * USB is configured, enable charging with the charging
247984edbeeab67c1575067335179513150115da367bArun Murthy		 * input current obtained from USB driver
248084edbeeab67c1575067335179513150115da367bArun Murthy		 */
248184edbeeab67c1575067335179513150115da367bArun Murthy		if (!ab8500_charger_get_usb_cur(di)) {
248284edbeeab67c1575067335179513150115da367bArun Murthy			/* Update maximum input current */
248384edbeeab67c1575067335179513150115da367bArun Murthy			ret = ab8500_charger_set_vbus_in_curr(di,
2484f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones					di->max_usb_in_curr.usb_type_max);
248584edbeeab67c1575067335179513150115da367bArun Murthy			if (ret)
248684edbeeab67c1575067335179513150115da367bArun Murthy				return;
248784edbeeab67c1575067335179513150115da367bArun Murthy
248884edbeeab67c1575067335179513150115da367bArun Murthy			ab8500_charger_set_usb_connected(di, true);
248984edbeeab67c1575067335179513150115da367bArun Murthy			ab8500_power_supply_changed(di, &di->usb_chg.psy);
249084edbeeab67c1575067335179513150115da367bArun Murthy		}
249184edbeeab67c1575067335179513150115da367bArun Murthy		break;
249284edbeeab67c1575067335179513150115da367bArun Murthy
249384edbeeab67c1575067335179513150115da367bArun Murthy	default:
249484edbeeab67c1575067335179513150115da367bArun Murthy		break;
249584edbeeab67c1575067335179513150115da367bArun Murthy	};
249684edbeeab67c1575067335179513150115da367bArun Murthy}
249784edbeeab67c1575067335179513150115da367bArun Murthy
249884edbeeab67c1575067335179513150115da367bArun Murthy/**
249984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_usbchargernotok_work() - check USB chg not ok status
250084edbeeab67c1575067335179513150115da367bArun Murthy * @work:	pointer to the work_struct structure
250184edbeeab67c1575067335179513150115da367bArun Murthy *
250284edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the USB charger Not OK status
250384edbeeab67c1575067335179513150115da367bArun Murthy */
250484edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_usbchargernotok_work(struct work_struct *work)
250584edbeeab67c1575067335179513150115da367bArun Murthy{
250684edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
250784edbeeab67c1575067335179513150115da367bArun Murthy	u8 reg_value;
250884edbeeab67c1575067335179513150115da367bArun Murthy	bool prev_status;
250984edbeeab67c1575067335179513150115da367bArun Murthy
251084edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
251184edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, check_usbchgnotok_work.work);
251284edbeeab67c1575067335179513150115da367bArun Murthy
251384edbeeab67c1575067335179513150115da367bArun Murthy	/* Check if the status bit for usbchargernotok is still active */
251484edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_get_register_interruptible(di->dev,
251584edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
251684edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0) {
251784edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
251884edbeeab67c1575067335179513150115da367bArun Murthy		return;
251984edbeeab67c1575067335179513150115da367bArun Murthy	}
252084edbeeab67c1575067335179513150115da367bArun Murthy	prev_status = di->flags.usbchargernotok;
252184edbeeab67c1575067335179513150115da367bArun Murthy
252284edbeeab67c1575067335179513150115da367bArun Murthy	if (reg_value & VBUS_CH_NOK) {
252384edbeeab67c1575067335179513150115da367bArun Murthy		di->flags.usbchargernotok = true;
252484edbeeab67c1575067335179513150115da367bArun Murthy		/* Check again in 1sec */
252584edbeeab67c1575067335179513150115da367bArun Murthy		queue_delayed_work(di->charger_wq,
252684edbeeab67c1575067335179513150115da367bArun Murthy			&di->check_usbchgnotok_work, HZ);
252784edbeeab67c1575067335179513150115da367bArun Murthy	} else {
252884edbeeab67c1575067335179513150115da367bArun Murthy		di->flags.usbchargernotok = false;
252984edbeeab67c1575067335179513150115da367bArun Murthy		di->flags.vbus_collapse = false;
253084edbeeab67c1575067335179513150115da367bArun Murthy	}
253184edbeeab67c1575067335179513150115da367bArun Murthy
253284edbeeab67c1575067335179513150115da367bArun Murthy	if (prev_status != di->flags.usbchargernotok)
253384edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_power_supply_changed(di, &di->usb_chg.psy);
253484edbeeab67c1575067335179513150115da367bArun Murthy}
253584edbeeab67c1575067335179513150115da367bArun Murthy
253684edbeeab67c1575067335179513150115da367bArun Murthy/**
253784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_main_thermal_prot_work() - check main thermal status
253884edbeeab67c1575067335179513150115da367bArun Murthy * @work:	pointer to the work_struct structure
253984edbeeab67c1575067335179513150115da367bArun Murthy *
254084edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the Main thermal prot status
254184edbeeab67c1575067335179513150115da367bArun Murthy */
254284edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_main_thermal_prot_work(
254384edbeeab67c1575067335179513150115da367bArun Murthy	struct work_struct *work)
254484edbeeab67c1575067335179513150115da367bArun Murthy{
254584edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
254684edbeeab67c1575067335179513150115da367bArun Murthy	u8 reg_value;
254784edbeeab67c1575067335179513150115da367bArun Murthy
254884edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
254984edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, check_main_thermal_prot_work);
255084edbeeab67c1575067335179513150115da367bArun Murthy
255184edbeeab67c1575067335179513150115da367bArun Murthy	/* Check if the status bit for main_thermal_prot is still active */
255284edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_get_register_interruptible(di->dev,
255384edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CHARGER, AB8500_CH_STATUS2_REG, &reg_value);
255484edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0) {
255584edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
255684edbeeab67c1575067335179513150115da367bArun Murthy		return;
255784edbeeab67c1575067335179513150115da367bArun Murthy	}
255884edbeeab67c1575067335179513150115da367bArun Murthy	if (reg_value & MAIN_CH_TH_PROT)
255984edbeeab67c1575067335179513150115da367bArun Murthy		di->flags.main_thermal_prot = true;
256084edbeeab67c1575067335179513150115da367bArun Murthy	else
256184edbeeab67c1575067335179513150115da367bArun Murthy		di->flags.main_thermal_prot = false;
256284edbeeab67c1575067335179513150115da367bArun Murthy
256384edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_power_supply_changed(di, &di->ac_chg.psy);
256484edbeeab67c1575067335179513150115da367bArun Murthy}
256584edbeeab67c1575067335179513150115da367bArun Murthy
256684edbeeab67c1575067335179513150115da367bArun Murthy/**
256784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_check_usb_thermal_prot_work() - check usb thermal status
256884edbeeab67c1575067335179513150115da367bArun Murthy * @work:	pointer to the work_struct structure
256984edbeeab67c1575067335179513150115da367bArun Murthy *
257084edbeeab67c1575067335179513150115da367bArun Murthy * Work queue function for checking the USB thermal prot status
257184edbeeab67c1575067335179513150115da367bArun Murthy */
257284edbeeab67c1575067335179513150115da367bArun Murthystatic void ab8500_charger_check_usb_thermal_prot_work(
257384edbeeab67c1575067335179513150115da367bArun Murthy	struct work_struct *work)
257484edbeeab67c1575067335179513150115da367bArun Murthy{
257584edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
257684edbeeab67c1575067335179513150115da367bArun Murthy	u8 reg_value;
257784edbeeab67c1575067335179513150115da367bArun Murthy
257884edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = container_of(work,
257984edbeeab67c1575067335179513150115da367bArun Murthy		struct ab8500_charger, check_usb_thermal_prot_work);
258084edbeeab67c1575067335179513150115da367bArun Murthy
258184edbeeab67c1575067335179513150115da367bArun Murthy	/* Check if the status bit for usb_thermal_prot is still active */
258284edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_get_register_interruptible(di->dev,
258384edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CHARGER, AB8500_CH_USBCH_STAT2_REG, &reg_value);
258484edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0) {
258584edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s ab8500 read failed\n", __func__);
258684edbeeab67c1575067335179513150115da367bArun Murthy		return;
258784edbeeab67c1575067335179513150115da367bArun Murthy	}
258884edbeeab67c1575067335179513150115da367bArun Murthy	if (reg_value & USB_CH_TH_PROT)
258984edbeeab67c1575067335179513150115da367bArun Murthy		di->flags.usb_thermal_prot = true;
259084edbeeab67c1575067335179513150115da367bArun Murthy	else
259184edbeeab67c1575067335179513150115da367bArun Murthy		di->flags.usb_thermal_prot = false;
259284edbeeab67c1575067335179513150115da367bArun Murthy
259384edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_power_supply_changed(di, &di->usb_chg.psy);
259484edbeeab67c1575067335179513150115da367bArun Murthy}
259584edbeeab67c1575067335179513150115da367bArun Murthy
259684edbeeab67c1575067335179513150115da367bArun Murthy/**
259784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchunplugdet_handler() - main charger unplugged
259884edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
259984edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
260084edbeeab67c1575067335179513150115da367bArun Murthy *
260184edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
260284edbeeab67c1575067335179513150115da367bArun Murthy */
260384edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di)
260484edbeeab67c1575067335179513150115da367bArun Murthy{
260584edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
260684edbeeab67c1575067335179513150115da367bArun Murthy
260784edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "Main charger unplugged\n");
260884edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->ac_work);
260984edbeeab67c1575067335179513150115da367bArun Murthy
2610b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	cancel_delayed_work_sync(&di->ac_charger_attached_work);
2611b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_lock(&di->charger_attached_mutex);
2612b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_unlock(&di->charger_attached_mutex);
2613b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
261484edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
261584edbeeab67c1575067335179513150115da367bArun Murthy}
261684edbeeab67c1575067335179513150115da367bArun Murthy
261784edbeeab67c1575067335179513150115da367bArun Murthy/**
261884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchplugdet_handler() - main charger plugged
261984edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
262084edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
262184edbeeab67c1575067335179513150115da367bArun Murthy *
262284edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
262384edbeeab67c1575067335179513150115da367bArun Murthy */
262484edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di)
262584edbeeab67c1575067335179513150115da367bArun Murthy{
262684edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
262784edbeeab67c1575067335179513150115da367bArun Murthy
262884edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "Main charger plugged\n");
262984edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->ac_work);
263084edbeeab67c1575067335179513150115da367bArun Murthy
2631b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_lock(&di->charger_attached_mutex);
2632b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_unlock(&di->charger_attached_mutex);
2633261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent
2634261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent	if (is_ab8500(di->parent))
2635261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent		queue_delayed_work(di->charger_wq,
2636b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			   &di->ac_charger_attached_work,
2637b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			   HZ);
263884edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
263984edbeeab67c1575067335179513150115da367bArun Murthy}
264084edbeeab67c1575067335179513150115da367bArun Murthy
264184edbeeab67c1575067335179513150115da367bArun Murthy/**
264284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainextchnotok_handler() - main charger not ok
264384edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
264484edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
264584edbeeab67c1575067335179513150115da367bArun Murthy *
264684edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
264784edbeeab67c1575067335179513150115da367bArun Murthy */
264884edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di)
264984edbeeab67c1575067335179513150115da367bArun Murthy{
265084edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
265184edbeeab67c1575067335179513150115da367bArun Murthy
265284edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "Main charger not ok\n");
265384edbeeab67c1575067335179513150115da367bArun Murthy	di->flags.mainextchnotok = true;
265484edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_power_supply_changed(di, &di->ac_chg.psy);
265584edbeeab67c1575067335179513150115da367bArun Murthy
265684edbeeab67c1575067335179513150115da367bArun Murthy	/* Schedule a new HW failure check */
265784edbeeab67c1575067335179513150115da367bArun Murthy	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
265884edbeeab67c1575067335179513150115da367bArun Murthy
265984edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
266084edbeeab67c1575067335179513150115da367bArun Murthy}
266184edbeeab67c1575067335179513150115da367bArun Murthy
266284edbeeab67c1575067335179513150115da367bArun Murthy/**
266384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchthprotr_handler() - Die temp is above main charger
266484edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold
266584edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
266684edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
266784edbeeab67c1575067335179513150115da367bArun Murthy *
266884edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
266984edbeeab67c1575067335179513150115da367bArun Murthy */
267084edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchthprotr_handler(int irq, void *_di)
267184edbeeab67c1575067335179513150115da367bArun Murthy{
267284edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
267384edbeeab67c1575067335179513150115da367bArun Murthy
267484edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev,
267584edbeeab67c1575067335179513150115da367bArun Murthy		"Die temp above Main charger thermal protection threshold\n");
267684edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
267784edbeeab67c1575067335179513150115da367bArun Murthy
267884edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
267984edbeeab67c1575067335179513150115da367bArun Murthy}
268084edbeeab67c1575067335179513150115da367bArun Murthy
268184edbeeab67c1575067335179513150115da367bArun Murthy/**
268284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_mainchthprotf_handler() - Die temp is below main charger
268384edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold
268484edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
268584edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
268684edbeeab67c1575067335179513150115da367bArun Murthy *
268784edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
268884edbeeab67c1575067335179513150115da367bArun Murthy */
268984edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di)
269084edbeeab67c1575067335179513150115da367bArun Murthy{
269184edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
269284edbeeab67c1575067335179513150115da367bArun Murthy
269384edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev,
269484edbeeab67c1575067335179513150115da367bArun Murthy		"Die temp ok for Main charger thermal protection threshold\n");
269584edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->check_main_thermal_prot_work);
269684edbeeab67c1575067335179513150115da367bArun Murthy
269784edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
269884edbeeab67c1575067335179513150115da367bArun Murthy}
269984edbeeab67c1575067335179513150115da367bArun Murthy
270034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonstatic void ab8500_charger_vbus_drop_end_work(struct work_struct *work)
270134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson{
270234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	struct ab8500_charger *di = container_of(work,
270334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		struct ab8500_charger, vbus_drop_end_work.work);
2704861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	int ret, curr;
2705f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	u8 reg_value;
270634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
270734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->flags.vbus_drop_end = false;
270834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
270934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	/* Reset the drop counter */
271034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	abx500_set_register_interruptible(di->dev,
271134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson				  AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01);
2712861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones
2713861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (is_ab8540(di->parent))
2714861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
2715861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				AB8540_CH_USBCH_STAT3_REG, &reg_value);
2716861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	else
2717861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
2718861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				AB8500_CH_USBCH_STAT2_REG, &reg_value);
2719f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	if (ret < 0) {
2720861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		dev_err(di->dev, "%s read failed\n", __func__);
2721861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		return;
2722861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	}
2723861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones
2724861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (is_ab8540(di->parent))
2725861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		curr = di->bm->chg_input_curr[
2726861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			reg_value & AB8540_AUTO_VBUS_IN_CURR_MASK];
2727861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	else
2728861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		curr = di->bm->chg_input_curr[
2729f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT];
2730861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones
2731861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (di->max_usb_in_curr.calculated_max != curr) {
2732861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		/* USB source is collapsing */
2733861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		di->max_usb_in_curr.calculated_max = curr;
2734861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		dev_dbg(di->dev,
2735861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			 "VBUS input current limiting to %d mA\n",
2736861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			 di->max_usb_in_curr.calculated_max);
2737861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	} else {
2738861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		/*
2739861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		 * USB source can not give more than this amount.
2740861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		 * Taking more will collapse the source.
2741861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		 */
2742861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		di->max_usb_in_curr.set_max =
2743861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			di->max_usb_in_curr.calculated_max;
2744861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		dev_dbg(di->dev,
2745861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			 "VBUS input current limited to %d mA\n",
2746861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			 di->max_usb_in_curr.set_max);
2747f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	}
274834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
274934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (di->usb.charger_connected)
2750f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones		ab8500_charger_set_vbus_in_curr(di,
2751f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones					di->max_usb_in_curr.usb_type_max);
275234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson}
275334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
275484edbeeab67c1575067335179513150115da367bArun Murthy/**
275584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusdetf_handler() - VBUS falling detected
275684edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
275784edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
275884edbeeab67c1575067335179513150115da367bArun Murthy *
275984edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
276084edbeeab67c1575067335179513150115da367bArun Murthy */
276184edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di)
276284edbeeab67c1575067335179513150115da367bArun Murthy{
276384edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
276484edbeeab67c1575067335179513150115da367bArun Murthy
276534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->vbus_detected = false;
276684edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "VBUS falling detected\n");
276784edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->detect_usb_type_work);
276884edbeeab67c1575067335179513150115da367bArun Murthy
276984edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
277084edbeeab67c1575067335179513150115da367bArun Murthy}
277184edbeeab67c1575067335179513150115da367bArun Murthy
277284edbeeab67c1575067335179513150115da367bArun Murthy/**
277384edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusdetr_handler() - VBUS rising detected
277484edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
277584edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
277684edbeeab67c1575067335179513150115da367bArun Murthy *
277784edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
277884edbeeab67c1575067335179513150115da367bArun Murthy */
277984edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di)
278084edbeeab67c1575067335179513150115da367bArun Murthy{
278184edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
278284edbeeab67c1575067335179513150115da367bArun Murthy
278384edbeeab67c1575067335179513150115da367bArun Murthy	di->vbus_detected = true;
278484edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "VBUS rising detected\n");
278534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
278684edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->detect_usb_type_work);
278784edbeeab67c1575067335179513150115da367bArun Murthy
278884edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
278984edbeeab67c1575067335179513150115da367bArun Murthy}
279084edbeeab67c1575067335179513150115da367bArun Murthy
279184edbeeab67c1575067335179513150115da367bArun Murthy/**
279284edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usblinkstatus_handler() - USB link status has changed
279384edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
279484edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
279584edbeeab67c1575067335179513150115da367bArun Murthy *
279684edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
279784edbeeab67c1575067335179513150115da367bArun Murthy */
279884edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usblinkstatus_handler(int irq, void *_di)
279984edbeeab67c1575067335179513150115da367bArun Murthy{
280084edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
280184edbeeab67c1575067335179513150115da367bArun Murthy
280284edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "USB link status changed\n");
280384edbeeab67c1575067335179513150115da367bArun Murthy
280484edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->usb_link_status_work);
280584edbeeab67c1575067335179513150115da367bArun Murthy
280684edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
280784edbeeab67c1575067335179513150115da367bArun Murthy}
280884edbeeab67c1575067335179513150115da367bArun Murthy
280984edbeeab67c1575067335179513150115da367bArun Murthy/**
281084edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchthprotr_handler() - Die temp is above usb charger
281184edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold
281284edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
281384edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
281484edbeeab67c1575067335179513150115da367bArun Murthy *
281584edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
281684edbeeab67c1575067335179513150115da367bArun Murthy */
281784edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchthprotr_handler(int irq, void *_di)
281884edbeeab67c1575067335179513150115da367bArun Murthy{
281984edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
282084edbeeab67c1575067335179513150115da367bArun Murthy
282184edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev,
282284edbeeab67c1575067335179513150115da367bArun Murthy		"Die temp above USB charger thermal protection threshold\n");
282384edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
282484edbeeab67c1575067335179513150115da367bArun Murthy
282584edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
282684edbeeab67c1575067335179513150115da367bArun Murthy}
282784edbeeab67c1575067335179513150115da367bArun Murthy
282884edbeeab67c1575067335179513150115da367bArun Murthy/**
282984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchthprotf_handler() - Die temp is below usb charger
283084edbeeab67c1575067335179513150115da367bArun Murthy * thermal protection threshold
283184edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
283284edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
283384edbeeab67c1575067335179513150115da367bArun Murthy *
283484edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
283584edbeeab67c1575067335179513150115da367bArun Murthy */
283684edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchthprotf_handler(int irq, void *_di)
283784edbeeab67c1575067335179513150115da367bArun Murthy{
283884edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
283984edbeeab67c1575067335179513150115da367bArun Murthy
284084edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev,
284184edbeeab67c1575067335179513150115da367bArun Murthy		"Die temp ok for USB charger thermal protection threshold\n");
284284edbeeab67c1575067335179513150115da367bArun Murthy	queue_work(di->charger_wq, &di->check_usb_thermal_prot_work);
284384edbeeab67c1575067335179513150115da367bArun Murthy
284484edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
284584edbeeab67c1575067335179513150115da367bArun Murthy}
284684edbeeab67c1575067335179513150115da367bArun Murthy
284784edbeeab67c1575067335179513150115da367bArun Murthy/**
284884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usbchargernotokr_handler() - USB charger not ok detected
284984edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
285084edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
285184edbeeab67c1575067335179513150115da367bArun Murthy *
285284edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
285384edbeeab67c1575067335179513150115da367bArun Murthy */
285484edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_usbchargernotokr_handler(int irq, void *_di)
285584edbeeab67c1575067335179513150115da367bArun Murthy{
285684edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
285784edbeeab67c1575067335179513150115da367bArun Murthy
285884edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "Not allowed USB charger detected\n");
285984edbeeab67c1575067335179513150115da367bArun Murthy	queue_delayed_work(di->charger_wq, &di->check_usbchgnotok_work, 0);
286084edbeeab67c1575067335179513150115da367bArun Murthy
286184edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
286284edbeeab67c1575067335179513150115da367bArun Murthy}
286384edbeeab67c1575067335179513150115da367bArun Murthy
286484edbeeab67c1575067335179513150115da367bArun Murthy/**
286584edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_chwdexp_handler() - Charger watchdog expired
286684edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
286784edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
286884edbeeab67c1575067335179513150115da367bArun Murthy *
286984edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
287084edbeeab67c1575067335179513150115da367bArun Murthy */
287184edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di)
287284edbeeab67c1575067335179513150115da367bArun Murthy{
287384edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
287484edbeeab67c1575067335179513150115da367bArun Murthy
287584edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "Charger watchdog expired\n");
287684edbeeab67c1575067335179513150115da367bArun Murthy
287784edbeeab67c1575067335179513150115da367bArun Murthy	/*
287884edbeeab67c1575067335179513150115da367bArun Murthy	 * The charger that was online when the watchdog expired
287984edbeeab67c1575067335179513150115da367bArun Murthy	 * needs to be restarted for charging to start again
288084edbeeab67c1575067335179513150115da367bArun Murthy	 */
288184edbeeab67c1575067335179513150115da367bArun Murthy	if (di->ac.charger_online) {
288284edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.wd_expired = true;
288384edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_power_supply_changed(di, &di->ac_chg.psy);
288484edbeeab67c1575067335179513150115da367bArun Murthy	}
288584edbeeab67c1575067335179513150115da367bArun Murthy	if (di->usb.charger_online) {
288684edbeeab67c1575067335179513150115da367bArun Murthy		di->usb.wd_expired = true;
288784edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_power_supply_changed(di, &di->usb_chg.psy);
288884edbeeab67c1575067335179513150115da367bArun Murthy	}
288984edbeeab67c1575067335179513150115da367bArun Murthy
289084edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
289184edbeeab67c1575067335179513150115da367bArun Murthy}
289284edbeeab67c1575067335179513150115da367bArun Murthy
289384edbeeab67c1575067335179513150115da367bArun Murthy/**
289434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * ab8500_charger_vbuschdropend_handler() - VBUS drop removed
289534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @irq:       interrupt number
289634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * @_di:       pointer to the ab8500_charger structure
289734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson *
289834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson * Returns IRQ status(IRQ_HANDLED)
289934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson */
290034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakanssonstatic irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di)
290134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson{
290234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	struct ab8500_charger *di = _di;
290334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
290434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	dev_dbg(di->dev, "VBUS charger drop ended\n");
290534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->flags.vbus_drop_end = true;
2906f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones
2907f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	/*
2908f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	 * VBUS might have dropped due to bad connection.
2909f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	 * Schedule a new input limit set to the value SW requests.
2910f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	 */
291134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work,
2912f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones			   round_jiffies(VBUS_IN_CURR_LIM_RETRY_SET_TIME * HZ));
291334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
291434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	return IRQ_HANDLED;
291534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson}
291634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
291734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson/**
291884edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected
291984edbeeab67c1575067335179513150115da367bArun Murthy * @irq:       interrupt number
292084edbeeab67c1575067335179513150115da367bArun Murthy * @_di:       pointer to the ab8500_charger structure
292184edbeeab67c1575067335179513150115da367bArun Murthy *
292284edbeeab67c1575067335179513150115da367bArun Murthy * Returns IRQ status(IRQ_HANDLED)
292384edbeeab67c1575067335179513150115da367bArun Murthy */
292484edbeeab67c1575067335179513150115da367bArun Murthystatic irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di)
292584edbeeab67c1575067335179513150115da367bArun Murthy{
292684edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = _di;
292784edbeeab67c1575067335179513150115da367bArun Murthy
292884edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "VBUS overvoltage detected\n");
292984edbeeab67c1575067335179513150115da367bArun Murthy	di->flags.vbus_ovv = true;
293084edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_power_supply_changed(di, &di->usb_chg.psy);
293184edbeeab67c1575067335179513150115da367bArun Murthy
293284edbeeab67c1575067335179513150115da367bArun Murthy	/* Schedule a new HW failure check */
293384edbeeab67c1575067335179513150115da367bArun Murthy	queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
293484edbeeab67c1575067335179513150115da367bArun Murthy
293584edbeeab67c1575067335179513150115da367bArun Murthy	return IRQ_HANDLED;
293684edbeeab67c1575067335179513150115da367bArun Murthy}
293784edbeeab67c1575067335179513150115da367bArun Murthy
293884edbeeab67c1575067335179513150115da367bArun Murthy/**
293984edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_ac_get_property() - get the ac/mains properties
294084edbeeab67c1575067335179513150115da367bArun Murthy * @psy:       pointer to the power_supply structure
294184edbeeab67c1575067335179513150115da367bArun Murthy * @psp:       pointer to the power_supply_property structure
294284edbeeab67c1575067335179513150115da367bArun Murthy * @val:       pointer to the power_supply_propval union
294384edbeeab67c1575067335179513150115da367bArun Murthy *
294484edbeeab67c1575067335179513150115da367bArun Murthy * This function gets called when an application tries to get the ac/mains
294584edbeeab67c1575067335179513150115da367bArun Murthy * properties by reading the sysfs files.
294684edbeeab67c1575067335179513150115da367bArun Murthy * AC/Mains properties are online, present and voltage.
294784edbeeab67c1575067335179513150115da367bArun Murthy * online:     ac/mains charging is in progress or not
294884edbeeab67c1575067335179513150115da367bArun Murthy * present:    presence of the ac/mains
294984edbeeab67c1575067335179513150115da367bArun Murthy * voltage:    AC/Mains voltage
295084edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success)
295184edbeeab67c1575067335179513150115da367bArun Murthy */
295284edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_ac_get_property(struct power_supply *psy,
295384edbeeab67c1575067335179513150115da367bArun Murthy	enum power_supply_property psp,
295484edbeeab67c1575067335179513150115da367bArun Murthy	union power_supply_propval *val)
295584edbeeab67c1575067335179513150115da367bArun Murthy{
295684edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di;
2957a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg	int ret;
295884edbeeab67c1575067335179513150115da367bArun Murthy
295984edbeeab67c1575067335179513150115da367bArun Murthy	di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy));
296084edbeeab67c1575067335179513150115da367bArun Murthy
296184edbeeab67c1575067335179513150115da367bArun Murthy	switch (psp) {
296284edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_HEALTH:
296384edbeeab67c1575067335179513150115da367bArun Murthy		if (di->flags.mainextchnotok)
296484edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
296584edbeeab67c1575067335179513150115da367bArun Murthy		else if (di->ac.wd_expired || di->usb.wd_expired)
296684edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_DEAD;
296784edbeeab67c1575067335179513150115da367bArun Murthy		else if (di->flags.main_thermal_prot)
296884edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
296984edbeeab67c1575067335179513150115da367bArun Murthy		else
297084edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_GOOD;
297184edbeeab67c1575067335179513150115da367bArun Murthy		break;
297284edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_ONLINE:
297384edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->ac.charger_online;
297484edbeeab67c1575067335179513150115da367bArun Murthy		break;
297584edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_PRESENT:
297684edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->ac.charger_connected;
297784edbeeab67c1575067335179513150115da367bArun Murthy		break;
297884edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
2979a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		ret = ab8500_charger_get_ac_voltage(di);
2980a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		if (ret >= 0)
2981a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg			di->ac.charger_voltage = ret;
2982a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		/* On error, use previous value */
298384edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->ac.charger_voltage * 1000;
298484edbeeab67c1575067335179513150115da367bArun Murthy		break;
298584edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
298684edbeeab67c1575067335179513150115da367bArun Murthy		/*
298784edbeeab67c1575067335179513150115da367bArun Murthy		 * This property is used to indicate when CV mode is entered
298884edbeeab67c1575067335179513150115da367bArun Murthy		 * for the AC charger
298984edbeeab67c1575067335179513150115da367bArun Murthy		 */
299084edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.cv_active = ab8500_charger_ac_cv(di);
299184edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->ac.cv_active;
299284edbeeab67c1575067335179513150115da367bArun Murthy		break;
299384edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_CURRENT_NOW:
2994a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		ret = ab8500_charger_get_ac_current(di);
2995a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		if (ret >= 0)
2996a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg			di->ac.charger_current = ret;
2997a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		val->intval = di->ac.charger_current * 1000;
299884edbeeab67c1575067335179513150115da367bArun Murthy		break;
299984edbeeab67c1575067335179513150115da367bArun Murthy	default:
300084edbeeab67c1575067335179513150115da367bArun Murthy		return -EINVAL;
300184edbeeab67c1575067335179513150115da367bArun Murthy	}
300284edbeeab67c1575067335179513150115da367bArun Murthy	return 0;
300384edbeeab67c1575067335179513150115da367bArun Murthy}
300484edbeeab67c1575067335179513150115da367bArun Murthy
300584edbeeab67c1575067335179513150115da367bArun Murthy/**
300684edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_usb_get_property() - get the usb properties
300784edbeeab67c1575067335179513150115da367bArun Murthy * @psy:        pointer to the power_supply structure
300884edbeeab67c1575067335179513150115da367bArun Murthy * @psp:        pointer to the power_supply_property structure
300984edbeeab67c1575067335179513150115da367bArun Murthy * @val:        pointer to the power_supply_propval union
301084edbeeab67c1575067335179513150115da367bArun Murthy *
301184edbeeab67c1575067335179513150115da367bArun Murthy * This function gets called when an application tries to get the usb
301284edbeeab67c1575067335179513150115da367bArun Murthy * properties by reading the sysfs files.
301384edbeeab67c1575067335179513150115da367bArun Murthy * USB properties are online, present and voltage.
301484edbeeab67c1575067335179513150115da367bArun Murthy * online:     usb charging is in progress or not
301584edbeeab67c1575067335179513150115da367bArun Murthy * present:    presence of the usb
301684edbeeab67c1575067335179513150115da367bArun Murthy * voltage:    vbus voltage
301784edbeeab67c1575067335179513150115da367bArun Murthy * Returns error code in case of failure else 0(on success)
301884edbeeab67c1575067335179513150115da367bArun Murthy */
301984edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_get_property(struct power_supply *psy,
302084edbeeab67c1575067335179513150115da367bArun Murthy	enum power_supply_property psp,
302184edbeeab67c1575067335179513150115da367bArun Murthy	union power_supply_propval *val)
302284edbeeab67c1575067335179513150115da367bArun Murthy{
302384edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di;
3024a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg	int ret;
302584edbeeab67c1575067335179513150115da367bArun Murthy
302684edbeeab67c1575067335179513150115da367bArun Murthy	di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy));
302784edbeeab67c1575067335179513150115da367bArun Murthy
302884edbeeab67c1575067335179513150115da367bArun Murthy	switch (psp) {
302984edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_HEALTH:
303084edbeeab67c1575067335179513150115da367bArun Murthy		if (di->flags.usbchargernotok)
303184edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
303284edbeeab67c1575067335179513150115da367bArun Murthy		else if (di->ac.wd_expired || di->usb.wd_expired)
303384edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_DEAD;
303484edbeeab67c1575067335179513150115da367bArun Murthy		else if (di->flags.usb_thermal_prot)
303584edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
303684edbeeab67c1575067335179513150115da367bArun Murthy		else if (di->flags.vbus_ovv)
303784edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
303884edbeeab67c1575067335179513150115da367bArun Murthy		else
303984edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = POWER_SUPPLY_HEALTH_GOOD;
304084edbeeab67c1575067335179513150115da367bArun Murthy		break;
304184edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_ONLINE:
304284edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->usb.charger_online;
304384edbeeab67c1575067335179513150115da367bArun Murthy		break;
304484edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_PRESENT:
304584edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->usb.charger_connected;
304684edbeeab67c1575067335179513150115da367bArun Murthy		break;
304784edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
3048a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		ret = ab8500_charger_get_vbus_voltage(di);
3049a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		if (ret >= 0)
3050a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg			di->usb.charger_voltage = ret;
305184edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->usb.charger_voltage * 1000;
305284edbeeab67c1575067335179513150115da367bArun Murthy		break;
305384edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
305484edbeeab67c1575067335179513150115da367bArun Murthy		/*
305584edbeeab67c1575067335179513150115da367bArun Murthy		 * This property is used to indicate when CV mode is entered
305684edbeeab67c1575067335179513150115da367bArun Murthy		 * for the USB charger
305784edbeeab67c1575067335179513150115da367bArun Murthy		 */
305884edbeeab67c1575067335179513150115da367bArun Murthy		di->usb.cv_active = ab8500_charger_usb_cv(di);
305984edbeeab67c1575067335179513150115da367bArun Murthy		val->intval = di->usb.cv_active;
306084edbeeab67c1575067335179513150115da367bArun Murthy		break;
306184edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_CURRENT_NOW:
3062a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		ret = ab8500_charger_get_usb_current(di);
3063a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		if (ret >= 0)
3064a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg			di->usb.charger_current = ret;
3065a864c5a869dcdb40617fc15166385e0ffa609592Jonas Aaberg		val->intval = di->usb.charger_current * 1000;
306684edbeeab67c1575067335179513150115da367bArun Murthy		break;
306784edbeeab67c1575067335179513150115da367bArun Murthy	case POWER_SUPPLY_PROP_CURRENT_AVG:
306884edbeeab67c1575067335179513150115da367bArun Murthy		/*
306984edbeeab67c1575067335179513150115da367bArun Murthy		 * This property is used to indicate when VBUS has collapsed
307084edbeeab67c1575067335179513150115da367bArun Murthy		 * due to too high output current from the USB charger
307184edbeeab67c1575067335179513150115da367bArun Murthy		 */
307284edbeeab67c1575067335179513150115da367bArun Murthy		if (di->flags.vbus_collapse)
307384edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = 1;
307484edbeeab67c1575067335179513150115da367bArun Murthy		else
307584edbeeab67c1575067335179513150115da367bArun Murthy			val->intval = 0;
307684edbeeab67c1575067335179513150115da367bArun Murthy		break;
307784edbeeab67c1575067335179513150115da367bArun Murthy	default:
307884edbeeab67c1575067335179513150115da367bArun Murthy		return -EINVAL;
307984edbeeab67c1575067335179513150115da367bArun Murthy	}
308084edbeeab67c1575067335179513150115da367bArun Murthy	return 0;
308184edbeeab67c1575067335179513150115da367bArun Murthy}
308284edbeeab67c1575067335179513150115da367bArun Murthy
308384edbeeab67c1575067335179513150115da367bArun Murthy/**
308484edbeeab67c1575067335179513150115da367bArun Murthy * ab8500_charger_init_hw_registers() - Set up charger related registers
308584edbeeab67c1575067335179513150115da367bArun Murthy * @di:		pointer to the ab8500_charger structure
308684edbeeab67c1575067335179513150115da367bArun Murthy *
308784edbeeab67c1575067335179513150115da367bArun Murthy * Set up charger OVV, watchdog and maximum voltage registers as well as
308884edbeeab67c1575067335179513150115da367bArun Murthy * charging of the backup battery
308984edbeeab67c1575067335179513150115da367bArun Murthy */
309084edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
309184edbeeab67c1575067335179513150115da367bArun Murthy{
309284edbeeab67c1575067335179513150115da367bArun Murthy	int ret = 0;
30930f4aa401853e07885707aedfc68c608051b0d6e4Yang QU	u8 bup_vch_range = 0, vbup33_vrtcn = 0;
309484edbeeab67c1575067335179513150115da367bArun Murthy
309584edbeeab67c1575067335179513150115da367bArun Murthy	/* Setup maximum charger current and voltage for ABB cut2.0 */
309684edbeeab67c1575067335179513150115da367bArun Murthy	if (!is_ab8500_1p1_or_earlier(di->parent)) {
309784edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev,
309884edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CHARGER,
309984edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CH_VOLT_LVL_MAX_REG, CH_VOL_LVL_4P6);
310084edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
310184edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev,
310284edbeeab67c1575067335179513150115da367bArun Murthy				"failed to set CH_VOLT_LVL_MAX_REG\n");
310384edbeeab67c1575067335179513150115da367bArun Murthy			goto out;
310484edbeeab67c1575067335179513150115da367bArun Murthy		}
310584edbeeab67c1575067335179513150115da367bArun Murthy
3106861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		if (is_ab8540(di->parent))
3107861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			ret = abx500_set_register_interruptible(di->dev,
3108861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG,
3109861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				CH_OP_CUR_LVL_2P);
3110861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		else
3111861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			ret = abx500_set_register_interruptible(di->dev,
3112861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				AB8500_CHARGER, AB8500_CH_OPT_CRNTLVL_MAX_REG,
3113861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				CH_OP_CUR_LVL_1P6);
311484edbeeab67c1575067335179513150115da367bArun Murthy		if (ret) {
311584edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev,
311684edbeeab67c1575067335179513150115da367bArun Murthy				"failed to set CH_OPT_CRNTLVL_MAX_REG\n");
311784edbeeab67c1575067335179513150115da367bArun Murthy			goto out;
311884edbeeab67c1575067335179513150115da367bArun Murthy		}
311984edbeeab67c1575067335179513150115da367bArun Murthy	}
312084edbeeab67c1575067335179513150115da367bArun Murthy
3121861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	if (is_ab9540_2p0(di->parent) || is_ab9540_3p0(di->parent)
3122861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	 || is_ab8505_2p0(di->parent) || is_ab8540(di->parent))
31230ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg		ret = abx500_mask_and_set_register_interruptible(di->dev,
31240ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			AB8500_CHARGER,
31250ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			AB8500_USBCH_CTRL2_REG,
31260ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			VBUS_AUTO_IN_CURR_LIM_ENA,
31270ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			VBUS_AUTO_IN_CURR_LIM_ENA);
31280ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg	else
31290ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg		/*
31300ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg		 * VBUS OVV set to 6.3V and enable automatic current limitation
31310ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg		 */
31320ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg		ret = abx500_set_register_interruptible(di->dev,
31330ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			AB8500_CHARGER,
31340ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			AB8500_USBCH_CTRL2_REG,
31350ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA);
313684edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
31370ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg		dev_err(di->dev,
31380ed5107fa86013c91b1752230d44b79dffee0cdaJonas Aaberg			"failed to set automatic current limitation\n");
313984edbeeab67c1575067335179513150115da367bArun Murthy		goto out;
314084edbeeab67c1575067335179513150115da367bArun Murthy	}
314184edbeeab67c1575067335179513150115da367bArun Murthy
314284edbeeab67c1575067335179513150115da367bArun Murthy	/* Enable main watchdog in OTP */
314384edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev,
314484edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_OTP_EMUL, AB8500_OTP_CONF_15, OTP_ENABLE_WD);
314584edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
314684edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to enable main WD in OTP\n");
314784edbeeab67c1575067335179513150115da367bArun Murthy		goto out;
314884edbeeab67c1575067335179513150115da367bArun Murthy	}
314984edbeeab67c1575067335179513150115da367bArun Murthy
315084edbeeab67c1575067335179513150115da367bArun Murthy	/* Enable main watchdog */
315184edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev,
315284edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_SYS_CTRL2_BLOCK,
315384edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_ENA);
315484edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
315584edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "faile to enable main watchdog\n");
315684edbeeab67c1575067335179513150115da367bArun Murthy		goto out;
315784edbeeab67c1575067335179513150115da367bArun Murthy	}
315884edbeeab67c1575067335179513150115da367bArun Murthy
315984edbeeab67c1575067335179513150115da367bArun Murthy	/*
316084edbeeab67c1575067335179513150115da367bArun Murthy	 * Due to internal synchronisation, Enable and Kick watchdog bits
316184edbeeab67c1575067335179513150115da367bArun Murthy	 * cannot be enabled in a single write.
316284edbeeab67c1575067335179513150115da367bArun Murthy	 * A minimum delay of 2*32 kHz period (62.5µs) must be inserted
316384edbeeab67c1575067335179513150115da367bArun Murthy	 * between writing Enable then Kick bits.
316484edbeeab67c1575067335179513150115da367bArun Murthy	 */
316584edbeeab67c1575067335179513150115da367bArun Murthy	udelay(63);
316684edbeeab67c1575067335179513150115da367bArun Murthy
316784edbeeab67c1575067335179513150115da367bArun Murthy	/* Kick main watchdog */
316884edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev,
316984edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_SYS_CTRL2_BLOCK,
317084edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_MAIN_WDOG_CTRL_REG,
317184edbeeab67c1575067335179513150115da367bArun Murthy		(MAIN_WDOG_ENA | MAIN_WDOG_KICK));
317284edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
317384edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to kick main watchdog\n");
317484edbeeab67c1575067335179513150115da367bArun Murthy		goto out;
317584edbeeab67c1575067335179513150115da367bArun Murthy	}
317684edbeeab67c1575067335179513150115da367bArun Murthy
317784edbeeab67c1575067335179513150115da367bArun Murthy	/* Disable main watchdog */
317884edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev,
317984edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_SYS_CTRL2_BLOCK,
318084edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_MAIN_WDOG_CTRL_REG, MAIN_WDOG_DIS);
318184edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
318284edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to disable main watchdog\n");
318384edbeeab67c1575067335179513150115da367bArun Murthy		goto out;
318484edbeeab67c1575067335179513150115da367bArun Murthy	}
318584edbeeab67c1575067335179513150115da367bArun Murthy
318684edbeeab67c1575067335179513150115da367bArun Murthy	/* Set watchdog timeout */
318784edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
318884edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_CH_WD_TIMER_REG, WD_TIMER);
318984edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
319084edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to set charger watchdog timeout\n");
319134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		goto out;
319234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	}
319334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
319434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	ret = ab8500_charger_led_en(di, false);
319534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (ret < 0) {
319634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		dev_err(di->dev, "failed to disable LED\n");
319734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		goto out;
319834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	}
319934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
320084edbeeab67c1575067335179513150115da367bArun Murthy	/* Backup battery voltage and current */
32010f4aa401853e07885707aedfc68c608051b0d6e4Yang QU	if (di->bm->bkup_bat_v > BUP_VCH_SEL_3P1V)
32020f4aa401853e07885707aedfc68c608051b0d6e4Yang QU		bup_vch_range = BUP_VCH_RANGE;
32030f4aa401853e07885707aedfc68c608051b0d6e4Yang QU	if (di->bm->bkup_bat_v == BUP_VCH_SEL_3P3V)
32040f4aa401853e07885707aedfc68c608051b0d6e4Yang QU		vbup33_vrtcn = VBUP33_VRTCN;
32050f4aa401853e07885707aedfc68c608051b0d6e4Yang QU
320684edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_set_register_interruptible(di->dev,
320784edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_RTC,
320884edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_RTC_BACKUP_CHG_REG,
32090f4aa401853e07885707aedfc68c608051b0d6e4Yang QU		(di->bm->bkup_bat_v & 0x3) | di->bm->bkup_bat_i);
321084edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
321184edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to setup backup battery charging\n");
321284edbeeab67c1575067335179513150115da367bArun Murthy		goto out;
321384edbeeab67c1575067335179513150115da367bArun Murthy	}
32140f4aa401853e07885707aedfc68c608051b0d6e4Yang QU	if (is_ab8540(di->parent)) {
32150f4aa401853e07885707aedfc68c608051b0d6e4Yang QU		ret = abx500_set_register_interruptible(di->dev,
32160f4aa401853e07885707aedfc68c608051b0d6e4Yang QU			AB8500_RTC,
32170f4aa401853e07885707aedfc68c608051b0d6e4Yang QU			AB8500_RTC_CTRL1_REG,
32180f4aa401853e07885707aedfc68c608051b0d6e4Yang QU			bup_vch_range | vbup33_vrtcn);
32190f4aa401853e07885707aedfc68c608051b0d6e4Yang QU		if (ret) {
3220861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			dev_err(di->dev,
3221861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				"failed to setup backup battery charging\n");
32220f4aa401853e07885707aedfc68c608051b0d6e4Yang QU			goto out;
32230f4aa401853e07885707aedfc68c608051b0d6e4Yang QU		}
32240f4aa401853e07885707aedfc68c608051b0d6e4Yang QU	}
322584edbeeab67c1575067335179513150115da367bArun Murthy
322684edbeeab67c1575067335179513150115da367bArun Murthy	/* Enable backup battery charging */
322784edbeeab67c1575067335179513150115da367bArun Murthy	abx500_mask_and_set_register_interruptible(di->dev,
322884edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_RTC, AB8500_RTC_CTRL_REG,
322984edbeeab67c1575067335179513150115da367bArun Murthy		RTC_BUP_CH_ENA, RTC_BUP_CH_ENA);
323084edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0)
323184edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s mask and set failed\n", __func__);
323284edbeeab67c1575067335179513150115da367bArun Murthy
3233db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	if (is_ab8540(di->parent)) {
3234db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		ret = abx500_mask_and_set_register_interruptible(di->dev,
3235db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones			AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
3236db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones			BUS_VSYS_VOL_SELECT_MASK, BUS_VSYS_VOL_SELECT_3P6V);
3237db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		if (ret) {
3238861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			dev_err(di->dev,
3239861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				"failed to setup usb power path vsys voltage\n");
3240db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones			goto out;
3241db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		}
3242db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		ret = abx500_mask_and_set_register_interruptible(di->dev,
3243db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones			AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
3244db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones			BUS_PP_PRECHG_CURRENT_MASK, 0);
3245db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		if (ret) {
3246861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones			dev_err(di->dev,
3247861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones				"failed to setup usb power path prechage current\n");
3248db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones			goto out;
3249db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones		}
3250db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	}
3251db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones
325284edbeeab67c1575067335179513150115da367bArun Murthyout:
325384edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
325484edbeeab67c1575067335179513150115da367bArun Murthy}
325584edbeeab67c1575067335179513150115da367bArun Murthy
325684edbeeab67c1575067335179513150115da367bArun Murthy/*
325784edbeeab67c1575067335179513150115da367bArun Murthy * ab8500 charger driver interrupts and their respective isr
325884edbeeab67c1575067335179513150115da367bArun Murthy */
325984edbeeab67c1575067335179513150115da367bArun Murthystatic struct ab8500_charger_interrupts ab8500_charger_irq[] = {
326084edbeeab67c1575067335179513150115da367bArun Murthy	{"MAIN_CH_UNPLUG_DET", ab8500_charger_mainchunplugdet_handler},
326184edbeeab67c1575067335179513150115da367bArun Murthy	{"MAIN_CHARGE_PLUG_DET", ab8500_charger_mainchplugdet_handler},
326284edbeeab67c1575067335179513150115da367bArun Murthy	{"MAIN_EXT_CH_NOT_OK", ab8500_charger_mainextchnotok_handler},
326384edbeeab67c1575067335179513150115da367bArun Murthy	{"MAIN_CH_TH_PROT_R", ab8500_charger_mainchthprotr_handler},
326484edbeeab67c1575067335179513150115da367bArun Murthy	{"MAIN_CH_TH_PROT_F", ab8500_charger_mainchthprotf_handler},
326584edbeeab67c1575067335179513150115da367bArun Murthy	{"VBUS_DET_F", ab8500_charger_vbusdetf_handler},
326684edbeeab67c1575067335179513150115da367bArun Murthy	{"VBUS_DET_R", ab8500_charger_vbusdetr_handler},
326784edbeeab67c1575067335179513150115da367bArun Murthy	{"USB_LINK_STATUS", ab8500_charger_usblinkstatus_handler},
326884edbeeab67c1575067335179513150115da367bArun Murthy	{"USB_CH_TH_PROT_R", ab8500_charger_usbchthprotr_handler},
326984edbeeab67c1575067335179513150115da367bArun Murthy	{"USB_CH_TH_PROT_F", ab8500_charger_usbchthprotf_handler},
327084edbeeab67c1575067335179513150115da367bArun Murthy	{"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler},
327184edbeeab67c1575067335179513150115da367bArun Murthy	{"VBUS_OVV", ab8500_charger_vbusovv_handler},
327284edbeeab67c1575067335179513150115da367bArun Murthy	{"CH_WD_EXP", ab8500_charger_chwdexp_handler},
327334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	{"VBUS_CH_DROP_END", ab8500_charger_vbuschdropend_handler},
327484edbeeab67c1575067335179513150115da367bArun Murthy};
327584edbeeab67c1575067335179513150115da367bArun Murthy
327684edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_usb_notifier_call(struct notifier_block *nb,
327784edbeeab67c1575067335179513150115da367bArun Murthy		unsigned long event, void *power)
327884edbeeab67c1575067335179513150115da367bArun Murthy{
327984edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di =
328084edbeeab67c1575067335179513150115da367bArun Murthy		container_of(nb, struct ab8500_charger, nb);
328184edbeeab67c1575067335179513150115da367bArun Murthy	enum ab8500_usb_state bm_usb_state;
328284edbeeab67c1575067335179513150115da367bArun Murthy	unsigned mA = *((unsigned *)power);
328384edbeeab67c1575067335179513150115da367bArun Murthy
3284c9ade0fca3f7939194677353097b16c9795df46bLee Jones	if (!di)
3285c9ade0fca3f7939194677353097b16c9795df46bLee Jones		return NOTIFY_DONE;
3286c9ade0fca3f7939194677353097b16c9795df46bLee Jones
328784edbeeab67c1575067335179513150115da367bArun Murthy	if (event != USB_EVENT_VBUS) {
328884edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "not a standard host, returning\n");
328984edbeeab67c1575067335179513150115da367bArun Murthy		return NOTIFY_DONE;
329084edbeeab67c1575067335179513150115da367bArun Murthy	}
329184edbeeab67c1575067335179513150115da367bArun Murthy
329284edbeeab67c1575067335179513150115da367bArun Murthy	/* TODO: State is fabricate  here. See if charger really needs USB
329384edbeeab67c1575067335179513150115da367bArun Murthy	 * state or if mA is enough
329484edbeeab67c1575067335179513150115da367bArun Murthy	 */
329584edbeeab67c1575067335179513150115da367bArun Murthy	if ((di->usb_state.usb_current == 2) && (mA > 2))
329684edbeeab67c1575067335179513150115da367bArun Murthy		bm_usb_state = AB8500_BM_USB_STATE_RESUME;
329784edbeeab67c1575067335179513150115da367bArun Murthy	else if (mA == 0)
329884edbeeab67c1575067335179513150115da367bArun Murthy		bm_usb_state = AB8500_BM_USB_STATE_RESET_HS;
329984edbeeab67c1575067335179513150115da367bArun Murthy	else if (mA == 2)
330084edbeeab67c1575067335179513150115da367bArun Murthy		bm_usb_state = AB8500_BM_USB_STATE_SUSPEND;
330184edbeeab67c1575067335179513150115da367bArun Murthy	else if (mA >= 8) /* 8, 100, 500 */
330284edbeeab67c1575067335179513150115da367bArun Murthy		bm_usb_state = AB8500_BM_USB_STATE_CONFIGURED;
330384edbeeab67c1575067335179513150115da367bArun Murthy	else /* Should never occur */
330484edbeeab67c1575067335179513150115da367bArun Murthy		bm_usb_state = AB8500_BM_USB_STATE_RESET_FS;
330584edbeeab67c1575067335179513150115da367bArun Murthy
330684edbeeab67c1575067335179513150115da367bArun Murthy	dev_dbg(di->dev, "%s usb_state: 0x%02x mA: %d\n",
330784edbeeab67c1575067335179513150115da367bArun Murthy		__func__, bm_usb_state, mA);
330884edbeeab67c1575067335179513150115da367bArun Murthy
330984edbeeab67c1575067335179513150115da367bArun Murthy	spin_lock(&di->usb_state.usb_lock);
331034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->usb_state.state_tmp = bm_usb_state;
331134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	di->usb_state.usb_current_tmp = mA;
331284edbeeab67c1575067335179513150115da367bArun Murthy	spin_unlock(&di->usb_state.usb_lock);
331384edbeeab67c1575067335179513150115da367bArun Murthy
331434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	/*
331534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 * wait for some time until you get updates from the usb stack
331634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 * and negotiations are completed
331734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	 */
331834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	queue_delayed_work(di->charger_wq, &di->usb_state_changed_work, HZ/2);
331984edbeeab67c1575067335179513150115da367bArun Murthy
332084edbeeab67c1575067335179513150115da367bArun Murthy	return NOTIFY_OK;
332184edbeeab67c1575067335179513150115da367bArun Murthy}
332284edbeeab67c1575067335179513150115da367bArun Murthy
332384edbeeab67c1575067335179513150115da367bArun Murthy#if defined(CONFIG_PM)
332484edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_resume(struct platform_device *pdev)
332584edbeeab67c1575067335179513150115da367bArun Murthy{
332684edbeeab67c1575067335179513150115da367bArun Murthy	int ret;
332784edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = platform_get_drvdata(pdev);
332884edbeeab67c1575067335179513150115da367bArun Murthy
332984edbeeab67c1575067335179513150115da367bArun Murthy	/*
333084edbeeab67c1575067335179513150115da367bArun Murthy	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
333184edbeeab67c1575067335179513150115da367bArun Murthy	 * logic. That means we have to continously kick the charger
333284edbeeab67c1575067335179513150115da367bArun Murthy	 * watchdog even when no charger is connected. This is only
333384edbeeab67c1575067335179513150115da367bArun Murthy	 * valid once the AC charger has been enabled. This is
333484edbeeab67c1575067335179513150115da367bArun Murthy	 * a bug that is not handled by the algorithm and the
333584edbeeab67c1575067335179513150115da367bArun Murthy	 * watchdog have to be kicked by the charger driver
333684edbeeab67c1575067335179513150115da367bArun Murthy	 * when the AC charger is disabled
333784edbeeab67c1575067335179513150115da367bArun Murthy	 */
333884edbeeab67c1575067335179513150115da367bArun Murthy	if (di->ac_conn && is_ab8500_1p1_or_earlier(di->parent)) {
333984edbeeab67c1575067335179513150115da367bArun Murthy		ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
334084edbeeab67c1575067335179513150115da367bArun Murthy			AB8500_CHARG_WD_CTRL, CHARG_WD_KICK);
334184edbeeab67c1575067335179513150115da367bArun Murthy		if (ret)
334284edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "Failed to kick WD!\n");
334384edbeeab67c1575067335179513150115da367bArun Murthy
334484edbeeab67c1575067335179513150115da367bArun Murthy		/* If not already pending start a new timer */
3345b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones		queue_delayed_work(di->charger_wq, &di->kick_wd_work,
3346b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones				   round_jiffies(WD_KICK_INTERVAL));
334784edbeeab67c1575067335179513150115da367bArun Murthy	}
334884edbeeab67c1575067335179513150115da367bArun Murthy
334984edbeeab67c1575067335179513150115da367bArun Murthy	/* If we still have a HW failure, schedule a new check */
335084edbeeab67c1575067335179513150115da367bArun Murthy	if (di->flags.mainextchnotok || di->flags.vbus_ovv) {
335184edbeeab67c1575067335179513150115da367bArun Murthy		queue_delayed_work(di->charger_wq,
335284edbeeab67c1575067335179513150115da367bArun Murthy			&di->check_hw_failure_work, 0);
335384edbeeab67c1575067335179513150115da367bArun Murthy	}
335484edbeeab67c1575067335179513150115da367bArun Murthy
335534c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (di->flags.vbus_drop_end)
335634c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 0);
335734c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
335884edbeeab67c1575067335179513150115da367bArun Murthy	return 0;
335984edbeeab67c1575067335179513150115da367bArun Murthy}
336084edbeeab67c1575067335179513150115da367bArun Murthy
336184edbeeab67c1575067335179513150115da367bArun Murthystatic int ab8500_charger_suspend(struct platform_device *pdev,
336284edbeeab67c1575067335179513150115da367bArun Murthy	pm_message_t state)
336384edbeeab67c1575067335179513150115da367bArun Murthy{
336484edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = platform_get_drvdata(pdev);
336584edbeeab67c1575067335179513150115da367bArun Murthy
3366b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones	/* Cancel any pending jobs */
3367b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones	cancel_delayed_work(&di->check_hw_failure_work);
3368b09f86dbfc20d9420dac43dba016cb65b582c983Lee Jones	cancel_delayed_work(&di->vbus_drop_end_work);
336934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
337053ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_delayed_work(&di->attach_work);
337153ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_delayed_work(&di->usb_charger_attached_work);
337253ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_delayed_work(&di->ac_charger_attached_work);
337353ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_delayed_work(&di->check_usbchgnotok_work);
337453ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_delayed_work(&di->check_vbat_work);
337553ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_delayed_work(&di->kick_wd_work);
337653ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg
337753ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_work(&di->usb_link_status_work);
337853ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_work(&di->ac_work);
337953ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg	flush_work(&di->detect_usb_type_work);
338053ef1f590dc59f3c1478c68ea1f06a28f55ddccbJonas Aaberg
338134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	if (atomic_read(&di->current_stepping_sessions))
338234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		return -EAGAIN;
338334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
338484edbeeab67c1575067335179513150115da367bArun Murthy	return 0;
338584edbeeab67c1575067335179513150115da367bArun Murthy}
338684edbeeab67c1575067335179513150115da367bArun Murthy#else
338784edbeeab67c1575067335179513150115da367bArun Murthy#define ab8500_charger_suspend      NULL
338884edbeeab67c1575067335179513150115da367bArun Murthy#define ab8500_charger_resume       NULL
338984edbeeab67c1575067335179513150115da367bArun Murthy#endif
339084edbeeab67c1575067335179513150115da367bArun Murthy
33918891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jonesstatic struct notifier_block charger_nb = {
33928891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	.notifier_call = ab8500_external_charger_prepare,
33938891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones};
33948891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones
3395415ec69fb1861fc377c65cb30ddc76999891b8e1Bill Pembertonstatic int ab8500_charger_remove(struct platform_device *pdev)
339684edbeeab67c1575067335179513150115da367bArun Murthy{
339784edbeeab67c1575067335179513150115da367bArun Murthy	struct ab8500_charger *di = platform_get_drvdata(pdev);
339884edbeeab67c1575067335179513150115da367bArun Murthy	int i, irq, ret;
339984edbeeab67c1575067335179513150115da367bArun Murthy
340084edbeeab67c1575067335179513150115da367bArun Murthy	/* Disable AC charging */
340184edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_charger_ac_en(&di->ac_chg, false, 0, 0);
340284edbeeab67c1575067335179513150115da367bArun Murthy
340384edbeeab67c1575067335179513150115da367bArun Murthy	/* Disable USB charging */
340484edbeeab67c1575067335179513150115da367bArun Murthy	ab8500_charger_usb_en(&di->usb_chg, false, 0, 0);
340584edbeeab67c1575067335179513150115da367bArun Murthy
340684edbeeab67c1575067335179513150115da367bArun Murthy	/* Disable interrupts */
340784edbeeab67c1575067335179513150115da367bArun Murthy	for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
340884edbeeab67c1575067335179513150115da367bArun Murthy		irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
340984edbeeab67c1575067335179513150115da367bArun Murthy		free_irq(irq, di);
341084edbeeab67c1575067335179513150115da367bArun Murthy	}
341184edbeeab67c1575067335179513150115da367bArun Murthy
341284edbeeab67c1575067335179513150115da367bArun Murthy	/* Backup battery voltage and current disable */
341384edbeeab67c1575067335179513150115da367bArun Murthy	ret = abx500_mask_and_set_register_interruptible(di->dev,
341484edbeeab67c1575067335179513150115da367bArun Murthy		AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0);
341584edbeeab67c1575067335179513150115da367bArun Murthy	if (ret < 0)
341684edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "%s mask and set failed\n", __func__);
341784edbeeab67c1575067335179513150115da367bArun Murthy
3418efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov	usb_unregister_notifier(di->usb_phy, &di->nb);
3419721002ec1dd55a52425455826af49cf8853b2d4fKishon Vijay Abraham I	usb_put_phy(di->usb_phy);
342084edbeeab67c1575067335179513150115da367bArun Murthy
342184edbeeab67c1575067335179513150115da367bArun Murthy	/* Delete the work queue */
342284edbeeab67c1575067335179513150115da367bArun Murthy	destroy_workqueue(di->charger_wq);
342384edbeeab67c1575067335179513150115da367bArun Murthy
34248891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	/* Unregister external charger enable notifier */
34258891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	if (!di->ac_chg.enabled)
34268891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones		blocking_notifier_chain_unregister(
34278891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones			&charger_notifier_list, &charger_nb);
34288891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones
342984edbeeab67c1575067335179513150115da367bArun Murthy	flush_scheduled_work();
343072a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones	if (di->usb_chg.enabled)
343101ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		power_supply_unregister(&di->usb_chg.psy);
3432405fea1c6691eb8259f2ca879c9348a4cf5d898dMarcus Cooper
3433405fea1c6691eb8259f2ca879c9348a4cf5d898dMarcus Cooper	if (di->ac_chg.enabled && !di->ac_chg.external)
343401ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		power_supply_unregister(&di->ac_chg.psy);
3435405fea1c6691eb8259f2ca879c9348a4cf5d898dMarcus Cooper
343684edbeeab67c1575067335179513150115da367bArun Murthy	return 0;
343784edbeeab67c1575067335179513150115da367bArun Murthy}
343884edbeeab67c1575067335179513150115da367bArun Murthy
34394aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.Vstatic char *supply_interface[] = {
34404aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	"ab8500_chargalg",
34414aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	"ab8500_fg",
34424aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	"ab8500_btemp",
34434aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V};
34444aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V
3445c8afa6406e60aec6ff90033e5ffe41a206609296Bill Pembertonstatic int ab8500_charger_probe(struct platform_device *pdev)
344684edbeeab67c1575067335179513150115da367bArun Murthy{
34474aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	struct device_node *np = pdev->dev.of_node;
34487722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones	struct abx500_bm_data *plat = pdev->dev.platform_data;
34492aac3de19b72608f474c90034185c2be4908728fLee Jones	struct ab8500_charger *di;
3450b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	int irq, i, charger_status, ret = 0, ch_stat;
345184edbeeab67c1575067335179513150115da367bArun Murthy
34524aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
34534aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	if (!di) {
34544aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V		dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__);
345584edbeeab67c1575067335179513150115da367bArun Murthy		return -ENOMEM;
34564aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	}
34577722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones
34587722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones	if (!plat) {
34597722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones		dev_err(&pdev->dev, "no battery management data supplied\n");
34607722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones		return -EINVAL;
34617722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones	}
34627722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones	di->bm = plat;
34637722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones
34647722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones	if (np) {
34657722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones		ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
34667722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones		if (ret) {
34677722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones			dev_err(&pdev->dev, "failed to get battery information\n");
34687722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones			return ret;
34694aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V		}
34707722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones		di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
34717722b79964f0b1d7909eb7ef69632d73b07ca6a3Lee Jones	} else
34724aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V		di->autopower_cfg = false;
347384edbeeab67c1575067335179513150115da367bArun Murthy
347484edbeeab67c1575067335179513150115da367bArun Murthy	/* get parent data */
347584edbeeab67c1575067335179513150115da367bArun Murthy	di->dev = &pdev->dev;
347684edbeeab67c1575067335179513150115da367bArun Murthy	di->parent = dev_get_drvdata(pdev->dev.parent);
347784edbeeab67c1575067335179513150115da367bArun Murthy	di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
347884edbeeab67c1575067335179513150115da367bArun Murthy
347984edbeeab67c1575067335179513150115da367bArun Murthy	/* initialize lock */
348084edbeeab67c1575067335179513150115da367bArun Murthy	spin_lock_init(&di->usb_state.usb_lock);
348134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	mutex_init(&di->usb_ipt_crnt_lock);
348284edbeeab67c1575067335179513150115da367bArun Murthy
348384edbeeab67c1575067335179513150115da367bArun Murthy	di->autopower = false;
3484ff38090aa2e1423e130cc72e790145bad7de8215Henrik Sölver	di->invalid_charger_detect_state = 0;
348584edbeeab67c1575067335179513150115da367bArun Murthy
348684edbeeab67c1575067335179513150115da367bArun Murthy	/* AC supply */
348784edbeeab67c1575067335179513150115da367bArun Murthy	/* power_supply base class */
348884edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.psy.name = "ab8500_ac";
348984edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS;
349084edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.psy.properties = ab8500_charger_ac_props;
349184edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props);
349284edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.psy.get_property = ab8500_charger_ac_get_property;
34934aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	di->ac_chg.psy.supplied_to = supply_interface;
34944aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
349584edbeeab67c1575067335179513150115da367bArun Murthy	/* ux500_charger sub-class */
349684edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.ops.enable = &ab8500_charger_ac_en;
34974dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable;
349884edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
349984edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.ops.update_curr = &ab8500_charger_update_charger_current;
350084edbeeab67c1575067335179513150115da367bArun Murthy	di->ac_chg.max_out_volt = ab8500_charger_voltage_map[
350184edbeeab67c1575067335179513150115da367bArun Murthy		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
3502861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	di->ac_chg.max_out_curr =
3503861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1];
3504e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy	di->ac_chg.wdt_refresh = CHG_WD_INTERVAL;
350597034a1e042d4316a83a3f68d61edf6c42e3f265Lee Jones	di->ac_chg.enabled = di->bm->ac_enabled;
3506e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy	di->ac_chg.external = false;
350784edbeeab67c1575067335179513150115da367bArun Murthy
35088891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	/*notifier for external charger enabling*/
35098891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones	if (!di->ac_chg.enabled)
35108891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones		blocking_notifier_chain_register(
35118891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones			&charger_notifier_list, &charger_nb);
35128891716e24d7b0f4b1c3b4fdff641bcb1fb282c4Lee Jones
351384edbeeab67c1575067335179513150115da367bArun Murthy	/* USB supply */
351484edbeeab67c1575067335179513150115da367bArun Murthy	/* power_supply base class */
351584edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.psy.name = "ab8500_usb";
351684edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.psy.type = POWER_SUPPLY_TYPE_USB;
351784edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.psy.properties = ab8500_charger_usb_props;
351884edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props);
351984edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.psy.get_property = ab8500_charger_usb_get_property;
35204aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	di->usb_chg.psy.supplied_to = supply_interface;
35214aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
352284edbeeab67c1575067335179513150115da367bArun Murthy	/* ux500_charger sub-class */
352384edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.ops.enable = &ab8500_charger_usb_en;
35244dcdf57773fd45b483fc7613b9e51b89a57d655cLee Jones	di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
352584edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
352684edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current;
3527db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	di->usb_chg.ops.pp_enable = &ab8540_charger_power_path_enable;
3528db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	di->usb_chg.ops.pre_chg_enable = &ab8540_charger_usb_pre_chg_enable;
352984edbeeab67c1575067335179513150115da367bArun Murthy	di->usb_chg.max_out_volt = ab8500_charger_voltage_map[
353084edbeeab67c1575067335179513150115da367bArun Murthy		ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
3531861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones	di->usb_chg.max_out_curr =
3532861a30da53e2c5b9823b5390c1757baaf8f6e356Lee Jones		di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1];
3533e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy	di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
353497034a1e042d4316a83a3f68d61edf6c42e3f265Lee Jones	di->usb_chg.enabled = di->bm->usb_enabled;
3535e07a56453b14b929cf01bf032cc3e3220094609cLoic Pallardy	di->usb_chg.external = false;
3536db43e6c473b57d4e7a55c4bd6edef71f40f13eaeLee Jones	di->usb_chg.power_path = di->bm->usb_power_path;
3537f7470b5d246294761892f4bafc0eeedaa4369d92Lee Jones	di->usb_state.usb_current = -1;
353884edbeeab67c1575067335179513150115da367bArun Murthy
353984edbeeab67c1575067335179513150115da367bArun Murthy	/* Create a work queue for the charger */
354084edbeeab67c1575067335179513150115da367bArun Murthy	di->charger_wq =
354184edbeeab67c1575067335179513150115da367bArun Murthy		create_singlethread_workqueue("ab8500_charger_wq");
354284edbeeab67c1575067335179513150115da367bArun Murthy	if (di->charger_wq == NULL) {
354384edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to create work queue\n");
35444aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V		return -ENOMEM;
354584edbeeab67c1575067335179513150115da367bArun Murthy	}
354684edbeeab67c1575067335179513150115da367bArun Murthy
3547b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_init(&di->charger_attached_mutex);
3548b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
354984edbeeab67c1575067335179513150115da367bArun Murthy	/* Init work for HW failure check */
3550203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo	INIT_DEFERRABLE_WORK(&di->check_hw_failure_work,
355184edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_check_hw_failure_work);
3552203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo	INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work,
355384edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_check_usbchargernotok_work);
355484edbeeab67c1575067335179513150115da367bArun Murthy
3555b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	INIT_DELAYED_WORK(&di->ac_charger_attached_work,
3556b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			  ab8500_charger_ac_attached_work);
3557b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	INIT_DELAYED_WORK(&di->usb_charger_attached_work,
3558b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones			  ab8500_charger_usb_attached_work);
3559b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
356084edbeeab67c1575067335179513150115da367bArun Murthy	/*
356184edbeeab67c1575067335179513150115da367bArun Murthy	 * For ABB revision 1.0 and 1.1 there is a bug in the watchdog
356284edbeeab67c1575067335179513150115da367bArun Murthy	 * logic. That means we have to continously kick the charger
356384edbeeab67c1575067335179513150115da367bArun Murthy	 * watchdog even when no charger is connected. This is only
356484edbeeab67c1575067335179513150115da367bArun Murthy	 * valid once the AC charger has been enabled. This is
356584edbeeab67c1575067335179513150115da367bArun Murthy	 * a bug that is not handled by the algorithm and the
356684edbeeab67c1575067335179513150115da367bArun Murthy	 * watchdog have to be kicked by the charger driver
356784edbeeab67c1575067335179513150115da367bArun Murthy	 * when the AC charger is disabled
356884edbeeab67c1575067335179513150115da367bArun Murthy	 */
3569203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo	INIT_DEFERRABLE_WORK(&di->kick_wd_work,
357084edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_kick_watchdog_work);
357184edbeeab67c1575067335179513150115da367bArun Murthy
3572203b42f7317494ae5e5efc7be6fb7f29c927f102Tejun Heo	INIT_DEFERRABLE_WORK(&di->check_vbat_work,
357384edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_check_vbat_work);
357484edbeeab67c1575067335179513150115da367bArun Murthy
35754b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper	INIT_DELAYED_WORK(&di->attach_work,
35764b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper		ab8500_charger_usb_link_attach_work);
35774b45f4a9cd4eae34b23becb686f2c2a637d844d3Marcus Cooper
357834c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	INIT_DELAYED_WORK(&di->usb_state_changed_work,
357934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ab8500_charger_usb_state_changed_work);
358034c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
358134c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	INIT_DELAYED_WORK(&di->vbus_drop_end_work,
358234c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson		ab8500_charger_vbus_drop_end_work);
358334c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson
358484edbeeab67c1575067335179513150115da367bArun Murthy	/* Init work for charger detection */
358584edbeeab67c1575067335179513150115da367bArun Murthy	INIT_WORK(&di->usb_link_status_work,
358684edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_usb_link_status_work);
358784edbeeab67c1575067335179513150115da367bArun Murthy	INIT_WORK(&di->ac_work, ab8500_charger_ac_work);
358884edbeeab67c1575067335179513150115da367bArun Murthy	INIT_WORK(&di->detect_usb_type_work,
358984edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_detect_usb_type_work);
359084edbeeab67c1575067335179513150115da367bArun Murthy
359184edbeeab67c1575067335179513150115da367bArun Murthy	/* Init work for checking HW status */
359284edbeeab67c1575067335179513150115da367bArun Murthy	INIT_WORK(&di->check_main_thermal_prot_work,
359384edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_check_main_thermal_prot_work);
359484edbeeab67c1575067335179513150115da367bArun Murthy	INIT_WORK(&di->check_usb_thermal_prot_work,
359584edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_charger_check_usb_thermal_prot_work);
359684edbeeab67c1575067335179513150115da367bArun Murthy
359784edbeeab67c1575067335179513150115da367bArun Murthy	/*
359884edbeeab67c1575067335179513150115da367bArun Murthy	 * VDD ADC supply needs to be enabled from this driver when there
359984edbeeab67c1575067335179513150115da367bArun Murthy	 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
360084edbeeab67c1575067335179513150115da367bArun Murthy	 * interrupts during charging
360184edbeeab67c1575067335179513150115da367bArun Murthy	 */
36028feffd109977c045669913f4e80e8811f2212cd9Sachin Kamat	di->regu = devm_regulator_get(di->dev, "vddadc");
360384edbeeab67c1575067335179513150115da367bArun Murthy	if (IS_ERR(di->regu)) {
360484edbeeab67c1575067335179513150115da367bArun Murthy		ret = PTR_ERR(di->regu);
360584edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to get vddadc regulator\n");
360684edbeeab67c1575067335179513150115da367bArun Murthy		goto free_charger_wq;
360784edbeeab67c1575067335179513150115da367bArun Murthy	}
360884edbeeab67c1575067335179513150115da367bArun Murthy
360984edbeeab67c1575067335179513150115da367bArun Murthy
361084edbeeab67c1575067335179513150115da367bArun Murthy	/* Initialize OVV, and other registers */
361184edbeeab67c1575067335179513150115da367bArun Murthy	ret = ab8500_charger_init_hw_registers(di);
361284edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
361384edbeeab67c1575067335179513150115da367bArun Murthy		dev_err(di->dev, "failed to initialize ABB registers\n");
36148feffd109977c045669913f4e80e8811f2212cd9Sachin Kamat		goto free_charger_wq;
361584edbeeab67c1575067335179513150115da367bArun Murthy	}
361684edbeeab67c1575067335179513150115da367bArun Murthy
361784edbeeab67c1575067335179513150115da367bArun Murthy	/* Register AC charger class */
361872a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones	if (di->ac_chg.enabled) {
361901ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		ret = power_supply_register(di->dev, &di->ac_chg.psy);
362001ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		if (ret) {
362101ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN			dev_err(di->dev, "failed to register AC charger\n");
362201ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN			goto free_charger_wq;
362301ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		}
362484edbeeab67c1575067335179513150115da367bArun Murthy	}
362584edbeeab67c1575067335179513150115da367bArun Murthy
362684edbeeab67c1575067335179513150115da367bArun Murthy	/* Register USB charger class */
362772a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones	if (di->usb_chg.enabled) {
362801ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		ret = power_supply_register(di->dev, &di->usb_chg.psy);
362901ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		if (ret) {
363001ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN			dev_err(di->dev, "failed to register USB charger\n");
363101ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN			goto free_ac;
363201ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		}
363384edbeeab67c1575067335179513150115da367bArun Murthy	}
363484edbeeab67c1575067335179513150115da367bArun Murthy
3635662dca54ca67c92b7aa14b9a2ec54acacf33ce45Kishon Vijay Abraham I	di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
3636ded017ee6c7b90f7356bd8488f8af1c10ba90490Kishon Vijay Abraham I	if (IS_ERR_OR_NULL(di->usb_phy)) {
3637efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov		dev_err(di->dev, "failed to get usb transceiver\n");
363884edbeeab67c1575067335179513150115da367bArun Murthy		ret = -EINVAL;
363984edbeeab67c1575067335179513150115da367bArun Murthy		goto free_usb;
364084edbeeab67c1575067335179513150115da367bArun Murthy	}
364184edbeeab67c1575067335179513150115da367bArun Murthy	di->nb.notifier_call = ab8500_charger_usb_notifier_call;
3642efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov	ret = usb_register_notifier(di->usb_phy, &di->nb);
364384edbeeab67c1575067335179513150115da367bArun Murthy	if (ret) {
3644efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov		dev_err(di->dev, "failed to register usb notifier\n");
3645efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov		goto put_usb_phy;
364684edbeeab67c1575067335179513150115da367bArun Murthy	}
364784edbeeab67c1575067335179513150115da367bArun Murthy
364884edbeeab67c1575067335179513150115da367bArun Murthy	/* Identify the connected charger types during startup */
364934c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	charger_status = ab8500_charger_detect_chargers(di, true);
365084edbeeab67c1575067335179513150115da367bArun Murthy	if (charger_status & AC_PW_CONN) {
365184edbeeab67c1575067335179513150115da367bArun Murthy		di->ac.charger_connected = 1;
365284edbeeab67c1575067335179513150115da367bArun Murthy		di->ac_conn = true;
365384edbeeab67c1575067335179513150115da367bArun Murthy		ab8500_power_supply_changed(di, &di->ac_chg.psy);
365484edbeeab67c1575067335179513150115da367bArun Murthy		sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present");
365584edbeeab67c1575067335179513150115da367bArun Murthy	}
365684edbeeab67c1575067335179513150115da367bArun Murthy
365784edbeeab67c1575067335179513150115da367bArun Murthy	if (charger_status & USB_PW_CONN) {
365884edbeeab67c1575067335179513150115da367bArun Murthy		di->vbus_detected = true;
365984edbeeab67c1575067335179513150115da367bArun Murthy		di->vbus_detected_start = true;
366084edbeeab67c1575067335179513150115da367bArun Murthy		queue_work(di->charger_wq,
366184edbeeab67c1575067335179513150115da367bArun Murthy			&di->detect_usb_type_work);
366284edbeeab67c1575067335179513150115da367bArun Murthy	}
366384edbeeab67c1575067335179513150115da367bArun Murthy
366484edbeeab67c1575067335179513150115da367bArun Murthy	/* Register interrupts */
366584edbeeab67c1575067335179513150115da367bArun Murthy	for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
366684edbeeab67c1575067335179513150115da367bArun Murthy		irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
366784edbeeab67c1575067335179513150115da367bArun Murthy		ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr,
366884edbeeab67c1575067335179513150115da367bArun Murthy			IRQF_SHARED | IRQF_NO_SUSPEND,
366984edbeeab67c1575067335179513150115da367bArun Murthy			ab8500_charger_irq[i].name, di);
367084edbeeab67c1575067335179513150115da367bArun Murthy
367184edbeeab67c1575067335179513150115da367bArun Murthy		if (ret != 0) {
367284edbeeab67c1575067335179513150115da367bArun Murthy			dev_err(di->dev, "failed to request %s IRQ %d: %d\n"
367384edbeeab67c1575067335179513150115da367bArun Murthy				, ab8500_charger_irq[i].name, irq, ret);
367484edbeeab67c1575067335179513150115da367bArun Murthy			goto free_irq;
367584edbeeab67c1575067335179513150115da367bArun Murthy		}
367684edbeeab67c1575067335179513150115da367bArun Murthy		dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
367784edbeeab67c1575067335179513150115da367bArun Murthy			ab8500_charger_irq[i].name, irq, ret);
367884edbeeab67c1575067335179513150115da367bArun Murthy	}
367984edbeeab67c1575067335179513150115da367bArun Murthy
368084edbeeab67c1575067335179513150115da367bArun Murthy	platform_set_drvdata(pdev, di);
368184edbeeab67c1575067335179513150115da367bArun Murthy
3682b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_lock(&di->charger_attached_mutex);
3683b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
368434c11a709e928090cf34ecd706f7d3170f4e5026Paer-Olof Haakansson	ch_stat = ab8500_charger_detect_chargers(di, false);
3685b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
3686b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) {
3687261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent		if (is_ab8500(di->parent))
3688261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent			queue_delayed_work(di->charger_wq,
3689261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent					   &di->ac_charger_attached_work,
3690261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent					   HZ);
3691b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	}
3692b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) {
3693261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent		if (is_ab8500(di->parent))
3694261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent			queue_delayed_work(di->charger_wq,
3695261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent					   &di->usb_charger_attached_work,
3696261c5136fa988008387e31cf5381dc5b088e2a17Rabin Vincent					   HZ);
3697b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	}
3698b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
3699b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones	mutex_unlock(&di->charger_attached_mutex);
3700b269fff4f9ad2cec9413ea9e10f26c5d8c9f5ddcLee Jones
370184edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
370284edbeeab67c1575067335179513150115da367bArun Murthy
370384edbeeab67c1575067335179513150115da367bArun Murthyfree_irq:
3704efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsov	usb_unregister_notifier(di->usb_phy, &di->nb);
370584edbeeab67c1575067335179513150115da367bArun Murthy
370684edbeeab67c1575067335179513150115da367bArun Murthy	/* We also have to free all successfully registered irqs */
370784edbeeab67c1575067335179513150115da367bArun Murthy	for (i = i - 1; i >= 0; i--) {
370884edbeeab67c1575067335179513150115da367bArun Murthy		irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
370984edbeeab67c1575067335179513150115da367bArun Murthy		free_irq(irq, di);
371084edbeeab67c1575067335179513150115da367bArun Murthy	}
3711efd71c89a411d72f1e20d91e34f0779e0e0019b4Anton Vorontsovput_usb_phy:
3712721002ec1dd55a52425455826af49cf8853b2d4fKishon Vijay Abraham I	usb_put_phy(di->usb_phy);
371384edbeeab67c1575067335179513150115da367bArun Murthyfree_usb:
371472a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones	if (di->usb_chg.enabled)
371501ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		power_supply_unregister(&di->usb_chg.psy);
371684edbeeab67c1575067335179513150115da367bArun Murthyfree_ac:
371772a90ddbc3d89a63b769ae1b8538c612cf01e675Lee Jones	if (di->ac_chg.enabled)
371801ec8c5423901c4fe8d97f786ed9a0c31215b53aMichel JAOUEN		power_supply_unregister(&di->ac_chg.psy);
371984edbeeab67c1575067335179513150115da367bArun Murthyfree_charger_wq:
372084edbeeab67c1575067335179513150115da367bArun Murthy	destroy_workqueue(di->charger_wq);
372184edbeeab67c1575067335179513150115da367bArun Murthy	return ret;
372284edbeeab67c1575067335179513150115da367bArun Murthy}
372384edbeeab67c1575067335179513150115da367bArun Murthy
37244aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.Vstatic const struct of_device_id ab8500_charger_match[] = {
37254aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	{ .compatible = "stericsson,ab8500-charger", },
37264aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V	{ },
37274aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V};
37284aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V
372984edbeeab67c1575067335179513150115da367bArun Murthystatic struct platform_driver ab8500_charger_driver = {
373084edbeeab67c1575067335179513150115da367bArun Murthy	.probe = ab8500_charger_probe,
373128ea73f4c67cb3dd8c972b21d9fdf84ea78d6daaBill Pemberton	.remove = ab8500_charger_remove,
373284edbeeab67c1575067335179513150115da367bArun Murthy	.suspend = ab8500_charger_suspend,
373384edbeeab67c1575067335179513150115da367bArun Murthy	.resume = ab8500_charger_resume,
373484edbeeab67c1575067335179513150115da367bArun Murthy	.driver = {
373584edbeeab67c1575067335179513150115da367bArun Murthy		.name = "ab8500-charger",
373684edbeeab67c1575067335179513150115da367bArun Murthy		.owner = THIS_MODULE,
37374aef72dbb2e8997e627dd94ae2b9109dc09fffaaRajanikanth H.V		.of_match_table = ab8500_charger_match,
373884edbeeab67c1575067335179513150115da367bArun Murthy	},
373984edbeeab67c1575067335179513150115da367bArun Murthy};
374084edbeeab67c1575067335179513150115da367bArun Murthy
374184edbeeab67c1575067335179513150115da367bArun Murthystatic int __init ab8500_charger_init(void)
374284edbeeab67c1575067335179513150115da367bArun Murthy{
374384edbeeab67c1575067335179513150115da367bArun Murthy	return platform_driver_register(&ab8500_charger_driver);
374484edbeeab67c1575067335179513150115da367bArun Murthy}
374584edbeeab67c1575067335179513150115da367bArun Murthy
374684edbeeab67c1575067335179513150115da367bArun Murthystatic void __exit ab8500_charger_exit(void)
374784edbeeab67c1575067335179513150115da367bArun Murthy{
374884edbeeab67c1575067335179513150115da367bArun Murthy	platform_driver_unregister(&ab8500_charger_driver);
374984edbeeab67c1575067335179513150115da367bArun Murthy}
375084edbeeab67c1575067335179513150115da367bArun Murthy
375184edbeeab67c1575067335179513150115da367bArun Murthysubsys_initcall_sync(ab8500_charger_init);
375284edbeeab67c1575067335179513150115da367bArun Murthymodule_exit(ab8500_charger_exit);
375384edbeeab67c1575067335179513150115da367bArun Murthy
375484edbeeab67c1575067335179513150115da367bArun MurthyMODULE_LICENSE("GPL v2");
375584edbeeab67c1575067335179513150115da367bArun MurthyMODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
375684edbeeab67c1575067335179513150115da367bArun MurthyMODULE_ALIAS("platform:ab8500-charger");
375784edbeeab67c1575067335179513150115da367bArun MurthyMODULE_DESCRIPTION("AB8500 charger management driver");
3758