From patchwork Wed Sep 16 13:25:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peng Fan X-Patchwork-Id: 1365307 X-Patchwork-Delegate: lukma@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=nxp.com header.i=@nxp.com header.a=rsa-sha256 header.s=selector2 header.b=ZjdYFPGM; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Bs0cF2Jyqz9sSC for ; Wed, 16 Sep 2020 23:02:04 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 08D3A8236D; Wed, 16 Sep 2020 15:00:28 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=nxp.com header.i=@nxp.com header.b="ZjdYFPGM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DB62F82383; Wed, 16 Sep 2020 15:00:14 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FORGED_SPF_HELO,MSGID_FROM_MTA_HEADER, SPF_HELO_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on20631.outbound.protection.outlook.com [IPv6:2a01:111:f400:7d00::631]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B3A4082366 for ; Wed, 16 Sep 2020 15:00:07 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=peng.fan@nxp.com ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=POlGlInv7XzgzivwwikRi6W4DMI5Kw52SWUmP+pTDAtPQoYH9P5DaatubdDDOFYmN+CyDFlXqbcmHQmbQRNJgiLm/9GLKJUXrumCSmF/cFb/actoZXRLFIGeJbSlB5vR4E/GSe/tw0ucRXLuLvyKHa7DcBkNEyTCWNWO1/FLnZPZGgYEGVMXqI0uiOoBPlNNV3GVrgeddPi2dQuc9hMpeprt4s8cc6QcA3FPYhrz5boYSQNue03STnDfbdf5vbbFbKpLlTTMK2uMJwMMYL2L0PIpSrTc2GNDC5QoKBj3I/mlaYGLQlIz6XLVpGT1W2M2WLztrIhAaiGwNDH1Pq5aRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=O2D+oNQIREVqxxKbqflwvCn61TiBdZsDWAa0vxJLhXw=; b=bEm3u20W2USTyE30ADNZBtxCA6R0gqu2yw4EfZEeuRZgdbtoSRY0zspL5p0rRfdxwsVPtSWzyzzIhZh5flWvziBu9kL/JIp9BB7wNhbYemX9xGmTu/OgrrnmdcR6SiipagBZmO0DBQHs0ALsSJP0HEhmzH9oUb0nvdZeVWaLNczna9HPfPbWhAkUA0f/6JiWUTFj4SbxIyqJxqkDSfJ/5OjTJnpauTA44YTeOR4IdgCPo9D25GCfQQxfsD+UcpRhAUJRsouDk/5/00MaTCjm2aYa1Fv2fusFAXh8epChH6SLm73gz6n3hFnBrSCaE31SPRBw+5FtzMDTveJbhw+p2Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=O2D+oNQIREVqxxKbqflwvCn61TiBdZsDWAa0vxJLhXw=; b=ZjdYFPGMJJex/qHBWIJs2s1aiCGVVbWtjVvCXYdE4r+V3jr9DdxsRYB5Kr/vMTy4h4XpvSsYb/92zUprY9nSoqs8QpLL0HUM9B4T1PcMAQJV/Go00d/1s4nwTBOI6/l0RRxWoIznny+hB+2wex+IzGusF9tyObv/3IsMEEn4lEE= Authentication-Results: denx.de; dkim=none (message not signed) header.d=none;denx.de; dmarc=none action=none header.from=nxp.com; Received: from DB6PR0402MB2760.eurprd04.prod.outlook.com (2603:10a6:4:a1::14) by DB6PR0401MB2373.eurprd04.prod.outlook.com (2603:10a6:4:4b::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3370.18; Wed, 16 Sep 2020 13:00:05 +0000 Received: from DB6PR0402MB2760.eurprd04.prod.outlook.com ([fe80::39ff:13b4:4f28:1413]) by DB6PR0402MB2760.eurprd04.prod.outlook.com ([fe80::39ff:13b4:4f28:1413%10]) with mapi id 15.20.3370.019; Wed, 16 Sep 2020 13:00:05 +0000 From: peng.fan@nxp.com To: sbabic@denx.de, lukma@denx.de, marex@denx.de Cc: uboot-imx@nxp.com, u-boot@lists.denx.de, Li Jun , Ye Li , Peter Chen , "faqiang . zhu" , Peng Fan Subject: [PATCH 10/16] usb: gadget: add super speed support Date: Wed, 16 Sep 2020 21:25:31 +0800 Message-Id: <20200916132537.8313-11-peng.fan@nxp.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200916132537.8313-1-peng.fan@nxp.com> References: <20200916132537.8313-1-peng.fan@nxp.com> X-ClientProxiedBy: SG2PR03CA0131.apcprd03.prod.outlook.com (2603:1096:4:91::35) To DB6PR0402MB2760.eurprd04.prod.outlook.com (2603:10a6:4:a1::14) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from linux-1xn6.ap.freescale.net (119.31.174.71) by SG2PR03CA0131.apcprd03.prod.outlook.com (2603:1096:4:91::35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3391.5 via Frontend Transport; Wed, 16 Sep 2020 13:00:02 +0000 X-Mailer: git-send-email 2.28.0 X-Originating-IP: [119.31.174.71] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 489e56be-3dab-45e2-8d18-08d85a406eb9 X-MS-TrafficTypeDiagnostic: DB6PR0401MB2373: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:255; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: kapWMTdI21frinUUk5XqoRGVuIDcS9Pccehw16kUtQMUFYFGD/TbQ+kIfMb5H000l4thfxkd7TyoNy5P/v27oe9HTlhR/n3tA+/Z1yTGZNexQp3zcBa3HpZIBFd06VWxlPXTuUaIUzE5TtAe4IVJiVEqaME8qx2OGB93BXXodvTi4f0FEfaP31/zUYucLNyAzxWqawygMIZVEuyQVQ5BAoMG4b+6qU/G1vUZ/hK/FRbPVdPmkFCzIDEsoUZ6kUxAAurUWMa55tMUVHBzjt0YidEH5j03es4iEcwloFynXxGchWTIZb3dbpTwopagr+T4Bu2iymADylNZt0uQiMq/fw== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DB6PR0402MB2760.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(346002)(366004)(376002)(136003)(39860400002)(396003)(54906003)(19627235002)(6666004)(9686003)(1076003)(6512007)(5660300002)(478600001)(52116002)(36756003)(6506007)(66946007)(26005)(6486002)(16526019)(186003)(956004)(316002)(66556008)(66476007)(2616005)(86362001)(83380400001)(8936002)(2906002)(4326008)(8676002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: ZczhWnYnEHO99ov06Z8AX5Qg66KNaD79iQYjvN2qyx13dABTbaDbbs52V0YO9Q382gdETi/QVe3QG02ejOLzM1XuhqEDhLHAo96e27P91bXB58aejqA9XOrXgUasjCRFRncpCUJSGSXfBMr3mJ5UgoeSKKP9T3TJ0uCJUmP3HoY4PwVI1ZJLJy5U0m2MTkwYN+8w3EgLa91UT/JeHcNwFvO0zdfFzSp2G0pOB68Ev3htrQ5LmkjfFn7J4nvMxj7t4EzXRHx5FjR6FF4xe85/63ZPqLWAR/t/PQ10w/X7JlTeNtoEpv0vXviqnEcyeYflGuOAai0a0Zy9oBNRapbcskzY2VGsRbCsmjgxO29NLGr1nwEaA99thV1omr2cRJ1v5NXPGNkpRK1A43uf7rVEUP/CYsGjuysjvCIa/oRIZdv5rnCiQmQZubuhxFpAmI/NVKU5xPnMd6wihIDIH1PsVwtb3eHlHyTQ/uanZgTQy8wplO0zutkIdvzE6mPQoaGfbfwZxLnYsCi7IacDKKLYdm9zKRaRm3DE3/Iowdy6CQR/O/afP8ZOmx0znFoGoqVqHNBc3Cl95k62ypuqJwbh/MT7la9lCU2DXwW/54DgIK5fxHlzDL3pbfaoaH51263PmUxOJWqWmDyVlAMYGlrYnw== X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 489e56be-3dab-45e2-8d18-08d85a406eb9 X-MS-Exchange-CrossTenant-AuthSource: DB6PR0402MB2760.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Sep 2020 13:00:05.8584 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Vnikr7WC9RlKl0eHZmdYoOhhNgpeurAfgbezfvj5BjxXRiNgJ/rIH6AVQ2VFn7paD4ITJQ7EldpKKZj386gPPQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0401MB2373 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean From: Li Jun This patch is to add usb gadget super speed support in common driver, including BOS descriptor and select the super speed descriptor from function driver. Reviewed-by: Ye Li Reviewed-by: Peter Chen Tested-by: faqiang.zhu Signed-off-by: Li Jun Signed-off-by: Peng Fan --- drivers/usb/gadget/composite.c | 85 ++++++++++++++++++++++++---------- include/linux/usb/composite.h | 4 ++ include/linux/usb/gadget.h | 6 +++ 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index b453055838..abb42db6bd 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -88,6 +88,8 @@ int usb_add_function(struct usb_configuration *config, config->fullspeed = 1; if (!config->highspeed && function->hs_descriptors) config->highspeed = 1; + if (!config->superspeed && function->ss_descriptors) + config->superspeed = 1; done: if (value) @@ -223,7 +225,9 @@ static int config_buf(struct usb_configuration *config, /* add each function's descriptors */ list_for_each_entry(f, &config->functions, list) { - if (speed == USB_SPEED_HIGH) + if (speed == USB_SPEED_SUPER) + descriptors = f->ss_descriptors; + else if (speed == USB_SPEED_HIGH) descriptors = f->hs_descriptors; else descriptors = f->descriptors; @@ -251,7 +255,9 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) struct usb_configuration *c; struct list_head *pos; - if (gadget_is_dualspeed(gadget)) { + if (gadget_is_superspeed(gadget)) { + speed = gadget->speed; + } else if (gadget_is_dualspeed(gadget)) { if (gadget->speed == USB_SPEED_HIGH) hs = 1; if (type == USB_DT_OTHER_SPEED_CONFIG) @@ -275,7 +281,10 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) continue; check_config: - if (speed == USB_SPEED_HIGH) { + if (speed == USB_SPEED_SUPER) { + if (!c->superspeed) + continue; + } else if (speed == USB_SPEED_HIGH) { if (!c->highspeed) continue; } else { @@ -294,8 +303,12 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type) struct usb_gadget *gadget = cdev->gadget; unsigned count = 0; int hs = 0; + int ss = 0; struct usb_configuration *c; + if (gadget->speed == USB_SPEED_SUPER) + ss = 1; + if (gadget_is_dualspeed(gadget)) { if (gadget->speed == USB_SPEED_HIGH) hs = 1; @@ -304,7 +317,10 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type) } list_for_each_entry(c, &cdev->configs, list) { /* ignore configs that won't work at this speed */ - if (hs) { + if (ss) { + if (!c->superspeed) + continue; + } else if (hs) { if (!c->highspeed) continue; } else { @@ -388,6 +404,9 @@ static int set_config(struct usb_composite_dev *cdev, case USB_SPEED_HIGH: speed = "high"; break; + case USB_SPEED_SUPER: + speed = "super"; + break; default: speed = "?"; break; @@ -412,7 +431,9 @@ static int set_config(struct usb_composite_dev *cdev, * function's setup callback instead of the current * configuration's setup callback. */ - if (gadget->speed == USB_SPEED_HIGH) + if (gadget->speed == USB_SPEED_SUPER) + descriptors = f->ss_descriptors; + else if (gadget->speed == USB_SPEED_HIGH) descriptors = f->hs_descriptors; else descriptors = f->descriptors; @@ -492,8 +513,9 @@ int usb_add_config(struct usb_composite_dev *cdev, list_del(&config->list); config->cdev = NULL; } else { - debug("cfg %d/%p speeds:%s%s\n", + debug("cfg %d/%p speeds:%s%s%s\n", config->bConfigurationValue, config, + config->superspeed ? " super" : "", config->highspeed ? " high" : "", config->fullspeed ? (gadget_is_dualspeed(cdev->gadget) @@ -751,6 +773,7 @@ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) static int bos_desc(struct usb_composite_dev *cdev) { struct usb_ext_cap_descriptor *usb_ext; + struct usb_dcd_config_params dcd_config_params; struct usb_bos_descriptor *bos = cdev->req->buf; bos->bLength = USB_DT_BOS_SIZE; @@ -794,9 +817,19 @@ static int bos_desc(struct usb_composite_dev *cdev) USB_HIGH_SPEED_OPERATION | USB_5GBPS_OPERATION); ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION; - ss_cap->bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT; - ss_cap->bU2DevExitLat = - cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); + + /* Get Controller configuration */ + if (cdev->gadget->ops->get_config_params) { + cdev->gadget->ops->get_config_params( + &dcd_config_params); + } else { + dcd_config_params.bU1devExitLat = + USB_DEFAULT_U1_DEV_EXIT_LAT; + dcd_config_params.bU2DevExitLat = + cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); + } + ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; + ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; } return le16_to_cpu(bos->wTotalLength); } @@ -999,32 +1032,28 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) cdev->desc.bNumConfigurations = count_configs(cdev, USB_DT_DEVICE); - /* - * If the speed is Super speed, then the supported - * max packet size is 512 and it should be sent as - * exponent of 2. So, 9(2^9=512) should be filled in - * bMaxPacketSize0. Also fill USB version as 3.0 - * if speed is Super speed. - */ - if (cdev->gadget->speed == USB_SPEED_SUPER) { + cdev->desc.bMaxPacketSize0 = + cdev->gadget->ep0->maxpacket; + if (gadget->speed >= USB_SPEED_SUPER) { + cdev->desc.bcdUSB = cpu_to_le16(0x0310); cdev->desc.bMaxPacketSize0 = 9; - cdev->desc.bcdUSB = cpu_to_le16(0x0300); } else { - cdev->desc.bMaxPacketSize0 = - cdev->gadget->ep0->maxpacket; + cdev->desc.bcdUSB = cpu_to_le16(0x0200); } value = min(w_length, (u16) sizeof cdev->desc); memcpy(req->buf, &cdev->desc, value); break; case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) + if (!gadget_is_dualspeed(gadget) || + gadget->speed >= USB_SPEED_SUPER) break; device_qual(cdev); value = min_t(int, w_length, sizeof(struct usb_qualifier_descriptor)); break; case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) + if (!gadget_is_dualspeed(gadget) || + gadget->speed >= USB_SPEED_SUPER) break; case USB_DT_CONFIG: @@ -1039,10 +1068,16 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) value = min(w_length, (u16) value); break; case USB_DT_BOS: - if (gadget_is_superspeed(cdev->gadget)) + /* + * Super speed connection should support BOS, and + * USB compliance test (USB 2.0 Command Verifier) + * also issues this request, return for now for + * USB 2.0 connection. + */ + if (gadget->speed >= USB_SPEED_SUPER) { value = bos_desc(cdev); - if (value >= 0) value = min(w_length, (u16)value); + } break; default: goto unknown; @@ -1421,7 +1456,7 @@ composite_resume(struct usb_gadget *gadget) } static struct usb_gadget_driver composite_driver = { - .speed = USB_SPEED_HIGH, + .speed = USB_SPEED_SUPER, .bind = composite_bind, .unbind = composite_unbind, diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index d75a0bc4c4..935e5c0cbb 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -146,6 +146,7 @@ struct usb_function { struct usb_gadget_strings **strings; struct usb_descriptor_header **descriptors; struct usb_descriptor_header **hs_descriptors; + struct usb_descriptor_header **ss_descriptors; struct usb_configuration *config; @@ -279,6 +280,7 @@ struct usb_configuration { u8 next_interface_id; unsigned highspeed:1; unsigned fullspeed:1; + unsigned superspeed:1; struct usb_function *interface[MAX_CONFIG_INTERFACES]; }; @@ -292,6 +294,7 @@ int usb_add_config(struct usb_composite_dev *, * identifiers. * @strings: tables of strings, keyed by identifiers assigned during bind() * and language IDs provided in control requests + * @max_speed: Highest speed the driver supports. * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -319,6 +322,7 @@ struct usb_composite_driver { const char *name; const struct usb_device_descriptor *dev; struct usb_gadget_strings **strings; + enum usb_device_speed max_speed; /* REVISIT: bind() functions can be marked __init, which * makes trouble for section mismatch analysis. See if diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 8d54b91734..7e6d329e54 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -449,6 +449,11 @@ static inline void usb_ep_fifo_flush(struct usb_ep *ep) /*-------------------------------------------------------------------------*/ +struct usb_dcd_config_params { + __u8 bU1devExitLat; /* U1 Device exit Latency */ + __le16 bU2DevExitLat; /* U2 Device exit Latency */ +}; + struct usb_gadget; struct usb_gadget_driver; @@ -464,6 +469,7 @@ struct usb_gadget_ops { int (*pullup) (struct usb_gadget *, int is_on); int (*ioctl)(struct usb_gadget *, unsigned code, unsigned long param); + void (*get_config_params)(struct usb_dcd_config_params *); int (*udc_start)(struct usb_gadget *, struct usb_gadget_driver *); int (*udc_stop)(struct usb_gadget *);