From patchwork Tue Mar 5 16:29:43 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Warren X-Patchwork-Id: 225085 X-Patchwork-Delegate: twarren@nvidia.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id CE6632C0299 for ; Wed, 6 Mar 2013 03:31:44 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 75C414A1AC; Tue, 5 Mar 2013 17:31:33 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id lGV9XGxb1LKF; Tue, 5 Mar 2013 17:31:33 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B909E4A1BA; Tue, 5 Mar 2013 17:31:13 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0CECA4A194 for ; Tue, 5 Mar 2013 17:30:58 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rfcw7N9jihgu for ; Tue, 5 Mar 2013 17:30:54 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by theia.denx.de (Postfix) with ESMTPS id 36E204A191 for ; Tue, 5 Mar 2013 17:30:30 +0100 (CET) Received: by mail-pb0-f50.google.com with SMTP id up1so4597828pbc.23 for ; Tue, 05 Mar 2013 08:30:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-nvconfidentiality; bh=GzqZUR3Pr4EO/Wdfk7fJ//P4UrLcIZtXN79C0270yXQ=; b=nk2LKky4sOqrDFsrdmVx+uuKSzXve2znQIVoXmeV06eNolNkYMQU4e8cxGUoBPQyDG AVjvyYhkQU5qBBI6VCB4vSHHuF0yGIGMdmgY0PQlNCDnu1UzOACsG5K9JK/FoC+Wdnxa j2IDwPIHufY7hKx+n+3NzamYlQ3EZbbXZFS7DwjmXp3xFrqwY5mxrlmXlzv8k7KWiMUg zZa+WH+gxsOOrF8S3PV0TzxT/JS0o5xidAkatMuap5I5RShzuc/FyjOGnFSG6YE56DkE ms7cInGTo/lpHkSn84Q7SiO3aDyFg6A9AAHsQ4cBm+Zf5EGjbIXmQnRJnQliANcMMewb KShw== X-Received: by 10.68.117.104 with SMTP id kd8mr39022522pbb.1.1362501029472; Tue, 05 Mar 2013 08:30:29 -0800 (PST) Received: from localhost.localdomain (ip68-230-103-25.ph.ph.cox.net. [68.230.103.25]) by mx.google.com with ESMTPS id qp13sm27311372pbb.3.2013.03.05.08.30.26 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 05 Mar 2013 08:30:28 -0800 (PST) From: Tom Warren To: u-boot@lists.denx.de Date: Tue, 5 Mar 2013 09:29:43 -0700 Message-Id: <1362500985-13196-5-git-send-email-twarren@nvidia.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1362500985-13196-1-git-send-email-twarren@nvidia.com> References: <1362500985-13196-1-git-send-email-twarren@nvidia.com> X-NVConfidentiality: public Cc: swarren@nvidia.com, afleming@freescale.com, Tom Warren , twarren.nvidia@gmail.com Subject: [U-Boot] [PATCH v2 4/6] mmc: Tegra: Add SD bus power/voltage function and MMC pad init call. X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Tegra30 requires the SD Bus Voltage & Power bits be set in the SD Power Control register. Tegra20 works w/o them set, but do it anyway for those SoCs as it's part of the SD spec. Also call a common board pad init routine (pad_init_mmc) in mmc_reset(), used by Tegra30 only for now. Note that Tegra20 SD/MMC HW differs enough from Tegra20 that a new compatible entry is used in the fdt compat_names/id tables. Signed-off-by: Tom Warren --- v2: - pass mmc 'host' struct to pad_init_mmc - probe for Tegra30 SDMMC id in tegra_mmc_init drivers/mmc/tegra_mmc.c | 63 +++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 55 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 6063d08..8f5f1a5 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -38,6 +37,38 @@ struct mmc_host mmc_host[MAX_HOSTS]; #error "Please enable device tree support to use this driver" #endif +static void mmc_set_power(struct mmc_host *host, unsigned short power) +{ + u8 pwr = 0; + debug("%s: power = %x\n", __func__, power); + + if (power != (unsigned short)-1) { + switch (1 << power) { + case MMC_VDD_165_195: + pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8; + break; + case MMC_VDD_29_30: + case MMC_VDD_30_31: + pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0; + break; + case MMC_VDD_32_33: + case MMC_VDD_33_34: + pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3; + break; + } + } + debug("%s: pwr = %X\n", __func__, pwr); + + /* Set the bus voltage first (if any) */ + writeb(pwr, &host->reg->pwrcon); + if (pwr == 0) + return; + + /* Now enable bus power */ + pwr |= TEGRA_MMC_PWRCTL_SD_BUS_POWER; + writeb(pwr, &host->reg->pwrcon); +} + static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data, struct bounce_buffer *bbstate) { @@ -334,8 +365,7 @@ static void mmc_change_clock(struct mmc_host *host, uint clock) debug(" mmc_change_clock called\n"); /* - * Change Tegra SDMMCx clock divisor here. Source is 216MHz, - * PLLP_OUT0 + * Change Tegra SDMMCx clock divisor here. Source is PLLP_OUT0 */ if (clock == 0) goto out; @@ -410,7 +440,7 @@ static void mmc_set_ios(struct mmc *mmc) debug("mmc_set_ios: hostctl = %08X\n", ctrl); } -static void mmc_reset(struct mmc_host *host) +static void mmc_reset(struct mmc_host *host, struct mmc *mmc) { unsigned int timeout; debug(" mmc_reset called\n"); @@ -436,6 +466,14 @@ static void mmc_reset(struct mmc_host *host) timeout--; udelay(1000); } + + /* Set SD bus voltage & enable bus power */ + mmc_set_power(host, fls(mmc->voltages) - 1); + debug("%s: power control = %02X, host control = %02X\n", __func__, + readb(&host->reg->pwrcon), readb(&host->reg->hostctl)); + + /* Make sure SDIO pads are set up */ + pad_init_mmc(host); } static int mmc_core_init(struct mmc *mmc) @@ -444,7 +482,7 @@ static int mmc_core_init(struct mmc *mmc) unsigned int mask; debug(" mmc_core_init called\n"); - mmc_reset(host); + mmc_reset(host, mmc); host->version = readw(&host->reg->hcver); debug("host version = %x\n", host->version); @@ -641,12 +679,21 @@ void tegra_mmc_init(void) const void *blob = gd->fdt_blob; debug("%s entry\n", __func__); + /* See if any Tegra30 MMC controllers are present */ count = fdtdec_find_aliases_for_id(blob, "sdhci", - COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, MAX_HOSTS); - debug("%s: count of sdhci nodes is %d\n", __func__, count); + COMPAT_NVIDIA_TEGRA30_SDMMC, node_list, MAX_HOSTS); + debug("%s: count of T30 sdhci nodes is %d\n", __func__, count); + if (process_nodes(blob, node_list, count)) { + printf("%s: Error processing T30 mmc node(s)!\n", __func__); + return; + } + /* Now look for any Tegra20 MMC controllers */ + count = fdtdec_find_aliases_for_id(blob, "sdhci", + COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, MAX_HOSTS); + debug("%s: count of T20 sdhci nodes is %d\n", __func__, count); if (process_nodes(blob, node_list, count)) { - printf("%s: Error processing mmc node(s)!\n", __func__); + printf("%s: Error processing T20 mmc node(s)!\n", __func__); return; } }