Loading Documentation/devicetree/bindings/connector/samsung,usb-connector-11pin.txt 0 → 100644 +49 −0 Original line number Diff line number Diff line Samsung micro-USB 11-pin connector ================================== Samsung micro-USB 11-pin connector is an extension of micro-USB connector. It is present in multiple Samsung mobile devices. It has additional pins to route MHL traffic simultanously with USB. The bindings are superset of usb-connector bindings for micro-USB connector[1]. Required properties: - compatible: must be: "samsung,usb-connector-11pin", "usb-b-connector", - type: must be "micro". Required nodes: - any data bus to the connector should be modeled using the OF graph bindings specified in bindings/graph.txt, unless the bus is between parent node and the connector. Since single connector can have multpile data buses every bus has assigned OF graph port number as follows: 0: High Speed (HS), 3: Mobile High-Definition Link (MHL), specific to 11-pin Samsung micro-USB. [1]: bindings/connector/usb-connector.txt Example ------- Micro-USB connector with HS lines routed via controller (MUIC) and MHL lines connected to HDMI-MHL bridge (sii8620): muic-max77843@66 { ... usb_con: connector { compatible = "samsung,usb-connector-11pin", "usb-b-connector"; label = "micro-USB"; type = "micro"; ports { #address-cells = <1>; #size-cells = <0>; port@3 { reg = <3>; usb_con_mhl: endpoint { remote-endpoint = <&sii8620_mhl>; }; }; }; }; }; Documentation/devicetree/bindings/connector/usb-connector.txt 0 → 100644 +75 −0 Original line number Diff line number Diff line USB Connector ============= USB connector node represents physical USB connector. It should be a child of USB interface controller. Required properties: - compatible: describes type of the connector, must be one of: "usb-a-connector", "usb-b-connector", "usb-c-connector". Optional properties: - label: symbolic name for the connector, - type: size of the connector, should be specified in case of USB-A, USB-B non-fullsize connectors: "mini", "micro". Required nodes: - any data bus to the connector should be modeled using the OF graph bindings specified in bindings/graph.txt, unless the bus is between parent node and the connector. Since single connector can have multpile data buses every bus has assigned OF graph port number as follows: 0: High Speed (HS), present in all connectors, 1: Super Speed (SS), present in SS capable connectors, 2: Sideband use (SBU), present in USB-C. Examples -------- 1. Micro-USB connector with HS lines routed via controller (MUIC): muic-max77843@66 { ... usb_con: connector { compatible = "usb-b-connector"; label = "micro-USB"; type = "micro"; }; }; 2. USB-C connector attached to CC controller (s2mm005), HS lines routed to companion PMIC (max77865), SS lines to USB3 PHY and SBU to DisplayPort. DisplayPort video lines are routed to the connector via SS mux in USB3 PHY. ccic: s2mm005@33 { ... usb_con: connector { compatible = "usb-c-connector"; label = "USB-C"; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; usb_con_hs: endpoint { remote-endpoint = <&max77865_usbc_hs>; }; }; port@1 { reg = <1>; usb_con_ss: endpoint { remote-endpoint = <&usbdrd_phy_ss>; }; }; port@2 { reg = <2>; usb_con_sbu: endpoint { remote-endpoint = <&dp_aux>; }; }; }; }; }; drivers/extcon/extcon.c +34 −10 Original line number Diff line number Diff line Loading @@ -1336,6 +1336,28 @@ void extcon_dev_unregister(struct extcon_dev *edev) EXPORT_SYMBOL_GPL(extcon_dev_unregister); #ifdef CONFIG_OF /* * extcon_find_edev_by_node - Find the extcon device from devicetree. * @node : OF node identifying edev * * Return the pointer of extcon device if success or ERR_PTR(err) if fail. */ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) { struct extcon_dev *edev; mutex_lock(&extcon_dev_list_lock); list_for_each_entry(edev, &extcon_dev_list, entry) if (edev->dev.parent && edev->dev.parent->of_node == node) goto out; edev = ERR_PTR(-EPROBE_DEFER); out: mutex_unlock(&extcon_dev_list_lock); return edev; } /* * extcon_get_edev_by_phandle - Get the extcon device from devicetree. * @dev : the instance to the given device Loading Loading @@ -1363,25 +1385,27 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) return ERR_PTR(-ENODEV); } mutex_lock(&extcon_dev_list_lock); list_for_each_entry(edev, &extcon_dev_list, entry) { if (edev->dev.parent && edev->dev.parent->of_node == node) { mutex_unlock(&extcon_dev_list_lock); edev = extcon_find_edev_by_node(node); of_node_put(node); return edev; } } mutex_unlock(&extcon_dev_list_lock); of_node_put(node); return ERR_PTR(-EPROBE_DEFER); } #else struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) { return ERR_PTR(-ENOSYS); } struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) { return ERR_PTR(-ENOSYS); } #endif /* CONFIG_OF */ EXPORT_SYMBOL_GPL(extcon_find_edev_by_node); EXPORT_SYMBOL_GPL(extcon_get_edev_by_phandle); /** Loading drivers/gpu/drm/bridge/sil-sii8620.c +94 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/extcon.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/interrupt.h> Loading @@ -25,6 +26,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> Loading Loading @@ -81,6 +83,10 @@ struct sii8620 { struct edid *edid; unsigned int gen2_write_burst:1; enum sii8620_mt_state mt_state; struct extcon_dev *extcon; struct notifier_block extcon_nb; struct work_struct extcon_wq; int cable_state; struct list_head mt_queue; struct { int r_size; Loading Loading @@ -2170,6 +2176,77 @@ static void sii8620_init_rcp_input_dev(struct sii8620 *ctx) ctx->rc_dev = rc_dev; } static void sii8620_cable_out(struct sii8620 *ctx) { disable_irq(to_i2c_client(ctx->dev)->irq); sii8620_hw_off(ctx); } static void sii8620_extcon_work(struct work_struct *work) { struct sii8620 *ctx = container_of(work, struct sii8620, extcon_wq); int state = extcon_get_state(ctx->extcon, EXTCON_DISP_MHL); if (state == ctx->cable_state) return; ctx->cable_state = state; if (state > 0) sii8620_cable_in(ctx); else sii8620_cable_out(ctx); } static int sii8620_extcon_notifier(struct notifier_block *self, unsigned long event, void *ptr) { struct sii8620 *ctx = container_of(self, struct sii8620, extcon_nb); schedule_work(&ctx->extcon_wq); return NOTIFY_DONE; } static int sii8620_extcon_init(struct sii8620 *ctx) { struct extcon_dev *edev; struct device_node *musb, *muic; int ret; /* get micro-USB connector node */ musb = of_graph_get_remote_node(ctx->dev->of_node, 1, -1); /* next get micro-USB Interface Controller node */ muic = of_get_next_parent(musb); if (!muic) { dev_info(ctx->dev, "no extcon found, switching to 'always on' mode\n"); return 0; } edev = extcon_find_edev_by_node(muic); of_node_put(muic); if (IS_ERR(edev)) { if (PTR_ERR(edev) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_err(ctx->dev, "Invalid or missing extcon\n"); return PTR_ERR(edev); } ctx->extcon = edev; ctx->extcon_nb.notifier_call = sii8620_extcon_notifier; INIT_WORK(&ctx->extcon_wq, sii8620_extcon_work); ret = extcon_register_notifier(edev, EXTCON_DISP_MHL, &ctx->extcon_nb); if (ret) { dev_err(ctx->dev, "failed to register notifier for MHL\n"); return ret; } return 0; } static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge) { return container_of(bridge, struct sii8620, bridge); Loading Loading @@ -2302,12 +2379,19 @@ static int sii8620_probe(struct i2c_client *client, if (ret) return ret; ret = sii8620_extcon_init(ctx); if (ret < 0) { dev_err(ctx->dev, "failed to initialize EXTCON\n"); return ret; } i2c_set_clientdata(client, ctx); ctx->bridge.funcs = &sii8620_bridge_funcs; ctx->bridge.of_node = dev->of_node; drm_bridge_add(&ctx->bridge); if (!ctx->extcon) sii8620_cable_in(ctx); return 0; Loading @@ -2317,8 +2401,15 @@ static int sii8620_remove(struct i2c_client *client) { struct sii8620 *ctx = i2c_get_clientdata(client); disable_irq(to_i2c_client(ctx->dev)->irq); sii8620_hw_off(ctx); if (ctx->extcon) { extcon_unregister_notifier(ctx->extcon, EXTCON_DISP_MHL, &ctx->extcon_nb); flush_work(&ctx->extcon_wq); if (ctx->cable_state > 0) sii8620_cable_out(ctx); } else { sii8620_cable_out(ctx); } drm_bridge_remove(&ctx->bridge); return 0; Loading include/linux/extcon.h +6 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ extern void devm_extcon_unregister_notifier_all(struct device *dev, * Following APIs get the extcon_dev from devicetree or by through extcon name. */ extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); extern struct extcon_dev *extcon_find_edev_by_node(struct device_node *node); extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index); Loading Loading @@ -283,6 +284,11 @@ static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) return ERR_PTR(-ENODEV); } static inline struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) { return ERR_PTR(-ENODEV); } static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) { Loading Loading
Documentation/devicetree/bindings/connector/samsung,usb-connector-11pin.txt 0 → 100644 +49 −0 Original line number Diff line number Diff line Samsung micro-USB 11-pin connector ================================== Samsung micro-USB 11-pin connector is an extension of micro-USB connector. It is present in multiple Samsung mobile devices. It has additional pins to route MHL traffic simultanously with USB. The bindings are superset of usb-connector bindings for micro-USB connector[1]. Required properties: - compatible: must be: "samsung,usb-connector-11pin", "usb-b-connector", - type: must be "micro". Required nodes: - any data bus to the connector should be modeled using the OF graph bindings specified in bindings/graph.txt, unless the bus is between parent node and the connector. Since single connector can have multpile data buses every bus has assigned OF graph port number as follows: 0: High Speed (HS), 3: Mobile High-Definition Link (MHL), specific to 11-pin Samsung micro-USB. [1]: bindings/connector/usb-connector.txt Example ------- Micro-USB connector with HS lines routed via controller (MUIC) and MHL lines connected to HDMI-MHL bridge (sii8620): muic-max77843@66 { ... usb_con: connector { compatible = "samsung,usb-connector-11pin", "usb-b-connector"; label = "micro-USB"; type = "micro"; ports { #address-cells = <1>; #size-cells = <0>; port@3 { reg = <3>; usb_con_mhl: endpoint { remote-endpoint = <&sii8620_mhl>; }; }; }; }; };
Documentation/devicetree/bindings/connector/usb-connector.txt 0 → 100644 +75 −0 Original line number Diff line number Diff line USB Connector ============= USB connector node represents physical USB connector. It should be a child of USB interface controller. Required properties: - compatible: describes type of the connector, must be one of: "usb-a-connector", "usb-b-connector", "usb-c-connector". Optional properties: - label: symbolic name for the connector, - type: size of the connector, should be specified in case of USB-A, USB-B non-fullsize connectors: "mini", "micro". Required nodes: - any data bus to the connector should be modeled using the OF graph bindings specified in bindings/graph.txt, unless the bus is between parent node and the connector. Since single connector can have multpile data buses every bus has assigned OF graph port number as follows: 0: High Speed (HS), present in all connectors, 1: Super Speed (SS), present in SS capable connectors, 2: Sideband use (SBU), present in USB-C. Examples -------- 1. Micro-USB connector with HS lines routed via controller (MUIC): muic-max77843@66 { ... usb_con: connector { compatible = "usb-b-connector"; label = "micro-USB"; type = "micro"; }; }; 2. USB-C connector attached to CC controller (s2mm005), HS lines routed to companion PMIC (max77865), SS lines to USB3 PHY and SBU to DisplayPort. DisplayPort video lines are routed to the connector via SS mux in USB3 PHY. ccic: s2mm005@33 { ... usb_con: connector { compatible = "usb-c-connector"; label = "USB-C"; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; usb_con_hs: endpoint { remote-endpoint = <&max77865_usbc_hs>; }; }; port@1 { reg = <1>; usb_con_ss: endpoint { remote-endpoint = <&usbdrd_phy_ss>; }; }; port@2 { reg = <2>; usb_con_sbu: endpoint { remote-endpoint = <&dp_aux>; }; }; }; }; };
drivers/extcon/extcon.c +34 −10 Original line number Diff line number Diff line Loading @@ -1336,6 +1336,28 @@ void extcon_dev_unregister(struct extcon_dev *edev) EXPORT_SYMBOL_GPL(extcon_dev_unregister); #ifdef CONFIG_OF /* * extcon_find_edev_by_node - Find the extcon device from devicetree. * @node : OF node identifying edev * * Return the pointer of extcon device if success or ERR_PTR(err) if fail. */ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) { struct extcon_dev *edev; mutex_lock(&extcon_dev_list_lock); list_for_each_entry(edev, &extcon_dev_list, entry) if (edev->dev.parent && edev->dev.parent->of_node == node) goto out; edev = ERR_PTR(-EPROBE_DEFER); out: mutex_unlock(&extcon_dev_list_lock); return edev; } /* * extcon_get_edev_by_phandle - Get the extcon device from devicetree. * @dev : the instance to the given device Loading Loading @@ -1363,25 +1385,27 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) return ERR_PTR(-ENODEV); } mutex_lock(&extcon_dev_list_lock); list_for_each_entry(edev, &extcon_dev_list, entry) { if (edev->dev.parent && edev->dev.parent->of_node == node) { mutex_unlock(&extcon_dev_list_lock); edev = extcon_find_edev_by_node(node); of_node_put(node); return edev; } } mutex_unlock(&extcon_dev_list_lock); of_node_put(node); return ERR_PTR(-EPROBE_DEFER); } #else struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) { return ERR_PTR(-ENOSYS); } struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) { return ERR_PTR(-ENOSYS); } #endif /* CONFIG_OF */ EXPORT_SYMBOL_GPL(extcon_find_edev_by_node); EXPORT_SYMBOL_GPL(extcon_get_edev_by_phandle); /** Loading
drivers/gpu/drm/bridge/sil-sii8620.c +94 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/extcon.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/interrupt.h> Loading @@ -25,6 +26,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> Loading Loading @@ -81,6 +83,10 @@ struct sii8620 { struct edid *edid; unsigned int gen2_write_burst:1; enum sii8620_mt_state mt_state; struct extcon_dev *extcon; struct notifier_block extcon_nb; struct work_struct extcon_wq; int cable_state; struct list_head mt_queue; struct { int r_size; Loading Loading @@ -2170,6 +2176,77 @@ static void sii8620_init_rcp_input_dev(struct sii8620 *ctx) ctx->rc_dev = rc_dev; } static void sii8620_cable_out(struct sii8620 *ctx) { disable_irq(to_i2c_client(ctx->dev)->irq); sii8620_hw_off(ctx); } static void sii8620_extcon_work(struct work_struct *work) { struct sii8620 *ctx = container_of(work, struct sii8620, extcon_wq); int state = extcon_get_state(ctx->extcon, EXTCON_DISP_MHL); if (state == ctx->cable_state) return; ctx->cable_state = state; if (state > 0) sii8620_cable_in(ctx); else sii8620_cable_out(ctx); } static int sii8620_extcon_notifier(struct notifier_block *self, unsigned long event, void *ptr) { struct sii8620 *ctx = container_of(self, struct sii8620, extcon_nb); schedule_work(&ctx->extcon_wq); return NOTIFY_DONE; } static int sii8620_extcon_init(struct sii8620 *ctx) { struct extcon_dev *edev; struct device_node *musb, *muic; int ret; /* get micro-USB connector node */ musb = of_graph_get_remote_node(ctx->dev->of_node, 1, -1); /* next get micro-USB Interface Controller node */ muic = of_get_next_parent(musb); if (!muic) { dev_info(ctx->dev, "no extcon found, switching to 'always on' mode\n"); return 0; } edev = extcon_find_edev_by_node(muic); of_node_put(muic); if (IS_ERR(edev)) { if (PTR_ERR(edev) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_err(ctx->dev, "Invalid or missing extcon\n"); return PTR_ERR(edev); } ctx->extcon = edev; ctx->extcon_nb.notifier_call = sii8620_extcon_notifier; INIT_WORK(&ctx->extcon_wq, sii8620_extcon_work); ret = extcon_register_notifier(edev, EXTCON_DISP_MHL, &ctx->extcon_nb); if (ret) { dev_err(ctx->dev, "failed to register notifier for MHL\n"); return ret; } return 0; } static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge) { return container_of(bridge, struct sii8620, bridge); Loading Loading @@ -2302,12 +2379,19 @@ static int sii8620_probe(struct i2c_client *client, if (ret) return ret; ret = sii8620_extcon_init(ctx); if (ret < 0) { dev_err(ctx->dev, "failed to initialize EXTCON\n"); return ret; } i2c_set_clientdata(client, ctx); ctx->bridge.funcs = &sii8620_bridge_funcs; ctx->bridge.of_node = dev->of_node; drm_bridge_add(&ctx->bridge); if (!ctx->extcon) sii8620_cable_in(ctx); return 0; Loading @@ -2317,8 +2401,15 @@ static int sii8620_remove(struct i2c_client *client) { struct sii8620 *ctx = i2c_get_clientdata(client); disable_irq(to_i2c_client(ctx->dev)->irq); sii8620_hw_off(ctx); if (ctx->extcon) { extcon_unregister_notifier(ctx->extcon, EXTCON_DISP_MHL, &ctx->extcon_nb); flush_work(&ctx->extcon_wq); if (ctx->cable_state > 0) sii8620_cable_out(ctx); } else { sii8620_cable_out(ctx); } drm_bridge_remove(&ctx->bridge); return 0; Loading
include/linux/extcon.h +6 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ extern void devm_extcon_unregister_notifier_all(struct device *dev, * Following APIs get the extcon_dev from devicetree or by through extcon name. */ extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); extern struct extcon_dev *extcon_find_edev_by_node(struct device_node *node); extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index); Loading Loading @@ -283,6 +284,11 @@ static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) return ERR_PTR(-ENODEV); } static inline struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) { return ERR_PTR(-ENODEV); } static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) { Loading