2014-04-10 13:17:25

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 00/13] extcon: major rework

This patchset adds many improvements to extcon class driver and extcon
provider drivers. It changes extcon API to faster and safer by replaceing
function taking extcon and cable names with functions working with
structures representing this objects.

It adds more advanced devicetree support which allows to pass specified
cables to client drivers. It gives independency from cable naming
conventions in individual extcon provider drivers, and allows to simply
connect client drivers with providers in way that being transpatent for
both of them.

It adds also some minor fixes like additional checks for safety increase,
and another improvements.

Also added some improvements to extcon provider drivers, improved devicetree
support and updated them to use faster extcon API.

Patches contains also documentation for extcon, and devicetree bindings
for all provider drivers.

More details can be found in commit messages and Documentation.

Best regards
Robert Baldyga
Samsung R&D Institute Poland

Robert Baldyga (13):
Documentation: add extcon devicetree bindings
Documentation: update charger-manager devicetree bindings
extcon: extcon-class: remove extcon_set_cable_state() function
extcon: extcon-class: match extcon device by devicetree node
extcon: extcon-class: improve extcon client API
extcon: extcon-class: remove unused functions
extcon: extcon-class: improve get_cable_state_()/set_cable_state_()
functions
extcon: extcon-class: simplify extcon_updata_state() function
extcon: extcon-class: move example to Documentation
extcon: extcon-gpio: add devicetree support
extcon: extcon-adc-jack: add devicetree support
extcon: extcon-max8997: check if pdata exists
extcon: extcon-max77693: check if pdata exists

.../devicetree/bindings/extcon/extcon-adc-jack.txt | 60 +++
.../devicetree/bindings/extcon/extcon-arizona.txt | 47 +++
.../devicetree/bindings/extcon/extcon-bindings.txt | 36 ++
.../devicetree/bindings/extcon/extcon-gpio.txt | 63 +++
.../devicetree/bindings/extcon/extcon-max14577.txt | 49 +++
.../devicetree/bindings/extcon/extcon-max77693.txt | 56 +++
.../devicetree/bindings/extcon/extcon-max8997.txt | 49 +++
.../devicetree/bindings/extcon/extcon-palmas.txt | 37 +-
.../bindings/power_supply/charger-manager.txt | 11 +-
Documentation/extcon/extcon.txt | 108 +++++
drivers/extcon/extcon-adc-jack.c | 75 ++++
drivers/extcon/extcon-arizona.c | 1 +
drivers/extcon/extcon-class.c | 412 +++++++++-----------
drivers/extcon/extcon-gpio.c | 64 ++-
drivers/extcon/extcon-max14577.c | 26 +-
drivers/extcon/extcon-max77693.c | 82 ++--
drivers/extcon/extcon-max8997.c | 35 +-
drivers/extcon/extcon-palmas.c | 28 +-
drivers/power/charger-manager.c | 36 +-
drivers/usb/dwc3/dwc3-omap.c | 68 ++--
drivers/usb/phy/phy-omap-otg.c | 72 ++--
include/linux/extcon.h | 157 +++-----
include/linux/extcon/extcon-gpio.h | 2 +-
include/linux/platform_data/usb-omap1.h | 2 -
include/linux/power/charger-manager.h | 6 +-
25 files changed, 1067 insertions(+), 515 deletions(-)
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-adc-jack.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-arizona.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-bindings.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-gpio.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-max14577.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-max77693.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-max8997.txt
create mode 100644 Documentation/extcon/extcon.txt

--
1.7.9.5


2014-04-10 13:17:37

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 01/13] Documentation: add extcon devicetree bindings

This patch adds extcon devicetree bindings. Documentation describes in general
client and provider bindings, and contains detailed desctiprion of bindings
for each extcon provider.

Signed-off-by: Robert Baldyga <[email protected]>
---
.../devicetree/bindings/extcon/extcon-adc-jack.txt | 60 +++++++++++++++++++
.../devicetree/bindings/extcon/extcon-arizona.txt | 47 +++++++++++++++
.../devicetree/bindings/extcon/extcon-bindings.txt | 36 +++++++++++
.../devicetree/bindings/extcon/extcon-gpio.txt | 63 ++++++++++++++++++++
.../devicetree/bindings/extcon/extcon-max14577.txt | 49 +++++++++++++++
.../devicetree/bindings/extcon/extcon-max77693.txt | 56 +++++++++++++++++
.../devicetree/bindings/extcon/extcon-max8997.txt | 49 +++++++++++++++
.../devicetree/bindings/extcon/extcon-palmas.txt | 37 ++++++++++--
8 files changed, 393 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-adc-jack.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-arizona.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-bindings.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-gpio.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-max14577.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-max77693.txt
create mode 100644 Documentation/devicetree/bindings/extcon/extcon-max8997.txt

diff --git a/Documentation/devicetree/bindings/extcon/extcon-adc-jack.txt b/Documentation/devicetree/bindings/extcon/extcon-adc-jack.txt
new file mode 100644
index 0000000..6e43891
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-adc-jack.txt
@@ -0,0 +1,60 @@
+* ADC JACK Extcon Controller
+
+ADC JACK extcon controller is responsible for cable detection.
+
+Required Properties:
+
+- compatible: should be "extcon-adc-jack".
+
+- #extcon-cells: should be 1.
+
+- subnode <cables>: node describing list of cables.
+ - subnode <cable>:
+ - cable-name: name of specific cable
+ - adc-min: minimum specific cable ADC values range
+ - adc-max: maximum specific cable ADC values range
+
+Subnodes of node 'cables' describes specific cables with ADC value ranges
+associated with this cables. When measured ADC value will be between min and
+max value for specific cable, clients will be notified about connection of
+this cable. Value ranges for individual cables cannot be overlaping.
+
+Example 1: An example of a extcon controller node is listed below.
+
+ extcon: adc-jack {
+ compatible = "extcon-adc-jack";
+ #extcon-cells = <1>;
+
+ cables {
+ cable@0 {
+ cable-name = "CABLE-0";
+ adc-min = 120;
+ adc-max = 240;
+ }
+ cable@1 {
+ cable-name = "CABLE-1";
+ adc-min = 250;
+ adc-max = 400;
+ }
+ cable@2 {
+ cable-name = "CABLE-2";
+ adc-min = 500;
+ adc-max = 700;
+ };
+ };
+ };
+
+Example 2: USB controller node that uses cable from the extcon
+ controller. Refer to the standard extcon bindings for
+ information about 'extcon-cables' and 'extcon-names'
+ property.
+
+ usb@12480000 {
+ vusb_d-supply = <&vusb_reg>;
+ vusb_a-supply = <&vusbdac_reg>;
+
+ extcon-cables = <&extcon 0>;
+ extcon-names = "USB";
+
+ status = "okay";
+ };
diff --git a/Documentation/devicetree/bindings/extcon/extcon-arizona.txt b/Documentation/devicetree/bindings/extcon/extcon-arizona.txt
new file mode 100644
index 0000000..9af4422
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-arizona.txt
@@ -0,0 +1,47 @@
+* Wolfson Arizona Extcon Controller
+
+The Wolfson Arizona Extcon Controller is responsible for cable
+detection.
+
+Required Properties:
+
+- compatible: should be "wlf,arizona-extcon".
+
+- #extcon-cells: should be 1.
+
+The following is the list of cables detected by the controller. Each
+cable is assigned an identifier and client nodes use this identifies
+to specify the cable which they are interested in.
+
+ Cable ID
+ ----------------------------
+
+ Mechanical 0
+ Microphone 1
+ Headphone 2
+ Line-out 3
+
+Example 1: An example of a extcon controller node is listed below.
+
+ extcon: arizona-extcon {
+ compatible = "wlf,arizona-extcon";
+ #extcon-cells = <1>;
+ };
+
+Example 2: Audio controller node that uses cable from the extcon
+ controller. Refer to the standard extcon bindings for
+ information about 'extcon-cables' and 'extcon-names'
+ property.
+
+ audio-controller@b0000 {
+ reg = <0xb0000 0x2210>;
+ interrupts = <19>, <20>;
+
+ extcon-cables = <&extcon 1>, <&extcon 3>;
+ extcon-names = "Microphone", "Line-out";
+
+ clocks = <&gate_clk 12>;
+ clock-names = "internal";
+
+ status = "okay";
+ };
diff --git a/Documentation/devicetree/bindings/extcon/extcon-bindings.txt b/Documentation/devicetree/bindings/extcon/extcon-bindings.txt
new file mode 100644
index 0000000..5167f69
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-bindings.txt
@@ -0,0 +1,36 @@
+Extcon controllers can be represented by any node in the device
+tree. Those nodes are designated as extcon cable providers. Extcon
+cable consumer nodes use phandle and cable specifier pair to register
+interest in specific cables.
+
+==Extcon providers==
+
+Required properties:
+#extcon-cells: Number of cells in extcon specifier.
+ Always should be 1.
+
+For example:
+
+ extcon {
+ #extcon-cells = <1>;
+ };
+
+==Extcon consumers==
+
+Required properties:
+extcon-cables: List of phandle and cable specifier pairs, one pair
+ for each cable.
+
+Optional properties:
+extcon-names: List of extcon cable name strings sorted in the same
+ order as the extcon-cables property. Consumers drivers
+ will use extcon-names to match cable names with cable
+ specifiers.
+
+
+For example:
+
+ device {
+ extcon-cables = <&extcon 4>, <&extcon 7>;
+ extcon-names = "USB", "Charger";
+ };
diff --git a/Documentation/devicetree/bindings/extcon/extcon-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt
new file mode 100644
index 0000000..216cc30
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt
@@ -0,0 +1,63 @@
+* GPIO Extcon Controller
+
+The GPIO Extcon Controller is responsible for cable detection.
+
+Required Properties:
+
+- compatible: should be "extcon-gpio".
+
+- #extcon-cells: should be 1.
+
+- gpios: device-tree gpio specification.
+
+- gpio-controller-name: choosen controller name.
+
+- gpio-cable-name: choosen cable name.
+
+Optional Properties:
+
+- gpio-debounce: debounce time value in ms.
+
+- gpio-active-low: indicates that cable is active when gpio state is low.
+
+- gpio-check-on-resume: indicates that state should be checked on resume.
+
+The following is the list of cables detected by the controller. Each
+cable is assigned an identifier and client nodes use this identifies
+to specify the cable which they are interested in.
+
+ Cable ID
+ ----------------------------
+
+ GPIO 0
+
+Example 1: An example of a extcon controller node is listed below.
+
+ extcon: gpio {
+ compatible = "extcon-gpio";
+ #extcon-cells = <1>;
+
+ gpios = <&gpx1 0 1>;
+
+ gpio-controller-name = "gpio-controller";
+ gpio-cable-name = "gpio-cable";
+
+ gpio-debounce = 15;
+ gpio-active-low;
+ gpio-check-on-resume;
+ };
+
+Example 2: USB controller node that uses cable from the extcon
+ controller. Refer to the standard extcon bindings for
+ information about 'extcon-cables' and 'extcon-names'
+ property.
+
+ usb@12480000 {
+ vusb_d-supply = <&vusb_reg>;
+ vusb_a-supply = <&vusbdac_reg>;
+
+ extcon-cables = <&extcon 0>;
+ extcon-names = "USB-HOST";
+
+ status = "okay";
+ };
diff --git a/Documentation/devicetree/bindings/extcon/extcon-max14577.txt b/Documentation/devicetree/bindings/extcon/extcon-max14577.txt
new file mode 100644
index 0000000..a2b9e9e
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-max14577.txt
@@ -0,0 +1,49 @@
+* Maxim MAX14577 MUIC Extcon Controller
+
+The MUIC part of MAX14577 IC is responsible for cable detection.
+
+Required Properties:
+
+- compatible: should be "maxim,max14577-muic".
+
+- #extcon-cells: should be 1.
+
+The following is the list of cables detected by the controller. Each
+cable is assigned an identifier and client nodes use this identifies
+to specify the cable which they are interested in.
+
+ Cable ID
+ ----------------------------
+
+ USB 0
+ TA 1
+ Fast-charger 2
+ Slow-charger 3
+ Charge-downstream 4
+ JIG-USB-ON 5
+ JIG-USB-OFF 6
+ JIG-UART-OFF 7
+ JIG-UART-ON 8
+
+Example 1: An example of a extcon controller node is listed below.
+
+ extcon: max14577-muic {
+ compatible = "maxim,max14577-muic";
+ #extcon-cells = <1>;
+ };
+
+Example 2: USB controller node that uses cable from the extcon
+ controller. Refer to the standard extcon bindings for
+ information about 'extcon-cables' and 'extcon-names'
+ property.
+
+ usb@12480000 {
+ vusb_d-supply = <&vusb_reg>;
+ vusb_a-supply = <&vusbdac_reg>;
+
+ extcon-cables = <&extcon 0>, <&extcon 1>;
+ extcon-names = "USB", "USB-HOST";
+
+ status = "okay";
+ };
+
diff --git a/Documentation/devicetree/bindings/extcon/extcon-max77693.txt b/Documentation/devicetree/bindings/extcon/extcon-max77693.txt
new file mode 100644
index 0000000..ad6fe05
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-max77693.txt
@@ -0,0 +1,56 @@
+* Maxim MAX77693 MUIC Extcon Controller
+
+The MUIC part of MAX77693 IC is responsible for cable detection.
+
+Required Properties:
+
+- compatible: should be "maxim,max77693-muic".
+
+- #extcon-cells: should be 1.
+
+The following is the list of cables detected by the controller. Each
+cable is assigned an identifier and client nodes use this identifies
+to specify the cable which they are interested in.
+
+ Cable ID
+ ----------------------------
+
+ USB 0
+ USB-Host 1
+ TA 2
+ Fast-charger 3
+ Slow-charger 4
+ Charge-downstream 5
+ MHL 6
+ MHL_TA 7
+ JIG-USB-ON 8
+ JIG-USB-OFF 9
+ JIG-UART-OFF 10
+ Dock-Car 11
+ Dock-Smart 12
+ Dock-Desk 13
+ Dock-Audio 14
+ Audio-video-load 15
+
+Example 1: An example of a extcon controller node is listed below.
+
+ extcon: max77693-muic {
+ compatible = "maxim,max77693-muic";
+ #extcon-cells = <1>;
+ };
+
+Example 2: USB controller node that uses cable from the extcon
+ controller. Refer to the standard extcon bindings for
+ information about 'extcon-cables' and 'extcon-names'
+ property.
+
+ usb@12480000 {
+ vusb_d-supply = <&vusb_reg>;
+ vusb_a-supply = <&vusbdac_reg>;
+
+ extcon-cables = <&extcon 0>, <&extcon 1>;
+ extcon-names = "USB", "USB-HOST";
+
+ status = "okay";
+ };
+
diff --git a/Documentation/devicetree/bindings/extcon/extcon-max8997.txt b/Documentation/devicetree/bindings/extcon/extcon-max8997.txt
new file mode 100644
index 0000000..4ca7c5a
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-max8997.txt
@@ -0,0 +1,49 @@
+* Maxim MAX8997 MUIC Extcon Controller
+
+The MUIC part of MAX8997 IC is responsible for cable detection.
+
+Required Properties:
+
+- compatible: should be "maxim,max8997-muic".
+
+- #extcon-cells: should be 1.
+
+The following is the list of cables detected by the controller. Each
+cable is assigned an identifier and client nodes use this identifies
+to specify the cable which they are interested in.
+
+ Cable ID
+ ----------------------------
+
+ USB 0
+ USB-Host 1
+ TA 2
+ Fast-charger 3
+ Slow-charger 4
+ Charge-downstream 5
+ MHL 6
+ Dock-Desk 7
+ Dock-Card 8
+ JIG 9
+
+Example 1: An example of a extcon controller node is listed below.
+
+ extcon: max8997-muic {
+ compatible = "maxim,max8997-muic";
+ #extcon-cells = <1>;
+ };
+
+Example 2: USB controller node that uses cable from the extcon
+ controller. Refer to the standard extcon bindings for
+ information about 'extcon-cables' and 'extcon-names'
+ property.
+
+ usb@12480000 {
+ vusb_d-supply = <&vusb_reg>;
+ vusb_a-supply = <&vusbdac_reg>;
+
+ extcon-cables = <&extcon 0>, <&extcon 1>;
+ extcon-names = "USB", "USB-HOST";
+
+ status = "okay";
+ };
diff --git a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
index 45414bb..35adcee 100644
--- a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
+++ b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
@@ -8,12 +8,41 @@ Required Properties:
* "ti,palmas-usb" (DEPRECATED - use "ti,palmas-usb-vid").
* "ti,twl6035-usb" (DEPRECATED - use "ti,twl6035-usb-vid").

+- #extcon-cells: should be 1.
+
Optional Properties:
- ti,wakeup : To enable the wakeup comparator in probe
- ti,enable-id-detection: Perform ID detection.
- ti,enable-vbus-detection: Perform VBUS detection.

-palmas-usb {
- compatible = "ti,twl6035-usb", "ti,palmas-usb";
- ti,wakeup;
-};
+The following is the list of cables detected by the controller. Each
+cable is assigned an identifier and client nodes use this identifies
+to specify the cable which they are interested in.
+
+ Cable ID
+ ----------------------------
+ USB 0
+ USB-HOST 1
+
+Example 1: An example of a extcon controller node is listed below.
+
+ palmas-usb {
+ compatible = "ti,twl6035-usb", "ti,palmas-usb";
+ #extcon-cells = <1>;
+ ti,wakeup;
+ };
+
+Example 2: USB controller node that uses cable from the extcon
+ controller. Refer to the standard extcon bindings for
+ information about 'extcon-cables' and 'extcon-names'
+ property.
+
+ usb@12480000 {
+ vusb_d-supply = <&vusb_reg>;
+ vusb_a-supply = <&vusbdac_reg>;
+
+ extcon-cables = <&extcon 0>, <&extcon 1>;
+ extcon-names = "USB", "USB-HOST";
+
+ status = "okay";
+ };
--
1.7.9.5

2014-04-10 13:18:01

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 02/13] Documentation: update charger-manager devicetree bindings

This patch changes charger-manager bindings to be compatible with
new extcon bindings.

Signed-off-by: Robert Baldyga <[email protected]>
---
.../bindings/power_supply/charger-manager.txt | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
index 2b33750..f987bb5 100644
--- a/Documentation/devicetree/bindings/power_supply/charger-manager.txt
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -10,8 +10,7 @@ Required properties :
- subnode <regulator> :
- cm-regulator-name : name of charger regulator
- subnode <cable> :
- - cm-cable-name : name of charger cable
- - cm-cable-extcon : name of extcon dev
+ - extcon-cable : specified extcon cable
(optional) - cm-cable-min : minimum current of cable
(optional) - cm-cable-max : maximum current of cable

@@ -65,14 +64,14 @@ Example :
regulator@0 {
cm-regulator-name = "chg-reg";
cable@0 {
- cm-cable-name = "USB";
- cm-cable-extcon = "extcon-dev.0";
+ /* USB cable */
+ extcon-cable = <&extcon 0>;
cm-cable-min = <475000>;
cm-cable-max = <500000>;
};
cable@1 {
- cm-cable-name = "TA";
- cm-cable-extcon = "extcon-dev.0";
+ /* TA cable */
+ extcon-cable = <&extcon 1>;
cm-cable-min = <650000>;
cm-cable-max = <675000>;
};
--
1.7.9.5

2014-04-10 13:18:17

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 03/13] extcon: extcon-class: remove extcon_set_cable_state() function

This patch removes extcon_set_cable_state() and replace all calls of
this function witch extcon_set_cable_state_(), which is faster version.
This is first step of changing extcon API to faster and safer.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-class.c | 17 --------
drivers/extcon/extcon-max14577.c | 24 ++++++------
drivers/extcon/extcon-max77693.c | 79 +++++++++++++++++++++++---------------
drivers/extcon/extcon-max8997.c | 32 +++++++++------
drivers/extcon/extcon-palmas.c | 27 +++++++++----
include/linux/extcon.h | 8 ----
6 files changed, 99 insertions(+), 88 deletions(-)

diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index a45c5e9..1b98c4e 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -358,23 +358,6 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
EXPORT_SYMBOL_GPL(extcon_set_cable_state_);

/**
- * extcon_set_cable_state() - Set the status of a specific cable.
- * @edev: the extcon device that has the cable.
- * @cable_name: cable name.
- * @cable_state: the new cable status. The default semantics is
- * true: attached / false: detached.
- *
- * Note that this is slower than 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);
-}
-EXPORT_SYMBOL_GPL(extcon_set_cable_state);
-
-/**
* extcon_get_extcon_dev() - Get the extcon device instance from the name
* @extcon_name: The extcon name provided with extcon_dev_register()
*/
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c
index 3846941..7a947d3 100644
--- a/drivers/extcon/extcon-max14577.c
+++ b/drivers/extcon/extcon-max14577.c
@@ -333,7 +333,7 @@ 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 cable;
int ret = 0;
u8 path = CTRL1_SW_OPEN;

@@ -344,17 +344,17 @@ 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");
+ cable = EXTCON_CABLE_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");
+ cable = EXTCON_CABLE_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");
+ cable = EXTCON_CABLE_JIG_UART_OFF;
path = CTRL1_SW_UART;
break;
default:
@@ -367,7 +367,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, cable, attached);

return 0;
}
@@ -464,20 +464,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_CABLE_USB, attached);
break;
case MAX14577_CHARGER_TYPE_DEDICATED_CHG:
- extcon_set_cable_state(info->edev, "TA", attached);
+ extcon_set_cable_state_(info->edev, EXTCON_CABLE_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_CABLE_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_CABLE_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_CABLE_FAST_CHARGER, attached);
break;
case MAX14577_CHARGER_TYPE_NONE:
case MAX14577_CHARGER_TYPE_DEAD_BATTERY:
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 905051d..7a014cd 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -216,6 +216,7 @@ enum {
EXTCON_CABLE_DOCK_SMART,
EXTCON_CABLE_DOCK_DESK,
EXTCON_CABLE_DOCK_AUDIO,
+ EXTCON_CABLE_AV_LOAD,

_EXTCON_CABLE_NUM,
};
@@ -236,6 +237,7 @@ static const char *max77693_extcon_cable[] = {
[EXTCON_CABLE_DOCK_SMART] = "Dock-Smart",
[EXTCON_CABLE_DOCK_DESK] = "Dock-Desk",
[EXTCON_CABLE_DOCK_AUDIO] = "Dock-Audio",
+ [EXTCON_CABLE_AV_LOAD] = "Audio-video-load",

NULL,
};
@@ -480,7 +482,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];
+ int dock;

dev_info(info->dev,
"external connector is %s (adc:0x%02x)\n",
@@ -525,19 +527,22 @@ 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_CABLE_DOCK_SMART, attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_MHL, attached);
goto out;
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* Dock-Car */
- strcpy(dock_name, "Dock-Car");
+ dock = EXTCON_CABLE_JIG_UART_ON;
break;
case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */
- strcpy(dock_name, "Dock-Desk");
+ dock = EXTCON_CABLE_DOCK_DESK;
break;
case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */
- strcpy(dock_name, "Dock-Audio");
+ dock = EXTCON_CABLE_DOCK_AUDIO;
if (!attached)
- extcon_set_cable_state(info->edev, "USB", false);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_USB, false);
break;
default:
dev_err(info->dev, "failed to detect %s dock device\n",
@@ -549,7 +554,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, attached);

out:
return 0;
@@ -614,20 +619,22 @@ 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_CABLE_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_CABLE_AV_LOAD, 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_CABLE_MHL, attached);
break;
default:
dev_err(info->dev, "failed to detect %s cable of gnd type\n",
@@ -641,7 +648,7 @@ 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 cable;
int ret = 0;
u8 path = CONTROL1_SW_OPEN;

@@ -652,17 +659,17 @@ 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");
+ cable = EXTCON_CABLE_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");
+ cable = EXTCON_CABLE_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");
+ cable = EXTCON_CABLE_JIG_UART_OFF;
path = CONTROL1_SW_UART;
break;
default:
@@ -675,7 +682,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, cable, attached);

return 0;
}
@@ -829,10 +836,11 @@ 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, "MHL_TA", attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_MHL_TA, attached);
if (!cable_attached)
- extcon_set_cable_state(info->edev,
- "MHL", cable_attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_MHL, cable_attached);
break;
}

@@ -855,11 +863,13 @@ 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_CABLE_USB, attached);

if (!cable_attached)
- extcon_set_cable_state(info->edev, "Dock-Audio",
- cable_attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_DOCK_AUDIO,
+ cable_attached);
break;
case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */
/*
@@ -887,9 +897,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_CABLE_DOCK_SMART, attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_MHL, attached);

break;
}
@@ -923,23 +934,27 @@ 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_CABLE_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_CABLE_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_CABLE_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_CABLE_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_CABLE_FAST_CHARGER, attached);
break;
case MAX77693_CHARGER_TYPE_DEAD_BATTERY:
break;
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index f97a38a..a3df70d 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -348,10 +348,12 @@ 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_CABLE_USB_HOST, attached);
break;
case MAX8997_USB_DEVICE:
- extcon_set_cable_state(info->edev, "USB", attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_USB, attached);
break;
default:
dev_err(info->dev, "failed to detect %s usb cable\n",
@@ -375,10 +377,12 @@ 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);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_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_CABLE_DOCK_CARD, attached);
break;
default:
dev_err(info->dev, "failed to detect %s dock device\n",
@@ -401,7 +405,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_CABLE_JIG, attached);

return 0;
}
@@ -423,7 +427,8 @@ 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_CABLE_MHL, attached);
break;
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
@@ -506,17 +511,20 @@ 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_CABLE_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_CABLE_TA, attached);
break;
case MAX8997_CHARGER_TYPE_500MA:
- extcon_set_cable_state(info->edev, "Slow-charger", attached);
+ extcon_set_cable_state_(info->edev,
+ EXTCON_CABLE_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_CABLE_FAST_CHARGER, attached);
break;
default:
dev_err(info->dev,
@@ -758,7 +766,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
}

/* Set initial path for UART */
- max8997_muic_set_path(info, info->path_uart, true);
+ max8997_muic_set_path(info, info->path_usb, true);

/* Set ADC debounce time */
max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index ddff2b7..26c0619 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -28,9 +28,14 @@
#include <linux/of.h>
#include <linux/of_platform.h>

+enum {
+ EXTCON_CABLE_USB = 0,
+ EXTCON_CABLE_USB_HOST,
+};
+
static const char *palmas_extcon_cable[] = {
- [0] = "USB",
- [1] = "USB-HOST",
+ [EXTCON_CABLE_USB] = "USB",
+ [EXTCON_CABLE_USB_HOST] = "USB-HOST",
NULL,
};

@@ -56,7 +61,8 @@ 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_(&palmas_usb->edev,
+ EXTCON_CABLE_USB, true);
dev_info(palmas_usb->dev, "USB cable is attached\n");
} else {
dev_dbg(palmas_usb->dev,
@@ -65,7 +71,8 @@ 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_(&palmas_usb->edev,
+ EXTCON_CABLE_USB, false);
dev_info(palmas_usb->dev, "USB cable is detached\n");
} else {
dev_dbg(palmas_usb->dev,
@@ -92,7 +99,8 @@ 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_(&palmas_usb->edev,
+ EXTCON_CABLE_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)) {
@@ -100,17 +108,20 @@ 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_(&palmas_usb->edev,
+ EXTCON_CABLE_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_(&palmas_usb->edev,
+ EXTCON_CABLE_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_(&palmas_usb->edev,
+ EXTCON_CABLE_USB_HOST, true);
dev_info(palmas_usb->dev, " USB-HOST cable is attached\n");
}

diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index f488145..ed4a47b 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -214,8 +214,6 @@ extern int extcon_set_cable_state_(struct extcon_dev *edev, int cable_index,

extern int extcon_get_cable_state(struct extcon_dev *edev,
const char *cable_name);
-extern int extcon_set_cable_state(struct extcon_dev *edev,
- const char *cable_name, bool cable_state);

/*
* Following APIs are for notifiees (those who want to be notified)
@@ -282,12 +280,6 @@ static inline int extcon_get_cable_state_(struct extcon_dev *edev,
return 0;
}

-static inline int extcon_set_cable_state_(struct extcon_dev *edev,
- int cable_index, bool cable_state)
-{
- return 0;
-}
-
static inline int extcon_get_cable_state(struct extcon_dev *edev,
const char *cable_name)
{
--
1.7.9.5

2014-04-10 13:18:56

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 04/13] extcon: extcon-class: match extcon device by devicetree node

This patch modifies extcon_get_edev_by_phandle() function, to match
extcon device by devicetree node. This modification needed to add
field 'node' in extcon_dev structure, and fill it in probe function
of each extcon provider driver.

This patch replaces also extcon_get_extcon_dev() function with
of_extcon_get_extcon_dev(), returning extcon device which contains
given devicetree node.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-adc-jack.c | 1 +
drivers/extcon/extcon-arizona.c | 1 +
drivers/extcon/extcon-class.c | 19 +++++++++----------
drivers/extcon/extcon-gpio.c | 1 +
drivers/extcon/extcon-max14577.c | 2 ++
drivers/extcon/extcon-max77693.c | 1 +
drivers/extcon/extcon-max8997.c | 1 +
drivers/extcon/extcon-palmas.c | 1 +
include/linux/extcon.h | 8 ++------
9 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index e23f1c2..d65915e 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -111,6 +111,7 @@ static int adc_jack_probe(struct platform_device *pdev)
}

data->edev.dev.parent = &pdev->dev;
+ data->edev.node = pdev->dev.of_node;
data->edev.supported_cable = pdata->cable_names;

/* Check the length of array and set num_cables */
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 98a14f6..fc69cca 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -1153,6 +1153,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)

info->edev.name = "Headset Jack";
info->edev.dev.parent = arizona->dev;
+ info->edev.node = pdev->dev.of_node;
info->edev.supported_cable = arizona_cable;

ret = extcon_dev_register(&info->edev);
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 1b98c4e..1075ce8 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -358,24 +358,23 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
EXPORT_SYMBOL_GPL(extcon_set_cable_state_);

/**
- * extcon_get_extcon_dev() - Get the extcon device instance from the name
- * @extcon_name: The extcon name provided with extcon_dev_register()
+ * of_extcon_get_extcon_dev() - Get the extcon device instance from the name
+ * @np: The node of extcon device
*/
-struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
+struct extcon_dev *of_extcon_get_extcon_dev(const struct device_node *np)
{
- struct extcon_dev *sd;
+ struct extcon_dev *edev;

mutex_lock(&extcon_dev_list_lock);
- list_for_each_entry(sd, &extcon_dev_list, entry) {
- if (!strcmp(sd->name, extcon_name))
+ list_for_each_entry(edev, &extcon_dev_list, entry) {
+ if (edev->node == np)
goto out;
}
- sd = NULL;
+ edev = NULL;
out:
mutex_unlock(&extcon_dev_list_lock);
- return sd;
+ return edev;
}
-EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);

static int _call_per_cable(struct notifier_block *nb, unsigned long val,
void *ptr)
@@ -827,7 +826,7 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
return ERR_PTR(-ENODEV);
}

- edev = extcon_get_extcon_dev(node->name);
+ edev = of_extcon_get_extcon_dev(node);
if (!edev) {
dev_err(dev, "unable to get extcon device : %s\n", node->name);
return ERR_PTR(-ENODEV);
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 13d5222..fc90b7a 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -100,6 +100,7 @@ static int gpio_extcon_probe(struct platform_device *pdev)

extcon_data->edev.name = pdata->name;
extcon_data->edev.dev.parent = &pdev->dev;
+ extcon_data->edev.node = pdev->dev.of_node;
extcon_data->gpio = pdata->gpio;
extcon_data->gpio_active_low = pdata->gpio_active_low;
extcon_data->state_on = pdata->state_on;
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c
index 7a947d3..b017a0d 100644
--- a/drivers/extcon/extcon-max14577.c
+++ b/drivers/extcon/extcon-max14577.c
@@ -676,6 +676,8 @@ static int max14577_muic_probe(struct platform_device *pdev)
return -ENOMEM;
}
info->edev->name = DEV_NAME;
+ info->edev->dev.parent = &pdev->dev;
+ info->edev->node = pdev->dev.of_node;
info->edev->supported_cable = max14577_extcon_cable;
ret = extcon_dev_register(info->edev);
if (ret) {
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 7a014cd..2cd8892 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -1200,6 +1200,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
}
info->edev->name = DEV_NAME;
info->edev->dev.parent = &pdev->dev;
+ info->edev->node = pdev->dev.of_node;
info->edev->supported_cable = max77693_extcon_cable;
ret = extcon_dev_register(info->edev);
if (ret) {
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index a3df70d..c071588 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -718,6 +718,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
}
info->edev->name = DEV_NAME;
info->edev->dev.parent = &pdev->dev;
+ info->edev->node = pdev->dev.of_node;
info->edev->supported_cable = max8997_extcon_cable;
ret = extcon_dev_register(info->edev);
if (ret) {
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 26c0619..153a40e 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -199,6 +199,7 @@ static int palmas_usb_probe(struct platform_device *pdev)

palmas_usb->edev.supported_cable = palmas_extcon_cable;
palmas_usb->edev.dev.parent = palmas_usb->dev;
+ palmas_usb->edev.node = pdev->dev.of_node;
palmas_usb->edev.mutually_exclusive = mutually_exclusive;

status = extcon_dev_register(&palmas_usb->edev);
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index ed4a47b..d0fd810 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -77,6 +77,7 @@ struct extcon_cable;
/**
* struct extcon_dev - An extcon device represents one external connector.
* @name: The name of this extcon device. Parent device name is
+ * @node: Devicetree node of parent device.
* used if NULL.
* @supported_cable: Array of supported cable names ending with NULL.
* If supported_cable is NULL, cable name related APIs
@@ -113,6 +114,7 @@ struct extcon_cable;
struct extcon_dev {
/* Optional user initializing data */
const char *name;
+ const struct device_node *node;
const char **supported_cable;
const u32 *mutually_exclusive;

@@ -185,7 +187,6 @@ struct extcon_specific_cable_nb {
*/
extern int extcon_dev_register(struct extcon_dev *edev);
extern void extcon_dev_unregister(struct extcon_dev *edev);
-extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);

/*
* get/set/update_state access the 32b encoded state value, which represents
@@ -292,11 +293,6 @@ static inline int extcon_set_cable_state(struct extcon_dev *edev,
return 0;
}

-static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
-{
- return NULL;
-}
-
static inline int extcon_register_notifier(struct extcon_dev *edev,
struct notifier_block *nb)
{
--
1.7.9.5

2014-04-10 13:19:10

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 06/13] extcon: extcon-class: remove unused functions

This patch removes two functions, extcon_find_cable_index() and
extcon_get_edev_by_phandle(). They are not longer needed, since
extcon client API has changed to be oriented on extcon_cable instead
of extcon_dev.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-class.c | 67 -----------------------------------------
include/linux/extcon.h | 18 -----------
2 files changed, 85 deletions(-)

diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 708b352..2be0ac9 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -283,32 +283,6 @@ 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.
- * @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.
- */
-int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
-{
- 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;
- }
- }
-
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(extcon_find_cable_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().
@@ -876,47 +850,6 @@ void extcon_dev_unregister(struct extcon_dev *edev)
}
EXPORT_SYMBOL_GPL(extcon_dev_unregister);

-#ifdef CONFIG_OF
-/*
- * extcon_get_edev_by_phandle - Get the extcon device from devicetree
- * @dev - instance to the given device
- * @index - index into list of extcon_dev
- *
- * return the instance of extcon device
- */
-struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
-{
- struct device_node *node;
- struct extcon_dev *edev;
-
- if (!dev->of_node) {
- dev_err(dev, "device does not have a device node entry\n");
- return ERR_PTR(-EINVAL);
- }
-
- node = of_parse_phandle(dev->of_node, "extcon", index);
- if (!node) {
- dev_err(dev, "failed to get phandle in %s node\n",
- dev->of_node->full_name);
- return ERR_PTR(-ENODEV);
- }
-
- edev = of_extcon_get_extcon_dev(node);
- if (!edev) {
- dev_err(dev, "unable to get extcon device : %s\n", node->name);
- return ERR_PTR(-ENODEV);
- }
-
- return edev;
-}
-#else
-struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
-{
- return ERR_PTR(-ENOSYS);
-}
-#endif /* CONFIG_OF */
-EXPORT_SYMBOL_GPL(extcon_get_edev_by_phandle);
-
static int __init extcon_class_init(void)
{
return create_extcon_class();
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index a571cad..939a7b0 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -210,8 +210,6 @@ extern int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state);
* They are used to access the status of each cable based on the cable_name
tt or cable_index, which is retrieved by extcon_find_cable_index
*/
-extern int extcon_find_cable_index(struct extcon_dev *sdev,
- const char *cable_name);
extern int extcon_get_cable_state_(struct extcon_dev *edev, int cable_index);
extern int extcon_set_cable_state_(struct extcon_dev *edev,
int cable_index, bool cable_state);
@@ -252,11 +250,6 @@ extern int extcon_register_notifier(struct extcon_dev *edev,
extern int extcon_unregister_notifier(struct extcon_dev *edev,
struct notifier_block *nb);

-/*
- * Following API get the extcon device from devicetree.
- * This function use phandle of devicetree to get extcon device directly.
- */
-extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index);
#else /* CONFIG_EXTCON */
static inline int extcon_dev_register(struct extcon_dev *edev)
{
@@ -281,12 +274,6 @@ static inline int extcon_update_state(struct extcon_dev *edev, u32 mask,
return 0;
}

-static inline int extcon_find_cable_index(struct extcon_dev *edev,
- const char *cable_name)
-{
- return 0;
-}
-
static inline int extcon_get_cable_state_(struct extcon_dev *edev,
int cable_index)
{
@@ -341,10 +328,5 @@ static inline int extcon_unregister_interest(struct extcon_cable_nb
return 0;
}

-static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
- int index)
-{
- return ERR_PTR(-ENODEV);
-}
#endif /* CONFIG_EXTCON */
#endif /* __LINUX_EXTCON_H__ */
--
1.7.9.5

2014-04-10 13:19:27

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 07/13] extcon: extcon-class: improve get_cable_state_()/set_cable_state_() functions

Added check if pointer to edev is not NULL, and updated documentation of index
parameter. Function extcon_find_cable_index() has been deleted and cannot be
used to retrieve cable number.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-class.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 2be0ac9..2659805 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -285,10 +285,12 @@ EXPORT_SYMBOL_GPL(extcon_set_state);
/**
* 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().
+ * @index: cable index in extcon device.
*/
int extcon_get_cable_state_(struct extcon_dev *edev, int index)
{
+ if (!edev)
+ return -ENODEV;
if (index < 0 || (edev->max_supported && edev->max_supported <= index))
return -EINVAL;

@@ -312,8 +314,7 @@ 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().
+ * @index: cable index in extcon device.
* @cable_state: the new cable status. The default semantics is
* true: attached / false: detached.
*/
@@ -322,6 +323,8 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
{
u32 state;

+ if (!edev)
+ return -ENODEV;
if (index < 0 || (edev->max_supported && edev->max_supported <= index))
return -EINVAL;

--
1.7.9.5

2014-04-10 13:19:57

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 08/13] extcon: extcon-class: simplify extcon_updata_state() function

This patch simplifies extcon_updata_state() function. There is greatly
simplified kobject_uevent preparation. Also meaning of variable passed
to raw_notifier_call_chain() (and in effect to _call_per_cable()) has
changed. Now positions on ones in variable 'val' in _call_per_cable()
indicates numbers of cables which changed their status. It allowed
to simplify also _call_per_cable() function.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-class.c | 81 ++++++++++++++++-------------------------
include/linux/extcon.h | 1 -
2 files changed, 31 insertions(+), 51 deletions(-)

diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 2659805..ce76c08 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -206,59 +206,48 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
{
char name_buf[120];
char state_buf[120];
- char *prop_buf;
+ char *tmp;
char *envp[3];
int env_offset = 0;
int length;
unsigned long flags;
+ u32 change;

spin_lock_irqsave(&edev->lock, flags);

- if (edev->state != ((edev->state & ~mask) | (state & mask))) {
- u32 old_state = edev->state;
-
- if (check_mutually_exclusive(edev, (edev->state & ~mask) |
- (state & mask))) {
+ change = (edev->state & mask) ^ (state & mask);
+ if (change) {
+ if (check_mutually_exclusive(edev, edev->state ^ change)) {
spin_unlock_irqrestore(&edev->lock, flags);
return -EPERM;
}

- edev->state &= ~mask;
- edev->state |= state & mask;
-
- raw_notifier_call_chain(&edev->nh, old_state, edev);
- /* This could be in interrupt handler */
- prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
- if (prop_buf) {
- length = name_show(&edev->dev, NULL, prop_buf);
- if (length > 0) {
- if (prop_buf[length - 1] == '\n')
- prop_buf[length - 1] = 0;
- snprintf(name_buf, sizeof(name_buf),
- "NAME=%s", prop_buf);
- envp[env_offset++] = name_buf;
- }
- length = state_show(&edev->dev, NULL, prop_buf);
- if (length > 0) {
- if (prop_buf[length - 1] == '\n')
- prop_buf[length - 1] = 0;
- snprintf(state_buf, sizeof(state_buf),
- "STATE=%s", prop_buf);
- envp[env_offset++] = state_buf;
- }
- envp[env_offset] = NULL;
- /* Unlock early before uevent */
- spin_unlock_irqrestore(&edev->lock, flags);
+ edev->state ^= change;

- kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
- free_page((unsigned long)prop_buf);
- } else {
- /* Unlock early before uevent */
- spin_unlock_irqrestore(&edev->lock, flags);
+ raw_notifier_call_chain(&edev->nh, change, edev);
+
+ tmp = name_buf + sprintf(name_buf, "NAME=");
+ length = name_show(&edev->dev, NULL, tmp);
+ if (length > 0) {
+ if (tmp[length - 1] == '\n')
+ tmp[length - 1] = 0;
+ envp[env_offset++] = name_buf;
+ }

- dev_err(&edev->dev, "out of memory in extcon_set_state\n");
- kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
+ tmp = state_buf + sprintf(state_buf, "STATE=");
+ length = state_show(&edev->dev, NULL, tmp);
+ if (length > 0) {
+ if (tmp[length - 1] == '\n')
+ tmp[length - 1] = 0;
+ envp[env_offset++] = state_buf;
}
+
+ envp[env_offset] = NULL;
+
+ /* Unlock early before uevent */
+ spin_unlock_irqrestore(&edev->lock, flags);
+
+ kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
} else {
/* No changes */
spin_unlock_irqrestore(&edev->lock, flags);
@@ -464,18 +453,10 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
{
struct extcon_cable_nb *obj = container_of(nb,
struct extcon_cable_nb, internal_nb);
- struct extcon_dev *edev = ptr;
-
- if ((val & (1 << obj->cable->cable_index)) !=
- (edev->state & (1 << obj->cable->cable_index))) {
- bool cable_state = true;
-
- obj->previous_value = val;
-
- if (val & (1 << obj->cable->cable_index))
- cable_state = false;

- return obj->notifier_function(obj, cable_state);
+ if ((1 << obj->cable->cable_index) & val) {
+ int state = extcon_get_cable_state(obj->cable);
+ return obj->notifier_function(obj, !!state);
}

return NOTIFY_OK;
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index 939a7b0..4194931 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -177,7 +177,6 @@ typedef int (*extcon_notifier_fn_t)(struct extcon_cable_nb *cable_nb,
*/
struct extcon_cable_nb {
struct notifier_block internal_nb;
- unsigned long previous_value;
extcon_notifier_fn_t notifier_function;
struct extcon_cable *cable;
};
--
1.7.9.5

2014-04-10 13:20:23

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 09/13] extcon: extcon-class: move example to Documentation

This patch removes cable array example form extcon code, to avoid
littering driver namespace. Now it's located in extcon documentation.

Signed-off-by: Robert Baldyga <[email protected]>
---
Documentation/extcon/extcon.txt | 108 +++++++++++++++++++++++++++++++++++++++
drivers/extcon/extcon-class.c | 32 ------------
include/linux/extcon.h | 42 ---------------
3 files changed, 108 insertions(+), 74 deletions(-)
create mode 100644 Documentation/extcon/extcon.txt

diff --git a/Documentation/extcon/extcon.txt b/Documentation/extcon/extcon.txt
new file mode 100644
index 0000000..6713f5f
--- /dev/null
+++ b/Documentation/extcon/extcon.txt
@@ -0,0 +1,108 @@
+Extcon - external connector
+===========================
+
+Extcon is generic framework used for notifying client drivers
+about specific cable connections and disconnections.
+
+Provider API
+============
+
+Providers API consists of very few functions:
+
+extcon_dev_register() - register new extcon provider
+extcon_dev_unregister() - unregister extcon provider
+
+extcon_get_cable_state_() - get specific cable state
+extcon_set_cable_state_() - set specific cable state
+
+extcon_update_state() - update entire extcon state
+extcon_set_state() - set entire extcon state
+
+There are few fields in struct extcon_dev to be filled before passing it
+to extcon_dev_register() functions:
+
+name - name of extcon controller
+node - devicetree node of parent device
+supported_cable - array of strings with cable names ended with NULL pointer
+
+Example of cable array definition example can be found below:
+
+ enum extcon_cable_name {
+ EXTCON_USB = 0,
+ EXTCON_USB_HOST,
+ EXTCON_TA,
+ EXTCON_FAST_CHARGER,
+ EXTCON_SLOW_CHARGER,
+ EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_HDMI,
+ EXTCON_MHL,
+ EXTCON_DVI,
+ EXTCON_VGA,
+ EXTCON_DOCK,
+ EXTCON_LINE_IN,
+ EXTCON_LINE_OUT,
+ EXTCON_MIC_IN,
+ EXTCON_HEADPHONE_OUT,
+ EXTCON_SPDIF_IN,
+ EXTCON_SPDIF_OUT,
+ EXTCON_VIDEO_IN,
+ EXTCON_VIDEO_OUT,
+ EXTCON_MECHANICAL,
+ };
+
+ const char *extcon_cable_name[] = {
+ [EXTCON_USB] = "USB",
+ [EXTCON_USB_HOST] = "USB-Host",
+ [EXTCON_TA] = "TA",
+ [EXTCON_FAST_CHARGER] = "Fast-charger",
+ [EXTCON_SLOW_CHARGER] = "Slow-charger",
+ [EXTCON_CHARGE_DOWNSTREAM] = "Charge-downstream",
+ [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",
+ };
+
+Cable name strings are used for debug messages and sysfs.
+
+After extcon device registration you can use functions modifying extcon state.
+If any extcon clients will register their interests in some cables, they will
+recieve notifications about cable state changes.
+
+Client API
+==========
+
+Extcon client API is also pretty simple. It consists of funtions:
+
+of_extcon_get_cable() - returns extcon_cable at selected index
+of_extcon_get_cable_by_name() - returns extcon_cable associated with
+ selected name
+extcon_get_cable_by_name() - the same as above, but takes struct device
+ instead of struct device_node
+
+extcon_register_interest() - register interest in selected cable
+extcon_unregister_interest() - unregister cable interest
+
+extcon_get_cable_state() - get state of given cable
+
+The extcon_register_interest() function takes three parameters,
+struct extcon_cable, struct extcon_cable_nb and extcon_notifier_fn_t
+which is pointer to callback function called when cable state changes.
+
+There are also two functions:
+
+extcon_register_notifier() - register notifier for entire extcon state
+extcon_unregister_notifier() - unregister such notifier
+
+But they should be used only for debug, and use of them in client drivers
+is not recommended.
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index ce76c08..2ea9a84 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -33,38 +33,6 @@
#include <linux/sysfs.h>
#include <linux/of.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] = {
- [EXTCON_USB] = "USB",
- [EXTCON_USB_HOST] = "USB-Host",
- [EXTCON_TA] = "TA",
- [EXTCON_FAST_CHARGER] = "Fast-charger",
- [EXTCON_SLOW_CHARGER] = "Slow-charger",
- [EXTCON_CHARGE_DOWNSTREAM] = "Charge-downstream",
- [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",
-};
-
static struct class *extcon_class;
#if defined(CONFIG_ANDROID)
static struct class_compat *switch_class;
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index 4194931..42cf8b3 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -31,48 +31,6 @@
#define SUPPORTED_CABLE_MAX 32
#define CABLE_NAME_MAX 30

-/*
- * The standard cable name is to help support general notifier
- * and notifiee device drivers to share the common names.
- * Please use standard cable names unless your notifier device has
- * a very unique and abnormal cable or
- * the cable type is supposed to be used with only one unique
- * pair of notifier/notifiee devices.
- *
- * Please add any other "standard" cables used with extcon dev.
- *
- * You may add a dot and number to specify version or specification
- * of the specific cable if it is required. (e.g., "Fast-charger.18"
- * and "Fast-charger.10" for 1.8A and 1.0A chargers)
- * However, the notifiee and notifier should be able to handle such
- * string and if the notifiee can negotiate the protocol or identify,
- * you don't need such convention. This convention is helpful when
- * notifier can distinguish but notifiee cannot.
- */
-enum extcon_cable_name {
- EXTCON_USB = 0,
- EXTCON_USB_HOST,
- EXTCON_TA, /* Travel Adaptor */
- EXTCON_FAST_CHARGER,
- EXTCON_SLOW_CHARGER,
- EXTCON_CHARGE_DOWNSTREAM, /* Charging an external device */
- EXTCON_HDMI,
- EXTCON_MHL,
- EXTCON_DVI,
- EXTCON_VGA,
- EXTCON_DOCK,
- EXTCON_LINE_IN,
- EXTCON_LINE_OUT,
- EXTCON_MIC_IN,
- EXTCON_HEADPHONE_OUT,
- EXTCON_SPDIF_IN,
- EXTCON_SPDIF_OUT,
- EXTCON_VIDEO_IN,
- EXTCON_VIDEO_OUT,
- EXTCON_MECHANICAL,
-};
-extern const char extcon_cable_name[][CABLE_NAME_MAX + 1];
-
struct extcon_cable;

/**
--
1.7.9.5

2014-04-10 13:20:44

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 10/13] extcon: extcon-gpio: add devicetree support

This patch modifies extcon-gpio driver to use initialization data from
devicetree if platform data is not available. It allows to set controller
and cable names, and another parameters from devicetree bindings.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-gpio.c | 63 ++++++++++++++++++++++++++++++------
include/linux/extcon/extcon-gpio.h | 2 +-
2 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index fc90b7a..2a3cfd7 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -28,6 +28,8 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/extcon.h>
#include <linux/extcon/extcon-gpio.h>

@@ -53,7 +55,7 @@ static void gpio_extcon_work(struct work_struct *work)
state = gpio_get_value(data->gpio);
if (data->gpio_active_low)
state = !state;
- extcon_set_state(&data->edev, state);
+ extcon_set_cable_state_(&data->edev, 0, state);
}

static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
@@ -70,7 +72,7 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
struct gpio_extcon_data *extcon_data =
container_of(edev, struct gpio_extcon_data, edev);
const char *state;
- if (extcon_get_state(edev))
+ if (extcon_get_cable_state_(edev, 0))
state = extcon_data->state_on;
else
state = extcon_data->state_off;
@@ -80,17 +82,50 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
return -EINVAL;
}

+static struct gpio_extcon_platform_data *get_pdata_from_dt(struct device *dev)
+{
+ int ret;
+ struct gpio_extcon_platform_data *pdata =
+ devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+
+ ret = of_property_read_string_index(dev->of_node,
+ "gpio-controller-name", 0, &pdata->name);
+ if (ret)
+ return NULL;
+
+ ret = of_property_read_string_index(dev->of_node,
+ "gpio-cable-name", 0, &pdata->cable_name);
+ if (ret)
+ return NULL;
+
+ ret = of_property_read_u32_array(dev->of_node,
+ "gpio-debounce", &pdata->debounce, 0);
+ if (ret)
+ pdata->debounce = 0;
+
+ pdata->gpio = of_get_gpio(dev->of_node, 0);
+ if (pdata->gpio < 0)
+ return NULL;
+
+ pdata->gpio_active_low = of_property_read_bool(dev->of_node,
+ "gpio-active-low");
+
+ pdata->check_on_resume = of_property_read_bool(dev->of_node,
+ "check-on-resume");
+ return pdata;
+}
+
static int gpio_extcon_probe(struct platform_device *pdev)
{
struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct gpio_extcon_data *extcon_data;
+ const char *gpio_extcon_cable[2];
int ret;

- if (!pdata)
- return -EBUSY;
- if (!pdata->irq_flags) {
- dev_err(&pdev->dev, "IRQ flag is not specified.\n");
- return -EINVAL;
+ if (!pdata) {
+ pdata = get_pdata_from_dt(&pdev->dev);
+ if (!pdata)
+ return -EINVAL;
}

extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data),
@@ -98,10 +133,14 @@ static int gpio_extcon_probe(struct platform_device *pdev)
if (!extcon_data)
return -ENOMEM;

+ gpio_extcon_cable[0] = pdata->cable_name;
+ gpio_extcon_cable[1] = NULL;
+
extcon_data->edev.name = pdata->name;
extcon_data->edev.dev.parent = &pdev->dev;
extcon_data->edev.node = pdev->dev.of_node;
extcon_data->gpio = pdata->gpio;
+ extcon_data->edev.supported_cable = gpio_extcon_cable;
extcon_data->gpio_active_low = pdata->gpio_active_low;
extcon_data->state_on = pdata->state_on;
extcon_data->state_off = pdata->state_off;
@@ -135,8 +174,8 @@ static int gpio_extcon_probe(struct platform_device *pdev)
}

ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler,
- pdata->irq_flags, pdev->name,
- extcon_data);
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ pdev->name, extcon_data);
if (ret < 0)
goto err;

@@ -177,6 +216,11 @@ static int gpio_extcon_resume(struct device *dev)
}
#endif

+static struct of_device_id of_gpio_match_tbl[] = {
+ { .compatible = "extcon-gpio", },
+ { /* end */ },
+};
+
static SIMPLE_DEV_PM_OPS(gpio_extcon_pm_ops, NULL, gpio_extcon_resume);

static struct platform_driver gpio_extcon_driver = {
@@ -184,6 +228,7 @@ static struct platform_driver gpio_extcon_driver = {
.remove = gpio_extcon_remove,
.driver = {
.name = "extcon-gpio",
+ .of_match_table = of_gpio_match_tbl,
.owner = THIS_MODULE,
.pm = &gpio_extcon_pm_ops,
},
diff --git a/include/linux/extcon/extcon-gpio.h b/include/linux/extcon/extcon-gpio.h
index 8900fdf..3850588 100644
--- a/include/linux/extcon/extcon-gpio.h
+++ b/include/linux/extcon/extcon-gpio.h
@@ -43,10 +43,10 @@
*/
struct gpio_extcon_platform_data {
const char *name;
+ const char *cable_name;
unsigned gpio;
bool gpio_active_low;
unsigned long debounce;
- unsigned long irq_flags;

/* if NULL, "0" or "1" will be printed */
const char *state_on;
--
1.7.9.5

2014-04-10 13:21:01

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 11/13] extcon: extcon-adc-jack: add devicetree support

This patch modifies extcon-adc-jack driver to use initialization data from
devicetree, when platform data is not available. It allows to define cable list
with ADC value ranges for each of them in devicetree bindings.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-adc-jack.c | 74 ++++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)

diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index d65915e..293871b1 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -21,6 +21,7 @@
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
+#include <linux/of.h>
#include <linux/iio/consumer.h>
#include <linux/extcon/extcon-adc-jack.h>
#include <linux/extcon.h>
@@ -92,12 +93,78 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
return IRQ_HANDLED;
}

+static struct adc_jack_pdata *get_pdata_from_dt(struct device *dev)
+{
+ int ret, cnt, i;
+ struct device_node *cables_np, *child;
+ struct adc_jack_pdata *pdata =
+ devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+
+ ret = of_property_read_string_index(dev->of_node,
+ "adc-name", 0, &pdata->name);
+ if (ret)
+ return NULL;
+
+ ret = of_property_read_string_index(dev->of_node,
+ "adc-consumer-channel", 0, &pdata->consumer_channel);
+ if (ret)
+ return NULL;
+
+ cables_np = of_find_node_by_name(dev->of_node, "cables");
+ if (!cables_np)
+ return NULL;
+
+ cnt = of_get_child_count(cables_np);
+ if (cnt <= 0)
+ return NULL;
+
+ pdata->cable_names = devm_kcalloc(dev, cnt+1,
+ sizeof(*pdata->cable_names), GFP_KERNEL);
+ if (!pdata->cable_names)
+ return NULL;
+
+ pdata->adc_conditions = devm_kcalloc(dev, cnt+1,
+ sizeof(*pdata->adc_conditions), GFP_KERNEL);
+ if (!pdata->adc_conditions)
+ return NULL;
+
+ i = 0;
+ for_each_child_of_node(cables_np, child) {
+ ret = of_property_read_string_index(child,
+ "cable-name", 0, &pdata->cable_names[i]);
+ if (ret)
+ return NULL;
+
+ pdata->adc_conditions[i].state = (1<<i);
+
+ ret = of_property_read_u32_array(child, "adc-min",
+ &pdata->adc_conditions[i].min_adc, 0);
+ if (ret)
+ return NULL;
+
+ ret = of_property_read_u32_array(child, "adc-max",
+ &pdata->adc_conditions[i].max_adc, 0);
+ if (ret)
+ return NULL;
+
+ i++;
+ }
+
+ return pdata;
+}
+
static int adc_jack_probe(struct platform_device *pdev)
{
struct adc_jack_data *data;
struct adc_jack_pdata *pdata = dev_get_platdata(&pdev->dev);
int i, err = 0;

+ if (!pdata) {
+ pdata = get_pdata_from_dt(&pdev->dev);
+ if (!pdata)
+ return -EINVAL;
+ }
+
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -188,11 +255,18 @@ static int adc_jack_remove(struct platform_device *pdev)
return 0;
}

+static struct of_device_id of_adc_jack_match_tbl[] = {
+ { .compatible = "extcon-adc-jack", },
+ { /* end */ },
+};
+
+
static struct platform_driver adc_jack_driver = {
.probe = adc_jack_probe,
.remove = adc_jack_remove,
.driver = {
.name = "adc-jack",
+ .of_match_table = of_adc_jack_match_tbl,
.owner = THIS_MODULE,
},
};
--
1.7.9.5

2014-04-10 13:21:18

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 12/13] extcon: extcon-max8997: check if pdata exists

This patch adds check if pdata is NULL, to avoid NULL pointer dereference
when platform data is not available. After this changes, in described
situation driver will be configured with default values.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-max8997.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index c071588..d7d12e9 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -726,7 +726,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
goto err_irq;
}

- if (pdata->muic_pdata) {
+ if (pdata && pdata->muic_pdata) {
struct max8997_muic_platform_data *muic_pdata
= pdata->muic_pdata;

--
1.7.9.5

2014-04-10 13:21:34

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 13/13] extcon: extcon-max77693: check if pdata exists

This patch adds check if pdata is NULL, to avoid NULL pointer dereference
when platform data is not available. After this changes, in described
situation driver will be configured with default values.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-max77693.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 2cd8892..fa8534e 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -1210,7 +1210,7 @@ static int max77693_muic_probe(struct platform_device *pdev)


/* Initialize MUIC register by using platform data or default data */
- if (pdata->muic_data) {
+ if (pdata && pdata->muic_data) {
init_data = pdata->muic_data->init_data;
num_init_data = pdata->muic_data->num_init_data;
} else {
--
1.7.9.5

2014-04-10 13:18:52

by Robert Baldyga

[permalink] [raw]
Subject: [PATCH 05/13] extcon: extcon-class: improve extcon client API

This patch improves extcon client API to get rid of ugly functions operating
on name strings. It gives independency from naming convention in extcon
provider drivers. Names given at provider registration are now used only
for sysfs, debugs, and to support platforms using legacy devicetree bindings.

>From now individual cables are specified in devicetree, so client API has
changed from extcon_dev oriented to extcon_cable oriented. Added also some
minor modifications to simplify interest registration.

The extcon_specific_cable_nb structure has been changed to extcon_cable_nb.
Now this is the only struct which has to be supplied by client. Pointer to
user_nb has been changed to extcon_notifier_fn_t to simplify interest
registation process.

Each single cable is represented by struct extcon_cable. Pointer to
extcon_cable is returned from functions:

of_extcon_get_cable() - returning cable of given index

of_extcon_get_cable_by_name() - returing cable by name defined in devicetree

extcon_get_cable_by_name() - similar to of_extcon_get_cable_by_name(),
but it takes struct device instead of struct device_node

Function extcon_register_interest() has been changed. Registration is now
not based on cable name string, but on pointer to struct extcon_cable.

Also extcon_get_cable_state() function has been changed. Now it takes
pointer to struct extcon_cable.

This patch modifies all client drivers to make it using new extcon API.

Signed-off-by: Robert Baldyga <[email protected]>
---
drivers/extcon/extcon-class.c | 201 +++++++++++++++++++++----------
drivers/power/charger-manager.c | 36 +++---
drivers/usb/dwc3/dwc3-omap.c | 68 ++++++-----
drivers/usb/phy/phy-omap-otg.c | 72 ++++++-----
include/linux/extcon.h | 92 ++++++++------
include/linux/platform_data/usb-omap1.h | 2 -
include/linux/power/charger-manager.h | 6 +-
7 files changed, 288 insertions(+), 189 deletions(-)

diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 1075ce8..708b352 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -324,15 +324,14 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state_);

/**
* extcon_get_cable_state() - Get the status of a specific cable.
- * @edev: the extcon device that has the cable.
- * @cable_name: cable name.
- *
- * Note that this is slower than extcon_get_cable_state_.
+ * @cable: the cable.
*/
-int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
+int extcon_get_cable_state(struct extcon_cable *cable)
{
- return extcon_get_cable_state_(edev, extcon_find_cable_index
- (edev, cable_name));
+ if (!cable)
+ return -ENODEV;
+
+ return !!(cable->edev->state & (1 << cable->cable_index));
}
EXPORT_SYMBOL_GPL(extcon_get_cable_state);

@@ -376,24 +375,130 @@ out:
return edev;
}

+/**
+ * of_extcon_get_cable() - Get specified extcon cable instance from devicetree
+ * @np: The node of extcon device
+ */
+struct extcon_cable *of_extcon_get_cable(struct device_node *np, int index)
+{
+ struct of_phandle_args extcon_spec;
+ struct extcon_dev *edev;
+ struct extcon_cable *cable;
+ int ret;
+
+ if (index < 0)
+ return ERR_PTR(-EINVAL);
+
+ ret = of_parse_phandle_with_args(np, "extcon-cables", "#extcon-cells",
+ index, &extcon_spec);
+ if (ret)
+ return ERR_PTR(ret);
+
+ edev = of_extcon_get_extcon_dev(extcon_spec.np);
+ if (!edev) {
+ pr_devel("unable to get extcon device");
+ return ERR_PTR(-ENODEV);
+ }
+
+ cable = &edev->cables[extcon_spec.args[0]];
+
+ of_node_put(extcon_spec.np);
+ return cable;
+}
+EXPORT_SYMBOL_GPL(of_extcon_get_cable);
+
+struct extcon_cable *of_extcon_get_cable_legacy(struct device_node *np,
+ const char *name)
+{
+ struct device_node *node;
+ struct extcon_dev *edev;
+ int i;
+
+ node = of_parse_phandle(np, "extcon", 0);
+ if (!node)
+ return ERR_PTR(-EINVAL);
+ edev = of_extcon_get_extcon_dev(node);
+ if (!edev)
+ return ERR_PTR(-ENODEV);
+
+ if (!edev->supported_cable)
+ return ERR_PTR(-EINVAL);
+
+ for (i = 0; edev->supported_cable[i]; ++i) {
+ if (!strncmp(edev->supported_cable[i], name, CABLE_NAME_MAX))
+ return &edev->cables[i];
+ }
+ return ERR_PTR(-ENODEV);
+}
+
+/*
+ * of_extcon_get_cable_by_name() - Get extcon cable from devicetree by name
+ * @np - devicetree node of client device
+ * @name - name of the cable specified in devicetree
+ *
+ * return the instance of extcon cable
+ */
+struct extcon_cable *of_extcon_get_cable_by_name(struct device_node *np,
+ const char *name)
+{
+ struct extcon_cable *cable;
+ int index = 0;
+
+ if (!np)
+ return ERR_PTR(-EINVAL);
+
+ if (!of_property_read_bool(np, "extcon-cables")) {
+ if (!of_property_read_bool(np, "extcon")) {
+ return of_extcon_get_cable_legacy(np, name);
+ } else {
+ pr_devel("device node has not extcon entry\n");
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
+ if (name)
+ index = of_property_match_string(np, "extcon-names", name);
+ cable = of_extcon_get_cable(np, index);
+ if (IS_ERR(cable)) {
+ pr_devel("unable to find cable\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ return cable;
+}
+EXPORT_SYMBOL_GPL(of_extcon_get_cable_by_name);
+
+/*
+ * of_extcon_get_cable_by_name() - Get extcon cable from devicetree by name
+ * @np - devicetree node of client device
+ * @name - name of the cable specified in devicetree
+ *
+ * return the instance of extcon cable
+ */
+struct extcon_cable *extcon_get_cable_by_name(struct device *dev,
+ const char *name)
+{
+ return of_extcon_get_cable_by_name(dev->of_node, name);
+}
+EXPORT_SYMBOL_GPL(extcon_get_cable_by_name);
+
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_cable_nb *obj = container_of(nb,
+ struct extcon_cable_nb, internal_nb);
struct extcon_dev *edev = ptr;

- if ((val & (1 << obj->cable_index)) !=
- (edev->state & (1 << obj->cable_index))) {
+ if ((val & (1 << obj->cable->cable_index)) !=
+ (edev->state & (1 << obj->cable->cable_index))) {
bool cable_state = true;

obj->previous_value = val;

- if (val & (1 << obj->cable_index))
+ if (val & (1 << obj->cable->cable_index))
cable_state = false;

- return obj->user_nb->notifier_call(obj->user_nb,
- cable_state, ptr);
+ return obj->notifier_function(obj, cable_state);
}

return NOTIFY_OK;
@@ -403,14 +508,11 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
* extcon_register_interest() - Register a notifier for a state change of a
* specific cable, not an entier set of cables of a
* extcon device.
- * @obj: an empty extcon_specific_cable_nb object to be returned.
- * @extcon_name: the name of extcon device.
- * if NULL, extcon_register_interest will register
- * every cable with the target cable_name given.
- * @cable_name: the target cable name.
+ * @obj: an empty extcon_cable_nb object to be returned.
+ * @cable: the target cable.
* @nb: the notifier block to get notified.
*
- * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
+ * Provide an empty extcon_cable_nb. extcon_register_interest() sets
* the struct for you.
*
* extcon_register_interest is a helper function for those who want to get
@@ -422,65 +524,38 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
* "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_interest(struct extcon_specific_cable_nb *obj,
- const char *extcon_name, const char *cable_name,
- struct notifier_block *nb)
+int extcon_register_interest(struct extcon_cable_nb *obj,
+ struct extcon_cable *cable,
+ extcon_notifier_fn_t notifier_function)
{
- if (!obj || !cable_name || !nb)
+ if (!obj || !cable || !notifier_function)
return -EINVAL;

- if (extcon_name) {
- obj->edev = extcon_get_extcon_dev(extcon_name);
- if (!obj->edev)
- return -ENODEV;
-
- obj->cable_index = extcon_find_cable_index(obj->edev,
- cable_name);
- if (obj->cable_index < 0)
- return obj->cable_index;
+ obj->cable = cable;

- obj->user_nb = nb;
+ obj->internal_nb.notifier_call = _call_per_cable;
+ obj->notifier_function = notifier_function;

- obj->internal_nb.notifier_call = _call_per_cable;
-
- return raw_notifier_chain_register(&obj->edev->nh,
- &obj->internal_nb);
- } else {
- struct class_dev_iter iter;
- struct extcon_dev *extd;
- struct device *dev;
-
- if (!extcon_class)
- return -ENODEV;
- class_dev_iter_init(&iter, extcon_class, NULL, NULL);
- while ((dev = class_dev_iter_next(&iter))) {
- extd = dev_get_drvdata(dev);
-
- if (extcon_find_cable_index(extd, cable_name) < 0)
- continue;
-
- class_dev_iter_exit(&iter);
- return extcon_register_interest(obj, extd->name,
- cable_name, nb);
- }
-
- return -ENODEV;
- }
+ return raw_notifier_chain_register(&cable->edev->nh,
+ &obj->internal_nb);
}
EXPORT_SYMBOL_GPL(extcon_register_interest);

/**
* extcon_unregister_interest() - Unregister the notifier registered by
* extcon_register_interest().
- * @obj: the extcon_specific_cable_nb object returned by
+ * @obj: the extcon_cable_nb object returned by
* extcon_register_interest().
*/
-int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
+int extcon_unregister_interest(struct extcon_cable_nb *obj)
{
if (!obj)
return -EINVAL;

- return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
+ obj->cable = NULL;
+
+ return raw_notifier_chain_unregister(&obj->cable->edev->nh,
+ &obj->internal_nb);
}
EXPORT_SYMBOL_GPL(extcon_unregister_interest);

@@ -572,7 +647,7 @@ int extcon_dev_register(struct extcon_dev *edev)
;
edev->max_supported = index;
} else {
- edev->max_supported = 0;
+ return -EINVAL;
}

if (index > SUPPORTED_CABLE_MAX) {
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 9e4dab4..29876ed 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1181,8 +1181,8 @@ static void charger_extcon_work(struct work_struct *work)
ret = regulator_set_current_limit(cable->charger->consumer,
cable->min_uA, cable->max_uA);
if (ret < 0) {
- pr_err("Cannot set current limit of %s (%s)\n",
- cable->charger->regulator_name, cable->name);
+ pr_err("Cannot set current limit of %s\n",
+ cable->charger->regulator_name);
return;
}

@@ -1202,17 +1202,17 @@ static void charger_extcon_work(struct work_struct *work)
* @event: the cable state.
* @ptr: the data pointer of notifier block.
*/
-static int charger_extcon_notifier(struct notifier_block *self,
- unsigned long event, void *ptr)
+static int charger_extcon_notifier(struct extcon_cable_nb *cable_nb,
+ bool state)
{
struct charger_cable *cable =
- container_of(self, struct charger_cable, nb);
+ container_of(cable_nb, struct charger_cable, cable_nb);

/*
* The newly state of charger cable.
* If cable is attached, cable->attached is true.
*/
- cable->attached = event;
+ cable->attached = state;

/*
* Setup monitoring to check battery state
@@ -1242,6 +1242,7 @@ static int charger_extcon_notifier(struct notifier_block *self,
static int charger_extcon_init(struct charger_manager *cm,
struct charger_cable *cable)
{
+ struct extcon_cable *ecable = cable->cable;
int ret = 0;

/*
@@ -1250,12 +1251,12 @@ static int charger_extcon_init(struct charger_manager *cm,
* cable (e.g., TA, USB, MHL, Dock).
*/
INIT_WORK(&cable->wq, charger_extcon_work);
- cable->nb.notifier_call = charger_extcon_notifier;
- ret = extcon_register_interest(&cable->extcon_dev,
- cable->extcon_name, cable->name, &cable->nb);
+
+ ret = extcon_register_interest(&cable->cable_nb,
+ ecable, charger_extcon_notifier);
if (ret < 0) {
- pr_info("Cannot register extcon_dev for %s(cable: %s)\n",
- cable->extcon_name, cable->name);
+ pr_info("Cannot register extcon_dev for %s(cable: %d)\n",
+ ecable->edev->name, ecable->cable_index);
ret = -EINVAL;
}

@@ -1632,11 +1633,8 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
chg_regs->cables = cables;

for_each_child_of_node(child, _child) {
- of_property_read_string(_child,
- "cm-cable-name", &cables->name);
- of_property_read_string(_child,
- "cm-cable-extcon",
- &cables->extcon_name);
+ cables->cable =
+ of_extcon_get_cable(_child, 0);
of_property_read_u32(_child,
"cm-cable-min",
&cables->min_uA);
@@ -1859,8 +1857,8 @@ err_reg_extcon:
for (j = 0; j < charger->num_cables; j++) {
struct charger_cable *cable = &charger->cables[j];
/* Remove notifier block if only edev exists */
- if (cable->extcon_dev.edev)
- extcon_unregister_interest(&cable->extcon_dev);
+ if (cable->cable_nb.cable)
+ extcon_unregister_interest(&cable->cable_nb);
}

regulator_put(desc->charger_regulators[i].consumer);
@@ -1891,7 +1889,7 @@ static int charger_manager_remove(struct platform_device *pdev)
= &desc->charger_regulators[i];
for (j = 0 ; j < charger->num_cables ; j++) {
struct charger_cable *cable = &charger->cables[j];
- extcon_unregister_interest(&cable->extcon_dev);
+ extcon_unregister_interest(&cable->cable_nb);
}
}

diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index b1d7ee6..73725f4 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -133,10 +133,8 @@ struct dwc3_omap {

u32 dma_status:1;

- struct extcon_specific_cable_nb extcon_vbus_dev;
- struct extcon_specific_cable_nb extcon_id_dev;
- struct notifier_block vbus_nb;
- struct notifier_block id_nb;
+ struct extcon_cable_nb vbus_nb;
+ struct extcon_cable_nb id_nb;

struct regulator *vbus_reg;
};
@@ -357,12 +355,13 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)

static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);

-static int dwc3_omap_id_notifier(struct notifier_block *nb,
- unsigned long event, void *ptr)
+static int dwc3_omap_id_notifier(struct extcon_cable_nb *cable_nb,
+ bool state)
{
- struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, id_nb);
+ struct dwc3_omap *omap = container_of(cable_nb,
+ struct dwc3_omap, id_nb);

- if (event)
+ if (state)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
else
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
@@ -370,12 +369,13 @@ static int dwc3_omap_id_notifier(struct notifier_block *nb,
return NOTIFY_DONE;
}

-static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
- unsigned long event, void *ptr)
+static int dwc3_omap_vbus_notifier(struct extcon_cable_nb *cable_nb,
+ bool state)
{
- struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, vbus_nb);
+ struct dwc3_omap *omap = container_of(cable_nb,
+ struct dwc3_omap, vbus_nb);

- if (event)
+ if (state)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
else
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
@@ -390,9 +390,10 @@ static int dwc3_omap_probe(struct platform_device *pdev)
struct dwc3_omap *omap;
struct resource *res;
struct device *dev = &pdev->dev;
- struct extcon_dev *edev;
struct regulator *vbus_reg = NULL;

+ struct extcon_cable *cable_vbus, *cable_id;
+
int ret = -ENOMEM;
int irq;

@@ -520,29 +521,30 @@ static int dwc3_omap_probe(struct platform_device *pdev)

dwc3_omap_enable_irqs(omap);

- if (of_property_read_bool(node, "extcon")) {
- edev = extcon_get_edev_by_phandle(dev, 0);
- if (IS_ERR(edev)) {
- dev_vdbg(dev, "couldn't get extcon device\n");
+ if (of_property_read_bool(node, "extcon") ||
+ of_property_read_bool(node, "extcon-cable")) {
+ cable_vbus = extcon_get_cable_by_name(dev, "USB");
+ if (IS_ERR(cable_vbus)) {
+ dev_vdbg(dev, "couldn't get extcon cable USB\n");
ret = -EPROBE_DEFER;
goto err2;
}

- omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
- ret = extcon_register_interest(&omap->extcon_vbus_dev,
- edev->name, "USB", &omap->vbus_nb);
+ ret = extcon_register_interest(&omap->vbus_nb,
+ cable_vbus, dwc3_omap_vbus_notifier);
if (ret < 0)
dev_vdbg(dev, "failed to register notifier for USB\n");
- omap->id_nb.notifier_call = dwc3_omap_id_notifier;
- ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
- "USB-HOST", &omap->id_nb);
+
+ cable_id = extcon_get_cable_by_name(dev, "USB-HOST");
+ ret = extcon_register_interest(&omap->id_nb,
+ cable_id, dwc3_omap_id_notifier);
if (ret < 0)
dev_vdbg(dev,
"failed to register notifier for USB-HOST\n");

- if (extcon_get_cable_state(edev, "USB") == true)
+ if (extcon_get_cable_state(cable_vbus) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
- if (extcon_get_cable_state(edev, "USB-HOST") == true)
+ if (extcon_get_cable_state(cable_id) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
}

@@ -555,10 +557,10 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return 0;

err3:
- if (omap->extcon_vbus_dev.edev)
- extcon_unregister_interest(&omap->extcon_vbus_dev);
- if (omap->extcon_id_dev.edev)
- extcon_unregister_interest(&omap->extcon_id_dev);
+ if (omap->vbus_nb.cable)
+ extcon_unregister_interest(&omap->vbus_nb);
+ if (omap->id_nb.cable)
+ extcon_unregister_interest(&omap->id_nb);

err2:
dwc3_omap_disable_irqs(omap);
@@ -576,10 +578,10 @@ static int dwc3_omap_remove(struct platform_device *pdev)
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);

- if (omap->extcon_vbus_dev.edev)
- extcon_unregister_interest(&omap->extcon_vbus_dev);
- if (omap->extcon_id_dev.edev)
- extcon_unregister_interest(&omap->extcon_id_dev);
+ if (omap->vbus_nb.cable)
+ extcon_unregister_interest(&omap->vbus_nb);
+ if (omap->id_nb.cable)
+ extcon_unregister_interest(&omap->id_nb);
dwc3_omap_disable_irqs(omap);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c
index 11598cd..976a358 100644
--- a/drivers/usb/phy/phy-omap-otg.c
+++ b/drivers/usb/phy/phy-omap-otg.c
@@ -30,10 +30,8 @@ struct otg_device {
void __iomem *base;
bool id;
bool vbus;
- struct extcon_specific_cable_nb vbus_dev;
- struct extcon_specific_cable_nb id_dev;
- struct notifier_block vbus_nb;
- struct notifier_block id_nb;
+ struct extcon_cable_nb vbus_nb;
+ struct extcon_cable_nb id_nb;
};

#define OMAP_OTG_CTRL 0x0c
@@ -69,10 +67,11 @@ static void omap_otg_set_mode(struct otg_device *otg_dev)
omap_otg_ctrl(otg_dev, OMAP_OTG_ID | OMAP_OTG_BSESSEND);
}

-static int omap_otg_id_notifier(struct notifier_block *nb,
- unsigned long event, void *ptr)
+static int omap_otg_id_notifier(struct extcon_cable_nb *cable_nb,
+ bool state)
{
- struct otg_device *otg_dev = container_of(nb, struct otg_device, id_nb);
+ struct otg_device *otg_dev = container_of(cable_nb,
+ struct otg_device, id_nb);

otg_dev->id = event;
omap_otg_set_mode(otg_dev);
@@ -80,13 +79,13 @@ static int omap_otg_id_notifier(struct notifier_block *nb,
return NOTIFY_DONE;
}

-static int omap_otg_vbus_notifier(struct notifier_block *nb,
- unsigned long event, void *ptr)
+static int omap_otg_vbus_notifier(struct extcon_cable_nb *cable_nb,
+ bool state)
{
- struct otg_device *otg_dev = container_of(nb, struct otg_device,
- vbus_nb);
+ struct otg_device *otg_dev = container_of(cable_nb,
+ struct otg_device, vbus_nb);

- otg_dev->vbus = event;
+ otg_dev->vbus = state;
omap_otg_set_mode(otg_dev);

return NOTIFY_DONE;
@@ -96,17 +95,13 @@ static int omap_otg_probe(struct platform_device *pdev)
{
const struct omap_usb_config *config = pdev->dev.platform_data;
struct otg_device *otg_dev;
- struct extcon_dev *extcon;
+ struct extcon_cable *cable_vbus, *cable_id;
int ret;
u32 rev;

- if (!config || !config->extcon)
+ if (!config)
return -ENODEV;

- extcon = extcon_get_extcon_dev(config->extcon);
- if (!extcon)
- return -EPROBE_DEFER;
-
otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
if (!otg_dev)
return -ENOMEM;
@@ -115,41 +110,52 @@ static int omap_otg_probe(struct platform_device *pdev)
if (IS_ERR(otg_dev->base))
return PTR_ERR(otg_dev->base);

- otg_dev->id_nb.notifier_call = omap_otg_id_notifier;
- otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier;
-
- ret = extcon_register_interest(&otg_dev->id_dev, config->extcon,
- "USB-HOST", &otg_dev->id_nb);
+ cable_id = extcon_get_cable_by_name(&pdev->dev, "USB-HOST");
+ if (IS_ERR(cable_id)) {
+ dev_vdbg(&pdev->dev, "couldn't get extcon cable USB-HOST\n");
+ return PTR_ERR(cable_id);
+ }
+ ret = extcon_register_interest(&otg_dev->id_nb,
+ cable_id, omap_otg_id_notifier);
if (ret)
return ret;

- ret = extcon_register_interest(&otg_dev->vbus_dev, config->extcon,
- "USB", &otg_dev->vbus_nb);
+ cable_vbus = extcon_get_cable_by_name(&pdev->dev, "USB");
+ if (IS_ERR(cable_vbus)) {
+ dev_vdbg(&pdev->dev, "couldn't get extcon cable USB\n");
+ ret = PTR_ERR(cable_vbus);
+ goto err;
+ }
+ ret = extcon_register_interest(&otg_dev->vbus_nb,
+ cable_vbus, omap_otg_vbus_notifier);
if (ret) {
- extcon_unregister_interest(&otg_dev->id_dev);
- return ret;
+ goto err;
}

- otg_dev->id = extcon_get_cable_state(extcon, "USB-HOST");
- otg_dev->vbus = extcon_get_cable_state(extcon, "USB");
+ otg_dev->id = extcon_get_cable_state(cable_id);
+ otg_dev->vbus = extcon_get_cable_state(cable_vbus);
omap_otg_set_mode(otg_dev);

rev = readl(otg_dev->base);

dev_info(&pdev->dev,
- "OMAP USB OTG controller rev %d.%d (%s, id=%d, vbus=%d)\n",
- (rev >> 4) & 0xf, rev & 0xf, config->extcon, otg_dev->id,
+ "OMAP USB OTG controller rev %d.%d (id=%d, vbus=%d)\n",
+ (rev >> 4) & 0xf, rev & 0xf, otg_dev->id,
otg_dev->vbus);

return 0;
+
+err:
+ extcon_unregister_interest(&otg_dev->id_nb);
+ return ret;
}

static int omap_otg_remove(struct platform_device *pdev)
{
struct otg_device *otg_dev = platform_get_drvdata(pdev);

- extcon_unregister_interest(&otg_dev->id_dev);
- extcon_unregister_interest(&otg_dev->vbus_dev);
+ extcon_unregister_interest(&otg_dev->id_nb);
+ extcon_unregister_interest(&otg_dev->vbus_nb);

return 0;
}
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index d0fd810..a571cad 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -1,6 +1,7 @@
/*
* External connector (extcon) class driver
*
+ *
* Copyright (C) 2012 Samsung Electronics
* Author: Donggeun Kim <[email protected]>
* Author: MyungJoo Ham <[email protected]>
@@ -79,6 +80,7 @@ struct extcon_cable;
* @name: The name of this extcon device. Parent device name is
* @node: Devicetree node of parent device.
* used if NULL.
+ * @node: Devicetree node of parent device.
* @supported_cable: Array of supported cable names ending with NULL.
* If supported_cable is NULL, cable name related APIs
* are disabled.
@@ -160,23 +162,24 @@ struct extcon_cable {
struct attribute *attrs[3]; /* to be fed to attr_g.attrs */
};

+struct extcon_cable_nb;
+
+typedef int (*extcon_notifier_fn_t)(struct extcon_cable_nb *cable_nb,
+ bool cable_state);
+
/**
- * struct extcon_specific_cable_nb - An internal data for
- * extcon_register_interest().
+ * struct extcon_cable_nb - An internal data for extcon_register_interest().
* @internal_nb: A notifier block bridging extcon notifier
* and cable notifier.
- * @user_nb: user provided notifier block for events from
- * a specific cable.
- * @cable_index: the target cable.
- * @edev: the target extcon device.
- * @previous_value: the saved previous event value.
+ * @user_nb: Notifier block for events from a specific cable, used
+ * to handle user provided callback function.
+ * @cable: The target cable.
*/
-struct extcon_specific_cable_nb {
+struct extcon_cable_nb {
struct notifier_block internal_nb;
- struct notifier_block *user_nb;
- int cable_index;
- struct extcon_dev *edev;
unsigned long previous_value;
+ extcon_notifier_fn_t notifier_function;
+ struct extcon_cable *cable;
};

#if IS_ENABLED(CONFIG_EXTCON)
@@ -205,16 +208,13 @@ extern int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state);
/*
* get/set_cable_state access each bit of the 32b encoded state value.
* They are used to access the status of each cable based on the cable_name
- * or cable_index, which is retrieved by extcon_find_cable_index
+tt or cable_index, which is retrieved by extcon_find_cable_index
*/
extern int extcon_find_cable_index(struct extcon_dev *sdev,
const char *cable_name);
extern int extcon_get_cable_state_(struct extcon_dev *edev, int cable_index);
-extern int extcon_set_cable_state_(struct extcon_dev *edev, int cable_index,
- bool cable_state);
-
-extern int extcon_get_cable_state(struct extcon_dev *edev,
- const char *cable_name);
+extern int extcon_set_cable_state_(struct extcon_dev *edev,
+ int cable_index, bool cable_state);

/*
* Following APIs are for notifiees (those who want to be notified)
@@ -222,11 +222,23 @@ extern int extcon_get_cable_state(struct extcon_dev *edev,
* Notifiees are the connected device drivers wanting to get notified by
* a specific external port of a connection device.
*/
-extern int extcon_register_interest(struct extcon_specific_cable_nb *obj,
- const char *extcon_name,
- const char *cable_name,
- struct notifier_block *nb);
-extern int extcon_unregister_interest(struct extcon_specific_cable_nb *nb);
+
+extern struct extcon_cable *
+of_extcon_get_cable(struct device_node *np, int index);
+
+extern struct extcon_cable *
+of_extcon_get_cable_by_name(struct device_node *np, const char *name);
+
+extern struct extcon_cable *
+extcon_get_cable_by_name(struct device *dev, const char *name);
+
+extern int extcon_register_interest(struct extcon_cable_nb *obj,
+ struct extcon_cable *cable,
+ extcon_notifier_fn_t notifier_function);
+
+extern int extcon_unregister_interest(struct extcon_cable_nb *nb);
+
+extern int extcon_get_cable_state(struct extcon_cable *cable);

/*
* Following APIs are to monitor every action of a notifier.
@@ -281,14 +293,7 @@ static inline int extcon_get_cable_state_(struct extcon_dev *edev,
return 0;
}

-static inline int extcon_get_cable_state(struct extcon_dev *edev,
- const char *cable_name)
-{
- return 0;
-}
-
-static inline int extcon_set_cable_state(struct extcon_dev *edev,
- const char *cable_name, int state)
+static inline int extcon_get_cable_state(struct extcon_cable *cable)
{
return 0;
}
@@ -305,15 +310,32 @@ static inline int extcon_unregister_notifier(struct extcon_dev *edev,
return 0;
}

-static inline int extcon_register_interest(struct extcon_specific_cable_nb *obj,
- const char *extcon_name,
- const char *cable_name,
- struct notifier_block *nb)
+static inline struct extcon_cable *
+of_extcon_get_cable(struct device_node *np, int index)
+{
+ return NULL;
+}
+
+static inline struct extcon_cable *
+of_extcon_get_cable_by_name(struct device_node *np, const char *name)
+{
+ return NULL;
+}
+
+static inline struct extcon_cable *
+extcon_get_cable_by_name(struct device *dev, const char *name)
+{
+ return NULL;
+}
+
+static inline int extcon_register_interest(struct extcon_cable_nb *obj,
+ struct extcon_cable *cable,
+ extcon_notifier_fn_t notifier_function)
{
return 0;
}

-static inline int extcon_unregister_interest(struct extcon_specific_cable_nb
+static inline int extcon_unregister_interest(struct extcon_cable_nb
*obj)
{
return 0;
diff --git a/include/linux/platform_data/usb-omap1.h b/include/linux/platform_data/usb-omap1.h
index 43b5ce1..8c7764d 100644
--- a/include/linux/platform_data/usb-omap1.h
+++ b/include/linux/platform_data/usb-omap1.h
@@ -23,8 +23,6 @@ struct omap_usb_config {
unsigned register_dev:1;
u8 otg; /* port number, 1-based: usb1 == 2 */

- const char *extcon; /* extcon device for OTG */
-
u8 hmc_mode;

/* implicitly true if otg: host supports remote wakeup? */
diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h
index 07e7945..28e7a4b 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -84,13 +84,11 @@ struct charger_global_desc {
* @cm: the Charger Manager representing the battery.
*/
struct charger_cable {
- const char *extcon_name;
- const char *name;
+ struct extcon_cable *cable;

/* The charger-manager use Exton framework*/
- struct extcon_specific_cable_nb extcon_dev;
+ struct extcon_cable_nb cable_nb;
struct work_struct wq;
- struct notifier_block nb;

/* The state of charger cable */
bool attached;
--
1.7.9.5

2014-04-10 18:13:27

by Aaro Koskinen

[permalink] [raw]
Subject: Re: [PATCH 05/13] extcon: extcon-class: improve extcon client API

Hi,

On Thu, Apr 10, 2014 at 03:16:43PM +0200, Robert Baldyga wrote:
> +struct extcon_cable *extcon_get_cable_by_name(struct device *dev,
> + const char *name)
> +{
> + return of_extcon_get_cable_by_name(dev->of_node, name);
> +}
> +EXPORT_SYMBOL_GPL(extcon_get_cable_by_name);

[...]

> @@ -96,17 +95,13 @@ static int omap_otg_probe(struct platform_device *pdev)
> {
> const struct omap_usb_config *config = pdev->dev.platform_data;
^^^^^^^^^^^^^

[...]

> - ret = extcon_register_interest(&otg_dev->id_dev, config->extcon,
> - "USB-HOST", &otg_dev->id_nb);
> + cable_id = extcon_get_cable_by_name(&pdev->dev, "USB-HOST");

NACK. OMAP1 is not using DT, so this driver would stop working
with this series.

A.