mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-23 23:49:40 +07:00
Update extcon for v3.17
This patchset add new extcon provider driver and fix minor issue of extcon driver. Detailed description for patchset: 1. Add new Silicon-Mitus SM5502 MUIC (Micro-USB Interface Controller) device - extcon-sm5502 driver is capable of identifying the type of the external power source and attached accessory. And external power sources, such as Dedicated charger or a standard USB port, are able to charge the battery in the smart phone via the connector. 2. Fix minor issue of extcon driver - extcon-arizona driver - extcon-palmas driver - Remove unnecessary OOM messages for all extcon device drivers 3. Fix minor issue of extcon core - Re-order the sequence of extcon device driver in Kconfig/Makefile alphabitically - Set parent device of extcon device automatically using devm_extcon_dev_allocate() 4. Fix MAX77693 driver - This patchset has dependency on MFD/Regulator/Extcon. So, Lee Jones (MFD Maintainer) created Immutable branch between MFD and Extcon due for v3.17 merge-window and then I merged this patchset from MFD git repo[1] to Extcon git repo. [1] git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd (branch: ib-mfd-extcon-regulator) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJT0aFrAAoJEJzN3yze689TGL4QAIAsofuwlFTSi28WAxTDxXPE 7o8FGcikRkvOcMsKaa/482JpvRrcZEsO2uXMMGdYv4mCm8BPGlw1fmNYx1Ai+aWT A04P7TqKdddo7Id4FGSYpSMHekfrgmEkwxliEEZ2zcRJrAovq4KSKZoZ4eY5NXUm widR7LtGFQXnCmNuEzptNlG+s9TNtPF2u0kondgR0zZlEqU03b8uN4m5DO6UaxTB 1X3rqeSENcPWyu/2tWl0pUGDJqUFfSzqU0XMoDU5zto/N5RZKyucRXUUPZRYlb+Z OuvsQT1ASi2nzqB7DDroC6iFmYi3hQPkyzI8K9L3XZVXcObHWNH6gv8WKpUaFtZI VK3nKaDm8jO9DvHZ+p8PEkKBkvPNA1lAOoJdqeJUe9WtVF6TP/Gi5R1OF+b1CdOV ms2jEQWDAzNejNT1h6XxRMcJkmSlPtGHYP6z5sIbzXOJJSqq224jn9viTJSCCfJa FV7Qyd6xjxJEMuWbZLYteTNL9nFbLhAnFa1ETgFsbhZ5AwHzojMZip4LwsaoVlFi OUwsQ6jNLLVCqLo0B68ksAuS3AKw3b3ar5kB0qEiDmkskTP6Acx+WqyMY+dJSaMQ x3XNzzWug8370pvwXcRnuDrx1Vsweiz4H2QkpuGc3lzL9Oxy5wNRnf+BgK8OT2k9 OYgQsnO3NyoKc8YDrpUh =zJIS -----END PGP SIGNATURE----- Merge tag 'extcon-next-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next Chanwoo writes: Update extcon for v3.17 This patchset add new extcon provider driver and fix minor issue of extcon driver. Detailed description for patchset: 1. Add new Silicon-Mitus SM5502 MUIC (Micro-USB Interface Controller) device - extcon-sm5502 driver is capable of identifying the type of the external power source and attached accessory. And external power sources, such as Dedicated charger or a standard USB port, are able to charge the battery in the smart phone via the connector. 2. Fix minor issue of extcon driver - extcon-arizona driver - extcon-palmas driver - Remove unnecessary OOM messages for all extcon device drivers 3. Fix minor issue of extcon core - Re-order the sequence of extcon device driver in Kconfig/Makefile alphabitically - Set parent device of extcon device automatically using devm_extcon_dev_allocate() 4. Fix MAX77693 driver - This patchset has dependency on MFD/Regulator/Extcon. So, Lee Jones (MFD Maintainer) created Immutable branch between MFD and Extcon due for v3.17 merge-window and then I merged this patchset from MFD git repo[1] to Extcon git repo. [1] git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd (branch: ib-mfd-extcon-regulator)
This commit is contained in:
commit
16eb2bfc65
23
Documentation/devicetree/bindings/extcon/extcon-sm5502.txt
Normal file
23
Documentation/devicetree/bindings/extcon/extcon-sm5502.txt
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
* SM5502 MUIC (Micro-USB Interface Controller) device
|
||||
|
||||
The Silicon Mitus SM5502 is a MUIC (Micro-USB Interface Controller) device
|
||||
which can detect the state of external accessory when external accessory is
|
||||
attached or detached and button is pressed or released. It is interfaced to
|
||||
the host controller using an I2C interface.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "siliconmitus,sm5502-muic"
|
||||
- reg: Specifies the I2C slave address of the MUIC block. It should be 0x25
|
||||
- interrupt-parent: Specifies the phandle of the interrupt controller to which
|
||||
the interrupts from sm5502 are delivered to.
|
||||
- interrupts: Interrupt specifiers for detection interrupt sources.
|
||||
|
||||
Example:
|
||||
|
||||
sm5502@25 {
|
||||
compatible = "siliconmitus,sm5502-muic";
|
||||
interrupt-parent = <&gpx1>;
|
||||
interrupts = <5 0>;
|
||||
reg = <0x25>;
|
||||
};
|
@ -14,6 +14,20 @@ if EXTCON
|
||||
|
||||
comment "Extcon Device Drivers"
|
||||
|
||||
config EXTCON_ADC_JACK
|
||||
tristate "ADC Jack extcon support"
|
||||
depends on IIO
|
||||
help
|
||||
Say Y here to enable extcon device driver based on ADC values.
|
||||
|
||||
config EXTCON_ARIZONA
|
||||
tristate "Wolfson Arizona EXTCON support"
|
||||
depends on MFD_ARIZONA && INPUT && SND_SOC
|
||||
help
|
||||
Say Y here to enable support for external accessory detection
|
||||
with Wolfson Arizona devices. These are audio CODECs with
|
||||
advanced audio accessory detection support.
|
||||
|
||||
config EXTCON_GPIO
|
||||
tristate "GPIO extcon support"
|
||||
depends on GPIOLIB
|
||||
@ -21,12 +35,6 @@ config EXTCON_GPIO
|
||||
Say Y here to enable GPIO based extcon support. Note that GPIO
|
||||
extcon supports single state per extcon instance.
|
||||
|
||||
config EXTCON_ADC_JACK
|
||||
tristate "ADC Jack extcon support"
|
||||
depends on IIO
|
||||
help
|
||||
Say Y here to enable extcon device driver based on ADC values.
|
||||
|
||||
config EXTCON_MAX14577
|
||||
tristate "MAX14577/77836 EXTCON Support"
|
||||
depends on MFD_MAX14577
|
||||
@ -55,14 +63,6 @@ config EXTCON_MAX8997
|
||||
Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
|
||||
detector and switch.
|
||||
|
||||
config EXTCON_ARIZONA
|
||||
tristate "Wolfson Arizona EXTCON support"
|
||||
depends on MFD_ARIZONA && INPUT && SND_SOC
|
||||
help
|
||||
Say Y here to enable support for external accessory detection
|
||||
with Wolfson Arizona devices. These are audio CODECs with
|
||||
advanced audio accessory detection support.
|
||||
|
||||
config EXTCON_PALMAS
|
||||
tristate "Palmas USB EXTCON support"
|
||||
depends on MFD_PALMAS
|
||||
@ -70,4 +70,14 @@ config EXTCON_PALMAS
|
||||
Say Y here to enable support for USB peripheral and USB host
|
||||
detection by palmas usb.
|
||||
|
||||
config EXTCON_SM5502
|
||||
tristate "SM5502 EXTCON support"
|
||||
select IRQ_DOMAIN
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
If you say yes here you get support for the MUIC device of
|
||||
Silicon Mitus SM5502. The SM5502 is a USB port accessory
|
||||
detector and switch.
|
||||
|
||||
endif # MULTISTATE_SWITCH
|
||||
|
@ -1,12 +1,13 @@
|
||||
#
|
||||
|
||||
# Makefile for external connector class (extcon) devices
|
||||
#
|
||||
|
||||
obj-$(CONFIG_EXTCON) += extcon-class.o
|
||||
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
|
||||
obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
|
||||
obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
|
||||
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
|
||||
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
|
||||
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
|
||||
obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
|
||||
obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
|
||||
obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o
|
||||
obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
|
||||
|
@ -112,7 +112,6 @@ static int adc_jack_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "failed to allocate extcon device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
data->edev->dev.parent = &pdev->dev;
|
||||
data->edev->name = pdata->name;
|
||||
|
||||
/* Check the length of array and set num_cables */
|
||||
|
@ -39,6 +39,11 @@
|
||||
#define ARIZONA_ACCDET_MODE_HPL 1
|
||||
#define ARIZONA_ACCDET_MODE_HPR 2
|
||||
|
||||
#define ARIZONA_MICD_CLAMP_MODE_JDL 0x4
|
||||
#define ARIZONA_MICD_CLAMP_MODE_JDH 0x5
|
||||
#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
|
||||
#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
|
||||
|
||||
#define ARIZONA_HPDET_MAX 10000
|
||||
|
||||
#define HPDET_DEBOUNCE 500
|
||||
@ -324,14 +329,17 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
|
||||
}
|
||||
|
||||
static struct {
|
||||
unsigned int threshold;
|
||||
unsigned int factor_a;
|
||||
unsigned int factor_b;
|
||||
} arizona_hpdet_b_ranges[] = {
|
||||
{ 5528, 362464 },
|
||||
{ 11084, 6186851 },
|
||||
{ 11065, 65460395 },
|
||||
{ 100, 5528, 362464 },
|
||||
{ 169, 11084, 6186851 },
|
||||
{ 169, 11065, 65460395 },
|
||||
};
|
||||
|
||||
#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
|
||||
|
||||
static struct {
|
||||
int min;
|
||||
int max;
|
||||
@ -386,7 +394,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
|
||||
>> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
|
||||
|
||||
if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
|
||||
(val < 100 || val >= 0x3fb)) {
|
||||
(val < arizona_hpdet_b_ranges[range].threshold ||
|
||||
val >= ARIZONA_HPDET_B_RANGE_MAX)) {
|
||||
range++;
|
||||
dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
|
||||
range);
|
||||
@ -399,7 +408,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
|
||||
}
|
||||
|
||||
/* If we go out of range report top of range */
|
||||
if (val < 100 || val >= 0x3fb) {
|
||||
if (val < arizona_hpdet_b_ranges[range].threshold ||
|
||||
val >= ARIZONA_HPDET_B_RANGE_MAX) {
|
||||
dev_dbg(arizona->dev, "Measurement out of range\n");
|
||||
return ARIZONA_HPDET_MAX;
|
||||
}
|
||||
@ -664,9 +674,8 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
|
||||
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
|
||||
|
||||
/* Just report headphone */
|
||||
ret = extcon_update_state(info->edev,
|
||||
1 << ARIZONA_CABLE_HEADPHONE,
|
||||
1 << ARIZONA_CABLE_HEADPHONE);
|
||||
ret = extcon_set_cable_state_(info->edev,
|
||||
ARIZONA_CABLE_HEADPHONE, true);
|
||||
if (ret != 0)
|
||||
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
|
||||
|
||||
@ -723,9 +732,8 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
|
||||
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
|
||||
|
||||
/* Just report headphone */
|
||||
ret = extcon_update_state(info->edev,
|
||||
1 << ARIZONA_CABLE_HEADPHONE,
|
||||
1 << ARIZONA_CABLE_HEADPHONE);
|
||||
ret = extcon_set_cable_state_(info->edev,
|
||||
ARIZONA_CABLE_HEADPHONE, true);
|
||||
if (ret != 0)
|
||||
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
|
||||
|
||||
@ -812,16 +820,15 @@ static void arizona_micd_detect(struct work_struct *work)
|
||||
if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
|
||||
arizona_identify_headphone(info);
|
||||
|
||||
ret = extcon_update_state(info->edev,
|
||||
1 << ARIZONA_CABLE_MICROPHONE,
|
||||
1 << ARIZONA_CABLE_MICROPHONE);
|
||||
ret = extcon_set_cable_state_(info->edev,
|
||||
ARIZONA_CABLE_MICROPHONE, true);
|
||||
|
||||
if (ret != 0)
|
||||
dev_err(arizona->dev, "Headset report failed: %d\n",
|
||||
ret);
|
||||
|
||||
/* Don't need to regulate for button detection */
|
||||
ret = regulator_allow_bypass(info->micvdd, false);
|
||||
ret = regulator_allow_bypass(info->micvdd, true);
|
||||
if (ret != 0) {
|
||||
dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
|
||||
ret);
|
||||
@ -962,10 +969,16 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
|
||||
|
||||
if (arizona->pdata.jd_gpio5) {
|
||||
mask = ARIZONA_MICD_CLAMP_STS;
|
||||
present = 0;
|
||||
if (arizona->pdata.jd_invert)
|
||||
present = ARIZONA_MICD_CLAMP_STS;
|
||||
else
|
||||
present = 0;
|
||||
} else {
|
||||
mask = ARIZONA_JD1_STS;
|
||||
present = ARIZONA_JD1_STS;
|
||||
if (arizona->pdata.jd_invert)
|
||||
present = 0;
|
||||
else
|
||||
present = ARIZONA_JD1_STS;
|
||||
}
|
||||
|
||||
ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
|
||||
@ -1096,6 +1109,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
struct arizona_pdata *pdata = &arizona->pdata;
|
||||
struct arizona_extcon_info *info;
|
||||
unsigned int val;
|
||||
unsigned int clamp_mode;
|
||||
int jack_irq_fall, jack_irq_rise;
|
||||
int ret, mode, i, j;
|
||||
|
||||
@ -1103,12 +1117,10 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
dev_err(&pdev->dev, "Failed to allocate memory\n");
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->micvdd = devm_regulator_get(arizona->dev, "MICVDD");
|
||||
info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
|
||||
if (IS_ERR(info->micvdd)) {
|
||||
ret = PTR_ERR(info->micvdd);
|
||||
dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
|
||||
@ -1156,7 +1168,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
info->edev->name = "Headset Jack";
|
||||
info->edev->dev.parent = arizona->dev;
|
||||
|
||||
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
|
||||
if (ret < 0) {
|
||||
@ -1174,7 +1185,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
|
||||
info->input->name = "Headset";
|
||||
info->input->phys = "arizona/extcon";
|
||||
info->input->dev.parent = &pdev->dev;
|
||||
|
||||
if (pdata->num_micd_configs) {
|
||||
info->micd_modes = pdata->micd_configs;
|
||||
@ -1305,15 +1315,21 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
|
||||
val);
|
||||
|
||||
regmap_update_bits(arizona->regmap,
|
||||
ARIZONA_MICD_CLAMP_CONTROL,
|
||||
ARIZONA_MICD_CLAMP_MODE_MASK, 0x9);
|
||||
if (arizona->pdata.jd_invert)
|
||||
clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
|
||||
else
|
||||
clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
|
||||
} else {
|
||||
regmap_update_bits(arizona->regmap,
|
||||
ARIZONA_MICD_CLAMP_CONTROL,
|
||||
ARIZONA_MICD_CLAMP_MODE_MASK, 0x4);
|
||||
if (arizona->pdata.jd_invert)
|
||||
clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
|
||||
else
|
||||
clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
|
||||
}
|
||||
|
||||
regmap_update_bits(arizona->regmap,
|
||||
ARIZONA_MICD_CLAMP_CONTROL,
|
||||
ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
|
||||
|
||||
regmap_update_bits(arizona->regmap,
|
||||
ARIZONA_JACK_DETECT_DEBOUNCE,
|
||||
ARIZONA_MICD_CLAMP_DB,
|
||||
|
@ -645,6 +645,8 @@ struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
|
||||
return edev;
|
||||
}
|
||||
|
||||
edev->dev.parent = dev;
|
||||
|
||||
*ptr = edev;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
|
@ -105,7 +105,6 @@ static int gpio_extcon_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
extcon_data->edev->name = pdata->name;
|
||||
extcon_data->edev->dev.parent = &pdev->dev;
|
||||
|
||||
extcon_data->gpio = pdata->gpio;
|
||||
extcon_data->gpio_active_low = pdata->gpio_active_low;
|
||||
|
@ -692,10 +692,9 @@ static int max14577_muic_probe(struct platform_device *pdev)
|
||||
u8 id;
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
dev_err(&pdev->dev, "failed to allocate memory\n");
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->dev = &pdev->dev;
|
||||
info->max14577 = max14577;
|
||||
|
||||
|
@ -255,10 +255,10 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
|
||||
case ADC_DEBOUNCE_TIME_10MS:
|
||||
case ADC_DEBOUNCE_TIME_25MS:
|
||||
case ADC_DEBOUNCE_TIME_38_62MS:
|
||||
ret = max77693_update_reg(info->max77693->regmap_muic,
|
||||
ret = regmap_update_bits(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_CTRL3,
|
||||
time << CONTROL3_ADCDBSET_SHIFT,
|
||||
CONTROL3_ADCDBSET_MASK);
|
||||
CONTROL3_ADCDBSET_MASK,
|
||||
time << CONTROL3_ADCDBSET_SHIFT);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to set ADC debounce time\n");
|
||||
return ret;
|
||||
@ -286,15 +286,15 @@ static int max77693_muic_set_path(struct max77693_muic_info *info,
|
||||
u8 val, bool attached)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 ctrl1, ctrl2 = 0;
|
||||
unsigned int ctrl1, ctrl2 = 0;
|
||||
|
||||
if (attached)
|
||||
ctrl1 = val;
|
||||
else
|
||||
ctrl1 = CONTROL1_SW_OPEN;
|
||||
|
||||
ret = max77693_update_reg(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK);
|
||||
ret = regmap_update_bits(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "failed to update MUIC register\n");
|
||||
return ret;
|
||||
@ -305,9 +305,9 @@ static int max77693_muic_set_path(struct max77693_muic_info *info,
|
||||
else
|
||||
ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
|
||||
|
||||
ret = max77693_update_reg(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_CTRL2, ctrl2,
|
||||
CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
|
||||
ret = regmap_update_bits(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_CTRL2,
|
||||
CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "failed to update MUIC register\n");
|
||||
return ret;
|
||||
@ -969,8 +969,8 @@ static void max77693_muic_irq_work(struct work_struct *work)
|
||||
if (info->irq == muic_irqs[i].virq)
|
||||
irq_type = muic_irqs[i].irq;
|
||||
|
||||
ret = max77693_bulk_read(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_STATUS1, 2, info->status);
|
||||
ret = regmap_bulk_read(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_STATUS1, info->status, 2);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to read MUIC register\n");
|
||||
mutex_unlock(&info->mutex);
|
||||
@ -1042,8 +1042,8 @@ static int max77693_muic_detect_accessory(struct max77693_muic_info *info)
|
||||
mutex_lock(&info->mutex);
|
||||
|
||||
/* Read STATUSx register to detect accessory */
|
||||
ret = max77693_bulk_read(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_STATUS1, 2, info->status);
|
||||
ret = regmap_bulk_read(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_STATUS1, info->status, 2);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to read MUIC register\n");
|
||||
mutex_unlock(&info->mutex);
|
||||
@ -1095,14 +1095,13 @@ static int max77693_muic_probe(struct platform_device *pdev)
|
||||
int delay_jiffies;
|
||||
int ret;
|
||||
int i;
|
||||
u8 id;
|
||||
unsigned int id;
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info),
|
||||
GFP_KERNEL);
|
||||
if (!info) {
|
||||
dev_err(&pdev->dev, "failed to allocate memory\n");
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->dev = &pdev->dev;
|
||||
info->max77693 = max77693;
|
||||
if (info->max77693->regmap_muic) {
|
||||
@ -1154,7 +1153,8 @@ static int max77693_muic_probe(struct platform_device *pdev)
|
||||
struct max77693_muic_irq *muic_irq = &muic_irqs[i];
|
||||
unsigned int virq = 0;
|
||||
|
||||
virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq);
|
||||
virq = regmap_irq_get_virq(max77693->irq_data_muic,
|
||||
muic_irq->irq);
|
||||
if (!virq) {
|
||||
ret = -EINVAL;
|
||||
goto err_irq;
|
||||
@ -1183,7 +1183,6 @@ static int max77693_muic_probe(struct platform_device *pdev)
|
||||
goto err_irq;
|
||||
}
|
||||
info->edev->name = DEV_NAME;
|
||||
info->edev->dev.parent = &pdev->dev;
|
||||
|
||||
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
|
||||
if (ret) {
|
||||
@ -1204,7 +1203,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
|
||||
enum max77693_irq_source irq_src
|
||||
= MAX77693_IRQ_GROUP_NR;
|
||||
|
||||
max77693_write_reg(info->max77693->regmap_muic,
|
||||
regmap_write(info->max77693->regmap_muic,
|
||||
init_data[i].addr,
|
||||
init_data[i].data);
|
||||
|
||||
@ -1262,7 +1261,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
|
||||
max77693_muic_set_path(info, info->path_uart, true);
|
||||
|
||||
/* Check revision number of MUIC device*/
|
||||
ret = max77693_read_reg(info->max77693->regmap_muic,
|
||||
ret = regmap_read(info->max77693->regmap_muic,
|
||||
MAX77693_MUIC_REG_ID, &id);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to read revision number\n");
|
||||
|
@ -661,10 +661,8 @@ static int max8997_muic_probe(struct platform_device *pdev)
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
|
||||
GFP_KERNEL);
|
||||
if (!info) {
|
||||
dev_err(&pdev->dev, "failed to allocate memory\n");
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->dev = &pdev->dev;
|
||||
info->muic = max8997->muic;
|
||||
@ -706,7 +704,6 @@ static int max8997_muic_probe(struct platform_device *pdev)
|
||||
goto err_irq;
|
||||
}
|
||||
info->edev->name = DEV_NAME;
|
||||
info->edev->dev.parent = &pdev->dev;
|
||||
|
||||
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
|
||||
if (ret) {
|
||||
|
@ -194,7 +194,6 @@ static int palmas_usb_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL);
|
||||
palmas_usb->edev->dev.parent = palmas_usb->dev;
|
||||
palmas_usb->edev->mutually_exclusive = mutually_exclusive;
|
||||
|
||||
status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
|
||||
@ -278,7 +277,7 @@ static int palmas_usb_resume(struct device *dev)
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_usb_suspend, palmas_usb_resume);
|
||||
|
||||
static struct of_device_id of_palmas_match_tbl[] = {
|
||||
static const struct of_device_id of_palmas_match_tbl[] = {
|
||||
{ .compatible = "ti,palmas-usb", },
|
||||
{ .compatible = "ti,palmas-usb-vid", },
|
||||
{ .compatible = "ti,twl6035-usb", },
|
||||
|
724
drivers/extcon/extcon-sm5502.c
Normal file
724
drivers/extcon/extcon-sm5502.c
Normal file
@ -0,0 +1,724 @@
|
||||
/*
|
||||
* extcon-sm5502.c - Silicon Mitus SM5502 extcon drvier to support USB switches
|
||||
*
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd
|
||||
* Author: Chanwoo Choi <cw00.choi@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/extcon.h>
|
||||
#include <linux/extcon/sm5502.h>
|
||||
|
||||
#define DELAY_MS_DEFAULT 17000 /* unit: millisecond */
|
||||
|
||||
struct muic_irq {
|
||||
unsigned int irq;
|
||||
const char *name;
|
||||
unsigned int virq;
|
||||
};
|
||||
|
||||
struct reg_data {
|
||||
u8 reg;
|
||||
unsigned int val;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
struct sm5502_muic_info {
|
||||
struct device *dev;
|
||||
struct extcon_dev *edev;
|
||||
|
||||
struct i2c_client *i2c;
|
||||
struct regmap *regmap;
|
||||
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
struct muic_irq *muic_irqs;
|
||||
unsigned int num_muic_irqs;
|
||||
int irq;
|
||||
bool irq_attach;
|
||||
bool irq_detach;
|
||||
struct work_struct irq_work;
|
||||
|
||||
struct reg_data *reg_data;
|
||||
unsigned int num_reg_data;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/* Default value of SM5502 register to bring up MUIC device. */
|
||||
static struct reg_data sm5502_reg_data[] = {
|
||||
{
|
||||
.reg = SM5502_REG_CONTROL,
|
||||
.val = SM5502_REG_CONTROL_MASK_INT_MASK,
|
||||
.invert = false,
|
||||
}, {
|
||||
.reg = SM5502_REG_INTMASK1,
|
||||
.val = SM5502_REG_INTM1_KP_MASK
|
||||
| SM5502_REG_INTM1_LKP_MASK
|
||||
| SM5502_REG_INTM1_LKR_MASK,
|
||||
.invert = true,
|
||||
}, {
|
||||
.reg = SM5502_REG_INTMASK2,
|
||||
.val = SM5502_REG_INTM2_VBUS_DET_MASK
|
||||
| SM5502_REG_INTM2_REV_ACCE_MASK
|
||||
| SM5502_REG_INTM2_ADC_CHG_MASK
|
||||
| SM5502_REG_INTM2_STUCK_KEY_MASK
|
||||
| SM5502_REG_INTM2_STUCK_KEY_RCV_MASK
|
||||
| SM5502_REG_INTM2_MHL_MASK,
|
||||
.invert = true,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
/* List of detectable cables */
|
||||
enum {
|
||||
EXTCON_CABLE_USB = 0,
|
||||
EXTCON_CABLE_USB_HOST,
|
||||
EXTCON_CABLE_TA,
|
||||
|
||||
EXTCON_CABLE_END,
|
||||
};
|
||||
|
||||
static const char *sm5502_extcon_cable[] = {
|
||||
[EXTCON_CABLE_USB] = "USB",
|
||||
[EXTCON_CABLE_USB_HOST] = "USB-Host",
|
||||
[EXTCON_CABLE_TA] = "TA",
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Define supported accessory type */
|
||||
enum sm5502_muic_acc_type {
|
||||
SM5502_MUIC_ADC_GROUND = 0x0,
|
||||
SM5502_MUIC_ADC_SEND_END_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S1_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S2_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S3_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S4_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S5_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S6_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S7_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S8_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S9_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S10_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S11_BUTTON,
|
||||
SM5502_MUIC_ADC_REMOTE_S12_BUTTON,
|
||||
SM5502_MUIC_ADC_RESERVED_ACC_1,
|
||||
SM5502_MUIC_ADC_RESERVED_ACC_2,
|
||||
SM5502_MUIC_ADC_RESERVED_ACC_3,
|
||||
SM5502_MUIC_ADC_RESERVED_ACC_4,
|
||||
SM5502_MUIC_ADC_RESERVED_ACC_5,
|
||||
SM5502_MUIC_ADC_AUDIO_TYPE2,
|
||||
SM5502_MUIC_ADC_PHONE_POWERED_DEV,
|
||||
SM5502_MUIC_ADC_TTY_CONVERTER,
|
||||
SM5502_MUIC_ADC_UART_CABLE,
|
||||
SM5502_MUIC_ADC_TYPE1_CHARGER,
|
||||
SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB,
|
||||
SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB,
|
||||
SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE,
|
||||
SM5502_MUIC_ADC_TYPE2_CHARGER,
|
||||
SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART,
|
||||
SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART,
|
||||
SM5502_MUIC_ADC_AUDIO_TYPE1,
|
||||
SM5502_MUIC_ADC_OPEN = 0x1f,
|
||||
|
||||
/* The below accessories have same ADC value (0x1f or 0x1e).
|
||||
So, Device type1 is used to separate specific accessory. */
|
||||
/* |---------|--ADC| */
|
||||
/* | [7:5]|[4:0]| */
|
||||
SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e, /* | 001|11110| */
|
||||
SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END = 0x5e, /* | 010|11110| */
|
||||
/* |Dev Type1|--ADC| */
|
||||
SM5502_MUIC_ADC_OPEN_USB = 0x5f, /* | 010|11111| */
|
||||
SM5502_MUIC_ADC_OPEN_TA = 0xdf, /* | 110|11111| */
|
||||
SM5502_MUIC_ADC_OPEN_USB_OTG = 0xff, /* | 111|11111| */
|
||||
};
|
||||
|
||||
/* List of supported interrupt for SM5502 */
|
||||
static struct muic_irq sm5502_muic_irqs[] = {
|
||||
{ SM5502_IRQ_INT1_ATTACH, "muic-attach" },
|
||||
{ SM5502_IRQ_INT1_DETACH, "muic-detach" },
|
||||
{ SM5502_IRQ_INT1_KP, "muic-kp" },
|
||||
{ SM5502_IRQ_INT1_LKP, "muic-lkp" },
|
||||
{ SM5502_IRQ_INT1_LKR, "muic-lkr" },
|
||||
{ SM5502_IRQ_INT1_OVP_EVENT, "muic-ovp-event" },
|
||||
{ SM5502_IRQ_INT1_OCP_EVENT, "muic-ocp-event" },
|
||||
{ SM5502_IRQ_INT1_OVP_OCP_DIS, "muic-ovp-ocp-dis" },
|
||||
{ SM5502_IRQ_INT2_VBUS_DET, "muic-vbus-det" },
|
||||
{ SM5502_IRQ_INT2_REV_ACCE, "muic-rev-acce" },
|
||||
{ SM5502_IRQ_INT2_ADC_CHG, "muic-adc-chg" },
|
||||
{ SM5502_IRQ_INT2_STUCK_KEY, "muic-stuck-key" },
|
||||
{ SM5502_IRQ_INT2_STUCK_KEY_RCV, "muic-stuck-key-rcv" },
|
||||
{ SM5502_IRQ_INT2_MHL, "muic-mhl" },
|
||||
};
|
||||
|
||||
/* Define interrupt list of SM5502 to register regmap_irq */
|
||||
static const struct regmap_irq sm5502_irqs[] = {
|
||||
/* INT1 interrupts */
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_ATTACH_MASK, },
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_DETACH_MASK, },
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_KP_MASK, },
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKP_MASK, },
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKR_MASK, },
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_EVENT_MASK, },
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OCP_EVENT_MASK, },
|
||||
{ .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_OCP_DIS_MASK, },
|
||||
|
||||
/* INT2 interrupts */
|
||||
{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_VBUS_DET_MASK,},
|
||||
{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_REV_ACCE_MASK, },
|
||||
{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_ADC_CHG_MASK, },
|
||||
{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_MASK, },
|
||||
{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK, },
|
||||
{ .reg_offset = 1, .mask = SM5502_IRQ_INT2_MHL_MASK, },
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip sm5502_muic_irq_chip = {
|
||||
.name = "sm5502",
|
||||
.status_base = SM5502_REG_INT1,
|
||||
.mask_base = SM5502_REG_INTMASK1,
|
||||
.mask_invert = false,
|
||||
.num_regs = 2,
|
||||
.irqs = sm5502_irqs,
|
||||
.num_irqs = ARRAY_SIZE(sm5502_irqs),
|
||||
};
|
||||
|
||||
/* Define regmap configuration of SM5502 for I2C communication */
|
||||
static bool sm5502_muic_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case SM5502_REG_INTMASK1:
|
||||
case SM5502_REG_INTMASK2:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct regmap_config sm5502_muic_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_reg = sm5502_muic_volatile_reg,
|
||||
.max_register = SM5502_REG_END,
|
||||
};
|
||||
|
||||
/* Change DM_CON/DP_CON/VBUSIN switch according to cable type */
|
||||
static int sm5502_muic_set_path(struct sm5502_muic_info *info,
|
||||
unsigned int con_sw, unsigned int vbus_sw,
|
||||
bool attached)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!attached) {
|
||||
con_sw = DM_DP_SWITCH_OPEN;
|
||||
vbus_sw = VBUSIN_SWITCH_OPEN;
|
||||
}
|
||||
|
||||
switch (con_sw) {
|
||||
case DM_DP_SWITCH_OPEN:
|
||||
case DM_DP_SWITCH_USB:
|
||||
case DM_DP_SWITCH_AUDIO:
|
||||
case DM_DP_SWITCH_UART:
|
||||
ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
|
||||
SM5502_REG_MANUAL_SW1_DP_MASK |
|
||||
SM5502_REG_MANUAL_SW1_DM_MASK,
|
||||
con_sw);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev,
|
||||
"cannot update DM_CON/DP_CON switch\n");
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
|
||||
con_sw);
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
switch (vbus_sw) {
|
||||
case VBUSIN_SWITCH_OPEN:
|
||||
case VBUSIN_SWITCH_VBUSOUT:
|
||||
case VBUSIN_SWITCH_MIC:
|
||||
case VBUSIN_SWITCH_VBUSOUT_WITH_USB:
|
||||
ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
|
||||
SM5502_REG_MANUAL_SW1_VBUSIN_MASK,
|
||||
vbus_sw);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev,
|
||||
"cannot update VBUSIN switch\n");
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw);
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return cable type of attached or detached accessories */
|
||||
static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
|
||||
{
|
||||
unsigned int cable_type = -1, adc, dev_type1;
|
||||
int ret;
|
||||
|
||||
/* Read ADC value according to external cable or button */
|
||||
ret = regmap_read(info->regmap, SM5502_REG_ADC, &adc);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to read ADC register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If ADC is SM5502_MUIC_ADC_GROUND(0x0), external cable hasn't
|
||||
* connected with to MUIC device.
|
||||
*/
|
||||
cable_type &= SM5502_REG_ADC_MASK;
|
||||
if (cable_type == SM5502_MUIC_ADC_GROUND)
|
||||
return SM5502_MUIC_ADC_GROUND;
|
||||
|
||||
switch (cable_type) {
|
||||
case SM5502_MUIC_ADC_GROUND:
|
||||
case SM5502_MUIC_ADC_SEND_END_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S1_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S2_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S3_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S4_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S5_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S6_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S7_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S8_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S9_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S10_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S11_BUTTON:
|
||||
case SM5502_MUIC_ADC_REMOTE_S12_BUTTON:
|
||||
case SM5502_MUIC_ADC_RESERVED_ACC_1:
|
||||
case SM5502_MUIC_ADC_RESERVED_ACC_2:
|
||||
case SM5502_MUIC_ADC_RESERVED_ACC_3:
|
||||
case SM5502_MUIC_ADC_RESERVED_ACC_4:
|
||||
case SM5502_MUIC_ADC_RESERVED_ACC_5:
|
||||
case SM5502_MUIC_ADC_AUDIO_TYPE2:
|
||||
case SM5502_MUIC_ADC_PHONE_POWERED_DEV:
|
||||
case SM5502_MUIC_ADC_TTY_CONVERTER:
|
||||
case SM5502_MUIC_ADC_UART_CABLE:
|
||||
case SM5502_MUIC_ADC_TYPE1_CHARGER:
|
||||
case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB:
|
||||
case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB:
|
||||
case SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE:
|
||||
case SM5502_MUIC_ADC_TYPE2_CHARGER:
|
||||
case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART:
|
||||
case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART:
|
||||
break;
|
||||
case SM5502_MUIC_ADC_AUDIO_TYPE1:
|
||||
/*
|
||||
* Check whether cable type is
|
||||
* SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE
|
||||
* or SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END
|
||||
* by using Button event.
|
||||
*/
|
||||
break;
|
||||
case SM5502_MUIC_ADC_OPEN:
|
||||
ret = regmap_read(info->regmap, SM5502_REG_DEV_TYPE1,
|
||||
&dev_type1);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to read DEV_TYPE1 reg\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (dev_type1) {
|
||||
case SM5502_REG_DEV_TYPE1_USB_SDP_MASK:
|
||||
cable_type = SM5502_MUIC_ADC_OPEN_USB;
|
||||
break;
|
||||
case SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK:
|
||||
cable_type = SM5502_MUIC_ADC_OPEN_TA;
|
||||
break;
|
||||
case SM5502_REG_DEV_TYPE1_USB_OTG_MASK:
|
||||
cable_type = SM5502_MUIC_ADC_OPEN_USB_OTG;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(info->dev,
|
||||
"cannot identify the cable type: adc(0x%x) "
|
||||
"dev_type1(0x%x)\n", adc, dev_type1);
|
||||
return -EINVAL;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
dev_err(info->dev,
|
||||
"failed to identify the cable type: adc(0x%x)\n", adc);
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
return cable_type;
|
||||
}
|
||||
|
||||
static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
|
||||
bool attached)
|
||||
{
|
||||
static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
|
||||
const char **cable_names = info->edev->supported_cable;
|
||||
unsigned int cable_type = SM5502_MUIC_ADC_GROUND;
|
||||
unsigned int con_sw = DM_DP_SWITCH_OPEN;
|
||||
unsigned int vbus_sw = VBUSIN_SWITCH_OPEN;
|
||||
unsigned int idx = 0;
|
||||
int ret;
|
||||
|
||||
if (!cable_names)
|
||||
return 0;
|
||||
|
||||
/* Get the type of attached or detached cable */
|
||||
if (attached)
|
||||
cable_type = sm5502_muic_get_cable_type(info);
|
||||
else if (!attached)
|
||||
cable_type = prev_cable_type;
|
||||
prev_cable_type = cable_type;
|
||||
|
||||
switch (cable_type) {
|
||||
case SM5502_MUIC_ADC_OPEN_USB:
|
||||
idx = EXTCON_CABLE_USB;
|
||||
con_sw = DM_DP_SWITCH_USB;
|
||||
vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB;
|
||||
break;
|
||||
case SM5502_MUIC_ADC_OPEN_TA:
|
||||
idx = EXTCON_CABLE_TA;
|
||||
con_sw = DM_DP_SWITCH_OPEN;
|
||||
vbus_sw = VBUSIN_SWITCH_VBUSOUT;
|
||||
break;
|
||||
case SM5502_MUIC_ADC_OPEN_USB_OTG:
|
||||
idx = EXTCON_CABLE_USB_HOST;
|
||||
con_sw = DM_DP_SWITCH_USB;
|
||||
vbus_sw = VBUSIN_SWITCH_OPEN;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(info->dev,
|
||||
"cannot handle this cable_type (0x%x)\n", cable_type);
|
||||
return 0;
|
||||
};
|
||||
|
||||
/* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
|
||||
ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Change the state of external accessory */
|
||||
extcon_set_cable_state(info->edev, cable_names[idx], attached);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sm5502_muic_irq_work(struct work_struct *work)
|
||||
{
|
||||
struct sm5502_muic_info *info = container_of(work,
|
||||
struct sm5502_muic_info, irq_work);
|
||||
int ret = 0;
|
||||
|
||||
if (!info->edev)
|
||||
return;
|
||||
|
||||
mutex_lock(&info->mutex);
|
||||
|
||||
/* Detect attached or detached cables */
|
||||
if (info->irq_attach) {
|
||||
ret = sm5502_muic_cable_handler(info, true);
|
||||
info->irq_attach = false;
|
||||
}
|
||||
if (info->irq_detach) {
|
||||
ret = sm5502_muic_cable_handler(info, false);
|
||||
info->irq_detach = false;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(info->dev, "failed to handle MUIC interrupt\n");
|
||||
|
||||
mutex_unlock(&info->mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets irq_attach or irq_detach in sm5502_muic_info and returns 0.
|
||||
* Returns -ESRCH if irq_type does not match registered IRQ for this dev type.
|
||||
*/
|
||||
static int sm5502_parse_irq(struct sm5502_muic_info *info, int irq_type)
|
||||
{
|
||||
switch (irq_type) {
|
||||
case SM5502_IRQ_INT1_ATTACH:
|
||||
info->irq_attach = true;
|
||||
break;
|
||||
case SM5502_IRQ_INT1_DETACH:
|
||||
info->irq_detach = true;
|
||||
break;
|
||||
case SM5502_IRQ_INT1_KP:
|
||||
case SM5502_IRQ_INT1_LKP:
|
||||
case SM5502_IRQ_INT1_LKR:
|
||||
case SM5502_IRQ_INT1_OVP_EVENT:
|
||||
case SM5502_IRQ_INT1_OCP_EVENT:
|
||||
case SM5502_IRQ_INT1_OVP_OCP_DIS:
|
||||
case SM5502_IRQ_INT2_VBUS_DET:
|
||||
case SM5502_IRQ_INT2_REV_ACCE:
|
||||
case SM5502_IRQ_INT2_ADC_CHG:
|
||||
case SM5502_IRQ_INT2_STUCK_KEY:
|
||||
case SM5502_IRQ_INT2_STUCK_KEY_RCV:
|
||||
case SM5502_IRQ_INT2_MHL:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t sm5502_muic_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct sm5502_muic_info *info = data;
|
||||
int i, irq_type = -1, ret;
|
||||
|
||||
for (i = 0; i < info->num_muic_irqs; i++)
|
||||
if (irq == info->muic_irqs[i].virq)
|
||||
irq_type = info->muic_irqs[i].irq;
|
||||
|
||||
ret = sm5502_parse_irq(info, irq_type);
|
||||
if (ret < 0) {
|
||||
dev_warn(info->dev, "cannot handle is interrupt:%d\n",
|
||||
irq_type);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
schedule_work(&info->irq_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void sm5502_muic_detect_cable_wq(struct work_struct *work)
|
||||
{
|
||||
struct sm5502_muic_info *info = container_of(to_delayed_work(work),
|
||||
struct sm5502_muic_info, wq_detcable);
|
||||
int ret;
|
||||
|
||||
/* Notify the state of connector cable or not */
|
||||
ret = sm5502_muic_cable_handler(info, true);
|
||||
if (ret < 0)
|
||||
dev_warn(info->dev, "failed to detect cable state\n");
|
||||
}
|
||||
|
||||
static void sm5502_init_dev_type(struct sm5502_muic_info *info)
|
||||
{
|
||||
unsigned int reg_data, vendor_id, version_id;
|
||||
int i, ret;
|
||||
|
||||
/* To test I2C, Print version_id and vendor_id of SM5502 */
|
||||
ret = regmap_read(info->regmap, SM5502_REG_DEVICE_ID, ®_data);
|
||||
if (ret) {
|
||||
dev_err(info->dev,
|
||||
"failed to read DEVICE_ID register: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
vendor_id = ((reg_data & SM5502_REG_DEVICE_ID_VENDOR_MASK) >>
|
||||
SM5502_REG_DEVICE_ID_VENDOR_SHIFT);
|
||||
version_id = ((reg_data & SM5502_REG_DEVICE_ID_VERSION_MASK) >>
|
||||
SM5502_REG_DEVICE_ID_VERSION_SHIFT);
|
||||
|
||||
dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
|
||||
version_id, vendor_id);
|
||||
|
||||
/* Initiazle the register of SM5502 device to bring-up */
|
||||
for (i = 0; i < info->num_reg_data; i++) {
|
||||
unsigned int val = 0;
|
||||
|
||||
if (!info->reg_data[i].invert)
|
||||
val |= ~info->reg_data[i].val;
|
||||
else
|
||||
val = info->reg_data[i].val;
|
||||
regmap_write(info->regmap, info->reg_data[i].reg, val);
|
||||
}
|
||||
}
|
||||
|
||||
static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device_node *np = i2c->dev.of_node;
|
||||
struct sm5502_muic_info *info;
|
||||
int i, ret, irq_flags;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
i2c_set_clientdata(i2c, info);
|
||||
|
||||
info->dev = &i2c->dev;
|
||||
info->i2c = i2c;
|
||||
info->irq = i2c->irq;
|
||||
info->muic_irqs = sm5502_muic_irqs;
|
||||
info->num_muic_irqs = ARRAY_SIZE(sm5502_muic_irqs);
|
||||
info->reg_data = sm5502_reg_data;
|
||||
info->num_reg_data = ARRAY_SIZE(sm5502_reg_data);
|
||||
|
||||
mutex_init(&info->mutex);
|
||||
|
||||
INIT_WORK(&info->irq_work, sm5502_muic_irq_work);
|
||||
|
||||
info->regmap = devm_regmap_init_i2c(i2c, &sm5502_muic_regmap_config);
|
||||
if (IS_ERR(info->regmap)) {
|
||||
ret = PTR_ERR(info->regmap);
|
||||
dev_err(info->dev, "failed to allocate register map: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Support irq domain for SM5502 MUIC device */
|
||||
irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
|
||||
ret = regmap_add_irq_chip(info->regmap, info->irq, irq_flags, 0,
|
||||
&sm5502_muic_irq_chip, &info->irq_data);
|
||||
if (ret != 0) {
|
||||
dev_err(info->dev, "failed to request IRQ %d: %d\n",
|
||||
info->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < info->num_muic_irqs; i++) {
|
||||
struct muic_irq *muic_irq = &info->muic_irqs[i];
|
||||
unsigned int virq = 0;
|
||||
|
||||
virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
|
||||
if (virq <= 0)
|
||||
return -EINVAL;
|
||||
muic_irq->virq = virq;
|
||||
|
||||
ret = devm_request_threaded_irq(info->dev, virq, NULL,
|
||||
sm5502_muic_irq_handler,
|
||||
IRQF_NO_SUSPEND,
|
||||
muic_irq->name, info);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed: irq request (IRQ: %d,"
|
||||
" error :%d)\n", muic_irq->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate extcon device */
|
||||
info->edev = devm_extcon_dev_allocate(info->dev, sm5502_extcon_cable);
|
||||
if (IS_ERR(info->edev)) {
|
||||
dev_err(info->dev, "failed to allocate memory for extcon\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
info->edev->name = np->name;
|
||||
|
||||
/* Register extcon device */
|
||||
ret = devm_extcon_dev_register(info->dev, info->edev);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to register extcon device\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect accessory after completing the initialization of platform
|
||||
*
|
||||
* - 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.
|
||||
*/
|
||||
INIT_DELAYED_WORK(&info->wq_detcable, sm5502_muic_detect_cable_wq);
|
||||
queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
|
||||
msecs_to_jiffies(DELAY_MS_DEFAULT));
|
||||
|
||||
/* Initialize SM5502 device and print vendor id and version id */
|
||||
sm5502_init_dev_type(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm5502_muic_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
|
||||
|
||||
regmap_del_irq_chip(info->irq, info->irq_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id sm5502_dt_match[] = {
|
||||
{ .compatible = "siliconmitus,sm5502-muic" },
|
||||
{ },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sm5502_muic_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
|
||||
|
||||
enable_irq_wake(info->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm5502_muic_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
|
||||
|
||||
disable_irq_wake(info->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops,
|
||||
sm5502_muic_suspend, sm5502_muic_resume);
|
||||
|
||||
static const struct i2c_device_id sm5502_i2c_id[] = {
|
||||
{ "sm5502", TYPE_SM5502 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id);
|
||||
|
||||
static struct i2c_driver sm5502_muic_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "sm5502",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &sm5502_muic_pm_ops,
|
||||
.of_match_table = sm5502_dt_match,
|
||||
},
|
||||
.probe = sm5022_muic_i2c_probe,
|
||||
.remove = sm5502_muic_i2c_remove,
|
||||
.id_table = sm5502_i2c_id,
|
||||
};
|
||||
|
||||
static int __init sm5502_muic_i2c_init(void)
|
||||
{
|
||||
return i2c_add_driver(&sm5502_muic_i2c_driver);
|
||||
}
|
||||
subsys_initcall(sm5502_muic_i2c_init);
|
||||
|
||||
MODULE_DESCRIPTION("Silicon Mitus SM5502 Extcon driver");
|
||||
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -384,6 +384,7 @@ config MFD_MAX77693
|
||||
depends on I2C=y
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
Say yes here to add support for Maxim Semiconductor MAX77693.
|
||||
This is a companion Power Management IC with Flash, Haptic, Charger,
|
||||
|
@ -116,7 +116,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o
|
||||
|
||||
obj-$(CONFIG_MFD_MAX14577) += max14577.o
|
||||
obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
|
||||
obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
|
||||
obj-$(CONFIG_MFD_MAX77693) += max77693.o
|
||||
obj-$(CONFIG_MFD_MAX8907) += max8907.o
|
||||
max8925-objs := max8925-core.o max8925-i2c.o
|
||||
obj-$(CONFIG_MFD_MAX8925) += max8925.o
|
||||
|
@ -1,336 +0,0 @@
|
||||
/*
|
||||
* max77693-irq.c - Interrupt controller support for MAX77693
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics Co.Ltd
|
||||
* SangYoung Son <hello.son@samsung.com>
|
||||
*
|
||||
* This program is not provided / owned by Maxim Integrated Products.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* This driver is based on max8997-irq.c
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/mfd/max77693.h>
|
||||
#include <linux/mfd/max77693-private.h>
|
||||
|
||||
static const u8 max77693_mask_reg[] = {
|
||||
[LED_INT] = MAX77693_LED_REG_FLASH_INT_MASK,
|
||||
[TOPSYS_INT] = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
|
||||
[CHG_INT] = MAX77693_CHG_REG_CHG_INT_MASK,
|
||||
[MUIC_INT1] = MAX77693_MUIC_REG_INTMASK1,
|
||||
[MUIC_INT2] = MAX77693_MUIC_REG_INTMASK2,
|
||||
[MUIC_INT3] = MAX77693_MUIC_REG_INTMASK3,
|
||||
};
|
||||
|
||||
static struct regmap *max77693_get_regmap(struct max77693_dev *max77693,
|
||||
enum max77693_irq_source src)
|
||||
{
|
||||
switch (src) {
|
||||
case LED_INT ... CHG_INT:
|
||||
return max77693->regmap;
|
||||
case MUIC_INT1 ... MUIC_INT3:
|
||||
return max77693->regmap_muic;
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
struct max77693_irq_data {
|
||||
int mask;
|
||||
enum max77693_irq_source group;
|
||||
};
|
||||
|
||||
#define DECLARE_IRQ(idx, _group, _mask) \
|
||||
[(idx)] = { .group = (_group), .mask = (_mask) }
|
||||
static const struct max77693_irq_data max77693_irqs[] = {
|
||||
DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_OPEN, LED_INT, 1 << 0),
|
||||
DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_SHORT, LED_INT, 1 << 1),
|
||||
DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_OPEN, LED_INT, 1 << 2),
|
||||
DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_SHORT, LED_INT, 1 << 3),
|
||||
DECLARE_IRQ(MAX77693_LED_IRQ_MAX_FLASH, LED_INT, 1 << 4),
|
||||
|
||||
DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T120C_INT, TOPSYS_INT, 1 << 0),
|
||||
DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T140C_INT, TOPSYS_INT, 1 << 1),
|
||||
DECLARE_IRQ(MAX77693_TOPSYS_IRQ_LOWSYS_INT, TOPSYS_INT, 1 << 3),
|
||||
|
||||
DECLARE_IRQ(MAX77693_CHG_IRQ_BYP_I, CHG_INT, 1 << 0),
|
||||
DECLARE_IRQ(MAX77693_CHG_IRQ_THM_I, CHG_INT, 1 << 2),
|
||||
DECLARE_IRQ(MAX77693_CHG_IRQ_BAT_I, CHG_INT, 1 << 3),
|
||||
DECLARE_IRQ(MAX77693_CHG_IRQ_CHG_I, CHG_INT, 1 << 4),
|
||||
DECLARE_IRQ(MAX77693_CHG_IRQ_CHGIN_I, CHG_INT, 1 << 6),
|
||||
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC, MUIC_INT1, 1 << 0),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_LOW, MUIC_INT1, 1 << 1),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_ERR, MUIC_INT1, 1 << 2),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC1K, MUIC_INT1, 1 << 3),
|
||||
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGTYP, MUIC_INT2, 1 << 0),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGDETREUN, MUIC_INT2, 1 << 1),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DCDTMR, MUIC_INT2, 1 << 2),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DXOVP, MUIC_INT2, 1 << 3),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VBVOLT, MUIC_INT2, 1 << 4),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VIDRM, MUIC_INT2, 1 << 5),
|
||||
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_EOC, MUIC_INT3, 1 << 0),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CGMBC, MUIC_INT3, 1 << 1),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_OVP, MUIC_INT3, 1 << 2),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, MUIC_INT3, 1 << 3),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, MUIC_INT3, 1 << 4),
|
||||
DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_BAT_DET, MUIC_INT3, 1 << 5),
|
||||
};
|
||||
|
||||
static void max77693_irq_lock(struct irq_data *data)
|
||||
{
|
||||
struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
|
||||
|
||||
mutex_lock(&max77693->irqlock);
|
||||
}
|
||||
|
||||
static void max77693_irq_sync_unlock(struct irq_data *data)
|
||||
{
|
||||
struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
|
||||
u8 mask_reg = max77693_mask_reg[i];
|
||||
struct regmap *map = max77693_get_regmap(max77693, i);
|
||||
|
||||
if (mask_reg == MAX77693_REG_INVALID ||
|
||||
IS_ERR_OR_NULL(map))
|
||||
continue;
|
||||
max77693->irq_masks_cache[i] = max77693->irq_masks_cur[i];
|
||||
|
||||
max77693_write_reg(map, max77693_mask_reg[i],
|
||||
max77693->irq_masks_cur[i]);
|
||||
}
|
||||
|
||||
mutex_unlock(&max77693->irqlock);
|
||||
}
|
||||
|
||||
static const inline struct max77693_irq_data *
|
||||
irq_to_max77693_irq(struct max77693_dev *max77693, int irq)
|
||||
{
|
||||
struct irq_data *data = irq_get_irq_data(irq);
|
||||
return &max77693_irqs[data->hwirq];
|
||||
}
|
||||
|
||||
static void max77693_irq_mask(struct irq_data *data)
|
||||
{
|
||||
struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
|
||||
const struct max77693_irq_data *irq_data =
|
||||
irq_to_max77693_irq(max77693, data->irq);
|
||||
|
||||
if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
|
||||
return;
|
||||
|
||||
if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
|
||||
max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
|
||||
else
|
||||
max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
|
||||
}
|
||||
|
||||
static void max77693_irq_unmask(struct irq_data *data)
|
||||
{
|
||||
struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
|
||||
const struct max77693_irq_data *irq_data =
|
||||
irq_to_max77693_irq(max77693, data->irq);
|
||||
|
||||
if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
|
||||
return;
|
||||
|
||||
if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
|
||||
max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
|
||||
else
|
||||
max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
|
||||
}
|
||||
|
||||
static struct irq_chip max77693_irq_chip = {
|
||||
.name = "max77693",
|
||||
.irq_bus_lock = max77693_irq_lock,
|
||||
.irq_bus_sync_unlock = max77693_irq_sync_unlock,
|
||||
.irq_mask = max77693_irq_mask,
|
||||
.irq_unmask = max77693_irq_unmask,
|
||||
};
|
||||
|
||||
#define MAX77693_IRQSRC_CHG (1 << 0)
|
||||
#define MAX77693_IRQSRC_TOP (1 << 1)
|
||||
#define MAX77693_IRQSRC_FLASH (1 << 2)
|
||||
#define MAX77693_IRQSRC_MUIC (1 << 3)
|
||||
static irqreturn_t max77693_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct max77693_dev *max77693 = data;
|
||||
u8 irq_reg[MAX77693_IRQ_GROUP_NR] = {};
|
||||
u8 irq_src;
|
||||
int ret;
|
||||
int i, cur_irq;
|
||||
|
||||
ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_INTSRC,
|
||||
&irq_src);
|
||||
if (ret < 0) {
|
||||
dev_err(max77693->dev, "Failed to read interrupt source: %d\n",
|
||||
ret);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (irq_src & MAX77693_IRQSRC_CHG)
|
||||
/* CHG_INT */
|
||||
ret = max77693_read_reg(max77693->regmap, MAX77693_CHG_REG_CHG_INT,
|
||||
&irq_reg[CHG_INT]);
|
||||
|
||||
if (irq_src & MAX77693_IRQSRC_TOP)
|
||||
/* TOPSYS_INT */
|
||||
ret = max77693_read_reg(max77693->regmap,
|
||||
MAX77693_PMIC_REG_TOPSYS_INT, &irq_reg[TOPSYS_INT]);
|
||||
|
||||
if (irq_src & MAX77693_IRQSRC_FLASH)
|
||||
/* LED_INT */
|
||||
ret = max77693_read_reg(max77693->regmap,
|
||||
MAX77693_LED_REG_FLASH_INT, &irq_reg[LED_INT]);
|
||||
|
||||
if (irq_src & MAX77693_IRQSRC_MUIC)
|
||||
/* MUIC INT1 ~ INT3 */
|
||||
max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1,
|
||||
MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]);
|
||||
|
||||
/* Apply masking */
|
||||
for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
|
||||
if (i >= MUIC_INT1 && i <= MUIC_INT3)
|
||||
irq_reg[i] &= max77693->irq_masks_cur[i];
|
||||
else
|
||||
irq_reg[i] &= ~max77693->irq_masks_cur[i];
|
||||
}
|
||||
|
||||
/* Report */
|
||||
for (i = 0; i < MAX77693_IRQ_NR; i++) {
|
||||
if (irq_reg[max77693_irqs[i].group] & max77693_irqs[i].mask) {
|
||||
cur_irq = irq_find_mapping(max77693->irq_domain, i);
|
||||
if (cur_irq)
|
||||
handle_nested_irq(cur_irq);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int max77693_irq_resume(struct max77693_dev *max77693)
|
||||
{
|
||||
if (max77693->irq)
|
||||
max77693_irq_thread(0, max77693);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77693_irq_domain_map(struct irq_domain *d, unsigned int irq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct max77693_dev *max77693 = d->host_data;
|
||||
|
||||
irq_set_chip_data(irq, max77693);
|
||||
irq_set_chip_and_handler(irq, &max77693_irq_chip, handle_edge_irq);
|
||||
irq_set_nested_thread(irq, 1);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops max77693_irq_domain_ops = {
|
||||
.map = max77693_irq_domain_map,
|
||||
};
|
||||
|
||||
int max77693_irq_init(struct max77693_dev *max77693)
|
||||
{
|
||||
struct irq_domain *domain;
|
||||
int i;
|
||||
int ret = 0;
|
||||
u8 intsrc_mask;
|
||||
|
||||
mutex_init(&max77693->irqlock);
|
||||
|
||||
/* Mask individual interrupt sources */
|
||||
for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
|
||||
struct regmap *map;
|
||||
/* MUIC IRQ 0:MASK 1:NOT MASK */
|
||||
/* Other IRQ 1:MASK 0:NOT MASK */
|
||||
if (i >= MUIC_INT1 && i <= MUIC_INT3) {
|
||||
max77693->irq_masks_cur[i] = 0x00;
|
||||
max77693->irq_masks_cache[i] = 0x00;
|
||||
} else {
|
||||
max77693->irq_masks_cur[i] = 0xff;
|
||||
max77693->irq_masks_cache[i] = 0xff;
|
||||
}
|
||||
map = max77693_get_regmap(max77693, i);
|
||||
|
||||
if (IS_ERR_OR_NULL(map))
|
||||
continue;
|
||||
if (max77693_mask_reg[i] == MAX77693_REG_INVALID)
|
||||
continue;
|
||||
if (i >= MUIC_INT1 && i <= MUIC_INT3)
|
||||
max77693_write_reg(map, max77693_mask_reg[i], 0x00);
|
||||
else
|
||||
max77693_write_reg(map, max77693_mask_reg[i], 0xff);
|
||||
}
|
||||
|
||||
domain = irq_domain_add_linear(NULL, MAX77693_IRQ_NR,
|
||||
&max77693_irq_domain_ops, max77693);
|
||||
if (!domain) {
|
||||
dev_err(max77693->dev, "could not create irq domain\n");
|
||||
ret = -ENODEV;
|
||||
goto err_irq;
|
||||
}
|
||||
max77693->irq_domain = domain;
|
||||
|
||||
/* Unmask max77693 interrupt */
|
||||
ret = max77693_read_reg(max77693->regmap,
|
||||
MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask);
|
||||
if (ret < 0) {
|
||||
dev_err(max77693->dev, "fail to read PMIC register\n");
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
intsrc_mask &= ~(MAX77693_IRQSRC_CHG);
|
||||
intsrc_mask &= ~(MAX77693_IRQSRC_FLASH);
|
||||
intsrc_mask &= ~(MAX77693_IRQSRC_MUIC);
|
||||
ret = max77693_write_reg(max77693->regmap,
|
||||
MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask);
|
||||
if (ret < 0) {
|
||||
dev_err(max77693->dev, "fail to write PMIC register\n");
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"max77693-irq", max77693);
|
||||
if (ret)
|
||||
dev_err(max77693->dev, "Failed to request IRQ %d: %d\n",
|
||||
max77693->irq, ret);
|
||||
|
||||
err_irq:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void max77693_irq_exit(struct max77693_dev *max77693)
|
||||
{
|
||||
if (max77693->irq)
|
||||
free_irq(max77693->irq, max77693);
|
||||
}
|
@ -49,75 +49,106 @@ static const struct mfd_cell max77693_devs[] = {
|
||||
{ .name = "max77693-haptic", },
|
||||
};
|
||||
|
||||
int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(map, reg, &val);
|
||||
*dest = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max77693_read_reg);
|
||||
|
||||
int max77693_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(map, reg, buf, count);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max77693_bulk_read);
|
||||
|
||||
int max77693_write_reg(struct regmap *map, u8 reg, u8 value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(map, reg, value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max77693_write_reg);
|
||||
|
||||
int max77693_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_write(map, reg, buf, count);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max77693_bulk_write);
|
||||
|
||||
int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(map, reg, mask, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max77693_update_reg);
|
||||
|
||||
static const struct regmap_config max77693_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MAX77693_PMIC_REG_END,
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77693_led_irqs[] = {
|
||||
{ .mask = LED_IRQ_FLED2_OPEN, },
|
||||
{ .mask = LED_IRQ_FLED2_SHORT, },
|
||||
{ .mask = LED_IRQ_FLED1_OPEN, },
|
||||
{ .mask = LED_IRQ_FLED1_SHORT, },
|
||||
{ .mask = LED_IRQ_MAX_FLASH, },
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip max77693_led_irq_chip = {
|
||||
.name = "max77693-led",
|
||||
.status_base = MAX77693_LED_REG_FLASH_INT,
|
||||
.mask_base = MAX77693_LED_REG_FLASH_INT_MASK,
|
||||
.mask_invert = false,
|
||||
.num_regs = 1,
|
||||
.irqs = max77693_led_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max77693_led_irqs),
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77693_topsys_irqs[] = {
|
||||
{ .mask = TOPSYS_IRQ_T120C_INT, },
|
||||
{ .mask = TOPSYS_IRQ_T140C_INT, },
|
||||
{ .mask = TOPSYS_IRQ_LOWSYS_INT, },
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip max77693_topsys_irq_chip = {
|
||||
.name = "max77693-topsys",
|
||||
.status_base = MAX77693_PMIC_REG_TOPSYS_INT,
|
||||
.mask_base = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
|
||||
.mask_invert = false,
|
||||
.num_regs = 1,
|
||||
.irqs = max77693_topsys_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max77693_topsys_irqs),
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77693_charger_irqs[] = {
|
||||
{ .mask = CHG_IRQ_BYP_I, },
|
||||
{ .mask = CHG_IRQ_THM_I, },
|
||||
{ .mask = CHG_IRQ_BAT_I, },
|
||||
{ .mask = CHG_IRQ_CHG_I, },
|
||||
{ .mask = CHG_IRQ_CHGIN_I, },
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip max77693_charger_irq_chip = {
|
||||
.name = "max77693-charger",
|
||||
.status_base = MAX77693_CHG_REG_CHG_INT,
|
||||
.mask_base = MAX77693_CHG_REG_CHG_INT_MASK,
|
||||
.mask_invert = false,
|
||||
.num_regs = 1,
|
||||
.irqs = max77693_charger_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max77693_charger_irqs),
|
||||
};
|
||||
|
||||
static const struct regmap_config max77693_regmap_muic_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MAX77693_MUIC_REG_END,
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77693_muic_irqs[] = {
|
||||
{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC, },
|
||||
{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_LOW, },
|
||||
{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_ERR, },
|
||||
{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC1K, },
|
||||
|
||||
{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGTYP, },
|
||||
{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGDETREUN, },
|
||||
{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DCDTMR, },
|
||||
{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DXOVP, },
|
||||
{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VBVOLT, },
|
||||
{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VIDRM, },
|
||||
|
||||
{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_EOC, },
|
||||
{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CGMBC, },
|
||||
{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_OVP, },
|
||||
{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_MBCCHG_ERR, },
|
||||
{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CHG_ENABLED, },
|
||||
{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_BAT_DET, },
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip max77693_muic_irq_chip = {
|
||||
.name = "max77693-muic",
|
||||
.status_base = MAX77693_MUIC_REG_INT1,
|
||||
.mask_base = MAX77693_MUIC_REG_INTMASK1,
|
||||
.mask_invert = true,
|
||||
.num_regs = 3,
|
||||
.irqs = max77693_muic_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max77693_muic_irqs),
|
||||
};
|
||||
|
||||
static int max77693_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max77693_dev *max77693;
|
||||
u8 reg_data;
|
||||
unsigned int reg_data;
|
||||
int ret = 0;
|
||||
|
||||
max77693 = devm_kzalloc(&i2c->dev,
|
||||
@ -139,7 +170,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
|
||||
ret = regmap_read(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
|
||||
®_data);
|
||||
if (ret < 0) {
|
||||
dev_err(max77693->dev, "device not found on this channel\n");
|
||||
@ -176,9 +207,45 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
||||
goto err_regmap_muic;
|
||||
}
|
||||
|
||||
ret = max77693_irq_init(max77693);
|
||||
if (ret < 0)
|
||||
goto err_irq;
|
||||
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING, 0,
|
||||
&max77693_led_irq_chip,
|
||||
&max77693->irq_data_led);
|
||||
if (ret) {
|
||||
dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
|
||||
goto err_regmap_muic;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING, 0,
|
||||
&max77693_topsys_irq_chip,
|
||||
&max77693->irq_data_topsys);
|
||||
if (ret) {
|
||||
dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
|
||||
goto err_irq_topsys;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING, 0,
|
||||
&max77693_charger_irq_chip,
|
||||
&max77693->irq_data_charger);
|
||||
if (ret) {
|
||||
dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
|
||||
goto err_irq_charger;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING, 0,
|
||||
&max77693_muic_irq_chip,
|
||||
&max77693->irq_data_muic);
|
||||
if (ret) {
|
||||
dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
|
||||
goto err_irq_muic;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(max77693->dev);
|
||||
|
||||
@ -190,8 +257,14 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
||||
return ret;
|
||||
|
||||
err_mfd:
|
||||
max77693_irq_exit(max77693);
|
||||
err_irq:
|
||||
mfd_remove_devices(max77693->dev);
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
|
||||
err_irq_muic:
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
|
||||
err_irq_charger:
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
|
||||
err_irq_topsys:
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
|
||||
err_regmap_muic:
|
||||
i2c_unregister_device(max77693->haptic);
|
||||
err_i2c_haptic:
|
||||
@ -204,7 +277,12 @@ static int max77693_i2c_remove(struct i2c_client *i2c)
|
||||
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
|
||||
|
||||
mfd_remove_devices(max77693->dev);
|
||||
max77693_irq_exit(max77693);
|
||||
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
|
||||
regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
|
||||
|
||||
i2c_unregister_device(max77693->muic);
|
||||
i2c_unregister_device(max77693->haptic);
|
||||
|
||||
@ -222,8 +300,11 @@ static int max77693_suspend(struct device *dev)
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
irq_set_irq_wake(max77693->irq, 1);
|
||||
if (device_may_wakeup(dev)) {
|
||||
enable_irq_wake(max77693->irq);
|
||||
disable_irq(max77693->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -232,9 +313,12 @@ static int max77693_resume(struct device *dev)
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
irq_set_irq_wake(max77693->irq, 0);
|
||||
return max77693_irq_resume(max77693);
|
||||
if (device_may_wakeup(dev)) {
|
||||
disable_irq_wake(max77693->irq);
|
||||
enable_irq(max77693->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops max77693_pm = {
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/mfd/max77693.h>
|
||||
#include <linux/mfd/max77693-private.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define CHGIN_ILIM_STEP_20mA 20000
|
||||
|
||||
@ -39,9 +40,9 @@
|
||||
static int max77693_chg_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
unsigned int val;
|
||||
|
||||
ret = max77693_read_reg(rdev->regmap, rdev->desc->enable_reg, &val);
|
||||
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -57,12 +58,11 @@ static int max77693_chg_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int chg_min_uA = rdev->constraints->min_uA;
|
||||
unsigned int chg_max_uA = rdev->constraints->max_uA;
|
||||
u8 reg, sel;
|
||||
unsigned int reg, sel;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = max77693_read_reg(rdev->regmap,
|
||||
MAX77693_CHG_REG_CHG_CNFG_09, ®);
|
||||
ret = regmap_read(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -96,7 +96,7 @@ static int max77693_chg_set_current_limit(struct regulator_dev *rdev,
|
||||
/* the first four codes for charger current are all 60mA */
|
||||
sel += 3;
|
||||
|
||||
return max77693_write_reg(rdev->regmap,
|
||||
return regmap_write(rdev->regmap,
|
||||
MAX77693_CHG_REG_CHG_CNFG_09, sel);
|
||||
}
|
||||
/* end of CHARGER regulator ops */
|
||||
|
287
include/linux/extcon/sm5502.h
Normal file
287
include/linux/extcon/sm5502.h
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* sm5502.h
|
||||
*
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_EXTCON_SM5502_H
|
||||
#define __LINUX_EXTCON_SM5502_H
|
||||
|
||||
enum sm5502_types {
|
||||
TYPE_SM5502,
|
||||
};
|
||||
|
||||
/* SM5502 registers */
|
||||
enum sm5502_reg {
|
||||
SM5502_REG_DEVICE_ID = 0x01,
|
||||
SM5502_REG_CONTROL,
|
||||
SM5502_REG_INT1,
|
||||
SM5502_REG_INT2,
|
||||
SM5502_REG_INTMASK1,
|
||||
SM5502_REG_INTMASK2,
|
||||
SM5502_REG_ADC,
|
||||
SM5502_REG_TIMING_SET1,
|
||||
SM5502_REG_TIMING_SET2,
|
||||
SM5502_REG_DEV_TYPE1,
|
||||
SM5502_REG_DEV_TYPE2,
|
||||
SM5502_REG_BUTTON1,
|
||||
SM5502_REG_BUTTON2,
|
||||
SM5502_REG_CAR_KIT_STATUS,
|
||||
SM5502_REG_RSVD1,
|
||||
SM5502_REG_RSVD2,
|
||||
SM5502_REG_RSVD3,
|
||||
SM5502_REG_RSVD4,
|
||||
SM5502_REG_MANUAL_SW1,
|
||||
SM5502_REG_MANUAL_SW2,
|
||||
SM5502_REG_DEV_TYPE3,
|
||||
SM5502_REG_RSVD5,
|
||||
SM5502_REG_RSVD6,
|
||||
SM5502_REG_RSVD7,
|
||||
SM5502_REG_RSVD8,
|
||||
SM5502_REG_RSVD9,
|
||||
SM5502_REG_RESET,
|
||||
SM5502_REG_RSVD10,
|
||||
SM5502_REG_RESERVED_ID1,
|
||||
SM5502_REG_RSVD11,
|
||||
SM5502_REG_RSVD12,
|
||||
SM5502_REG_RESERVED_ID2,
|
||||
SM5502_REG_RSVD13,
|
||||
SM5502_REG_OCP,
|
||||
SM5502_REG_RSVD14,
|
||||
SM5502_REG_RSVD15,
|
||||
SM5502_REG_RSVD16,
|
||||
SM5502_REG_RSVD17,
|
||||
SM5502_REG_RSVD18,
|
||||
SM5502_REG_RSVD19,
|
||||
SM5502_REG_RSVD20,
|
||||
SM5502_REG_RSVD21,
|
||||
SM5502_REG_RSVD22,
|
||||
SM5502_REG_RSVD23,
|
||||
SM5502_REG_RSVD24,
|
||||
SM5502_REG_RSVD25,
|
||||
SM5502_REG_RSVD26,
|
||||
SM5502_REG_RSVD27,
|
||||
SM5502_REG_RSVD28,
|
||||
SM5502_REG_RSVD29,
|
||||
SM5502_REG_RSVD30,
|
||||
SM5502_REG_RSVD31,
|
||||
SM5502_REG_RSVD32,
|
||||
SM5502_REG_RSVD33,
|
||||
SM5502_REG_RSVD34,
|
||||
SM5502_REG_RSVD35,
|
||||
SM5502_REG_RSVD36,
|
||||
SM5502_REG_RESERVED_ID3,
|
||||
|
||||
SM5502_REG_END,
|
||||
};
|
||||
|
||||
/* Define SM5502 MASK/SHIFT constant */
|
||||
#define SM5502_REG_DEVICE_ID_VENDOR_SHIFT 0
|
||||
#define SM5502_REG_DEVICE_ID_VERSION_SHIFT 3
|
||||
#define SM5502_REG_DEVICE_ID_VENDOR_MASK (0x3 << SM5502_REG_DEVICE_ID_VENDOR_SHIFT)
|
||||
#define SM5502_REG_DEVICE_ID_VERSION_MASK (0x1f << SM5502_REG_DEVICE_ID_VERSION_SHIFT)
|
||||
|
||||
#define SM5502_REG_CONTROL_MASK_INT_SHIFT 0
|
||||
#define SM5502_REG_CONTROL_WAIT_SHIFT 1
|
||||
#define SM5502_REG_CONTROL_MANUAL_SW_SHIFT 2
|
||||
#define SM5502_REG_CONTROL_RAW_DATA_SHIFT 3
|
||||
#define SM5502_REG_CONTROL_SW_OPEN_SHIFT 4
|
||||
#define SM5502_REG_CONTROL_MASK_INT_MASK (0x1 << SM5502_REG_CONTROL_MASK_INT_SHIFT)
|
||||
#define SM5502_REG_CONTROL_WAIT_MASK (0x1 << SM5502_REG_CONTROL_WAIT_SHIFT)
|
||||
#define SM5502_REG_CONTROL_MANUAL_SW_MASK (0x1 << SM5502_REG_CONTROL_MANUAL_SW_SHIFT)
|
||||
#define SM5502_REG_CONTROL_RAW_DATA_MASK (0x1 << SM5502_REG_CONTROL_RAW_DATA_SHIFT)
|
||||
#define SM5502_REG_CONTROL_SW_OPEN_MASK (0x1 << SM5502_REG_CONTROL_SW_OPEN_SHIFT)
|
||||
|
||||
#define SM5502_REG_INTM1_ATTACH_SHIFT 0
|
||||
#define SM5502_REG_INTM1_DETACH_SHIFT 1
|
||||
#define SM5502_REG_INTM1_KP_SHIFT 2
|
||||
#define SM5502_REG_INTM1_LKP_SHIFT 3
|
||||
#define SM5502_REG_INTM1_LKR_SHIFT 4
|
||||
#define SM5502_REG_INTM1_OVP_EVENT_SHIFT 5
|
||||
#define SM5502_REG_INTM1_OCP_EVENT_SHIFT 6
|
||||
#define SM5502_REG_INTM1_OVP_OCP_DIS_SHIFT 7
|
||||
#define SM5502_REG_INTM1_ATTACH_MASK (0x1 << SM5502_REG_INTM1_ATTACH_SHIFT)
|
||||
#define SM5502_REG_INTM1_DETACH_MASK (0x1 << SM5502_REG_INTM1_DETACH_SHIFT)
|
||||
#define SM5502_REG_INTM1_KP_MASK (0x1 << SM5502_REG_INTM1_KP_SHIFT)
|
||||
#define SM5502_REG_INTM1_LKP_MASK (0x1 << SM5502_REG_INTM1_LKP_SHIFT)
|
||||
#define SM5502_REG_INTM1_LKR_MASK (0x1 << SM5502_REG_INTM1_LKR_SHIFT)
|
||||
#define SM5502_REG_INTM1_OVP_EVENT_MASK (0x1 << SM5502_REG_INTM1_OVP_EVENT_SHIFT)
|
||||
#define SM5502_REG_INTM1_OCP_EVENT_MASK (0x1 << SM5502_REG_INTM1_OCP_EVENT_SHIFT)
|
||||
#define SM5502_REG_INTM1_OVP_OCP_DIS_MASK (0x1 << SM5502_REG_INTM1_OVP_OCP_DIS_SHIFT)
|
||||
|
||||
#define SM5502_REG_INTM2_VBUS_DET_SHIFT 0
|
||||
#define SM5502_REG_INTM2_REV_ACCE_SHIFT 1
|
||||
#define SM5502_REG_INTM2_ADC_CHG_SHIFT 2
|
||||
#define SM5502_REG_INTM2_STUCK_KEY_SHIFT 3
|
||||
#define SM5502_REG_INTM2_STUCK_KEY_RCV_SHIFT 4
|
||||
#define SM5502_REG_INTM2_MHL_SHIFT 5
|
||||
#define SM5502_REG_INTM2_VBUS_DET_MASK (0x1 << SM5502_REG_INTM2_VBUS_DET_SHIFT)
|
||||
#define SM5502_REG_INTM2_REV_ACCE_MASK (0x1 << SM5502_REG_INTM2_REV_ACCE_SHIFT)
|
||||
#define SM5502_REG_INTM2_ADC_CHG_MASK (0x1 << SM5502_REG_INTM2_ADC_CHG_SHIFT)
|
||||
#define SM5502_REG_INTM2_STUCK_KEY_MASK (0x1 << SM5502_REG_INTM2_STUCK_KEY_SHIFT)
|
||||
#define SM5502_REG_INTM2_STUCK_KEY_RCV_MASK (0x1 << SM5502_REG_INTM2_STUCK_KEY_RCV_SHIFT)
|
||||
#define SM5502_REG_INTM2_MHL_MASK (0x1 << SM5502_REG_INTM2_MHL_SHIFT)
|
||||
|
||||
#define SM5502_REG_ADC_SHIFT 0
|
||||
#define SM5502_REG_ADC_MASK (0x1f << SM5502_REG_ADC_SHIFT)
|
||||
|
||||
#define SM5502_REG_TIMING_SET1_KEY_PRESS_SHIFT 4
|
||||
#define SM5502_REG_TIMING_SET1_KEY_PRESS_MASK (0xf << SM5502_REG_TIMING_SET1_KEY_PRESS_SHIFT)
|
||||
#define TIMING_KEY_PRESS_100MS 0x0
|
||||
#define TIMING_KEY_PRESS_200MS 0x1
|
||||
#define TIMING_KEY_PRESS_300MS 0x2
|
||||
#define TIMING_KEY_PRESS_400MS 0x3
|
||||
#define TIMING_KEY_PRESS_500MS 0x4
|
||||
#define TIMING_KEY_PRESS_600MS 0x5
|
||||
#define TIMING_KEY_PRESS_700MS 0x6
|
||||
#define TIMING_KEY_PRESS_800MS 0x7
|
||||
#define TIMING_KEY_PRESS_900MS 0x8
|
||||
#define TIMING_KEY_PRESS_1000MS 0x9
|
||||
#define SM5502_REG_TIMING_SET1_ADC_DET_SHIFT 0
|
||||
#define SM5502_REG_TIMING_SET1_ADC_DET_MASK (0xf << SM5502_REG_TIMING_SET1_ADC_DET_SHIFT)
|
||||
#define TIMING_ADC_DET_50MS 0x0
|
||||
#define TIMING_ADC_DET_100MS 0x1
|
||||
#define TIMING_ADC_DET_150MS 0x2
|
||||
#define TIMING_ADC_DET_200MS 0x3
|
||||
#define TIMING_ADC_DET_300MS 0x4
|
||||
#define TIMING_ADC_DET_400MS 0x5
|
||||
#define TIMING_ADC_DET_500MS 0x6
|
||||
#define TIMING_ADC_DET_600MS 0x7
|
||||
#define TIMING_ADC_DET_700MS 0x8
|
||||
#define TIMING_ADC_DET_800MS 0x9
|
||||
#define TIMING_ADC_DET_900MS 0xA
|
||||
#define TIMING_ADC_DET_1000MS 0xB
|
||||
|
||||
#define SM5502_REG_TIMING_SET2_SW_WAIT_SHIFT 4
|
||||
#define SM5502_REG_TIMING_SET2_SW_WAIT_MASK (0xf << SM5502_REG_TIMING_SET2_SW_WAIT_SHIFT)
|
||||
#define TIMING_SW_WAIT_10MS 0x0
|
||||
#define TIMING_SW_WAIT_30MS 0x1
|
||||
#define TIMING_SW_WAIT_50MS 0x2
|
||||
#define TIMING_SW_WAIT_70MS 0x3
|
||||
#define TIMING_SW_WAIT_90MS 0x4
|
||||
#define TIMING_SW_WAIT_110MS 0x5
|
||||
#define TIMING_SW_WAIT_130MS 0x6
|
||||
#define TIMING_SW_WAIT_150MS 0x7
|
||||
#define TIMING_SW_WAIT_170MS 0x8
|
||||
#define TIMING_SW_WAIT_190MS 0x9
|
||||
#define TIMING_SW_WAIT_210MS 0xA
|
||||
#define SM5502_REG_TIMING_SET2_LONG_KEY_SHIFT 0
|
||||
#define SM5502_REG_TIMING_SET2_LONG_KEY_MASK (0xf << SM5502_REG_TIMING_SET2_LONG_KEY_SHIFT)
|
||||
#define TIMING_LONG_KEY_300MS 0x0
|
||||
#define TIMING_LONG_KEY_400MS 0x1
|
||||
#define TIMING_LONG_KEY_500MS 0x2
|
||||
#define TIMING_LONG_KEY_600MS 0x3
|
||||
#define TIMING_LONG_KEY_700MS 0x4
|
||||
#define TIMING_LONG_KEY_800MS 0x5
|
||||
#define TIMING_LONG_KEY_900MS 0x6
|
||||
#define TIMING_LONG_KEY_1000MS 0x7
|
||||
#define TIMING_LONG_KEY_1100MS 0x8
|
||||
#define TIMING_LONG_KEY_1200MS 0x9
|
||||
#define TIMING_LONG_KEY_1300MS 0xA
|
||||
#define TIMING_LONG_KEY_1400MS 0xB
|
||||
#define TIMING_LONG_KEY_1500MS 0xC
|
||||
|
||||
#define SM5502_REG_DEV_TYPE1_AUDIO_TYPE1_SHIFT 0
|
||||
#define SM5502_REG_DEV_TYPE1_AUDIO_TYPE2_SHIFT 1
|
||||
#define SM5502_REG_DEV_TYPE1_USB_SDP_SHIFT 2
|
||||
#define SM5502_REG_DEV_TYPE1_UART_SHIFT 3
|
||||
#define SM5502_REG_DEV_TYPE1_CAR_KIT_CHARGER_SHIFT 4
|
||||
#define SM5502_REG_DEV_TYPE1_USB_CHG_SHIFT 5
|
||||
#define SM5502_REG_DEV_TYPE1_DEDICATED_CHG_SHIFT 6
|
||||
#define SM5502_REG_DEV_TYPE1_USB_OTG_SHIFT 7
|
||||
#define SM5502_REG_DEV_TYPE1_AUDIO_TYPE1_MASK (0x1 << SM5502_REG_DEV_TYPE1_AUDIO_TYPE1_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE1_AUDIO_TYPE1__MASK (0x1 << SM5502_REG_DEV_TYPE1_AUDIO_TYPE2_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE1_USB_SDP_MASK (0x1 << SM5502_REG_DEV_TYPE1_USB_SDP_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE1_UART_MASK (0x1 << SM5502_REG_DEV_TYPE1_UART_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE1_CAR_KIT_CHARGER_MASK (0x1 << SM5502_REG_DEV_TYPE1_CAR_KIT_CHARGER_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE1_USB_CHG_MASK (0x1 << SM5502_REG_DEV_TYPE1_USB_CHG_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK (0x1 << SM5502_REG_DEV_TYPE1_DEDICATED_CHG_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE1_USB_OTG_MASK (0x1 << SM5502_REG_DEV_TYPE1_USB_OTG_SHIFT)
|
||||
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_USB_ON_SHIFT 0
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_USB_OFF_SHIFT 1
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_UART_ON_SHIFT 2
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_UART_OFF_SHIFT 3
|
||||
#define SM5502_REG_DEV_TYPE2_PPD_SHIFT 4
|
||||
#define SM5502_REG_DEV_TYPE2_TTY_SHIFT 5
|
||||
#define SM5502_REG_DEV_TYPE2_AV_CABLE_SHIFT 6
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_USB_ON_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_USB_ON_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_USB_OFF_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_USB_OFF_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_UART_ON_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_UART_ON_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE2_JIG_UART_OFF_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_UART_OFF_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE2_PPD_MASK (0x1 << SM5502_REG_DEV_TYPE2_PPD_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE2_TTY_MASK (0x1 << SM5502_REG_DEV_TYPE2_TTY_SHIFT)
|
||||
#define SM5502_REG_DEV_TYPE2_AV_CABLE_MASK (0x1 << SM5502_REG_DEV_TYPE2_AV_CABLE_SHIFT)
|
||||
|
||||
#define SM5502_REG_MANUAL_SW1_VBUSIN_SHIFT 0
|
||||
#define SM5502_REG_MANUAL_SW1_DP_SHIFT 2
|
||||
#define SM5502_REG_MANUAL_SW1_DM_SHIFT 5
|
||||
#define SM5502_REG_MANUAL_SW1_VBUSIN_MASK (0x3 << SM5502_REG_MANUAL_SW1_VBUSIN_SHIFT)
|
||||
#define SM5502_REG_MANUAL_SW1_DP_MASK (0x7 << SM5502_REG_MANUAL_SW1_DP_SHIFT)
|
||||
#define SM5502_REG_MANUAL_SW1_DM_MASK (0x7 << SM5502_REG_MANUAL_SW1_DM_SHIFT)
|
||||
#define VBUSIN_SWITCH_OPEN 0x0
|
||||
#define VBUSIN_SWITCH_VBUSOUT 0x1
|
||||
#define VBUSIN_SWITCH_MIC 0x2
|
||||
#define VBUSIN_SWITCH_VBUSOUT_WITH_USB 0x3
|
||||
#define DM_DP_CON_SWITCH_OPEN 0x0
|
||||
#define DM_DP_CON_SWITCH_USB 0x1
|
||||
#define DM_DP_CON_SWITCH_AUDIO 0x2
|
||||
#define DM_DP_CON_SWITCH_UART 0x3
|
||||
#define DM_DP_SWITCH_OPEN ((DM_DP_CON_SWITCH_OPEN <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
|
||||
| (DM_DP_CON_SWITCH_OPEN <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
|
||||
#define DM_DP_SWITCH_USB ((DM_DP_CON_SWITCH_USB <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
|
||||
| (DM_DP_CON_SWITCH_USB <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
|
||||
#define DM_DP_SWITCH_AUDIO ((DM_DP_CON_SWITCH_AUDIO <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
|
||||
| (DM_DP_CON_SWITCH_AUDIO <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
|
||||
#define DM_DP_SWITCH_UART ((DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
|
||||
| (DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
|
||||
|
||||
/* SM5502 Interrupts */
|
||||
enum sm5502_irq {
|
||||
/* INT1 */
|
||||
SM5502_IRQ_INT1_ATTACH,
|
||||
SM5502_IRQ_INT1_DETACH,
|
||||
SM5502_IRQ_INT1_KP,
|
||||
SM5502_IRQ_INT1_LKP,
|
||||
SM5502_IRQ_INT1_LKR,
|
||||
SM5502_IRQ_INT1_OVP_EVENT,
|
||||
SM5502_IRQ_INT1_OCP_EVENT,
|
||||
SM5502_IRQ_INT1_OVP_OCP_DIS,
|
||||
|
||||
/* INT2 */
|
||||
SM5502_IRQ_INT2_VBUS_DET,
|
||||
SM5502_IRQ_INT2_REV_ACCE,
|
||||
SM5502_IRQ_INT2_ADC_CHG,
|
||||
SM5502_IRQ_INT2_STUCK_KEY,
|
||||
SM5502_IRQ_INT2_STUCK_KEY_RCV,
|
||||
SM5502_IRQ_INT2_MHL,
|
||||
|
||||
SM5502_IRQ_NUM,
|
||||
};
|
||||
|
||||
#define SM5502_IRQ_INT1_ATTACH_MASK BIT(0)
|
||||
#define SM5502_IRQ_INT1_DETACH_MASK BIT(1)
|
||||
#define SM5502_IRQ_INT1_KP_MASK BIT(2)
|
||||
#define SM5502_IRQ_INT1_LKP_MASK BIT(3)
|
||||
#define SM5502_IRQ_INT1_LKR_MASK BIT(4)
|
||||
#define SM5502_IRQ_INT1_OVP_EVENT_MASK BIT(5)
|
||||
#define SM5502_IRQ_INT1_OCP_EVENT_MASK BIT(6)
|
||||
#define SM5502_IRQ_INT1_OVP_OCP_DIS_MASK BIT(7)
|
||||
#define SM5502_IRQ_INT2_VBUS_DET_MASK BIT(0)
|
||||
#define SM5502_IRQ_INT2_REV_ACCE_MASK BIT(1)
|
||||
#define SM5502_IRQ_INT2_ADC_CHG_MASK BIT(2)
|
||||
#define SM5502_IRQ_INT2_STUCK_KEY_MASK BIT(3)
|
||||
#define SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK BIT(4)
|
||||
#define SM5502_IRQ_INT2_MHL_MASK BIT(5)
|
||||
|
||||
#endif /* __LINUX_EXTCON_SM5502_H */
|
@ -127,6 +127,9 @@ struct arizona_pdata {
|
||||
/** Internal pull on GPIO5 is disabled when used for jack detection */
|
||||
bool jd_gpio5_nopull;
|
||||
|
||||
/** set to true if jackdet contact opens on insert */
|
||||
bool jd_invert;
|
||||
|
||||
/** Use the headphone detect circuit to identify the accessory */
|
||||
bool hpdet_acc_id;
|
||||
|
||||
|
@ -262,6 +262,41 @@ enum max77693_irq_source {
|
||||
MAX77693_IRQ_GROUP_NR,
|
||||
};
|
||||
|
||||
#define LED_IRQ_FLED2_OPEN BIT(0)
|
||||
#define LED_IRQ_FLED2_SHORT BIT(1)
|
||||
#define LED_IRQ_FLED1_OPEN BIT(2)
|
||||
#define LED_IRQ_FLED1_SHORT BIT(3)
|
||||
#define LED_IRQ_MAX_FLASH BIT(4)
|
||||
|
||||
#define TOPSYS_IRQ_T120C_INT BIT(0)
|
||||
#define TOPSYS_IRQ_T140C_INT BIT(1)
|
||||
#define TOPSYS_IRQ_LOWSYS_INT BIT(3)
|
||||
|
||||
#define CHG_IRQ_BYP_I BIT(0)
|
||||
#define CHG_IRQ_THM_I BIT(2)
|
||||
#define CHG_IRQ_BAT_I BIT(3)
|
||||
#define CHG_IRQ_CHG_I BIT(4)
|
||||
#define CHG_IRQ_CHGIN_I BIT(6)
|
||||
|
||||
#define MUIC_IRQ_INT1_ADC BIT(0)
|
||||
#define MUIC_IRQ_INT1_ADC_LOW BIT(1)
|
||||
#define MUIC_IRQ_INT1_ADC_ERR BIT(2)
|
||||
#define MUIC_IRQ_INT1_ADC1K BIT(3)
|
||||
|
||||
#define MUIC_IRQ_INT2_CHGTYP BIT(0)
|
||||
#define MUIC_IRQ_INT2_CHGDETREUN BIT(1)
|
||||
#define MUIC_IRQ_INT2_DCDTMR BIT(2)
|
||||
#define MUIC_IRQ_INT2_DXOVP BIT(3)
|
||||
#define MUIC_IRQ_INT2_VBVOLT BIT(4)
|
||||
#define MUIC_IRQ_INT2_VIDRM BIT(5)
|
||||
|
||||
#define MUIC_IRQ_INT3_EOC BIT(0)
|
||||
#define MUIC_IRQ_INT3_CGMBC BIT(1)
|
||||
#define MUIC_IRQ_INT3_OVP BIT(2)
|
||||
#define MUIC_IRQ_INT3_MBCCHG_ERR BIT(3)
|
||||
#define MUIC_IRQ_INT3_CHG_ENABLED BIT(4)
|
||||
#define MUIC_IRQ_INT3_BAT_DET BIT(5)
|
||||
|
||||
enum max77693_irq {
|
||||
/* PMIC - FLASH */
|
||||
MAX77693_LED_IRQ_FLED2_OPEN,
|
||||
@ -282,6 +317,10 @@ enum max77693_irq {
|
||||
MAX77693_CHG_IRQ_CHG_I,
|
||||
MAX77693_CHG_IRQ_CHGIN_I,
|
||||
|
||||
MAX77693_IRQ_NR,
|
||||
};
|
||||
|
||||
enum max77693_irq_muic {
|
||||
/* MUIC INT1 */
|
||||
MAX77693_MUIC_IRQ_INT1_ADC,
|
||||
MAX77693_MUIC_IRQ_INT1_ADC_LOW,
|
||||
@ -304,7 +343,7 @@ enum max77693_irq {
|
||||
MAX77693_MUIC_IRQ_INT3_CHG_ENABLED,
|
||||
MAX77693_MUIC_IRQ_INT3_BAT_DET,
|
||||
|
||||
MAX77693_IRQ_NR,
|
||||
MAX77693_MUIC_IRQ_NR,
|
||||
};
|
||||
|
||||
struct max77693_dev {
|
||||
@ -319,7 +358,10 @@ struct max77693_dev {
|
||||
struct regmap *regmap_muic;
|
||||
struct regmap *regmap_haptic;
|
||||
|
||||
struct irq_domain *irq_domain;
|
||||
struct regmap_irq_chip_data *irq_data_led;
|
||||
struct regmap_irq_chip_data *irq_data_topsys;
|
||||
struct regmap_irq_chip_data *irq_data_charger;
|
||||
struct regmap_irq_chip_data *irq_data_muic;
|
||||
|
||||
int irq;
|
||||
int irq_gpio;
|
||||
@ -332,14 +374,6 @@ enum max77693_types {
|
||||
TYPE_MAX77693,
|
||||
};
|
||||
|
||||
extern int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest);
|
||||
extern int max77693_bulk_read(struct regmap *map, u8 reg, int count,
|
||||
u8 *buf);
|
||||
extern int max77693_write_reg(struct regmap *map, u8 reg, u8 value);
|
||||
extern int max77693_bulk_write(struct regmap *map, u8 reg, int count,
|
||||
u8 *buf);
|
||||
extern int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask);
|
||||
|
||||
extern int max77693_irq_init(struct max77693_dev *max77686);
|
||||
extern void max77693_irq_exit(struct max77693_dev *max77686);
|
||||
extern int max77693_irq_resume(struct max77693_dev *max77686);
|
||||
|
Loading…
Reference in New Issue
Block a user