From patchwork Wed Oct 7 00:30:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krzysztof Kozlowski X-Patchwork-Id: 7340961 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1D49ABEEA4 for ; Wed, 7 Oct 2015 00:32:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1EF9320719 for ; Wed, 7 Oct 2015 00:32:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0186820604 for ; Wed, 7 Oct 2015 00:32:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752960AbbJGAbD (ORCPT ); Tue, 6 Oct 2015 20:31:03 -0400 Received: from mailout2.w1.samsung.com ([210.118.77.12]:30470 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753336AbbJGAaZ (ORCPT ); Tue, 6 Oct 2015 20:30:25 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NVT007ZUQQMF000@mailout2.w1.samsung.com>; Wed, 07 Oct 2015 01:30:22 +0100 (BST) X-AuditID: cbfec7f4-f79c56d0000012ee-c5-5614679d03e9 Received: from eusync2.samsung.com ( [203.254.199.212]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 7E.5B.04846.D9764165; Wed, 7 Oct 2015 01:30:21 +0100 (BST) Received: from localhost.localdomain ([10.252.80.64]) by eusync2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NVT0051UQQ6T380@eusync2.samsung.com>; Wed, 07 Oct 2015 01:30:21 +0100 (BST) From: Krzysztof Kozlowski To: Greg Kroah-Hartman , Peter Chen , Marek Szyprowski , Ben Gamari , Wolfram Sang , Krzysztof Kozlowski , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Kukjin Kim , linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org Cc: Kevin Hilman , Arnd Bergmann , riku.voipio@linaro.org Subject: [RFT 2/3] usb: misc: usb3503: Allow usage of device through phy interface Date: Wed, 07 Oct 2015 09:30:06 +0900 Message-id: <1444177807-15524-3-git-send-email-k.kozlowski@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1444177807-15524-1-git-send-email-k.kozlowski@samsung.com> References: <1444177807-15524-1-git-send-email-k.kozlowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrMLMWRmVeSWpSXmKPExsVy+t/xK7pz00XCDI6fsbD4O+kYu8Ws+XdZ LOYfOcdq0bx4PZvF6xeGFv2PXzNbPN38mMli0+NrrBaXd81hs5hxfh+TxaJlrcwWa4/cZbc4 Nvsvk0XXuX4mi5UnZjE78Hv8/jWJ0ePf4X4mj02rOtk87lzbw+axf+4ado/NS+o9+rasYvQ4 89vZ4+SpJywenzfJBXBFcdmkpOZklqUW6dslcGUc/7yPseCBUsX8w7NYGhjbZboYOTkkBEwk ru1dxgJhi0lcuLeerYuRi0NIYCmjxNWZc6Cc/4wSi3qb2UGq2ASMJTYvXwKWEBE4xiyx9tdd RpAEs0CcxO0d/5hBbGGBEIktc9eBjWURUJW4d6mNCcTmFXCX2DX1BtQ6OYmTxyazgticAh4S G/v2gNlCQDVLXvawTWDkXcDIsIpRNLU0uaA4KT3XUK84Mbe4NC9dLzk/dxMjJKi/7GBcfMzq EKMAB6MSD+8PY5EwIdbEsuLK3EOMEhzMSiK8CkeEw4R4UxIrq1KL8uOLSnNSiw8xSnOwKInz zt31PkRIID2xJDU7NbUgtQgmy8TBKdXAWFkTlWt1en6u8PWl++16Vmctks/7qPojvsfjWVlx zbSVRhc3+331mLL36NejOaX/vZgPHJ+1vbNunh/LgpzpRtu/WGv9vZBbeyc8asUlbe4DjJ2N u0NUX82df3L9knl23o/X71R+I2XVV92xz7rwSOrlUg/D5zZztTgOKPhOihLUtCpz0OBLVWIp zkg01GIuKk4EAPN8qgpmAgAA Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=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 The USB3503 hub controller can be connected through I2C interface (e.g. on Odroid-U3 board) or directly by phy (e.g. on Arndale board). Thus the usb3503 driver can act as a i2c or platform device. In the second configuration (phy) the driver did not get a reference to necessary phy to use it. This lead to probe failure if PHY driver was probed after usb3503 probe. The patch adds support for generic phy framework so the driver will the phy reference (if provided) and use it. Signed-off-by: Krzysztof Kozlowski Reported-by: Kevin Hilman Reported-by: Arnd Bergmann Cc: Kevin Hilman Cc: Arnd Bergmann Cc: riku.voipio@linaro.org Cc: Marek Szyprowski --- drivers/usb/misc/usb3503.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 64ff5b91752d..e9423fc28105 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #define USB3503_VIDL 0x00 @@ -59,6 +60,7 @@ struct usb3503 { struct regmap *regmap; struct device *dev; struct clk *clk; + struct phy *phy; u8 port_off_mask; int gpio_intn; int gpio_reset; @@ -66,6 +68,29 @@ struct usb3503 { bool secondary_ref_clk; }; +static int usb3503_phy_on(struct usb3503 *hub) +{ + int err; + + err = phy_power_on(hub->phy); + if (err) + return err; + + err = phy_init(hub->phy); + if (err) { + phy_power_off(hub->phy); + return err; + } + + return 0; +} + +static void usb3503_phy_off(struct usb3503 *hub) +{ + phy_exit(hub->phy); + phy_power_off(hub->phy); +} + static int usb3503_reset(struct usb3503 *hub, int state) { if (!state && gpio_is_valid(hub->gpio_connect)) @@ -189,6 +214,13 @@ static int usb3503_probe(struct usb3503 *hub) u32 rate = 0; hub->port_off_mask = 0; + hub->phy = devm_phy_optional_get(dev, "usb2-phy"); + if (IS_ERR(hub->phy)) { + err = PTR_ERR(hub->phy); + if (err != -EPROBE_DEFER) + dev_err(dev, "unable to get phy: %d\n", err); + return err; + } if (!of_property_read_u32(np, "refclk-frequency", &rate)) { switch (rate) { case 38400000: @@ -300,6 +332,10 @@ static int usb3503_probe(struct usb3503 *hub) } } + err = usb3503_phy_on(hub); + if (err) + return err; + usb3503_switch_mode(hub, hub->mode); dev_info(dev, "%s: probed in %s mode\n", __func__, @@ -339,9 +375,29 @@ static int usb3503_platform_probe(struct platform_device *pdev) return -ENOMEM; hub->dev = &pdev->dev; + platform_set_drvdata(pdev, hub); + return usb3503_probe(hub); } +static int usb3503_i2c_remove(struct i2c_client *i2c) +{ + struct usb3503 *hub = i2c_get_clientdata(i2c); + + usb3503_phy_off(hub); + + return 0; +} + +static int usb3503_platform_remove(struct platform_device *pdev) +{ + struct usb3503 *hub = platform_get_drvdata(pdev); + + usb3503_phy_off(hub); + + return 0; +} + #ifdef CONFIG_PM_SLEEP static int usb3503_i2c_suspend(struct device *dev) { @@ -350,6 +406,8 @@ static int usb3503_i2c_suspend(struct device *dev) usb3503_switch_mode(hub, USB3503_MODE_STANDBY); + usb3503_phy_off(hub); + if (hub->clk) clk_disable_unprepare(hub->clk); @@ -360,10 +418,15 @@ static int usb3503_i2c_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct usb3503 *hub = i2c_get_clientdata(client); + int err; if (hub->clk) clk_prepare_enable(hub->clk); + err = usb3503_phy_on(hub); + if (err) + return err; + usb3503_switch_mode(hub, hub->mode); return 0; @@ -395,6 +458,7 @@ static struct i2c_driver usb3503_i2c_driver = { .of_match_table = of_match_ptr(usb3503_of_match), }, .probe = usb3503_i2c_probe, + .remove = usb3503_i2c_remove, .id_table = usb3503_id, }; @@ -404,6 +468,7 @@ static struct platform_driver usb3503_platform_driver = { .of_match_table = of_match_ptr(usb3503_of_match), }, .probe = usb3503_platform_probe, + .remove = usb3503_platform_remove, }; static int __init usb3503_init(void)