Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756314AbbEVKui (ORCPT ); Fri, 22 May 2015 06:50:38 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:49438 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755849AbbEVKuA (ORCPT ); Fri, 22 May 2015 06:50:00 -0400 X-AuditID: cbfee68e-f79c56d000006efb-c4-555f09d6055a From: Chanwoo Choi To: linux-kernel@vger.kernel.org Cc: rogerq@ti.com, r.baldyga@samsung.com, peter.chen@freescale.com, kishon@ti.com, balbi@ti.com, iivanov@mm-sol.com, cw00.choi@samsung.com, myungjoo.ham@samsung.com Subject: [PATCH 1/2] extcon: Add extcon_set_cable_line_state() to inform the additional state of external connectors Date: Fri, 22 May 2015 19:49:49 +0900 Message-id: <1432291790-4933-2-git-send-email-cw00.choi@samsung.com> X-Mailer: git-send-email 1.8.5.5 In-reply-to: <1432291790-4933-1-git-send-email-cw00.choi@samsung.com> References: <1432291790-4933-1-git-send-email-cw00.choi@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrCLMWRmVeSWpSXmKPExsWyRsSkUPcaZ3yowfSvvBYH79dbXP/ynNXi 2cSHjBYXnvawWVzeNYfN4nbjCjaLY7P/Mlk8OLyT3aLnkZYDp8e/w/1MHpv2T2P26NuyitHj +I3tTB6fN8kFsEZx2aSk5mSWpRbp2yVwZfz59Yu9YIJhxf/Py1kaGG+pdzFyckgImEh0LnrD DGGLSVy4t56ti5GLQ0hgKaPE0QtL2GCKnp+azgiRWMQosezXWnaQhJDAF0aJGUe1QGw2AS2J /S9ugDWICChIbO59xgrSwCywglFi19UDYCuEBcokji9cCmazCKhKnP/byARi8wq4SKxb9wXq DAWJZctnsoLYnAKuEovetzBDLHORaOvcywwyVEJgFbvE2ZYz7BCDBCS+TT7E0sXIAZSQldh0 AGqOpMTBFTdYJjAKL2BkWMUomlqQXFCclF5kpFecmFtcmpeul5yfu4kRGPin/z3r28F484D1 IUYBDkYlHl7Dg3GhQqyJZcWVuYcYTYE2TGSWEk3OB8ZXXkm8obGZkYWpiamxkbmlmZI4b4LU z2AhgfTEktTs1NSC1KL4otKc1OJDjEwcnFINjNWJL4vfCz0LrrhYm6w55fTEpui85zzzbjdU Rq/T9jB8fGqn7o+76j5B3Wdq+30EuGJL7t1umtz/+d3Rxx+eBLGZ/4+6fnNNzpsd73fz3Fpd pjXDm8PSLitWRc3W7PbaPm2+8GnPi7bL3zBnfcrNfZGxl1/SxZP/RoWjwTmLpDKxp0s95xZK KLEUZyQaajEXFScCAPGK04p3AgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrHIsWRmVeSWpSXmKPExsVy+t9jAd1rnPGhBv332S0O3q+3uP7lOavF s4kPGS0uPO1hs7i8aw6bxe3GFWwWx2b/ZbJ4cHgnu0XPIy0HTo9/h/uZPDbtn8bs0bdlFaPH 8RvbmTw+b5ILYI1qYLTJSE1MSS1SSM1Lzk/JzEu3VfIOjneONzUzMNQ1tLQwV1LIS8xNtVVy 8QnQdcvMAbpHSaEsMacUKBSQWFyspG+HaUJoiJuuBUxjhK5vSBBcj5EBGkhYw5jx59cv9oIJ hhX/Py9naWC8pd7FyMkhIWAi8fzUdEYIW0ziwr31bF2MXBxCAosYJZb9WssOkhAS+MIoMeOo FojNJqAlsf/FDTYQW0RAQWJz7zNWkAZmgRWMEruuHmAGSQgLlEkcX7gUzGYRUJU4/7eRCcTm FXCRWLfuCzPENgWJZctnsoLYnAKuEovetzBDLHORaOvcyzyBkXcBI8MqRtHUguSC4qT0XCO9 4sTc4tK8dL3k/NxNjOC4eia9g3FVg8UhRgEORiUeXoODcaFCrIllxZW5hxglOJiVRHg/sMWH CvGmJFZWpRblxxeV5qQWH2I0BbpqIrOUaHI+MObzSuINjU3MjCyNzA0tjIzNlcR5T+b7hAoJ pCeWpGanphakFsH0MXFwSjUwTrjql7xC1sZk7/cJLoaW2cEWFyvq41Wniz0xLLW81/QgcfLH 63d5NvDN3ie8239Wubtp5JPHwuuPdK7YLfeSrThXzX+x64lDC0onb971/JLas9myJ/K6vH9P Z3ZeuGSBrMz6WXtL0lRW9gqqlFU9f2PrKG05K19a3dU6Ynn5/q8l7aUG30TuKbEUZyQaajEX FScCAJWVO0jBAgAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6345 Lines: 193 This patch adds the extcon_set_cable_line_state() function to inform the additional state of each external connector and 'enum extcon_line_state' enumeration which include the specific states of each external connector. The each external connector might need the different line state. So, current 'extcon_line_state' enumeration contains the specific state for USB as following: - Following the state mean the state of both ID and VBUS line for USB: enum extcon_line_state { EXTCON_USB_ID_LOW = BIT(1), /* ID line is low. */ EXTCON_USB_ID_HIGH = BIT(2), /* ID line is high. */ EXTCON_USB_VBUS_LOW = BIT(3), /* VBUS line is low. */ EXTCON_USB_VBUS_HIGH = BIT(4), /* VBUS line is high. */ }; Cc: Myungjoo Ham Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/extcon.h | 24 ++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 5099c11..2f7db54 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -279,7 +279,9 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) for (index = 0; index < edev->max_supported; index++) { if (is_extcon_changed(edev->state, state, index, &attached)) - raw_notifier_call_chain(&edev->nh[index], attached, edev); + raw_notifier_call_chain(&edev->nh[index], + attached ? EXTCON_ATTACHED : + EXTCON_DETACHED, edev); } edev->state &= ~mask; @@ -418,6 +420,69 @@ int extcon_set_cable_state(struct extcon_dev *edev, EXPORT_SYMBOL_GPL(extcon_set_cable_state); /** + * extcon_set_cable_line_state() - Set the line state of specific cable. + * @edev: the extcon device that has the cable. + * @id: the unique id of each external connector. + * @state: the line state for specific cable. + * + * Note that this function support the only USB connector to inform the state + * of both ID and VBUS line until now. This function may be extended to support + * the additional external connectors. + * + * If the id is EXTCON_USB, it can support only following line states: + * - EXTCON_USB_ID_LOW + * - EXTCON_USB_ID_HIGH, + * - EXTCON_USB_VBUS_LOW + * - EXTCON_USB_VBUS_HIGH + */ +int extcon_set_cable_line_state(struct extcon_dev *edev, enum extcon id, + enum extcon_line_state state) +{ + unsigned long flags; + unsigned long line_state; + int ret = 0, index; + + index = find_cable_index_by_id(edev, id); + if (index < 0) + return index; + + spin_lock_irqsave(&edev->lock, flags); + line_state = edev->line_state[index]; + + switch (id) { + case EXTCON_USB: + if (line_state & state) { + dev_info(&edev->dev, + "0x%x state is already set for %s\n", + state, extcon_name[id]); + goto err; + } + + if ((state & EXTCON_USB_ID_LOW) || (state & EXTCON_USB_ID_HIGH)) + line_state &= ~(EXTCON_USB_ID_LOW | EXTCON_USB_ID_HIGH); + + if ((state & EXTCON_USB_VBUS_LOW) + || (state & EXTCON_USB_VBUS_HIGH)) + line_state &= + ~(EXTCON_USB_VBUS_LOW | EXTCON_USB_VBUS_HIGH); + + line_state |= state; + break; + default: + ret = -EINVAL; + goto err; + } + edev->line_state[index] = line_state; + + ret = raw_notifier_call_chain(&edev->nh[index], line_state, edev); +err: + spin_unlock_irqrestore(&edev->lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(extcon_set_cable_line_state); + +/** * extcon_get_extcon_dev() - Get the extcon device instance from the name * @extcon_name: The extcon name provided with extcon_dev_register() */ @@ -897,6 +962,13 @@ int extcon_dev_register(struct extcon_dev *edev) goto err_dev; } + edev->line_state = devm_kzalloc(&edev->dev, + sizeof(*edev->line_state) * edev->max_supported, GFP_KERNEL); + if (!edev->line_state) { + ret = -ENOMEM; + goto err_dev; + } + for (index = 0; index < edev->max_supported; index++) RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]); diff --git a/include/linux/extcon.h b/include/linux/extcon.h index be9652b..79e5073 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -66,6 +66,19 @@ enum extcon { EXTCON_END, }; +enum extcon_line_state { + /* Following two definition are used for whether external connectors + * is attached or detached. */ + EXTCON_DETACHED = 0x0, + EXTCON_ATTACHED = 0x1, + + /* Following states are only used for EXTCON_USB. */ + EXTCON_USB_ID_LOW = BIT(1), /* ID line is low. */ + EXTCON_USB_ID_HIGH = BIT(2), /* ID line is high. */ + EXTCON_USB_VBUS_LOW = BIT(3), /* VBUS line is low. */ + EXTCON_USB_VBUS_HIGH = BIT(4), /* VBUS line is high. */ +}; + struct extcon_cable; /** @@ -90,6 +103,8 @@ struct extcon_cable; * @dev: Device of this extcon. * @state: Attach/detach state of this extcon. Do not provide at * register-time. + * @line_state: Line state for each external connecotrs are included in + * this extcon device. * @nh: Notifier for the state change events from this extcon * @entry: To support list of extcon devices so that users can * search for extcon devices based on the extcon name. @@ -121,6 +136,7 @@ struct extcon_dev { int max_supported; spinlock_t lock; /* could be called by irq handler */ u32 state; + unsigned long *line_state; /* /sys/class/extcon/.../cable.n/... */ struct device_type extcon_dev_type; @@ -217,6 +233,8 @@ 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); +extern int extcon_set_cable_line_state(struct extcon_dev *edev, enum extcon id, + enum extcon_line_state state); /* * Following APIs are for notifiees (those who want to be notified) @@ -324,6 +342,12 @@ static inline int extcon_set_cable_state(struct extcon_dev *edev, return 0; } +static inline int extcon_set_cable_line_state(struct extcon_dev *edev, + enum extcon id, enum extcon_line_state state) +{ + return 0; +} + static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) { return NULL; -- 1.8.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/