Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Documentation: extcon: add documentation for Extcon subsystem

The Extcon (External Connector) subsystem driver lacked proper
documentation. This commit adds comprehensive documentation
explaining the purpose, key components, and usage of the Extcon
framework.

The new documentation includes:
- An overview of the Extcon subsystem
- Descriptions of key structures
- Explanations of core functions
- Information on the sysfs interface
- A usage example for driver developers

Link: https://lore.kernel.org/lkml/20241103025436.69196-1-yesanishhere@gmail.com/
Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: anish kumar <yesanishhere@gmail.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>

authored by

anish kumar and committed by
Chanwoo Choi
68c84483 91329cb0

+257
+255
Documentation/driver-api/extcon.rst
··· 1 + ======================= 2 + Extcon Device Subsystem 3 + ======================= 4 + 5 + Overview 6 + ======== 7 + 8 + The Extcon (External Connector) subsystem provides a unified framework for 9 + managing external connectors in Linux systems. It allows drivers to report 10 + the state of external connectors and provides a standardized interface for 11 + userspace to query and monitor these states. 12 + 13 + Extcon is particularly useful in modern devices with multiple connectivity 14 + options, such as smartphones, tablets, and laptops. It helps manage various 15 + types of connectors, including: 16 + 17 + 1. USB connectors (e.g., USB-C, micro-USB) 18 + 2. Charging ports (e.g., fast charging, wireless charging) 19 + 3. Audio jacks (e.g., 3.5mm headphone jack) 20 + 4. Video outputs (e.g., HDMI, DisplayPort) 21 + 5. Docking stations 22 + 23 + Real-world examples: 24 + 25 + 1. Smartphone USB-C port: 26 + A single USB-C port on a smartphone can serve multiple functions. Extcon 27 + can manage the different states of this port, such as: 28 + - USB data connection 29 + - Charging (various types like fast charging, USB Power Delivery) 30 + - Audio output (USB-C headphones) 31 + - Video output (USB-C to HDMI adapter) 32 + 33 + 2. Laptop docking station: 34 + When a laptop is connected to a docking station, multiple connections are 35 + made simultaneously. Extcon can handle the state changes for: 36 + - Power delivery 37 + - External displays 38 + - USB hub connections 39 + - Ethernet connectivity 40 + 41 + 3. Wireless charging pad: 42 + Extcon can manage the state of a wireless charging connection, allowing 43 + the system to respond appropriately when a device is placed on or removed 44 + from the charging pad. 45 + 46 + 4. Smart TV HDMI ports: 47 + In a smart TV, Extcon can manage multiple HDMI ports, detecting when 48 + devices are connected or disconnected, and potentially identifying the 49 + type of device (e.g., gaming console, set-top box, Blu-ray player). 50 + 51 + The Extcon framework simplifies the development of drivers for these complex 52 + scenarios by providing a standardized way to report and query connector 53 + states, handle mutually exclusive connections, and manage connector 54 + properties. This allows for more robust and flexible handling of external 55 + connections in modern devices. 56 + 57 + Key Components 58 + ============== 59 + 60 + extcon_dev 61 + ---------- 62 + 63 + The core structure representing an Extcon device:: 64 + 65 + struct extcon_dev { 66 + const char *name; 67 + const unsigned int *supported_cable; 68 + const u32 *mutually_exclusive; 69 + 70 + /* Internal data */ 71 + struct device dev; 72 + unsigned int id; 73 + struct raw_notifier_head nh_all; 74 + struct raw_notifier_head *nh; 75 + struct list_head entry; 76 + int max_supported; 77 + spinlock_t lock; 78 + u32 state; 79 + 80 + /* Sysfs related */ 81 + struct device_type extcon_dev_type; 82 + struct extcon_cable *cables; 83 + struct attribute_group attr_g_muex; 84 + struct attribute **attrs_muex; 85 + struct device_attribute *d_attrs_muex; 86 + }; 87 + 88 + Key fields: 89 + 90 + - ``name``: Name of the Extcon device 91 + - ``supported_cable``: Array of supported cable types 92 + - ``mutually_exclusive``: Array defining mutually exclusive cable types 93 + This field is crucial for enforcing hardware constraints. It's an array of 94 + 32-bit unsigned integers, where each element represents a set of mutually 95 + exclusive cable types. The array should be terminated with a 0. 96 + 97 + For example: 98 + 99 + :: 100 + 101 + static const u32 mutually_exclusive[] = { 102 + BIT(0) | BIT(1), /* Cable 0 and 1 are mutually exclusive */ 103 + BIT(2) | BIT(3) | BIT(4), /* Cables 2, 3, and 4 are mutually exclusive */ 104 + 0 /* Terminator */ 105 + }; 106 + 107 + In this example, cables 0 and 1 cannot be connected simultaneously, and 108 + cables 2, 3, and 4 are also mutually exclusive. This is useful for 109 + scenarios like a single port that can either be USB or HDMI, but not both 110 + at the same time. 111 + 112 + The Extcon core uses this information to prevent invalid combinations of 113 + cable states, ensuring that the reported states are always consistent 114 + with the hardware capabilities. 115 + 116 + - ``state``: Current state of the device (bitmap of connected cables) 117 + 118 + 119 + extcon_cable 120 + ------------ 121 + 122 + Represents an individual cable managed by an Extcon device:: 123 + 124 + struct extcon_cable { 125 + struct extcon_dev *edev; 126 + int cable_index; 127 + struct attribute_group attr_g; 128 + struct device_attribute attr_name; 129 + struct device_attribute attr_state; 130 + struct attribute *attrs[3]; 131 + union extcon_property_value usb_propval[EXTCON_PROP_USB_CNT]; 132 + union extcon_property_value chg_propval[EXTCON_PROP_CHG_CNT]; 133 + union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT]; 134 + union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT]; 135 + DECLARE_BITMAP(usb_bits, EXTCON_PROP_USB_CNT); 136 + DECLARE_BITMAP(chg_bits, EXTCON_PROP_CHG_CNT); 137 + DECLARE_BITMAP(jack_bits, EXTCON_PROP_JACK_CNT); 138 + DECLARE_BITMAP(disp_bits, EXTCON_PROP_DISP_CNT); 139 + }; 140 + 141 + Core Functions 142 + ============== 143 + 144 + .. kernel-doc:: drivers/extcon/extcon.c 145 + :identifiers: extcon_get_state 146 + 147 + .. kernel-doc:: drivers/extcon/extcon.c 148 + :identifiers: extcon_set_state 149 + 150 + .. kernel-doc:: drivers/extcon/extcon.c 151 + :identifiers: extcon_set_state_sync 152 + 153 + .. kernel-doc:: drivers/extcon/extcon.c 154 + :identifiers: extcon_get_property 155 + 156 + 157 + Sysfs Interface 158 + =============== 159 + 160 + Extcon devices expose the following sysfs attributes: 161 + 162 + - ``name``: Name of the Extcon device 163 + - ``state``: Current state of all supported cables 164 + - ``cable.N/name``: Name of the Nth supported cable 165 + - ``cable.N/state``: State of the Nth supported cable 166 + 167 + Usage Example 168 + ------------- 169 + 170 + .. code-block:: c 171 + 172 + #include <linux/module.h> 173 + #include <linux/platform_device.h> 174 + #include <linux/extcon.h> 175 + 176 + struct my_extcon_data { 177 + struct extcon_dev *edev; 178 + struct device *dev; 179 + }; 180 + 181 + static const unsigned int my_extcon_cable[] = { 182 + EXTCON_USB, 183 + EXTCON_USB_HOST, 184 + EXTCON_NONE, 185 + }; 186 + 187 + static int my_extcon_probe(struct platform_device *pdev) 188 + { 189 + struct my_extcon_data *data; 190 + int ret; 191 + 192 + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 193 + if (!data) 194 + return -ENOMEM; 195 + 196 + data->dev = &pdev->dev; 197 + 198 + /* Initialize extcon device */ 199 + data->edev = devm_extcon_dev_allocate(data->dev, my_extcon_cable); 200 + if (IS_ERR(data->edev)) { 201 + dev_err(data->dev, "Failed to allocate extcon device\n"); 202 + return PTR_ERR(data->edev); 203 + } 204 + 205 + /* Register extcon device */ 206 + ret = devm_extcon_dev_register(data->dev, data->edev); 207 + if (ret < 0) { 208 + dev_err(data->dev, "Failed to register extcon device\n"); 209 + return ret; 210 + } 211 + 212 + platform_set_drvdata(pdev, data); 213 + 214 + /* Example: Set initial state */ 215 + extcon_set_state_sync(data->edev, EXTCON_USB, true); 216 + 217 + dev_info(data->dev, "My extcon driver probed successfully\n"); 218 + return 0; 219 + } 220 + 221 + static int my_extcon_remove(struct platform_device *pdev) 222 + { 223 + struct my_extcon_data *data = platform_get_drvdata(pdev); 224 + 225 + /* Example: Clear state before removal */ 226 + extcon_set_state_sync(data->edev, EXTCON_USB, false); 227 + 228 + dev_info(data->dev, "My extcon driver removed\n"); 229 + return 0; 230 + } 231 + 232 + static const struct of_device_id my_extcon_of_match[] = { 233 + { .compatible = "my,extcon-device", }, 234 + { }, 235 + }; 236 + MODULE_DEVICE_TABLE(of, my_extcon_of_match); 237 + 238 + static struct platform_driver my_extcon_driver = { 239 + .driver = { 240 + .name = "my-extcon-driver", 241 + .of_match_table = my_extcon_of_match, 242 + }, 243 + .probe = my_extcon_probe, 244 + .remove = my_extcon_remove, 245 + }; 246 + 247 + module_platform_driver(my_extcon_driver); 248 + 249 + This example demonstrates: 250 + --------------------------- 251 + 252 + - Defining supported cable types (USB and USB Host in this case). 253 + - Allocating and registering an extcon device. 254 + - Setting an initial state for a cable (USB connected in this example). 255 + - Clearing the state when the driver is removed.
+1
Documentation/driver-api/index.rst
··· 86 86 dmaengine/index 87 87 dpll 88 88 edac 89 + extcon 89 90 firmware/index 90 91 fpga/index 91 92 frame-buffer
+1
MAINTAINERS
··· 8635 8635 S: Maintained 8636 8636 T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon.git 8637 8637 F: Documentation/devicetree/bindings/extcon/ 8638 + F: Documentation/driver-api/extcon.rst 8638 8639 F: Documentation/firmware-guide/acpi/extcon-intel-int3496.rst 8639 8640 F: drivers/extcon/ 8640 8641 F: include/linux/extcon.h