summaryrefslogtreecommitdiff
path: root/drivers/extcon
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
commite5fd91f1ef340da553f7a79da9540c3db711c937 (patch)
treeb11842027dc6641da63f4bcc524f8678263304a3 /drivers/extcon
parent2a9b0348e685a63d97486f6749622b61e9e3292f (diff)
Linux-libre 4.2-gnu
Diffstat (limited to 'drivers/extcon')
-rw-r--r--drivers/extcon/Kconfig25
-rw-r--r--drivers/extcon/Makefile1
-rw-r--r--drivers/extcon/extcon-adc-jack.c15
-rw-r--r--drivers/extcon/extcon-arizona.c88
-rw-r--r--drivers/extcon/extcon-axp288.c381
-rw-r--r--drivers/extcon/extcon-gpio.c1
-rw-r--r--drivers/extcon/extcon-max14577.c60
-rw-r--r--drivers/extcon/extcon-max77693.c140
-rw-r--r--drivers/extcon/extcon-max77843.c89
-rw-r--r--drivers/extcon/extcon-max8997.c64
-rw-r--r--drivers/extcon/extcon-palmas.c36
-rw-r--r--drivers/extcon/extcon-rt8973a.c55
-rw-r--r--drivers/extcon/extcon-sm5502.c33
-rw-r--r--drivers/extcon/extcon-usb-gpio.c35
-rw-r--r--drivers/extcon/extcon.c347
15 files changed, 826 insertions, 544 deletions
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index fdc0bf054..0cebbf668 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -28,15 +28,22 @@ config EXTCON_ARIZONA
with Wolfson Arizona devices. These are audio CODECs with
advanced audio accessory detection support.
+config EXTCON_AXP288
+ tristate "X-Power AXP288 EXTCON support"
+ depends on MFD_AXP20X && USB_PHY
+ help
+ Say Y here to enable support for USB peripheral detection
+ and USB MUX switching by X-Power AXP288 PMIC.
+
config EXTCON_GPIO
tristate "GPIO extcon support"
- depends on GPIOLIB
+ depends on GPIOLIB || COMPILE_TEST
help
Say Y here to enable GPIO based extcon support. Note that GPIO
extcon supports single state per extcon instance.
config EXTCON_MAX14577
- tristate "MAX14577/77836 EXTCON Support"
+ tristate "Maxim MAX14577/77836 EXTCON Support"
depends on MFD_MAX14577
select IRQ_DOMAIN
select REGMAP_I2C
@@ -46,7 +53,7 @@ config EXTCON_MAX14577
detector and switch.
config EXTCON_MAX77693
- tristate "MAX77693 EXTCON Support"
+ tristate "Maxim MAX77693 EXTCON Support"
depends on MFD_MAX77693 && INPUT
select IRQ_DOMAIN
select REGMAP_I2C
@@ -56,7 +63,7 @@ config EXTCON_MAX77693
detector and switch.
config EXTCON_MAX77843
- tristate "MAX77843 EXTCON Support"
+ tristate "Maxim MAX77843 EXTCON Support"
depends on MFD_MAX77843
select IRQ_DOMAIN
select REGMAP_I2C
@@ -66,7 +73,7 @@ config EXTCON_MAX77843
detector add switch.
config EXTCON_MAX8997
- tristate "MAX8997 EXTCON Support"
+ tristate "Maxim MAX8997 EXTCON Support"
depends on MFD_MAX8997 && IRQ_DOMAIN
help
If you say yes here you get support for the MUIC device of
@@ -81,7 +88,7 @@ config EXTCON_PALMAS
detection by palmas usb.
config EXTCON_RT8973A
- tristate "RT8973A EXTCON support"
+ tristate "Richtek RT8973A EXTCON support"
depends on I2C
select IRQ_DOMAIN
select REGMAP_I2C
@@ -93,7 +100,7 @@ config EXTCON_RT8973A
from abnormal high input voltage (up to 28V).
config EXTCON_SM5502
- tristate "SM5502 EXTCON support"
+ tristate "Silicon Mitus SM5502 EXTCON support"
depends on I2C
select IRQ_DOMAIN
select REGMAP_I2C
@@ -105,9 +112,9 @@ config EXTCON_SM5502
config EXTCON_USB_GPIO
tristate "USB GPIO extcon support"
- depends on GPIOLIB
+ depends on GPIOLIB || COMPILE_TEST
help
Say Y here to enable GPIO based USB cable detection extcon support.
Used typically if GPIO is used for USB ID pin detection.
-endif # MULTISTATE_SWITCH
+endif
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 920411479..ba787d042 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_EXTCON) += extcon.o
obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
+obj-$(CONFIG_EXTCON_AXP288) += extcon-axp288.o
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index 2bb82e550..7fc0ae191 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -29,7 +29,6 @@
* struct adc_jack_data - internal data for adc_jack device driver
* @edev: extcon device.
* @cable_names: list of supported cables.
- * @num_cables: size of cable_names.
* @adc_conditions: list of adc value conditions.
* @num_conditions: size of adc_conditions.
* @irq: irq number of attach/detach event (0 if not exist).
@@ -41,8 +40,7 @@
struct adc_jack_data {
struct extcon_dev *edev;
- const char **cable_names;
- int num_cables;
+ const unsigned int **cable_names;
struct adc_jack_cond *adc_conditions;
int num_conditions;
@@ -112,17 +110,6 @@ static int adc_jack_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
- data->edev->name = pdata->name;
-
- /* Check the length of array and set num_cables */
- for (i = 0; data->edev->supported_cable[i]; i++)
- ;
- if (i == 0 || i > SUPPORTED_CABLE_MAX) {
- dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n",
- i - 1);
- return -EINVAL;
- }
- data->num_cables = i;
if (!pdata->adc_conditions ||
!pdata->adc_conditions[0].state) {
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index a0ed35b33..ad87f2630 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -32,13 +32,10 @@
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>
+#include <dt-bindings/mfd/arizona.h>
#define ARIZONA_MAX_MICD_RANGE 8
-#define ARIZONA_ACCDET_MODE_MIC 0
-#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
@@ -94,7 +91,7 @@ struct arizona_extcon_info {
bool detecting;
int jack_flips;
- int hpdet_ip;
+ int hpdet_ip_version;
struct extcon_dev *edev;
};
@@ -121,17 +118,12 @@ static const int arizona_micd_levels[] = {
1257,
};
-#define ARIZONA_CABLE_MECHANICAL 0
-#define ARIZONA_CABLE_MICROPHONE 1
-#define ARIZONA_CABLE_HEADPHONE 2
-#define ARIZONA_CABLE_LINEOUT 3
-
-static const char *arizona_cable[] = {
- "Mechanical",
- "Microphone",
- "Headphone",
- "Line-out",
- NULL,
+static const unsigned int arizona_cable[] = {
+ EXTCON_MECHANICAL,
+ EXTCON_MICROPHONE,
+ EXTCON_HEADPHONE,
+ EXTCON_LINE_OUT,
+ EXTCON_NONE,
};
static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
@@ -145,6 +137,7 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
switch (arizona->type) {
case WM5110:
+ case WM8280:
mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
ARIZONA_HP1L_SHRTI;
if (clamp)
@@ -380,7 +373,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
return ret;
}
- switch (info->hpdet_ip) {
+ switch (info->hpdet_ip_version) {
case 0:
if (!(val & ARIZONA_HP_DONE)) {
dev_err(arizona->dev, "HPDET did not complete: %x\n",
@@ -441,7 +434,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
default:
dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
- info->hpdet_ip);
+ info->hpdet_ip_version);
case 2:
if (!(val & ARIZONA_HP_DONE_B)) {
dev_err(arizona->dev, "HPDET did not complete: %x\n",
@@ -559,7 +552,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
struct arizona_extcon_info *info = data;
struct arizona *arizona = info->arizona;
int id_gpio = arizona->pdata.hpdet_id_gpio;
- int report = ARIZONA_CABLE_HEADPHONE;
+ unsigned int report = EXTCON_HEADPHONE;
int ret, reading;
bool mic = false;
@@ -573,7 +566,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
}
/* If the cable was removed while measuring ignore the result */
- ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
+ ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL);
if (ret < 0) {
dev_err(arizona->dev, "Failed to check cable state: %d\n",
ret);
@@ -604,9 +597,9 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
/* Report high impedence cables as line outputs */
if (reading >= 5000)
- report = ARIZONA_CABLE_LINEOUT;
+ report = EXTCON_LINE_OUT;
else
- report = ARIZONA_CABLE_HEADPHONE;
+ report = EXTCON_HEADPHONE;
ret = extcon_set_cable_state_(info->edev, report, true);
if (ret != 0)
@@ -670,9 +663,9 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
ret = regmap_update_bits(arizona->regmap,
ARIZONA_ACCESSORY_DETECT_MODE_1,
ARIZONA_ACCDET_MODE_MASK,
- ARIZONA_ACCDET_MODE_HPL);
+ arizona->pdata.hpdet_channel);
if (ret != 0) {
- dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
+ dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
goto err;
}
@@ -691,8 +684,7 @@ err:
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_set_cable_state_(info->edev,
- ARIZONA_CABLE_HEADPHONE, true);
+ ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
@@ -722,9 +714,9 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
ARIZONA_ACCESSORY_DETECT_MODE_1,
ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
info->micd_modes[0].src |
- ARIZONA_ACCDET_MODE_HPL);
+ arizona->pdata.hpdet_channel);
if (ret != 0) {
- dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
+ dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
goto err;
}
@@ -749,8 +741,7 @@ err:
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_set_cable_state_(info->edev,
- ARIZONA_CABLE_HEADPHONE, true);
+ ret = extcon_set_cable_state_(info->edev, EXTCON_HEADPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
@@ -789,7 +780,7 @@ static void arizona_micd_detect(struct work_struct *work)
mutex_lock(&info->lock);
/* If the cable was removed while measuring ignore the result */
- ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
+ ret = extcon_get_cable_state_(info->edev, EXTCON_MECHANICAL);
if (ret < 0) {
dev_err(arizona->dev, "Failed to check cable state: %d\n",
ret);
@@ -838,8 +829,7 @@ static void arizona_micd_detect(struct work_struct *work)
arizona_identify_headphone(info);
ret = extcon_set_cable_state_(info->edev,
- ARIZONA_CABLE_MICROPHONE, true);
-
+ EXTCON_MICROPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Headset report failed: %d\n",
ret);
@@ -1030,7 +1020,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
if (info->last_jackdet == present) {
dev_dbg(arizona->dev, "Detected jack\n");
ret = extcon_set_cable_state_(info->edev,
- ARIZONA_CABLE_MECHANICAL, true);
+ EXTCON_MECHANICAL, true);
if (ret != 0)
dev_err(arizona->dev, "Mechanical report failed: %d\n",
@@ -1120,6 +1110,26 @@ static void arizona_micd_set_level(struct arizona *arizona, int index,
regmap_update_bits(arizona->regmap, reg, mask, level);
}
+static int arizona_extcon_of_get_pdata(struct arizona *arizona)
+{
+ struct arizona_pdata *pdata = &arizona->pdata;
+ unsigned int val = ARIZONA_ACCDET_MODE_HPL;
+
+ of_property_read_u32(arizona->dev->of_node, "wlf,hpdet-channel", &val);
+ switch (val) {
+ case ARIZONA_ACCDET_MODE_HPL:
+ case ARIZONA_ACCDET_MODE_HPR:
+ pdata->hpdet_channel = val;
+ break;
+ default:
+ dev_err(arizona->dev,
+ "Wrong wlf,hpdet-channel DT value %d\n", val);
+ pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
+ }
+
+ return 0;
+}
+
static int arizona_extcon_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
@@ -1137,6 +1147,11 @@ static int arizona_extcon_probe(struct platform_device *pdev)
if (!info)
return -ENOMEM;
+ if (IS_ENABLED(CONFIG_OF)) {
+ if (!dev_get_platdata(arizona->dev))
+ arizona_extcon_of_get_pdata(arizona);
+ }
+
info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
if (IS_ERR(info->micvdd)) {
ret = PTR_ERR(info->micvdd);
@@ -1161,7 +1176,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
break;
default:
info->micd_clamp = true;
- info->hpdet_ip = 1;
+ info->hpdet_ip_version = 1;
break;
}
break;
@@ -1172,7 +1187,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
break;
default:
info->micd_clamp = true;
- info->hpdet_ip = 2;
+ info->hpdet_ip_version = 2;
break;
}
break;
@@ -1185,7 +1200,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
- info->edev->name = "Headset Jack";
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret < 0) {
diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c
new file mode 100644
index 000000000..ea962bc54
--- /dev/null
+++ b/drivers/extcon/extcon-axp288.c
@@ -0,0 +1,381 @@
+/*
+ * extcon-axp288.c - X-Power AXP288 PMIC extcon cable detection driver
+ *
+ * Copyright (C) 2015 Intel Corporation
+ * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/usb/phy.h>
+#include <linux/notifier.h>
+#include <linux/extcon.h>
+#include <linux/regmap.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/axp20x.h>
+
+/* Power source status register */
+#define PS_STAT_VBUS_TRIGGER BIT(0)
+#define PS_STAT_BAT_CHRG_DIR BIT(2)
+#define PS_STAT_VBUS_ABOVE_VHOLD BIT(3)
+#define PS_STAT_VBUS_VALID BIT(4)
+#define PS_STAT_VBUS_PRESENT BIT(5)
+
+/* BC module global register */
+#define BC_GLOBAL_RUN BIT(0)
+#define BC_GLOBAL_DET_STAT BIT(2)
+#define BC_GLOBAL_DBP_TOUT BIT(3)
+#define BC_GLOBAL_VLGC_COM_SEL BIT(4)
+#define BC_GLOBAL_DCD_TOUT_MASK (BIT(6)|BIT(5))
+#define BC_GLOBAL_DCD_TOUT_300MS 0
+#define BC_GLOBAL_DCD_TOUT_100MS 1
+#define BC_GLOBAL_DCD_TOUT_500MS 2
+#define BC_GLOBAL_DCD_TOUT_900MS 3
+#define BC_GLOBAL_DCD_DET_SEL BIT(7)
+
+/* BC module vbus control and status register */
+#define VBUS_CNTL_DPDM_PD_EN BIT(4)
+#define VBUS_CNTL_DPDM_FD_EN BIT(5)
+#define VBUS_CNTL_FIRST_PO_STAT BIT(6)
+
+/* BC USB status register */
+#define USB_STAT_BUS_STAT_MASK (BIT(3)|BIT(2)|BIT(1)|BIT(0))
+#define USB_STAT_BUS_STAT_SHIFT 0
+#define USB_STAT_BUS_STAT_ATHD 0
+#define USB_STAT_BUS_STAT_CONN 1
+#define USB_STAT_BUS_STAT_SUSP 2
+#define USB_STAT_BUS_STAT_CONF 3
+#define USB_STAT_USB_SS_MODE BIT(4)
+#define USB_STAT_DEAD_BAT_DET BIT(6)
+#define USB_STAT_DBP_UNCFG BIT(7)
+
+/* BC detect status register */
+#define DET_STAT_MASK (BIT(7)|BIT(6)|BIT(5))
+#define DET_STAT_SHIFT 5
+#define DET_STAT_SDP 1
+#define DET_STAT_CDP 2
+#define DET_STAT_DCP 3
+
+/* IRQ enable-1 register */
+#define PWRSRC_IRQ_CFG_MASK (BIT(4)|BIT(3)|BIT(2))
+
+/* IRQ enable-6 register */
+#define BC12_IRQ_CFG_MASK BIT(1)
+
+enum axp288_extcon_reg {
+ AXP288_PS_STAT_REG = 0x00,
+ AXP288_PS_BOOT_REASON_REG = 0x02,
+ AXP288_BC_GLOBAL_REG = 0x2c,
+ AXP288_BC_VBUS_CNTL_REG = 0x2d,
+ AXP288_BC_USB_STAT_REG = 0x2e,
+ AXP288_BC_DET_STAT_REG = 0x2f,
+ AXP288_PWRSRC_IRQ_CFG_REG = 0x40,
+ AXP288_BC12_IRQ_CFG_REG = 0x45,
+};
+
+enum axp288_mux_select {
+ EXTCON_GPIO_MUX_SEL_PMIC = 0,
+ EXTCON_GPIO_MUX_SEL_SOC,
+};
+
+enum axp288_extcon_irq {
+ VBUS_FALLING_IRQ = 0,
+ VBUS_RISING_IRQ,
+ MV_CHNG_IRQ,
+ BC_USB_CHNG_IRQ,
+ EXTCON_IRQ_END,
+};
+
+static const unsigned int axp288_extcon_cables[] = {
+ EXTCON_SLOW_CHARGER,
+ EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_FAST_CHARGER,
+ EXTCON_NONE,
+};
+
+struct axp288_extcon_info {
+ struct device *dev;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *regmap_irqc;
+ struct axp288_extcon_pdata *pdata;
+ int irq[EXTCON_IRQ_END];
+ struct extcon_dev *edev;
+ struct notifier_block extcon_nb;
+ struct usb_phy *otg;
+};
+
+/* Power up/down reason string array */
+static char *axp288_pwr_up_down_info[] = {
+ "Last wake caused by user pressing the power button",
+ "Last wake caused by a charger insertion",
+ "Last wake caused by a battery insertion",
+ "Last wake caused by SOC initiated global reset",
+ "Last wake caused by cold reset",
+ "Last shutdown caused by PMIC UVLO threshold",
+ "Last shutdown caused by SOC initiated cold off",
+ "Last shutdown caused by user pressing the power button",
+ NULL,
+};
+
+/*
+ * Decode and log the given "reset source indicator" (rsi)
+ * register and then clear it.
+ */
+static void axp288_extcon_log_rsi(struct axp288_extcon_info *info)
+{
+ char **rsi;
+ unsigned int val, i, clear_mask = 0;
+ int ret;
+
+ ret = regmap_read(info->regmap, AXP288_PS_BOOT_REASON_REG, &val);
+ for (i = 0, rsi = axp288_pwr_up_down_info; *rsi; rsi++, i++) {
+ if (val & BIT(i)) {
+ dev_dbg(info->dev, "%s\n", *rsi);
+ clear_mask |= BIT(i);
+ }
+ }
+
+ /* Clear the register value for next reboot (write 1 to clear bit) */
+ regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask);
+}
+
+static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
+{
+ static bool notify_otg, notify_charger;
+ static unsigned int cable;
+ int ret, stat, cfg, pwr_stat;
+ u8 chrg_type;
+ bool vbus_attach = false;
+
+ ret = regmap_read(info->regmap, AXP288_PS_STAT_REG, &pwr_stat);
+ if (ret < 0) {
+ dev_err(info->dev, "failed to read vbus status\n");
+ return ret;
+ }
+
+ vbus_attach = (pwr_stat & PS_STAT_VBUS_PRESENT);
+ if (!vbus_attach)
+ goto notify_otg;
+
+ /* Check charger detection completion status */
+ ret = regmap_read(info->regmap, AXP288_BC_GLOBAL_REG, &cfg);
+ if (ret < 0)
+ goto dev_det_ret;
+ if (cfg & BC_GLOBAL_DET_STAT) {
+ dev_dbg(info->dev, "can't complete the charger detection\n");
+ goto dev_det_ret;
+ }
+
+ ret = regmap_read(info->regmap, AXP288_BC_DET_STAT_REG, &stat);
+ if (ret < 0)
+ goto dev_det_ret;
+
+ chrg_type = (stat & DET_STAT_MASK) >> DET_STAT_SHIFT;
+
+ switch (chrg_type) {
+ case DET_STAT_SDP:
+ dev_dbg(info->dev, "sdp cable is connecetd\n");
+ notify_otg = true;
+ notify_charger = true;
+ cable = EXTCON_SLOW_CHARGER;
+ break;
+ case DET_STAT_CDP:
+ dev_dbg(info->dev, "cdp cable is connecetd\n");
+ notify_otg = true;
+ notify_charger = true;
+ cable = EXTCON_CHARGE_DOWNSTREAM;
+ break;
+ case DET_STAT_DCP:
+ dev_dbg(info->dev, "dcp cable is connecetd\n");
+ notify_charger = true;
+ cable = EXTCON_FAST_CHARGER;
+ break;
+ default:
+ dev_warn(info->dev,
+ "disconnect or unknown or ID event\n");
+ }
+
+notify_otg:
+ if (notify_otg) {
+ /*
+ * If VBUS is absent Connect D+/D- lines to PMIC for BC
+ * detection. Else connect them to SOC for USB communication.
+ */
+ if (info->pdata->gpio_mux_cntl)
+ gpiod_set_value(info->pdata->gpio_mux_cntl,
+ vbus_attach ? EXTCON_GPIO_MUX_SEL_SOC
+ : EXTCON_GPIO_MUX_SEL_PMIC);
+
+ atomic_notifier_call_chain(&info->otg->notifier,
+ vbus_attach ? USB_EVENT_VBUS : USB_EVENT_NONE, NULL);
+ }
+
+ if (notify_charger)
+ extcon_set_cable_state_(info->edev, cable, vbus_attach);
+
+ /* Clear the flags on disconnect event */
+ if (!vbus_attach)
+ notify_otg = notify_charger = false;
+
+ return 0;
+
+dev_det_ret:
+ if (ret < 0)
+ dev_err(info->dev, "failed to detect BC Mod\n");
+
+ return ret;
+}
+
+static irqreturn_t axp288_extcon_isr(int irq, void *data)
+{
+ struct axp288_extcon_info *info = data;
+ int ret;
+
+ ret = axp288_handle_chrg_det_event(info);
+ if (ret < 0)
+ dev_err(info->dev, "failed to handle the interrupt\n");
+
+ return IRQ_HANDLED;
+}
+
+static void axp288_extcon_enable_irq(struct axp288_extcon_info *info)
+{
+ /* Unmask VBUS interrupt */
+ regmap_write(info->regmap, AXP288_PWRSRC_IRQ_CFG_REG,
+ PWRSRC_IRQ_CFG_MASK);
+ regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
+ BC_GLOBAL_RUN, 0);
+ /* Unmask the BC1.2 complete interrupts */
+ regmap_write(info->regmap, AXP288_BC12_IRQ_CFG_REG, BC12_IRQ_CFG_MASK);
+ /* Enable the charger detection logic */
+ regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
+ BC_GLOBAL_RUN, BC_GLOBAL_RUN);
+}
+
+static int axp288_extcon_probe(struct platform_device *pdev)
+{
+ struct axp288_extcon_info *info;
+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+ int ret, i, pirq, gpio;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = &pdev->dev;
+ info->regmap = axp20x->regmap;
+ info->regmap_irqc = axp20x->regmap_irqc;
+ info->pdata = pdev->dev.platform_data;
+
+ if (!info->pdata) {
+ /* Try ACPI provided pdata via device properties */
+ if (!device_property_present(&pdev->dev,
+ "axp288_extcon_data\n"))
+ dev_err(&pdev->dev, "failed to get platform data\n");
+ return -ENODEV;
+ }
+ platform_set_drvdata(pdev, info);
+
+ axp288_extcon_log_rsi(info);
+
+ /* Initialize extcon device */
+ info->edev = devm_extcon_dev_allocate(&pdev->dev,
+ axp288_extcon_cables);
+ if (IS_ERR(info->edev)) {
+ dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
+ return PTR_ERR(info->edev);
+ }
+
+ /* Register extcon device */
+ ret = devm_extcon_dev_register(&pdev->dev, info->edev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register extcon device\n");
+ return ret;
+ }
+
+ /* Get otg transceiver phy */
+ info->otg = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR(info->otg)) {
+ dev_err(&pdev->dev, "failed to get otg transceiver\n");
+ return PTR_ERR(info->otg);
+ }
+
+ /* Set up gpio control for USB Mux */
+ if (info->pdata->gpio_mux_cntl) {
+ gpio = desc_to_gpio(info->pdata->gpio_mux_cntl);
+ ret = gpio_request(gpio, "USB_MUX");
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "failed to request the gpio=%d\n", gpio);
+ goto gpio_req_failed;
+ }
+ gpiod_direction_output(info->pdata->gpio_mux_cntl,
+ EXTCON_GPIO_MUX_SEL_PMIC);
+ }
+
+ for (i = 0; i < EXTCON_IRQ_END; i++) {
+ pirq = platform_get_irq(pdev, i);
+ info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
+ if (info->irq[i] < 0) {
+ dev_err(&pdev->dev,
+ "failed to get virtual interrupt=%d\n", pirq);
+ ret = info->irq[i];
+ goto gpio_req_failed;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, info->irq[i],
+ NULL, axp288_extcon_isr,
+ IRQF_ONESHOT | IRQF_NO_SUSPEND,
+ pdev->name, info);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request interrupt=%d\n",
+ info->irq[i]);
+ goto gpio_req_failed;
+ }
+ }
+
+ /* Enable interrupts */
+ axp288_extcon_enable_irq(info);
+
+ return 0;
+
+gpio_req_failed:
+ usb_put_phy(info->otg);
+ return ret;
+}
+
+static int axp288_extcon_remove(struct platform_device *pdev)
+{
+ struct axp288_extcon_info *info = platform_get_drvdata(pdev);
+
+ usb_put_phy(info->otg);
+ return 0;
+}
+
+static struct platform_driver axp288_extcon_driver = {
+ .probe = axp288_extcon_probe,
+ .remove = axp288_extcon_remove,
+ .driver = {
+ .name = "axp288_extcon",
+ },
+};
+module_platform_driver(axp288_extcon_driver);
+
+MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
+MODULE_DESCRIPTION("X-Powers AXP288 extcon driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 7af33fc43..355459a54 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -104,7 +104,6 @@ static int gpio_extcon_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
- extcon_data->edev->name = pdata->name;
extcon_data->gpio = pdata->gpio;
extcon_data->gpio_active_low = pdata->gpio_active_low;
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c
index 3823aa4a3..df0659d98 100644
--- a/drivers/extcon/extcon-max14577.c
+++ b/drivers/extcon/extcon-max14577.c
@@ -148,33 +148,14 @@ enum max14577_muic_acc_type {
MAX14577_MUIC_ADC_OPEN,
};
-/* max14577 MUIC device support below list of accessories(external connector) */
-enum {
- EXTCON_CABLE_USB = 0,
- EXTCON_CABLE_TA,
- EXTCON_CABLE_FAST_CHARGER,
- EXTCON_CABLE_SLOW_CHARGER,
- EXTCON_CABLE_CHARGE_DOWNSTREAM,
- EXTCON_CABLE_JIG_USB_ON,
- EXTCON_CABLE_JIG_USB_OFF,
- EXTCON_CABLE_JIG_UART_OFF,
- EXTCON_CABLE_JIG_UART_ON,
-
- _EXTCON_CABLE_NUM,
-};
-
-static const char *max14577_extcon_cable[] = {
- [EXTCON_CABLE_USB] = "USB",
- [EXTCON_CABLE_TA] = "TA",
- [EXTCON_CABLE_FAST_CHARGER] = "Fast-charger",
- [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger",
- [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream",
- [EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON",
- [EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF",
- [EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF",
- [EXTCON_CABLE_JIG_UART_ON] = "JIG-UART-ON",
-
- NULL,
+static const unsigned int max14577_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_TA,
+ EXTCON_FAST_CHARGER,
+ EXTCON_SLOW_CHARGER,
+ EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_JIG,
+ EXTCON_NONE,
};
/*
@@ -348,7 +329,6 @@ static int max14577_muic_get_cable_type(struct max14577_muic_info *info,
static int max14577_muic_jig_handler(struct max14577_muic_info *info,
int cable_type, bool attached)
{
- char cable_name[32];
int ret = 0;
u8 path = CTRL1_SW_OPEN;
@@ -358,18 +338,12 @@ static int max14577_muic_jig_handler(struct max14577_muic_info *info,
switch (cable_type) {
case MAX14577_MUIC_ADC_FACTORY_MODE_USB_OFF: /* ADC_JIG_USB_OFF */
- /* PATH:AP_USB */
- strcpy(cable_name, "JIG-USB-OFF");
- path = CTRL1_SW_USB;
- break;
case MAX14577_MUIC_ADC_FACTORY_MODE_USB_ON: /* ADC_JIG_USB_ON */
/* PATH:AP_USB */
- strcpy(cable_name, "JIG-USB-ON");
path = CTRL1_SW_USB;
break;
case MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF: /* ADC_JIG_UART_OFF */
/* PATH:AP_UART */
- strcpy(cable_name, "JIG-UART-OFF");
path = CTRL1_SW_UART;
break;
default:
@@ -382,7 +356,7 @@ static int max14577_muic_jig_handler(struct max14577_muic_info *info,
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, cable_name, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_JIG, attached);
return 0;
}
@@ -479,20 +453,22 @@ static int max14577_muic_chg_handler(struct max14577_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "USB", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB, attached);
break;
case MAX14577_CHARGER_TYPE_DEDICATED_CHG:
- extcon_set_cable_state(info->edev, "TA", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
break;
case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:
- extcon_set_cable_state(info->edev,
- "Charge-downstream", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ attached);
break;
case MAX14577_CHARGER_TYPE_SPECIAL_500MA:
- extcon_set_cable_state(info->edev, "Slow-charger", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ attached);
break;
case MAX14577_CHARGER_TYPE_SPECIAL_1A:
- extcon_set_cable_state(info->edev, "Fast-charger", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ attached);
break;
case MAX14577_CHARGER_TYPE_NONE:
case MAX14577_CHARGER_TYPE_DEAD_BATTERY:
@@ -742,8 +718,6 @@ static int max14577_muic_probe(struct platform_device *pdev)
return -ENOMEM;
}
- info->edev->name = dev_name(&pdev->dev);
-
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
dev_err(&pdev->dev, "failed to register extcon device\n");
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index a66bec8f6..f4f3b3d53 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -200,44 +200,17 @@ enum max77693_muic_acc_type {
/*
* MAX77693 MUIC device support below list of accessories(external connector)
*/
-enum {
- EXTCON_CABLE_USB = 0,
- EXTCON_CABLE_USB_HOST,
- EXTCON_CABLE_TA,
- EXTCON_CABLE_FAST_CHARGER,
- EXTCON_CABLE_SLOW_CHARGER,
- EXTCON_CABLE_CHARGE_DOWNSTREAM,
- EXTCON_CABLE_MHL,
- EXTCON_CABLE_MHL_TA,
- EXTCON_CABLE_JIG_USB_ON,
- EXTCON_CABLE_JIG_USB_OFF,
- EXTCON_CABLE_JIG_UART_OFF,
- EXTCON_CABLE_JIG_UART_ON,
- EXTCON_CABLE_DOCK_SMART,
- EXTCON_CABLE_DOCK_DESK,
- EXTCON_CABLE_DOCK_AUDIO,
-
- _EXTCON_CABLE_NUM,
-};
-
-static const char *max77693_extcon_cable[] = {
- [EXTCON_CABLE_USB] = "USB",
- [EXTCON_CABLE_USB_HOST] = "USB-Host",
- [EXTCON_CABLE_TA] = "TA",
- [EXTCON_CABLE_FAST_CHARGER] = "Fast-charger",
- [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger",
- [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream",
- [EXTCON_CABLE_MHL] = "MHL",
- [EXTCON_CABLE_MHL_TA] = "MHL-TA",
- [EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON",
- [EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF",
- [EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF",
- [EXTCON_CABLE_JIG_UART_ON] = "JIG-UART-ON",
- [EXTCON_CABLE_DOCK_SMART] = "Dock-Smart",
- [EXTCON_CABLE_DOCK_DESK] = "Dock-Desk",
- [EXTCON_CABLE_DOCK_AUDIO] = "Dock-Audio",
-
- NULL,
+static const unsigned int max77693_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_TA,
+ EXTCON_FAST_CHARGER,
+ EXTCON_SLOW_CHARGER,
+ EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_MHL,
+ EXTCON_JIG,
+ EXTCON_DOCK,
+ EXTCON_NONE,
};
/*
@@ -484,7 +457,7 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
int ret = 0;
int vbvolt;
bool cable_attached;
- char dock_name[CABLE_NAME_MAX];
+ unsigned int dock_id;
dev_info(info->dev,
"external connector is %s (adc:0x%02x)\n",
@@ -507,15 +480,15 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
}
/*
- * Notify Dock-Smart/MHL state.
- * - Dock-Smart device include three type of cable which
+ * Notify Dock/MHL state.
+ * - Dock device include three type of cable which
* are HDMI, USB for mouse/keyboard and micro-usb port
- * for USB/TA cable. Dock-Smart device need always exteranl
- * power supply(USB/TA cable through micro-usb cable). Dock-
- * Smart device support screen output of target to separate
+ * for USB/TA cable. Dock device need always exteranl
+ * power supply(USB/TA cable through micro-usb cable). Dock
+ * device support screen output of target to separate
* monitor and mouse/keyboard for desktop mode.
*
- * Features of 'USB/TA cable with Dock-Smart device'
+ * Features of 'USB/TA cable with Dock device'
* - Support MHL
* - Support external output feature of audio
* - Support charging through micro-usb port without data
@@ -529,16 +502,16 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "Dock-Smart", attached);
- extcon_set_cable_state(info->edev, "MHL", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_DOCK, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
goto out;
case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */
- strcpy(dock_name, "Dock-Desk");
+ dock_id = EXTCON_DOCK;
break;
case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */
- strcpy(dock_name, "Dock-Audio");
+ dock_id = EXTCON_DOCK;
if (!attached)
- extcon_set_cable_state(info->edev, "USB", false);
+ extcon_set_cable_state_(info->edev, EXTCON_USB, false);
break;
default:
dev_err(info->dev, "failed to detect %s dock device\n",
@@ -550,7 +523,7 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, dock_name, attached);
+ extcon_set_cable_state_(info->edev, dock_id, attached);
out:
return 0;
@@ -615,20 +588,19 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "USB-Host", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB_HOST, attached);
break;
case MAX77693_MUIC_GND_AV_CABLE_LOAD:
/* Audio Video Cable with load, PATH:AUDIO */
ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev,
- "Audio-video-load", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB, attached);
break;
case MAX77693_MUIC_GND_MHL:
case MAX77693_MUIC_GND_MHL_VB:
/* MHL or MHL with USB/TA cable */
- extcon_set_cable_state(info->edev, "MHL", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
break;
default:
dev_err(info->dev, "failed to detect %s cable of gnd type\n",
@@ -642,7 +614,6 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
static int max77693_muic_jig_handler(struct max77693_muic_info *info,
int cable_type, bool attached)
{
- char cable_name[32];
int ret = 0;
u8 path = CONTROL1_SW_OPEN;
@@ -652,23 +623,13 @@ static int max77693_muic_jig_handler(struct max77693_muic_info *info,
switch (cable_type) {
case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: /* ADC_JIG_USB_OFF */
- /* PATH:AP_USB */
- strcpy(cable_name, "JIG-USB-OFF");
- path = CONTROL1_SW_USB;
- break;
case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: /* ADC_JIG_USB_ON */
/* PATH:AP_USB */
- strcpy(cable_name, "JIG-USB-ON");
path = CONTROL1_SW_USB;
break;
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: /* ADC_JIG_UART_OFF */
- /* PATH:AP_UART */
- strcpy(cable_name, "JIG-UART-OFF");
- path = CONTROL1_SW_UART;
- break;
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* ADC_JIG_UART_ON */
/* PATH:AP_UART */
- strcpy(cable_name, "JIG-UART-ON");
path = CONTROL1_SW_UART;
break;
default:
@@ -681,7 +642,7 @@ static int max77693_muic_jig_handler(struct max77693_muic_info *info,
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, cable_name, attached);
+ extcon_set_cable_state_(info->edev, EXTCON_JIG, attached);
return 0;
}
@@ -823,22 +784,22 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_GND_MHL:
case MAX77693_MUIC_GND_MHL_VB:
/*
- * MHL cable with MHL-TA(USB/TA) cable
+ * MHL cable with USB/TA cable
* - MHL cable include two port(HDMI line and separate
* micro-usb port. When the target connect MHL cable,
- * extcon driver check whether MHL-TA(USB/TA) cable is
- * connected. If MHL-TA cable is connected, extcon
+ * extcon driver check whether USB/TA cable is
+ * connected. If USB/TA cable is connected, extcon
* driver notify state to notifiee for charging battery.
*
- * Features of 'MHL-TA(USB/TA) with MHL cable'
+ * Features of 'USB/TA with MHL cable'
* - Support MHL
* - Support charging through micro-usb port without
* data connection
*/
- extcon_set_cable_state(info->edev, "MHL-TA", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
if (!cable_attached)
- extcon_set_cable_state(info->edev,
- "MHL", cable_attached);
+ extcon_set_cable_state_(info->edev, EXTCON_MHL,
+ cable_attached);
break;
}
@@ -861,11 +822,12 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
* - Support charging through micro-usb port without
* data connection.
*/
- extcon_set_cable_state(info->edev, "USB", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB,
+ attached);
if (!cable_attached)
- extcon_set_cable_state(info->edev, "Dock-Audio",
- cable_attached);
+ extcon_set_cable_state_(info->edev, EXTCON_DOCK,
+ cable_attached);
break;
case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */
/*
@@ -893,10 +855,10 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "Dock-Smart",
- attached);
- extcon_set_cable_state(info->edev, "MHL", attached);
-
+ extcon_set_cable_state_(info->edev, EXTCON_DOCK,
+ attached);
+ extcon_set_cable_state_(info->edev, EXTCON_MHL,
+ attached);
break;
}
@@ -929,23 +891,26 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "USB", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB,
+ attached);
break;
case MAX77693_CHARGER_TYPE_DEDICATED_CHG:
/* Only TA cable */
- extcon_set_cable_state(info->edev, "TA", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
break;
}
break;
case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT:
- extcon_set_cable_state(info->edev,
- "Charge-downstream", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ attached);
break;
case MAX77693_CHARGER_TYPE_APPLE_500MA:
- extcon_set_cable_state(info->edev, "Slow-charger", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ attached);
break;
case MAX77693_CHARGER_TYPE_APPLE_1A_2A:
- extcon_set_cable_state(info->edev, "Fast-charger", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ attached);
break;
case MAX77693_CHARGER_TYPE_DEAD_BATTERY:
break;
@@ -1182,7 +1147,6 @@ static int max77693_muic_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
return -ENOMEM;
}
- info->edev->name = DEV_NAME;
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
index 8db6a926e..fac2f1417 100644
--- a/drivers/extcon/extcon-max77843.c
+++ b/drivers/extcon/extcon-max77843.c
@@ -118,36 +118,16 @@ enum max77843_muic_charger_type {
MAX77843_MUIC_CHG_GND,
};
-enum {
- MAX77843_CABLE_USB = 0,
- MAX77843_CABLE_USB_HOST,
- MAX77843_CABLE_TA,
- MAX77843_CABLE_CHARGE_DOWNSTREAM,
- MAX77843_CABLE_FAST_CHARGER,
- MAX77843_CABLE_SLOW_CHARGER,
- MAX77843_CABLE_MHL,
- MAX77843_CABLE_MHL_TA,
- MAX77843_CABLE_JIG_USB_ON,
- MAX77843_CABLE_JIG_USB_OFF,
- MAX77843_CABLE_JIG_UART_ON,
- MAX77843_CABLE_JIG_UART_OFF,
-
- MAX77843_CABLE_NUM,
-};
-
-static const char *max77843_extcon_cable[] = {
- [MAX77843_CABLE_USB] = "USB",
- [MAX77843_CABLE_USB_HOST] = "USB-HOST",
- [MAX77843_CABLE_TA] = "TA",
- [MAX77843_CABLE_CHARGE_DOWNSTREAM] = "CHARGER-DOWNSTREAM",
- [MAX77843_CABLE_FAST_CHARGER] = "FAST-CHARGER",
- [MAX77843_CABLE_SLOW_CHARGER] = "SLOW-CHARGER",
- [MAX77843_CABLE_MHL] = "MHL",
- [MAX77843_CABLE_MHL_TA] = "MHL-TA",
- [MAX77843_CABLE_JIG_USB_ON] = "JIG-USB-ON",
- [MAX77843_CABLE_JIG_USB_OFF] = "JIG-USB-OFF",
- [MAX77843_CABLE_JIG_UART_ON] = "JIG-UART-ON",
- [MAX77843_CABLE_JIG_UART_OFF] = "JIG-UART-OFF",
+static const unsigned int max77843_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_TA,
+ EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_FAST_CHARGER,
+ EXTCON_SLOW_CHARGER,
+ EXTCON_MHL,
+ EXTCON_JIG,
+ EXTCON_NONE,
};
struct max77843_muic_irq {
@@ -362,7 +342,7 @@ static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "USB-HOST", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB_HOST, attached);
break;
case MAX77843_MUIC_GND_MHL_VB:
case MAX77843_MUIC_GND_MHL:
@@ -370,7 +350,7 @@ static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "MHL", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
break;
default:
dev_err(info->dev, "failed to detect %s accessory(gnd:0x%x)\n",
@@ -385,36 +365,29 @@ static int max77843_muic_jig_handler(struct max77843_muic_info *info,
int cable_type, bool attached)
{
int ret;
+ u8 path = CONTROL1_SW_OPEN;
dev_dbg(info->dev, "external connector is %s (adc:0x%02x)\n",
attached ? "attached" : "detached", cable_type);
switch (cable_type) {
case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
- ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
- if (ret < 0)
- return ret;
- extcon_set_cable_state(info->edev, "JIG-USB-OFF", attached);
- break;
case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
- ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
- if (ret < 0)
- return ret;
- extcon_set_cable_state(info->edev, "JIG-USB-ON", attached);
+ path = CONTROL1_SW_USB;
break;
case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
- ret = max77843_muic_set_path(info, CONTROL1_SW_UART, attached);
- if (ret < 0)
- return ret;
- extcon_set_cable_state(info->edev, "JIG-UART-OFF", attached);
+ path = CONTROL1_SW_UART;
break;
default:
- ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
- if (ret < 0)
- return ret;
- break;
+ return -EINVAL;
}
+ ret = max77843_muic_set_path(info, path, attached);
+ if (ret < 0)
+ return ret;
+
+ extcon_set_cable_state_(info->edev, EXTCON_JIG, attached);
+
return 0;
}
@@ -505,36 +478,38 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "USB", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB, attached);
break;
case MAX77843_MUIC_CHG_DOWNSTREAM:
ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev,
- "CHARGER-DOWNSTREAM", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ attached);
break;
case MAX77843_MUIC_CHG_DEDICATED:
ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "TA", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
break;
case MAX77843_MUIC_CHG_SPECIAL_500MA:
ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "SLOW-CHAREGER", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ attached);
break;
case MAX77843_MUIC_CHG_SPECIAL_1A:
ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "FAST-CHARGER", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ attached);
break;
case MAX77843_MUIC_CHG_GND:
gnd_type = max77843_muic_get_cable_type(info,
@@ -542,9 +517,9 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
/* Charger cable on MHL accessory is attach or detach */
if (gnd_type == MAX77843_MUIC_GND_MHL_VB)
- extcon_set_cable_state(info->edev, "MHL-TA", true);
+ extcon_set_cable_state_(info->edev, EXTCON_TA, true);
else if (gnd_type == MAX77843_MUIC_GND_MHL)
- extcon_set_cable_state(info->edev, "MHL-TA", false);
+ extcon_set_cable_state_(info->edev, EXTCON_TA, false);
break;
case MAX77843_MUIC_CHG_NONE:
break;
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 5774e56c6..7b1ef200b 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -145,34 +145,17 @@ struct max8997_muic_info {
int path_uart;
};
-enum {
- EXTCON_CABLE_USB = 0,
- EXTCON_CABLE_USB_HOST,
- EXTCON_CABLE_TA,
- EXTCON_CABLE_FAST_CHARGER,
- EXTCON_CABLE_SLOW_CHARGER,
- EXTCON_CABLE_CHARGE_DOWNSTREAM,
- EXTCON_CABLE_MHL,
- EXTCON_CABLE_DOCK_DESK,
- EXTCON_CABLE_DOCK_CARD,
- EXTCON_CABLE_JIG,
-
- _EXTCON_CABLE_NUM,
-};
-
-static const char *max8997_extcon_cable[] = {
- [EXTCON_CABLE_USB] = "USB",
- [EXTCON_CABLE_USB_HOST] = "USB-Host",
- [EXTCON_CABLE_TA] = "TA",
- [EXTCON_CABLE_FAST_CHARGER] = "Fast-charger",
- [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger",
- [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream",
- [EXTCON_CABLE_MHL] = "MHL",
- [EXTCON_CABLE_DOCK_DESK] = "Dock-Desk",
- [EXTCON_CABLE_DOCK_CARD] = "Dock-Card",
- [EXTCON_CABLE_JIG] = "JIG",
-
- NULL,
+static const unsigned int max8997_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_TA,
+ EXTCON_FAST_CHARGER,
+ EXTCON_SLOW_CHARGER,
+ EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_MHL,
+ EXTCON_DOCK,
+ EXTCON_JIG,
+ EXTCON_NONE,
};
/*
@@ -347,10 +330,10 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info,
switch (usb_type) {
case MAX8997_USB_HOST:
- extcon_set_cable_state(info->edev, "USB-Host", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB_HOST, attached);
break;
case MAX8997_USB_DEVICE:
- extcon_set_cable_state(info->edev, "USB", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_USB, attached);
break;
default:
dev_err(info->dev, "failed to detect %s usb cable\n",
@@ -374,10 +357,8 @@ static int max8997_muic_handle_dock(struct max8997_muic_info *info,
switch (cable_type) {
case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
- extcon_set_cable_state(info->edev, "Dock-desk", attached);
- break;
case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
- extcon_set_cable_state(info->edev, "Dock-card", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_DOCK, attached);
break;
default:
dev_err(info->dev, "failed to detect %s dock device\n",
@@ -400,7 +381,7 @@ static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
return ret;
}
- extcon_set_cable_state(info->edev, "JIG", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_JIG, attached);
return 0;
}
@@ -422,7 +403,7 @@ static int max8997_muic_adc_handler(struct max8997_muic_info *info)
return ret;
break;
case MAX8997_MUIC_ADC_MHL:
- extcon_set_cable_state(info->edev, "MHL", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_MHL, attached);
break;
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
@@ -505,17 +486,19 @@ static int max8997_muic_chg_handler(struct max8997_muic_info *info)
}
break;
case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
- extcon_set_cable_state(info->edev,
- "Charge-downstream", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CHARGE_DOWNSTREAM,
+ attached);
break;
case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
- extcon_set_cable_state(info->edev, "TA", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
break;
case MAX8997_CHARGER_TYPE_500MA:
- extcon_set_cable_state(info->edev, "Slow-charger", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_SLOW_CHARGER,
+ attached);
break;
case MAX8997_CHARGER_TYPE_1A:
- extcon_set_cable_state(info->edev, "Fast-charger", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_FAST_CHARGER,
+ attached);
break;
default:
dev_err(info->dev,
@@ -700,7 +683,6 @@ static int max8997_muic_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err_irq;
}
- info->edev->name = DEV_NAME;
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 11c6757b6..eebdf2a33 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -29,10 +29,10 @@
#include <linux/of.h>
#include <linux/of_platform.h>
-static const char *palmas_extcon_cable[] = {
- [0] = "USB",
- [1] = "USB-HOST",
- NULL,
+static const unsigned int palmas_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
};
static const int mutually_exclusive[] = {0x3, 0x0};
@@ -49,6 +49,7 @@ static void palmas_usb_wakeup(struct palmas *palmas, int enable)
static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
{
struct palmas_usb *palmas_usb = _palmas_usb;
+ struct extcon_dev *edev = palmas_usb->edev;
unsigned int vbus_line_state;
palmas_read(palmas_usb->palmas, PALMAS_INTERRUPT_BASE,
@@ -57,7 +58,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
if (vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS) {
if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
- extcon_set_cable_state(palmas_usb->edev, "USB", true);
+ extcon_set_cable_state_(edev, EXTCON_USB, true);
dev_info(palmas_usb->dev, "USB cable is attached\n");
} else {
dev_dbg(palmas_usb->dev,
@@ -66,7 +67,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
} else if (!(vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS)) {
if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
- extcon_set_cable_state(palmas_usb->edev, "USB", false);
+ extcon_set_cable_state_(edev, EXTCON_USB, false);
dev_info(palmas_usb->dev, "USB cable is detached\n");
} else {
dev_dbg(palmas_usb->dev,
@@ -81,6 +82,7 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
{
unsigned int set, id_src;
struct palmas_usb *palmas_usb = _palmas_usb;
+ struct extcon_dev *edev = palmas_usb->edev;
palmas_read(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_LATCH_SET, &set);
@@ -93,7 +95,7 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
palmas_usb->linkstat = PALMAS_USB_STATE_ID;
- extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true);
+ extcon_set_cable_state_(edev, EXTCON_USB_HOST, true);
dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
} else if ((set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) &&
(id_src & PALMAS_USB_ID_INT_SRC_ID_FLOAT)) {
@@ -101,17 +103,17 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
- extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false);
+ extcon_set_cable_state_(edev, EXTCON_USB_HOST, false);
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) &&
(!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) {
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
- extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false);
+ extcon_set_cable_state_(edev, EXTCON_USB_HOST, false);
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_DISCONNECT) &&
(id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) {
palmas_usb->linkstat = PALMAS_USB_STATE_ID;
- extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true);
+ extcon_set_cable_state_(edev, EXTCON_USB_HOST, true);
dev_info(palmas_usb->dev, " USB-HOST cable is attached\n");
}
@@ -193,13 +195,11 @@ static int palmas_usb_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
- palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL);
palmas_usb->edev->mutually_exclusive = mutually_exclusive;
status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
if (status) {
dev_err(&pdev->dev, "failed to register extcon device\n");
- kfree(palmas_usb->edev->name);
return status;
}
@@ -213,7 +213,6 @@ static int palmas_usb_probe(struct platform_device *pdev)
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->id_irq, status);
- kfree(palmas_usb->edev->name);
return status;
}
}
@@ -228,7 +227,6 @@ static int palmas_usb_probe(struct platform_device *pdev)
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->vbus_irq, status);
- kfree(palmas_usb->edev->name);
return status;
}
}
@@ -238,15 +236,6 @@ static int palmas_usb_probe(struct platform_device *pdev)
return 0;
}
-static int palmas_usb_remove(struct platform_device *pdev)
-{
- struct palmas_usb *palmas_usb = platform_get_drvdata(pdev);
-
- kfree(palmas_usb->edev->name);
-
- return 0;
-}
-
#ifdef CONFIG_PM_SLEEP
static int palmas_usb_suspend(struct device *dev)
{
@@ -287,7 +276,6 @@ static const struct of_device_id of_palmas_match_tbl[] = {
static struct platform_driver palmas_usb_driver = {
.probe = palmas_usb_probe,
- .remove = palmas_usb_remove,
.driver = {
.name = "palmas-usb",
.of_match_table = of_palmas_match_tbl,
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c
index 9ccd5af89..92c939221 100644
--- a/drivers/extcon/extcon-rt8973a.c
+++ b/drivers/extcon/extcon-rt8973a.c
@@ -90,27 +90,12 @@ static struct reg_data rt8973a_reg_data[] = {
};
/* List of detectable cables */
-enum {
- EXTCON_CABLE_USB = 0,
- EXTCON_CABLE_USB_HOST,
- EXTCON_CABLE_TA,
- EXTCON_CABLE_JIG_OFF_USB,
- EXTCON_CABLE_JIG_ON_USB,
- EXTCON_CABLE_JIG_OFF_UART,
- EXTCON_CABLE_JIG_ON_UART,
-
- EXTCON_CABLE_END,
-};
-
-static const char *rt8973a_extcon_cable[] = {
- [EXTCON_CABLE_USB] = "USB",
- [EXTCON_CABLE_USB_HOST] = "USB-Host",
- [EXTCON_CABLE_TA] = "TA",
- [EXTCON_CABLE_JIG_OFF_USB] = "JIG-USB-OFF",
- [EXTCON_CABLE_JIG_ON_USB] = "JIG-USB-ON",
- [EXTCON_CABLE_JIG_OFF_UART] = "JIG-UART-OFF",
- [EXTCON_CABLE_JIG_ON_UART] = "JIG-UART-ON",
- NULL,
+static const unsigned int rt8973a_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_TA,
+ EXTCON_JIG,
+ EXTCON_NONE,
};
/* Define OVP (Over Voltage Protection), OTP (Over Temperature Protection) */
@@ -313,14 +298,11 @@ static int rt8973a_muic_cable_handler(struct rt8973a_muic_info *info,
enum rt8973a_event_type event)
{
static unsigned int prev_cable_type;
- const char **cable_names = info->edev->supported_cable;
unsigned int con_sw = DM_DP_SWITCH_UART;
- int ret, idx = 0, cable_type;
+ int ret, cable_type;
+ unsigned int id;
bool attached = false;
- if (!cable_names)
- return 0;
-
switch (event) {
case RT8973A_EVENT_ATTACH:
cable_type = rt8973a_muic_get_cable_type(info);
@@ -347,31 +329,25 @@ static int rt8973a_muic_cable_handler(struct rt8973a_muic_info *info,
switch (cable_type) {
case RT8973A_MUIC_ADC_OTG:
- idx = EXTCON_CABLE_USB_HOST;
+ id = EXTCON_USB_HOST;
con_sw = DM_DP_SWITCH_USB;
break;
case RT8973A_MUIC_ADC_TA:
- idx = EXTCON_CABLE_TA;
+ id = EXTCON_TA;
con_sw = DM_DP_SWITCH_OPEN;
break;
case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB:
- idx = EXTCON_CABLE_JIG_OFF_USB;
- con_sw = DM_DP_SWITCH_UART;
- break;
case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB:
- idx = EXTCON_CABLE_JIG_ON_USB;
- con_sw = DM_DP_SWITCH_UART;
+ id = EXTCON_JIG;
+ con_sw = DM_DP_SWITCH_USB;
break;
case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART:
- idx = EXTCON_CABLE_JIG_OFF_UART;
- con_sw = DM_DP_SWITCH_UART;
- break;
case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART:
- idx = EXTCON_CABLE_JIG_ON_UART;
+ id = EXTCON_JIG;
con_sw = DM_DP_SWITCH_UART;
break;
case RT8973A_MUIC_ADC_USB:
- idx = EXTCON_CABLE_USB;
+ id = EXTCON_USB;
con_sw = DM_DP_SWITCH_USB;
break;
case RT8973A_MUIC_ADC_OPEN:
@@ -421,7 +397,7 @@ static int rt8973a_muic_cable_handler(struct rt8973a_muic_info *info,
return ret;
/* Change the state of external accessory */
- extcon_set_cable_state(info->edev, cable_names[idx], attached);
+ extcon_set_cable_state_(info->edev, id, attached);
return 0;
}
@@ -643,7 +619,6 @@ static int rt8973a_muic_i2c_probe(struct i2c_client *i2c,
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);
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
index 2f93cf307..817dece23 100644
--- a/drivers/extcon/extcon-sm5502.c
+++ b/drivers/extcon/extcon-sm5502.c
@@ -92,19 +92,11 @@ static struct reg_data sm5502_reg_data[] = {
};
/* 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,
+static const unsigned int sm5502_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_TA,
+ EXTCON_NONE,
};
/* Define supported accessory type */
@@ -377,16 +369,12 @@ 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;
+ unsigned int id;
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);
@@ -396,17 +384,17 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
switch (cable_type) {
case SM5502_MUIC_ADC_OPEN_USB:
- idx = EXTCON_CABLE_USB;
+ id = EXTCON_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;
+ id = EXTCON_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;
+ id = EXTCON_USB_HOST;
con_sw = DM_DP_SWITCH_USB;
vbus_sw = VBUSIN_SWITCH_OPEN;
break;
@@ -422,7 +410,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
return ret;
/* Change the state of external accessory */
- extcon_set_cable_state(info->edev, cable_names[idx], attached);
+ extcon_set_cable_state_(info->edev, id, attached);
return 0;
}
@@ -623,7 +611,6 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
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);
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index e45d1f13f..a2a44536a 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -15,6 +15,7 @@
*/
#include <linux/extcon.h>
+#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -38,18 +39,10 @@ struct usb_extcon_info {
struct delayed_work wq_detcable;
};
-/* List of detectable cables */
-enum {
- EXTCON_CABLE_USB = 0,
- EXTCON_CABLE_USB_HOST,
-
- EXTCON_CABLE_END,
-};
-
-static const char *usb_extcon_cable[] = {
- [EXTCON_CABLE_USB] = "USB",
- [EXTCON_CABLE_USB_HOST] = "USB-HOST",
- NULL,
+static const unsigned int usb_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
};
static void usb_extcon_detect_cable(struct work_struct *work)
@@ -67,24 +60,16 @@ static void usb_extcon_detect_cable(struct work_struct *work)
* As we don't have event for USB peripheral cable attached,
* we simulate USB peripheral attach here.
*/
- extcon_set_cable_state(info->edev,
- usb_extcon_cable[EXTCON_CABLE_USB_HOST],
- false);
- extcon_set_cable_state(info->edev,
- usb_extcon_cable[EXTCON_CABLE_USB],
- true);
+ extcon_set_cable_state_(info->edev, EXTCON_USB_HOST, false);
+ extcon_set_cable_state_(info->edev, EXTCON_USB, true);
} else {
/*
* ID = 0 means USB HOST cable attached.
* As we don't have event for USB peripheral cable detached,
* we simulate USB peripheral detach here.
*/
- extcon_set_cable_state(info->edev,
- usb_extcon_cable[EXTCON_CABLE_USB],
- false);
- extcon_set_cable_state(info->edev,
- usb_extcon_cable[EXTCON_CABLE_USB_HOST],
- true);
+ extcon_set_cable_state_(info->edev, EXTCON_USB, false);
+ extcon_set_cable_state_(info->edev, EXTCON_USB_HOST, true);
}
}
@@ -113,7 +98,7 @@ static int usb_extcon_probe(struct platform_device *pdev)
return -ENOMEM;
info->dev = dev;
- info->id_gpiod = devm_gpiod_get(&pdev->dev, "id");
+ info->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
if (IS_ERR(info->id_gpiod)) {
dev_err(dev, "failed to get ID GPIO\n");
return PTR_ERR(info->id_gpiod);
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index 4c9f165e4..43b57b02d 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -1,8 +1,11 @@
/*
- * drivers/extcon/extcon_class.c
+ * drivers/extcon/extcon.c - External Connector (extcon) framework.
*
* External connector (extcon) class driver
*
+ * Copyright (C) 2015 Samsung Electronics
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ *
* Copyright (C) 2012 Samsung Electronics
* Author: Donggeun Kim <dg77.kim@samsung.com>
* Author: MyungJoo Ham <myungjoo.ham@samsung.com>
@@ -19,8 +22,7 @@
* 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/module.h>
#include <linux/types.h>
@@ -33,36 +35,43 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
-/*
- * extcon_cable_name suggests the standard cable names for commonly used
- * cable types.
- *
- * However, please do not use extcon_cable_name directly for extcon_dev
- * struct's supported_cable pointer unless your device really supports
- * every single port-type of the following cable names. Please choose cable
- * names that are actually used in your extcon device.
- */
-const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
+#define SUPPORTED_CABLE_MAX 32
+#define CABLE_NAME_MAX 30
+
+static const char *extcon_name[] = {
+ [EXTCON_NONE] = "NONE",
+
+ /* USB external connector */
[EXTCON_USB] = "USB",
- [EXTCON_USB_HOST] = "USB-Host",
+ [EXTCON_USB_HOST] = "USB-HOST",
+
+ /* Charger external connector */
[EXTCON_TA] = "TA",
- [EXTCON_FAST_CHARGER] = "Fast-charger",
- [EXTCON_SLOW_CHARGER] = "Slow-charger",
- [EXTCON_CHARGE_DOWNSTREAM] = "Charge-downstream",
+ [EXTCON_FAST_CHARGER] = "FAST-CHARGER",
+ [EXTCON_SLOW_CHARGER] = "SLOW-CHARGER",
+ [EXTCON_CHARGE_DOWNSTREAM] = "CHARGE-DOWNSTREAM",
+
+ /* Audio/Video external connector */
+ [EXTCON_LINE_IN] = "LINE-IN",
+ [EXTCON_LINE_OUT] = "LINE-OUT",
+ [EXTCON_MICROPHONE] = "MICROPHONE",
+ [EXTCON_HEADPHONE] = "HEADPHONE",
+
[EXTCON_HDMI] = "HDMI",
[EXTCON_MHL] = "MHL",
[EXTCON_DVI] = "DVI",
[EXTCON_VGA] = "VGA",
- [EXTCON_DOCK] = "Dock",
- [EXTCON_LINE_IN] = "Line-in",
- [EXTCON_LINE_OUT] = "Line-out",
- [EXTCON_MIC_IN] = "Microphone",
- [EXTCON_HEADPHONE_OUT] = "Headphone",
- [EXTCON_SPDIF_IN] = "SPDIF-in",
- [EXTCON_SPDIF_OUT] = "SPDIF-out",
- [EXTCON_VIDEO_IN] = "Video-in",
- [EXTCON_VIDEO_OUT] = "Video-out",
- [EXTCON_MECHANICAL] = "Mechanical",
+ [EXTCON_SPDIF_IN] = "SPDIF-IN",
+ [EXTCON_SPDIF_OUT] = "SPDIF-OUT",
+ [EXTCON_VIDEO_IN] = "VIDEO-IN",
+ [EXTCON_VIDEO_OUT] = "VIDEO-OUT",
+
+ /* Etc external connector */
+ [EXTCON_DOCK] = "DOCK",
+ [EXTCON_JIG] = "JIG",
+ [EXTCON_MECHANICAL] = "MECHANICAL",
+
+ NULL,
};
static struct class *extcon_class;
@@ -102,6 +111,61 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
return 0;
}
+static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id)
+{
+ int i;
+
+ /* Find the the index of extcon cable in edev->supported_cable */
+ for (i = 0; i < edev->max_supported; i++) {
+ if (edev->supported_cable[i] == id)
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static int find_cable_id_by_name(struct extcon_dev *edev, const char *name)
+{
+ unsigned int id = -EINVAL;
+ int i = 0;
+
+ /* Find the id of extcon cable */
+ while (extcon_name[i]) {
+ if (!strncmp(extcon_name[i], name, CABLE_NAME_MAX)) {
+ id = i;
+ break;
+ }
+ i++;
+ }
+
+ return id;
+}
+
+static int find_cable_index_by_name(struct extcon_dev *edev, const char *name)
+{
+ unsigned int id;
+
+ if (edev->max_supported == 0)
+ return -EINVAL;
+
+ /* Find the the number of extcon cable */
+ id = find_cable_id_by_name(edev, name);
+ if (id < 0)
+ return id;
+
+ return find_cable_index_by_id(edev, id);
+}
+
+static bool is_extcon_changed(u32 prev, u32 new, int idx, bool *attached)
+{
+ if (((prev >> idx) & 0x1) != ((new >> idx) & 0x1)) {
+ *attached = new ? true : false;
+ return true;
+ }
+
+ return false;
+}
+
static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -119,11 +183,9 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
if (edev->max_supported == 0)
return sprintf(buf, "%u\n", edev->state);
- for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
- if (!edev->supported_cable[i])
- break;
+ for (i = 0; i < edev->max_supported; i++) {
count += sprintf(buf + count, "%s=%d\n",
- edev->supported_cable[i],
+ extcon_name[edev->supported_cable[i]],
!!(edev->state & (1 << i)));
}
@@ -155,15 +217,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
{
struct extcon_dev *edev = dev_get_drvdata(dev);
- /* Optional callback given by the user */
- if (edev->print_name) {
- int ret = edev->print_name(edev, buf);
-
- if (ret >= 0)
- return ret;
- }
-
- return sprintf(buf, "%s\n", dev_name(&edev->dev));
+ return sprintf(buf, "%s\n", edev->name);
}
static DEVICE_ATTR_RO(name);
@@ -172,9 +226,10 @@ static ssize_t cable_name_show(struct device *dev,
{
struct extcon_cable *cable = container_of(attr, struct extcon_cable,
attr_name);
+ int i = cable->cable_index;
return sprintf(buf, "%s\n",
- cable->edev->supported_cable[cable->cable_index]);
+ extcon_name[cable->edev->supported_cable[i]]);
}
static ssize_t cable_state_show(struct device *dev,
@@ -183,9 +238,11 @@ static ssize_t cable_state_show(struct device *dev,
struct extcon_cable *cable = container_of(attr, struct extcon_cable,
attr_state);
+ int i = cable->cable_index;
+
return sprintf(buf, "%d\n",
extcon_get_cable_state_(cable->edev,
- cable->cable_index));
+ cable->edev->supported_cable[i]));
}
/**
@@ -211,12 +268,14 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
char *envp[3];
int env_offset = 0;
int length;
+ int index;
unsigned long flags;
+ bool attached;
spin_lock_irqsave(&edev->lock, flags);
if (edev->state != ((edev->state & ~mask) | (state & mask))) {
- u32 old_state = edev->state;
+ u32 old_state;
if (check_mutually_exclusive(edev, (edev->state & ~mask) |
(state & mask))) {
@@ -224,10 +283,17 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
return -EPERM;
}
+ old_state = edev->state;
edev->state &= ~mask;
edev->state |= state & mask;
- raw_notifier_call_chain(&edev->nh, old_state, edev);
+ for (index = 0; index < edev->max_supported; index++) {
+ if (is_extcon_changed(old_state, edev->state, index,
+ &attached))
+ raw_notifier_call_chain(&edev->nh[index],
+ attached, edev);
+ }
+
/* This could be in interrupt handler */
prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
if (prop_buf) {
@@ -284,39 +350,19 @@ int extcon_set_state(struct extcon_dev *edev, u32 state)
EXPORT_SYMBOL_GPL(extcon_set_state);
/**
- * extcon_find_cable_index() - Get the cable index based on the cable name.
+ * extcon_get_cable_state_() - Get the status of a specific cable.
* @edev: the extcon device that has the cable.
- * @cable_name: cable name to be searched.
- *
- * Note that accessing a cable state based on cable_index is faster than
- * cable_name because using cable_name induces a loop with strncmp().
- * Thus, when get/set_cable_state is repeatedly used, using cable_index
- * is recommended.
+ * @id: the unique id of each external connector in extcon enumeration.
*/
-int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
+int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id)
{
- int i;
-
- if (edev->supported_cable) {
- for (i = 0; edev->supported_cable[i]; i++) {
- if (!strncmp(edev->supported_cable[i],
- cable_name, CABLE_NAME_MAX))
- return i;
- }
- }
+ int index;
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(extcon_find_cable_index);
+ index = find_cable_index_by_id(edev, id);
+ if (index < 0)
+ return index;
-/**
- * extcon_get_cable_state_() - Get the status of a specific cable.
- * @edev: the extcon device that has the cable.
- * @index: cable index that can be retrieved by extcon_find_cable_index().
- */
-int extcon_get_cable_state_(struct extcon_dev *edev, int index)
-{
- if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+ if (edev->max_supported && edev->max_supported <= index)
return -EINVAL;
return !!(edev->state & (1 << index));
@@ -332,25 +378,35 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
*/
int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
{
- return extcon_get_cable_state_(edev, extcon_find_cable_index
- (edev, cable_name));
+ unsigned int id;
+
+ id = find_cable_id_by_name(edev, cable_name);
+ if (id < 0)
+ return id;
+
+ return extcon_get_cable_state_(edev, id);
}
EXPORT_SYMBOL_GPL(extcon_get_cable_state);
/**
* extcon_set_cable_state_() - Set the status of a specific cable.
* @edev: the extcon device that has the cable.
- * @index: cable index that can be retrieved by
- * extcon_find_cable_index().
- * @cable_state: the new cable status. The default semantics is
+ * @id: the unique id of each external connector
+ * in extcon enumeration.
+ * @state: the new cable status. The default semantics is
* true: attached / false: detached.
*/
-int extcon_set_cable_state_(struct extcon_dev *edev,
- int index, bool cable_state)
+int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
+ bool cable_state)
{
u32 state;
+ int index;
+
+ index = find_cable_index_by_id(edev, id);
+ if (index < 0)
+ return index;
- if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+ if (edev->max_supported && edev->max_supported <= index)
return -EINVAL;
state = cable_state ? (1 << index) : 0;
@@ -370,8 +426,13 @@ EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
int extcon_set_cable_state(struct extcon_dev *edev,
const char *cable_name, bool cable_state)
{
- return extcon_set_cable_state_(edev, extcon_find_cable_index
- (edev, cable_name), cable_state);
+ unsigned int id;
+
+ id = find_cable_id_by_name(edev, cable_name);
+ if (id < 0)
+ return id;
+
+ return extcon_set_cable_state_(edev, id, cable_state);
}
EXPORT_SYMBOL_GPL(extcon_set_cable_state);
@@ -395,29 +456,6 @@ out:
}
EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
-static int _call_per_cable(struct notifier_block *nb, unsigned long val,
- void *ptr)
-{
- struct extcon_specific_cable_nb *obj = container_of(nb,
- struct extcon_specific_cable_nb, internal_nb);
- struct extcon_dev *edev = ptr;
-
- if ((val & (1 << obj->cable_index)) !=
- (edev->state & (1 << obj->cable_index))) {
- bool cable_state = true;
-
- obj->previous_value = val;
-
- if (val & (1 << obj->cable_index))
- cable_state = false;
-
- return obj->user_nb->notifier_call(obj->user_nb,
- cable_state, ptr);
- }
-
- return NOTIFY_OK;
-}
-
/**
* extcon_register_interest() - Register a notifier for a state change of a
* specific cable, not an entier set of cables of a
@@ -456,20 +494,18 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
if (!obj->edev)
return -ENODEV;
- obj->cable_index = extcon_find_cable_index(obj->edev,
- cable_name);
+ obj->cable_index = find_cable_index_by_name(obj->edev,
+ cable_name);
if (obj->cable_index < 0)
return obj->cable_index;
obj->user_nb = nb;
- obj->internal_nb.notifier_call = _call_per_cable;
-
spin_lock_irqsave(&obj->edev->lock, flags);
- ret = raw_notifier_chain_register(&obj->edev->nh,
- &obj->internal_nb);
+ ret = raw_notifier_chain_register(
+ &obj->edev->nh[obj->cable_index],
+ obj->user_nb);
spin_unlock_irqrestore(&obj->edev->lock, flags);
- return ret;
} else {
struct class_dev_iter iter;
struct extcon_dev *extd;
@@ -481,7 +517,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
while ((dev = class_dev_iter_next(&iter))) {
extd = dev_get_drvdata(dev);
- if (extcon_find_cable_index(extd, cable_name) < 0)
+ if (find_cable_index_by_name(extd, cable_name) < 0)
continue;
class_dev_iter_exit(&iter);
@@ -489,8 +525,10 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
cable_name, nb);
}
- return -ENODEV;
+ ret = -ENODEV;
}
+
+ return ret;
}
EXPORT_SYMBOL_GPL(extcon_register_interest);
@@ -509,7 +547,8 @@ int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
return -EINVAL;
spin_lock_irqsave(&obj->edev->lock, flags);
- ret = raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
+ ret = raw_notifier_chain_unregister(
+ &obj->edev->nh[obj->cable_index], obj->user_nb);
spin_unlock_irqrestore(&obj->edev->lock, flags);
return ret;
@@ -519,21 +558,24 @@ EXPORT_SYMBOL_GPL(extcon_unregister_interest);
/**
* extcon_register_notifier() - Register a notifiee to get notified by
* any attach status changes from the extcon.
- * @edev: the extcon device.
+ * @edev: the extcon device that has the external connecotr.
+ * @id: the unique id of each external connector in extcon enumeration.
* @nb: a notifier block to be registered.
*
* Note that the second parameter given to the callback of nb (val) is
* "old_state", not the current state. The current state can be retrieved
* by looking at the third pameter (edev pointer)'s state value.
*/
-int extcon_register_notifier(struct extcon_dev *edev,
- struct notifier_block *nb)
+int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb)
{
unsigned long flags;
- int ret;
+ int ret, idx;
+
+ idx = find_cable_index_by_id(edev, id);
spin_lock_irqsave(&edev->lock, flags);
- ret = raw_notifier_chain_register(&edev->nh, nb);
+ ret = raw_notifier_chain_register(&edev->nh[idx], nb);
spin_unlock_irqrestore(&edev->lock, flags);
return ret;
@@ -542,17 +584,20 @@ EXPORT_SYMBOL_GPL(extcon_register_notifier);
/**
* extcon_unregister_notifier() - Unregister a notifiee from the extcon device.
- * @edev: the extcon device.
- * @nb: a registered notifier block to be unregistered.
+ * @edev: the extcon device that has the external connecotr.
+ * @id: the unique id of each external connector in extcon enumeration.
+ * @nb: a notifier block to be registered.
*/
-int extcon_unregister_notifier(struct extcon_dev *edev,
- struct notifier_block *nb)
+int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
+ struct notifier_block *nb)
{
unsigned long flags;
- int ret;
+ int ret, idx;
+
+ idx = find_cable_index_by_id(edev, id);
spin_lock_irqsave(&edev->lock, flags);
- ret = raw_notifier_chain_unregister(&edev->nh, nb);
+ ret = raw_notifier_chain_unregister(&edev->nh[idx], nb);
spin_unlock_irqrestore(&edev->lock, flags);
return ret;
@@ -595,7 +640,7 @@ static void dummy_sysfs_dev_release(struct device *dev)
/*
* extcon_dev_allocate() - Allocate the memory of extcon device.
- * @supported_cable: Array of supported cable names ending with NULL.
+ * @supported_cable: Array of supported extcon ending with EXTCON_NONE.
* If supported_cable is NULL, cable name related APIs
* are disabled.
*
@@ -605,7 +650,7 @@ static void dummy_sysfs_dev_release(struct device *dev)
*
* Return the pointer of extcon device if success or ERR_PTR(err) if fail
*/
-struct extcon_dev *extcon_dev_allocate(const char **supported_cable)
+struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable)
{
struct extcon_dev *edev;
@@ -647,7 +692,7 @@ static void devm_extcon_dev_release(struct device *dev, void *res)
/**
* devm_extcon_dev_allocate - Allocate managed extcon device
* @dev: device owning the extcon device being created
- * @supported_cable: Array of supported cable names ending with NULL.
+ * @supported_cable: Array of supported extcon ending with EXTCON_NONE.
* If supported_cable is NULL, cable name related APIs
* are disabled.
*
@@ -659,7 +704,7 @@ static void devm_extcon_dev_release(struct device *dev, void *res)
* or ERR_PTR(err) if fail
*/
struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
- const char **supported_cable)
+ const unsigned int *supported_cable)
{
struct extcon_dev **ptr, *edev;
@@ -701,6 +746,7 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
int extcon_dev_register(struct extcon_dev *edev)
{
int ret, index = 0;
+ static atomic_t edev_no = ATOMIC_INIT(-1);
if (!extcon_class) {
ret = create_extcon_class();
@@ -708,30 +754,29 @@ int extcon_dev_register(struct extcon_dev *edev)
return ret;
}
- if (edev->supported_cable) {
- /* Get size of array */
- for (index = 0; edev->supported_cable[index]; index++)
- ;
- edev->max_supported = index;
- } else {
- edev->max_supported = 0;
- }
+ if (!edev->supported_cable)
+ return -EINVAL;
+
+ for (; edev->supported_cable[index] != EXTCON_NONE; index++);
+ edev->max_supported = index;
if (index > SUPPORTED_CABLE_MAX) {
- dev_err(&edev->dev, "extcon: maximum number of supported cables exceeded.\n");
+ dev_err(&edev->dev,
+ "exceed the maximum number of supported cables\n");
return -EINVAL;
}
edev->dev.class = extcon_class;
edev->dev.release = extcon_dev_release;
- edev->name = edev->name ? edev->name : dev_name(edev->dev.parent);
+ edev->name = dev_name(edev->dev.parent);
if (IS_ERR_OR_NULL(edev->name)) {
dev_err(&edev->dev,
"extcon device name is null\n");
return -EINVAL;
}
- dev_set_name(&edev->dev, "%s", edev->name);
+ dev_set_name(&edev->dev, "extcon%lu",
+ (unsigned long)atomic_inc_return(&edev_no));
if (edev->max_supported) {
char buf[10];
@@ -864,7 +909,15 @@ int extcon_dev_register(struct extcon_dev *edev)
spin_lock_init(&edev->lock);
- RAW_INIT_NOTIFIER_HEAD(&edev->nh);
+ edev->nh = devm_kzalloc(&edev->dev,
+ sizeof(*edev->nh) * edev->max_supported, GFP_KERNEL);
+ if (!edev->nh) {
+ ret = -ENOMEM;
+ goto err_dev;
+ }
+
+ for (index = 0; index < edev->max_supported; index++)
+ RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]);
dev_set_drvdata(&edev->dev, edev);
edev->state = 0;
@@ -1044,6 +1097,15 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
#endif /* CONFIG_OF */
EXPORT_SYMBOL_GPL(extcon_get_edev_by_phandle);
+/**
+ * extcon_get_edev_name() - Get the name of the extcon device.
+ * @edev: the extcon device
+ */
+const char *extcon_get_edev_name(struct extcon_dev *edev)
+{
+ return !edev ? NULL : edev->name;
+}
+
static int __init extcon_class_init(void)
{
return create_extcon_class();
@@ -1059,6 +1121,7 @@ static void __exit extcon_class_exit(void)
}
module_exit(extcon_class_exit);
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");