From patchwork Tue Nov 19 08:19:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Faiz Abbas X-Patchwork-Id: 1197283 X-Patchwork-Delegate: lokeshvutla@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="WcxwDz3+"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 47HJyK4q71z9sPW for ; Tue, 19 Nov 2019 19:34:00 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 57C16C21F34; Tue, 19 Nov 2019 08:33:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id C7B25C21F3A; Tue, 19 Nov 2019 08:19:50 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id F164FC21F24; Tue, 19 Nov 2019 08:19:49 +0000 (UTC) Received: from lelv0142.ext.ti.com (lelv0142.ext.ti.com [198.47.23.249]) by lists.denx.de (Postfix) with ESMTPS id DA052C21F29 for ; Tue, 19 Nov 2019 08:18:37 +0000 (UTC) Received: from lelv0266.itg.ti.com ([10.180.67.225]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id xAJ8Ia2m024109; Tue, 19 Nov 2019 02:18:36 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1574151516; bh=ze4l4ruDmLsY9GmanEvg73Y4y46I5W/HFd4A49SJyaI=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=WcxwDz3+MvqsMvJE/DcWzLKptG1u/o5K3GToybH2ANmHiE0IRdXOmj+/asYvNWABk 2b3hC3+jG8XoR2lcqUxINqXLgwWaDjcOibrXIvir0rI8g1+ppf45e9upeycxDsm00L bTlX4c21W1dv/5AAIODDAbmR/nqvParjnCHbZ6xw= Received: from DLEE115.ent.ti.com (dlee115.ent.ti.com [157.170.170.26]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id xAJ8IacI060069 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 19 Nov 2019 02:18:36 -0600 Received: from DLEE102.ent.ti.com (157.170.170.32) by DLEE115.ent.ti.com (157.170.170.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Tue, 19 Nov 2019 02:18:36 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE102.ent.ti.com (157.170.170.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Tue, 19 Nov 2019 02:18:36 -0600 Received: from a0230074-OptiPlex-7010.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id xAJ8IU1f114351; Tue, 19 Nov 2019 02:18:35 -0600 From: Faiz Abbas To: Date: Tue, 19 Nov 2019 13:49:19 +0530 Message-ID: <20191119081925.19497-3-faiz_abbas@ti.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20191119081925.19497-1-faiz_abbas@ti.com> References: <20191119081925.19497-1-faiz_abbas@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Subject: [U-Boot] [PATCH 2/8] mmc: am654_sdhci: Add Support for configuring PHY in J721e X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add Support for writing to PHY registers for J721e. There are number of differences between the J721e 8 bit PHY, J721e 4 bit PHY and AM654 PHY. Create a driver_data structure with an ops and flags field and use the flags field to indicate these differences. The differences are as follows: 1. The J721e 4 bit instance PHY does not have a DLL. Introduce a DLL_PRESENT flag to make sure that DLL related registers are accessed only where they are present. Also add a separate set_ios_post() callback. 2. The J721e 8 bit instance is not muxed with anything else inside the SoC and hence the IOMUX_ENABLE filed does not exist. Add a flag which is used to indicate the presence of this field. 3. The register field used to select DLL frequency is 3 bit wide in J721e as compared to 2 bits in AM65x. Add another flag that distinguishes these fields. 4. The strobe select field is 8 bit wide as compared to 4 bit wide for AM65x. Add yet another flag to indicate this difference. Strobe select is used only for HS400 speed mode, support for which has not been added in AM65x. Signed-off-by: Faiz Abbas --- drivers/mmc/am654_sdhci.c | 127 +++++++++++++++++++++++++++++--------- 1 file changed, 98 insertions(+), 29 deletions(-) diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index a4359fcc18..41a90834ff 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -36,11 +36,14 @@ #define OTAPDLYSEL_SHIFT 12 #define OTAPDLYSEL_MASK GENMASK(15, 12) #define STRBSEL_SHIFT 24 -#define STRBSEL_MASK GENMASK(27, 24) +#define STRBSEL_4BIT_MASK GENMASK(27, 24) +#define STRBSEL_8BIT_MASK GENMASK(31, 24) #define SEL50_SHIFT 8 #define SEL50_MASK BIT(SEL50_SHIFT) #define SEL100_SHIFT 9 #define SEL100_MASK BIT(SEL100_SHIFT) +#define FREQSEL_SHIFT 8 +#define FREQSEL_MASK GENMASK(10, 8) #define DLL_TRIM_ICP_SHIFT 4 #define DLL_TRIM_ICP_MASK GENMASK(7, 4) #define DR_TY_SHIFT 20 @@ -72,11 +75,20 @@ struct am654_sdhci_plat { u32 otap_del_sel; u32 trm_icp; u32 drv_strength; + u32 strb_sel; u32 flags; #define DLL_PRESENT (1 << 0) +#define IOMUX_PRESENT (1 << 1) +#define FREQSEL_2_BIT (1 << 2) +#define STRBSEL_4_BIT (1 << 3) bool dll_on; }; +struct am654_driver_data { + const struct sdhci_ops *ops; + u32 flags; +}; + static void am654_sdhci_set_control_reg(struct sdhci_host *host) { struct mmc *mmc = (struct mmc *)host->mmc; @@ -97,7 +109,7 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host) struct udevice *dev = host->mmc->dev; struct am654_sdhci_plat *plat = dev_get_platdata(dev); unsigned int speed = host->mmc->clock; - int sel50, sel100; + int sel50, sel100, freqsel; u32 mask, val; int ret; @@ -121,25 +133,49 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host) mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; val = (1 << OTAPDLYENA_SHIFT) | (plat->otap_del_sel << OTAPDLYSEL_SHIFT); - regmap_update_bits(plat->base, PHY_CTRL4, mask, val); - switch (speed) { - case 200000000: - sel50 = 0; - sel100 = 0; - break; - case 100000000: - sel50 = 0; - sel100 = 1; - break; - default: - sel50 = 1; - sel100 = 0; + + /* Write to STRBSEL for HS400 speed mode */ + if (host->mmc->selected_mode == MMC_HS_400) { + if (plat->flags & STRBSEL_4_BIT) + mask |= STRBSEL_4BIT_MASK; + else + mask |= STRBSEL_8BIT_MASK; + + val |= plat->strb_sel << STRBSEL_SHIFT; } - /* Configure PHY DLL frequency */ - mask = SEL50_MASK | SEL100_MASK; - val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); - regmap_update_bits(plat->base, PHY_CTRL5, mask, val); + regmap_update_bits(plat->base, PHY_CTRL4, mask, val); + + if (plat->flags & FREQSEL_2_BIT) { + switch (speed) { + 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(plat->base, PHY_CTRL5, mask, val); + } else { + switch (speed) { + case 200000000: + freqsel = 0x0; + break; + default: + freqsel = 0x4; + } + regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK, + freqsel << FREQSEL_SHIFT); + } /* Enable DLL */ regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, @@ -164,8 +200,37 @@ const struct sdhci_ops am654_sdhci_ops = { .set_control_reg = &am654_sdhci_set_control_reg, }; +const struct am654_driver_data am654_drv_data = { + .ops = &am654_sdhci_ops, + .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | STRBSEL_4_BIT, +}; + +const struct am654_driver_data j721e_8bit_drv_data = { + .ops = &am654_sdhci_ops, + .flags = DLL_PRESENT, +}; + +static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host) +{ + struct udevice *dev = host->mmc->dev; + struct am654_sdhci_plat *plat = dev_get_platdata(dev); + u32 mask, val; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; + val = (1 << OTAPDLYENA_SHIFT) | + (plat->otap_del_sel << OTAPDLYSEL_SHIFT); + regmap_update_bits(plat->base, PHY_CTRL4, mask, val); + + return 0; +} + const struct sdhci_ops j721e_4bit_sdhci_ops = { - .set_control_reg = &am654_sdhci_set_control_reg, + .set_ios_post = &j721e_4bit_sdhci_set_ios_post, +}; + +const struct am654_driver_data j721e_4bit_drv_data = { + .ops = &j721e_4bit_sdhci_ops, + .flags = IOMUX_PRESENT, }; int am654_sdhci_init(struct am654_sdhci_plat *plat) @@ -202,7 +267,8 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat) } /* Enable pins by setting IO mux to 0 */ - regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0); + if (plat->flags & IOMUX_PRESENT) + regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0); /* Set slot type based on SD or eMMC */ if (plat->non_removable) @@ -215,6 +281,8 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat) static int am654_sdhci_probe(struct udevice *dev) { + struct am654_driver_data *drv_data = + (struct am654_driver_data *)dev_get_driver_data(dev); struct am654_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev); @@ -242,7 +310,8 @@ static int am654_sdhci_probe(struct udevice *dev) AM654_SDHCI_MIN_FREQ); if (ret) return ret; - host->ops = (struct sdhci_ops *)dev_get_driver_data(dev); + + host->ops = drv_data->ops; host->mmc->priv = host; upriv->mmc = host->mmc; @@ -265,10 +334,6 @@ static int am654_sdhci_ofdata_to_platdata(struct udevice *dev) host->ioaddr = (void *)dev_read_addr(dev); plat->non_removable = dev_read_bool(dev, "non-removable"); - if (device_is_compatible(dev, "ti,am654-sdhci-5.1") || - device_is_compatible(dev, "ti,j721e-sdhci-8bit")) - plat->flags |= DLL_PRESENT; - ret = dev_read_u32(dev, "ti,otap-del-sel", &plat->otap_del_sel); if (ret) return ret; @@ -314,23 +379,27 @@ static int am654_sdhci_ofdata_to_platdata(struct udevice *dev) static int am654_sdhci_bind(struct udevice *dev) { + struct am654_driver_data *drv_data = + (struct am654_driver_data *)dev_get_driver_data(dev); struct am654_sdhci_plat *plat = dev_get_platdata(dev); + plat->flags = drv_data->flags; + return sdhci_bind(dev, &plat->mmc, &plat->cfg); } static const struct udevice_id am654_sdhci_ids[] = { { .compatible = "ti,am654-sdhci-5.1", - .data = (ulong)&am654_sdhci_ops, + .data = (ulong)&am654_drv_data, }, { .compatible = "ti,j721e-sdhci-8bit", - .data = (ulong)&am654_sdhci_ops, + .data = (ulong)&j721e_8bit_drv_data, }, { .compatible = "ti,j721e-sdhci-4bit", - .data = (ulong)&j721e_4bit_sdhci_ops, + .data = (ulong)&j721e_4bit_drv_data, }, { } };