18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// extcon-max77693.c - MAX77693 extcon driver to support MAX77693 MUIC
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright (C) 2012 Samsung Electrnoics
68c2ecf20Sopenharmony_ci// Chanwoo Choi <cw00.choi@samsung.com>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/i2c.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci#include <linux/input.h>
138c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
148c2ecf20Sopenharmony_ci#include <linux/err.h>
158c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
168c2ecf20Sopenharmony_ci#include <linux/mfd/max77693.h>
178c2ecf20Sopenharmony_ci#include <linux/mfd/max77693-common.h>
188c2ecf20Sopenharmony_ci#include <linux/mfd/max77693-private.h>
198c2ecf20Sopenharmony_ci#include <linux/extcon-provider.h>
208c2ecf20Sopenharmony_ci#include <linux/regmap.h>
218c2ecf20Sopenharmony_ci#include <linux/irqdomain.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define	DEV_NAME			"max77693-muic"
248c2ecf20Sopenharmony_ci#define	DELAY_MS_DEFAULT		20000		/* unit: millisecond */
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/*
278c2ecf20Sopenharmony_ci * Default value of MAX77693 register to bring up MUIC device.
288c2ecf20Sopenharmony_ci * If user don't set some initial value for MUIC device through platform data,
298c2ecf20Sopenharmony_ci * extcon-max77693 driver use 'default_init_data' to bring up base operation
308c2ecf20Sopenharmony_ci * of MAX77693 MUIC device.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_cistatic struct max77693_reg_data default_init_data[] = {
338c2ecf20Sopenharmony_ci	{
348c2ecf20Sopenharmony_ci		/* STATUS2 - [3]ChgDetRun */
358c2ecf20Sopenharmony_ci		.addr = MAX77693_MUIC_REG_STATUS2,
368c2ecf20Sopenharmony_ci		.data = MAX77693_STATUS2_CHGDETRUN_MASK,
378c2ecf20Sopenharmony_ci	}, {
388c2ecf20Sopenharmony_ci		/* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */
398c2ecf20Sopenharmony_ci		.addr = MAX77693_MUIC_REG_INTMASK1,
408c2ecf20Sopenharmony_ci		.data = INTMASK1_ADC1K_MASK
418c2ecf20Sopenharmony_ci			| INTMASK1_ADC_MASK,
428c2ecf20Sopenharmony_ci	}, {
438c2ecf20Sopenharmony_ci		/* INTMASK2 - Unmask [0]ChgTypM */
448c2ecf20Sopenharmony_ci		.addr = MAX77693_MUIC_REG_INTMASK2,
458c2ecf20Sopenharmony_ci		.data = INTMASK2_CHGTYP_MASK,
468c2ecf20Sopenharmony_ci	}, {
478c2ecf20Sopenharmony_ci		/* INTMASK3 - Mask all of interrupts */
488c2ecf20Sopenharmony_ci		.addr = MAX77693_MUIC_REG_INTMASK3,
498c2ecf20Sopenharmony_ci		.data = 0x0,
508c2ecf20Sopenharmony_ci	}, {
518c2ecf20Sopenharmony_ci		/* CDETCTRL2 */
528c2ecf20Sopenharmony_ci		.addr = MAX77693_MUIC_REG_CDETCTRL2,
538c2ecf20Sopenharmony_ci		.data = CDETCTRL2_VIDRMEN_MASK
548c2ecf20Sopenharmony_ci			| CDETCTRL2_DXOVPEN_MASK,
558c2ecf20Sopenharmony_ci	},
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cienum max77693_muic_adc_debounce_time {
598c2ecf20Sopenharmony_ci	ADC_DEBOUNCE_TIME_5MS = 0,
608c2ecf20Sopenharmony_ci	ADC_DEBOUNCE_TIME_10MS,
618c2ecf20Sopenharmony_ci	ADC_DEBOUNCE_TIME_25MS,
628c2ecf20Sopenharmony_ci	ADC_DEBOUNCE_TIME_38_62MS,
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistruct max77693_muic_info {
668c2ecf20Sopenharmony_ci	struct device *dev;
678c2ecf20Sopenharmony_ci	struct max77693_dev *max77693;
688c2ecf20Sopenharmony_ci	struct extcon_dev *edev;
698c2ecf20Sopenharmony_ci	int prev_cable_type;
708c2ecf20Sopenharmony_ci	int prev_cable_type_gnd;
718c2ecf20Sopenharmony_ci	int prev_chg_type;
728c2ecf20Sopenharmony_ci	int prev_button_type;
738c2ecf20Sopenharmony_ci	u8 status[2];
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	int irq;
768c2ecf20Sopenharmony_ci	struct work_struct irq_work;
778c2ecf20Sopenharmony_ci	struct mutex mutex;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	/*
808c2ecf20Sopenharmony_ci	 * Use delayed workqueue to detect cable state and then
818c2ecf20Sopenharmony_ci	 * notify cable state to notifiee/platform through uevent.
828c2ecf20Sopenharmony_ci	 * After completing the booting of platform, the extcon provider
838c2ecf20Sopenharmony_ci	 * driver should notify cable state to upper layer.
848c2ecf20Sopenharmony_ci	 */
858c2ecf20Sopenharmony_ci	struct delayed_work wq_detcable;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* Button of dock device */
888c2ecf20Sopenharmony_ci	struct input_dev *dock;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	/*
918c2ecf20Sopenharmony_ci	 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
928c2ecf20Sopenharmony_ci	 * h/w path of COMP2/COMN1 on CONTROL1 register.
938c2ecf20Sopenharmony_ci	 */
948c2ecf20Sopenharmony_ci	int path_usb;
958c2ecf20Sopenharmony_ci	int path_uart;
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cienum max77693_muic_cable_group {
998c2ecf20Sopenharmony_ci	MAX77693_CABLE_GROUP_ADC = 0,
1008c2ecf20Sopenharmony_ci	MAX77693_CABLE_GROUP_ADC_GND,
1018c2ecf20Sopenharmony_ci	MAX77693_CABLE_GROUP_CHG,
1028c2ecf20Sopenharmony_ci	MAX77693_CABLE_GROUP_VBVOLT,
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cienum max77693_muic_charger_type {
1068c2ecf20Sopenharmony_ci	MAX77693_CHARGER_TYPE_NONE = 0,
1078c2ecf20Sopenharmony_ci	MAX77693_CHARGER_TYPE_USB,
1088c2ecf20Sopenharmony_ci	MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT,
1098c2ecf20Sopenharmony_ci	MAX77693_CHARGER_TYPE_DEDICATED_CHG,
1108c2ecf20Sopenharmony_ci	MAX77693_CHARGER_TYPE_APPLE_500MA,
1118c2ecf20Sopenharmony_ci	MAX77693_CHARGER_TYPE_APPLE_1A_2A,
1128c2ecf20Sopenharmony_ci	MAX77693_CHARGER_TYPE_DEAD_BATTERY = 7,
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/**
1168c2ecf20Sopenharmony_ci * struct max77693_muic_irq
1178c2ecf20Sopenharmony_ci * @irq: the index of irq list of MUIC device.
1188c2ecf20Sopenharmony_ci * @name: the name of irq.
1198c2ecf20Sopenharmony_ci * @virq: the virtual irq to use irq domain
1208c2ecf20Sopenharmony_ci */
1218c2ecf20Sopenharmony_cistruct max77693_muic_irq {
1228c2ecf20Sopenharmony_ci	unsigned int irq;
1238c2ecf20Sopenharmony_ci	const char *name;
1248c2ecf20Sopenharmony_ci	unsigned int virq;
1258c2ecf20Sopenharmony_ci};
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic struct max77693_muic_irq muic_irqs[] = {
1288c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT1_ADC,		"muic-ADC" },
1298c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT1_ADC_LOW,	"muic-ADCLOW" },
1308c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT1_ADC_ERR,	"muic-ADCError" },
1318c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT1_ADC1K,		"muic-ADC1K" },
1328c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT2_CHGTYP,	"muic-CHGTYP" },
1338c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT2_CHGDETREUN,	"muic-CHGDETREUN" },
1348c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT2_DCDTMR,	"muic-DCDTMR" },
1358c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT2_DXOVP,		"muic-DXOVP" },
1368c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT2_VBVOLT,	"muic-VBVOLT" },
1378c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT2_VIDRM,		"muic-VIDRM" },
1388c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT3_EOC,		"muic-EOC" },
1398c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT3_CGMBC,		"muic-CGMBC" },
1408c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT3_OVP,		"muic-OVP" },
1418c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR,	"muic-MBCCHG_ERR" },
1428c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT3_CHG_ENABLED,	"muic-CHG_ENABLED" },
1438c2ecf20Sopenharmony_ci	{ MAX77693_MUIC_IRQ_INT3_BAT_DET,	"muic-BAT_DET" },
1448c2ecf20Sopenharmony_ci};
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/* Define supported accessory type */
1478c2ecf20Sopenharmony_cienum max77693_muic_acc_type {
1488c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_GROUND = 0x0,
1498c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_SEND_END_BUTTON,
1508c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S1_BUTTON,
1518c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S2_BUTTON,
1528c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S3_BUTTON,
1538c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S4_BUTTON,
1548c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S5_BUTTON,
1558c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S6_BUTTON,
1568c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S7_BUTTON,
1578c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S8_BUTTON,
1588c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S9_BUTTON,
1598c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S10_BUTTON,
1608c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S11_BUTTON,
1618c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_REMOTE_S12_BUTTON,
1628c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_RESERVED_ACC_1,
1638c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_RESERVED_ACC_2,
1648c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_RESERVED_ACC_3,
1658c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_RESERVED_ACC_4,
1668c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_RESERVED_ACC_5,
1678c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_CEA936_AUDIO,
1688c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_PHONE_POWERED_DEV,
1698c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_TTY_CONVERTER,
1708c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_UART_CABLE,
1718c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG,
1728c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF,
1738c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON,
1748c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_AV_CABLE_NOLOAD,
1758c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG,
1768c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF,
1778c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON,
1788c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE,
1798c2ecf20Sopenharmony_ci	MAX77693_MUIC_ADC_OPEN,
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	/*
1828c2ecf20Sopenharmony_ci	 * The below accessories have same ADC value so ADCLow and
1838c2ecf20Sopenharmony_ci	 * ADC1K bit is used to separate specific accessory.
1848c2ecf20Sopenharmony_ci	 */
1858c2ecf20Sopenharmony_ci						/* ADC|VBVolot|ADCLow|ADC1K| */
1868c2ecf20Sopenharmony_ci	MAX77693_MUIC_GND_USB_HOST = 0x100,	/* 0x0|      0|     0|    0| */
1878c2ecf20Sopenharmony_ci	MAX77693_MUIC_GND_USB_HOST_VB = 0x104,	/* 0x0|      1|     0|    0| */
1888c2ecf20Sopenharmony_ci	MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0|      0|     1|    0| */
1898c2ecf20Sopenharmony_ci	MAX77693_MUIC_GND_MHL = 0x103,		/* 0x0|      0|     1|    1| */
1908c2ecf20Sopenharmony_ci	MAX77693_MUIC_GND_MHL_VB = 0x107,	/* 0x0|      1|     1|    1| */
1918c2ecf20Sopenharmony_ci};
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci/*
1948c2ecf20Sopenharmony_ci * MAX77693 MUIC device support below list of accessories(external connector)
1958c2ecf20Sopenharmony_ci */
1968c2ecf20Sopenharmony_cistatic const unsigned int max77693_extcon_cable[] = {
1978c2ecf20Sopenharmony_ci	EXTCON_USB,
1988c2ecf20Sopenharmony_ci	EXTCON_USB_HOST,
1998c2ecf20Sopenharmony_ci	EXTCON_CHG_USB_SDP,
2008c2ecf20Sopenharmony_ci	EXTCON_CHG_USB_DCP,
2018c2ecf20Sopenharmony_ci	EXTCON_CHG_USB_FAST,
2028c2ecf20Sopenharmony_ci	EXTCON_CHG_USB_SLOW,
2038c2ecf20Sopenharmony_ci	EXTCON_CHG_USB_CDP,
2048c2ecf20Sopenharmony_ci	EXTCON_DISP_MHL,
2058c2ecf20Sopenharmony_ci	EXTCON_JIG,
2068c2ecf20Sopenharmony_ci	EXTCON_DOCK,
2078c2ecf20Sopenharmony_ci	EXTCON_NONE,
2088c2ecf20Sopenharmony_ci};
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci/*
2118c2ecf20Sopenharmony_ci * max77693_muic_set_debounce_time - Set the debounce time of ADC
2128c2ecf20Sopenharmony_ci * @info: the instance including private data of max77693 MUIC
2138c2ecf20Sopenharmony_ci * @time: the debounce time of ADC
2148c2ecf20Sopenharmony_ci */
2158c2ecf20Sopenharmony_cistatic int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
2168c2ecf20Sopenharmony_ci		enum max77693_muic_adc_debounce_time time)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	int ret;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	switch (time) {
2218c2ecf20Sopenharmony_ci	case ADC_DEBOUNCE_TIME_5MS:
2228c2ecf20Sopenharmony_ci	case ADC_DEBOUNCE_TIME_10MS:
2238c2ecf20Sopenharmony_ci	case ADC_DEBOUNCE_TIME_25MS:
2248c2ecf20Sopenharmony_ci	case ADC_DEBOUNCE_TIME_38_62MS:
2258c2ecf20Sopenharmony_ci		/*
2268c2ecf20Sopenharmony_ci		 * Don't touch BTLDset, JIGset when you want to change adc
2278c2ecf20Sopenharmony_ci		 * debounce time. If it writes other than 0 to BTLDset, JIGset
2288c2ecf20Sopenharmony_ci		 * muic device will be reset and loose current state.
2298c2ecf20Sopenharmony_ci		 */
2308c2ecf20Sopenharmony_ci		ret = regmap_write(info->max77693->regmap_muic,
2318c2ecf20Sopenharmony_ci				  MAX77693_MUIC_REG_CTRL3,
2328c2ecf20Sopenharmony_ci				  time << MAX77693_CONTROL3_ADCDBSET_SHIFT);
2338c2ecf20Sopenharmony_ci		if (ret) {
2348c2ecf20Sopenharmony_ci			dev_err(info->dev, "failed to set ADC debounce time\n");
2358c2ecf20Sopenharmony_ci			return ret;
2368c2ecf20Sopenharmony_ci		}
2378c2ecf20Sopenharmony_ci		break;
2388c2ecf20Sopenharmony_ci	default:
2398c2ecf20Sopenharmony_ci		dev_err(info->dev, "invalid ADC debounce time\n");
2408c2ecf20Sopenharmony_ci		return -EINVAL;
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	return 0;
2448c2ecf20Sopenharmony_ci};
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci/*
2478c2ecf20Sopenharmony_ci * max77693_muic_set_path - Set hardware line according to attached cable
2488c2ecf20Sopenharmony_ci * @info: the instance including private data of max77693 MUIC
2498c2ecf20Sopenharmony_ci * @value: the path according to attached cable
2508c2ecf20Sopenharmony_ci * @attached: the state of cable (true:attached, false:detached)
2518c2ecf20Sopenharmony_ci *
2528c2ecf20Sopenharmony_ci * The max77693 MUIC device share outside H/W line among a varity of cables
2538c2ecf20Sopenharmony_ci * so, this function set internal path of H/W line according to the type of
2548c2ecf20Sopenharmony_ci * attached cable.
2558c2ecf20Sopenharmony_ci */
2568c2ecf20Sopenharmony_cistatic int max77693_muic_set_path(struct max77693_muic_info *info,
2578c2ecf20Sopenharmony_ci		u8 val, bool attached)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	int ret;
2608c2ecf20Sopenharmony_ci	unsigned int ctrl1, ctrl2 = 0;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	if (attached)
2638c2ecf20Sopenharmony_ci		ctrl1 = val;
2648c2ecf20Sopenharmony_ci	else
2658c2ecf20Sopenharmony_ci		ctrl1 = MAX77693_CONTROL1_SW_OPEN;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	ret = regmap_update_bits(info->max77693->regmap_muic,
2688c2ecf20Sopenharmony_ci			MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1);
2698c2ecf20Sopenharmony_ci	if (ret < 0) {
2708c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to update MUIC register\n");
2718c2ecf20Sopenharmony_ci		return ret;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	if (attached)
2758c2ecf20Sopenharmony_ci		ctrl2 |= MAX77693_CONTROL2_CPEN_MASK;	/* LowPwr=0, CPEn=1 */
2768c2ecf20Sopenharmony_ci	else
2778c2ecf20Sopenharmony_ci		ctrl2 |= MAX77693_CONTROL2_LOWPWR_MASK;	/* LowPwr=1, CPEn=0 */
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	ret = regmap_update_bits(info->max77693->regmap_muic,
2808c2ecf20Sopenharmony_ci			MAX77693_MUIC_REG_CTRL2,
2818c2ecf20Sopenharmony_ci			MAX77693_CONTROL2_LOWPWR_MASK | MAX77693_CONTROL2_CPEN_MASK,
2828c2ecf20Sopenharmony_ci			ctrl2);
2838c2ecf20Sopenharmony_ci	if (ret < 0) {
2848c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to update MUIC register\n");
2858c2ecf20Sopenharmony_ci		return ret;
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	dev_info(info->dev,
2898c2ecf20Sopenharmony_ci		"CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
2908c2ecf20Sopenharmony_ci		ctrl1, ctrl2, attached ? "attached" : "detached");
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	return 0;
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci/*
2968c2ecf20Sopenharmony_ci * max77693_muic_get_cable_type - Return cable type and check cable state
2978c2ecf20Sopenharmony_ci * @info: the instance including private data of max77693 MUIC
2988c2ecf20Sopenharmony_ci * @group: the path according to attached cable
2998c2ecf20Sopenharmony_ci * @attached: store cable state and return
3008c2ecf20Sopenharmony_ci *
3018c2ecf20Sopenharmony_ci * This function check the cable state either attached or detached,
3028c2ecf20Sopenharmony_ci * and then divide precise type of cable according to cable group.
3038c2ecf20Sopenharmony_ci *	- MAX77693_CABLE_GROUP_ADC
3048c2ecf20Sopenharmony_ci *	- MAX77693_CABLE_GROUP_ADC_GND
3058c2ecf20Sopenharmony_ci *	- MAX77693_CABLE_GROUP_CHG
3068c2ecf20Sopenharmony_ci *	- MAX77693_CABLE_GROUP_VBVOLT
3078c2ecf20Sopenharmony_ci */
3088c2ecf20Sopenharmony_cistatic int max77693_muic_get_cable_type(struct max77693_muic_info *info,
3098c2ecf20Sopenharmony_ci		enum max77693_muic_cable_group group, bool *attached)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	int cable_type = 0;
3128c2ecf20Sopenharmony_ci	int adc;
3138c2ecf20Sopenharmony_ci	int adc1k;
3148c2ecf20Sopenharmony_ci	int adclow;
3158c2ecf20Sopenharmony_ci	int vbvolt;
3168c2ecf20Sopenharmony_ci	int chg_type;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	switch (group) {
3198c2ecf20Sopenharmony_ci	case MAX77693_CABLE_GROUP_ADC:
3208c2ecf20Sopenharmony_ci		/*
3218c2ecf20Sopenharmony_ci		 * Read ADC value to check cable type and decide cable state
3228c2ecf20Sopenharmony_ci		 * according to cable type
3238c2ecf20Sopenharmony_ci		 */
3248c2ecf20Sopenharmony_ci		adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;
3258c2ecf20Sopenharmony_ci		adc >>= MAX77693_STATUS1_ADC_SHIFT;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci		/*
3288c2ecf20Sopenharmony_ci		 * Check current cable state/cable type and store cable type
3298c2ecf20Sopenharmony_ci		 * (info->prev_cable_type) for handling cable when cable is
3308c2ecf20Sopenharmony_ci		 * detached.
3318c2ecf20Sopenharmony_ci		 */
3328c2ecf20Sopenharmony_ci		if (adc == MAX77693_MUIC_ADC_OPEN) {
3338c2ecf20Sopenharmony_ci			*attached = false;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci			cable_type = info->prev_cable_type;
3368c2ecf20Sopenharmony_ci			info->prev_cable_type = MAX77693_MUIC_ADC_OPEN;
3378c2ecf20Sopenharmony_ci		} else {
3388c2ecf20Sopenharmony_ci			*attached = true;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci			cable_type = info->prev_cable_type = adc;
3418c2ecf20Sopenharmony_ci		}
3428c2ecf20Sopenharmony_ci		break;
3438c2ecf20Sopenharmony_ci	case MAX77693_CABLE_GROUP_ADC_GND:
3448c2ecf20Sopenharmony_ci		/*
3458c2ecf20Sopenharmony_ci		 * Read ADC value to check cable type and decide cable state
3468c2ecf20Sopenharmony_ci		 * according to cable type
3478c2ecf20Sopenharmony_ci		 */
3488c2ecf20Sopenharmony_ci		adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;
3498c2ecf20Sopenharmony_ci		adc >>= MAX77693_STATUS1_ADC_SHIFT;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci		/*
3528c2ecf20Sopenharmony_ci		 * Check current cable state/cable type and store cable type
3538c2ecf20Sopenharmony_ci		 * (info->prev_cable_type/_gnd) for handling cable when cable
3548c2ecf20Sopenharmony_ci		 * is detached.
3558c2ecf20Sopenharmony_ci		 */
3568c2ecf20Sopenharmony_ci		if (adc == MAX77693_MUIC_ADC_OPEN) {
3578c2ecf20Sopenharmony_ci			*attached = false;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci			cable_type = info->prev_cable_type_gnd;
3608c2ecf20Sopenharmony_ci			info->prev_cable_type_gnd = MAX77693_MUIC_ADC_OPEN;
3618c2ecf20Sopenharmony_ci		} else {
3628c2ecf20Sopenharmony_ci			*attached = true;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci			adclow = info->status[0] & MAX77693_STATUS1_ADCLOW_MASK;
3658c2ecf20Sopenharmony_ci			adclow >>= MAX77693_STATUS1_ADCLOW_SHIFT;
3668c2ecf20Sopenharmony_ci			adc1k = info->status[0] & MAX77693_STATUS1_ADC1K_MASK;
3678c2ecf20Sopenharmony_ci			adc1k >>= MAX77693_STATUS1_ADC1K_SHIFT;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci			vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK;
3708c2ecf20Sopenharmony_ci			vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci			/**
3738c2ecf20Sopenharmony_ci			 * [0x1|VBVolt|ADCLow|ADC1K]
3748c2ecf20Sopenharmony_ci			 * [0x1|     0|     0|    0] USB_HOST
3758c2ecf20Sopenharmony_ci			 * [0x1|     1|     0|    0] USB_HSOT_VB
3768c2ecf20Sopenharmony_ci			 * [0x1|     0|     1|    0] Audio Video cable with load
3778c2ecf20Sopenharmony_ci			 * [0x1|     0|     1|    1] MHL without charging cable
3788c2ecf20Sopenharmony_ci			 * [0x1|     1|     1|    1] MHL with charging cable
3798c2ecf20Sopenharmony_ci			 */
3808c2ecf20Sopenharmony_ci			cable_type = ((0x1 << 8)
3818c2ecf20Sopenharmony_ci					| (vbvolt << 2)
3828c2ecf20Sopenharmony_ci					| (adclow << 1)
3838c2ecf20Sopenharmony_ci					| adc1k);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci			info->prev_cable_type = adc;
3868c2ecf20Sopenharmony_ci			info->prev_cable_type_gnd = cable_type;
3878c2ecf20Sopenharmony_ci		}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		break;
3908c2ecf20Sopenharmony_ci	case MAX77693_CABLE_GROUP_CHG:
3918c2ecf20Sopenharmony_ci		/*
3928c2ecf20Sopenharmony_ci		 * Read charger type to check cable type and decide cable state
3938c2ecf20Sopenharmony_ci		 * according to type of charger cable.
3948c2ecf20Sopenharmony_ci		 */
3958c2ecf20Sopenharmony_ci		chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK;
3968c2ecf20Sopenharmony_ci		chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci		if (chg_type == MAX77693_CHARGER_TYPE_NONE) {
3998c2ecf20Sopenharmony_ci			*attached = false;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci			cable_type = info->prev_chg_type;
4028c2ecf20Sopenharmony_ci			info->prev_chg_type = MAX77693_CHARGER_TYPE_NONE;
4038c2ecf20Sopenharmony_ci		} else {
4048c2ecf20Sopenharmony_ci			*attached = true;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci			/*
4078c2ecf20Sopenharmony_ci			 * Check current cable state/cable type and store cable
4088c2ecf20Sopenharmony_ci			 * type(info->prev_chg_type) for handling cable when
4098c2ecf20Sopenharmony_ci			 * charger cable is detached.
4108c2ecf20Sopenharmony_ci			 */
4118c2ecf20Sopenharmony_ci			cable_type = info->prev_chg_type = chg_type;
4128c2ecf20Sopenharmony_ci		}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci		break;
4158c2ecf20Sopenharmony_ci	case MAX77693_CABLE_GROUP_VBVOLT:
4168c2ecf20Sopenharmony_ci		/*
4178c2ecf20Sopenharmony_ci		 * Read ADC value to check cable type and decide cable state
4188c2ecf20Sopenharmony_ci		 * according to cable type
4198c2ecf20Sopenharmony_ci		 */
4208c2ecf20Sopenharmony_ci		adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;
4218c2ecf20Sopenharmony_ci		adc >>= MAX77693_STATUS1_ADC_SHIFT;
4228c2ecf20Sopenharmony_ci		chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK;
4238c2ecf20Sopenharmony_ci		chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci		if (adc == MAX77693_MUIC_ADC_OPEN
4268c2ecf20Sopenharmony_ci				&& chg_type == MAX77693_CHARGER_TYPE_NONE)
4278c2ecf20Sopenharmony_ci			*attached = false;
4288c2ecf20Sopenharmony_ci		else
4298c2ecf20Sopenharmony_ci			*attached = true;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci		/*
4328c2ecf20Sopenharmony_ci		 * Read vbvolt field, if vbvolt is 1,
4338c2ecf20Sopenharmony_ci		 * this cable is used for charging.
4348c2ecf20Sopenharmony_ci		 */
4358c2ecf20Sopenharmony_ci		vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK;
4368c2ecf20Sopenharmony_ci		vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci		cable_type = vbvolt;
4398c2ecf20Sopenharmony_ci		break;
4408c2ecf20Sopenharmony_ci	default:
4418c2ecf20Sopenharmony_ci		dev_err(info->dev, "Unknown cable group (%d)\n", group);
4428c2ecf20Sopenharmony_ci		cable_type = -EINVAL;
4438c2ecf20Sopenharmony_ci		break;
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	return cable_type;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic int max77693_muic_dock_handler(struct max77693_muic_info *info,
4508c2ecf20Sopenharmony_ci		int cable_type, bool attached)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	int ret = 0;
4538c2ecf20Sopenharmony_ci	int vbvolt;
4548c2ecf20Sopenharmony_ci	bool cable_attached;
4558c2ecf20Sopenharmony_ci	unsigned int dock_id;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	dev_info(info->dev,
4588c2ecf20Sopenharmony_ci		"external connector is %s (adc:0x%02x)\n",
4598c2ecf20Sopenharmony_ci		attached ? "attached" : "detached", cable_type);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	switch (cable_type) {
4628c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_RESERVED_ACC_3:		/* Dock-Smart */
4638c2ecf20Sopenharmony_ci		/*
4648c2ecf20Sopenharmony_ci		 * Check power cable whether attached or detached state.
4658c2ecf20Sopenharmony_ci		 * The Dock-Smart device need surely external power supply.
4668c2ecf20Sopenharmony_ci		 * If power cable(USB/TA) isn't connected to Dock device,
4678c2ecf20Sopenharmony_ci		 * user can't use Dock-Smart for desktop mode.
4688c2ecf20Sopenharmony_ci		 */
4698c2ecf20Sopenharmony_ci		vbvolt = max77693_muic_get_cable_type(info,
4708c2ecf20Sopenharmony_ci				MAX77693_CABLE_GROUP_VBVOLT, &cable_attached);
4718c2ecf20Sopenharmony_ci		if (attached && !vbvolt) {
4728c2ecf20Sopenharmony_ci			dev_warn(info->dev,
4738c2ecf20Sopenharmony_ci				"Cannot detect external power supply\n");
4748c2ecf20Sopenharmony_ci			return 0;
4758c2ecf20Sopenharmony_ci		}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		/*
4788c2ecf20Sopenharmony_ci		 * Notify Dock/MHL state.
4798c2ecf20Sopenharmony_ci		 * - Dock device include three type of cable which
4808c2ecf20Sopenharmony_ci		 * are HDMI, USB for mouse/keyboard and micro-usb port
4818c2ecf20Sopenharmony_ci		 * for USB/TA cable. Dock device need always exteranl
4828c2ecf20Sopenharmony_ci		 * power supply(USB/TA cable through micro-usb cable). Dock
4838c2ecf20Sopenharmony_ci		 * device support screen output of target to separate
4848c2ecf20Sopenharmony_ci		 * monitor and mouse/keyboard for desktop mode.
4858c2ecf20Sopenharmony_ci		 *
4868c2ecf20Sopenharmony_ci		 * Features of 'USB/TA cable with Dock device'
4878c2ecf20Sopenharmony_ci		 * - Support MHL
4888c2ecf20Sopenharmony_ci		 * - Support external output feature of audio
4898c2ecf20Sopenharmony_ci		 * - Support charging through micro-usb port without data
4908c2ecf20Sopenharmony_ci		 *	     connection if TA cable is connected to target.
4918c2ecf20Sopenharmony_ci		 * - Support charging and data connection through micro-usb port
4928c2ecf20Sopenharmony_ci		 *           if USB cable is connected between target and host
4938c2ecf20Sopenharmony_ci		 *	     device.
4948c2ecf20Sopenharmony_ci		 * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
4958c2ecf20Sopenharmony_ci		 */
4968c2ecf20Sopenharmony_ci		ret = max77693_muic_set_path(info, info->path_usb, attached);
4978c2ecf20Sopenharmony_ci		if (ret < 0)
4988c2ecf20Sopenharmony_ci			return ret;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);
5018c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
5028c2ecf20Sopenharmony_ci		goto out;
5038c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE:	/* Dock-Desk */
5048c2ecf20Sopenharmony_ci		dock_id = EXTCON_DOCK;
5058c2ecf20Sopenharmony_ci		break;
5068c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD:		/* Dock-Audio */
5078c2ecf20Sopenharmony_ci		dock_id = EXTCON_DOCK;
5088c2ecf20Sopenharmony_ci		if (!attached) {
5098c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_USB, false);
5108c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
5118c2ecf20Sopenharmony_ci						false);
5128c2ecf20Sopenharmony_ci		}
5138c2ecf20Sopenharmony_ci		break;
5148c2ecf20Sopenharmony_ci	default:
5158c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to detect %s dock device\n",
5168c2ecf20Sopenharmony_ci			attached ? "attached" : "detached");
5178c2ecf20Sopenharmony_ci		return -EINVAL;
5188c2ecf20Sopenharmony_ci	}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	/* Dock-Car/Desk/Audio, PATH:AUDIO */
5218c2ecf20Sopenharmony_ci	ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO,
5228c2ecf20Sopenharmony_ci					attached);
5238c2ecf20Sopenharmony_ci	if (ret < 0)
5248c2ecf20Sopenharmony_ci		return ret;
5258c2ecf20Sopenharmony_ci	extcon_set_state_sync(info->edev, dock_id, attached);
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ciout:
5288c2ecf20Sopenharmony_ci	return 0;
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_cistatic int max77693_muic_dock_button_handler(struct max77693_muic_info *info,
5328c2ecf20Sopenharmony_ci		int button_type, bool attached)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	struct input_dev *dock = info->dock;
5358c2ecf20Sopenharmony_ci	unsigned int code;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	switch (button_type) {
5388c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON-1
5398c2ecf20Sopenharmony_ci		... MAX77693_MUIC_ADC_REMOTE_S3_BUTTON+1:
5408c2ecf20Sopenharmony_ci		/* DOCK_KEY_PREV */
5418c2ecf20Sopenharmony_ci		code = KEY_PREVIOUSSONG;
5428c2ecf20Sopenharmony_ci		break;
5438c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON-1
5448c2ecf20Sopenharmony_ci		... MAX77693_MUIC_ADC_REMOTE_S7_BUTTON+1:
5458c2ecf20Sopenharmony_ci		/* DOCK_KEY_NEXT */
5468c2ecf20Sopenharmony_ci		code = KEY_NEXTSONG;
5478c2ecf20Sopenharmony_ci		break;
5488c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON:
5498c2ecf20Sopenharmony_ci		/* DOCK_VOL_DOWN */
5508c2ecf20Sopenharmony_ci		code = KEY_VOLUMEDOWN;
5518c2ecf20Sopenharmony_ci		break;
5528c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON:
5538c2ecf20Sopenharmony_ci		/* DOCK_VOL_UP */
5548c2ecf20Sopenharmony_ci		code = KEY_VOLUMEUP;
5558c2ecf20Sopenharmony_ci		break;
5568c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON-1
5578c2ecf20Sopenharmony_ci		... MAX77693_MUIC_ADC_REMOTE_S12_BUTTON+1:
5588c2ecf20Sopenharmony_ci		/* DOCK_KEY_PLAY_PAUSE */
5598c2ecf20Sopenharmony_ci		code = KEY_PLAYPAUSE;
5608c2ecf20Sopenharmony_ci		break;
5618c2ecf20Sopenharmony_ci	default:
5628c2ecf20Sopenharmony_ci		dev_err(info->dev,
5638c2ecf20Sopenharmony_ci			"failed to detect %s key (adc:0x%x)\n",
5648c2ecf20Sopenharmony_ci			attached ? "pressed" : "released", button_type);
5658c2ecf20Sopenharmony_ci		return -EINVAL;
5668c2ecf20Sopenharmony_ci	}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	input_event(dock, EV_KEY, code, attached);
5698c2ecf20Sopenharmony_ci	input_sync(dock);
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	return 0;
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	int cable_type_gnd;
5778c2ecf20Sopenharmony_ci	int ret = 0;
5788c2ecf20Sopenharmony_ci	bool attached;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	cable_type_gnd = max77693_muic_get_cable_type(info,
5818c2ecf20Sopenharmony_ci				MAX77693_CABLE_GROUP_ADC_GND, &attached);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	switch (cable_type_gnd) {
5848c2ecf20Sopenharmony_ci	case MAX77693_MUIC_GND_USB_HOST:
5858c2ecf20Sopenharmony_ci	case MAX77693_MUIC_GND_USB_HOST_VB:
5868c2ecf20Sopenharmony_ci		/* USB_HOST, PATH: AP_USB */
5878c2ecf20Sopenharmony_ci		ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_USB,
5888c2ecf20Sopenharmony_ci						attached);
5898c2ecf20Sopenharmony_ci		if (ret < 0)
5908c2ecf20Sopenharmony_ci			return ret;
5918c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
5928c2ecf20Sopenharmony_ci		break;
5938c2ecf20Sopenharmony_ci	case MAX77693_MUIC_GND_AV_CABLE_LOAD:
5948c2ecf20Sopenharmony_ci		/* Audio Video Cable with load, PATH:AUDIO */
5958c2ecf20Sopenharmony_ci		ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO,
5968c2ecf20Sopenharmony_ci						attached);
5978c2ecf20Sopenharmony_ci		if (ret < 0)
5988c2ecf20Sopenharmony_ci			return ret;
5998c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_USB, attached);
6008c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
6018c2ecf20Sopenharmony_ci					attached);
6028c2ecf20Sopenharmony_ci		break;
6038c2ecf20Sopenharmony_ci	case MAX77693_MUIC_GND_MHL:
6048c2ecf20Sopenharmony_ci	case MAX77693_MUIC_GND_MHL_VB:
6058c2ecf20Sopenharmony_ci		/* MHL or MHL with USB/TA cable */
6068c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
6078c2ecf20Sopenharmony_ci		break;
6088c2ecf20Sopenharmony_ci	default:
6098c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to detect %s cable of gnd type\n",
6108c2ecf20Sopenharmony_ci			attached ? "attached" : "detached");
6118c2ecf20Sopenharmony_ci		return -EINVAL;
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	return 0;
6158c2ecf20Sopenharmony_ci}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_cistatic int max77693_muic_jig_handler(struct max77693_muic_info *info,
6188c2ecf20Sopenharmony_ci		int cable_type, bool attached)
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	int ret = 0;
6218c2ecf20Sopenharmony_ci	u8 path = MAX77693_CONTROL1_SW_OPEN;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	dev_info(info->dev,
6248c2ecf20Sopenharmony_ci		"external connector is %s (adc:0x%02x)\n",
6258c2ecf20Sopenharmony_ci		attached ? "attached" : "detached", cable_type);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	switch (cable_type) {
6288c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:	/* ADC_JIG_USB_OFF */
6298c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON:	/* ADC_JIG_USB_ON */
6308c2ecf20Sopenharmony_ci		/* PATH:AP_USB */
6318c2ecf20Sopenharmony_ci		path = MAX77693_CONTROL1_SW_USB;
6328c2ecf20Sopenharmony_ci		break;
6338c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF:	/* ADC_JIG_UART_OFF */
6348c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON:	/* ADC_JIG_UART_ON */
6358c2ecf20Sopenharmony_ci		/* PATH:AP_UART */
6368c2ecf20Sopenharmony_ci		path = MAX77693_CONTROL1_SW_UART;
6378c2ecf20Sopenharmony_ci		break;
6388c2ecf20Sopenharmony_ci	default:
6398c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to detect %s jig cable\n",
6408c2ecf20Sopenharmony_ci			attached ? "attached" : "detached");
6418c2ecf20Sopenharmony_ci		return -EINVAL;
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	ret = max77693_muic_set_path(info, path, attached);
6458c2ecf20Sopenharmony_ci	if (ret < 0)
6468c2ecf20Sopenharmony_ci		return ret;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	extcon_set_state_sync(info->edev, EXTCON_JIG, attached);
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	return 0;
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic int max77693_muic_adc_handler(struct max77693_muic_info *info)
6548c2ecf20Sopenharmony_ci{
6558c2ecf20Sopenharmony_ci	int cable_type;
6568c2ecf20Sopenharmony_ci	int button_type;
6578c2ecf20Sopenharmony_ci	bool attached;
6588c2ecf20Sopenharmony_ci	int ret = 0;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	/* Check accessory state which is either detached or attached */
6618c2ecf20Sopenharmony_ci	cable_type = max77693_muic_get_cable_type(info,
6628c2ecf20Sopenharmony_ci				MAX77693_CABLE_GROUP_ADC, &attached);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	dev_info(info->dev,
6658c2ecf20Sopenharmony_ci		"external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
6668c2ecf20Sopenharmony_ci		attached ? "attached" : "detached", cable_type,
6678c2ecf20Sopenharmony_ci		info->prev_cable_type);
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	switch (cable_type) {
6708c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_GROUND:
6718c2ecf20Sopenharmony_ci		/* USB_HOST/MHL/Audio */
6728c2ecf20Sopenharmony_ci		max77693_muic_adc_ground_handler(info);
6738c2ecf20Sopenharmony_ci		break;
6748c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:
6758c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON:
6768c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF:
6778c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON:
6788c2ecf20Sopenharmony_ci		/* JIG */
6798c2ecf20Sopenharmony_ci		ret = max77693_muic_jig_handler(info, cable_type, attached);
6808c2ecf20Sopenharmony_ci		if (ret < 0)
6818c2ecf20Sopenharmony_ci			return ret;
6828c2ecf20Sopenharmony_ci		break;
6838c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_RESERVED_ACC_3:		/* Dock-Smart */
6848c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE:	/* Dock-Desk */
6858c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD:		/* Dock-Audio */
6868c2ecf20Sopenharmony_ci		/*
6878c2ecf20Sopenharmony_ci		 * DOCK device
6888c2ecf20Sopenharmony_ci		 *
6898c2ecf20Sopenharmony_ci		 * The MAX77693 MUIC device can detect total 34 cable type
6908c2ecf20Sopenharmony_ci		 * except of charger cable and MUIC device didn't define
6918c2ecf20Sopenharmony_ci		 * specfic role of cable in the range of from 0x01 to 0x12
6928c2ecf20Sopenharmony_ci		 * of ADC value. So, can use/define cable with no role according
6938c2ecf20Sopenharmony_ci		 * to schema of hardware board.
6948c2ecf20Sopenharmony_ci		 */
6958c2ecf20Sopenharmony_ci		ret = max77693_muic_dock_handler(info, cable_type, attached);
6968c2ecf20Sopenharmony_ci		if (ret < 0)
6978c2ecf20Sopenharmony_ci			return ret;
6988c2ecf20Sopenharmony_ci		break;
6998c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON:      /* DOCK_KEY_PREV */
7008c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON:      /* DOCK_KEY_NEXT */
7018c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON:      /* DOCK_VOL_DOWN */
7028c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON:     /* DOCK_VOL_UP */
7038c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON:     /* DOCK_KEY_PLAY_PAUSE */
7048c2ecf20Sopenharmony_ci		/*
7058c2ecf20Sopenharmony_ci		 * Button of DOCK device
7068c2ecf20Sopenharmony_ci		 * - the Prev/Next/Volume Up/Volume Down/Play-Pause button
7078c2ecf20Sopenharmony_ci		 *
7088c2ecf20Sopenharmony_ci		 * The MAX77693 MUIC device can detect total 34 cable type
7098c2ecf20Sopenharmony_ci		 * except of charger cable and MUIC device didn't define
7108c2ecf20Sopenharmony_ci		 * specfic role of cable in the range of from 0x01 to 0x12
7118c2ecf20Sopenharmony_ci		 * of ADC value. So, can use/define cable with no role according
7128c2ecf20Sopenharmony_ci		 * to schema of hardware board.
7138c2ecf20Sopenharmony_ci		 */
7148c2ecf20Sopenharmony_ci		if (attached)
7158c2ecf20Sopenharmony_ci			button_type = info->prev_button_type = cable_type;
7168c2ecf20Sopenharmony_ci		else
7178c2ecf20Sopenharmony_ci			button_type = info->prev_button_type;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci		ret = max77693_muic_dock_button_handler(info, button_type,
7208c2ecf20Sopenharmony_ci							attached);
7218c2ecf20Sopenharmony_ci		if (ret < 0)
7228c2ecf20Sopenharmony_ci			return ret;
7238c2ecf20Sopenharmony_ci		break;
7248c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_SEND_END_BUTTON:
7258c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S1_BUTTON:
7268c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S2_BUTTON:
7278c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S4_BUTTON:
7288c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S5_BUTTON:
7298c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S6_BUTTON:
7308c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S8_BUTTON:
7318c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_REMOTE_S11_BUTTON:
7328c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_RESERVED_ACC_1:
7338c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_RESERVED_ACC_2:
7348c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_RESERVED_ACC_4:
7358c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_RESERVED_ACC_5:
7368c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_CEA936_AUDIO:
7378c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_PHONE_POWERED_DEV:
7388c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_TTY_CONVERTER:
7398c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_UART_CABLE:
7408c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG:
7418c2ecf20Sopenharmony_ci	case MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG:
7428c2ecf20Sopenharmony_ci		/*
7438c2ecf20Sopenharmony_ci		 * This accessory isn't used in general case if it is specially
7448c2ecf20Sopenharmony_ci		 * needed to detect additional accessory, should implement
7458c2ecf20Sopenharmony_ci		 * proper operation when this accessory is attached/detached.
7468c2ecf20Sopenharmony_ci		 */
7478c2ecf20Sopenharmony_ci		dev_info(info->dev,
7488c2ecf20Sopenharmony_ci			"accessory is %s but it isn't used (adc:0x%x)\n",
7498c2ecf20Sopenharmony_ci			attached ? "attached" : "detached", cable_type);
7508c2ecf20Sopenharmony_ci		return -EAGAIN;
7518c2ecf20Sopenharmony_ci	default:
7528c2ecf20Sopenharmony_ci		dev_err(info->dev,
7538c2ecf20Sopenharmony_ci			"failed to detect %s accessory (adc:0x%x)\n",
7548c2ecf20Sopenharmony_ci			attached ? "attached" : "detached", cable_type);
7558c2ecf20Sopenharmony_ci		return -EINVAL;
7568c2ecf20Sopenharmony_ci	}
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	return 0;
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_cistatic int max77693_muic_chg_handler(struct max77693_muic_info *info)
7628c2ecf20Sopenharmony_ci{
7638c2ecf20Sopenharmony_ci	int chg_type;
7648c2ecf20Sopenharmony_ci	int cable_type_gnd;
7658c2ecf20Sopenharmony_ci	int cable_type;
7668c2ecf20Sopenharmony_ci	bool attached;
7678c2ecf20Sopenharmony_ci	bool cable_attached;
7688c2ecf20Sopenharmony_ci	int ret = 0;
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	chg_type = max77693_muic_get_cable_type(info,
7718c2ecf20Sopenharmony_ci				MAX77693_CABLE_GROUP_CHG, &attached);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	dev_info(info->dev,
7748c2ecf20Sopenharmony_ci		"external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
7758c2ecf20Sopenharmony_ci			attached ? "attached" : "detached",
7768c2ecf20Sopenharmony_ci			chg_type, info->prev_chg_type);
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	switch (chg_type) {
7798c2ecf20Sopenharmony_ci	case MAX77693_CHARGER_TYPE_USB:
7808c2ecf20Sopenharmony_ci	case MAX77693_CHARGER_TYPE_DEDICATED_CHG:
7818c2ecf20Sopenharmony_ci	case MAX77693_CHARGER_TYPE_NONE:
7828c2ecf20Sopenharmony_ci		/* Check MAX77693_CABLE_GROUP_ADC_GND type */
7838c2ecf20Sopenharmony_ci		cable_type_gnd = max77693_muic_get_cable_type(info,
7848c2ecf20Sopenharmony_ci					MAX77693_CABLE_GROUP_ADC_GND,
7858c2ecf20Sopenharmony_ci					&cable_attached);
7868c2ecf20Sopenharmony_ci		switch (cable_type_gnd) {
7878c2ecf20Sopenharmony_ci		case MAX77693_MUIC_GND_MHL:
7888c2ecf20Sopenharmony_ci		case MAX77693_MUIC_GND_MHL_VB:
7898c2ecf20Sopenharmony_ci			/*
7908c2ecf20Sopenharmony_ci			 * MHL cable with USB/TA cable
7918c2ecf20Sopenharmony_ci			 * - MHL cable include two port(HDMI line and separate
7928c2ecf20Sopenharmony_ci			 * micro-usb port. When the target connect MHL cable,
7938c2ecf20Sopenharmony_ci			 * extcon driver check whether USB/TA cable is
7948c2ecf20Sopenharmony_ci			 * connected. If USB/TA cable is connected, extcon
7958c2ecf20Sopenharmony_ci			 * driver notify state to notifiee for charging battery.
7968c2ecf20Sopenharmony_ci			 *
7978c2ecf20Sopenharmony_ci			 * Features of 'USB/TA with MHL cable'
7988c2ecf20Sopenharmony_ci			 * - Support MHL
7998c2ecf20Sopenharmony_ci			 * - Support charging through micro-usb port without
8008c2ecf20Sopenharmony_ci			 *   data connection
8018c2ecf20Sopenharmony_ci			 */
8028c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
8038c2ecf20Sopenharmony_ci						attached);
8048c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_DISP_MHL,
8058c2ecf20Sopenharmony_ci						cable_attached);
8068c2ecf20Sopenharmony_ci			break;
8078c2ecf20Sopenharmony_ci		}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci		/* Check MAX77693_CABLE_GROUP_ADC type */
8108c2ecf20Sopenharmony_ci		cable_type = max77693_muic_get_cable_type(info,
8118c2ecf20Sopenharmony_ci					MAX77693_CABLE_GROUP_ADC,
8128c2ecf20Sopenharmony_ci					&cable_attached);
8138c2ecf20Sopenharmony_ci		switch (cable_type) {
8148c2ecf20Sopenharmony_ci		case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD:		/* Dock-Audio */
8158c2ecf20Sopenharmony_ci			/*
8168c2ecf20Sopenharmony_ci			 * Dock-Audio device with USB/TA cable
8178c2ecf20Sopenharmony_ci			 * - Dock device include two port(Dock-Audio and micro-
8188c2ecf20Sopenharmony_ci			 * usb port). When the target connect Dock-Audio device,
8198c2ecf20Sopenharmony_ci			 * extcon driver check whether USB/TA cable is connected
8208c2ecf20Sopenharmony_ci			 * or not. If USB/TA cable is connected, extcon driver
8218c2ecf20Sopenharmony_ci			 * notify state to notifiee for charging battery.
8228c2ecf20Sopenharmony_ci			 *
8238c2ecf20Sopenharmony_ci			 * Features of 'USB/TA cable with Dock-Audio device'
8248c2ecf20Sopenharmony_ci			 * - Support external output feature of audio.
8258c2ecf20Sopenharmony_ci			 * - Support charging through micro-usb port without
8268c2ecf20Sopenharmony_ci			 *   data connection.
8278c2ecf20Sopenharmony_ci			 */
8288c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_USB,
8298c2ecf20Sopenharmony_ci						attached);
8308c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
8318c2ecf20Sopenharmony_ci						attached);
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci			if (!cable_attached)
8348c2ecf20Sopenharmony_ci				extcon_set_state_sync(info->edev, EXTCON_DOCK,
8358c2ecf20Sopenharmony_ci							cable_attached);
8368c2ecf20Sopenharmony_ci			break;
8378c2ecf20Sopenharmony_ci		case MAX77693_MUIC_ADC_RESERVED_ACC_3:		/* Dock-Smart */
8388c2ecf20Sopenharmony_ci			/*
8398c2ecf20Sopenharmony_ci			 * Dock-Smart device with USB/TA cable
8408c2ecf20Sopenharmony_ci			 * - Dock-Desk device include three type of cable which
8418c2ecf20Sopenharmony_ci			 * are HDMI, USB for mouse/keyboard and micro-usb port
8428c2ecf20Sopenharmony_ci			 * for USB/TA cable. Dock-Smart device need always
8438c2ecf20Sopenharmony_ci			 * exteranl power supply(USB/TA cable through micro-usb
8448c2ecf20Sopenharmony_ci			 * cable). Dock-Smart device support screen output of
8458c2ecf20Sopenharmony_ci			 * target to separate monitor and mouse/keyboard for
8468c2ecf20Sopenharmony_ci			 * desktop mode.
8478c2ecf20Sopenharmony_ci			 *
8488c2ecf20Sopenharmony_ci			 * Features of 'USB/TA cable with Dock-Smart device'
8498c2ecf20Sopenharmony_ci			 * - Support MHL
8508c2ecf20Sopenharmony_ci			 * - Support external output feature of audio
8518c2ecf20Sopenharmony_ci			 * - Support charging through micro-usb port without
8528c2ecf20Sopenharmony_ci			 *   data connection if TA cable is connected to target.
8538c2ecf20Sopenharmony_ci			 * - Support charging and data connection through micro-
8548c2ecf20Sopenharmony_ci			 *   usb port if USB cable is connected between target
8558c2ecf20Sopenharmony_ci			 *   and host device
8568c2ecf20Sopenharmony_ci			 * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
8578c2ecf20Sopenharmony_ci			 */
8588c2ecf20Sopenharmony_ci			ret = max77693_muic_set_path(info, info->path_usb,
8598c2ecf20Sopenharmony_ci						    attached);
8608c2ecf20Sopenharmony_ci			if (ret < 0)
8618c2ecf20Sopenharmony_ci				return ret;
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_DOCK,
8648c2ecf20Sopenharmony_ci						attached);
8658c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_DISP_MHL,
8668c2ecf20Sopenharmony_ci						attached);
8678c2ecf20Sopenharmony_ci			break;
8688c2ecf20Sopenharmony_ci		}
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci		/* Check MAX77693_CABLE_GROUP_CHG type */
8718c2ecf20Sopenharmony_ci		switch (chg_type) {
8728c2ecf20Sopenharmony_ci		case MAX77693_CHARGER_TYPE_NONE:
8738c2ecf20Sopenharmony_ci			/*
8748c2ecf20Sopenharmony_ci			 * When MHL(with USB/TA cable) or Dock-Audio with USB/TA
8758c2ecf20Sopenharmony_ci			 * cable is attached, muic device happen below two irq.
8768c2ecf20Sopenharmony_ci			 * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting
8778c2ecf20Sopenharmony_ci			 *    MHL/Dock-Audio.
8788c2ecf20Sopenharmony_ci			 * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting
8798c2ecf20Sopenharmony_ci			 *    USB/TA cable connected to MHL or Dock-Audio.
8808c2ecf20Sopenharmony_ci			 * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC
8818c2ecf20Sopenharmony_ci			 * irq than MAX77693_MUIC_IRQ_INT2_CHGTYP irq.
8828c2ecf20Sopenharmony_ci			 *
8838c2ecf20Sopenharmony_ci			 * If user attach MHL (with USB/TA cable and immediately
8848c2ecf20Sopenharmony_ci			 * detach MHL with USB/TA cable before MAX77693_MUIC_IRQ
8858c2ecf20Sopenharmony_ci			 * _INT2_CHGTYP irq is happened, USB/TA cable remain
8868c2ecf20Sopenharmony_ci			 * connected state to target. But USB/TA cable isn't
8878c2ecf20Sopenharmony_ci			 * connected to target. The user be face with unusual
8888c2ecf20Sopenharmony_ci			 * action. So, driver should check this situation in
8898c2ecf20Sopenharmony_ci			 * spite of, that previous charger type is N/A.
8908c2ecf20Sopenharmony_ci			 */
8918c2ecf20Sopenharmony_ci			break;
8928c2ecf20Sopenharmony_ci		case MAX77693_CHARGER_TYPE_USB:
8938c2ecf20Sopenharmony_ci			/* Only USB cable, PATH:AP_USB */
8948c2ecf20Sopenharmony_ci			ret = max77693_muic_set_path(info, info->path_usb,
8958c2ecf20Sopenharmony_ci						    attached);
8968c2ecf20Sopenharmony_ci			if (ret < 0)
8978c2ecf20Sopenharmony_ci				return ret;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_USB,
9008c2ecf20Sopenharmony_ci						attached);
9018c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
9028c2ecf20Sopenharmony_ci						attached);
9038c2ecf20Sopenharmony_ci			break;
9048c2ecf20Sopenharmony_ci		case MAX77693_CHARGER_TYPE_DEDICATED_CHG:
9058c2ecf20Sopenharmony_ci			/* Only TA cable */
9068c2ecf20Sopenharmony_ci			extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
9078c2ecf20Sopenharmony_ci						attached);
9088c2ecf20Sopenharmony_ci			break;
9098c2ecf20Sopenharmony_ci		}
9108c2ecf20Sopenharmony_ci		break;
9118c2ecf20Sopenharmony_ci	case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT:
9128c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,
9138c2ecf20Sopenharmony_ci					attached);
9148c2ecf20Sopenharmony_ci		break;
9158c2ecf20Sopenharmony_ci	case MAX77693_CHARGER_TYPE_APPLE_500MA:
9168c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,
9178c2ecf20Sopenharmony_ci					attached);
9188c2ecf20Sopenharmony_ci		break;
9198c2ecf20Sopenharmony_ci	case MAX77693_CHARGER_TYPE_APPLE_1A_2A:
9208c2ecf20Sopenharmony_ci		extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,
9218c2ecf20Sopenharmony_ci					attached);
9228c2ecf20Sopenharmony_ci		break;
9238c2ecf20Sopenharmony_ci	case MAX77693_CHARGER_TYPE_DEAD_BATTERY:
9248c2ecf20Sopenharmony_ci		break;
9258c2ecf20Sopenharmony_ci	default:
9268c2ecf20Sopenharmony_ci		dev_err(info->dev,
9278c2ecf20Sopenharmony_ci			"failed to detect %s accessory (chg_type:0x%x)\n",
9288c2ecf20Sopenharmony_ci			attached ? "attached" : "detached", chg_type);
9298c2ecf20Sopenharmony_ci		return -EINVAL;
9308c2ecf20Sopenharmony_ci	}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	return 0;
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic void max77693_muic_irq_work(struct work_struct *work)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	struct max77693_muic_info *info = container_of(work,
9388c2ecf20Sopenharmony_ci			struct max77693_muic_info, irq_work);
9398c2ecf20Sopenharmony_ci	int irq_type = -1;
9408c2ecf20Sopenharmony_ci	int i, ret = 0;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	if (!info->edev)
9438c2ecf20Sopenharmony_ci		return;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	mutex_lock(&info->mutex);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
9488c2ecf20Sopenharmony_ci		if (info->irq == muic_irqs[i].virq)
9498c2ecf20Sopenharmony_ci			irq_type = muic_irqs[i].irq;
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(info->max77693->regmap_muic,
9528c2ecf20Sopenharmony_ci			MAX77693_MUIC_REG_STATUS1, info->status, 2);
9538c2ecf20Sopenharmony_ci	if (ret) {
9548c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to read MUIC register\n");
9558c2ecf20Sopenharmony_ci		mutex_unlock(&info->mutex);
9568c2ecf20Sopenharmony_ci		return;
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	switch (irq_type) {
9608c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT1_ADC:
9618c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT1_ADC_LOW:
9628c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT1_ADC_ERR:
9638c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT1_ADC1K:
9648c2ecf20Sopenharmony_ci		/*
9658c2ecf20Sopenharmony_ci		 * Handle all of accessory except for
9668c2ecf20Sopenharmony_ci		 * type of charger accessory.
9678c2ecf20Sopenharmony_ci		 */
9688c2ecf20Sopenharmony_ci		ret = max77693_muic_adc_handler(info);
9698c2ecf20Sopenharmony_ci		break;
9708c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT2_CHGTYP:
9718c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT2_CHGDETREUN:
9728c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT2_DCDTMR:
9738c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT2_DXOVP:
9748c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT2_VBVOLT:
9758c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT2_VIDRM:
9768c2ecf20Sopenharmony_ci		/* Handle charger accessory */
9778c2ecf20Sopenharmony_ci		ret = max77693_muic_chg_handler(info);
9788c2ecf20Sopenharmony_ci		break;
9798c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT3_EOC:
9808c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT3_CGMBC:
9818c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT3_OVP:
9828c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR:
9838c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT3_CHG_ENABLED:
9848c2ecf20Sopenharmony_ci	case MAX77693_MUIC_IRQ_INT3_BAT_DET:
9858c2ecf20Sopenharmony_ci		break;
9868c2ecf20Sopenharmony_ci	default:
9878c2ecf20Sopenharmony_ci		dev_err(info->dev, "muic interrupt: irq %d occurred\n",
9888c2ecf20Sopenharmony_ci				irq_type);
9898c2ecf20Sopenharmony_ci		mutex_unlock(&info->mutex);
9908c2ecf20Sopenharmony_ci		return;
9918c2ecf20Sopenharmony_ci	}
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	if (ret < 0)
9948c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to handle MUIC interrupt\n");
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	mutex_unlock(&info->mutex);
9978c2ecf20Sopenharmony_ci}
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_cistatic irqreturn_t max77693_muic_irq_handler(int irq, void *data)
10008c2ecf20Sopenharmony_ci{
10018c2ecf20Sopenharmony_ci	struct max77693_muic_info *info = data;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	info->irq = irq;
10048c2ecf20Sopenharmony_ci	schedule_work(&info->irq_work);
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
10078c2ecf20Sopenharmony_ci}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_cistatic const struct regmap_config max77693_muic_regmap_config = {
10108c2ecf20Sopenharmony_ci	.reg_bits = 8,
10118c2ecf20Sopenharmony_ci	.val_bits = 8,
10128c2ecf20Sopenharmony_ci};
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_cistatic int max77693_muic_detect_accessory(struct max77693_muic_info *info)
10158c2ecf20Sopenharmony_ci{
10168c2ecf20Sopenharmony_ci	int ret = 0;
10178c2ecf20Sopenharmony_ci	int adc;
10188c2ecf20Sopenharmony_ci	int chg_type;
10198c2ecf20Sopenharmony_ci	bool attached;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	mutex_lock(&info->mutex);
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	/* Read STATUSx register to detect accessory */
10248c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(info->max77693->regmap_muic,
10258c2ecf20Sopenharmony_ci			MAX77693_MUIC_REG_STATUS1, info->status, 2);
10268c2ecf20Sopenharmony_ci	if (ret) {
10278c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to read MUIC register\n");
10288c2ecf20Sopenharmony_ci		mutex_unlock(&info->mutex);
10298c2ecf20Sopenharmony_ci		return ret;
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	adc = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_ADC,
10338c2ecf20Sopenharmony_ci					&attached);
10348c2ecf20Sopenharmony_ci	if (attached && adc != MAX77693_MUIC_ADC_OPEN) {
10358c2ecf20Sopenharmony_ci		ret = max77693_muic_adc_handler(info);
10368c2ecf20Sopenharmony_ci		if (ret < 0) {
10378c2ecf20Sopenharmony_ci			dev_err(info->dev, "Cannot detect accessory\n");
10388c2ecf20Sopenharmony_ci			mutex_unlock(&info->mutex);
10398c2ecf20Sopenharmony_ci			return ret;
10408c2ecf20Sopenharmony_ci		}
10418c2ecf20Sopenharmony_ci	}
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	chg_type = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_CHG,
10448c2ecf20Sopenharmony_ci					&attached);
10458c2ecf20Sopenharmony_ci	if (attached && chg_type != MAX77693_CHARGER_TYPE_NONE) {
10468c2ecf20Sopenharmony_ci		ret = max77693_muic_chg_handler(info);
10478c2ecf20Sopenharmony_ci		if (ret < 0) {
10488c2ecf20Sopenharmony_ci			dev_err(info->dev, "Cannot detect charger accessory\n");
10498c2ecf20Sopenharmony_ci			mutex_unlock(&info->mutex);
10508c2ecf20Sopenharmony_ci			return ret;
10518c2ecf20Sopenharmony_ci		}
10528c2ecf20Sopenharmony_ci	}
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	mutex_unlock(&info->mutex);
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	return 0;
10578c2ecf20Sopenharmony_ci}
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_cistatic void max77693_muic_detect_cable_wq(struct work_struct *work)
10608c2ecf20Sopenharmony_ci{
10618c2ecf20Sopenharmony_ci	struct max77693_muic_info *info = container_of(to_delayed_work(work),
10628c2ecf20Sopenharmony_ci				struct max77693_muic_info, wq_detcable);
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	max77693_muic_detect_accessory(info);
10658c2ecf20Sopenharmony_ci}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_cistatic int max77693_muic_probe(struct platform_device *pdev)
10688c2ecf20Sopenharmony_ci{
10698c2ecf20Sopenharmony_ci	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
10708c2ecf20Sopenharmony_ci	struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
10718c2ecf20Sopenharmony_ci	struct max77693_muic_info *info;
10728c2ecf20Sopenharmony_ci	struct max77693_reg_data *init_data;
10738c2ecf20Sopenharmony_ci	int num_init_data;
10748c2ecf20Sopenharmony_ci	int delay_jiffies;
10758c2ecf20Sopenharmony_ci	int cable_type;
10768c2ecf20Sopenharmony_ci	bool attached;
10778c2ecf20Sopenharmony_ci	int ret;
10788c2ecf20Sopenharmony_ci	int i;
10798c2ecf20Sopenharmony_ci	unsigned int id;
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info),
10828c2ecf20Sopenharmony_ci				   GFP_KERNEL);
10838c2ecf20Sopenharmony_ci	if (!info)
10848c2ecf20Sopenharmony_ci		return -ENOMEM;
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	info->dev = &pdev->dev;
10878c2ecf20Sopenharmony_ci	info->max77693 = max77693;
10888c2ecf20Sopenharmony_ci	if (info->max77693->regmap_muic) {
10898c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "allocate register map\n");
10908c2ecf20Sopenharmony_ci	} else {
10918c2ecf20Sopenharmony_ci		info->max77693->regmap_muic = devm_regmap_init_i2c(
10928c2ecf20Sopenharmony_ci						info->max77693->i2c_muic,
10938c2ecf20Sopenharmony_ci						&max77693_muic_regmap_config);
10948c2ecf20Sopenharmony_ci		if (IS_ERR(info->max77693->regmap_muic)) {
10958c2ecf20Sopenharmony_ci			ret = PTR_ERR(info->max77693->regmap_muic);
10968c2ecf20Sopenharmony_ci			dev_err(max77693->dev,
10978c2ecf20Sopenharmony_ci				"failed to allocate register map: %d\n", ret);
10988c2ecf20Sopenharmony_ci			return ret;
10998c2ecf20Sopenharmony_ci		}
11008c2ecf20Sopenharmony_ci	}
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	/* Register input device for button of dock device */
11038c2ecf20Sopenharmony_ci	info->dock = devm_input_allocate_device(&pdev->dev);
11048c2ecf20Sopenharmony_ci	if (!info->dock) {
11058c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "%s: failed to allocate input\n", __func__);
11068c2ecf20Sopenharmony_ci		return -ENOMEM;
11078c2ecf20Sopenharmony_ci	}
11088c2ecf20Sopenharmony_ci	info->dock->name = "max77693-muic/dock";
11098c2ecf20Sopenharmony_ci	info->dock->phys = "max77693-muic/extcon";
11108c2ecf20Sopenharmony_ci	info->dock->dev.parent = &pdev->dev;
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	__set_bit(EV_REP, info->dock->evbit);
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	input_set_capability(info->dock, EV_KEY, KEY_VOLUMEUP);
11158c2ecf20Sopenharmony_ci	input_set_capability(info->dock, EV_KEY, KEY_VOLUMEDOWN);
11168c2ecf20Sopenharmony_ci	input_set_capability(info->dock, EV_KEY, KEY_PLAYPAUSE);
11178c2ecf20Sopenharmony_ci	input_set_capability(info->dock, EV_KEY, KEY_PREVIOUSSONG);
11188c2ecf20Sopenharmony_ci	input_set_capability(info->dock, EV_KEY, KEY_NEXTSONG);
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	ret = input_register_device(info->dock);
11218c2ecf20Sopenharmony_ci	if (ret < 0) {
11228c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Cannot register input device error(%d)\n",
11238c2ecf20Sopenharmony_ci				ret);
11248c2ecf20Sopenharmony_ci		return ret;
11258c2ecf20Sopenharmony_ci	}
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, info);
11288c2ecf20Sopenharmony_ci	mutex_init(&info->mutex);
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	INIT_WORK(&info->irq_work, max77693_muic_irq_work);
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	/* Support irq domain for MAX77693 MUIC device */
11338c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
11348c2ecf20Sopenharmony_ci		struct max77693_muic_irq *muic_irq = &muic_irqs[i];
11358c2ecf20Sopenharmony_ci		int virq;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci		virq = regmap_irq_get_virq(max77693->irq_data_muic,
11388c2ecf20Sopenharmony_ci					muic_irq->irq);
11398c2ecf20Sopenharmony_ci		if (virq <= 0)
11408c2ecf20Sopenharmony_ci			return -EINVAL;
11418c2ecf20Sopenharmony_ci		muic_irq->virq = virq;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci		ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
11448c2ecf20Sopenharmony_ci				max77693_muic_irq_handler,
11458c2ecf20Sopenharmony_ci				IRQF_NO_SUSPEND,
11468c2ecf20Sopenharmony_ci				muic_irq->name, info);
11478c2ecf20Sopenharmony_ci		if (ret) {
11488c2ecf20Sopenharmony_ci			dev_err(&pdev->dev,
11498c2ecf20Sopenharmony_ci				"failed: irq request (IRQ: %d, error :%d)\n",
11508c2ecf20Sopenharmony_ci				muic_irq->irq, ret);
11518c2ecf20Sopenharmony_ci			return ret;
11528c2ecf20Sopenharmony_ci		}
11538c2ecf20Sopenharmony_ci	}
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	/* Initialize extcon device */
11568c2ecf20Sopenharmony_ci	info->edev = devm_extcon_dev_allocate(&pdev->dev,
11578c2ecf20Sopenharmony_ci					      max77693_extcon_cable);
11588c2ecf20Sopenharmony_ci	if (IS_ERR(info->edev)) {
11598c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
11608c2ecf20Sopenharmony_ci		return PTR_ERR(info->edev);
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	ret = devm_extcon_dev_register(&pdev->dev, info->edev);
11648c2ecf20Sopenharmony_ci	if (ret) {
11658c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to register extcon device\n");
11668c2ecf20Sopenharmony_ci		return ret;
11678c2ecf20Sopenharmony_ci	}
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	/* Initialize MUIC register by using platform data or default data */
11708c2ecf20Sopenharmony_ci	if (pdata && pdata->muic_data) {
11718c2ecf20Sopenharmony_ci		init_data = pdata->muic_data->init_data;
11728c2ecf20Sopenharmony_ci		num_init_data = pdata->muic_data->num_init_data;
11738c2ecf20Sopenharmony_ci	} else {
11748c2ecf20Sopenharmony_ci		init_data = default_init_data;
11758c2ecf20Sopenharmony_ci		num_init_data = ARRAY_SIZE(default_init_data);
11768c2ecf20Sopenharmony_ci	}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	for (i = 0; i < num_init_data; i++) {
11798c2ecf20Sopenharmony_ci		regmap_write(info->max77693->regmap_muic,
11808c2ecf20Sopenharmony_ci				init_data[i].addr,
11818c2ecf20Sopenharmony_ci				init_data[i].data);
11828c2ecf20Sopenharmony_ci	}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	if (pdata && pdata->muic_data) {
11858c2ecf20Sopenharmony_ci		struct max77693_muic_platform_data *muic_pdata
11868c2ecf20Sopenharmony_ci						   = pdata->muic_data;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci		/*
11898c2ecf20Sopenharmony_ci		 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
11908c2ecf20Sopenharmony_ci		 * h/w path of COMP2/COMN1 on CONTROL1 register.
11918c2ecf20Sopenharmony_ci		 */
11928c2ecf20Sopenharmony_ci		if (muic_pdata->path_uart)
11938c2ecf20Sopenharmony_ci			info->path_uart = muic_pdata->path_uart;
11948c2ecf20Sopenharmony_ci		else
11958c2ecf20Sopenharmony_ci			info->path_uart = MAX77693_CONTROL1_SW_UART;
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci		if (muic_pdata->path_usb)
11988c2ecf20Sopenharmony_ci			info->path_usb = muic_pdata->path_usb;
11998c2ecf20Sopenharmony_ci		else
12008c2ecf20Sopenharmony_ci			info->path_usb = MAX77693_CONTROL1_SW_USB;
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci		/*
12038c2ecf20Sopenharmony_ci		 * Default delay time for detecting cable state
12048c2ecf20Sopenharmony_ci		 * after certain time.
12058c2ecf20Sopenharmony_ci		 */
12068c2ecf20Sopenharmony_ci		if (muic_pdata->detcable_delay_ms)
12078c2ecf20Sopenharmony_ci			delay_jiffies =
12088c2ecf20Sopenharmony_ci				msecs_to_jiffies(muic_pdata->detcable_delay_ms);
12098c2ecf20Sopenharmony_ci		else
12108c2ecf20Sopenharmony_ci			delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
12118c2ecf20Sopenharmony_ci	} else {
12128c2ecf20Sopenharmony_ci		info->path_usb = MAX77693_CONTROL1_SW_USB;
12138c2ecf20Sopenharmony_ci		info->path_uart = MAX77693_CONTROL1_SW_UART;
12148c2ecf20Sopenharmony_ci		delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
12158c2ecf20Sopenharmony_ci	}
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	/* Set initial path for UART when JIG is connected to get serial logs */
12188c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(info->max77693->regmap_muic,
12198c2ecf20Sopenharmony_ci			MAX77693_MUIC_REG_STATUS1, info->status, 2);
12208c2ecf20Sopenharmony_ci	if (ret) {
12218c2ecf20Sopenharmony_ci		dev_err(info->dev, "failed to read MUIC register\n");
12228c2ecf20Sopenharmony_ci		return ret;
12238c2ecf20Sopenharmony_ci	}
12248c2ecf20Sopenharmony_ci	cable_type = max77693_muic_get_cable_type(info,
12258c2ecf20Sopenharmony_ci					   MAX77693_CABLE_GROUP_ADC, &attached);
12268c2ecf20Sopenharmony_ci	if (attached && (cable_type == MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON ||
12278c2ecf20Sopenharmony_ci			 cable_type == MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF))
12288c2ecf20Sopenharmony_ci		max77693_muic_set_path(info, info->path_uart, true);
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	/* Check revision number of MUIC device*/
12318c2ecf20Sopenharmony_ci	ret = regmap_read(info->max77693->regmap_muic,
12328c2ecf20Sopenharmony_ci			MAX77693_MUIC_REG_ID, &id);
12338c2ecf20Sopenharmony_ci	if (ret < 0) {
12348c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to read revision number\n");
12358c2ecf20Sopenharmony_ci		return ret;
12368c2ecf20Sopenharmony_ci	}
12378c2ecf20Sopenharmony_ci	dev_info(info->dev, "device ID : 0x%x\n", id);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	/* Set ADC debounce time */
12408c2ecf20Sopenharmony_ci	max77693_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	/*
12438c2ecf20Sopenharmony_ci	 * Detect accessory after completing the initialization of platform
12448c2ecf20Sopenharmony_ci	 *
12458c2ecf20Sopenharmony_ci	 * - Use delayed workqueue to detect cable state and then
12468c2ecf20Sopenharmony_ci	 * notify cable state to notifiee/platform through uevent.
12478c2ecf20Sopenharmony_ci	 * After completing the booting of platform, the extcon provider
12488c2ecf20Sopenharmony_ci	 * driver should notify cable state to upper layer.
12498c2ecf20Sopenharmony_ci	 */
12508c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq);
12518c2ecf20Sopenharmony_ci	queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
12528c2ecf20Sopenharmony_ci			delay_jiffies);
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	return ret;
12558c2ecf20Sopenharmony_ci}
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_cistatic int max77693_muic_remove(struct platform_device *pdev)
12588c2ecf20Sopenharmony_ci{
12598c2ecf20Sopenharmony_ci	struct max77693_muic_info *info = platform_get_drvdata(pdev);
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	cancel_work_sync(&info->irq_work);
12628c2ecf20Sopenharmony_ci	input_unregister_device(info->dock);
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	return 0;
12658c2ecf20Sopenharmony_ci}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_cistatic struct platform_driver max77693_muic_driver = {
12688c2ecf20Sopenharmony_ci	.driver		= {
12698c2ecf20Sopenharmony_ci		.name	= DEV_NAME,
12708c2ecf20Sopenharmony_ci	},
12718c2ecf20Sopenharmony_ci	.probe		= max77693_muic_probe,
12728c2ecf20Sopenharmony_ci	.remove		= max77693_muic_remove,
12738c2ecf20Sopenharmony_ci};
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_cimodule_platform_driver(max77693_muic_driver);
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Maxim MAX77693 Extcon driver");
12788c2ecf20Sopenharmony_ciMODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
12798c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
12808c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:max77693-muic");
1281