Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp4414867imm; Mon, 8 Oct 2018 22:19:27 -0700 (PDT) X-Google-Smtp-Source: ACcGV60tnM78IWFB2V8g96kXDlBv3yG+4dhSXDxBAD4L1Sh857vwmZUxrRnau9MOtrF2BxciO6dg X-Received: by 2002:a62:c60a:: with SMTP id m10-v6mr27705073pfg.15.1539062367197; Mon, 08 Oct 2018 22:19:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539062367; cv=none; d=google.com; s=arc-20160816; b=H2hGQF2sxhHoC58d8BOoWboC6XoheRkoop+Y0k7pLKAYVX0RLQmklHPxkM8iLijmFY 8EiNz7qtChimxPzRVb8xkbjcNotniv6R1H6NJwlRPHuIKJ4X3uZscoO7ppjgYFpRc8ur oa+UmEDV0c61nBU42YJmR2bnrQS0RV6Svej2Vqow+o3w8tbzbjk4+EI/7GkkiIfOhVPJ vxnbPz+aV74NkUwFqXhgXKqlQp/z6WUN2BHoJPQdgJsBPVuRVtExrgBrpdcT1/Wa2nzz XOfn118ydznjWnloupR4tencpZputEiXN2bCOILtkx2nZ5Yb8o6nbFhqEQfdNojeJcxn oUew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:dkim-signature; bh=tfEnJw6QjP9EtSf91e0CISM+by/Kwwpf3yJdNHyrR8E=; b=eGbcGy/m1tpORSFPgZEvJsBMvgLM1oOBFdLtWjz92lD7xD6+U0zleyi4VPHIULwpqm blrfJLF1Mmse5BHZOioMEn58WKctp5y7wc/tjcGLx29fiOgRgqsRA1fYnloMZBxMNfVR maySKuL4UqrGXQf4H18cEYPWcoCc/oupoVWusDidmu8alxuf9W4aifJWOSDMpqT1mE/X OW33sOmMeFzmPUiLQDyN+fvfeYy3mhI+QjvrKNDdbzWskBUlAXH/NvKhj55C7GP30uKD Fa8DUKysibIsg3M3EmbilZeupSBtd5BNoU/sCytzmPHv3ucP6YutduiFt89xCxrk/xa2 ZzzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=udJYPGAt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q22-v6si20503383pls.243.2018.10.08.22.19.10; Mon, 08 Oct 2018 22:19:27 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=udJYPGAt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726439AbeJIMdy (ORCPT + 99 others); Tue, 9 Oct 2018 08:33:54 -0400 Received: from lelv0143.ext.ti.com ([198.47.23.248]:47176 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725808AbeJIMdy (ORCPT ); Tue, 9 Oct 2018 08:33:54 -0400 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id w995IfU6104391; Tue, 9 Oct 2018 00:18:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1539062321; bh=tfEnJw6QjP9EtSf91e0CISM+by/Kwwpf3yJdNHyrR8E=; h=Subject:To:CC:References:From:Date:In-Reply-To; b=udJYPGAtsiaQxA2v6dLdb+OGxz1ZVvXmbTBcK9dw8fqkDNM9tvCl8bHEi0OWTipU9 QsbJBGI9f5yjkLH5eDyw5ob/p4u01FAQ0cC156ZYG0l3WdaBKiq6pDqnxDRWi7tn/Q K3uqNYCWe7TSSwoBmh7Bm5KMMO/bUc5bgVk9TDJ4= Received: from DFLE112.ent.ti.com (dfle112.ent.ti.com [10.64.6.33]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id w995If1E025072; Tue, 9 Oct 2018 00:18:41 -0500 Received: from DFLE100.ent.ti.com (10.64.6.21) by DFLE112.ent.ti.com (10.64.6.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3; Tue, 9 Oct 2018 00:18:41 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DFLE100.ent.ti.com (10.64.6.21) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1466.3 via Frontend Transport; Tue, 9 Oct 2018 00:18:40 -0500 Received: from [172.24.190.233] (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id w995Ibru025194; Tue, 9 Oct 2018 00:18:38 -0500 Subject: Re: [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices To: Ulf Hansson , Faiz Abbas CC: Linux Kernel Mailing List , DTML , "linux-mmc@vger.kernel.org" , Rob Herring , Catalin Marinas , Adrian Hunter References: <20181004111451.9539-1-faiz_abbas@ti.com> <20181004111451.9539-3-faiz_abbas@ti.com> From: Kishon Vijay Abraham I Message-ID: Date: Tue, 9 Oct 2018 10:48:19 +0530 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: 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 Uffe, On Monday 08 October 2018 05:02 PM, Ulf Hansson wrote: > On 4 October 2018 at 13:14, Faiz Abbas wrote: >> Add driver support for the MMC physical layer present >> on TI's AM654 devices. >> >> Signed-off-by: Faiz Abbas >> Signed-off-by: Sekhar Nori > > I assume Kishon would like to pick up this through his tree? If not, > please tell and I can do it, with his ack. yes, I'll pick this in my tree. > > Reviewed-by: Ulf Hansson Thanks Kishon > > Kind regards > Uffe > >> --- >> drivers/phy/ti/Kconfig | 7 + >> drivers/phy/ti/Makefile | 1 + >> drivers/phy/ti/phy-am654-mmc.c | 291 +++++++++++++++++++++++++++++++++ >> 3 files changed, 299 insertions(+) >> create mode 100644 drivers/phy/ti/phy-am654-mmc.c >> >> diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig >> index 20503562666c..ea5fe4db01c8 100644 >> --- a/drivers/phy/ti/Kconfig >> +++ b/drivers/phy/ti/Kconfig >> @@ -76,3 +76,10 @@ config TWL4030_USB >> family chips (including the TWL5030 and TPS659x0 devices). >> This transceiver supports high and full speed devices plus, >> in host mode, low speed. >> + >> +config PHY_AM654_MMC >> + bool "TI AM654 MMC PHY Support" >> + select GENERIC_PHY >> + help >> + This option enables support for the Physical layer for MMC host >> + controllers present on TI AM654 SOCs. >> diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile >> index 9f361756eaf2..5b2db2d164a5 100644 >> --- a/drivers/phy/ti/Makefile >> +++ b/drivers/phy/ti/Makefile >> @@ -6,3 +6,4 @@ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o >> obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o >> obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o >> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o >> +obj-$(CONFIG_PHY_AM654_MMC) += phy-am654-mmc.o >> diff --git a/drivers/phy/ti/phy-am654-mmc.c b/drivers/phy/ti/phy-am654-mmc.c >> new file mode 100644 >> index 000000000000..91255947fb67 >> --- /dev/null >> +++ b/drivers/phy/ti/phy-am654-mmc.c >> @@ -0,0 +1,291 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * phy-am654-mmc.c - MMC PHY driver for TI's AM654 SOCs >> + * >> + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com >> + * >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/* MMC PHY Registers */ >> +#define PHYCTRL_CTRL1_REG 0x00 >> +#define PHYCTRL_CTRL2_REG 0x04 >> +#define PHYCTRL_CTRL3_REG 0x08 >> +#define PHYCTRL_CTRL4_REG 0x0C >> +#define PHYCTRL_CTRL5_REG 0x10 >> +#define PHYCTRL_CTRL6_REG 0x14 >> +#define PHYCTRL_STAT1_REG 0x30 >> +#define PHYCTRL_STAT2_REG 0x34 >> + >> +#define IOMUX_ENABLE_SHIFT 31 >> +#define IOMUX_ENABLE_MASK BIT(IOMUX_ENABLE_SHIFT) >> +#define OTAPDLYENA_SHIFT 20 >> +#define OTAPDLYENA_MASK BIT(OTAPDLYENA_SHIFT) >> +#define OTAPDLYSEL_SHIFT 12 >> +#define OTAPDLYSEL_MASK GENMASK(15, 12) >> +#define STRBSEL_SHIFT 24 >> +#define STRBSEL_MASK GENMASK(27, 24) >> +#define SEL50_SHIFT 8 >> +#define SEL50_MASK BIT(SEL50_SHIFT) >> +#define SEL100_SHIFT 9 >> +#define SEL100_MASK BIT(SEL100_SHIFT) >> +#define DLL_TRIM_ICP_SHIFT 4 >> +#define DLL_TRIM_ICP_MASK GENMASK(7, 4) >> +#define DR_TY_SHIFT 20 >> +#define DR_TY_MASK GENMASK(22, 20) >> +#define ENDLL_SHIFT 1 >> +#define ENDLL_MASK BIT(ENDLL_SHIFT) >> +#define DLLRDY_SHIFT 0 >> +#define DLLRDY_MASK BIT(DLLRDY_SHIFT) >> +#define PDB_SHIFT 0 >> +#define PDB_MASK BIT(PDB_SHIFT) >> +#define CALDONE_SHIFT 1 >> +#define CALDONE_MASK BIT(CALDONE_SHIFT) >> + >> +#define DRIVER_STRENGTH_50_OHM 0x0 >> +#define DRIVER_STRENGTH_33_OHM 0x1 >> +#define DRIVER_STRENGTH_66_OHM 0x2 >> +#define DRIVER_STRENGTH_100_OHM 0x3 >> +#define DRIVER_STRENGTH_40_OHM 0x4 >> + >> +static struct regmap_config am654_mmc_phy_regmap_config = { >> + .reg_bits = 32, >> + .val_bits = 32, >> + .reg_stride = 4, >> + .fast_io = true, >> +}; >> + >> +struct am654_mmc_phy { >> + struct regmap *reg_base; >> + struct clk *mmcclk; >> + int otap_del_sel; >> + int trm_icp; >> + int drv_strength; >> +}; >> + >> +static int am654_mmc_phy_init(struct phy *phy) >> +{ >> + struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy); >> + int ret; >> + u32 val; >> + >> + /* Reset registers to default value */ >> + regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, 0x10000); >> + regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0); >> + regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0); >> + >> + /* Calibrate IO lines */ >> + regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, >> + PDB_MASK, PDB_MASK); >> + ret = regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG, >> + val, val & CALDONE_MASK, 1, 20); >> + if (ret) >> + return ret; >> + >> + /* Enable pins by setting the IO mux to 0 */ >> + regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, >> + IOMUX_ENABLE_MASK, 0); >> + >> + mmc_phy->mmcclk = clk_get(&phy->dev, "mmcclk"); >> + if (IS_ERR(mmc_phy->mmcclk)) { >> + dev_err(&phy->dev, "Error getting mmcclk"); >> + return PTR_ERR(mmc_phy->mmcclk); >> + } >> + >> + return 0; >> +} >> + >> +static int am654_mmc_phy_exit(struct phy *phy) >> +{ >> + struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy); >> + >> + clk_put(mmc_phy->mmcclk); >> + >> + return 0; >> +} >> + >> +static int am654_mmc_phy_power_on(struct phy *phy) >> +{ >> + struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy); >> + u32 mask, val; >> + int sel50, sel100; >> + int rate; >> + >> + /* Setup DLL Output TAP delay */ >> + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; >> + val = (1 << OTAPDLYENA_SHIFT) | >> + (mmc_phy->otap_del_sel << OTAPDLYSEL_SHIFT); >> + regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, >> + mask, val); >> + >> + rate = clk_get_rate(mmc_phy->mmcclk); >> + switch (rate) { >> + case 200000000: >> + sel50 = 0; >> + sel100 = 0; >> + break; >> + case 100000000: >> + sel50 = 0; >> + sel100 = 1; >> + break; >> + default: >> + sel50 = 1; >> + sel100 = 0; >> + } >> + >> + /* Configure PHY DLL frequency */ >> + mask = SEL50_MASK | SEL100_MASK; >> + val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); >> + regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, >> + mask, val); >> + >> + /* Configure DLL TRIM */ >> + mask = DLL_TRIM_ICP_MASK; >> + val = mmc_phy->trm_icp << DLL_TRIM_ICP_SHIFT; >> + >> + /* Configure DLL driver strength */ >> + mask |= DR_TY_MASK; >> + val |= mmc_phy->drv_strength << DR_TY_SHIFT; >> + regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, mask, val); >> + >> + /* Enable DLL */ >> + regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, >> + ENDLL_MASK, 0x1 << ENDLL_SHIFT); >> + >> + /* >> + * Poll for DLL ready. Use a one second timeout. >> + * Works in all experiments done so far >> + */ >> + return regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG, >> + val, val & DLLRDY_MASK, 1000, 1000000); >> + >> +} >> + >> +static int am654_mmc_phy_power_off(struct phy *phy) >> +{ >> + struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy); >> + >> + /* Disable DLL */ >> + regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, >> + ENDLL_MASK, 0); >> + >> + /* Reset registers to default value except PDB */ >> + regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, >> + 0x10000 | PDB_MASK); >> + regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0); >> + regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0); >> + >> + return 0; >> +} >> + >> +static const struct phy_ops ops = { >> + .init = am654_mmc_phy_init, >> + .exit = am654_mmc_phy_exit, >> + .power_on = am654_mmc_phy_power_on, >> + .power_off = am654_mmc_phy_power_off, >> + .owner = THIS_MODULE, >> +}; >> + >> +static int am654_mmc_phy_probe(struct platform_device *pdev) >> +{ >> + struct phy_provider *phy_provider; >> + struct device *dev = &pdev->dev; >> + struct device_node *np = dev->of_node; >> + struct am654_mmc_phy *mmc_phy; >> + struct phy *generic_phy; >> + struct resource *res; >> + void __iomem *base; >> + struct regmap *map; >> + int drv_strength; >> + int err; >> + >> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >> + base = devm_ioremap_resource(&pdev->dev, res); >> + if (IS_ERR(base)) >> + return PTR_ERR(base); >> + >> + map = devm_regmap_init_mmio(dev, base, &am654_mmc_phy_regmap_config); >> + if (IS_ERR(map)) { >> + dev_err(dev, "could not initialize regmap\n"); >> + return PTR_ERR(map); >> + } >> + >> + mmc_phy = devm_kzalloc(dev, sizeof(struct am654_mmc_phy), GFP_KERNEL); >> + if (!mmc_phy) >> + return -ENOMEM; >> + >> + mmc_phy->reg_base = map; >> + err = of_property_read_u32(np, "ti,otap-del-sel", >> + &mmc_phy->otap_del_sel); >> + if (err) >> + return err; >> + >> + err = of_property_read_u32(np, "ti,trm-icp", >> + &mmc_phy->trm_icp); >> + if (err) >> + return err; >> + >> + err = of_property_read_u32(np, "ti,driver-strength-ohm", &drv_strength); >> + if (err) >> + return err; >> + >> + switch (drv_strength) { >> + case 50: >> + mmc_phy->drv_strength = DRIVER_STRENGTH_50_OHM; >> + break; >> + case 33: >> + mmc_phy->drv_strength = DRIVER_STRENGTH_33_OHM; >> + break; >> + case 66: >> + mmc_phy->drv_strength = DRIVER_STRENGTH_66_OHM; >> + break; >> + case 100: >> + mmc_phy->drv_strength = DRIVER_STRENGTH_100_OHM; >> + break; >> + case 40: >> + mmc_phy->drv_strength = DRIVER_STRENGTH_40_OHM; >> + break; >> + default: >> + dev_err(dev, "Invalid driver strength\n"); >> + return -EINVAL; >> + } >> + >> + generic_phy = devm_phy_create(dev, dev->of_node, &ops); >> + if (IS_ERR(generic_phy)) { >> + dev_err(dev, "failed to create PHY\n"); >> + return PTR_ERR(generic_phy); >> + } >> + >> + phy_set_drvdata(generic_phy, mmc_phy); >> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); >> + >> + return PTR_ERR_OR_ZERO(phy_provider); >> +} >> + >> +static const struct of_device_id am654_mmc_phy_dt_ids[] = { >> + { .compatible = "ti,am654-mmc-phy" }, >> + {} >> +}; >> + >> +MODULE_DEVICE_TABLE(of, am654_mmc_phy_dt_ids); >> + >> +static struct platform_driver am654_mmc_phy_driver = { >> + .probe = am654_mmc_phy_probe, >> + .driver = { >> + .name = "am654-mmc-phy", >> + .of_match_table = am654_mmc_phy_dt_ids, >> + }, >> +}; >> + >> +module_platform_driver(am654_mmc_phy_driver); >> + >> +MODULE_AUTHOR("Faiz Abbas "); >> +MODULE_DESCRIPTION("TI AM654 MMC PHY driver"); >> +MODULE_LICENSE("GPL v2"); >> -- >> 2.18.0 >>