From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.4 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_SANE_1 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA3C0C10F14 for ; Thu, 10 Oct 2019 08:59:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 72FBC2190F for ; Thu, 10 Oct 2019 08:59:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="iwV4mp+D" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389029AbfJJI7h (ORCPT ); Thu, 10 Oct 2019 04:59:37 -0400 Received: from fllv0016.ext.ti.com ([198.47.19.142]:43784 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387946AbfJJI7d (ORCPT ); Thu, 10 Oct 2019 04:59:33 -0400 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id x9A8wtvM111374; Thu, 10 Oct 2019 03:58:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1570697935; bh=FZ5m5fs3B8g3OBzN8iroXxEV7WIfFcZBg387gdAKDFo=; h=Subject:To:CC:References:From:Date:In-Reply-To; b=iwV4mp+D6AptkvLFGg/EZjal0oTFYZRm34GDNYRn7i+jZKfvBHvWvpojJ1Ov6mCT9 VDDkSh5r8hKyN+frX2QKumbJa8D8P++9nGOsckDUZefI9Cy8QsPoJ9UEZSQyCW069g +N+kmOMT4A0ZzFtXLknJCJchvHDpIzXu5uyIekJg= Received: from DFLE113.ent.ti.com (dfle113.ent.ti.com [10.64.6.34]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x9A8wtoY083866 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 10 Oct 2019 03:58:55 -0500 Received: from DFLE100.ent.ti.com (10.64.6.21) by DFLE113.ent.ti.com (10.64.6.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Thu, 10 Oct 2019 03:58:51 -0500 Received: from fllv0040.itg.ti.com (10.64.41.20) by DFLE100.ent.ti.com (10.64.6.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Thu, 10 Oct 2019 03:58:51 -0500 Received: from [172.24.190.233] (ileax41-snat.itg.ti.com [10.172.224.153]) by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id x9A8wlcw079738; Thu, 10 Oct 2019 03:58:48 -0500 Subject: Re: [PATCH v3 15/16] phy: phy-mmp3-usb: add a new driver To: Lubomir Rintel , "To : Olof Johansson" CC: "Cc : Rob Herring" , Mark Rutland , Thomas Gleixner , Jason Cooper , Russell King , Michael Turquette , Stephen Boyd , , , , References: <20190830220743.439670-1-lkundrak@v3.sk> <20190830220743.439670-16-lkundrak@v3.sk> From: Kishon Vijay Abraham I Message-ID: Date: Thu, 10 Oct 2019 14:28:22 +0530 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: <20190830220743.439670-16-lkundrak@v3.sk> Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 7bit X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On 31/08/19 3:37 AM, Lubomir Rintel wrote: Change the $subject to "phy: Add USB2 PHY driver for Marvell MMP3 SoC" > This is the USB2 PHY as found on the Marvell MMP3 SoC. Based on Marvell GPL > release. Just have "Add PHY driver for the USB2 PHY found on Marvell MMP3 SoC." here. > > While at that, also add a MAINTAINERS entry including the other MMP PHY > driver. Adding MAINTAINERS could be a different patch. > > Signed-off-by: Lubomir Rintel Once the commit log is fixed: Acked-by: Kishon Vijay Abraham I Thanks Kishon > --- > MAINTAINERS | 7 + > drivers/phy/marvell/Kconfig | 11 ++ > drivers/phy/marvell/Makefile | 1 + > drivers/phy/marvell/phy-mmp3-usb.c | 291 +++++++++++++++++++++++++++++ > 4 files changed, 310 insertions(+) > create mode 100644 drivers/phy/marvell/phy-mmp3-usb.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 176ef19f0b9db..449349f8f20bf 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -10799,6 +10799,13 @@ F: arch/arm/boot/dts/mmp* > F: arch/arm/mach-mmp/ > F: linux/soc/mmp/ > > +MMP USB PHY DRIVERS > +R: Lubomir Rintel > +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) > +S: Maintained > +F: drivers/phy/marvell/phy-mmp3-usb.c > +F: drivers/phy/marvell/phy-pxa-usb.c > + > MMU GATHER AND TLB INVALIDATION > M: Will Deacon > M: "Aneesh Kumar K.V" > diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig > index 0e1642419c0bf..d33ef35b3e51b 100644 > --- a/drivers/phy/marvell/Kconfig > +++ b/drivers/phy/marvell/Kconfig > @@ -102,3 +102,14 @@ config PHY_PXA_USB > The PHY driver will be used by Marvell udc/ehci/otg driver. > > To compile this driver as a module, choose M here. > + > +config PHY_MMP3_USB > + tristate "Marvell MMP3 USB PHY Driver" > + depends on MACH_MMP3_DT || COMPILE_TEST > + select GENERIC_PHY > + help > + Enable this to support Marvell MMP3 USB PHY driver for Marvell > + SoC. This driver will do the PHY initialization and shutdown. > + The PHY driver will be used by Marvell udc/ehci/otg driver. > + > + To compile this driver as a module, choose M here. > diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile > index 434eb9ca6cc3f..5a106b1549f41 100644 > --- a/drivers/phy/marvell/Makefile > +++ b/drivers/phy/marvell/Makefile > @@ -2,6 +2,7 @@ > obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o > obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o > obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o > +obj-$(CONFIG_PHY_MMP3_USB) += phy-mmp3-usb.o > obj-$(CONFIG_PHY_MVEBU_A3700_COMPHY) += phy-mvebu-a3700-comphy.o > obj-$(CONFIG_PHY_MVEBU_A3700_UTMI) += phy-mvebu-a3700-utmi.o > obj-$(CONFIG_PHY_MVEBU_A38X_COMPHY) += phy-armada38x-comphy.o > diff --git a/drivers/phy/marvell/phy-mmp3-usb.c b/drivers/phy/marvell/phy-mmp3-usb.c > new file mode 100644 > index 0000000000000..499869595a582 > --- /dev/null > +++ b/drivers/phy/marvell/phy-mmp3-usb.c > @@ -0,0 +1,291 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. > + * Copyright (C) 2018,2019 Lubomir Rintel > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define USB2_PLL_REG0 0x4 > +#define USB2_PLL_REG1 0x8 > +#define USB2_TX_REG0 0x10 > +#define USB2_TX_REG1 0x14 > +#define USB2_TX_REG2 0x18 > +#define USB2_RX_REG0 0x20 > +#define USB2_RX_REG1 0x24 > +#define USB2_RX_REG2 0x28 > +#define USB2_ANA_REG0 0x30 > +#define USB2_ANA_REG1 0x34 > +#define USB2_ANA_REG2 0x38 > +#define USB2_DIG_REG0 0x3C > +#define USB2_DIG_REG1 0x40 > +#define USB2_DIG_REG2 0x44 > +#define USB2_DIG_REG3 0x48 > +#define USB2_TEST_REG0 0x4C > +#define USB2_TEST_REG1 0x50 > +#define USB2_TEST_REG2 0x54 > +#define USB2_CHARGER_REG0 0x58 > +#define USB2_OTG_REG0 0x5C > +#define USB2_PHY_MON0 0x60 > +#define USB2_RESETVE_REG0 0x64 > +#define USB2_ICID_REG0 0x78 > +#define USB2_ICID_REG1 0x7C > + > +/* USB2_PLL_REG0 */ > + > +/* This is for Ax stepping */ > +#define USB2_PLL_FBDIV_SHIFT_MMP3 0 > +#define USB2_PLL_FBDIV_MASK_MMP3 (0xFF << 0) > + > +#define USB2_PLL_REFDIV_SHIFT_MMP3 8 > +#define USB2_PLL_REFDIV_MASK_MMP3 (0xF << 8) > + > +#define USB2_PLL_VDD12_SHIFT_MMP3 12 > +#define USB2_PLL_VDD18_SHIFT_MMP3 14 > + > +/* This is for B0 stepping */ > +#define USB2_PLL_FBDIV_SHIFT_MMP3_B0 0 > +#define USB2_PLL_REFDIV_SHIFT_MMP3_B0 9 > +#define USB2_PLL_VDD18_SHIFT_MMP3_B0 14 > +#define USB2_PLL_FBDIV_MASK_MMP3_B0 0x01FF > +#define USB2_PLL_REFDIV_MASK_MMP3_B0 0x3E00 > + > +#define USB2_PLL_CAL12_SHIFT_MMP3 0 > +#define USB2_PLL_CALI12_MASK_MMP3 (0x3 << 0) > + > +#define USB2_PLL_VCOCAL_START_SHIFT_MMP3 2 > + > +#define USB2_PLL_KVCO_SHIFT_MMP3 4 > +#define USB2_PLL_KVCO_MASK_MMP3 (0x7<<4) > + > +#define USB2_PLL_ICP_SHIFT_MMP3 8 > +#define USB2_PLL_ICP_MASK_MMP3 (0x7<<8) > + > +#define USB2_PLL_LOCK_BYPASS_SHIFT_MMP3 12 > + > +#define USB2_PLL_PU_PLL_SHIFT_MMP3 13 > +#define USB2_PLL_PU_PLL_MASK (0x1 << 13) > + > +#define USB2_PLL_READY_MASK_MMP3 (0x1 << 15) > + > +/* USB2_TX_REG0 */ > +#define USB2_TX_IMPCAL_VTH_SHIFT_MMP3 8 > +#define USB2_TX_IMPCAL_VTH_MASK_MMP3 (0x7 << 8) > + > +#define USB2_TX_RCAL_START_SHIFT_MMP3 13 > + > +/* USB2_TX_REG1 */ > +#define USB2_TX_CK60_PHSEL_SHIFT_MMP3 0 > +#define USB2_TX_CK60_PHSEL_MASK_MMP3 (0xf << 0) > + > +#define USB2_TX_AMP_SHIFT_MMP3 4 > +#define USB2_TX_AMP_MASK_MMP3 (0x7 << 4) > + > +#define USB2_TX_VDD12_SHIFT_MMP3 8 > +#define USB2_TX_VDD12_MASK_MMP3 (0x3 << 8) > + > +/* USB2_TX_REG2 */ > +#define USB2_TX_DRV_SLEWRATE_SHIFT 10 > + > +/* USB2_RX_REG0 */ > +#define USB2_RX_SQ_THRESH_SHIFT_MMP3 4 > +#define USB2_RX_SQ_THRESH_MASK_MMP3 (0xf << 4) > + > +#define USB2_RX_SQ_LENGTH_SHIFT_MMP3 10 > +#define USB2_RX_SQ_LENGTH_MASK_MMP3 (0x3 << 10) > + > +/* USB2_ANA_REG1*/ > +#define USB2_ANA_PU_ANA_SHIFT_MMP3 14 > + > +/* USB2_OTG_REG0 */ > +#define USB2_OTG_PU_OTG_SHIFT_MMP3 3 > + > +struct mmp3_usb_phy { > + struct phy *phy; > + void __iomem *base; > +}; > + > +static unsigned int u2o_get(void __iomem *base, unsigned int offset) > +{ > + return readl_relaxed(base + offset); > +} > + > +static void u2o_set(void __iomem *base, unsigned int offset, > + unsigned int value) > +{ > + u32 reg; > + > + reg = readl_relaxed(base + offset); > + reg |= value; > + writel_relaxed(reg, base + offset); > + readl_relaxed(base + offset); > +} > + > +static void u2o_clear(void __iomem *base, unsigned int offset, > + unsigned int value) > +{ > + u32 reg; > + > + reg = readl_relaxed(base + offset); > + reg &= ~value; > + writel_relaxed(reg, base + offset); > + readl_relaxed(base + offset); > +} > + > +static int mmp3_usb_phy_init(struct phy *phy) > +{ > + struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy); > + void __iomem *base = mmp3_usb_phy->base; > + > + if (cpu_is_mmp3_a0()) { > + u2o_clear(base, USB2_PLL_REG0, (USB2_PLL_FBDIV_MASK_MMP3 > + | USB2_PLL_REFDIV_MASK_MMP3)); > + u2o_set(base, USB2_PLL_REG0, > + 0xd << USB2_PLL_REFDIV_SHIFT_MMP3 > + | 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3); > + } else if (cpu_is_mmp3_b0()) { > + u2o_clear(base, USB2_PLL_REG0, USB2_PLL_REFDIV_MASK_MMP3_B0 > + | USB2_PLL_FBDIV_MASK_MMP3_B0); > + u2o_set(base, USB2_PLL_REG0, > + 0xd << USB2_PLL_REFDIV_SHIFT_MMP3_B0 > + | 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3_B0); > + } else { > + dev_err(&phy->dev, "unsupported silicon revision\n"); > + return -ENODEV; > + } > + > + u2o_clear(base, USB2_PLL_REG1, USB2_PLL_PU_PLL_MASK > + | USB2_PLL_ICP_MASK_MMP3 > + | USB2_PLL_KVCO_MASK_MMP3 > + | USB2_PLL_CALI12_MASK_MMP3); > + u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_PU_PLL_SHIFT_MMP3 > + | 1 << USB2_PLL_LOCK_BYPASS_SHIFT_MMP3 > + | 3 << USB2_PLL_ICP_SHIFT_MMP3 > + | 3 << USB2_PLL_KVCO_SHIFT_MMP3 > + | 3 << USB2_PLL_CAL12_SHIFT_MMP3); > + > + u2o_clear(base, USB2_TX_REG0, USB2_TX_IMPCAL_VTH_MASK_MMP3); > + u2o_set(base, USB2_TX_REG0, 2 << USB2_TX_IMPCAL_VTH_SHIFT_MMP3); > + > + u2o_clear(base, USB2_TX_REG1, USB2_TX_VDD12_MASK_MMP3 > + | USB2_TX_AMP_MASK_MMP3 > + | USB2_TX_CK60_PHSEL_MASK_MMP3); > + u2o_set(base, USB2_TX_REG1, 3 << USB2_TX_VDD12_SHIFT_MMP3 > + | 4 << USB2_TX_AMP_SHIFT_MMP3 > + | 4 << USB2_TX_CK60_PHSEL_SHIFT_MMP3); > + > + u2o_clear(base, USB2_TX_REG2, 3 << USB2_TX_DRV_SLEWRATE_SHIFT); > + u2o_set(base, USB2_TX_REG2, 2 << USB2_TX_DRV_SLEWRATE_SHIFT); > + > + u2o_clear(base, USB2_RX_REG0, USB2_RX_SQ_THRESH_MASK_MMP3); > + u2o_set(base, USB2_RX_REG0, 0xa << USB2_RX_SQ_THRESH_SHIFT_MMP3); > + > + u2o_set(base, USB2_ANA_REG1, 0x1 << USB2_ANA_PU_ANA_SHIFT_MMP3); > + > + u2o_set(base, USB2_OTG_REG0, 0x1 << USB2_OTG_PU_OTG_SHIFT_MMP3); > + > + return 0; > +} > + > +static int mmp3_usb_phy_calibrate(struct phy *phy) > +{ > + struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy); > + void __iomem *base = mmp3_usb_phy->base; > + int loops; > + > + /* > + * PLL VCO and TX Impedance Calibration Timing: > + * > + * _____________________________________ > + * PU __________| > + * _____________________________ > + * VCOCAL START _________| > + * ___ > + * REG_RCAL_START ________________| |________|_______ > + * | 200us | 400us | 40| 400us | USB PHY READY > + */ > + > + udelay(200); > + u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_VCOCAL_START_SHIFT_MMP3); > + udelay(400); > + u2o_set(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3); > + udelay(40); > + u2o_clear(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3); > + udelay(400); > + > + loops = 0; > + while ((u2o_get(base, USB2_PLL_REG1) & USB2_PLL_READY_MASK_MMP3) == 0) { > + mdelay(1); > + loops++; > + if (loops > 100) { > + dev_err(&phy->dev, "PLL_READY not set after 100mS.\n"); > + return -ETIMEDOUT; > + } > + } > + > + return 0; > +} > + > +static const struct phy_ops mmp3_usb_phy_ops = { > + .init = mmp3_usb_phy_init, > + .calibrate = mmp3_usb_phy_calibrate, > + .owner = THIS_MODULE, > +}; > + > +static const struct of_device_id mmp3_usb_phy_of_match[] = { > + { .compatible = "marvell,mmp3-usb-phy", }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, mmp3_usb_phy_of_match); > + > +static int mmp3_usb_phy_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct resource *resource; > + struct mmp3_usb_phy *mmp3_usb_phy; > + struct phy_provider *provider; > + > + mmp3_usb_phy = devm_kzalloc(dev, sizeof(*mmp3_usb_phy), GFP_KERNEL); > + if (!mmp3_usb_phy) > + return -ENOMEM; > + > + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + mmp3_usb_phy->base = devm_ioremap_resource(dev, resource); > + if (IS_ERR(mmp3_usb_phy->base)) { > + dev_err(dev, "failed to remap PHY regs\n"); > + return PTR_ERR(mmp3_usb_phy->base); > + } > + > + mmp3_usb_phy->phy = devm_phy_create(dev, NULL, &mmp3_usb_phy_ops); > + if (IS_ERR(mmp3_usb_phy->phy)) { > + dev_err(dev, "failed to create PHY\n"); > + return PTR_ERR(mmp3_usb_phy->phy); > + } > + > + phy_set_drvdata(mmp3_usb_phy->phy, mmp3_usb_phy); > + 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); > + } > + > + return 0; > +} > + > +static struct platform_driver mmp3_usb_phy_driver = { > + .probe = mmp3_usb_phy_probe, > + .driver = { > + .name = "mmp3-usb-phy", > + .of_match_table = mmp3_usb_phy_of_match, > + }, > +}; > +module_platform_driver(mmp3_usb_phy_driver); > + > +MODULE_AUTHOR("Lubomir Rintel "); > +MODULE_DESCRIPTION("Marvell MMP3 USB PHY Driver"); > +MODULE_LICENSE("GPL v2"); >