From patchwork Fri May 6 06:31:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12840630 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0666FC433FE for ; Fri, 6 May 2022 06:33:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352536AbiEFGh1 (ORCPT ); Fri, 6 May 2022 02:37:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350125AbiEFGh0 (ORCPT ); Fri, 6 May 2022 02:37:26 -0400 Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 41FB862BDA for ; Thu, 5 May 2022 23:33:43 -0700 (PDT) Received: from epcas2p2.samsung.com (unknown [182.195.41.54]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20220506063341epoutp042555a4175b3daeb41848b11f4e0669d6~scHdm3wY42011620116epoutp04P for ; Fri, 6 May 2022 06:33:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20220506063341epoutp042555a4175b3daeb41848b11f4e0669d6~scHdm3wY42011620116epoutp04P DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1651818821; bh=CDSe4hMSW9iyh5nlVlFrqmdmtEl+nqw4l8+FBs360vs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OJhhuvDUkIUnj451zGOMwge052Pkvvflprtsue+9FRfuKCw11uWlT6VWe8ciDQCV3 /33jFYWh0hiMNFmpNN9aU6o+7KvEtwslZ1ppg7q3dxAydHzzewprcl0J/onwRHf8gW 61GaJlaNhOnhLu6iWCprwlMoO96Gt2UZFs1L0E7g= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas2p3.samsung.com (KnoxPortal) with ESMTP id 20220506063340epcas2p3eb4d903c3fad698d2c06c7a372758834~scHc9tbwI0340303403epcas2p39; Fri, 6 May 2022 06:33:40 +0000 (GMT) Received: from epsmges2p3.samsung.com (unknown [182.195.36.101]) by epsnrtp1.localdomain (Postfix) with ESMTP id 4KvgkV0m2bz4x9QP; Fri, 6 May 2022 06:33:38 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p3.samsung.com (Symantec Messaging Gateway) with SMTP id FD.DF.10028.041C4726; Fri, 6 May 2022 15:33:36 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p3.samsung.com (KnoxPortal) with ESMTPA id 20220506063336epcas2p3da4c57aaa5a74460a742985f8a9d4ce1~scHY-hBdu3067030670epcas2p3F; Fri, 6 May 2022 06:33:36 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220506063336epsmtrp25c16d25f83ef329a3e2fdd5e60142f31~scHY9jqhU0488004880epsmtrp2M; Fri, 6 May 2022 06:33:36 +0000 (GMT) X-AuditID: b6c32a47-573ff7000000272c-fc-6274c140362a Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 5A.DD.08924.041C4726; Fri, 6 May 2022 15:33:36 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220506063336epsmtip2ffe229746b87d0601961c24c87b954ed~scHYrEJjQ0642706427epsmtip20; Fri, 6 May 2022 06:33:36 +0000 (GMT) From: Daehwan Jung To: Felipe Balbi , Greg Kroah-Hartman , Krzysztof Kozlowski , Alim Akhtar , Mathias Nyman , Lukas Bulwahn , Tony Lindgren , Juergen Gross , Arnd Bergmann , Matthias Kaehlcke Cc: linux-kernel@vger.kernel.org (open list), linux-usb@vger.kernel.org (open list:DESIGNWARE USB3 DRD IP DRIVER), linux-arm-kernel@lists.infradead.org (moderated list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), linux-samsung-soc@vger.kernel.org (open list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), sc.suh@samsung.com, taehyun.cho@samsung.com, jh0801.jung@samsung.com, eomji.oh@samsung.com, Daehwan Jung , Jack Pham , Howard Yen Subject: [PATCH v5 1/6] usb: host: export symbols for xhci-exynos to use xhci hooks Date: Fri, 6 May 2022 15:31:14 +0900 Message-Id: <1651818679-10594-2-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA0VTf0xTVxTe7Xt9fTSWvRXZLmwjTQUTUaCFAheRBaeyFybYuHQby7Q+6AsQ oC19ZdFlcyyOnwmKDBABCSgqEhTSIWqD8ktU2MZwbArMbjBwBBhIaBzEgq704fbfd875vu+c e+69JCb9nvAmU/Vm1qRn0uWEGG/r2RIeEN1lTlQU5kegsZo2Aq2W3BGhO7mTIvSotlyA+i/W CdCxc80EerjyBKC8qUECVY8EI9v4Mo5uzl4VIcvEAyEaslYTqOKnWwJ09kIOhr7pzcPRMUup ENlbJgAqtA0DVNLliTp+iY32pB3PSgD9z9MSnK7Kvo/TQ8eLBPSNSpuIrrVk0efapwW0pbGA oB89aCfojjNNIvq7+q/o462NgG5u/RWn7RYftfsnaTtSWEbHmmSsPsmgS9UnR8nf/0C7Sxsa plAGKCNQuFymZzLYKPnuveqAmNR056Hlss+Y9CxnSs1wnDzonR0mQ5aZlaUYOHOUnDXq0o3h xkCOyeCy9MmBeta8XalQBIc6iYfSUroG24Gxij584Y9VUTaYjSwEbiSkVHCh9m+iEIhJKXUd wGb73fVgEcB86zMBH9idlRf9+EvJiannOF+wAlhe/lDIB8sATg10iwoBSRKUP1yqA2v5jdQp DPY1Fbl8MaoYhyvWHpeVB6WBHR2PXRin/ODZS/ewNSyh9sCKxtME384HjgwUuPJuVAz8uazV 5QqpBRKOls2vk3ZDy9IQ4LEHnLnbKuKxN7TP31zncNC6mCPgxdkAfj3Gd4NUCKz8Kw+sjY1R W2CzNWgNQmoTvD3qmg2j3GF+z6qIT0tgfq6UF26Cp4aKhTz2gl2zAxhPoWHL82h+J6cBrB/r xYqBT+X//rUANILXWSOXkcxywcaQ/64syZBhAa5X7f/edVAxtxDYDQQk6AaQxOQbJR6V5kSp RMcc+Zw1GbSmrHSW6wahzt2dxLw9kwzOb6E3a5WqCIUqLEwZHhyqCJe/IYnVtTBSKpkxs2ks a2RNL3UC0s07W/BF6aG6fVTjlcmPlz6qdzTde+WJyaQu0GXPzP/JjoxpNvgOT9hCFnMntdEB s9orQq9e/7Zdl/3u92ZWTcWLW3pG3tbnxMWpHOZO3/raab9tiWduHLkVebBI51edkF8lVeP9 t6XbOmvIyaO2d9/a7rbcIJ5ZyK3UDRJJcXYgc6hqlj0O/6hi616zfXow80AU1qcRu++P3XnC evlD8OLkqwmcZOv4TMlv32qEwZeYhr4oXXNT/NEcz5ED6qdd9GpC/M7pxWud134f1wzJV0q3 9m6A7pbNbudJgy7U12vO5sjUSL+cS2YHHv8QdDFyVJznKHtzc0yRbLChb2a/bO9w5tUOOc6l MEp/zMQx/wK3TRxdXgQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmplkeLIzCtJLcpLzFFi42LZdlhJXtfhYEmSwdbzwhYP5m1js/g76Ri7 xbG2J+wWdxZMY7I4tXwhk0Xz4vVsFtf/vGe0aH9+gc1izk0ji7sPf7BY7H29ld1i0+NrrBaX d81hs5hxfh+TxaJlrcwWLUfbWSyaN01htfi84TGjRdfdG4wWkw6KWuy/4uUg6vH71yRGj29f J7F4zG64yOJxua+XyWPnrLvsHgs2lXos3vOSyWPTqk42jzvX9rB57J+7ht1j85J6j74tqxg9 1m+5yuLxeZNcAF8Ul01Kak5mWWqRvl0CV8bBC3sYC2Z7VCy7/5e9gfG1dRcjJ4eEgIlE//N/ LF2MXBxCAjsYJa613maGSEhKLJ17gx3CFpa433KEFaLoG6PE2ccnmLoYOTjYBLQkvi9kBKkR EZjLLLF1axFIDbPANBaJjXemgCWEBYIl9t38ywZiswioSixaeQJsAa+Aq8SMVTPZIBbISdw8 1wkW5xRwk7g0dQtYrxBQzcI/35knMPItYGRYxSiZWlCcm55bbFhglJdarlecmFtcmpeul5yf u4kRHFNaWjsY96z6oHeIkYmD8RCjBAezkgiv8KySJCHelMTKqtSi/Pii0pzU4kOM0hwsSuK8 F7pOxgsJpCeWpGanphakFsFkmTg4pRqYzD1SRHXmb3V+t0n5+97D1dMjf7JObdN6+Hc5t7xx +PP73jXHv50V89mVbxOiMMF5/W5u4TWqz77YL/pzJ/DZ/b49XGLJ/7bvOP7tp2XcjQmR32SW /bUMOPdb2P597Po67cL/DybMf6ez+ZKNesqbCc+NBbgK5/NN8tTfN3H7EpGVOS8ZDyV2W9Rd MA75JWE0U8Bp2SGRSUtVzy9PSc+U/3l5Yq933bbHGzJdzxcwLvlVMMdP7Yvdawbh5JLYP6Ha EWUBEhmmC+53f7K45ay1LFuY8d62Arm7f0/IbtlllHq4bIWHjoOjSvuuWVqtLA/Sg93Pea7Y lH8ofMeu22uWbn58lmHegW6p39yfT0tH31ZiKc5INNRiLipOBADI4NK5GAMAAA== X-CMS-MailID: 20220506063336epcas2p3da4c57aaa5a74460a742985f8a9d4ce1 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220506063336epcas2p3da4c57aaa5a74460a742985f8a9d4ce1 References: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Export symbols for xhci hooks usage: xhci_get_slot_ctx xhci_get_endpoint_address - Allow xhci hook to get ep_ctx from the xhci_container_ctx for getting the ep_ctx information to know which ep is offloading and comparing the context in remote subsystem memory if needed. xhci_ring_alloc - Allow xhci hook to allocate vendor specific ring. Vendors could alloc additional event ring. xhci_trb_virt_to_dma - Used to retrieve the DMA address of vendor specific ring. Vendors could get dequeue address of event ring. xhci_segment_free xhci_link_segments - Allow xhci hook to handle vendor specific segment. Vendors could directly free or link segments of vendor specific ring. xhci_initialize_ring_info - Allow xhci hook to initialize vendor specific ring. xhci_check_trb_in_td_math - Allow xhci hook to Check TRB math for validation. Vendors could check trb when allocating vendor specific ring. xhci_address_device - Allow override to give configuration info to Co-processor. xhci_bus_suspend xhci_bus_resume - Allow override of suspend and resume for power scenario. xhci_remove_stream_mapping - Allow to xhci hook to remove stream mapping. Vendors need to do it when free-ing vendor specific ring if it's stream type. Signed-off-by: Daehwan Jung Signed-off-by: Jack Pham Signed-off-by: Howard Yen --- drivers/usb/host/xhci-hub.c | 2 ++ drivers/usb/host/xhci-mem.c | 19 +++++++++++++------ drivers/usb/host/xhci-ring.c | 1 + drivers/usb/host/xhci.c | 4 +++- drivers/usb/host/xhci.h | 7 +++++++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index f65f1ba2b592..841617952ac7 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1812,6 +1812,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) return 0; } +EXPORT_SYMBOL_GPL(xhci_bus_suspend); /* * Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3. @@ -1956,6 +1957,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) spin_unlock_irqrestore(&xhci->lock, flags); return 0; } +EXPORT_SYMBOL_GPL(xhci_bus_resume); unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd) { diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index bbb27ee2c6a3..82b9f90c0f27 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -65,7 +65,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, return seg; } -static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) +void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) { if (seg->trbs) { dma_pool_free(xhci->segment_pool, seg->trbs, seg->dma); @@ -74,6 +74,7 @@ static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) kfree(seg->bounce_buf); kfree(seg); } +EXPORT_SYMBOL_GPL(xhci_segment_free); static void xhci_free_segments_for_ring(struct xhci_hcd *xhci, struct xhci_segment *first) @@ -96,9 +97,9 @@ static void xhci_free_segments_for_ring(struct xhci_hcd *xhci, * DMA address of the next segment. The caller needs to set any Link TRB * related flags, such as End TRB, Toggle Cycle, and no snoop. */ -static void xhci_link_segments(struct xhci_segment *prev, - struct xhci_segment *next, - enum xhci_ring_type type, bool chain_links) +void xhci_link_segments(struct xhci_segment *prev, + struct xhci_segment *next, + enum xhci_ring_type type, bool chain_links) { u32 val; @@ -118,6 +119,7 @@ static void xhci_link_segments(struct xhci_segment *prev, prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); } } +EXPORT_SYMBOL_GPL(xhci_link_segments); /* * Link the ring to the new segments. @@ -256,7 +258,7 @@ static int xhci_update_stream_segment_mapping( return ret; } -static void xhci_remove_stream_mapping(struct xhci_ring *ring) +void xhci_remove_stream_mapping(struct xhci_ring *ring) { struct xhci_segment *seg; @@ -269,6 +271,7 @@ static void xhci_remove_stream_mapping(struct xhci_ring *ring) seg = seg->next; } while (seg != ring->first_seg); } +EXPORT_SYMBOL_GPL(xhci_remove_stream_mapping); static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags) { @@ -316,6 +319,7 @@ void xhci_initialize_ring_info(struct xhci_ring *ring, */ ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1; } +EXPORT_SYMBOL_GPL(xhci_initialize_ring_info); /* Allocate segments and link them for a ring */ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, @@ -407,6 +411,7 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, kfree(ring); return NULL; } +EXPORT_SYMBOL_GPL(xhci_ring_alloc); void xhci_free_endpoint_ring(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, @@ -518,6 +523,7 @@ struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, return (struct xhci_slot_ctx *) (ctx->bytes + CTX_SIZE(xhci->hcc_params)); } +EXPORT_SYMBOL_GPL(xhci_get_slot_ctx); struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, @@ -1965,7 +1971,7 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci, } /* TRB math checks for xhci_trb_in_td(), using the command and event rings. */ -static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci) +int xhci_check_trb_in_td_math(struct xhci_hcd *xhci) { struct { dma_addr_t input_dma; @@ -2085,6 +2091,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci) xhci_dbg(xhci, "TRB math tests passed.\n"); return 0; } +EXPORT_SYMBOL_GPL(xhci_check_trb_in_td_math); static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) { diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f9707997969d..652b37cd9c5e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -79,6 +79,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, return 0; return seg->dma + (segment_offset * sizeof(*trb)); } +EXPORT_SYMBOL_GPL(xhci_trb_virt_to_dma); static bool trb_is_noop(union xhci_trb *trb) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 25b87e99b4dd..c06e8b21b724 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1468,6 +1468,7 @@ unsigned int xhci_get_endpoint_address(unsigned int ep_index) unsigned int direction = ep_index % 2 ? USB_DIR_OUT : USB_DIR_IN; return direction | number; } +EXPORT_SYMBOL_GPL(xhci_get_endpoint_address); /* Find the flag for this endpoint (for use in the control context). Use the * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is @@ -4324,10 +4325,11 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, return ret; } -static int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) +int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) { return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS); } +EXPORT_SYMBOL_GPL(xhci_address_device); static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev) { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 473a33ce299e..5316841e9b26 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -2054,6 +2054,11 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst); void xhci_free_endpoint_ring(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, unsigned int ep_index); +void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg); +void xhci_link_segments(struct xhci_segment *prev, + struct xhci_segment *next, + enum xhci_ring_type type, bool chain_links); +void xhci_remove_stream_mapping(struct xhci_ring *ring); struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, unsigned int num_streams, @@ -2100,6 +2105,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); +int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); int xhci_ext_cap_init(struct xhci_hcd *xhci); @@ -2116,6 +2122,7 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci, /* xHCI ring, segment, TRB, and TD functions */ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); +int xhci_check_trb_in_td_math(struct xhci_hcd *xhci); struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, struct xhci_segment *start_seg, union xhci_trb *start_trb, union xhci_trb *end_trb, dma_addr_t suspect_dma, bool debug); From patchwork Fri May 6 06:31:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12840633 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10AC0C433F5 for ; Fri, 6 May 2022 06:33:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356568AbiEFGhd (ORCPT ); Fri, 6 May 2022 02:37:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59870 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355433AbiEFGh3 (ORCPT ); Fri, 6 May 2022 02:37:29 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 95BDB62BDA for ; Thu, 5 May 2022 23:33:45 -0700 (PDT) Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220506063343epoutp03460273e09f0b3103697006ca51e6f9fe~scHfv5OAo0874808748epoutp03C for ; Fri, 6 May 2022 06:33:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220506063343epoutp03460273e09f0b3103697006ca51e6f9fe~scHfv5OAo0874808748epoutp03C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1651818823; bh=sic1v50tzKGx31K+Pke1xBGhbvgq+xivzhBOFgYgK00=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NPWSo77btFrui3ui4vfbThXYBXY/r4iUh3MUFjsS5+Bsusxi87St17qS0Z9eWWDbC N9PAthA+oc8x+OriSGtyq7BiHfsvKHG0aXJa3CgU/pvPFCg2urlYSoqzaBzeRVHsHC qXZ1gjxSrbUIgO6PeIomu10iH36nc1USd0BpA09Q= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas2p1.samsung.com (KnoxPortal) with ESMTP id 20220506063342epcas2p11f50d917aa4825b1b7a7ed49891d79bb~scHe7Chj62814128141epcas2p1W; Fri, 6 May 2022 06:33:42 +0000 (GMT) Received: from epsmges2p2.samsung.com (unknown [182.195.36.100]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4KvgkV6GsJz4x9Q1; Fri, 6 May 2022 06:33:38 +0000 (GMT) Received: from epcas2p1.samsung.com ( [182.195.41.53]) by epsmges2p2.samsung.com (Symantec Messaging Gateway) with SMTP id 80.EC.09764.241C4726; Fri, 6 May 2022 15:33:38 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p3.samsung.com (KnoxPortal) with ESMTPA id 20220506063338epcas2p3749d0e1a3fffde81a758f708861b62ec~scHanJ7fj0340303403epcas2p3v; Fri, 6 May 2022 06:33:38 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220506063338epsmtrp2d9ed052002dcbadeac560d60c66e9622~scHamBFGX0438604386epsmtrp2X; Fri, 6 May 2022 06:33:38 +0000 (GMT) X-AuditID: b6c32a46-f8bff70000002624-81-6274c14276de Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id E8.55.11276.241C4726; Fri, 6 May 2022 15:33:38 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220506063337epsmtip2c93408e2f79a62c19174717f510f9b05~scHaVyXQx0767807678epsmtip2J; Fri, 6 May 2022 06:33:37 +0000 (GMT) From: Daehwan Jung To: Felipe Balbi , Greg Kroah-Hartman , Krzysztof Kozlowski , Alim Akhtar , Mathias Nyman , Lukas Bulwahn , Tony Lindgren , Juergen Gross , Arnd Bergmann , Matthias Kaehlcke Cc: linux-kernel@vger.kernel.org (open list), linux-usb@vger.kernel.org (open list:DESIGNWARE USB3 DRD IP DRIVER), linux-arm-kernel@lists.infradead.org (moderated list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), linux-samsung-soc@vger.kernel.org (open list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), sc.suh@samsung.com, taehyun.cho@samsung.com, jh0801.jung@samsung.com, eomji.oh@samsung.com, Daehwan Jung , "J . Avila" , Puma Hsu , Howard Yen Subject: [PATCH v5 2/6] usb: host: add xhci hooks for xhci-exynos Date: Fri, 6 May 2022 15:31:15 +0900 Message-Id: <1651818679-10594-3-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA0VTe0xTZxTP13t7W1i6XIt1n8wRdglbeLcI9GMBxAnkxm0J2RLdXJZ6hTtA +qK3sM0srg6Vx7INmI6H4ioPIY2Ia6EqoSjIRBniEAFhoCiM8JDpeAmC21pat/9+5+T8fud3 zvk+ISbuIjyFaWo9q1MzSopwx61X/cKD3m7V75NOTgSh0VNWAj0vuiZA146OC9Cw8UceGm+v EKDOmtM8lF1ZT6CBtccAnRwMRSMPlnFkm2kUIPNYPx/1Np0kUMmtFh6qOHMEQ4d/ycFRtvkY H82fHwOotM4H5Y/cBaioVYIu39kZu4lefVYE6KXFIpw+YejB6UtlIwLaaM6kK5uneLTZlEfQ w/3NBH25/KyAtlR9RX/XYAJ0fUMfTs+bvRJFe9KjUlkmmdV5s+okTXKaOiWaeucDxQ5FeIRU FiSLRHLKW82o2Ggq7t3EoIQ0pX1myjuLUWbaU4kMx1EhMVE6Taae9U7VcPpoitUmK7VybTDH qLhMdUqwmtW/JZNKQ8PthXvTUxeefS/QLlaDzyu6p3kGUJoL8oGbEJJhMGepkJ8P3IVi8iKA uaeuYM5gDsDargbcUSUmlwCcrRG8YDy6O+EqsgFobBzCncEygLf7H9q1hEKC9IdPTwNHfiNZ jMEbZ78lHAFG1uNwJW9uXcqD3A5r/xlcN4KTvnCgKY9wYBEZD+vKCwhnOy842J2HObAbmQBv H29YV4XkpBAu3HjomiIOVq8WYk7sAac7GlxePeH8nzaXEAeb5o7wnGQDgIdGr7sIW2HZRA5w 2MZIP1jfFOKAkPSB7UPr42PkyzD36nOBMy2CuUfFTqIPLO4t4DvxZtg60+0SpGHZgonnXEqp fSm1c3gB8Cr7v4ERABPYxGo5VQrLhWpD/ztakkZlBuvP2j/hIjg2+yS4DfCEoA1AIUZtFHmU 6feJRcnMFwdYnUahy1SyXBsIty+vEPOUJGns/0KtV8jCIqVhEREyeWi4VE69ItqZfJ4RkymM nk1nWS2re8HjCd08DTyYFfMR+rs89iXbT2+uPRj1rfm0U/Nk/67OQwu9tg1dOy6k8+8tPm1Z liuiBrI6K3cFrA6tqc596dvj1Xdwi5bJGPPd/h6833hnZbLaav7Bp8fgt7dv+NWpkemb1pLB xF9TVXC/obbd9OEbq7stgb9Z/Q5uMAl6z42AgOsXkuC9HMvP8QeOK2ljZPdN/mHbTMzj6df3 bDNGVoxlwSk5TeUbAtuqLIGD8b3B2177K8D9symPkOaOvE/OWJZbi29plFGSb7qJJt3KH6Nb NX1XOmL4FFjMgF8/isv1nv09635Jy6U6t4jp+d1bPrYExr4vmU0xuG/OqEowlSrGpdktJ+TB sRIK51IZmT+m45h/AYM9V9hfBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpjkeLIzCtJLcpLzFFi42LZdlhJXtfpYEmSwe89bBYP5m1js/g76Ri7 xbG2J+wWdxZMY7J4cmQRu8Wp5QuZLJoXr2ezuP7nPaPFnJtGFncf/mCx2Pt6K7vFpsfXWC0u 75rDZjHj/D4mi0XLWpktWo62s1g0b5rCavF5w2NGi5lrlS267t5gtJh0UNRi/xUvBzGP378m MXp8+zqJxWN2w0UWj52z7rJ7LNhU6rF4z0smj02rOtk87lzbw+axf+4ado/NS+o9+rasYvRY v+Uqi8fnTXIBvFFcNimpOZllqUX6dglcGV9+9bMXfF3KWLHo3CumBsaZHYxdjJwcEgImEm9u PGPuYuTiEBLYzShx7topdoiEpMTSuTegbGGJ+y1HWCGKvjFKNG9ZAuRwcLAJaEl8Xwg2SERg LrPE1q1FIDXMAttZJA5cP8kGkhAWcJRY8f8mWBGLgKrE9V2dYHFeAVeJtXMnsEEskJO4ea6T GcTmFHCTuDR1C1i9EFDNwj/fmScw8i1gZFjFKJlaUJybnltsWGCYl1quV5yYW1yal66XnJ+7 iREcVVqaOxi3r/qgd4iRiYPxEKMEB7OSCK/wrJIkId6UxMqq1KL8+KLSnNTiQ4zSHCxK4rwX uk7GCwmkJ5akZqemFqQWwWSZODilGpg4GyPEDLyff2/QzWJ8cOAy61lT5mM1C88VyjHFmZ1x dUsO8s89LeWSbzqx0OdtW4PymSfeh/ee7ah47JJeweokN+/F9i2fWc26n3TfztcVW/Mrfnf9 Al55pYiWKbU5Rg5NH7cLvt6fxNhUG515UNtizvs5h+U5tRfEXWaVW6jK+PezlMlj0/1XVeyr rJtFelb5zZt2alnqeoFL6S+fS6/4L5G3sGpGYdmOyjijfsVSq7Jnq7cz5Rd1Nl/8rF8VUNoX nXrxr5Px/MPFj87//lPdJ/Uh4qnal7VJeuvu/1NSefaXt/QeyxPXSTfScpwUp3y2SfHlnTFr fcAGgZuH4o/5M97SkZcrqmvgOBhXpsRSnJFoqMVcVJwIALdR8GYZAwAA X-CMS-MailID: 20220506063338epcas2p3749d0e1a3fffde81a758f708861b62ec X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220506063338epcas2p3749d0e1a3fffde81a758f708861b62ec References: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org To enable supporting for USB offload, define "offload" in usb controller node of device tree. "offload" value can be used to determine which type of offload was been enabled in the SoC. For example: &usbdrd_dwc3 { ... /* support usb offloading, 0: disabled, 1: audio */ offload = <1>; ... }; There are several vendor_ops introduced by this patch: struct xhci_vendor_ops - function callbacks for vendor specific operations { @vendor_init: - called for vendor init process during xhci-plat-hcd probe. @vendor_cleanup: - called for vendor cleanup process during xhci-plat-hcd remove. @is_usb_offload_enabled: - called to check if usb offload enabled. @alloc_dcbaa: - called when allocating vendor specific dcbaa during memory initializtion. @free_dcbaa: - called to free vendor specific dcbaa when cleanup the memory. @alloc_transfer_ring: - called when vendor specific transfer ring allocation is required @free_transfer_ring: - called to free vendor specific transfer ring @sync_dev_ctx: - called when synchronization for device context is required @alloc_container_ctx - called to alloc vendor specific container context @free_container_ctx - called to free vendor specific container context } The xhci hooks with prefix "xhci_vendor_" on the ops in xhci_vendor_ops. For example, vendor_init ops will be invoked by xhci_vendor_init() hook, is_usb_offload_enabled ops will be invoked by xhci_vendor_is_usb_offload_enabled(), and so on. Signed-off-by: Daehwan Jung Signed-off-by: J. Avila Signed-off-by: Puma Hsu Signed-off-by: Howard Yen --- drivers/usb/host/xhci-hub.c | 5 ++ drivers/usb/host/xhci-mem.c | 131 +++++++++++++++++++++++++++++++---- drivers/usb/host/xhci-plat.c | 44 +++++++++++- drivers/usb/host/xhci-plat.h | 8 +++ drivers/usb/host/xhci.c | 80 ++++++++++++++++++++- drivers/usb/host/xhci.h | 47 +++++++++++++ 6 files changed, 297 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 841617952ac7..e07c9c132061 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -535,8 +535,13 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) cmd->status == COMP_COMMAND_RING_STOPPED) { xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); ret = -ETIME; + goto cmd_cleanup; } + ret = xhci_vendor_sync_dev_ctx(xhci, slot_id); + if (ret) + xhci_warn(xhci, "Sync device context failed, ret=%d\n", ret); + cmd_cleanup: xhci_free_command(xhci, cmd); return ret; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 82b9f90c0f27..5ee0ffb676d3 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -365,6 +365,54 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, return 0; } +static void xhci_vendor_free_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->free_container_ctx) + ops->free_container_ctx(xhci, ctx); +} + +static void xhci_vendor_alloc_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, + int type, gfp_t flags) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->alloc_container_ctx) + ops->alloc_container_ctx(xhci, ctx, type, flags); +} + +static struct xhci_ring *xhci_vendor_alloc_transfer_ring(struct xhci_hcd *xhci, + u32 endpoint_type, enum xhci_ring_type ring_type, + unsigned int max_packet, gfp_t mem_flags) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->alloc_transfer_ring) + return ops->alloc_transfer_ring(xhci, endpoint_type, ring_type, + max_packet, mem_flags); + return 0; +} + +void xhci_vendor_free_transfer_ring(struct xhci_hcd *xhci, + struct xhci_ring *ring, unsigned int ep_index) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->free_transfer_ring) + ops->free_transfer_ring(xhci, ring, ep_index); +} + +bool xhci_vendor_is_usb_offload_enabled(struct xhci_hcd *xhci, + struct xhci_virt_device *virt_dev, unsigned int ep_index) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->is_usb_offload_enabled) + return ops->is_usb_offload_enabled(xhci, virt_dev, ep_index); + return false; +} + /* * Create a new ring with zero or more segments. * @@ -417,7 +465,11 @@ void xhci_free_endpoint_ring(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, unsigned int ep_index) { - xhci_ring_free(xhci, virt_dev->eps[ep_index].ring); + if (xhci_vendor_is_usb_offload_enabled(xhci, virt_dev, ep_index)) + xhci_vendor_free_transfer_ring(xhci, virt_dev->eps[ep_index].ring, ep_index); + else + xhci_ring_free(xhci, virt_dev->eps[ep_index].ring); + virt_dev->eps[ep_index].ring = NULL; } @@ -475,6 +527,7 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, { struct xhci_container_ctx *ctx; struct device *dev = xhci_to_hcd(xhci)->self.sysdev; + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); if ((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)) return NULL; @@ -488,7 +541,12 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, if (type == XHCI_CTX_TYPE_INPUT) ctx->size += CTX_SIZE(xhci->hcc_params); - ctx->bytes = dma_pool_zalloc(xhci->device_pool, flags, &ctx->dma); + if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0) && + (ops && ops->alloc_container_ctx)) + xhci_vendor_alloc_container_ctx(xhci, ctx, type, flags); + else + ctx->bytes = dma_pool_zalloc(xhci->device_pool, flags, &ctx->dma); + if (!ctx->bytes) { kfree(ctx); return NULL; @@ -499,9 +557,16 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, void xhci_free_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) { + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + if (!ctx) return; - dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma); + if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0) && + (ops && ops->free_container_ctx)) + xhci_vendor_free_container_ctx(xhci, ctx); + else + dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma); + kfree(ctx); } @@ -894,7 +959,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) for (i = 0; i < 31; i++) { if (dev->eps[i].ring) - xhci_ring_free(xhci, dev->eps[i].ring); + xhci_free_endpoint_ring(xhci, dev, i); if (dev->eps[i].stream_info) xhci_free_stream_info(xhci, dev->eps[i].stream_info); @@ -1492,8 +1557,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, mult = 0; /* Set up the endpoint ring */ - virt_dev->eps[ep_index].new_ring = - xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags); + if (xhci_vendor_is_usb_offload_enabled(xhci, virt_dev, ep_index) && + usb_endpoint_xfer_isoc(&ep->desc)) { + virt_dev->eps[ep_index].new_ring = + xhci_vendor_alloc_transfer_ring(xhci, endpoint_type, ring_type, + max_packet, mem_flags); + } else { + virt_dev->eps[ep_index].new_ring = + xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags); + } + if (!virt_dev->eps[ep_index].new_ring) return -ENOMEM; @@ -1837,6 +1910,24 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) erst->entries = NULL; } +static struct xhci_device_context_array *xhci_vendor_alloc_dcbaa( + struct xhci_hcd *xhci, gfp_t flags) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->alloc_dcbaa) + return ops->alloc_dcbaa(xhci, flags); + return 0; +} + +static void xhci_vendor_free_dcbaa(struct xhci_hcd *xhci) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->free_dcbaa) + ops->free_dcbaa(xhci); +} + void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct device *dev = xhci_to_hcd(xhci)->self.sysdev; @@ -1888,9 +1979,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed medium stream array pool"); - if (xhci->dcbaa) - dma_free_coherent(dev, sizeof(*xhci->dcbaa), - xhci->dcbaa, xhci->dcbaa->dma); + if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0)) { + xhci_vendor_free_dcbaa(xhci); + } else { + if (xhci->dcbaa) + dma_free_coherent(dev, sizeof(*xhci->dcbaa), + xhci->dcbaa, xhci->dcbaa->dma); + } xhci->dcbaa = NULL; scratchpad_free(xhci); @@ -2427,15 +2522,21 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * xHCI section 5.4.6 - Device Context array must be * "physically contiguous and 64-byte (cache line) aligned". */ - xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, - flags); - if (!xhci->dcbaa) - goto fail; - xhci->dcbaa->dma = dma; + if (xhci_vendor_is_usb_offload_enabled(xhci, NULL, 0)) { + xhci->dcbaa = xhci_vendor_alloc_dcbaa(xhci, flags); + if (!xhci->dcbaa) + goto fail; + } else { + xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, + flags); + if (!xhci->dcbaa) + goto fail; + xhci->dcbaa->dma = dma; + } xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Device context base array address = 0x%llx (DMA), %p (virt)", (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa); - xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr); + xhci_write_64(xhci, xhci->dcbaa->dma, &xhci->op_regs->dcbaa_ptr); /* * Initialize the ring segment pool. The ring must be a contiguous diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 649ffd861b44..a5881ff945a6 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -173,6 +173,41 @@ static const struct of_device_id usb_xhci_of_match[] = { MODULE_DEVICE_TABLE(of, usb_xhci_of_match); #endif +static struct xhci_plat_priv_overwrite xhci_plat_vendor_overwrite; + +int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops) +{ + if (vendor_ops == NULL) + return -EINVAL; + + xhci_plat_vendor_overwrite.vendor_ops = vendor_ops; + + return 0; +} +EXPORT_SYMBOL_GPL(xhci_plat_register_vendor_ops); + +static int xhci_vendor_init(struct xhci_hcd *xhci, struct device *dev) +{ + struct xhci_vendor_ops *ops = NULL; + + if (xhci_plat_vendor_overwrite.vendor_ops) + ops = xhci->vendor_ops = xhci_plat_vendor_overwrite.vendor_ops; + + if (ops && ops->vendor_init) + return ops->vendor_init(xhci, dev); + return 0; +} + +static void xhci_vendor_cleanup(struct xhci_hcd *xhci) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->vendor_cleanup) + ops->vendor_cleanup(xhci); + + xhci->vendor_ops = NULL; +} + static int xhci_plat_probe(struct platform_device *pdev) { const struct xhci_plat_priv *priv_match; @@ -185,7 +220,6 @@ static int xhci_plat_probe(struct platform_device *pdev) int irq; struct xhci_plat_priv *priv = NULL; - if (usb_disabled()) return -ENODEV; @@ -321,6 +355,10 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_usb3_hcd; } + ret = xhci_vendor_init(xhci, &pdev->dev); + if (ret) + goto disable_usb_phy; + hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); xhci->shared_hcd->tpl_support = hcd->tpl_support; if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) @@ -393,8 +431,10 @@ static int xhci_plat_remove(struct platform_device *dev) usb_phy_shutdown(hcd->usb_phy); usb_remove_hcd(hcd); - usb_put_hcd(shared_hcd); + xhci_vendor_cleanup(xhci); + + usb_put_hcd(shared_hcd); clk_disable_unprepare(clk); clk_disable_unprepare(reg_clk); usb_put_hcd(hcd); diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 1fb149d1fbce..8c204f3234d8 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -17,8 +17,16 @@ struct xhci_plat_priv { int (*init_quirk)(struct usb_hcd *); int (*suspend_quirk)(struct usb_hcd *); int (*resume_quirk)(struct usb_hcd *); + void *vendor_priv; }; #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) #define xhci_to_priv(x) ((struct xhci_plat_priv *)(x)->priv) + +struct xhci_plat_priv_overwrite { + struct xhci_vendor_ops *vendor_ops; +}; + +int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops); + #endif /* _XHCI_PLAT_H */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c06e8b21b724..5ccf1bbe8732 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2986,6 +2986,14 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, xhci_finish_resource_reservation(xhci, ctrl_ctx); spin_unlock_irqrestore(&xhci->lock, flags); } + if (ret) + goto failed; + + ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id); + if (ret) + xhci_warn(xhci, "sync device context failed, ret=%d", ret); + +failed: return ret; } @@ -3129,7 +3137,11 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) for (i = 0; i < 31; i++) { if (virt_dev->eps[i].new_ring) { xhci_debugfs_remove_endpoint(xhci, virt_dev, i); - xhci_ring_free(xhci, virt_dev->eps[i].new_ring); + if (xhci_vendor_is_usb_offload_enabled(xhci, virt_dev, i)) + xhci_vendor_free_transfer_ring(xhci, virt_dev->eps[i].new_ring, i); + else + xhci_ring_free(xhci, virt_dev->eps[i].new_ring); + virt_dev->eps[i].new_ring = NULL; } } @@ -3290,6 +3302,13 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, wait_for_completion(stop_cmd->completion); + err = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id); + if (err) { + xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d", + __func__, err); + goto cleanup; + } + spin_lock_irqsave(&xhci->lock, flags); /* config ep command clears toggle if add and drop ep flags are set */ @@ -3321,6 +3340,11 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, wait_for_completion(cfg_cmd->completion); + err = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id); + if (err) + xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d", + __func__, err); + xhci_free_command(xhci, cfg_cmd); cleanup: xhci_free_command(xhci, stop_cmd); @@ -3866,6 +3890,13 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, /* Wait for the Reset Device command to finish */ wait_for_completion(reset_device_cmd->completion); + ret = xhci_vendor_sync_dev_ctx(xhci, slot_id); + if (ret) { + xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d", + __func__, ret); + goto command_cleanup; + } + /* The Reset Device command can't fail, according to the 0.95/0.96 spec, * unless we tried to reset a slot ID that wasn't enabled, * or the device wasn't in the addressed or configured state. @@ -4111,6 +4142,14 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); goto disable_slot; } + + ret = xhci_vendor_sync_dev_ctx(xhci, slot_id); + if (ret) { + xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d", + __func__, ret); + goto disable_slot; + } + vdev = xhci->devs[slot_id]; slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx); trace_xhci_alloc_dev(slot_ctx); @@ -4241,6 +4280,13 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */ wait_for_completion(command->completion); + ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id); + if (ret) { + xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d", + __func__, ret); + goto out; + } + /* FIXME: From section 4.3.4: "Software shall be responsible for timing * the SetAddress() "recovery interval" required by USB and aborting the * command on a timeout. @@ -4393,6 +4439,14 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, return -ENOMEM; } + ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id); + if (ret) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d", + __func__, ret); + return ret; + } + xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); spin_unlock_irqrestore(&xhci->lock, flags); @@ -4420,6 +4474,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, return ret; } +struct xhci_vendor_ops *xhci_vendor_get_ops(struct xhci_hcd *xhci) +{ + return xhci->vendor_ops; +} +EXPORT_SYMBOL_GPL(xhci_vendor_get_ops); + +int xhci_vendor_sync_dev_ctx(struct xhci_hcd *xhci, unsigned int slot_id) +{ + struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci); + + if (ops && ops->sync_dev_ctx) + return ops->sync_dev_ctx(xhci, slot_id); + return 0; +} + #ifdef CONFIG_PM /* BESL to HIRD Encoding array for USB2 LPM */ @@ -5144,6 +5213,15 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, return -ENOMEM; } + ret = xhci_vendor_sync_dev_ctx(xhci, hdev->slot_id); + if (ret) { + xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d", + __func__, ret); + xhci_free_command(xhci, config_cmd); + spin_unlock_irqrestore(&xhci->lock, flags); + return ret; + } + xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx); ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 5316841e9b26..5d356f40c2b9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1929,6 +1929,9 @@ struct xhci_hcd { struct list_head regset_list; void *dbc; + + struct xhci_vendor_ops *vendor_ops; + /* platform-specific data -- must come last */ unsigned long priv[] __aligned(sizeof(s64)); }; @@ -2214,6 +2217,50 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, urb->stream_id); } +/** + * struct xhci_vendor_ops - function callbacks for vendor specific operations + * @vendor_init: called for vendor init process + * @vendor_cleanup: called for vendor cleanup process + * @is_usb_offload_enabled: called to check if usb offload enabled + * @alloc_dcbaa: called when allocating vendor specific dcbaa + * @free_dcbaa: called to free vendor specific dcbaa + * @alloc_transfer_ring: called when remote transfer ring allocation is required + * @free_transfer_ring: called to free vendor specific transfer ring + * @sync_dev_ctx: called when synchronization for device context is required + * @alloc_container_ctx: called when allocating vendor specific container context + * @free_container_ctx: called to free vendor specific container context + */ +struct xhci_vendor_ops { + int (*vendor_init)(struct xhci_hcd *xhci, struct device *dev); + void (*vendor_cleanup)(struct xhci_hcd *xhci); + bool (*is_usb_offload_enabled)(struct xhci_hcd *xhci, + struct xhci_virt_device *vdev, + unsigned int ep_index); + + struct xhci_device_context_array *(*alloc_dcbaa)(struct xhci_hcd *xhci, + gfp_t flags); + void (*free_dcbaa)(struct xhci_hcd *xhci); + + struct xhci_ring *(*alloc_transfer_ring)(struct xhci_hcd *xhci, + u32 endpoint_type, enum xhci_ring_type ring_type, + unsigned int max_packet, gfp_t mem_flags); + void (*free_transfer_ring)(struct xhci_hcd *xhci, + struct xhci_ring *ring, unsigned int ep_index); + int (*sync_dev_ctx)(struct xhci_hcd *xhci, unsigned int slot_id); + void (*alloc_container_ctx)(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, + int type, gfp_t flags); + void (*free_container_ctx)(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); +}; +/** + * Only Below vendor ops are non-static. That's why we add prototype here. + */ +struct xhci_vendor_ops *xhci_vendor_get_ops(struct xhci_hcd *xhci); +int xhci_vendor_sync_dev_ctx(struct xhci_hcd *xhci, unsigned int slot_id); +void xhci_vendor_free_transfer_ring(struct xhci_hcd *xhci, + struct xhci_ring *ring, unsigned int ep_index); +bool xhci_vendor_is_usb_offload_enabled(struct xhci_hcd *xhci, + struct xhci_virt_device *virt_dev, unsigned int ep_index); + /* * TODO: As per spec Isochronous IDT transmissions are supported. We bypass * them anyways as we where unable to find a device that matches the From patchwork Fri May 6 06:31:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12840632 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9FCC7C433F5 for ; Fri, 6 May 2022 06:33:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355958AbiEFGhb (ORCPT ); Fri, 6 May 2022 02:37:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355503AbiEFGh3 (ORCPT ); Fri, 6 May 2022 02:37:29 -0400 Received: from mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7FFB365D31 for ; Thu, 5 May 2022 23:33:47 -0700 (PDT) Received: from epcas2p2.samsung.com (unknown [182.195.41.54]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20220506063343epoutp03370618b9788a9c2d78aa0435dc60ab65~scHf3TFhy0874608746epoutp03G for ; Fri, 6 May 2022 06:33:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20220506063343epoutp03370618b9788a9c2d78aa0435dc60ab65~scHf3TFhy0874608746epoutp03G DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1651818823; bh=hb34QOx+LRjNhP9A+ykl7khL8yUaFNzKHpIrai9d5jw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PiXjyc+754tPUWn+IBUApeuDc1gjSuCiX/5h0DPqU1vE2BOLkp+qFFdp7NMSSnveG VXVoRhvAIXzMUwStVPX20KfQULtRXvALXSsnDANdN3I9LMd46uC5ssexQasrRsKduo ru2DartwulNp06iUV/Oe7Lo5+fGcALrkCWEKExBM= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas2p2.samsung.com (KnoxPortal) with ESMTP id 20220506063343epcas2p2d7fcb3dfed8e6cb9d1fe24ec053f83de~scHfOVRTD0727807278epcas2p2a; Fri, 6 May 2022 06:33:43 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.36.91]) by epsnrtp1.localdomain (Postfix) with ESMTP id 4KvgkX2kLqz4x9Q8; Fri, 6 May 2022 06:33:40 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id 9E.41.10069.341C4726; Fri, 6 May 2022 15:33:39 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p3.samsung.com (KnoxPortal) with ESMTPA id 20220506063338epcas2p37d0e07d937624e56cb2114d9f75fdd42~scHbIUDWW3067030670epcas2p3M; Fri, 6 May 2022 06:33:38 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220506063338epsmtrp10560356314e0a7dab5e7ce4a4e6df0b9~scHbHaR_83174031740epsmtrp1Z; Fri, 6 May 2022 06:33:38 +0000 (GMT) X-AuditID: b6c32a45-a79ff70000002755-5f-6274c1434af8 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 9F.DD.08924.241C4726; Fri, 6 May 2022 15:33:38 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220506063338epsmtip293b3f0f1c983e4ae0d9d2546e576bbc4~scHa6qxU50766207662epsmtip2M; Fri, 6 May 2022 06:33:38 +0000 (GMT) From: Daehwan Jung To: Felipe Balbi , Greg Kroah-Hartman , Krzysztof Kozlowski , Alim Akhtar , Mathias Nyman , Lukas Bulwahn , Tony Lindgren , Juergen Gross , Arnd Bergmann , Matthias Kaehlcke Cc: linux-kernel@vger.kernel.org (open list), linux-usb@vger.kernel.org (open list:DESIGNWARE USB3 DRD IP DRIVER), linux-arm-kernel@lists.infradead.org (moderated list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), linux-samsung-soc@vger.kernel.org (open list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), sc.suh@samsung.com, taehyun.cho@samsung.com, jh0801.jung@samsung.com, eomji.oh@samsung.com, Daehwan Jung Subject: [PATCH v5 3/6] usb: host: xhci-plat: support override of hc driver Date: Fri, 6 May 2022 15:31:16 +0900 Message-Id: <1651818679-10594-4-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA0WTe0wUVxTGc2eGmeXVTBeoF5ogGdOkEh67lGUvDdg2iJ1CsaS1xpC0dIDJ Qtmd3ewsQk1aMSCPFVu6RZGnu2hteLTQFakgVkGRh8hDHoEKAgHaUl9EIlLQtLC7tv/97jnn +869594rwaWtpI8kTTDweoFTM6QL0XJtpzIwqsOQJGu6/jKarW4h0XPTDQrdyFug0JT5JIb6 frBgKOdMI4kqJ0PQ9NwagS7fu0Ah6/y4ExppqyTRqcFfMVRz7iiOcrvyCZRjLXFCK03zABmn JwAydXihK6Mxb3uwG+smwK4+MRFsRfYwwbaWT1PsmfYljLXWFZLs1Hg7yV6paqDY82cPs183 1wG2sXmMYFesvvFuCekRqTyXwuv9eCFZm5ImqCKZ2I8SoxIVYTJ5oDwcKRk/gdPwkczu9+MD 96SpN0/I+B3k1BmboXhOFJngXRF6bYaB90vVioZIhtelqHVKXZDIacQMQRUk8IY35TJZiGKz 8LP01LFbPZTujmtW86MWKhtYXIzAWQLpUGgd63IyAheJlL4I4GR+IbAvHgNoutXgyKwAePVE DvlCsrE8SNoTbQCW3Lc6JGsAzi72YkYgkZC0P3xqscU96VIc9jYctylwuheHI+011JaVBx0L x0YqbLYE/RpsyVuxsTsdDRtnShztfOHkQCG+xc70Hnj7RLPNFdJDElj1JNdRtBtWmqcJO3vA v7qbKTv7wKVv8hwswrbHRzG7OBvAI7M9uD3xBiz/PR9sbRund8LGtuAthPQOeP03myVOvwQL rj2n7GF3WJAntQt3wNKRYic7e8OOewMOQxaOt+Vi9qGUAdj0ZwUoBr7l/zcwA1AHXuF1okbF iyE6+X93lqzVWIHtDftHXwTfPVgO6gSYBHQCKMEZT3ePckOS1D2F++IQr9cm6jPUvNgJFJvD +xb38UrWbn4CwZAoDw2XhYaFyZUhCpmS2eYek9LESWkVZ+DTeV7H61/oMImzTzbWelZdVNFz /A8z8V71pZmJp+uXaw2l7VWfTMd8eOdhQwDZn5MXTn4/HKvWmLzedTN/eUzVGPXwLu36KOLZ vhjtKqxVRxdMHbg5VhHXPXrwrqVkv1/Lz64TmsF9CxPKSte/eW9qNG75QGjNxu16+pdjBSM9 qpnuS7K57fV7y6jUhvWB8E8ZRZdujkpQtH4s1gkJCR/k+grFn/ct3DwSOLirD01mzddvnA44 96zajVzfLp398XDYEBQoy6ltaatqkPmV5/kA/vWsPuz+q95Dw0WaAvNijiXxHc/0tx4YfyLS M5sOxRmzFsjWtSXd1TJmP150AdbmRi26JfUzmUH9wf+sMYSYysn9cb3I/Qs8yXxNTAQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrELMWRmVeSWpSXmKPExsWy7bCSvK7TwZIkg75L2hYP5m1js/g76Ri7 xbG2J+wWdxZMY7I4tXwhk0Xz4vVsFnNuGlncffiDxWLv663sFpseX2O1uLxrDpvFjPP7mCwW LWtltmg52s5i0bxpCqvF5w2PGS267t5gtJh0UNRi/xUvB2GP378mMXp8+zqJxWN2w0UWj52z 7rJ7LN7zkslj06pONo871/aweeyfu4bdY/OSeo++LasYPdZvucri8XmTXABPFJdNSmpOZllq kb5dAlfG1bMn2Atuc1dseb+NvYFxIVcXIyeHhICJxO8P59m6GLk4hAR2MErcvHOXESIhKbF0 7g12CFtY4n7LEVaIom+MEhcWPWLpYuTgYBPQkvi+EKxeRGAus8TWrUUgNcwCZ5kl/jxdzQaS EBbwlrh6eTaYzSKgKrGt7TOYzSvgKrH+/hQ2iAVyEjfPdTKD2JwCbhKXpm4BGyoEVLPwz3fm CYx8CxgZVjFKphYU56bnFhsWGOWllusVJ+YWl+al6yXn525iBEeLltYOxj2rPugdYmTiYDzE KMHBrCTCKzyrJEmINyWxsiq1KD++qDQntfgQozQHi5I474Wuk/FCAumJJanZqakFqUUwWSYO TqkGpg0i9ozyqg9Xf5h61yjX7sLr1kl1EUaP0g6q/sgokzlqMLd0u5mhhlcYc/GUsJvOJ6xn mdvN1T+e1mA/KYF/bd2JCut5kuZd8kEF6lF8uTPdORni1JsUPf+dOylUdmTheasfH277PIpR 6L2WF5JpyRolemSNWXRdf2eLhOKVY+kn8pd8eK5iynVsTcoar5OOsSfYHbeeelR35eSrvewF /24Wxn9R7/i/0C95GWPPNPbirpbHs8M/L/sxz3p3WXZLr0DCWb1dS8+KWvxc6CTfauBwUe39 tXOqE89+3mm9+Xhewm7fJc3fVmx1PvVJ5/q2Qu8dTsb7eGrzl57eGXrT/vmL3YIBzw84ezYo xswwVmIpzkg01GIuKk4EAHNcid0FAwAA X-CMS-MailID: 20220506063338epcas2p37d0e07d937624e56cb2114d9f75fdd42 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220506063338epcas2p37d0e07d937624e56cb2114d9f75fdd42 References: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org It helps xhci-plat driver increase usability. Vendors could use functions in xhci-plat mostly and use some overrides to do what they wants without modifying xhci-plat driver. Signed-off-by: Daehwan Jung --- drivers/usb/host/xhci-plat.c | 6 ++++++ drivers/usb/host/xhci-plat.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index a5881ff945a6..a340e14ce9a6 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -173,6 +173,12 @@ static const struct of_device_id usb_xhci_of_match[] = { MODULE_DEVICE_TABLE(of, usb_xhci_of_match); #endif +void xhci_plat_override_driver(const struct xhci_driver_overrides *xhci_vendor_overrides) +{ + xhci_init_driver(&xhci_plat_hc_driver, xhci_vendor_overrides); +} +EXPORT_SYMBOL_GPL(xhci_plat_override_driver); + static struct xhci_plat_priv_overwrite xhci_plat_vendor_overwrite; int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops) diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 8c204f3234d8..455e0018d5e6 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -28,5 +28,6 @@ struct xhci_plat_priv_overwrite { }; int xhci_plat_register_vendor_ops(struct xhci_vendor_ops *vendor_ops); +void xhci_plat_override_driver(const struct xhci_driver_overrides *xhci_vendor_overrides); #endif /* _XHCI_PLAT_H */ From patchwork Fri May 6 06:31:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12840631 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B200BC433FE for ; Fri, 6 May 2022 06:33:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1354044AbiEFGh2 (ORCPT ); Fri, 6 May 2022 02:37:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59818 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352175AbiEFGh0 (ORCPT ); Fri, 6 May 2022 02:37:26 -0400 Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B83965D35 for ; Thu, 5 May 2022 23:33:44 -0700 (PDT) Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20220506063342epoutp04527984c4dc248beb2899253d81b74f99~scHegxdrL2012220122epoutp04P for ; Fri, 6 May 2022 06:33:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20220506063342epoutp04527984c4dc248beb2899253d81b74f99~scHegxdrL2012220122epoutp04P DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1651818822; bh=boZqsu5x83x4yZ3yCA0TfzOorlYh1KIsxJqlRVWoJB4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=le7o0FoHyUHtbdvAS7zuFeeqsNyeTa9NjE066mGsvEFFNu/WPAXebr3hLE+vjPskr wpphZBaVNr2ddlTkDo0ZSpQteWCYwRe8pvJ/hzlmvb9lZs8ukd+QBVr0L1gAhzv4gL GWuGMYWxjcXVqJ43gLfEOx67qt4YmlN20/zX6URY= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas2p3.samsung.com (KnoxPortal) with ESMTP id 20220506063341epcas2p350432dd532c831e3b10dcc8cbaeb61ba~scHd0fdPb0340303403epcas2p3A; Fri, 6 May 2022 06:33:41 +0000 (GMT) Received: from epsmges2p4.samsung.com (unknown [182.195.36.101]) by epsnrtp2.localdomain (Postfix) with ESMTP id 4KvgkX1Zgbz4x9Q0; Fri, 6 May 2022 06:33:40 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p4.samsung.com (Symantec Messaging Gateway) with SMTP id 47.23.09694.441C4726; Fri, 6 May 2022 15:33:40 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p1.samsung.com (KnoxPortal) with ESMTPA id 20220506063339epcas2p1b94e823ab8b7974ac88fec9ea9c17109~scHbtJqjd2814728147epcas2p1B; Fri, 6 May 2022 06:33:39 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220506063339epsmtrp2d04be5075eb7648780f76c29e97a3dec~scHbrbqOL0488604886epsmtrp2G; Fri, 6 May 2022 06:33:39 +0000 (GMT) X-AuditID: b6c32a48-47fff700000025de-c3-6274c144b08e Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id 01.ED.08924.341C4726; Fri, 6 May 2022 15:33:39 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220506063339epsmtip289f88b7ce43971313c3e51b3a8fdee9a~scHbalUYJ0767807678epsmtip2K; Fri, 6 May 2022 06:33:39 +0000 (GMT) From: Daehwan Jung To: Felipe Balbi , Greg Kroah-Hartman , Krzysztof Kozlowski , Alim Akhtar , Mathias Nyman , Lukas Bulwahn , Tony Lindgren , Juergen Gross , Arnd Bergmann , Matthias Kaehlcke Cc: linux-kernel@vger.kernel.org (open list), linux-usb@vger.kernel.org (open list:DESIGNWARE USB3 DRD IP DRIVER), linux-arm-kernel@lists.infradead.org (moderated list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), linux-samsung-soc@vger.kernel.org (open list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), sc.suh@samsung.com, taehyun.cho@samsung.com, jh0801.jung@samsung.com, eomji.oh@samsung.com, Daehwan Jung Subject: [PATCH v5 4/6] usb: host: add some to xhci overrides for xhci-exynos Date: Fri, 6 May 2022 15:31:17 +0900 Message-Id: <1651818679-10594-5-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA0VTe1BUZRTvu3e5u5hL112ozx1nw+tYuQns0rJcE4zJTa+QRjmV4zhDV7g8 Zp/u3RVyKlACBCdCRgUWNV4igxiyrsRrY3htQIYmRqGAEExkBBlMiBDW7l6s/37nzO8x55zv E6CiekwiSNKbGZOe1hLYKl59x6bQAHWb+aD851ZvcvR8PUYu5zv5pDNzgk8OlZxByN6LpQiZ Xl6LkWcHg8nhsQUe6Zi6xidt4wNeZH/TWYwsvPE1QpZVZqDkp11ZPDLddsqLnLsyDsic4Z8A md/mR7bejowQU0uL+YCa/yufRxWnfc+jGq3DfKq85T5C2aqzMWpooAWjWs/V8KmrFalUrr0a ULX2H3jUnE0avXq/JiyRoeMYkz+jjzXEJekTwomovTHbY0JUckWAYgsZSvjraR0TTqjfjA7Y kaR1TUj4H6a1FlcrmmZZImhbmMlgMTP+iQbWHE4wxjitMdQYyNI61qJPCNQz5lcVcnlwiIv4 gSbxi2aZMcsnpaxtDEkDM0/nAG8BxJVwbKQcywGrBCK8AcDqod+9uGIWwAt3vlwp5gA892MX +kTSay/G3FiENwHY4dzNkRYAvN5010USCDBcBh+WAnffFy9AYU/NZ54MFO9BYX9LGd+tFuNv wUsPJj2Yh2+E90uXEDcW4m/A+s5HfC5NCgf7sj3J3vgOeOu03eMK8ZsC2PhtBXCnQVwNF217 OL4Y/vaNfUUrgXMzDozDLGyazUA4bRqAR0e7V8Z5BVp/yfL4oPgmWNsUxFlugJ13eG4GivvA 4x3LfK4thMczRZxwAyzoz/Pi8FrYNtW3YkjB+t5lwO2kCEDr9QWvPCC1/h9QAkA1eJYxsroE hg02Kv87WKxBZwOeByyjGkDx9IPAdoAIQDuAApTwFYqt5oMiYRz94RHGZIgxWbQM2w5CXLs7 iUr8Yg2uH6A3xyiUW+RKlUoRGhwiDyWeE0bGXaFFeAJtZjQMY2RMT3SIwFuShnQHPdWoG3j0 92FDwT3J/pPx7DHhvs+j/cB0TO5GYdihypmubsf5PodWXdl5+T1r6oTCvnn65ZCly2viLxWq H45v1qjI0RHbTLpl36/0UOx3b482l57e3hPo95XvR/mDKtO7vMyMT0aCTqyvem3bgYj13SMB jzsmkasZu05dKBHf+HP2yJ75uttRW5MtJ2RsUUOrsqtI+r7zgCy+IyVC98LR3XVR4sc7F6zr kiN3Pp96Zt3dY11VKQER0ol3mgueeX3toT61T16PpqT8Ws2LBX+MF/fL7u0FrdPJ0tzgwoqX pv5pGx+Y77uV7UxGGz+WL9bWaCaVq8VVdWtuXiS27nJEoionrid4bCKtkKEmlv4XgbR3HUkE AAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrILMWRmVeSWpSXmKPExsWy7bCSvK7zwZIkg623+S0ezNvGZvF30jF2 i2NtT9gt7iyYxmRxavlCJovmxevZLObcNLK4+/AHi8Xe11vZLTY9vsZqcXnXHDaLGef3MVks WtbKbNFytJ3FonnTFFaLzxseM1p03b3BaDHpoKjF/iteDsIev39NYvT49nUSi8fshossHjtn 3WX3WLznJZPHplWdbB53ru1h89g/dw27x+Yl9R59W1YxeqzfcpXF4/MmuQCeKC6blNSczLLU In27BK6M+bu1Ctr5KhYdfMjUwPiOu4uRk0NCwETi1JbZbF2MXBxCAjsYJSZdOs0IkZCUWDr3 BjuELSxxv+UIK0TRN0aJK58vAjkcHGwCWhLfF4LViwjMZZbYurUIpIZZ4CyzxJ+nq9lAEsIC vhIXXy8CG8QioCrxcuFvJhCbV8BVYtuRn1AL5CRunutkBrE5BdwkLk3dAjZUCKhm4Z/vzBMY +RYwMqxilEwtKM5Nzy02LDDKSy3XK07MLS7NS9dLzs/dxAiOFS2tHYx7Vn3QO8TIxMF4iFGC g1lJhFd4VkmSEG9KYmVValF+fFFpTmrxIUZpDhYlcd4LXSfjhQTSE0tSs1NTC1KLYLJMHJxS DUw12lfPbTCYJbpdxKRc1Oe1BQPvk9Mva8uPWQb9vtT04uXn71zCE6ZPWOkxSVbwXci0Rgaj Y1MuMFhqrTZ17NMvrpKeVa7e9G+F784XNzdkLZH77Lih+c8svuZpoXNMpucfWexWK1Z6iHdv 0reiumnC+asu7SkVMdx7OGza8auP170sv1pgJRNmWrHllfG04v8fgqJ89Nbcv5v59M/h+0Fv zddvfSj6L+QkY2/8TMMNS9u95+sLXI5TPFwZ7VD97fGm6cmTMjRXJ65uWzu5smzSzXk2bcvu uyRk8Gv5WWxKPDkht7OvOj5VfecF/pW9boKaaTcPzgsXvVGamrV89URRBpZWE6dQlv9C2ksa 2D4qsRRnJBpqMRcVJwIABvTKHAQDAAA= X-CMS-MailID: 20220506063339epcas2p1b94e823ab8b7974ac88fec9ea9c17109 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220506063339epcas2p1b94e823ab8b7974ac88fec9ea9c17109 References: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Co-processor needs some information about connected usb device. It's proper to pass information after usb device gets address when getting "Set Address" command. It supports vendors to implement it using xhci overrides. There're several power scenarios depending on vendors. It gives vendors flexibilty to meet their power requirement. They can override suspend and resume of root hub. Signed-off-by: Daehwan Jung --- drivers/usb/host/xhci.c | 6 ++++++ drivers/usb/host/xhci.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5ccf1bbe8732..8b3df1302650 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -5555,6 +5555,12 @@ void xhci_init_driver(struct hc_driver *drv, drv->check_bandwidth = over->check_bandwidth; if (over->reset_bandwidth) drv->reset_bandwidth = over->reset_bandwidth; + if (over->address_device) + drv->address_device = over->address_device; + if (over->bus_suspend) + drv->bus_suspend = over->bus_suspend; + if (over->bus_resume) + drv->bus_resume = over->bus_resume; } } EXPORT_SYMBOL_GPL(xhci_init_driver); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 5d356f40c2b9..ab74b24a13b3 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1947,6 +1947,9 @@ struct xhci_driver_overrides { struct usb_host_endpoint *ep); int (*check_bandwidth)(struct usb_hcd *, struct usb_device *); void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *); + int (*address_device)(struct usb_hcd *hcd, struct usb_device *udev); + int (*bus_suspend)(struct usb_hcd *hcd); + int (*bus_resume)(struct usb_hcd *hcd); }; #define XHCI_CFC_DELAY 10 From patchwork Fri May 6 06:31:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12840635 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5409C433EF for ; Fri, 6 May 2022 06:34:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1357882AbiEFGhs (ORCPT ); Fri, 6 May 2022 02:37:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59934 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355959AbiEFGhb (ORCPT ); Fri, 6 May 2022 02:37:31 -0400 Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ED6A765D35 for ; Thu, 5 May 2022 23:33:47 -0700 (PDT) Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20220506063346epoutp014930333238e653982f4fda2f19e69c39~scHiAYfT-1947419474epoutp01b for ; Fri, 6 May 2022 06:33:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20220506063346epoutp014930333238e653982f4fda2f19e69c39~scHiAYfT-1947419474epoutp01b DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1651818826; bh=IfKz3nJK9FEY9WTuvkeyNuhF9Ub+U+rwuEUUzi69DBI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rdRxILAep4y+PjQJPUL0uAtImGTMQq6jkcG864Evkr6ujy4i+eVTST8K00N12cbbU IBJ3WQpXQcXdO7Nd6Y5XGK85y364HvpAgYkrkizABzg4rmFpL9JHcHGrccvha+MAgb 4yDOOcXnAtlMg/Bn89VtVoaWBcolZz0O6xoTpeAg= Received: from epsnrtp3.localdomain (unknown [182.195.42.164]) by epcas2p4.samsung.com (KnoxPortal) with ESMTP id 20220506063345epcas2p45807103f833246ef4d846b54bf182a0c~scHhY5WUS0959509595epcas2p4L; Fri, 6 May 2022 06:33:45 +0000 (GMT) Received: from epsmges2p4.samsung.com (unknown [182.195.36.98]) by epsnrtp3.localdomain (Postfix) with ESMTP id 4KvgkY44chz4x9Q2; Fri, 6 May 2022 06:33:41 +0000 (GMT) Received: from epcas2p1.samsung.com ( [182.195.41.53]) by epsmges2p4.samsung.com (Symantec Messaging Gateway) with SMTP id A8.23.09694.441C4726; Fri, 6 May 2022 15:33:40 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p4.samsung.com (KnoxPortal) with ESMTPA id 20220506063339epcas2p41de479fb6b2d11012a45ac50ccc19a26~scHcI4J7A2345123451epcas2p4M; Fri, 6 May 2022 06:33:39 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20220506063339epsmtrp159bcdd0d7e5c4f9b10d3dddf8da1f49b~scHcHljTF3174331743epsmtrp1W; Fri, 6 May 2022 06:33:39 +0000 (GMT) X-AuditID: b6c32a48-47fff700000025de-c5-6274c144479d Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 9A.55.11276.341C4726; Fri, 6 May 2022 15:33:39 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220506063339epsmtip209f996e40c2376b1bf5072f3515c9140~scHb3i5hD0420504205epsmtip2h; Fri, 6 May 2022 06:33:39 +0000 (GMT) From: Daehwan Jung To: Felipe Balbi , Greg Kroah-Hartman , Krzysztof Kozlowski , Alim Akhtar , Mathias Nyman , Lukas Bulwahn , Tony Lindgren , Juergen Gross , Arnd Bergmann , Matthias Kaehlcke Cc: linux-kernel@vger.kernel.org (open list), linux-usb@vger.kernel.org (open list:DESIGNWARE USB3 DRD IP DRIVER), linux-arm-kernel@lists.infradead.org (moderated list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), linux-samsung-soc@vger.kernel.org (open list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), sc.suh@samsung.com, taehyun.cho@samsung.com, jh0801.jung@samsung.com, eomji.oh@samsung.com, Daehwan Jung Subject: [PATCH RFC v5 5/6] usb: host: add xhci-exynos driver Date: Fri, 6 May 2022 15:31:18 +0900 Message-Id: <1651818679-10594-6-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA0VTfVAUZRz23V1uF4drtjvUVyqCVUto7riDO1jwzpwRrx1sHKaanOoPWrkN GI6763bRcpwBkg9lFPBQgRMJRdRBCDsJiPiQQw8JQQJFKZhIjIEIJ4/4yKLiuLP+e34fz+/5 fbwvgUq+EQUQKUaBsxhZAyVaizV2hahlsZ3CPsXAbSk9XtEoopetTpx25j7C6dHK0wj97aVz CH24ql5El4+E02M/LWF028xXOG2fGPahh1rKRXTpnXaEPn8xB6Wzb+Zh9GH7SR967uoEoPPH HgDa2rmO7rgbt0PK/PnUCpiFeSvGnMn8DmO+to3hTFXrNMLYa46KmNHhVhHTcbYWZ65dyGAK GmoAU99wD2Pm7IHxfu+napI5Vs9ZgjhjokmfYkzSUrvfTtiZoI5UKGXKaDqKCjKyaZyWin0z XqZLMaxMSAXtZw3pK654luepsO0aiyld4IKSTbygpTiz3mCOMst5No1PNybJjZwQo1QowtUr iR+mJp9YzsbNtzvAJzbHHZ9MMHEW5ANfApIqaJ+dRfLBWkJCNgPYXHbaa7gAdOVeRD3GAoDF 9y8gzyjjFVcwT6ANwPqxbm/WEoDZxQN4PiAIERkKF88Bt9+fLEFhT+1xkdtAyR4UDrWex92l pKQWXi58tIoxcgv8rKB3VUJM7oKuxjofj1wgHOk/irqxL6mDg6caVqtCcoCAv/cXeceIhf/8 2od7sBT+0t3gxQFwujDXi3nY4spBPORMALPGb6GeQAS0TeYBd9soGQLrW8LcEJKb4I3vMXcG Sj4Hj3Qt4x63GB7JlXiIm2DJUJG3zY2wc6bfW5CBTY673g2VATh/rAspAoG2/wUqAagB6zkz n5bE8eFm1X9XSzSl2cHqKw5lmsGZ2d/kDoAQwAEggVL+YqlN2CcR69lPD3IWU4Il3cDxDqBe Wd4JNGBdomnlGxiFBKUqWqGKjFRGhasVUdQGcZz+Kishk1iBS+U4M2d5xkMI34BMJNMc0cq3 V/9RWiibvMHQ5W0/Oqdl3T5TuuEnGeSUPC/H/yB0aYPvO1Dr/Ehab3Ven0pTHB28vrrpeK+z rOdeSbwfPgpyBks+2Eodalcd2hm6IA+RrKn84frlHcV+ilL2+cmS7Q+bpPpJ2XuxCN8oF16d 31bFxO1W/5UsdulibunigpyqvuBXKnblvaNnFzUbXtvi/9LG3r+V+j1Cv5l5+OXT2oVT+FsV B36OGEzQvLBtr/xxzXz0lWsG7KMvsgae3HyxM/Kxqp95d/FB8Jpj4VEaTvfGlHr/1PjH6Vlb 65iJA9fnMmLrnK9/ToS1zLRie2sEpndJOxdSELPHtrni5VEK45NZZShq4dl/ASB6DXNOBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrELMWRmVeSWpSXmKPExsWy7bCSvK7zwZIkg3W79CwezNvGZvF30jF2 i2NtT9gt7iyYxmRxavlCJovmxevZLObcNLK4+/AHi8Xe11vZLTY9vsZqcXnXHDaLGef3MVks WtbKbNFytJ3FonnTFFaLzxseM1p03b3BaDHpoKjF/iteDsIev39NYvT49nUSi8fshossHjtn 3WX3WLznJZPHplWdbB53ru1h89g/dw27x+Yl9R59W1YxeqzfcpXF4/MmuQCeKC6blNSczLLU In27BK6MiX9b2AvO7GesmHXoPGsD4+O5jF2MnBwSAiYSD+atZgGxhQR2M0qsb86EiEtKLJ17 gx3CFpa433KEFaLmG6PEshPpXYwcHGwCWhLfF4KNERGYyyyxdWtRFyMXB7PAWWaJP09Xs4Ek hAVsJVb0PwGbwyKgKtHUd5oJxOYVcJX4tG0tK8R8OYmb5zqZQWxOATeJS1O3MELscpVY+Oc7 8wRGvgWMDKsYJVMLinPTc4sNCwzzUsv1ihNzi0vz0vWS83M3MYKjRUtzB+P2VR/0DjEycTAe YpTgYFYS4RWeVZIkxJuSWFmVWpQfX1Sak1p8iFGag0VJnPdC18l4IYH0xJLU7NTUgtQimCwT B6dUA9MUIz6Lj6UVC2QNWU+9XJV6zb5WIPahkq/1ec6ju6/MXF9THGJpXHFyQ7c63+uAx1JT O+ZWFGjv0LnxPDNE5lzgIe6vBTGfjG4ETfx13bXAK1vW7EWu1p91Ga/XviutXFHNuN+eoXGm Y4k8G2vJlVddmWda1y/b+6YtWyXbPKt2V1XGSp9z/oUGk/NDTrCtl/r3mWVNBceS/MXXtvy+ Hy/ZzrXmyF7V+Gk3/r07EfThbEz/hnVbrSpcc375ud6//7pDv/P69+WC5cddPt25ZJYglc/V f7P7qH7rjuqgpyG9a1ijnUtqsief9E+eW7zjyAdjK+E20xuOvQwfvarfnnIy8Z+jNUlnnzm/ 1cxJC5VYijMSDbWYi4oTASLvPKQFAwAA X-CMS-MailID: 20220506063339epcas2p41de479fb6b2d11012a45ac50ccc19a26 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220506063339epcas2p41de479fb6b2d11012a45ac50ccc19a26 References: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This driver is for Samsung Exynos xHCI host conroller. It works based on xhci platform driver and extends functions by xhci hooks and overrides. Vendor ops(xhci hooks) should be mapped before probing driver. It overrides functions of hc driver on vendor init. It supports USB Audio offload with Co-processor. It only cares DCBAA, Device Context, Transfer Ring, Event Ring, and ERST. They are allocated on specific address with xhci hooks. Co-processor could use them directly without xhci driver after then. Signed-off-by: Daehwan Jung --- drivers/usb/host/Kconfig | 8 + drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-exynos.c | 775 +++++++++++++++++++++++++++++++++ 3 files changed, 784 insertions(+) create mode 100644 drivers/usb/host/xhci-exynos.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 682b3d2da623..ccafcd9b4212 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -104,6 +104,14 @@ config USB_XHCI_TEGRA Say 'Y' to enable the support for the xHCI host controller found in NVIDIA Tegra124 and later SoCs. +config USB_XHCI_EXYNOS + tristate "xHCI support for Samsung Exynos SoC Series" + depends on USB_XHCI_PLATFORM + depends on ARCH_EXYNOS || COMPILE_TEST + help + Say 'Y' to enable the support for the xHCI host controller + found in Samsung Exynos SoCs. + endif # USB_XHCI_HCD config USB_EHCI_BRCMSTB diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 2948983618fb..300f22b6eb1b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -86,3 +86,4 @@ obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o obj-$(CONFIG_USB_MAX3421_HCD) += max3421-hcd.o obj-$(CONFIG_USB_XEN_HCD) += xen-hcd.o +obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos.o diff --git a/drivers/usb/host/xhci-exynos.c b/drivers/usb/host/xhci-exynos.c new file mode 100644 index 000000000000..5318a51ac5ee --- /dev/null +++ b/drivers/usb/host/xhci-exynos.c @@ -0,0 +1,775 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * xhci-exynos.c - xHCI host controller driver platform Bus Glue for Exynos. + * + * Copyright (C) 2022 Samsung Electronics Incorporated - http://www.samsung.com + * Author: Daehwan Jung + * + * A lot of code borrowed from the Linux xHCI driver. + */ +#include +#include + +#include "xhci.h" +#include "xhci-plat.h" + +/* EXYNOS uram memory map */ +#define EXYNOS_URAM_ABOX_EVT_RING_ADDR 0x02a00000 +#define EXYNOS_URAM_ISOC_OUT_RING_ADDR 0x02a01000 +#define EXYNOS_URAM_ISOC_IN_RING_ADDR 0x02a02000 +#define EXYNOS_URAM_DEVICE_CTX_ADDR 0x02a03000 +#define EXYNOS_URAM_DCBAA_ADDR 0x02a03880 +#define EXYNOS_URAM_ABOX_ERST_SEG_ADDR 0x02a03C80 +#define EXYNOS_URAM_CTX_SIZE 2112 + +int xhci_exynos_register_vendor_ops(void); + +struct xhci_hcd_exynos { + struct xhci_intr_reg __iomem *ir_set_audio; + + struct xhci_ring *event_ring_audio; + struct xhci_erst erst_audio; + + struct device *dev; + struct usb_hcd *hcd; + struct usb_hcd *shared_hcd; + + struct wakeup_source *main_wakelock; /* Wakelock for HS HCD */ + struct wakeup_source *shared_wakelock; /* Wakelock for SS HCD */ + + u32 in_ep; + u32 out_ep; + u32 in_deq; + u32 out_deq; + + /* This flag is used to check first allocation for URAM */ + bool exynos_uram_ctx_alloc; + bool exynos_uram_isoc_out_alloc; + bool exynos_uram_isoc_in_alloc; + + unsigned long long quirks; +}; + +static const struct dev_pm_ops xhci_exynos_pm_ops; + +static struct xhci_vendor_ops ops; +static void xhci_exynos_parse_endpoint(struct xhci_hcd *xhci, struct usb_device *udev, + struct usb_endpoint_descriptor *desc, struct xhci_container_ctx *ctx); +static void xhci_exynos_free_event_ring(struct xhci_hcd *xhci); +static struct xhci_segment *xhci_segment_alloc_uram_ep(struct xhci_hcd *xhci, + unsigned int cycle_state, + unsigned int max_packet, + gfp_t flags, int seg_num, + u32 endpoint_type); +static struct xhci_ring *xhci_ring_alloc_uram(struct xhci_hcd *xhci, + unsigned int num_segs, unsigned int cycle_state, + enum xhci_ring_type type, unsigned int max_packet, gfp_t flags, + u32 endpoint_type); +static void xhci_exynos_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring); +static int xhci_exynos_alloc_event_ring(struct xhci_hcd *xhci, gfp_t flags); + +int xhci_exynos_register_vendor_ops(void) +{ + return xhci_plat_register_vendor_ops(&ops); +} +EXPORT_SYMBOL_GPL(xhci_exynos_register_vendor_ops); + +static void xhci_exynos_quirks(struct device *dev, struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + xhci->quirks |= XHCI_PLAT | xhci_exynos->quirks; +} + +/* called during probe() after chip reset completes */ +static int xhci_exynos_setup(struct usb_hcd *hcd) +{ + int ret; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + ret = xhci_gen_setup(hcd, xhci_exynos_quirks); + xhci_exynos_alloc_event_ring(xhci, GFP_KERNEL); + + return ret; +} + +static void xhci_exynos_usb_offload_enable_event_ring(struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + u32 temp; + u64 temp_64; + + temp_64 = xhci_read_64(xhci, &xhci_exynos->ir_set_audio->erst_dequeue); + temp_64 &= ~ERST_PTR_MASK; + xhci_info(xhci, "ERST2 deq = 64'h%0lx", (unsigned long) temp_64); + + xhci_info(xhci, "// [USB Audio] Set the interrupt modulation register"); + temp = readl(&xhci_exynos->ir_set_audio->irq_control); + temp &= ~ER_IRQ_INTERVAL_MASK; + temp |= (u32)160; + writel(temp, &xhci_exynos->ir_set_audio->irq_control); + + temp = readl(&xhci_exynos->ir_set_audio->irq_pending); + xhci_info(xhci, "// [USB Audio] Enabling event ring interrupter %p by writing 0x%x to irq_pending", + xhci_exynos->ir_set_audio, (unsigned int) ER_IRQ_ENABLE(temp)); + writel(ER_IRQ_ENABLE(temp), &xhci_exynos->ir_set_audio->irq_pending); +} + +static int xhci_exynos_start(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci; + int ret; + + ret = xhci_run(hcd); + + xhci = hcd_to_xhci(hcd); + xhci_exynos_usb_offload_enable_event_ring(xhci); + + return ret; +} + +static int xhci_exynos_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + int ret; + struct xhci_hcd *xhci; + struct xhci_virt_device *virt_dev; + + ret = xhci_add_endpoint(hcd, udev, ep); + + if (!ret && udev->slot_id) { + xhci = hcd_to_xhci(hcd); + virt_dev = xhci->devs[udev->slot_id]; + xhci_exynos_parse_endpoint(xhci, udev, &ep->desc, virt_dev->out_ctx); + } + + return ret; +} + +static int xhci_exynos_address_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + int ret; + + ret = xhci_address_device(hcd, udev); + + /* TODO: store and pass hw info to Co-Processor here*/ + + return ret; +} + +static int xhci_exynos_wake_lock(struct xhci_hcd_exynos *xhci_exynos, + int is_main_hcd, int is_lock) +{ + struct usb_hcd *hcd = xhci_exynos->hcd; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct wakeup_source *main_wakelock, *shared_wakelock; + + main_wakelock = xhci_exynos->main_wakelock; + shared_wakelock = xhci_exynos->shared_wakelock; + + if (xhci->xhc_state & XHCI_STATE_REMOVING) + return -ESHUTDOWN; + + if (is_lock) { + if (is_main_hcd) + __pm_stay_awake(main_wakelock); + else + __pm_stay_awake(shared_wakelock); + } else { + if (is_main_hcd) + __pm_relax(main_wakelock); + else + __pm_relax(shared_wakelock); + } + + return 0; +} + +static int xhci_exynos_bus_suspend(struct usb_hcd *hcd) +{ + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + + int ret, main_hcd; + + if (hcd == xhci->main_hcd) + main_hcd = 1; + else + main_hcd = 0; + + ret = xhci_bus_suspend(hcd); + xhci_exynos_wake_lock(xhci_exynos, main_hcd, 0); + + return ret; +} + +static int xhci_exynos_bus_resume(struct usb_hcd *hcd) +{ + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + int ret, main_hcd; + + if (hcd == xhci->main_hcd) + main_hcd = 1; + else + main_hcd = 0; + + ret = xhci_bus_resume(hcd); + xhci_exynos_wake_lock(xhci_exynos, main_hcd, 1); + + return ret; +} + +const struct xhci_driver_overrides xhci_exynos_overrides = { + .reset = xhci_exynos_setup, + .start = xhci_exynos_start, + .add_endpoint = xhci_exynos_add_endpoint, + .address_device = xhci_exynos_address_device, + .bus_suspend = xhci_exynos_bus_suspend, + .bus_resume = xhci_exynos_bus_resume, +}; + +static int xhci_exynos_vendor_init(struct xhci_hcd *xhci, struct device *dev) +{ + struct usb_hcd *hcd; + struct xhci_hcd_exynos *xhci_exynos; + struct xhci_plat_priv *priv; + struct wakeup_source *main_wakelock, *shared_wakelock; + + xhci_plat_override_driver(&xhci_exynos_overrides); + dev->driver->pm = &xhci_exynos_pm_ops; + + main_wakelock = wakeup_source_register(dev, dev_name(dev)); + __pm_stay_awake(main_wakelock); + + /* Initialization shared wakelock for SS HCD */ + shared_wakelock = wakeup_source_register(dev, dev_name(dev)); + __pm_stay_awake(shared_wakelock); + + hcd = xhci->main_hcd; + + priv = hcd_to_xhci_priv(hcd); + xhci_exynos = priv->vendor_priv; + xhci_exynos->dev = dev; + xhci_exynos->main_wakelock = main_wakelock; + xhci_exynos->shared_wakelock = shared_wakelock; + + return 0; +} + +static void xhci_exynos_vendor_cleanup(struct xhci_hcd *xhci) +{ + xhci_exynos_free_event_ring(xhci); +} + +static bool xhci_exynos_is_usb_offload_enabled(struct xhci_hcd *xhci, + struct xhci_virt_device *virt_dev, unsigned int ep_index) +{ + /* TODO */ + return true; +} + +static struct xhci_device_context_array *xhci_exynos_alloc_dcbaa( + struct xhci_hcd *xhci, gfp_t flags) +{ + int i; + + xhci->dcbaa = ioremap(EXYNOS_URAM_DCBAA_ADDR, + sizeof(*xhci->dcbaa)); + if (!xhci->dcbaa) + return NULL; + /* Clear DCBAA */ + for (i = 0; i < MAX_HC_SLOTS; i++) + xhci->dcbaa->dev_context_ptrs[i] = 0x0; + + xhci->dcbaa->dma = EXYNOS_URAM_DCBAA_ADDR; + + return xhci->dcbaa; +} + +static void xhci_exynos_free_dcbaa(struct xhci_hcd *xhci) +{ + iounmap(xhci->dcbaa); + xhci->dcbaa = NULL; +} + +static struct xhci_ring *xhci_exynos_alloc_transfer_ring(struct xhci_hcd *xhci, u32 endpoint_type, + enum xhci_ring_type ring_type, unsigned int max_packet, gfp_t mem_flags) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + /* If URAM is not allocated, it try to allocate from URAM */ + if (xhci_exynos->exynos_uram_isoc_out_alloc == 0 && endpoint_type == ISOC_OUT_EP) { + xhci_exynos->exynos_uram_isoc_out_alloc = 1; + return xhci_ring_alloc_uram(xhci, 1, 1, ring_type, max_packet, mem_flags, + endpoint_type); + } else if (xhci_exynos->exynos_uram_isoc_in_alloc == 0 && endpoint_type == ISOC_IN_EP) { + xhci_exynos->exynos_uram_isoc_in_alloc = 1; + return xhci_ring_alloc_uram(xhci, 1, 1, ring_type, max_packet, mem_flags, + endpoint_type); + } else + return xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags); +} + +static void xhci_exynos_free_transfer_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, + unsigned int ep_index) +{ + xhci_exynos_ring_free(xhci, ring); +} + +static void xhci_exynos_alloc_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, + int type, gfp_t flags) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + if (type != XHCI_CTX_TYPE_INPUT && xhci_exynos->exynos_uram_ctx_alloc == 0) { + /* Only first Device Context uses URAM */ + int i; + + ctx->bytes = ioremap(EXYNOS_URAM_DEVICE_CTX_ADDR, EXYNOS_URAM_CTX_SIZE); + if (!ctx->bytes) + return; + + for (i = 0; i < EXYNOS_URAM_CTX_SIZE; i++) + ctx->bytes[i] = 0; + + ctx->dma = EXYNOS_URAM_DEVICE_CTX_ADDR; + + xhci_exynos->exynos_uram_ctx_alloc = 1; + } else { + ctx->bytes = dma_pool_zalloc(xhci->device_pool, flags, &ctx->dma); + if (!ctx->bytes) + return; + } +} + +static void xhci_exynos_free_container_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) +{ + /* Ignore dma_pool_free if it is allocated from URAM */ + if (ctx->dma != EXYNOS_URAM_DEVICE_CTX_ADDR) + dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma); +} + +static int xhci_exynos_sync_dev_ctx(struct xhci_hcd *xhci, unsigned int slot_id) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct xhci_virt_device *virt_dev; + struct xhci_slot_ctx *slot_ctx; + + int i; + int last_ep; + int last_ep_ctx = 31; + + virt_dev = xhci->devs[slot_id]; + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); + + last_ep = LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)); + + if (last_ep < 31) + last_ep_ctx = last_ep + 1; + + for (i = 0; i < last_ep_ctx; ++i) { + unsigned int epaddr = xhci_get_endpoint_address(i); + struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->out_ctx, i); + + if (epaddr == xhci_exynos->in_ep) + xhci_exynos->in_deq = ep_ctx->deq; + else if (epaddr == xhci_exynos->out_ep) + xhci_exynos->out_deq = ep_ctx->deq; + } + + return 0; +} +static struct xhci_vendor_ops ops = { + .vendor_init = xhci_exynos_vendor_init, + .vendor_cleanup = xhci_exynos_vendor_cleanup, + .is_usb_offload_enabled = xhci_exynos_is_usb_offload_enabled, + .alloc_dcbaa = xhci_exynos_alloc_dcbaa, + .free_dcbaa = xhci_exynos_free_dcbaa, + .alloc_transfer_ring = xhci_exynos_alloc_transfer_ring, + .free_transfer_ring = xhci_exynos_free_transfer_ring, + .alloc_container_ctx = xhci_exynos_alloc_container_ctx, + .free_container_ctx = xhci_exynos_free_container_ctx, + .sync_dev_ctx = xhci_exynos_sync_dev_ctx, +}; + + +static void xhci_exynos_parse_endpoint(struct xhci_hcd *xhci, struct usb_device *udev, + struct usb_endpoint_descriptor *desc, struct xhci_container_ctx *ctx) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + struct usb_endpoint_descriptor *d = desc; + + if ((d->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC) { + if (d->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + xhci_exynos->in_ep = d->bEndpointAddress; + else + xhci_exynos->out_ep = d->bEndpointAddress; + } +} + +static void xhci_exynos_segment_free_skip(struct xhci_hcd *xhci, struct xhci_segment *seg) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + if (seg->trbs) { + /* Check URAM address for memory free */ + if (seg->dma == EXYNOS_URAM_ABOX_EVT_RING_ADDR) { + iounmap(seg->trbs); + } else if (seg->dma == EXYNOS_URAM_ISOC_OUT_RING_ADDR) { + xhci_exynos->exynos_uram_isoc_out_alloc = 0; + iounmap(seg->trbs); + } else if (seg->dma == EXYNOS_URAM_ISOC_IN_RING_ADDR) { + xhci_exynos->exynos_uram_isoc_in_alloc = 0; + iounmap(seg->trbs); + } else + dma_pool_free(xhci->segment_pool, seg->trbs, seg->dma); + + seg->trbs = NULL; + } + kfree(seg->bounce_buf); + kfree(seg); +} + +static void xhci_exynos_free_segments_for_ring(struct xhci_hcd *xhci, + struct xhci_segment *first) +{ + struct xhci_segment *seg; + + seg = first->next; + + while (seg != first) { + struct xhci_segment *next = seg->next; + + xhci_exynos_segment_free_skip(xhci, seg); + seg = next; + } + xhci_exynos_segment_free_skip(xhci, first); +} + +static void xhci_exynos_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) +{ + if (!ring) + return; + + if (ring->first_seg) { + if (ring->type == TYPE_STREAM) + xhci_remove_stream_mapping(ring); + + xhci_exynos_free_segments_for_ring(xhci, ring->first_seg); + } + + kfree(ring); +} + +static void xhci_exynos_free_event_ring(struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + xhci_exynos_ring_free(xhci, xhci_exynos->event_ring_audio); +} + +static void xhci_exynos_set_hc_event_deq_audio(struct xhci_hcd *xhci) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + u64 temp; + dma_addr_t deq; + + deq = xhci_trb_virt_to_dma(xhci_exynos->event_ring_audio->deq_seg, + xhci_exynos->event_ring_audio->dequeue); + if (deq == 0 && !in_interrupt()) + xhci_warn(xhci, "WARN something wrong with SW event ring " + "dequeue ptr.\n"); + /* Update HC event ring dequeue pointer */ + temp = xhci_read_64(xhci, &xhci_exynos->ir_set_audio->erst_dequeue); + temp &= ERST_PTR_MASK; + /* Don't clear the EHB bit (which is RW1C) because + * there might be more events to service. + */ + temp &= ~ERST_EHB; + xhci_info(xhci, "//[%s] Write event ring dequeue pointer = 0x%llx, " + "preserving EHB bit", __func__, + ((u64) deq & (u64) ~ERST_PTR_MASK) | temp); + xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, + &xhci_exynos->ir_set_audio->erst_dequeue); + +} + + + +static int xhci_exynos_alloc_event_ring(struct xhci_hcd *xhci, gfp_t flags) +{ + struct xhci_plat_priv *priv = xhci_to_priv(xhci); + struct xhci_hcd_exynos *xhci_exynos = priv->vendor_priv; + + if (xhci_check_trb_in_td_math(xhci) < 0) + goto fail; + + xhci_exynos->event_ring_audio = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, + TYPE_EVENT, 0, flags); + /* Set the event ring dequeue address */ + xhci_exynos_set_hc_event_deq_audio(xhci); + + return 0; +fail: + return -1; +} + +static struct xhci_segment *xhci_segment_alloc_uram(struct xhci_hcd *xhci, + unsigned int cycle_state, + unsigned int max_packet, + gfp_t flags) +{ + struct xhci_segment *seg; + dma_addr_t dma; + int i; + struct device *dev = xhci_to_hcd(xhci)->self.sysdev; + + seg = kzalloc_node(sizeof(*seg), flags, dev_to_node(dev)); + if (!seg) + return NULL; + + seg->trbs = ioremap(EXYNOS_URAM_ABOX_EVT_RING_ADDR, TRB_SEGMENT_SIZE); + if (!seg->trbs) + return NULL; + + dma = EXYNOS_URAM_ABOX_EVT_RING_ADDR; + + if (max_packet) { + seg->bounce_buf = kzalloc_node(max_packet, flags, + dev_to_node(dev)); + if (!seg->bounce_buf) { + dma_pool_free(xhci->segment_pool, seg->trbs, dma); + kfree(seg); + return NULL; + } + } + /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */ + if (cycle_state == 0) { + for (i = 0; i < TRBS_PER_SEGMENT; i++) + seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE); + } + seg->dma = dma; + seg->next = NULL; + + return seg; +} + +static struct xhci_segment *xhci_segment_alloc_uram_ep(struct xhci_hcd *xhci, + unsigned int cycle_state, + unsigned int max_packet, + gfp_t flags, int seg_num, + u32 endpoint_type) +{ + struct xhci_segment *seg; + dma_addr_t dma; + int i; + struct device *dev = xhci_to_hcd(xhci)->self.sysdev; + + seg = kzalloc_node(sizeof(*seg), flags, dev_to_node(dev)); + if (!seg) + return NULL; + + if (seg_num != 0) { + /* Support just one segment */ + xhci_err(xhci, "%s : Unexpected SEG NUMBER!\n", __func__); + return NULL; + } + + if (endpoint_type == ISOC_OUT_EP) { + seg->trbs = ioremap(EXYNOS_URAM_ISOC_OUT_RING_ADDR, + TRB_SEGMENT_SIZE); + if (!seg->trbs) + return NULL; + + dma = EXYNOS_URAM_ISOC_OUT_RING_ADDR; + } else if (endpoint_type == ISOC_IN_EP) { + seg->trbs = ioremap(EXYNOS_URAM_ISOC_IN_RING_ADDR, + TRB_SEGMENT_SIZE); + if (!seg->trbs) + return NULL; + + dma = EXYNOS_URAM_ISOC_IN_RING_ADDR; + } else { + xhci_err(xhci, "%s : Unexpected EP Type!\n", __func__); + return NULL; + } + + for (i = 0; i < 256; i++) { + seg->trbs[i].link.segment_ptr = 0; + seg->trbs[i].link.intr_target = 0; + seg->trbs[i].link.control = 0; + } + + + if (max_packet) { + seg->bounce_buf = kzalloc_node(max_packet, flags, + dev_to_node(dev)); + if (!seg->bounce_buf) { + dma_pool_free(xhci->segment_pool, seg->trbs, dma); + kfree(seg); + return NULL; + } + } + /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */ + if (cycle_state == 0) { + for (i = 0; i < TRBS_PER_SEGMENT; i++) + seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE); + } + seg->dma = dma; + seg->next = NULL; + + return seg; +} + +static int xhci_alloc_segments_for_ring_uram(struct xhci_hcd *xhci, + struct xhci_segment **first, struct xhci_segment **last, + unsigned int num_segs, unsigned int cycle_state, + enum xhci_ring_type type, unsigned int max_packet, gfp_t flags, + u32 endpoint_type) +{ + struct xhci_segment *prev; + bool chain_links = false; + + if (type == TYPE_ISOC) { + prev = xhci_segment_alloc_uram_ep(xhci, cycle_state, + max_packet, flags, 0, + endpoint_type); + } else if (type == TYPE_EVENT) { + prev = xhci_segment_alloc_uram(xhci, cycle_state, max_packet, flags); + } else { + xhci_err(xhci, "Unexpected TYPE for URAM allocation!\n"); + return -ENOMEM; + } + + if (!prev) + return -ENOMEM; + num_segs--; + + *first = prev; + while (num_segs > 0) { + struct xhci_segment *next = NULL; + + if (type == TYPE_ISOC) { + prev = xhci_segment_alloc_uram_ep(xhci, cycle_state, + max_packet, flags, 1, + endpoint_type); + } else if (type == TYPE_EVENT) { + next = xhci_segment_alloc_uram(xhci, cycle_state, + max_packet, flags); + } else { + xhci_err(xhci, "Unexpected TYPE for URAM alloc(multi)!\n"); + return -ENOMEM; + } + + if (!next) { + prev = *first; + while (prev) { + next = prev->next; + xhci_segment_free(xhci, prev); + prev = next; + } + return -ENOMEM; + } + xhci_link_segments(prev, next, type, chain_links); + + prev = next; + num_segs--; + } + xhci_link_segments(prev, *first, type, chain_links); + *last = prev; + + return 0; +} + +static struct xhci_ring *xhci_ring_alloc_uram(struct xhci_hcd *xhci, + unsigned int num_segs, unsigned int cycle_state, + enum xhci_ring_type type, unsigned int max_packet, gfp_t flags, + u32 endpoint_type) +{ + struct xhci_ring *ring; + int ret; + struct device *dev = xhci_to_hcd(xhci)->self.sysdev; + + ring = kzalloc_node(sizeof(*ring), flags, dev_to_node(dev)); + if (!ring) + return NULL; + + ring->num_segs = num_segs; + ring->bounce_buf_len = max_packet; + INIT_LIST_HEAD(&ring->td_list); + ring->type = type; + if (num_segs == 0) + return ring; + + ret = xhci_alloc_segments_for_ring_uram(xhci, &ring->first_seg, + &ring->last_seg, num_segs, cycle_state, type, + max_packet, flags, endpoint_type); + if (ret) + goto fail; + + /* Only event ring does not use link TRB */ + if (type != TYPE_EVENT) { + /* See section 4.9.2.1 and 6.4.4.1 */ + ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |= + cpu_to_le32(LINK_TOGGLE); + } + xhci_initialize_ring_info(ring, cycle_state); + + return ring; + +fail: + kfree(ring); + return NULL; +} + +static int xhci_exynos_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + /* TODO: AP sleep scenario*/ + + return xhci_suspend(xhci, device_may_wakeup(dev)); +} + +static int xhci_exynos_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int ret; + + /* TODO: AP resume scenario*/ + + ret = xhci_resume(xhci, 0); + if (ret) + return ret; + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; +} + +static const struct dev_pm_ops xhci_exynos_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(xhci_exynos_suspend, xhci_exynos_resume) +}; + +MODULE_DESCRIPTION("xHCI Exynos Host Controller Driver"); +MODULE_LICENSE("GPL"); From patchwork Fri May 6 06:31:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jung Daehwan X-Patchwork-Id: 12840634 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD37BC433F5 for ; Fri, 6 May 2022 06:34:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380576AbiEFGhp (ORCPT ); Fri, 6 May 2022 02:37:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352175AbiEFGha (ORCPT ); Fri, 6 May 2022 02:37:30 -0400 Received: from mailout2.samsung.com (mailout2.samsung.com [203.254.224.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A78E66202 for ; Thu, 5 May 2022 23:33:48 -0700 (PDT) Received: from epcas2p1.samsung.com (unknown [182.195.41.53]) by mailout2.samsung.com (KnoxPortal) with ESMTP id 20220506063346epoutp02538118954d7f0e0515ff5f24ebc0bcd9~scHiFrOGP1115411154epoutp02H for ; Fri, 6 May 2022 06:33:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.samsung.com 20220506063346epoutp02538118954d7f0e0515ff5f24ebc0bcd9~scHiFrOGP1115411154epoutp02H DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1651818826; bh=a4Ha8wEr3wq1zSlLNuAyl1253SWX0FU94jcVWiTwflM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NyIxckSjT3QDkDuUVthcZjfp43rZ17kRDyX/9WuwUiylymt5YTJTmjYO4YJ8F29pJ A6qVyzKDnyh40wOe1vAjqP+W1EgkMyxpSukdbj+3EOo9FbfiA+aKVleDkJ0PqBRLdJ s7JEnLdOVh/Dc1TWsaINqAgfEz1lALt5/hb8ZJds= Received: from epsnrtp3.localdomain (unknown [182.195.42.164]) by epcas2p2.samsung.com (KnoxPortal) with ESMTP id 20220506063345epcas2p221a69de6758e82525668975853da6cf8~scHhh1sU_1423714237epcas2p2H; Fri, 6 May 2022 06:33:45 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.36.88]) by epsnrtp3.localdomain (Postfix) with ESMTP id 4KvgkY08TBz4x9Px; Fri, 6 May 2022 06:33:41 +0000 (GMT) Received: from epcas2p2.samsung.com ( [182.195.41.54]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id DF.41.10069.441C4726; Fri, 6 May 2022 15:33:40 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p4.samsung.com (KnoxPortal) with ESMTPA id 20220506063340epcas2p4c9d88670f9be952f3637e3a545a7d1da~scHcnp9i71119911199epcas2p4j; Fri, 6 May 2022 06:33:40 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220506063340epsmtrp28eaa0984bb745a087836f8a1472067ba~scHcmjYem0438604386epsmtrp2Y; Fri, 6 May 2022 06:33:40 +0000 (GMT) X-AuditID: b6c32a45-a8fff70000002755-62-6274c144fcf0 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id EB.55.11276.441C4726; Fri, 6 May 2022 15:33:40 +0900 (KST) Received: from ubuntu.dsn.sec.samsung.com (unknown [10.229.95.128]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20220506063340epsmtip2baa6570955d62dfa934b8183334829ba~scHcZxRzm0642406424epsmtip2D; Fri, 6 May 2022 06:33:40 +0000 (GMT) From: Daehwan Jung To: Felipe Balbi , Greg Kroah-Hartman , Krzysztof Kozlowski , Alim Akhtar , Mathias Nyman , Lukas Bulwahn , Tony Lindgren , Juergen Gross , Arnd Bergmann , Matthias Kaehlcke Cc: linux-kernel@vger.kernel.org (open list), linux-usb@vger.kernel.org (open list:DESIGNWARE USB3 DRD IP DRIVER), linux-arm-kernel@lists.infradead.org (moderated list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), linux-samsung-soc@vger.kernel.org (open list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES), sc.suh@samsung.com, taehyun.cho@samsung.com, jh0801.jung@samsung.com, eomji.oh@samsung.com, Daehwan Jung Subject: [PATCH RFC v5 6/6] usb: dwc3: dwc3-exynos: add host init Date: Fri, 6 May 2022 15:31:19 +0900 Message-Id: <1651818679-10594-7-git-send-email-dh10.jung@samsung.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrOJsWRmVeSWpSXmKPExsWy7bCmma7LwZIkg76ZVhYP5m1js/g76Ri7 xbG2J+wWdxZMY7I4tXwhk0Xz4vVsFnNuGlncffiDxWLv663sFpseX2O1uLxrDpvFjPP7mCwW LWtltmg52s5i0bxpCqvF5w2PGS267t5gtJh0UNRi/xUvB2GP378mMXp8+zqJxWN2w0UWj52z 7rJ7LN7zkslj06pONo871/aweeyfu4bdY/OSeo++LasYPdZvucri8XmTXABPVLZNRmpiSmqR Qmpecn5KZl66rZJ3cLxzvKmZgaGuoaWFuZJCXmJuqq2Si0+ArltmDtCHSgpliTmlQKGAxOJi JX07m6L80pJUhYz84hJbpdSClJwC8wK94sTc4tK8dL281BIrQwMDI1OgwoTsjKari9kLWpQq XlxuYW9gbJLpYuTkkBAwkeg51sTYxcjFISSwg1Hi2ukjzBDOJ0aJXbs3soNUCQl8Y5R49b0Q puPohpssEEV7GSVWXfrBCuH8YJRYP+UZWxcjBwebgJbE94VgY0UEpjNLnFzTywbiMAucZJa4 vGcRO0iRsICjxPKNvCBTWQRUJaa0bmUCsXkFXCXen2xnh9gmJ3HzXCcziM0p4CZxaeoWsKES Ahc4JJbdvcUKUeQi0fFkDhOELSzx6vgWqGYpic/v9rJB2MUSuz61MkE0NzBKND44wQyRMJaY 9aydEeQgZgFNifW79EFMCQFliSO3WEAqmAX4JDoO/2WHCPNKdLQJQTQqS0y/PAHqAkmJg6/P QQ30kPj2aCs0SGcySiz/uYJ9AqPcLIQFCxgZVzGKpRYU56anFhsVGMJjLDk/dxMjOAVrue5g nPz2g94hRiYOxkOMEhzMSiK8wrNKkoR4UxIrq1KL8uOLSnNSiw8xmgIDbyKzlGhyPjAL5JXE G5pYGpiYmRmaG5kamCuJ83qlbEgUEkhPLEnNTk0tSC2C6WPi4JRqYBK37CjYEJDjN9UtaNfC L/FaqyImbisK7xLuyZ+vfcf7e/EZkxzF/BOBrm/qzZw+f9t8OUSZ3+6P5zbGL2e09N/rTDs2 08dp5TwVaaXpGqcLBEImfi6webYm8eGMNDWjp5of3gtPWTvnPUtqWb290axt81fXmWxaflfw z+TXa+ZX8rtP+Wb+1MLrw5o2Tl4j+ZulqklJXAvPv+t8Pstd5eD/ldacX2+vvTpjduaD5GyV kl1NfltWrUjPqL7/Uj49xjFPzCvyXe/eP02TLpfxG3gsvyoWeaFkA7/4vEvR/artpxzEFes0 G3tPqq4zc70qxc1fLbdnzyVN9V3lW+Zc5cs+w8P+dr3h5809vflf/ZVYijMSDbWYi4oTAWfq 8rdKBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrILMWRmVeSWpSXmKPExsWy7bCSvK7LwZIkgwtfBC0ezNvGZvF30jF2 i2NtT9gt7iyYxmRxavlCJovmxevZLObcNLK4+/AHi8Xe11vZLTY9vsZqcXnXHDaLGef3MVks WtbKbNFytJ3FonnTFFaLzxseM1p03b3BaDHpoKjF/iteDsIev39NYvT49nUSi8fshossHjtn 3WX3WLznJZPHplWdbB53ru1h89g/dw27x+Yl9R59W1YxeqzfcpXF4/MmuQCeKC6blNSczLLU In27BK6MpquL2QtalCpeXG5hb2Bskuli5OSQEDCROLrhJksXIxeHkMBuRoknU5+yQCQkJZbO vcEOYQtL3G85wgpR9I1RouPvXbYuRg4ONgEtie8LGUFqRATmMkts3VoEUsMscJZZ4s/T1WA1 wgKOEss38oLUsAioSkxp3coEYvMKuEq8P9kONV9O4ua5TmYQm1PATeLS1C1gM4WAahb++c48 gZFvASPDKkbJ1ILi3PTcYsMCw7zUcr3ixNzi0rx0veT83E2M4FjR0tzBuH3VB71DjEwcjIcY JTiYlUR4hWeVJAnxpiRWVqUW5ccXleakFh9ilOZgURLnvdB1Ml5IID2xJDU7NbUgtQgmy8TB KdXAdDrL8UagtMslFsYdm/6vmWSealDhGrDSoTBxhpfix79Tn+6Y88xrnla0k/T3A+8lvwXI letd3Rpy7UiZh3S6nsbpql+Wv7lTT23xm+gcyCAxIX3dxW3bwq5ldnxISVV7vX3+kdlLu8q3 bfpb8LmuyzKuz02ugLd8umBmco11wLyrr+Q15u9xzq7XbEnX9s9e0Wn3YodBdtfCmmmxJ162 L6tw/tqWNbnn56tDa5OD/FcIBt0vCrbx2f3xSFEem3+W2rSMj9tnCqzev6QtdOUK8Y+zGvcx FP91qT1n6TRB2/yn78azdcsWbZRace1foljkAdepk07KRqtxe1du0dyRvl3rb4PEwVN9B9iY H6b8UGIpzkg01GIuKk4EACDKll8EAwAA X-CMS-MailID: 20220506063340epcas2p4c9d88670f9be952f3637e3a545a7d1da X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20220506063340epcas2p4c9d88670f9be952f3637e3a545a7d1da References: <1651818679-10594-1-git-send-email-dh10.jung@samsung.com> Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This is for xHCI Host Controller driver on Exynos SOC. It registers vendor ops before loading xhci platform driver. Signed-off-by: Daehwan Jung --- drivers/usb/dwc3/dwc3-exynos.c | 100 ++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 0ecf20eeceee..c22ea5cd6ab0 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -17,6 +17,12 @@ #include #include +#include "core.h" + +#if IS_ENABLED(CONFIG_USB_XHCI_EXYNOS) +int xhci_exynos_register_vendor_ops(void); +#endif + #define DWC3_EXYNOS_MAX_CLOCKS 4 struct dwc3_exynos_driverdata { @@ -27,6 +33,7 @@ struct dwc3_exynos_driverdata { struct dwc3_exynos { struct device *dev; + struct dwc3 *dwc; const char **clk_names; struct clk *clks[DWC3_EXYNOS_MAX_CLOCKS]; @@ -46,12 +53,81 @@ static int dwc3_exynos_remove_child(struct device *dev, void *unused) return 0; } +#if IS_ENABLED(CONFIG_USB_XHCI_EXYNOS) +static int dwc3_exynos_host_init(struct dwc3_exynos *exynos) +{ + struct dwc3 *dwc = exynos->dwc; + struct device *dev = exynos->dev; + struct platform_device *xhci; + struct resource *res; + struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); + int ret = 0; + + /* Configuration xhci resources */ + xhci_exynos_register_vendor_ops(); + + res = platform_get_resource(dwc3_pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "missing memory resource\n"); + return -ENODEV; + } + dwc->xhci_resources[0].start = res->start; + dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + + DWC3_XHCI_REGS_END; + dwc->xhci_resources[0].flags = res->flags; + dwc->xhci_resources[0].name = res->name; + + res = platform_get_resource(dwc3_pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "missing irq resource\n"); + return -ENODEV; + } + + dwc->xhci_resources[1].start = dwc->irq_gadget; + dwc->xhci_resources[1].end = dwc->irq_gadget; + dwc->xhci_resources[1].flags = res->flags; + dwc->xhci_resources[1].name = res->name; + + xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); + if (!xhci) { + dev_err(dwc->dev, "couldn't allocate xHCI device\n"); + return -ENOMEM; + } + + xhci->dev.parent = dwc->dev; + ret = dma_set_mask_and_coherent(&xhci->dev, DMA_BIT_MASK(36)); + if (ret) { + pr_err("xhci dma set mask ret = %d\n", ret); + return ret; + } + + ret = platform_device_add_resources(xhci, dwc->xhci_resources, + DWC3_XHCI_RESOURCES_NUM); + if (ret) { + dev_err(dwc->dev, "couldn't add resources to xHCI device\n"); + goto err; + } + + ret = platform_device_add(xhci); + if (ret) { + dev_err(dwc->dev, "couldn't add xHCI device\n"); + goto err; + } + + return 0; +err: + platform_device_put(xhci); + return ret; +} +#endif + static int dwc3_exynos_probe(struct platform_device *pdev) { struct dwc3_exynos *exynos; struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; + struct device_node *node = dev->of_node, *dwc3_np; const struct dwc3_exynos_driverdata *driver_data; + struct platform_device *dwc3_pdev; int i, ret; exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL); @@ -109,6 +185,12 @@ static int dwc3_exynos_probe(struct platform_device *pdev) goto vdd10_err; } + dwc3_np = of_get_compatible_child(node, "snps,dwc3"); + if (!dwc3_np) { + dev_err(dev, "failed to find dwc3 core child!\n"); + goto vdd33_err; + } + if (node) { ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { @@ -121,6 +203,22 @@ static int dwc3_exynos_probe(struct platform_device *pdev) goto populate_err; } + dwc3_pdev = of_find_device_by_node(dwc3_np); + exynos->dwc = platform_get_drvdata(dwc3_pdev); + if (!exynos->dwc) { + ret = -EPROBE_DEFER; + dev_err(dev, "failed to get dwc3 core node!\n"); + goto populate_err; + } + +#if IS_ENABLED(CONFIG_USB_XHCI_EXYNOS) + /* USB host initialization. */ + ret = dwc3_exynos_host_init(exynos); + if (ret) { + dev_err(dev, "USB host pre-initialization fail!\n"); + goto populate_err; + } +#endif return 0; populate_err: