From patchwork Thu Oct 1 10:10:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Shimoda X-Patchwork-Id: 7307261 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 CF4249F314 for ; Thu, 1 Oct 2015 10:11:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7B3AE20668 for ; Thu, 1 Oct 2015 10:11:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id ECEE420629 for ; Thu, 1 Oct 2015 10:11:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932362AbbJAKLD (ORCPT ); Thu, 1 Oct 2015 06:11:03 -0400 Received: from relmlor2.renesas.com ([210.160.252.172]:11401 "EHLO relmlie1.idc.renesas.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932314AbbJAKKt (ORCPT ); Thu, 1 Oct 2015 06:10:49 -0400 Received: from unknown (HELO relmlir2.idc.renesas.com) ([10.200.68.152]) by relmlie1.idc.renesas.com with ESMTP; 01 Oct 2015 19:10:47 +0900 Received: from relmlac4.idc.renesas.com (relmlac4.idc.renesas.com [10.200.69.24]) by relmlir2.idc.renesas.com (Postfix) with ESMTP id BF86E52EF1; Thu, 1 Oct 2015 19:10:47 +0900 (JST) Received: by relmlac4.idc.renesas.com (Postfix, from userid 0) id C120D480A5; Thu, 1 Oct 2015 19:10:47 +0900 (JST) Received: from relmlac4.idc.renesas.com (localhost [127.0.0.1]) by relmlac4.idc.renesas.com (Postfix) with ESMTP id BBADA480A3; Thu, 1 Oct 2015 19:10:47 +0900 (JST) Received: from relmlii1.idc.renesas.com [10.200.68.65] by relmlac4.idc.renesas.com with ESMTP id VAW10613; Thu, 1 Oct 2015 19:10:47 +0900 X-IronPort-AV: E=Sophos;i="5.17,616,1437404400"; d="scan'";a="195548121" Received: from mail-sg2apc01lp0239.outbound.protection.outlook.com (HELO APC01-SG2-obe.outbound.protection.outlook.com) ([65.55.88.239]) by relmlii1.idc.renesas.com with ESMTP/TLS/AES256-SHA; 01 Oct 2015 19:10:45 +0900 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=<>; Received: from localhost (211.11.155.144) by TY1PR06MB0927.apcprd06.prod.outlook.com (10.164.99.153) with Microsoft SMTP Server (TLS) id 15.1.280.20; Thu, 1 Oct 2015 10:10:42 +0000 From: Yoshihiro Shimoda To: , , , , , CC: , , , Yoshihiro Shimoda Subject: [PATCH v3] phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver Date: Thu, 1 Oct 2015 19:10:38 +0900 Message-ID: <1443694238-8152-1-git-send-email-yoshihiro.shimoda.uh@renesas.com> X-Mailer: git-send-email 1.9.4.msysgit.1 MIME-Version: 1.0 X-Originating-IP: [211.11.155.144] X-ClientProxiedBy: TY1PR01CA0012.jpnprd01.prod.outlook.com (25.161.131.150) To TY1PR06MB0927.apcprd06.prod.outlook.com (25.164.99.153) X-Microsoft-Exchange-Diagnostics: 1; TY1PR06MB0927; 2:wgc+cHHfx4kVAMGTDfN9XJ1PIGPt+N/vg1FLzJDKpXK0bYCFYkFkfOcHCIR65YaT3rLEgXs0SbqKVt99n1gTxbwQOQIsWd4hZFCcgDFkSK6eRRCcH1S2bt60vJzQ8dEr/KQJCs4WBFvD+AqtxZRcn0irYYTNgrledeIEDju51Zg=; 3:YaZgWJd7/WkvJG9iHFzJKZuIK1tdwwpOxuc6rMcIJgT/jh3TPTJxo4JAXo00Wy+ir5JCRI+LO4eND53OhkjsoARbi4UBZFrfYBxc1col4wJGdA8bUnxE2SscGvh9yoy1FN3JuQ9vwVBTTfb9Ol19Dg==; 25:lMmyw/jsbtNnf2aDPW0rex10G3kL8NT2RJY36EL1Zzi/uSM+w9EXuMEaWrYQ83bToZLIX0zWW/VjkWkmf9X6VQpt0Gh2LPKLw+EVhmUEe6sdHH+QNgzVGnFKVTnYwadiUT87r5pqj2XSOOP5whLYIcf1H76ZhUEYuTnRGneB5ya9iPtMjDuxhVAR59TNdX4LEd2PWK8hQLA4ylR4ZxWNBqGpLGriXH18L0W4Q+G+5nebyaSoEWBOXjZPd0HzB75ZuPVIl/GhsSu1WWhkYssMzA== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:TY1PR06MB0927; X-Microsoft-Exchange-Diagnostics: 1; TY1PR06MB0927; 20:ByRcEAXmZYx/3A9hno4Pvhh6/4izTBAFwiSsfJKQVCcl5jEgGuuFECrdChSNhj5t329A/X1qA3vo6uqrGSOlVztFN/zebUzBE7xlr69ywPtYPz6NJknUgjSfRDe8t/7d0s3O7GozoRIWQUnB4q0Vq8ThrKkd/wBDI+nNwkzPPLTOKIKZfKkQFX6gUM5mZxdav8cOku8LlII9FiDki8A0uzTBK1bGEfoM6zyC+1hRF0YNqdUTSazMq5Y5IiHV03r1C2TOz/7WRBZ7rEFMTisGjzBCQC6yjpBdN5Y3mm7fmtN++J5lE8Vk12j8FvTYYQjSP4k6TJkMAGJ4AFWe9IGRrR9LuF9S1UjIH9YbpXJmr7VAAoh7L51lACLNt5m6DnWXgeCuO12uUOYIwuhxFfvOzqH4GQZT7+DPOd6xXXxvATLoUHyPQpuNFk1LupUwzq45ky47a8fmojei0wdEWeZ/3SELvpdi5ADNq9VTO54Enm/c/Lo0DUXndnkXs969HyqP; 4:3p1HJaKG3UJ1SDoAqoUdGoJZrPmvu3Y0FDmNNvYhSaG8UIs0ln2obJk9S+3Xc1/4bpL+YNQUC3LzKHxNlDtBtG7vR91XFzjIVLTZBjzoLpeFL88j7vfGch9xs9GfmmQaIXZK1DLxT8VLwJYO8379TMAzAlYrqoEWAYqD3u1Qs96+YENqxLOm7NxjLoyUHjQ5cMbbqXEguHH3imr8CdaxcrbpQvQbcjwE/KbSh7nUK26MLcSt7Nq/Ti8+7v607XjqYUc2a21LL9ksaU3/f9t/l3wiO2dnpwgm0YOUxAatVxoeGXLijVMd2D+d6RqevtrET9KOFY8x8195vBPoosn8zugimtwyIqsLw9wZGTYEEoU= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(5005006)(520078)(8121501046)(3002001); SRVR:TY1PR06MB0927; BCL:0; PCL:0; RULEID:; SRVR:TY1PR06MB0927; X-Forefront-PRVS: 0716E70AB6 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6069001)(6009001)(189002)(199003)(122386002)(76506005)(50986999)(47776003)(5003940100001)(105586002)(33646002)(5001830100001)(101416001)(77156002)(46102003)(575784001)(66066001)(64706001)(97736004)(229853001)(5001770100001)(106356001)(107886002)(5001860100001)(62966003)(5001960100002)(50466002)(81156007)(4001540100001)(48376002)(40100003)(42186005)(230783001)(19580405001)(92566002)(77096005)(68736005)(5007970100001)(5008740100001)(189998001)(19580395003)(36756003)(42382002)(78352002)(5004730100002)(87976001)(50226001)(2004002)(4001430100001); DIR:OUT; SFP:1102; SCL:1; SRVR:TY1PR06MB0927; H:localhost; FPR:; SPF:None; PTR:InfoNoRecords; MX:0; A:0; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; TY1PR06MB0927; 23:1hSF+IqDzzbA+k6DL+Kt8xMa8MsDhcQyQyHuXLbBq?= =?us-ascii?Q?healypBrWJJqX3K7RjKWvAGgNSurv2O9Wws1Hcgwq8XnBiqZs487rnESKA7z?= =?us-ascii?Q?DgBK9E9A9OKdAPmXUV+0Dh211Gx49f/ZL5zMePniugwfSkOUMNj8bycb5bQY?= =?us-ascii?Q?rOkPo9kDN3UvfQz584hZrvzwXsMSJklmgYKLl3l09Exgl3NONQhqJBLLU4gG?= =?us-ascii?Q?1pQwm0pqm/nAkHlwPNSPA++bZG+4vWq19L5JPbUTrWFy1EuZIeQD7rlHxLEv?= =?us-ascii?Q?eS14XQZZm/GbC37BiUsE4/WPpURV/8Lg3BIE6vH65D9NFCBkxncg7Cd1Jl6u?= =?us-ascii?Q?EMEzPFku6Fo7RzLhUw4BCLQ9qudhi6nupm0qjokTAn044CAaclEYG8v2iGM3?= =?us-ascii?Q?jz0KKyRQl3AfPVUC8x02hICHyM59Jr+t6v7cth8JSbPY6SZZx1JwC/x5nfw/?= =?us-ascii?Q?2fRLgNUscGxEXdnH8ey/9/qHGCAjrrPLovnr16Z83LfQPGugcGBy0kQ4shxM?= =?us-ascii?Q?qUStrKCDEmd0Wt8dGgmLvfrJnUyGF/ZHfgJNDZMnOJVnoMyhlFpoYvBinQER?= =?us-ascii?Q?F6z8U0RVz7CKJ/5u0s5NkxaTmk/5+K6EPyW41W0kP0/L9EjcbXeXwqdTxU9c?= =?us-ascii?Q?BH5MOfjWoaNuMTJXXjVCliR83zjuihx6pYMCk+K0zze1dPiKjaP9odlPLILW?= =?us-ascii?Q?dS+KEcUoAxRAgcUWIR8/m0jo4bbFq742+M3s17Hl96KOumFCDQHHmoyqAtQz?= =?us-ascii?Q?HhL1kzuccd5oTxIDjeJu/iKoONXZyFDG/04HLW4OdFO2nEhfVZSl2CmN/YYl?= =?us-ascii?Q?GCk44vVKOG0k0rtggxIk3GMQUBY3JTW8f72r0sJENfGnfQ983saI0fa0xW60?= =?us-ascii?Q?3d6qVzi3hW+ZldiS7s589g0stkJGF+YY379l4T0sU6jd4D2sR/BvT79fvG4w?= =?us-ascii?Q?yQZOmew/0n/gQ480LbDI4z8LlgLxxf9HXstK0m5vQuAiV71kxLMICgt2mw7o?= =?us-ascii?Q?LEhtqvXT3zQDKGFfvVbi4WTacvx1CkM1sjgQp3sVJc+XmU7eb2uYkhGa5nst?= =?us-ascii?Q?rlqQyR/m9FrJkQ+7otAW50g/nZBycu7uyvPrLkgvhklly+tY9ymTlTPsJgQb?= =?us-ascii?Q?tnqHtyaVezZSp6+7meNTwGkAJw8t4iTt/QdEaL0y4B7CNZR9dXw9BlaUpkBh?= =?us-ascii?Q?Z0gImRMe/0FhNgbI/86RGHv0Bl4mq2afXaMs/zp+vkkF+ioiA6P5wNxnPoJ7?= =?us-ascii?Q?lpIzs8agL8Tl/Cfnkl72nhzmM53rSUjI21WUjICaWGZXhyecX+f8H3XZFmLD?= =?us-ascii?Q?UOki5+MdlhUL6vnoE+Hy9fb/qoqR4w+AyMLLTtRk3pr?= X-Microsoft-Exchange-Diagnostics: 1; TY1PR06MB0927; 5:pXL/SYZ7xjfF/Qu7OdfsbUdr6kTY2Q/iNQwpJQEfoYrzMmZdYpVgtOowhSnbhtqKGEfTFzujROHEf8g0z4Po1XMtQkepLDuESS4R8S5RnBxMbQTy7UnqdzVM4O+JSdW20wnQHWSru011vBGCzLSMCg==; 24:umB4LgQzSxMHdLwNPDMJSIfvLQw6sbboaxAwFvyIK9ebxOLDdrU/lPEN1ZM8p7Igd4rEC/CSg/heRwsngSNDpk1W2WJyY9s5HZDLBzVaNko=; 20:1vSvNnFJWTtrFWikw/sj5BKbtK81k4e2oCzL/CTCxcAxlbUVTHtLOcv3kWoyBj90rLVCLjsoRtHFq5U4cuziOfwGBTWgP00excJwCdwJn41Sn3jbGrG17+giEUU/QX80xE03pfzD6Q0g0X3Rrrvf5eTMplIOuHlGmxstltkdxZU= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: renesas.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Oct 2015 10:10:42.8953 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY1PR06MB0927 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.2 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 --- This patch is based on the latest linux-phy / next branch. (commit id = 6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f) Changes from v2: - Modify Kconfig to add "depends on OF" and "depends on ARCH_SHMOBILE". - Add more information in the dt document. - Change reg-names from "usb2" to "usb2_host". Changes from v1: - Revise some typos. - Remove using clk API to enable/disable the clocks. (In other words, this driver expects to enable/disable the clocks by Runtime PM API by the phy-core driver.) - Remove an unnecessary header file (asm/cmpxchg.h). .../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 47da573..ae3ba34 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 a5b18c1..97e83bc 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..f934e21 --- /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_phy_usb2_data { + void __iomem *base; + struct clk *clk; +}; + +struct rcar_gen3_phy_usb2_channel { + struct rcar_gen3_phy_usb2_data usb2; + struct rcar_gen3_phy_usb2_data hsusb; + struct phy *phy; + spinlock_t lock; +}; + +static int rcar_gen3_phy_usb2_init(struct phy *p) +{ + struct rcar_gen3_phy_usb2_channel *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_phy_usb2_channel *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_phy_usb2_channel *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_phy_usb2_channel *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_phy_usb2_channel *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 ");