From patchwork Tue May 20 12:09:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 4209131 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DD30A9F23C for ; Tue, 20 May 2014 12:09:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F00222035D for ; Tue, 20 May 2014 12:09:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 92DBC20353 for ; Tue, 20 May 2014 12:09:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752706AbaETMJZ (ORCPT ); Tue, 20 May 2014 08:09:25 -0400 Received: from mailout2.w1.samsung.com ([210.118.77.12]:19526 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752045AbaETMJY (ORCPT ); Tue, 20 May 2014 08:09:24 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0N5V008CAGF91QB0@mailout2.w1.samsung.com>; Tue, 20 May 2014 13:09:09 +0100 (BST) X-AuditID: cbfec7f4-b7fac6d000006cfe-00-537b45f1d03c Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 30.E0.27902.1F54B735; Tue, 20 May 2014 13:09:21 +0100 (BST) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync3.samsung.com (Oracle Communications Messaging Server 7u4-23.01 (7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0N5V00CHDGFIB7B0@eusync3.samsung.com>; Tue, 20 May 2014 13:09:21 +0100 (BST) From: Marek Szyprowski To: linux-usb@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Kishon Vijay Abraham I , Kamil Debski , Tomasz Figa Subject: [PATCH] drivers: phy: exynos4x12-phy: fix HSIC1 power on/off sequence Date: Tue, 20 May 2014 14:09:14 +0200 Message-id: <1400587754-8363-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrPJMWRmVeSWpSXmKPExsVy+t/xq7ofXauDDTZsFLP48foCm8WFpz1s FjPO72OyWLSsldli7ZG77BbrZ7xmcWDz6NuyitHj+I3tTB6fN8kFMEdx2aSk5mSWpRbp2yVw Zbw72Mha0Ktc8frlNbYGxomyXYwcHBICJhKffkd0MXICmWISF+6tZ+ti5OIQEljKKHH58gkW CKePSWL74rfMIFVsAoYSXW+72EBsEQEHiSVL74B1MAssYpT4tPEPWEJYwE/ixba/rCA2i4Cq xKSd51lAbF4Bd4k5s2axQKyTk/j/cgXTBEbuBYwMqxhFU0uTC4qT0nMN9YoTc4tL89L1kvNz NzFCAuHLDsbFx6wOMQpwMCrx8DrYVgULsSaWFVfmHmKU4GBWEuG94FQdLMSbklhZlVqUH19U mpNafIiRiYNTqoFRdGKoe0lBGMPEPbudprlOmcti2he1NLAwM7aIzVZAzEtGYVb4rCkiZ94V 986Ym9f2LJPl5J99H31N7wtfyjB8fm5up23VtxS3a6byCqqLuA9OWfUtfutWu4QZVlXNW95I HEt1nDhB4szkiZLvgyZer6v812KmoXy4uG/9Mt8tHguuuhuy1bxTYinOSDTUYi4qTgQAeqEf 6eIBAAA= 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=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 From experiments with real hardware, it seems that URSTCON bits for HSIC0 and HSIC1 seems to be swapped, so updated macro definitions for them. HSIC1 also requires enabling power to device phy to get properly enabled (similar hack is already implemented for HSIC0). Signed-off-by: Marek Szyprowski --- Hello, This fix for Exynos4x12 USB2 PHY driver is needed to add support for OdroidU3 board, which uses both HSIC0 and HSIC1 ports. Without it only LAN chip, which is connected to HSIC0 works correctly. Best regards Marek Szyprowski Samsung R&D Institute Poland --- drivers/phy/phy-exynos4x12-usb2.c | 48 +++++++++++++++++++++++++++------------ drivers/phy/phy-samsung-usb2.h | 2 +- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c index d92a7cc5698a..431568b5cc61 100644 --- a/drivers/phy/phy-exynos4x12-usb2.c +++ b/drivers/phy/phy-exynos4x12-usb2.c @@ -87,8 +87,16 @@ #define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2) #define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3) #define EXYNOS_4x12_URSTCON_PHY1 BIT(4) -#define EXYNOS_4x12_URSTCON_HSIC0 BIT(5) -#define EXYNOS_4x12_URSTCON_HSIC1 BIT(6) +/* + * According to Exynos 4x12 reference manual the values for + * EXYNOS_4x12_URSTCON_HSIC are: + * URSTCON_HSIC0 = BIT(5) + * URSTCON_HSIC1 = BIT(6) + * but from experiments with real hardware the above 2 bitfields + * seems to be swapped, so define them to match the actual + * hardware */ +#define EXYNOS_4x12_URSTCON_HSIC1 BIT(5) +#define EXYNOS_4x12_URSTCON_HSIC0 BIT(6) #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7) #define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8) #define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9) @@ -216,14 +224,15 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) break; case EXYNOS4x12_HSIC0: phypwr = EXYNOS_4x12_UPHYPWR_HSIC0; - rstbits = EXYNOS_4x12_URSTCON_HSIC1 | + rstbits = EXYNOS_4x12_URSTCON_HSIC0 | EXYNOS_4x12_URSTCON_HOST_LINK_P0 | EXYNOS_4x12_URSTCON_HOST_PHY; break; case EXYNOS4x12_HSIC1: phypwr = EXYNOS_4x12_UPHYPWR_HSIC1; rstbits = EXYNOS_4x12_URSTCON_HSIC1 | - EXYNOS_4x12_URSTCON_HOST_LINK_P1; + EXYNOS_4x12_URSTCON_HOST_LINK_P1 | + EXYNOS_4x12_URSTCON_HOST_PHY; break; }; @@ -256,18 +265,22 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst) { struct samsung_usb2_phy_driver *drv = inst->drv; + struct samsung_usb2_phy_instance *device = + &drv->instances[EXYNOS4x12_DEVICE]; - inst->enabled = 1; + inst->enabled++; exynos4x12_setup_clk(inst); exynos4x12_phy_pwr(inst, 1); exynos4x12_isol(inst, 0); /* Power on the device, as it is necessary for HSIC to work */ - if (inst->cfg->id == EXYNOS4x12_HSIC0) { - struct samsung_usb2_phy_instance *device = - &drv->instances[EXYNOS4x12_DEVICE]; - exynos4x12_phy_pwr(device, 1); - exynos4x12_isol(device, 0); + if (inst->cfg->id == EXYNOS4x12_HSIC0 || + inst->cfg->id == EXYNOS4x12_HSIC1) { + if (!device->enabled) { + exynos4x12_phy_pwr(device, 1); + exynos4x12_isol(device, 0); + } + device->enabled++; } return 0; @@ -279,13 +292,20 @@ static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst) struct samsung_usb2_phy_instance *device = &drv->instances[EXYNOS4x12_DEVICE]; - inst->enabled = 0; + inst->enabled--; + if (inst->enabled) + return 0; + exynos4x12_isol(inst, 1); exynos4x12_phy_pwr(inst, 0); - if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) { - exynos4x12_isol(device, 1); - exynos4x12_phy_pwr(device, 0); + if (inst->cfg->id == EXYNOS4x12_HSIC0 || + inst->cfg->id == EXYNOS4x12_HSIC1) { + device->enabled--; + if (!device->enabled) { + exynos4x12_isol(device, 1); + exynos4x12_phy_pwr(device, 0); + } } return 0; diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h index 51a16016a214..848744ab8f38 100644 --- a/drivers/phy/phy-samsung-usb2.h +++ b/drivers/phy/phy-samsung-usb2.h @@ -29,7 +29,7 @@ struct samsung_usb2_phy_instance { const struct samsung_usb2_common_phy *cfg; struct phy *phy; struct samsung_usb2_phy_driver *drv; - bool enabled; + int enabled; }; struct samsung_usb2_phy_driver {