From patchwork Mon Nov 30 01:44:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Shimoda X-Patchwork-Id: 7719931 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 73EA59F30B for ; Mon, 30 Nov 2015 01:45:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 41605203A0 for ; Mon, 30 Nov 2015 01:45:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D0D2220570 for ; Mon, 30 Nov 2015 01:45:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752473AbbK3Bow (ORCPT ); Sun, 29 Nov 2015 20:44:52 -0500 Received: from relmlor2.renesas.com ([210.160.252.172]:14376 "EHLO relmlie1.idc.renesas.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752173AbbK3Boq (ORCPT ); Sun, 29 Nov 2015 20:44:46 -0500 Received: from unknown (HELO relmlir2.idc.renesas.com) ([10.200.68.152]) by relmlie1.idc.renesas.com with ESMTP; 30 Nov 2015 10:44:44 +0900 Received: from relmlac4.idc.renesas.com (relmlac4.idc.renesas.com [10.200.69.24]) by relmlir2.idc.renesas.com (Postfix) with ESMTP id 3B8EE3EECE; Mon, 30 Nov 2015 10:44:44 +0900 (JST) Received: by relmlac4.idc.renesas.com (Postfix, from userid 0) id 1CEF248014; Mon, 30 Nov 2015 10:44:44 +0900 (JST) Received: from relmlac4.idc.renesas.com (localhost [127.0.0.1]) by relmlac4.idc.renesas.com (Postfix) with ESMTP id 1BFD8480A5; Mon, 30 Nov 2015 10:44:44 +0900 (JST) Received: from relmlii2.idc.renesas.com [10.200.68.66] by relmlac4.idc.renesas.com with ESMTP id LAT03157; Mon, 30 Nov 2015 10:44:44 +0900 X-IronPort-AV: E=Sophos;i="5.20,361,1444662000"; d="scan'";a="200739601" Received: from mail-hk2apc01lp0208.outbound.protection.outlook.com (HELO APC01-HK2-obe.outbound.protection.outlook.com) ([65.55.88.208]) by relmlii2.idc.renesas.com with ESMTP/TLS/AES256-SHA; 30 Nov 2015 10:44:43 +0900 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=<>; Received: from localhost (211.11.155.144) by HK2PR06MB0913.apcprd06.prod.outlook.com (10.162.246.28) with Microsoft SMTP Server (TLS) id 15.1.331.20; Mon, 30 Nov 2015 01:44:41 +0000 From: Yoshihiro Shimoda To: , , , , , CC: , , , Yoshihiro Shimoda Subject: [PATCH v6 1/4] phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver Date: Mon, 30 Nov 2015 10:44:30 +0900 Message-ID: <1448847873-7072-2-git-send-email-yoshihiro.shimoda.uh@renesas.com> X-Mailer: git-send-email 1.9.4.msysgit.1 In-Reply-To: <1448847873-7072-1-git-send-email-yoshihiro.shimoda.uh@renesas.com> References: <1448847873-7072-1-git-send-email-yoshihiro.shimoda.uh@renesas.com> MIME-Version: 1.0 X-Originating-IP: [211.11.155.144] X-ClientProxiedBy: HKXPR03CA0034.apcprd03.prod.outlook.com (10.141.129.24) To HK2PR06MB0913.apcprd06.prod.outlook.com (25.162.246.28) X-Microsoft-Exchange-Diagnostics: 1; HK2PR06MB0913; 2:I2CXgk/pGojw3GBKoTWUXBHwh20B6WVsGpziDIQ+M9/AF6cU5uk5bsbCTjqAmlTKnlxgwvFH9GZ18JJjnzV5zHNe76xje9SWVJW4VjEVPw00g2ej3Qe8fdyiMKHokG3BJ8Zrau0bLTJOgYD9JSqVMg==; 3:g/57mpHynwNM7C/FJDGylug1xhGj2KiewLHphbsh3CtJjxXn/QeRDh7V+Nz1VtRf8etouNaxlIdeOIoKQ7s4z7gHKKQWvU+6MgQQJZPuGVwrmKiNH1eAx4j15HTgZctK; 25:UN0aJO0nYg4qUQ59UFXkeRuUKf4irwJF9iB9IqO9jvDi6Jc7DbXl/g03lYczn1CajvfyxzTsl1LPJ16NXRJDwcRCtyLry+7h1gkErrybXdsk53jhX7qp3goaqr5OPaDTFIMk4lhD+b8/H2ujVVyuV0yM2ugxy2NONR7hUMTqJgLfcbXqE+OIsGyO8jDbSxnVvtemM9v2VsXyf6I9kVD8YM59PaJKNcmj7ApKuekxQmjzBwUbA+oOEa2N8w6eCJLA X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:HK2PR06MB0913; X-Microsoft-Exchange-Diagnostics: 1; HK2PR06MB0913; 20:gKeXTs1/hHNCPhQ/MGyPM1klkVaBwlbJTCZl30Ci929KvYK91pdC10bXjFYn1laD+/+ZOZ9In5Bw7pjdWuc/fjH3D+BY75ZoE9dB18wIeUpJW4SbIA42kGHf7oRwooToZXLa3jFl/X/GFfh8WYVAYkfumzqcYAHb7vmmm7Ag2gYySETcD4rD+HxjJjcpQ7goTc1SCab6E68kaW4DvCxC9pBCcc0OALo0vmiLTziIkZCn+wVgIj0fO5ajJM9iU+QXRUribKZYhRvhZ9P9UMvC/tlweBky3vtNf6+BGEngQ8IvSw+e4BFKqHyx/0oXbkegms/u4fy19qqOaaFWih1H6VOH43cLhq3t60+/1Q0RjfIkWCTA+V9/9/+fyPKg+EkC0cTBfSKbV+rW96BTrGPionA9Ezn2PfyM64h8y0K/BBhMbFKww+RW7x6zQIT9oYLw6DvDVU99czhstCX4Td+CnU4ls4YwhpzaDyXeCaWiwO3wNl80cswhdd2hmwh3gMgz; 4:NrrVfeAa4O1Al+Ux14rZOeCp4JHOPpWAXwwAI7kttZdvsFOYseK1vSKUmHrCvouNXnaLVkAG7PEMV11cMK43RGTh3dk5PtIIwovLTySEZ5Qg2YraipS5FhclkM502ieAUwZmDBazDznljvlw5s2Z107O6n21QsQJrRRBnwQ3TOwTXgkWga1M76/O6Gtm/j4hdWqhnvJ9/tlIGgKiyYzoiEL+DPaBqcfNj+CKz5QdvxY6qUUft/a+BrTqwi/q1bZNrliaszd4SSVFylHzMRAxQm2r+xkNh2Pb1JEcfl5PkBVs6XvzLaVrFl3aR87EzNKKdOo+Zg/Mu88P+ckvlBQeytLE7CGejXg0/MkYAz07N+FIyVHNs6Fmo/LxC7UR0lKjyRVzxsNCjSS0kHoR1UdEhZL7ISIXBo1tQGWbtT FXAGQ= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(85106069007906); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(8121501046)(5005006)(520078)(10201501046)(3002001); SRVR:HK2PR06MB0913; BCL:0; PCL:0; RULEID:; SRVR:HK2PR06MB0913; X-Forefront-PRVS: 0776C39A48 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6009001)(6069001)(189002)(199003)(106356001)(101416001)(230783001)(3846002)(5001960100002)(575784001)(5003940100001)(66066001)(50986999)(48376002)(47776003)(122386002)(5001770100001)(1096002)(5004730100002)(189998001)(586003)(87976001)(6116002)(78352003)(4001430100002)(81156007)(92566002)(76506005)(107886002)(50226001)(19580395003)(19580405001)(77096005)(97736004)(50466002)(76176999)(229853001)(42382002)(40100003)(105586002)(33646002)(2950100001)(36756003)(5008740100001)(42186005)(2004002); DIR:OUT; SFP:1102; SCL:1; SRVR:HK2PR06MB0913; H:localhost; FPR:; SPF:None; PTR:InfoNoRecords; MX:0; A:0; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; HK2PR06MB0913; 23:kn/XbGqwTTpJjMoSv+CkhkZhdWKeR1dNxmfxn7wiI?= =?us-ascii?Q?ZlyoF9dq4JGWUGniu4pQk3WT4i4LPk4M7GqvMycbzIPoUKmEVy8O3IaWCGyG?= =?us-ascii?Q?WaGm8RctE9xadPyu65YLVbhTO2VwOnLToj6soE4ozqBcTmFFaxryLcIScCQz?= =?us-ascii?Q?bCKc3WmA1fUF8+84Elb+D9qKX7kT86hyL3/PQ2q52yZmE7Wqev6Ps+Yvmytq?= =?us-ascii?Q?Q6kSlBPYUODF1BrgwLKE12kajMcHZa1iLcYwWR5gLQxjOGxJ4NRYpw1ogw/A?= =?us-ascii?Q?y2gJ52+jRBxqfG8jqVrpe3NT34B0ouQ/JcXTRgp9vDZTrzYFhhk4d8hhHwfC?= =?us-ascii?Q?pX11tkUkMp2zsNSLXVQfn87+8TXrKGn/1k085pJjOMrlhXTpEDKBME3LBKG8?= =?us-ascii?Q?P1Tczzp8mzn4+Vm1uZCaNk0ty+VuS+0CUGq553nCVLw6I/A+lWn17DfnC5yZ?= =?us-ascii?Q?Fq6s54P9HYGNz0tHK8xTM4FJSGTNlrJtIsGGSoZ/QCfX6yH94YD7k310Ql/U?= =?us-ascii?Q?oU2mzyd0Pgm2lVsVnNOlwyTyJLrUYHU8btnS+bmRpQ/FrmeXNFlf6hrcKgJJ?= =?us-ascii?Q?V/BLsofD2leekxQ5das+EopYw4wlCWmj781MYkUtDhwQ20lKy8ZNiCeJn8hV?= =?us-ascii?Q?2e2BXMcZGd5h1CSHqPUboKHyMog+cf9Ky9XJwnkbLY8B31b2SUBQfUjyJrtt?= =?us-ascii?Q?ymCp+7zFtaV3fTCSdJSoWoM/Wy34ZNncoG5FNblZM5uTSTovD3T9KfsIDrZ/?= =?us-ascii?Q?IBSbKUtWyHbE2LDAb4LVZsTiAl/siP6LV3b4QZNtg82j+c54oJqrWPgiqPof?= =?us-ascii?Q?DmOmR82cDk6S9UsKXPRcAkIw9W1cqln+IS/sXtMdnX+gzuVHA2my4an+C6YW?= =?us-ascii?Q?wEOK+UHk3Gt+PqRWQN7t8DdToHBr1Dm6wVabPcx0Xr4RQgUT0fRl7fEX/D4h?= =?us-ascii?Q?p0GkCJ5YOEHy13klbPzFWuNLqYkBOfMYEpgzHCLKyVd/pedZ8K0LHUP25Ahj?= =?us-ascii?Q?M8imIb7cXpgvBGuaG1n1ome3VKgY+kNKFqNbcHhw6yjGSoSMnFfCMOrV26IL?= =?us-ascii?Q?dkpGKlRbN6soh56hjS1F6nHo7DGiS1q1bvleDpw7Mdwf54m2fbwi3mToFRWx?= =?us-ascii?Q?2fZa7LODk+YG8oc8sD7nN2VJOvJkfXjtldUi03t54oTxvDwYkm7jrQ5d/MhX?= =?us-ascii?Q?lgj0pFSWz5odt9JmxDnwjRYbIt7/bpGs5Nq?= X-Microsoft-Exchange-Diagnostics: 1; HK2PR06MB0913; 5:eN/ofRk1Hr941k+gXiNTWbu9FWLdyF7icqPD+riTFlB13oXBg7fTvGJ6iVeM1t1taysrbP8DC+11JtGTphs6uiyxD7a1AtIpsOl5CHU96cUc61vSv3fDG5MhvQqscCsTZ/g/ENZJ+BJkr8H3RWH2iw==; 24:BI4mR2/NaUhdS0ZUlno2d+MEIETZpnKenHE05Qn8pWXW/EOPYEImd58VTchT/pDfsKhSD7gezAguPMqTu6KRMqiXafFpdW8IHckl/Hxnoww=; 20:8eRzHmDkRgmRfgbmEqO//uLdzZMK6gRHOVVPYNudqtiGyVVdH5OOkVcG5lUNK2F8zdQHnMmV745v2dxGlQ1eDa9YPeAip28nv9xvtk3occ+jCpiDumwxsXXbkCZMlI9JEpfXbCAl91tdfn3i7LoGa+INGlFSKyFyhrEdF2PQ5Rg= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: renesas.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Nov 2015 01:44:41.7122 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: HK2PR06MB0913 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.0 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 Acked-by: Rob Herring --- .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt | 37 ++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rcar-gen3-usb2.c | 217 +++++++++++++++++++++ 4 files changed, 262 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..affa0f7 --- /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 0x700>; + reg-names = "usb2_host"; + clocks = <&mstp7_clks R8A7795_CLK_EHCI0>; + }; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 7eb5859d..e9ab088 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -118,6 +118,13 @@ 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 && ARCH_SHMOBILE + select 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..2696152 --- /dev/null +++ b/drivers/phy/phy-rcar-gen3-usb2.c @@ -0,0 +1,217 @@ +/* + * 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 + +/******* 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; +}; + +static int rcar_gen3_phy_usb2_init(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; + u32 val; + + /* 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 */ + val = readl(hsusb_base + HSUSB_UGCTRL2); + val = (val & ~HSUSB_UGCTRL2_USB0SEL) | + HSUSB_UGCTRL2_USB0SEL_HOST; + writel(val & HSUSB_UGCTRL2_MASK, hsusb_base + HSUSB_UGCTRL2); + } + + 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; + u32 val; + + val = readl(usb2_base + USB2_USBCTR); + val |= USB2_USBCTR_PLL_RST; + writel(val, usb2_base + USB2_USBCTR); + val &= ~USB2_USBCTR_PLL_RST; + writel(val, 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 */ + val = readw(hsusb_base + HSUSB_LPSTS); + val |= HSUSB_LPSTS_SUSPM; + writew(val, hsusb_base + HSUSB_LPSTS); + } + + 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; + u32 val; + + if (hsusb_base) { + /* Power off HSUSB PHY */ + val = readw(hsusb_base + HSUSB_LPSTS); + val &= ~HSUSB_LPSTS_SUSPM; + writew(val, hsusb_base + HSUSB_LPSTS); + } + + 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; + + 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_OR_ZERO(provider); +} + +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 ");