From patchwork Tue Oct 13 10:22:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Shimoda X-Patchwork-Id: 7382841 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DC27D9F1D5 for ; Tue, 13 Oct 2015 10:23:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8AC48207CC for ; Tue, 13 Oct 2015 10:23:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 01234207C2 for ; Tue, 13 Oct 2015 10:23:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932083AbbJMKWZ (ORCPT ); Tue, 13 Oct 2015 06:22:25 -0400 Received: from relmlor4.renesas.com ([210.160.252.174]:61837 "EHLO relmlie3.idc.renesas.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752519AbbJMKWV (ORCPT ); Tue, 13 Oct 2015 06:22:21 -0400 Received: from unknown (HELO relmlir2.idc.renesas.com) ([10.200.68.152]) by relmlie3.idc.renesas.com with ESMTP; 13 Oct 2015 19:22:19 +0900 Received: from relmlac2.idc.renesas.com (relmlac2.idc.renesas.com [10.200.69.22]) by relmlir2.idc.renesas.com (Postfix) with ESMTP id 55184511F6; Tue, 13 Oct 2015 19:22:19 +0900 (JST) Received: by relmlac2.idc.renesas.com (Postfix, from userid 0) id 2ECF72806E; Tue, 13 Oct 2015 19:22:19 +0900 (JST) Received: from relmlac2.idc.renesas.com (localhost [127.0.0.1]) by relmlac2.idc.renesas.com (Postfix) with ESMTP id 136012806D; Tue, 13 Oct 2015 19:22:19 +0900 (JST) Received: from relmlii2.idc.renesas.com [10.200.68.66] by relmlac2.idc.renesas.com with ESMTP id VAB17104; Tue, 13 Oct 2015 19:22:18 +0900 X-IronPort-AV: E=Sophos;i="5.17,677,1437404400"; d="scan'";a="197502665" Received: from mail-sg2apc01lp0240.outbound.protection.outlook.com (HELO APC01-SG2-obe.outbound.protection.outlook.com) ([65.55.88.240]) by relmlii2.idc.renesas.com with ESMTP/TLS/AES256-SHA; 13 Oct 2015 19:22:17 +0900 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=<>; Received: from localhost (211.11.155.144) by HK2PR06MB0914.apcprd06.prod.outlook.com (10.162.246.29) with Microsoft SMTP Server (TLS) id 15.1.293.16; Tue, 13 Oct 2015 10:22:15 +0000 From: Yoshihiro Shimoda To: , , , , , CC: , , , Yoshihiro Shimoda Subject: [PATCH v4 1/3] phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver Date: Tue, 13 Oct 2015 19:22:04 +0900 Message-ID: <1444731726-5328-2-git-send-email-yoshihiro.shimoda.uh@renesas.com> X-Mailer: git-send-email 1.9.4.msysgit.1 In-Reply-To: <1444731726-5328-1-git-send-email-yoshihiro.shimoda.uh@renesas.com> References: <1444731726-5328-1-git-send-email-yoshihiro.shimoda.uh@renesas.com> MIME-Version: 1.0 X-Originating-IP: [211.11.155.144] X-ClientProxiedBy: HKXPR02CA0040.apcprd02.prod.outlook.com (25.161.48.25) To HK2PR06MB0914.apcprd06.prod.outlook.com (25.162.246.29) X-Microsoft-Exchange-Diagnostics: 1; HK2PR06MB0914; 2:TrmdfSdDZ3tgE3q4Jx0tmqAHNRuifBziQuoSc0FMeX1kq6g/5ilqQdh+uW34cAdNoXWGEcpgCIaLlyxv5iGRocbXrOJPrLN2ke+3xD5ljjF1lOWRckq25A/c2udPUW0zbQVe6PZGvRibBOwyV481qtTJZHnHBdl2cijcLULDXnM=; 3:mPpKdwkpBlXtY6oF5Dr8LhWW7T7hqF1Ns+Q/2THtTTKUJJVjcfIwNDPDq/Se3jQs2/LjoazGmG5hWx44FQ63lxsoqZyEwUA7lNCU5/PeIL2g4XIq6zxz5+5BrPgONxVRDU1ZLl1YLvdEeCzIEoFS7w==; 25:FqU1MINJ14y3WkP9OrPVn+MgGsO59kTB9PCWJs60n5bonXXQIPrBn5Nd3hkWdYwfUENNC6inIm5D+GBHWSHyRCTek/Bra/yHqbWxwc4kTCb1FbVCZyQsZ00pJJjr/w1zSosD4wWmf3Bnfl/I52v5wz2P9bRGkLh5f//Lg0pZv2WUTzDq4JDFM5uHRJPr2tSuM/T0Kk1B+bYTkNkPgAAKqQkTFmNl1ZPZrPy3VOKDFJVfJRrUQwarFs8atgmoACq7jfbcahmdDqhdY6hDuIwwlw== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:HK2PR06MB0914; X-Microsoft-Exchange-Diagnostics: 1; HK2PR06MB0914; 20:aF4NC0u+zEDqncKcVfeM4ygRlwIteNvmNMOECRlxDKqIIsTItqZAPX+rwXDNGQt8di03Bi3T8QJ0toGJ9hdKFoHb7mBEWYhvhF/gGrLdgT0Ivlybk16WmVWmzJv9FRFGx95FvKyxrsf1YSQE505cOJzFlOX/s970t9N0aNs/DMs0SLKsxhB5T+G7KsYtO3M7kbrDjsKLMMqB/7LRJQsepFHrw78hgQ6gYmlydzL9DukpvmmvvZzvQcYb9f1uV6B97RXA1ewiyl+cj21C3lbrzlsuD5Pg3nNjTpO4a0tSqREseM0XOyHTnfi/3VnN6llHFoutiyQpCXPwbE44ay90j4Hu34XlKN5t2Aan/VbzLDz2HsGxB/8DhbilmrzwTheBn/LMtcobG557Wr6hUJPhz6rxdR9XcDwQJE9tYKQbTELOWMGATPx23xGhntmSNFBMUfZfaAAORhqD4lH+g2zVMiTpbVhd3ieg59WdYL5OtMVIy1dD6XdYzylayE6tnjzX; 4:y5vpxinnFuQBFENwqHJbyl+M3vScjNbREP/UbIlfmWZU3JcP6yAkvTCUJ9XmDLcux1tuZGsgG8oCv6wU1dmIuFYMBqeB1iSFs+cr+evFsUbYPbmU3uq2z44TjQcUUVopir0pBcLRlvVQvBiYmfaE7SOuZYvzgEaDcOlA0HlkUQrLu+tNeiJMUKpp2QfudAY2G8OaAWiIDknoZ2ylBgiO7IvzxFOwnByNcONxgnJQ8wLZ33kqz8HXWfmHGFVpPRtItVL/UxcrhvHZujOpHi+j00w/Dll3KyLO4Xo5RrBcdYhCBOEVx4s6VpC99iShKO0FYc6+fjuDMjnjnDE9YyCCvwOLhqNS5FyKJBaewzANZtM= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(85106069007906); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(5005006)(520078)(8121501046)(3002001); SRVR:HK2PR06MB0914; BCL:0; PCL:0; RULEID:; SRVR:HK2PR06MB0914; X-Forefront-PRVS: 07283408BE X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6069001)(6009001)(189002)(199003)(42186005)(5003940100001)(5007970100001)(46102003)(97736004)(36756003)(19580405001)(50986999)(105586002)(33646002)(229853001)(78352002)(5001960100002)(76506005)(42382002)(575784001)(81156007)(19580395003)(48376002)(5004730100002)(50466002)(5001920100001)(189998001)(107886002)(5001770100001)(47776003)(101416001)(87976001)(64706001)(92566002)(2950100001)(230783001)(106356001)(76176999)(5008740100001)(122386002)(40100003)(77096005)(50226001)(66066001)(2004002)(4001430100001); DIR:OUT; SFP:1102; SCL:1; SRVR:HK2PR06MB0914; H:localhost; FPR:; SPF:None; PTR:InfoNoRecords; MX:0; A:0; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; HK2PR06MB0914; 23:lUEpS0lwqUrWXpRB7ylOwy2sB3DDzWNuNHduTNexI?= =?us-ascii?Q?EzsiKQlSWIF/tyCrVz9n+enty1e7c4/Px8cdLG4G3q27EgojtynHPZzJCdrW?= =?us-ascii?Q?607BZZoNHWmD3hwZaiZ+9IIakAFSKrov1aPCD6ATkAHAe/0aQ55vOxQBvKB9?= =?us-ascii?Q?t0DtI7rN6F7TLZTGa4EvtpONy01TChs1figPotr2i1ObtaP7odPZI5pithey?= =?us-ascii?Q?lFg7icuPmd6rg2xK5X7ZlQuNeZO7uhXv9cL3nu2WUa8KmX82rAoYZgZ3Egvr?= =?us-ascii?Q?vhl0Q8Y8eceJYplC0Giba8kpwZt8SfT5MZ5qFflDDrClyEJYUPC0pUDOCOXT?= =?us-ascii?Q?KTCImkxfK7FsKir9TMifgtgal0SExrXpI7gNTvwkUw8W8Szm/H2TzVxqY3l6?= =?us-ascii?Q?CnKLkiFg3p3R0fPiNPeL+mvg1oHqvLYLk1x1OS3OxIlbO+gjPTDMRTKbhyTI?= =?us-ascii?Q?bEreQCNvPnb9h0Gniz6OHmYHWTp8kE8RGOxOgGNwrP4Ze3xFcaesUzZyhRre?= =?us-ascii?Q?T1M/b4YOX2X1eYb9Giy2LMK9gx/+/ADzqit5FX3azKBw50KS+4K740wmWqbc?= =?us-ascii?Q?bJXR4KXzY9WPdvm/dq4naWW3ewUsv2Dvul0UtNSXM1nAgAeTIz+MTn1OrLsK?= =?us-ascii?Q?IINwvgVdGvUszQmpdJygw+la0Tl/91BtRzMqM1XqKmjyYCvy6r0k6uewTfg9?= =?us-ascii?Q?vG94sMe6Y8e8MjWb+1QPBV6eVr8c+tGe2Z+WvJ4GSF8pAgDTDQumfmZ1hu2k?= =?us-ascii?Q?NYklo2gHFkFRxNks5bDLBtysN1RcQrEK3IzZF0kSiZHaCkW6GNry7yXWYnFK?= =?us-ascii?Q?csBrGOy9zOingKZidxdXwAA06Dtr+Tu+XtFzCE1L5p/hwpdpwPjcKzaQCz8+?= =?us-ascii?Q?/SRB3i/6wJONK67F77g9rCETyINc0K2Id8sXXw9UW1W3rfd/tkHVd0ZB3pIj?= =?us-ascii?Q?9ja9DgNBc6Nw8Psa1F/r4/5BqNFLbpE++oXijN8RsNEC/f2RESQulmwxx0Iq?= =?us-ascii?Q?i/2UVHjqkYXcU09Hd/NMdGis6wZHCL5KWhjcTPsJbaP4WbeOM5IPbfqz4L5o?= =?us-ascii?Q?4bthDrO/UofGl1I5w0sAvvBOW/PBd/8aDJu2D+vqfs+8oI2b6RgAwRqZzu8G?= =?us-ascii?Q?RGKHo2jAR4nT7UesE9vqd7+T0172IEAWoGA0gmZRQdcen5ngbpWAytgzwsv7?= =?us-ascii?Q?lih5yzeDx9GdqV7xH0g2VslMoQntXcDnbWfAmrXIdfg/tWb3e7POLqWeYzHQ?= =?us-ascii?Q?A4/H62oZc+024VeuF0=3D?= X-Microsoft-Exchange-Diagnostics: 1; HK2PR06MB0914; 5:V8Qc6HepCK8Dk1S6aPMVqDPCKYJYKtVElK/edTBOb23ApBJpKENKVoCG7QgkmeyUEnTckU54w0AppzGTrozo1LoVYS0eFV1UwKf6NfdT19PWwiCuLD8q5fpQktHaRECL+PeGZRaIdEhJhKZ2zgHGHA==; 24:tKlsO5cALmhAcXwR4ofFXbOfzpkN9lI9UpJJxiPb/45aUJhEEcOBLjM5L5WEdizkw7A7uxpyskSa0IKj0z5ZDcI3jChCfjiy29sEX1SX92A=; 20:dBTG1rZ8BoSSUPOKtbbMKXdypMavGbZ1yF0RWRf+IibLZ5z1ZTFjGF0hFHzTZeFoeh2q7N4gY+ext5VuohhJzaE432JID25xRQex411RY+d1EVwWKVWFsvoSr2dfNy+cRU13XK5fEUXKQWnvXloP3O+TbIBLXcoV4jFNBubIlOM= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: renesas.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Oct 2015 10:22:15.6320 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: HK2PR06MB0914 Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-4.6 required=5.0 tests=AXB_X_OUTLOOKPROT_ENVSDR, BAYES_00,RCVD_IN_DNSWL_HI,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds support for R-Car generation 3 USB2 PHY driver. This SoC has 3 EHCI/OHCI channels, and the channel 0 is shared with the HSUSB (USB2.0 peripheral) device. And each channel has independent registers about the PHYs. So, the purpose of this driver is: 1) initializes some registers of SoC specific to use the {ehci,ohci}-platform driver. 2) detects id pin to select host or peripheral on the channel 0. For now, this driver only supports 1) above. Signed-off-by: Yoshihiro Shimoda --- .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt | 37 ++++ drivers/phy/Kconfig | 8 + drivers/phy/Makefile | 1 + drivers/phy/phy-rcar-gen3-usb2.c | 240 +++++++++++++++++++++ 4 files changed, 286 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt create mode 100644 drivers/phy/phy-rcar-gen3-usb2.c diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt new file mode 100644 index 0000000..589f5c0 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt @@ -0,0 +1,37 @@ +* Renesas R-Car generation 3 USB 2.0 PHY + +This file provides information on what the device node for the R-Car generation +3 USB 2.0 PHY contains. + +Required properties: +- compatible: "renesas,usb2-phy-r8a7795" if the device is a part of an R8A7795 + SoC. +- reg: offset and length of the partial USB 2.0 Host register block. +- reg-names: must be "usb2_host". +- clocks: clock phandle and specifier pair(s). +- #phy-cells: see phy-bindings.txt in the same directory, must be <0>. + +Optional properties: +To use a USB channel where USB 2.0 Host and HSUSB (USB 2.0 Peripheral) are +combined, the device tree node should set HSUSB properties to reg and reg-names +properties. This is because HSUSB has registers to select USB 2.0 host or +peripheral at that channel: +- reg: offset and length of the partial HSUSB register block. +- reg-names: must be "hsusb". + +Example (R-Car H3): + + usb-phy@ee080200 { + compatible = "renesas,usb2-phy-r8a7795"; + reg = <0 0xee080200 0 0x700>, <0 0xe6590100 0 0x100>; + reg-names = "usb2_host", "hsusb"; + clocks = <&mstp7_clks R8A7795_CLK_EHCI0>, + <&mstp7_clks R8A7795_CLK_HSUSB>; + }; + + usb-phy@ee0a0200 { + compatible = "renesas,usb2-phy-r8a7795"; + reg = <0 0xee0a0200 0 0x6ff>; + reg-names = "usb2_host"; + clocks = <&mstp7_clks R8A7795_CLK_EHCI0>; + }; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 7eb5859d..45c6131 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -118,6 +118,14 @@ config PHY_RCAR_GEN2 help Support for USB PHY found on Renesas R-Car generation 2 SoCs. +config PHY_RCAR_GEN3_USB2 + tristate "Renesas R-Car generation 3 USB 2.0 PHY driver" + depends on OF + depends on ARCH_SHMOBILE + depends on GENERIC_PHY + help + Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs. + config OMAP_CONTROL_PHY tristate "OMAP CONTROL PHY Driver" depends on ARCH_OMAP2PLUS || COMPILE_TEST diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 075db1a..91d7a62 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o +obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c new file mode 100644 index 0000000..d90dfcf --- /dev/null +++ b/drivers/phy/phy-rcar-gen3-usb2.c @@ -0,0 +1,240 @@ +/* + * Renesas R-Car Gen3 for USB2.0 PHY driver + * + * Copyright (C) 2015 Renesas Electronics Corporation + * + * This is based on the phy-rcar-gen2 driver: + * Copyright (C) 2014 Renesas Solutions Corp. + * Copyright (C) 2014 Cogent Embedded, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +/******* USB2.0 Host registers (original offset is +0x200) *******/ +#define USB2_INT_ENABLE 0x000 +#define USB2_USBCTR 0x00c +#define USB2_SPD_RSM_TIMSET 0x10c +#define USB2_OC_TIMSET 0x110 + +/* INT_ENABLE */ +#define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) +#define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) +#define USB2_INT_ENABLE_INIT (USB2_INT_ENABLE_USBH_INTB_EN | \ + USB2_INT_ENABLE_USBH_INTA_EN) + +/* USBCTR */ +#define USB2_USBCTR_DIRPD BIT(2) +#define USB2_USBCTR_PLL_RST BIT(1) + +/* SPD_RSM_TIMSET */ +#define USB2_SPD_RSM_TIMSET_INIT 0x014e029b + +/* OC_TIMSET */ +#define USB2_OC_TIMSET_INIT 0x000209ab + +/******* HSUSB registers (original offset is +0x100) *******/ +#define HSUSB_LPSTS 0x02 +#define HSUSB_UGCTRL2 0x84 + +/* Low Power Status register (LPSTS) */ +#define HSUSB_LPSTS_SUSPM 0x4000 + +/* USB General control register 2 (UGCTRL2) */ +#define HSUSB_UGCTRL2_MASK 0x00000031 /* bit[31:6] should be 0 */ +#define HSUSB_UGCTRL2_USB0SEL 0x00000030 +#define HSUSB_UGCTRL2_USB0SEL_HOST 0x00000010 +#define HSUSB_UGCTRL2_USB0SEL_HS_USB 0x00000020 +#define HSUSB_UGCTRL2_USB0SEL_OTG 0x00000030 + +struct rcar_gen3_data { + void __iomem *base; + struct clk *clk; +}; + +struct rcar_gen3_chan { + struct rcar_gen3_data usb2; + struct rcar_gen3_data hsusb; + struct phy *phy; + spinlock_t lock; +}; + +static int rcar_gen3_phy_usb2_init(struct phy *p) +{ + struct rcar_gen3_chan *channel = phy_get_drvdata(p); + unsigned long flags; + void __iomem *usb2_base = channel->usb2.base; + void __iomem *hsusb_base = channel->hsusb.base; + u32 tmp; + + spin_lock_irqsave(&channel->lock, flags); + + /* Initialize USB2 part */ + writel(USB2_INT_ENABLE_INIT, usb2_base + USB2_INT_ENABLE); + writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); + writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); + + /* Initialize HSUSB part */ + if (hsusb_base) { + /* TODO: support "OTG" mode */ + tmp = readl(hsusb_base + HSUSB_UGCTRL2); + tmp = (tmp & ~HSUSB_UGCTRL2_USB0SEL) | + HSUSB_UGCTRL2_USB0SEL_HOST; + writel(tmp & HSUSB_UGCTRL2_MASK, hsusb_base + HSUSB_UGCTRL2); + } + + spin_unlock_irqrestore(&channel->lock, flags); + + return 0; +} + +static int rcar_gen3_phy_usb2_exit(struct phy *p) +{ + struct rcar_gen3_chan *channel = phy_get_drvdata(p); + + writel(0, channel->usb2.base + USB2_INT_ENABLE); + + return 0; +} + +static int rcar_gen3_phy_usb2_power_on(struct phy *p) +{ + struct rcar_gen3_chan *channel = phy_get_drvdata(p); + void __iomem *usb2_base = channel->usb2.base; + void __iomem *hsusb_base = channel->hsusb.base; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&channel->lock, flags); + + tmp = readl(usb2_base + USB2_USBCTR); + tmp |= USB2_USBCTR_PLL_RST; + writel(tmp, usb2_base + USB2_USBCTR); + tmp &= ~USB2_USBCTR_PLL_RST; + writel(tmp, usb2_base + USB2_USBCTR); + + /* + * TODO: To reduce power consuming, this driver should set the SUSPM + * after the PHY detects ID pin as peripheral. + */ + if (hsusb_base) { + /* Power on HSUSB PHY */ + tmp = readw(hsusb_base + HSUSB_LPSTS); + tmp |= HSUSB_LPSTS_SUSPM; + writew(tmp, hsusb_base + HSUSB_LPSTS); + } + + spin_unlock_irqrestore(&channel->lock, flags); + + return 0; +} + +static int rcar_gen3_phy_usb2_power_off(struct phy *p) +{ + struct rcar_gen3_chan *channel = phy_get_drvdata(p); + void __iomem *hsusb_base = channel->hsusb.base; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&channel->lock, flags); + + if (hsusb_base) { + /* Power off HSUSB PHY */ + tmp = readw(hsusb_base + HSUSB_LPSTS); + tmp &= ~HSUSB_LPSTS_SUSPM; + writew(tmp, hsusb_base + HSUSB_LPSTS); + } + + spin_unlock_irqrestore(&channel->lock, flags); + + return 0; +} + +static struct phy_ops rcar_gen3_phy_usb2_ops = { + .init = rcar_gen3_phy_usb2_init, + .exit = rcar_gen3_phy_usb2_exit, + .power_on = rcar_gen3_phy_usb2_power_on, + .power_off = rcar_gen3_phy_usb2_power_off, + .owner = THIS_MODULE, +}; + +static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { + { .compatible = "renesas,usb2-phy-r8a7795" }, + { } +}; +MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table); + +static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rcar_gen3_chan *channel; + struct phy_provider *provider; + struct resource *res; + + if (!dev->of_node) { + dev_err(dev, "This driver needs device tree\n"); + return -EINVAL; + } + + channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL); + if (!channel) + return -ENOMEM; + + spin_lock_init(&channel->lock); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2_host"); + channel->usb2.base = devm_ioremap_resource(dev, res); + if (IS_ERR(channel->usb2.base)) + return PTR_ERR(channel->usb2.base); + + /* "hsusb" memory resource is optional */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hsusb"); + + /* To avoid error message by devm_ioremap_resource() */ + if (res) { + channel->hsusb.base = devm_ioremap_resource(dev, res); + if (IS_ERR(channel->hsusb.base)) + channel->hsusb.base = NULL; + } + + /* devm_phy_create() will call pm_runtime_enable(dev); */ + channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops); + if (IS_ERR(channel->phy)) { + dev_err(dev, "Failed to create USB2 PHY\n"); + return PTR_ERR(channel->phy); + } + + phy_set_drvdata(channel->phy, channel); + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(provider)) { + dev_err(dev, "Failed to register PHY provider\n"); + return PTR_ERR(provider); + } + + dev_set_drvdata(dev, channel); + + return 0; +} + +static struct platform_driver rcar_gen3_phy_usb2_driver = { + .driver = { + .name = "phy_rcar_gen3_usb2", + .of_match_table = rcar_gen3_phy_usb2_match_table, + }, + .probe = rcar_gen3_phy_usb2_probe, +}; +module_platform_driver(rcar_gen3_phy_usb2_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY"); +MODULE_AUTHOR("Yoshihiro Shimoda ");