From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933161AbcGIFEH (ORCPT ); Sat, 9 Jul 2016 01:04:07 -0400 Received: from mail-sn1nam02on0057.outbound.protection.outlook.com ([104.47.36.57]:20389 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933048AbcGIFDy (ORCPT ); Sat, 9 Jul 2016 01:03:54 -0400 X-Greylist: delayed 1107 seconds by postgrey-1.27 at vger.kernel.org; Sat, 09 Jul 2016 01:03:53 EDT Authentication-Results: spf=none (sender IP is 192.88.168.50) smtp.mailfrom=lvd4224.freescale.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=fail action=none header.from=nxp.com; From: Rajesh Bhagat To: , , CC: , , , , , , Rajesh Bhagat Subject: [PATCH v2 3/5] drivers: usb: phy: Add qoriq usb 2.0 phy driver support Date: Sat, 9 Jul 2016 10:00:54 +0530 Message-ID: <1468038656-10345-4-git-send-email-rajesh.bhagat@nxp.com> X-Mailer: git-send-email 1.7.7.4 In-Reply-To: <1468038656-10345-1-git-send-email-rajesh.bhagat@nxp.com> References: <1468038656-10345-1-git-send-email-rajesh.bhagat@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131125122599146039;(91ab9b29-cfa4-454e-5278-08d120cd25b8);() X-Forefront-Antispam-Report: CIP:192.88.168.50;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6039001)(6009001)(7916002)(2980300002)(428002)(199003)(189002)(33646002)(19580395003)(356003)(105586002)(45336002)(19580405001)(68736007)(103686003)(90966002)(305945005)(189998001)(7846002)(8666005)(47776003)(36756003)(16796002)(81156014)(6806005)(106466001)(50226002)(11100500001)(46386002)(87936001)(81166006)(8676002)(97736004)(8936002)(48376002)(586003)(86372001)(50986999)(52956003)(229853001)(2906002)(101416001)(42186005)(960300001)(2201001)(5001770100001)(5003940100001)(50466002)(76176999)(92566002)(4326007)(2950100001)(7059030)(2004002)(42882005)(4720700001);DIR:OUT;SFP:1101;SCL:1;SRVR:BLUPR0301MB2017;H:tx30smr01.am.freescale.net;FPR:;SPF:None;PTR:InfoDomainNonexistent;A:0;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD022;1:9hELFaqZZtAjETOEQRvMS5My9B0/wrP0VBKKZ2zFbT3B8SdWmKdVFJlIOxEBiw4/CtkN7NLEo9xPe/2EcFVMRbkwePm5VKFMEZIHT+xhQLCMC3lGUhCdIwyU9T61lpiTRbjVr3U63UB/EvjlnpZwuk4XzTLW/cfKbyS5EFksqoxBgv4cGl31TXJ0gaqA9WJwsqHVeEsPnhDXRutaXAesZPHK2QuPeIIDJajBquDYEqr4rg+SYPTh8SNm0aMCTyM/YqGm/OmPq89bRAKQD7LYGiiBgNRBiHgKMAAQ56UzwF22P2+K1ynJPC+p6h8rAat9StjiPV4yH1MEbi64WiDYMnhp7QCi/w0hNMXSxjhhCsErxV0FtE08ZRnah5a2kxZQB6tPYj0pQMbLOdVAR6uFY168ph2uRXtlldki6irxutJIJ1FhfQpAsfm7I1rpjhheKctTXA+rA5JyyxDeDVWHsHaUpb1NGteOv1wNhNb6YYSYEiFYao167XUvxaPPGRHQX2RReyQlzh9oYopM1IAlsW9J9hEZUd1RM8T6Kxq6jYhElypwSC6bJs8DjrHGOTw7lYm/D6Lb9yfMLQCMYPXvuLKY66yVXjzDMIXEPzAloqQ= MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: a96e902b-aef1-419e-d237-08d3a7b1d41d X-Microsoft-Exchange-Diagnostics: 1;BLUPR0301MB2017;2:kilFdrgesEcQ0e/m9mn33GNgfOiLiuANBFFZUwqzQakn4ng7B82NBouD+WWRw/1sObxyZ3mDxWx5ih3j1bD58yDXsa6HkS9b6I4eZ+IErWLXSsAzkPrUm25r6rPNUjhQKeHfYjQomPbhUlLkwdk9icGNqCuuRTQVB6bhmTfA0KS/KmnNqtqdqPCB5IPCKrIG;3:PE/fPasTyGswftjvlsQUcqDqxYqnqwyzIXZgh22PEIp2dMt8WhRtuX5KukQ1SlCRKxBbljhzABdyMG6MPXPEWAKaYN9Km9akfBBp/brDlulNX2LROfRnBfLy9UUW5n00YWfjX7/0FntFuY5vCZDdQs59Oi6UUrT2IYwurRE4JZAY10Ttf2cD3tehDkhrcB8DdyP+5ttDPDoQhCMRO98HvzGEFUwIpTEIqXXikrXaDd0=;25:VpbyRf/UZgRdjAZhAZO++65iR4Gq/j/0zxyykvOn0nDGVGF5o7JrSqGrZjZZ5tKBeZjii9SUJT7SikqzKf2zP+1cE2n6rJr32Al2dVTEWaHE7pMPoLOn4zRJXiXdmKEEoIDBqtcDH1O+t70OB4KpBiJCuKFF3q8O/w4FsYaBegwrU3Z8Y57JmAdvv90zucPetIYujEcmvu7mtV8ymtTE2qbiji1tRluAf6Bon2JwwgnbaVbNncQ/jX3FFxl6mho6YLIPNuDDIiZbkgok634UwyJ0rhlxNioWyJPhremEnjCh0CNqX6Fgzlsj9tQsfWCgpdHjD8YmDJVWuEhfC3OE5oFL/QzSGM0oDbNEvThGfxEMQt5ZXPmqyvDSYhoFMES+zUWSRMxQvP3ShHED27Aa3TdX9FS/4eO7U3z5uN+RsDY= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR0301MB2017; X-Microsoft-Exchange-Diagnostics: 1;BLUPR0301MB2017;31:ZSa8qg6VsaTaNnyAhQdowCRdutI0WhsNpp/HKcCiwwmb7TX8o1Zyv5ui7M1pSITkxdhIwcnqouFbDtHB4MuXFF95MLH6hIyK/8I30w9H9RL8WFKNY0cvweUlHvv7MkJuFk+dx2e7f9Nuurfp6Nv5rc0C7ndV9+DtkVqzKSvsO5QRw2IP8O3BGbp9chUKao3QTEUHF87TvqqgbyxkOdjsUA==;4:QnlAVT22AAAB5DitHbYY9ptXaO9w99qUBfbv4BWEzDRR4wrrh1F6scSHV0rv6c78Q+cUQgd4OhcCSeuUjUw6CMKEf3a8pWFyehz4YW4uF1NGnqFgpPZIjZYyEiBMhvweO9x6UzQOJYzwvhL71C8r9fhWmk8Ewuhpe4Lvn4zKi/QcArcc3+U6PnxeQB7l9wSDbq8GOwH8wttA97sTyIVMB1+tY9xjjeuTkgarKZeHnJHdGWVJnNU0AcN33fXaKPCoTgQ5NTGIClFUWiJAZy5NOwCYEGgZRHaf3R0RyQg4dnKc4Dq21VdvFlM8wtZzOxLX8212LSg4C1ZbDyq/086V5m3xhZXXfo+KgS3HnzhY0zkwJCSv9o4MMVXHKroW+iJDHWrSbBAQx64n82o3svoyT2I15MEx/aIPEMy5yG0vUFGGshyrtWlX4ahUYtRLeFXV3HOPqxzKapj7MNQ+WMWAWutkYPQRz4R9yMX+DaaeaawfoADOwgYC26oOnOLUA3TFmOaEIHLPxUOwtyJH9z6cmQ== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(5005006)(8121501046)(13023025)(13018025)(13017025)(13015025)(13024025)(3002001)(10201501046)(6055026);SRVR:BLUPR0301MB2017;BCL:0;PCL:0;RULEID:(400006);SRVR:BLUPR0301MB2017; X-Forefront-PRVS: 0998671D02 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BLUPR0301MB2017;23:n07x8WKV8B7LO9f9dH+IuSrj8H+01VCWYsUR3B+?= =?us-ascii?Q?OjLOPxrwx7wr1iCoc6W61VtJ/2mZFN1cc1egY65HJcS/0syIxsZxEVL6DKN4?= =?us-ascii?Q?qdIeAnngfSOBL9iamT/uro9inAgjklCTZRm2L3nHKnz+ZWi1ocjlwQ6+JLf6?= =?us-ascii?Q?4lsgC7QqJnqrzYV/yM3PkUfwtrERwXsGghI6oCkoEVzSwEMwZ0sRu2HIVKp3?= =?us-ascii?Q?f+wjNTyF6Nfpf4T3Ht2M+CX3dTK6K6NqrQnQFnQitZwxAtn/cmC+ERdpZjBo?= =?us-ascii?Q?u3pbzeiH4skMvTp/6IQ/lNGDHc2W8kcYka3Oyt+8SOyB55mbp6BuBJPrcqpa?= =?us-ascii?Q?0B+Ru4G+6mcsWiWC8bvXucHGTSXH9HzzKAHXWY7/ZfA7nNa7PK18LtU3pqmB?= =?us-ascii?Q?6PZ6iU4zTDuWQGF9jUgtTKtl+uFAiI7LjrVZawrM8BuYg9DE48v1AIIOUyow?= =?us-ascii?Q?kZ3KuOlLCPXhwbYaXKoSxAJ9yj97cyZ7B44JqmTw0Zbo6nPkWM8BtiNArOoa?= =?us-ascii?Q?czs2n1BEaLdmlRCCntU59+bhW35r/l78uXkNrCXI0jJNhPi0RvsJHxc6Owtn?= =?us-ascii?Q?7Ozalid2Eu0ooN4qHZL8uVcxJrZODjhRQylhX9+f9eiUMKQ3AK9UkoZT6dvr?= =?us-ascii?Q?heUJiRCahnChSm9PTtUAaaivtk/SIzi3HxSFvLHGec2pRmpC6CK1np02ZbIX?= =?us-ascii?Q?eyyjjv3Sc9C4N4VcJWAXopVon0eGa5rXF/2udG12seEvAbplq7ZdHvywkpwi?= =?us-ascii?Q?yfa+KlAO/Kta72smNcpXDsKDNwDemxtL2AE35x73Tben4ofVLSNkjjgDInNW?= =?us-ascii?Q?7Jdv8nU7jNM22DLz8E/ETvQgLZqKntU7KjjQTzk9bjMxkSEna2e1fv472wRK?= =?us-ascii?Q?Azi5pE8yn9US5AmGkyxM9iqhJpbzKlBd7lZjSbUhS94mIhWz16OTubzJTJpu?= =?us-ascii?Q?sI5uYTm8LfURJNHmeSoKbu1y3523oYdAxBzmyQFwI1vtP+G8s2W48yLDmia9?= =?us-ascii?Q?7RuSRjtt3LhzHxovb4BtG+MiiZGI9+p7yMUIPx5g1q11NkP0e7S+PMKvd+JY?= =?us-ascii?Q?hXsFHSyr1/kJZEBjpg2iJYI5Kq1dJrTdN/i8+q+c9193DwQxWU7LtXY6Z9An?= =?us-ascii?Q?W5zQdvm1TAUEoLzU5tXi5fDU9PwQdsenP07ttKbNnxwtJhREyymD5Vb02AW8?= =?us-ascii?Q?oWeT3eE7gcHTVfl/MdiKIwXY6UirE6UHx0v7W76qMr9PH4hRhE86O9QFS7YG?= =?us-ascii?Q?RGbP92rtn3g3e+BMf2CrthWiiS/oJV0MQC00fa0r9/maZUv8/FIi+XeAj4Ri?= =?us-ascii?Q?CLen34ZRIXgNHKtxBsaQKgXeTVgbt0yU4iH91qN3fb4F2?= X-Microsoft-Exchange-Diagnostics: 1;BLUPR0301MB2017;6:up0QaANx9jLmvu7XfMxApO50v6uFVu/lKhtNtLmZaKWwTpX8aUlpnTEqEb7CVdTzqtigEnXCxcMH0982YCcnx7ltS0Ytc7QcXvtZ8RJkF3h1Tl+vurADfVL97Qk/EzfsD5vPFjSEjcozDCyGSws57zUvP0N2EW7GBC9caGxmwz1Np3cIlfuGkg4QKuTGYyvRVnR8ySbYKYVBLbwuJTwQ+N4EmRn+46lDmznxbLYZJex7iF9SqmrLLUCJ2NsbamuMqtTWVpYVcVkAVofFFygwUPxtBCUrN7yVtCWtwL4eooE=;5:maUIKsaHPOH1Z8KOR+bE5Eb/BaIfk+82Bq2uNOV0RYBdKMO7ZEaqYtoeuPjAXpco1i/21Jkg/+CvWDz7qP7Rmvnxun8tb+HdmSsSb/rVL5RM5uvKF7TytYZVEbMa4+VR5JJC2HB2BeAruX/0ehe1kpaRIK5DZruIRgiENIEO8Rs=;24:AzrOQjtuVku6kbc+QoQwSqdPPUOT1Bf9mkgx/H5+j6Qa71KXKPejHGR4yfda+L0UYhhd0PnAUKAL0AiZGj7EIexeCJSgLIOvAHZ6IVnt6nM=;7:CFr2ZUfg3SwXPq4xNTmcDjXDbRtz/JQBSq+O/A5eK4Jwp6W/XPg2R2Qdy67UOZhtq+hKga6nqpHb9wOwmACVKTN7YCV+0VBWIDC2TUuqBu1yiVeepvAf2xXOQx1ZK8pKQ4UsH+qCljbk8ArFJ1qbyPn2h99h0CAnfD+JdamEY4D3zW1lC5+qrA9RCveTame1UZn/QBmd41fP7FN5QB3IejQTZ03XTH8Ir1yJCKkl90hEW3IYOVFVg3unlSyzvhxa SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Jul 2016 04:30:59.6026 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e;Ip=[192.88.168.50];Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR0301MB2017 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adds qoriq usb 2.0 phy driver support for LS1021A and LS1012A platform. Signed-off-by: Rajesh Bhagat --- Changes in v2: - Replaced Freescale with QorIQ in comments section - Changed the compatible string to fsl,qoriq-usb2-phy and added version - Added dependency on ARCH_MXC/ARCH_LAYERSCAPE and OF in Kconfig - Dropped CONFIG_ULPI #ifdefs to make code generic - Removed calls to devm free/release calls drivers/phy/Kconfig | 8 ++ drivers/phy/Makefile | 1 + drivers/phy/phy-qoriq-usb2.c | 228 +++++++++++++++++++++++++++++++++++++++++++ drivers/phy/phy-qoriq-usb2.h | 50 ++++++++++ 4 files changed, 287 insertions(+) create mode 100644 drivers/phy/phy-qoriq-usb2.c create mode 100644 drivers/phy/phy-qoriq-usb2.h diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index b869b98..cc69299 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -434,4 +434,12 @@ config PHY_CYGNUS_PCIE source "drivers/phy/tegra/Kconfig" +config PHY_QORIQ_USB2 + tristate "QorIQ USB 2.0 PHY driver" + depends on ARCH_MXC || ARCH_LAYERSCAPE + depends on OF + select GENERIC_PHY + help + Enable this to support the USB2.0 PHY on the QorIQ SoC. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 9c3e73c..044105a 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -53,5 +53,6 @@ obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o +obj-$(CONFIG_PHY_QORIQ_USB2) += phy-qoriq-usb2.o obj-$(CONFIG_ARCH_TEGRA) += tegra/ diff --git a/drivers/phy/phy-qoriq-usb2.c b/drivers/phy/phy-qoriq-usb2.c new file mode 100644 index 0000000..f74d255 --- /dev/null +++ b/drivers/phy/phy-qoriq-usb2.c @@ -0,0 +1,228 @@ +/* + * QorIQ SoC USB 2.0 PHY driver + * + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Rajesh Bhagat + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "phy-qoriq-usb2.h" + +static int qoriq_usb2_phy_init(struct phy *_phy) +{ + struct qoriq_usb2_phy_ctx *ctx = phy_get_drvdata(_phy); + struct device *dev = ctx->dev; + + if (ctx->ulpi_phy) { + if (usb_phy_init(ctx->ulpi_phy)) { + dev_err(dev, "unable to init transceiver, probably missing\n"); + return -ENODEV; + } + } + + return 0; +} + +static int qoriq_usb2_phy_power_on(struct phy *_phy) +{ + struct qoriq_usb2_phy_ctx *ctx = phy_get_drvdata(_phy); + u32 flags; + + if (ctx->ulpi_phy) { + flags = usb_phy_io_read(ctx->ulpi_phy, ULPI_OTG_CTRL); + usb_phy_io_write(ctx->ulpi_phy, flags | + (ULPI_OTG_CTRL_DRVVBUS_EXT | + ULPI_OTG_CTRL_EXTVBUSIND), ULPI_OTG_CTRL); + flags = usb_phy_io_read(ctx->ulpi_phy, ULPI_IFC_CTRL); + usb_phy_io_write(ctx->ulpi_phy, flags | + (ULPI_IFC_CTRL_EXTERNAL_VBUS | + ULPI_IFC_CTRL_PASSTHRU), ULPI_IFC_CTRL); + } + + return 0; +} + +static int qoriq_usb2_phy_power_off(struct phy *_phy) +{ + /* TODO: Add logic to power off phy */ + + return 0; +} + +static int qoriq_usb2_phy_exit(struct phy *_phy) +{ + struct qoriq_usb2_phy_ctx *ctx = phy_get_drvdata(_phy); + + if (ctx->ulpi_phy) + usb_phy_shutdown(ctx->ulpi_phy); + + return 0; +} + +static const struct phy_ops ops = { + .init = qoriq_usb2_phy_init, + .power_on = qoriq_usb2_phy_power_on, + .power_off = qoriq_usb2_phy_power_off, + .exit = qoriq_usb2_phy_exit, + .owner = THIS_MODULE, +}; + + +static enum qoriq_usb2_phy_ver of_usb_get_phy_version(struct device_node *np) +{ + enum qoriq_usb2_phy_ver phy_version = QORIQ_PHY_UNKNOWN; + + if (of_device_is_compatible(np, "fsl,qoriq-usb2-phy")) { + if (of_device_is_compatible(np, "fsl,qoriq-usb2-phy-v1.0")) + phy_version = QORIQ_PHY_LEGACY; + else if (of_device_is_compatible(np, "fsl,qoriq-usb2-phy-v2.0")) + phy_version = QORIQ_PHY_NXP_ISP1508; + } + return phy_version; +} + +static int qoriq_usb2_phy_probe(struct platform_device *pdev) +{ + int ret; + struct resource *res; + struct qoriq_usb2_phy_ctx *ctx; + struct device *dev = &pdev->dev; + const struct of_device_id *of_id; + struct phy_provider *phy_provider; + struct device_node *np = pdev->dev.of_node; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->dev = dev; + + of_id = of_match_device(dev->driver->of_match_table, dev); + if (!of_id) { + dev_err(dev, "failed to get device match\n"); + ret = -EINVAL; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to get I/O memory\n"); + ret = -ENOENT; + goto err_out; + } + + ctx->regs = devm_ioremap(dev, res->start, resource_size(res)); + if (!ctx->regs) { + dev_err(dev, "failed to remap I/O memory\n"); + ret = -ENOMEM; + goto err_out; + } + + platform_set_drvdata(pdev, ctx); + + ctx->phy = devm_phy_create(ctx->dev, NULL, &ops); + if (IS_ERR(ctx->phy)) { + dev_err(dev, "failed to create PHY\n"); + ret = PTR_ERR(ctx->phy); + goto err_out; + } + phy_set_drvdata(ctx->phy, ctx); + + ctx->phy_version = of_usb_get_phy_version(np); + if (ctx->phy_version == QORIQ_PHY_UNKNOWN) { + ret = -EINVAL; + dev_err(dev, "failed to get PHY version\n"); + goto err_out; + } + + ctx->phy_type = of_usb_get_phy_mode(np); + switch (ctx->phy_type) { + case USBPHY_INTERFACE_MODE_ULPI: + switch (ctx->phy_version) { + case QORIQ_PHY_NXP_ISP1508: + ctx->ulpi_phy = qoriq_otg_ulpi_create(0); + if (!ctx->ulpi_phy) { + dev_err(dev, "qoriq_otg_ulpi_create returned NULL\n"); + ret = -ENOMEM; + goto err_out; + } + ctx->ulpi_phy->io_priv = ctx->regs + ULPI_VIEWPORT; + break; + default: + ctx->ulpi_phy = NULL; + break; + } + break; + default: + dev_err(&pdev->dev, "phy_type %d is invalid or unsupported\n", + ctx->phy_type); + ret = -EINVAL; + goto err_out; + } + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) { + dev_err(dev, "failed to register phy_provider\n"); + ret = PTR_ERR_OR_ZERO(phy_provider); + goto err_out; + } + + dev_dbg(dev, "initialized\n"); + return 0; + +err_out: + return ret; +} + +static int qoriq_usb2_phy_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct qoriq_usb2_phy_ctx *ctx = platform_get_drvdata(pdev); + + devm_phy_destroy(ctx->dev, ctx->phy); + devm_iounmap(dev, ctx->regs); + dev_dbg(dev, "de-initialized\n"); + return 0; +} + +static const struct of_device_id qoriq_usb2_phy_dt_ids[] = { + { .compatible = "fsl,qoriq-usb2-phy"}, + {} +}; + +MODULE_DEVICE_TABLE(of, qoriq_usb2_phy_dt_ids); + +static struct platform_driver qoriq_usb2_phy_driver = { + .probe = qoriq_usb2_phy_probe, + .remove = qoriq_usb2_phy_remove, + .driver = { + .name = "qoriq_usb2_phy", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(qoriq_usb2_phy_dt_ids), + }, +}; + +module_platform_driver(qoriq_usb2_phy_driver); + +MODULE_ALIAS("platform:qoriq-usb2-phy"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("QorIQ SoC USB PHY driver"); +MODULE_AUTHOR("Rajesh Bhagat "); diff --git a/drivers/phy/phy-qoriq-usb2.h b/drivers/phy/phy-qoriq-usb2.h new file mode 100644 index 0000000..47c37a5 --- /dev/null +++ b/drivers/phy/phy-qoriq-usb2.h @@ -0,0 +1,50 @@ +/* + * Freescale SoC USB 2.0 PHY driver + * + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Rajesh Bhagat + * + * 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. + * + */ +#ifndef _PHY_QORIQ_USB2_H +#define _PHY_QORIQ_USB2_H + +#include +#include +#include +#include + +#define ULPI_VIEWPORT 0x170 + +enum qoriq_usb2_phy_ver { + QORIQ_PHY_LEGACY, + QORIQ_PHY_NXP_ISP1508, + QORIQ_PHY_UNKNOWN, +}; + +struct qoriq_usb2_phy_ctx { + struct phy *phy; + struct clk *clk; + struct device *dev; + void __iomem *regs; + struct usb_phy *ulpi_phy; + enum usb_phy_interface phy_type; + enum qoriq_usb2_phy_ver phy_version; +}; + +#ifdef CONFIG_USB_ULPI_VIEWPORT +static inline struct usb_phy *qoriq_otg_ulpi_create(unsigned int flags) +{ + return otg_ulpi_create(&ulpi_viewport_access_ops, flags); +} +#else +static inline struct usb_phy *qoriq_otg_ulpi_create(unsigned int flags) +{ + return NULL; +} +#endif + +#endif -- 2.6.2.198.g614a2ac From mboxrd@z Thu Jan 1 00:00:00 1970 From: Rajesh Bhagat Subject: [PATCH v2 3/5] drivers: usb: phy: Add qoriq usb 2.0 phy driver support Date: Sat, 9 Jul 2016 10:00:54 +0530 Message-ID: <1468038656-10345-4-git-send-email-rajesh.bhagat@nxp.com> References: <1468038656-10345-1-git-send-email-rajesh.bhagat@nxp.com> Mime-Version: 1.0 Content-Type: text/plain Return-path: In-Reply-To: <1468038656-10345-1-git-send-email-rajesh.bhagat-3arQi8VN3Tc@public.gmane.org> Sender: linux-usb-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: Peter.Chen-3arQi8VN3Tc@public.gmane.org, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org, kishon-l0cyMroinI0@public.gmane.org, robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, Rajesh Bhagat List-Id: devicetree@vger.kernel.org Adds qoriq usb 2.0 phy driver support for LS1021A and LS1012A platform. Signed-off-by: Rajesh Bhagat --- Changes in v2: - Replaced Freescale with QorIQ in comments section - Changed the compatible string to fsl,qoriq-usb2-phy and added version - Added dependency on ARCH_MXC/ARCH_LAYERSCAPE and OF in Kconfig - Dropped CONFIG_ULPI #ifdefs to make code generic - Removed calls to devm free/release calls drivers/phy/Kconfig | 8 ++ drivers/phy/Makefile | 1 + drivers/phy/phy-qoriq-usb2.c | 228 +++++++++++++++++++++++++++++++++++++++++++ drivers/phy/phy-qoriq-usb2.h | 50 ++++++++++ 4 files changed, 287 insertions(+) create mode 100644 drivers/phy/phy-qoriq-usb2.c create mode 100644 drivers/phy/phy-qoriq-usb2.h diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index b869b98..cc69299 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -434,4 +434,12 @@ config PHY_CYGNUS_PCIE source "drivers/phy/tegra/Kconfig" +config PHY_QORIQ_USB2 + tristate "QorIQ USB 2.0 PHY driver" + depends on ARCH_MXC || ARCH_LAYERSCAPE + depends on OF + select GENERIC_PHY + help + Enable this to support the USB2.0 PHY on the QorIQ SoC. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 9c3e73c..044105a 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -53,5 +53,6 @@ obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o +obj-$(CONFIG_PHY_QORIQ_USB2) += phy-qoriq-usb2.o obj-$(CONFIG_ARCH_TEGRA) += tegra/ diff --git a/drivers/phy/phy-qoriq-usb2.c b/drivers/phy/phy-qoriq-usb2.c new file mode 100644 index 0000000..f74d255 --- /dev/null +++ b/drivers/phy/phy-qoriq-usb2.c @@ -0,0 +1,228 @@ +/* + * QorIQ SoC USB 2.0 PHY driver + * + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Rajesh Bhagat + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "phy-qoriq-usb2.h" + +static int qoriq_usb2_phy_init(struct phy *_phy) +{ + struct qoriq_usb2_phy_ctx *ctx = phy_get_drvdata(_phy); + struct device *dev = ctx->dev; + + if (ctx->ulpi_phy) { + if (usb_phy_init(ctx->ulpi_phy)) { + dev_err(dev, "unable to init transceiver, probably missing\n"); + return -ENODEV; + } + } + + return 0; +} + +static int qoriq_usb2_phy_power_on(struct phy *_phy) +{ + struct qoriq_usb2_phy_ctx *ctx = phy_get_drvdata(_phy); + u32 flags; + + if (ctx->ulpi_phy) { + flags = usb_phy_io_read(ctx->ulpi_phy, ULPI_OTG_CTRL); + usb_phy_io_write(ctx->ulpi_phy, flags | + (ULPI_OTG_CTRL_DRVVBUS_EXT | + ULPI_OTG_CTRL_EXTVBUSIND), ULPI_OTG_CTRL); + flags = usb_phy_io_read(ctx->ulpi_phy, ULPI_IFC_CTRL); + usb_phy_io_write(ctx->ulpi_phy, flags | + (ULPI_IFC_CTRL_EXTERNAL_VBUS | + ULPI_IFC_CTRL_PASSTHRU), ULPI_IFC_CTRL); + } + + return 0; +} + +static int qoriq_usb2_phy_power_off(struct phy *_phy) +{ + /* TODO: Add logic to power off phy */ + + return 0; +} + +static int qoriq_usb2_phy_exit(struct phy *_phy) +{ + struct qoriq_usb2_phy_ctx *ctx = phy_get_drvdata(_phy); + + if (ctx->ulpi_phy) + usb_phy_shutdown(ctx->ulpi_phy); + + return 0; +} + +static const struct phy_ops ops = { + .init = qoriq_usb2_phy_init, + .power_on = qoriq_usb2_phy_power_on, + .power_off = qoriq_usb2_phy_power_off, + .exit = qoriq_usb2_phy_exit, + .owner = THIS_MODULE, +}; + + +static enum qoriq_usb2_phy_ver of_usb_get_phy_version(struct device_node *np) +{ + enum qoriq_usb2_phy_ver phy_version = QORIQ_PHY_UNKNOWN; + + if (of_device_is_compatible(np, "fsl,qoriq-usb2-phy")) { + if (of_device_is_compatible(np, "fsl,qoriq-usb2-phy-v1.0")) + phy_version = QORIQ_PHY_LEGACY; + else if (of_device_is_compatible(np, "fsl,qoriq-usb2-phy-v2.0")) + phy_version = QORIQ_PHY_NXP_ISP1508; + } + return phy_version; +} + +static int qoriq_usb2_phy_probe(struct platform_device *pdev) +{ + int ret; + struct resource *res; + struct qoriq_usb2_phy_ctx *ctx; + struct device *dev = &pdev->dev; + const struct of_device_id *of_id; + struct phy_provider *phy_provider; + struct device_node *np = pdev->dev.of_node; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->dev = dev; + + of_id = of_match_device(dev->driver->of_match_table, dev); + if (!of_id) { + dev_err(dev, "failed to get device match\n"); + ret = -EINVAL; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to get I/O memory\n"); + ret = -ENOENT; + goto err_out; + } + + ctx->regs = devm_ioremap(dev, res->start, resource_size(res)); + if (!ctx->regs) { + dev_err(dev, "failed to remap I/O memory\n"); + ret = -ENOMEM; + goto err_out; + } + + platform_set_drvdata(pdev, ctx); + + ctx->phy = devm_phy_create(ctx->dev, NULL, &ops); + if (IS_ERR(ctx->phy)) { + dev_err(dev, "failed to create PHY\n"); + ret = PTR_ERR(ctx->phy); + goto err_out; + } + phy_set_drvdata(ctx->phy, ctx); + + ctx->phy_version = of_usb_get_phy_version(np); + if (ctx->phy_version == QORIQ_PHY_UNKNOWN) { + ret = -EINVAL; + dev_err(dev, "failed to get PHY version\n"); + goto err_out; + } + + ctx->phy_type = of_usb_get_phy_mode(np); + switch (ctx->phy_type) { + case USBPHY_INTERFACE_MODE_ULPI: + switch (ctx->phy_version) { + case QORIQ_PHY_NXP_ISP1508: + ctx->ulpi_phy = qoriq_otg_ulpi_create(0); + if (!ctx->ulpi_phy) { + dev_err(dev, "qoriq_otg_ulpi_create returned NULL\n"); + ret = -ENOMEM; + goto err_out; + } + ctx->ulpi_phy->io_priv = ctx->regs + ULPI_VIEWPORT; + break; + default: + ctx->ulpi_phy = NULL; + break; + } + break; + default: + dev_err(&pdev->dev, "phy_type %d is invalid or unsupported\n", + ctx->phy_type); + ret = -EINVAL; + goto err_out; + } + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) { + dev_err(dev, "failed to register phy_provider\n"); + ret = PTR_ERR_OR_ZERO(phy_provider); + goto err_out; + } + + dev_dbg(dev, "initialized\n"); + return 0; + +err_out: + return ret; +} + +static int qoriq_usb2_phy_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct qoriq_usb2_phy_ctx *ctx = platform_get_drvdata(pdev); + + devm_phy_destroy(ctx->dev, ctx->phy); + devm_iounmap(dev, ctx->regs); + dev_dbg(dev, "de-initialized\n"); + return 0; +} + +static const struct of_device_id qoriq_usb2_phy_dt_ids[] = { + { .compatible = "fsl,qoriq-usb2-phy"}, + {} +}; + +MODULE_DEVICE_TABLE(of, qoriq_usb2_phy_dt_ids); + +static struct platform_driver qoriq_usb2_phy_driver = { + .probe = qoriq_usb2_phy_probe, + .remove = qoriq_usb2_phy_remove, + .driver = { + .name = "qoriq_usb2_phy", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(qoriq_usb2_phy_dt_ids), + }, +}; + +module_platform_driver(qoriq_usb2_phy_driver); + +MODULE_ALIAS("platform:qoriq-usb2-phy"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("QorIQ SoC USB PHY driver"); +MODULE_AUTHOR("Rajesh Bhagat "); diff --git a/drivers/phy/phy-qoriq-usb2.h b/drivers/phy/phy-qoriq-usb2.h new file mode 100644 index 0000000..47c37a5 --- /dev/null +++ b/drivers/phy/phy-qoriq-usb2.h @@ -0,0 +1,50 @@ +/* + * Freescale SoC USB 2.0 PHY driver + * + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Rajesh Bhagat + * + * 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. + * + */ +#ifndef _PHY_QORIQ_USB2_H +#define _PHY_QORIQ_USB2_H + +#include +#include +#include +#include + +#define ULPI_VIEWPORT 0x170 + +enum qoriq_usb2_phy_ver { + QORIQ_PHY_LEGACY, + QORIQ_PHY_NXP_ISP1508, + QORIQ_PHY_UNKNOWN, +}; + +struct qoriq_usb2_phy_ctx { + struct phy *phy; + struct clk *clk; + struct device *dev; + void __iomem *regs; + struct usb_phy *ulpi_phy; + enum usb_phy_interface phy_type; + enum qoriq_usb2_phy_ver phy_version; +}; + +#ifdef CONFIG_USB_ULPI_VIEWPORT +static inline struct usb_phy *qoriq_otg_ulpi_create(unsigned int flags) +{ + return otg_ulpi_create(&ulpi_viewport_access_ops, flags); +} +#else +static inline struct usb_phy *qoriq_otg_ulpi_create(unsigned int flags) +{ + return NULL; +} +#endif + +#endif -- 2.6.2.198.g614a2ac -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html