From patchwork Thu Apr 26 11:26:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Shimoda X-Patchwork-Id: 10365649 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 528B1602DC for ; Thu, 26 Apr 2018 11:27:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 43E322906A for ; Thu, 26 Apr 2018 11:27:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 390B32908A; Thu, 26 Apr 2018 11:27:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7620B2906A for ; Thu, 26 Apr 2018 11:27:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755029AbeDZL13 (ORCPT ); Thu, 26 Apr 2018 07:27:29 -0400 Received: from relmlor4.renesas.com ([210.160.252.174]:20298 "EHLO relmlie3.idc.renesas.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754932AbeDZL1M (ORCPT ); Thu, 26 Apr 2018 07:27:12 -0400 Received: from unknown (HELO relmlir2.idc.renesas.com) ([10.200.68.152]) by relmlie3.idc.renesas.com with ESMTP; 26 Apr 2018 20:27:11 +0900 Received: from relmlii2.idc.renesas.com (relmlii2.idc.renesas.com [10.200.68.66]) by relmlir2.idc.renesas.com (Postfix) with ESMTP id 862EB956A6; Thu, 26 Apr 2018 20:27:11 +0900 (JST) X-IronPort-AV: E=Sophos;i="5.49,330,1520866800"; d="scan'208";a="279389823" Received: from mail-ty1jpn01lp0183.outbound.protection.outlook.com (HELO JPN01-TY1-obe.outbound.protection.outlook.com) ([23.103.139.183]) by relmlii2.idc.renesas.com with ESMTP/TLS/AES256-SHA256; 26 Apr 2018 20:27:11 +0900 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=renesasgroup.onmicrosoft.com; s=selector1-renesas-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=Anf/Vi7BVRuoky8hEq62ATkpFnSNlQHuUl8V6JeoTJY=; b=oAWjCcsyta3l1YNcucS0VgQVrtECj1lKRgaoKx8ZKAu6eizQen7a9wtRiPdsUITootJs/SwRuuCHw1kQhi7XXYqqF01bC8Imu9kFmU8qDVKhhVTSAbBeEofYGnspSy2vNIglrNkGvLhb4H3mKqW37wTLrmqtfjqgGHTaFrHsYHg= Received: from localhost.localdomain (211.11.155.138) by TYAPR01MB2304.jpnprd01.prod.outlook.com (2603:1096:404:8::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.696.13; Thu, 26 Apr 2018 11:27:08 +0000 From: Yoshihiro Shimoda To: gregkh@linuxfoundation.org, robh+dt@kernel.org, mark.rutland@arm.com Cc: heikki.krogerus@linux.intel.com, hdegoede@redhat.com, andy.shevchenko@gmail.com, linux-usb@vger.kernel.org, linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org, Yoshihiro Shimoda Subject: [PATCH/RFC v2 4/6] usb: role: rcar-usb3-role-switch: add support for R-Car SoCs Date: Thu, 26 Apr 2018 20:26:44 +0900 Message-Id: <1524742006-17984-5-git-send-email-yoshihiro.shimoda.uh@renesas.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1524742006-17984-1-git-send-email-yoshihiro.shimoda.uh@renesas.com> References: <1524742006-17984-1-git-send-email-yoshihiro.shimoda.uh@renesas.com> MIME-Version: 1.0 X-Originating-IP: [211.11.155.138] X-ClientProxiedBy: OSAPR01CA0066.jpnprd01.prod.outlook.com (2603:1096:604:a::30) To TYAPR01MB2304.jpnprd01.prod.outlook.com (2603:1096:404:8::18) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(48565401081)(5600026)(4534165)(4627221)(201703031133081)(8559017)(2017052603328)(7153060)(7193020); SRVR:TYAPR01MB2304; X-Microsoft-Exchange-Diagnostics: 1; TYAPR01MB2304; 3:vugyNYd03pLvOBuA6c2Ic4/NipsyuMRFf9LSuAjgQTk/HCvDGX5xFFvNd+8zft3DLG0foW8kXd6THcNQGmXUW1orsSxeJ3o62AnRIqyIy2wDIwdjXOWSNc+N7tuNCIHkMbh5d7zK4fw6Hean4idy/2DL8qYfZw38gJI8++yHhVkPw2+LKSMG2+pbXcezb/hoCzWOrgD9lY338/UtO7A5H1y2duLW30MBUTfqd9/u9zN8rx+uuy1m00zI3kJGhoQL; 25:NtXFMsCyl9w7T4pg8BpPDrg8OIlSAIwLQPh2MMGwwx8pj+8X87ygZFGQ9u1VW8SWK5INYKqPJwbAcswMFsPA3Ry5DFA2IGl9w+EaIAUSrEdQzdDWo2KDK87lSMJ8wULZD2O4mgPyphlde/4R+Tpsld/o/uIMtIBQEf282nHsy8WOCnxki0InT4rYG0qlfVcLZTg3uy3iajwrMAQIWf1P/6OtdwzZXBgLerfprw9JPO1bgqF4zKyXkSheYHzsb5GT3ErwcRRB8SqkmezDdLJ8RFxrobb6cKt/ZrDT3DSBjtjQG9v4gTGktkrrUGNSH3mIi/nHSmtpiYXe6FkUmeuYOw==; 31:ZwpUs//xlbAKVb0F0cwQT+FQxGO52s1Oca7lSePdchco5eZe7r2ZnKekC6lVR1wr/sE56vi6jD8xs81E2qYt7N5bvi8cUc3yFzs/7Q3A8BOx3Pau7sCUWcfXJxVYG98uNm3jlTiTfb4+H2jwcrQXGGMjU95FR6xxsbTjpfzPH+eUZXZwAxDduwoKEBKeYX56ihtXYgH7wUUPSv3857dq+FZn8TvYNCKRqYhwmNxXuHE= X-MS-TrafficTypeDiagnostic: TYAPR01MB2304: Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=<>; X-Microsoft-Exchange-Diagnostics: 1; TYAPR01MB2304; 20:G+0q0/btK8oMkoZUevwDcEq2ve6TggkjaxuYLwxzy+8v597F+HF6NdMj187nPE8RS0Hs+BEf2SluycGS1vl1SWPUTR7x/zgET3H/1WWLYcc05kydrP9/cTCsNVwk7il2FhAQcvzrTXKp6bYJgbVfycuFPY44o8MqV5pWq++lPQh88JWjs7ap2rPlUsTD0HGXq8WVNNGAweqDYWtylUo8fAfhMGZxCdT4AnBQiYZHjJAYR1mtXXxf3FigJNwct2oWw203ALyTbU8PGSct2u1Nw6R70sMTb3kDIuwuvw1ap3WNrxS8uahzxW/Z6z2yLifs2ab4hbegg+rf+EJF771y7XcpNOgSNkTT43h8p6agt4iZzD/u/881H26S6yfOlD7BYI4mE2oS06a4847RLpy2q/4SF+MUe/Iucp5Z/b9ovsUnrYaTR6UbMJDjipC/cWfoDqeQB7P6DcvjABNGTpNCTXaMZUORjPaHF3GHhvILrXKOXVsVSYsOVE49TRbXECre; 4:IlmgACjOT3QEK+C1TsuBtf1cKaABeHWIIHshOAEDnWCXbc3lOtoDheqah7SLczjRtvIc9Sk5lVKI2lZrkJ9p/7F0b4obGRY+359P0WIu2NqZjqH/+vmVNzGcvETr7txh8Qxe2IVkemo3hEoEM1SA+nm/SYF+EJ7KuKnLKGBcsY6YMHwQK/FXF/Jj+SPom//Ne/zeCuPW1z7SgsEpId9sYZxDsxHD+cek89yuTxPbU+aiadhy462t8gISai3rkbMShAV9XdPO5fuFBqPcnVfO1Q== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(3231232)(944501410)(52105095)(93006095)(10201501046)(6055026)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061750153)(20161123564045)(20161123560045)(20161123558120)(20161123562045)(6072148)(201708071742011); SRVR:TYAPR01MB2304; BCL:0; PCL:0; RULEID:; SRVR:TYAPR01MB2304; X-Forefront-PRVS: 0654257CF5 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6029001)(6069001)(346002)(39380400002)(376002)(39860400002)(396003)(366004)(189003)(199004)(25786009)(48376002)(386003)(81166006)(6506007)(5890100001)(106356001)(316002)(16526019)(305945005)(50466002)(42882007)(26005)(16586007)(51416003)(52116002)(8936002)(81156014)(8676002)(50226002)(11346002)(53936002)(6666003)(78352004)(476003)(486006)(2616005)(446003)(7736002)(59450400001)(956004)(6486002)(6512007)(97736004)(2906002)(66066001)(6116002)(39060400002)(107886003)(3846002)(5660300001)(105586002)(4326008)(47776003)(498600001)(68736007)(36756003)(76176011)(3720700003); DIR:OUT; SFP:1102; SCL:1; SRVR:TYAPR01MB2304; H:localhost.localdomain; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:0; A:0; Received-SPF: None (protection.outlook.com: localhost.localdomain does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; TYAPR01MB2304; 23:GwKIxdL+WnZ/r3FNyUHqk4dZg6g0blk7sHigYykTX?= =?us-ascii?Q?Drl43/WMHoy/E5/yNauY7dQ/ncGOw978xqdZY62WcLZyDuCKWwNDMsp+BYQF?= =?us-ascii?Q?1VDbeug1bcHMm1DTU2gdG4FrQJjQTw4Y1VBRcG/6io/Jn+VUUjEQ49dVBipw?= =?us-ascii?Q?Gq5EjgdmEHTGqaswyjGxt+6qy8Fx+/rH0sLqIVVgMGQdneMy5jyvHU2bOc7t?= =?us-ascii?Q?WBKsoVyXEqmhIfLOl3l+Pmh5egp+wLHR2QGdflVoYbmxe60m7jlR+kJiOy4g?= =?us-ascii?Q?SrKIR1KbxcGey2/8/dY1c6SsV3rvs6looV1HjkZOQ1K5XtrbLW1MKVVTaLzl?= =?us-ascii?Q?zsjYWVipJPjC9JOF+4auu1tBd4+WTeUtSnjNXPyKRz+X1IRPXW+XoQjWmAdf?= =?us-ascii?Q?wypqrckGXcnifjmrzKWVuqCDChYoI6GtT11tJVwRDybdCelm1Fl99qmYZcLM?= =?us-ascii?Q?4qXoAuBHq3p37p0s8kesgZ6z3zaR5Sz1wcrH/OBnSejcbu5Mha62TzNj1TMZ?= =?us-ascii?Q?HqxdHVM/q4zuf8YmEXNITRsw78WF4MMlfYKiXaKPkHsZkdgcENfo1WLRmvHB?= =?us-ascii?Q?8q+OkkQiexuTpiEmCbIxi0fGIU/UbCdu1LGUGnJPXsJENxSgv/kCNZ7po+zg?= =?us-ascii?Q?/STJ8HGgEnXrBaN7PK5ujimWq486qKlH99HlLEIRD4wZweHbJMDH1/vXksHV?= =?us-ascii?Q?M9Kv0VEZ96oH7Bbi9cABam9SuNSkg72Y3uvRgzjuBMvqP0ek9T3c42boGKfI?= =?us-ascii?Q?mH7Rp102pWLXYDU4KvuqJu8gBOnaIhD5Ozj1JtlnLldTli3MU/eepSKnFXvX?= =?us-ascii?Q?tQ+hV+MhOxI2ffJ6bbIIBGIbMQcaXFpZAVjyuiHHHukg+K2NnYDm12D7x9NJ?= =?us-ascii?Q?gXHxXTK5tffCT0fFJPuzWEfcuJo9TKRv8t32vkEewtsIwdk+ujOoqcNmRy9R?= =?us-ascii?Q?L2IPNgk0Pxi/g68GVzCVoxdSrUgeXHFyWiT9EADSVmtWG/NxSNqMUToqr+cE?= =?us-ascii?Q?Y08LPMmwvSrjZq1q5JKhv5eShuYvZ9PsgT4OWucMomsD9cxl4LnRHR3fhyjT?= =?us-ascii?Q?Zvd0o0bkTcECU75wNB9tJGeWndawYmhBjP/gJby1Bgh3pAbqH4tzaf8aEsE6?= =?us-ascii?Q?JeGwETGc1YdX+DzafJQOBZlZiZ95jlpOvJVDHTU7iArbqw1u8qL+uPJdwWbx?= =?us-ascii?Q?VwTQkk6VSJ3zD6FmVxpCglDp1MeerWrTvSBDjXj/uf1RMK1LHlB0goXXmUpc?= =?us-ascii?Q?4SgtHKfj2bWon/ZQ0j21lwkzvNtPPuj86zgtswzQDXjBu0nda2Cttw6DZhh4?= =?us-ascii?Q?M067lIV72DKxNrR5WE18PGdKDSgvtbHc1k16dB694xT?= X-Microsoft-Antispam-Message-Info: rNy6OcZQ50+B0T9hfNLNE1skEDS1kBdMQ9pju2KUE+2tyVFMlrlIb3IkTil6x5mBXkI0481FRdsgHz2Ns5+oxSvTTVDguJJb6WA2nar1B4p13+8sOaCpDAXTT3DZQRJOb4W+j1UU35UIqEfhI/O9xcbGJeS1PZOtdBG3RkYlcqRP9a8PAOjfyRGbFSjKrnpb X-Microsoft-Exchange-Diagnostics: 1; TYAPR01MB2304; 6:gF4Cx7CV55lheXWdomFaG6q1J6F8RDqO/feWXo8PTEBsjGdsbvEYBzlYGlXAMU+eY2POwh5iRm/PJDJaJUMixyIHgVgQWpAj1KswSx5MFDZTfEGnNjbKoN363evL2uDkASs4az+gZpWHwjCb7TEeiedF4FkfDcPUaHhioR+bZi9zJgpP0g/IWPcvhAyTkE/Xqq4NJvLEk3GptQ2H+zdRWODAd54vmR5bJyhr7mz8pTUhcu8Mpb5XNdAbyV7WPfFJZUmIhYZDawl/S0j8vtRggxAFgTdil165vnzCzms5m9yfD18JV74urK3WcAv/vqTx7ExevbZaPu7gIKg4OjI36BL8GWGKKQBkBzzTLsYq2un9YHoiBnCpAl0ADt6h9fvXsazSxyvjs5NhzT87HQ++RZMZPos4BxYpJUNZh7427NvQhQQd0P5FVRKecphLWDpvOeXr6pFfH0k8f6SzDewWWw==; 5:cD845oNgxl3xzX99JO73YAvJR8wwrBpJaeO/knCCTThN5RXltpY1aUvcJULzlUZwpCC9LS+z95G3AZzj4KzqOrhUQLwRP9kfqdgDC3zCrNzKDTK6RLHAblyB6iPsnXcS/ZIRmEojDMfcK5LtzwnBoOCoFvubuWz2HSqvwzPFlhk=; 24:89EKoinnN/Kx2vU+MPrmzNfsWEVvqsR9C3yZx6CdcJ6jwHJHLACtgBI1ZR3hnqEH8CM24DCXMF4ajelnB4Mf8irScLk0dFrXoTDVZ4L9B+8= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; TYAPR01MB2304; 7:vv9iZduyGxplBN8B33FPyENLHhTUyu6aofpIi423Y/tZNZk58PSAWnOcgKU5iAT2io20niaiTTp2zL9Z1isbuy3nUNi6Yh8U6YJKHu87qHLD4UkvwGhEkmgWIur6lPq1L6kAmtuSiSFd9HQCn79O3u3VKDwGJHn9ZTeGEus9nYl6d64NpRexEtQgOa3g5cYpervJWi2W1D/Qgo/7iUD9nPJjtI7H4Vw6hr5v0Nc9fCKvawum8AuTb2RTdHfBr0vP; 20:QnPcWexYYl7kxlczu6QcVXDe1Fi6eMpsJ35S10ajJCC6osTxq++pmQnnjLvLjtK64B+E0A+J3bCVuy7D11EQ1azCPdVXhJe6TRjnzge3h2P4tHiSVttDTKBN+/8SFSdvz3DYdEdaeFLtpH2ihsjBK3hL6ufU45OwIGPf8Pw7kmM= X-MS-Office365-Filtering-Correlation-Id: ce7b6f65-4f71-4462-229d-08d5ab68a5ee X-OriginatorOrg: renesas.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Apr 2018 11:27:08.8463 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ce7b6f65-4f71-4462-229d-08d5ab68a5ee X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 53d82571-da19-47e4-9cb4-625a166a4a2a X-MS-Exchange-Transport-CrossTenantHeadersStamped: TYAPR01MB2304 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds role switch support for R-Car SoCs. Some R-Car SoCs (e.g. R-Car H3) have USB 3.0 dual-role device controller which has the USB 3.0 xHCI host and Renesas USB 3.0 peripheral. Unfortunately, the mode change register contains the USB 3.0 peripheral controller side only. So, the USB 3.0 peripheral driver (renesas_usb3) manages this register. However, in peripheral mode, the host should stop. Also the host hardware needs to reinitialize its own registers when the mode changes from peripheral to host mode. Otherwise, the host cannot work correctly (e.g. detect a device as high-speed). To achieve this by a driver, this role switch driver manages the mode change register and attach/release the xhci-plat driver. The renesas_usb3 udc driver should call devm_of_platform_populate() to probe this driver. Signed-off-by: Yoshihiro Shimoda --- drivers/usb/roles/Kconfig | 13 ++ drivers/usb/roles/Makefile | 1 + drivers/usb/roles/rcar-usb3-role-switch.c | 190 ++++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 drivers/usb/roles/rcar-usb3-role-switch.c diff --git a/drivers/usb/roles/Kconfig b/drivers/usb/roles/Kconfig index f5a5e6f..a44cbc7 100644 --- a/drivers/usb/roles/Kconfig +++ b/drivers/usb/roles/Kconfig @@ -11,4 +11,17 @@ config USB_ROLES_INTEL_XHCI To compile the driver as a module, choose M here: the module will be called intel-xhci-usb-role-switch. +config USB_ROLES_RCAR_USB3 + tristate "Renesas R-Car USB3.0 Role Switch" + depends on OF + depends on ARCH_RENESAS || COMPILE_TEST + help + Driver for the internal USB role switch for switching the USB data + lines between the xHCI host controller and the Renesas gadget + controller (by using renesas_usb3 driver) found on various Renesas + R-Car SoCs. + + To compile the driver as a module, choose M here: the module will + be called rcar-usb3-role-switch. + endif # USB_ROLE_SWITCH diff --git a/drivers/usb/roles/Makefile b/drivers/usb/roles/Makefile index e44b179..7ce3be3 100644 --- a/drivers/usb/roles/Makefile +++ b/drivers/usb/roles/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_USB_ROLES_INTEL_XHCI) += intel-xhci-usb-role-switch.o +obj-$(CONFIG_USB_ROLES_RCAR_USB3) += rcar-usb3-role-switch.o diff --git a/drivers/usb/roles/rcar-usb3-role-switch.c b/drivers/usb/roles/rcar-usb3-role-switch.c new file mode 100644 index 0000000..2bcab60 --- /dev/null +++ b/drivers/usb/roles/rcar-usb3-role-switch.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas R-Car USB 3.0 role switch driver + * + * Copyright (C) 2018 Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +#define USB3_DRD_CON 0x218 +#define DRD_CON_PERI_CON BIT(24) + +struct rcar_usb3_role_switch { + struct usb_role_switch *role_sw; + void __iomem *reg; + struct device *host_dev; + enum usb_role save_role; /* for suspend/resume */ +}; + +static enum usb_role +rcar_usb3_role_switch_get_mode(struct rcar_usb3_role_switch *rcar_sw) +{ + u32 val = readl(rcar_sw->reg + USB3_DRD_CON); + + if (val & DRD_CON_PERI_CON) + return USB_ROLE_DEVICE; + + return USB_ROLE_HOST; +} + +static void +rcar_usb3_role_switch_set_mode(struct rcar_usb3_role_switch *rcar_sw, + bool host) +{ + void __iomem *drd_con = rcar_sw->reg + USB3_DRD_CON; + + if (host) + writel(readl(drd_con) & ~DRD_CON_PERI_CON, drd_con); + else + writel(readl(drd_con) | DRD_CON_PERI_CON, drd_con); +} + +static int rcar_usb3_role_switch_set_role(struct device *dev, + enum usb_role role) +{ + struct rcar_usb3_role_switch *rcar_sw = dev_get_drvdata(dev); + struct device *host = rcar_sw->host_dev; + enum usb_role cur_role; + + pm_runtime_get_sync(dev->parent); + + cur_role = rcar_usb3_role_switch_get_mode(rcar_sw); + if (cur_role == USB_ROLE_HOST && role == USB_ROLE_DEVICE) { + device_release_driver(host); + rcar_usb3_role_switch_set_mode(rcar_sw, false); + } else if (cur_role == USB_ROLE_DEVICE && role == USB_ROLE_HOST) { + /* Must set the mode before device_attach of the host */ + rcar_usb3_role_switch_set_mode(rcar_sw, true); + if (device_attach(host) < 0) + dev_err(dev, "device_attach(usb3_port) failed\n"); + } + + pm_runtime_put(dev->parent); + + return 0; +} + +static enum usb_role rcar_usb3_role_switch_get_role(struct device *dev) +{ + struct rcar_usb3_role_switch *rcar_sw = dev_get_drvdata(dev); + enum usb_role cur_role; + + pm_runtime_get(dev->parent); + cur_role = rcar_usb3_role_switch_get_mode(rcar_sw); + pm_runtime_put(dev->parent); + + return cur_role; +} + +static struct usb_role_switch_desc rcar_usb3_role_switch_desc = { + .set = rcar_usb3_role_switch_set_role, + .get = rcar_usb3_role_switch_get_role, +}; + +static const struct of_device_id rcar_usb3_role_switch_of_match[] = { + { .compatible = "renesas,rcar-usb3-role-switch" }, + { } +}; +MODULE_DEVICE_TABLE(of, rcar_usb3_role_switch_of_match); + +static int rcar_usb3_role_switch_remove(struct platform_device *pdev) +{ + struct rcar_usb3_role_switch *rcar_sw = platform_get_drvdata(pdev); + + usb_role_switch_unregister(rcar_sw->role_sw); + pm_runtime_disable(pdev->dev.parent); + + return 0; +} + +static int rcar_usb3_role_switch_probe(struct platform_device *pdev) +{ + struct rcar_usb3_role_switch *rcar_sw; + struct resource *res; + + rcar_sw = devm_kzalloc(&pdev->dev, sizeof(*rcar_sw), GFP_KERNEL); + if (!rcar_sw) + return -ENOMEM; + + res = platform_get_resource(to_platform_device(pdev->dev.parent), + IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + rcar_sw->reg = devm_ioremap_nocache(&pdev->dev, res->start, + resource_size(res)); + if (IS_ERR(rcar_sw->reg)) + return PTR_ERR(rcar_sw->reg); + + platform_set_drvdata(pdev, rcar_sw); + pm_runtime_enable(pdev->dev.parent); + + rcar_usb3_role_switch_desc.allow_userspace_control = true; + rcar_sw->role_sw = usb_role_switch_register(&pdev->dev, + &rcar_usb3_role_switch_desc); + if (IS_ERR(rcar_sw->role_sw)) { + pm_runtime_disable(pdev->dev.parent); + return PTR_ERR(rcar_sw->role_sw); + } + + rcar_sw->host_dev = device_connection_find_by_graph(&pdev->dev, 0, 0); + if (!IS_ERR_OR_NULL(rcar_sw->host_dev)) { + dev_info(&pdev->dev, "%s: host_dev = %p (%s)\n", __func__, + rcar_sw->host_dev, dev_name(rcar_sw->host_dev)); + } else { + usb_role_switch_unregister(rcar_sw->role_sw); + pm_runtime_disable(pdev->dev.parent); + return PTR_ERR(rcar_sw->host_dev); + } + + return 0; +} + +static int __maybe_unused rcar_usb3_role_switch_suspend(struct device *dev) +{ + struct rcar_usb3_role_switch *rcar_sw = dev_get_drvdata(dev); + + pm_runtime_get_sync(dev->parent); + rcar_sw->save_role = rcar_usb3_role_switch_get_mode(rcar_sw); + pm_runtime_put(dev->parent); + + return 0; +} + +static int __maybe_unused rcar_usb3_role_switch_resume(struct device *dev) +{ + struct rcar_usb3_role_switch *rcar_sw = dev_get_drvdata(dev); + bool host = rcar_sw->save_role == USB_ROLE_HOST ? true : false; + + pm_runtime_get_sync(dev->parent); + rcar_usb3_role_switch_set_mode(rcar_sw, host); + pm_runtime_put(dev->parent); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(rcar_usb3_role_switch_pm_ops, + rcar_usb3_role_switch_suspend, + rcar_usb3_role_switch_resume); + +static struct platform_driver rcar_usb3_role_switch_driver = { + .probe = rcar_usb3_role_switch_probe, + .remove = rcar_usb3_role_switch_remove, + .driver = { + .name = "rcar_usb3_role_switch", + .pm = &rcar_usb3_role_switch_pm_ops, + .of_match_table = rcar_usb3_role_switch_of_match, + }, +}; +module_platform_driver(rcar_usb3_role_switch_driver); + +MODULE_DESCRIPTION("Renesas USB3.0 role switch driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Yoshihiro Shimoda ");