// SPDX-License-Identifier: GPL-2.0+
//
// extcon-max77693.c - MAX77693 extcon driver to support MAX77693 MUIC
//
// Copyright (C) 2012 Samsung Electrnoics
// Chanwoo Choi <cw00.choi@samsung.com>
#include <linux/devm-helpers.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/mfd/max77693.h>
#include <linux/mfd/max77693-common.h>
#include <linux/mfd/max77693-private.h>
#include <linux/extcon-provider.h>
#include <linux/regmap.h>
#include <linux/irqdomain.h>
#define DEV_NAME "max77693-muic"
#define DELAY_MS_DEFAULT 20000 /* unit: millisecond */
/*
* Default value of MAX77693 register to bring up MUIC device.
* If user don't set some initial value for MUIC device through platform data,
* extcon-max77693 driver use 'default_init_data' to bring up base operation
* of MAX77693 MUIC device.
*/
static struct max77693_reg_data default_init_data[] = {
{
/* STATUS2 - [3]ChgDetRun */
.addr = MAX77693_MUIC_REG_STATUS2,
.data = MAX77693_STATUS2_CHGDETRUN_MASK,
}, {
/* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */
.addr = MAX77693_MUIC_REG_INTMASK1,
.data = INTMASK1_ADC1K_MASK
| INTMASK1_ADC_MASK,
}, {
/* INTMASK2 - Unmask [0]ChgTypM */
.addr = MAX77693_MUIC_REG_INTMASK2,
.data = INTMASK2_CHGTYP_MASK,
}, {
/* INTMASK3 - Mask all of interrupts */
.addr = MAX77693_MUIC_REG_INTMASK3,
.data = 0x0,
}, {
/* CDETCTRL2 */
.addr = MAX77693_MUIC_REG_CDETCTRL2,
.data = CDETCTRL2_VIDRMEN_MASK
| CDETCTRL2_DXOVPEN_MASK,
},
};
enum max77693_muic_adc_debounce_time {
ADC_DEBOUNCE_TIME_5MS = 0,
ADC_DEBOUNCE_TIME_10MS,
ADC_DEBOUNCE_TIME_25MS,
ADC_DEBOUNCE_TIME_38_62MS,
};
struct max77693_muic_info {
struct device *dev;
struct max77693_dev *max77693;
struct extcon_dev *edev;
int prev_cable_type;
int prev_cable_type_gnd;
int prev_chg_type;
int prev_button_type;
u8 status[2];
int irq;
struct work_struct irq_work;
struct mutex mutex;
/*
* Use delayed workqueue to detect cable state and then
* notify cable state to notifiee/platform through uevent.
* After completing the booting of platform, the extcon provider
* driver should notify cable state to upper layer.
*/
struct delayed_work wq_detcable;
/* Button of dock device */
struct input_dev *dock;
/*
* Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
* h/w path of COMP2/COMN1 on CONTROL1 register.
*/
int path_usb;
int path_uart;
};
enum max77693_muic_cable_group {
MAX77693_CABLE_GROUP_ADC = 0,
MAX77693_CABLE_GROUP_ADC_GND,
MAX77693_CABLE_GROUP_CHG,
MAX77693_CABLE_GROUP_VBVOLT,
};
enum max77693_muic_charger_type {
MAX77693_CHARGER_TYPE_NONE = 0,
MAX77693_CHARGER_TYPE_USB,
MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT,
MAX77693_CHARGER_TYPE_DEDICATED_CHG,
MAX77693_CHARGER_TYPE_APPLE_500MA,
MAX77693_CHARGER_TYPE_APPLE_1A_2A,
MAX77693_CHARGER_TYPE_DEAD_BATTERY = 7,
};
/**
* struct max77693_muic_irq
* @irq: the index of irq list of MUIC device.
* @name: the name of irq.
* @virq: the virtual irq to use irq domain
*/
struct max77693_muic_irq {
unsigned int irq;
const char *name;
unsigned int virq;
};
static struct max77693_muic_irq muic_irqs[] = {
{ MAX77693_MUIC_IRQ_INT1_ADC, "muic-ADC" },
{ MAX77693_MUIC_IRQ_INT1_ADC_LOW, "muic-ADCLOW" },
{ MAX77693_MUIC_IRQ_INT1_ADC_ERR, "muic-ADCError" },
{ MAX77693_MUIC_IRQ_INT1_ADC1K, "muic-ADC1K" },
{ MAX77693_MUIC_IRQ_INT2_CHGTYP, "muic-CHGTYP" },
{ MAX77693_MUIC_IRQ_INT2_CHGDETREUN, "muic-CHGDETREUN" },
{ MAX77693_MUIC_IRQ_INT2_DCDTMR, "muic-DCDTMR" },
{ MAX77693_MUIC_IRQ_INT2_DXOVP, "muic-DXOVP" },
{ MAX77693_MUIC_IRQ_INT2_VBVOLT, "muic-VBVOLT" },
{ MAX77693_MUIC_IRQ_INT2_VIDRM, "muic-VIDRM" },
{ MAX77693_MUIC_IRQ_INT3_EOC, "muic-EOC" },
{ MAX77693_MUIC_IRQ_INT3_CGMBC, "muic-CGMBC" },
{ MAX77693_MUIC_IRQ_INT3_OVP,