From patchwork Tue Sep 13 12:57:32 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Girish K S X-Patchwork-Id: 4045 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 97D2723EF5 for ; Tue, 13 Sep 2011 12:57:43 +0000 (UTC) Received: from mail-ey0-f180.google.com (mail-ey0-f180.google.com [209.85.215.180]) by fiordland.canonical.com (Postfix) with ESMTP id 860D4A1878A for ; Tue, 13 Sep 2011 12:57:43 +0000 (UTC) Received: by eyb6 with SMTP id 6so59182eyb.11 for ; Tue, 13 Sep 2011 05:57:43 -0700 (PDT) Received: by 10.223.33.19 with SMTP id f19mr1434360fad.122.1315918663180; Tue, 13 Sep 2011 05:57:43 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.11.8 with SMTP id m8cs6689lab; Tue, 13 Sep 2011 05:57:42 -0700 (PDT) Received: by 10.68.29.66 with SMTP id i2mr620564pbh.375.1315918660759; Tue, 13 Sep 2011 05:57:40 -0700 (PDT) Received: from mail-pz0-f45.google.com (mail-pz0-f45.google.com [209.85.210.45]) by mx.google.com with ESMTPS id q8si1784864pbg.50.2011.09.13.05.57.39 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 13 Sep 2011 05:57:40 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.210.45 is neither permitted nor denied by best guess record for domain of girish.shivananjappa@linaro.org) client-ip=209.85.210.45; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.210.45 is neither permitted nor denied by best guess record for domain of girish.shivananjappa@linaro.org) smtp.mail=girish.shivananjappa@linaro.org Received: by pzk33 with SMTP id 33so1054833pzk.32 for ; Tue, 13 Sep 2011 05:57:39 -0700 (PDT) Received: by 10.68.0.69 with SMTP id 5mr1953899pbc.143.1315918659407; Tue, 13 Sep 2011 05:57:39 -0700 (PDT) Received: from girishks ([115.113.119.130]) by mx.google.com with ESMTPS id f6sm5114572pbp.2.2011.09.13.05.57.35 (version=SSLv3 cipher=OTHER); Tue, 13 Sep 2011 05:57:38 -0700 (PDT) From: Girish K S To: linux-mmc@vger.kernel.org Cc: cjb@laptop.org, kgene.kim@samsung.com, patches@linaro.org, linux-samsung-soc@vger.kernel.org, Girish K S Subject: [PATCH] mmc: core: eMMC 4.5 Power Class Selection Feature Date: Tue, 13 Sep 2011 18:27:32 +0530 Message-Id: <1315918652-14340-1-git-send-email-girish.shivananjappa@linaro.org> X-Mailer: git-send-email 1.7.1 This patch adds the power class selection feature available for mmc versions 4.0 and above. During the enumeration stage before switching to the lower data bus, check if the power class is supported for the current bus width. If the power class is available then switch to the power class and use the higher data bus. If power class is not supported then switch to the lower data bus in a worst case. Signed-off-by: Girish K S --- drivers/mmc/core/mmc.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mmc/mmc.h | 13 ++++++++ 2 files changed, 90 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 63cc77b..a4004da 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -536,6 +536,81 @@ static struct device_type mmc_type = { }; /* + * Select the PowerClass for the current bus width + * If power class is defined for 4/8 bit bus in the + * extended CSD register, select it by executing the + * mmc_switch command. + */ +static int mmc_select_powerclass(struct mmc_card *card, unsigned int bus_width) +{ + u8 *ext_csd; + int err; + unsigned int pwrclass_val; + unsigned int index = 0; + struct mmc_host *host = card->host; + + BUG_ON(!card); + BUG_ON(!host); + + /* Power class selection is supported for versions >= 4.0 */ + if (card->csd.mmca_vsn < CSD_SPEC_VER_4) + return 0; + /*Power class values are defined only for 4/8 bit bus*/ + if (bus_width == EXT_CSD_BUS_WIDTH_1) + return 0; + + switch ((1 << host->ios.vdd)) { + case MMC_VDD_165_195: + if (host->ios.clock <= 26000000) + index = EXT_CSD_PWR_CL_26_195; + else if (host->ios.clock <= 52000000) + index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? + EXT_CSD_PWR_CL_52_195 : + EXT_CSD_PWR_CL_DDR_52_195; + else if (host->ios.clock <= 200000000) + index = EXT_CSD_PWR_CL_200_195; + break; + case MMC_VDD_32_33: + case MMC_VDD_33_34: + case MMC_VDD_34_35: + case MMC_VDD_35_36: + if (host->ios.clock <= 26000000) + index = EXT_CSD_PWR_CL_26_360; + else if (host->ios.clock <= 52000000) + index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? + EXT_CSD_PWR_CL_52_360 : + EXT_CSD_PWR_CL_DDR_52_360; + else if (host->ios.clock <= 200000000) + index = EXT_CSD_PWR_CL_200_360; + break; + default: + BUG(); + break; + } + + err = mmc_get_ext_csd(card, &ext_csd); + if (err) + goto ret; + + pwrclass_val = ext_csd[index]; + + if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) + pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> + EXT_CSD_PWR_CL_8BIT_SHIFT; + else + pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_4BIT_MASK) >> + EXT_CSD_PWR_CL_4BIT_SHIFT; + + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_POWER_CLASS, + pwrclass_val, + 0); +ret: + mmc_free_ext_csd(ext_csd); + return err; +} + +/* * Handle the detection and initialisation of a card. * * In the case of a resume, "oldcard" will contain the card @@ -802,6 +877,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, bus_width = bus_widths[idx]; if (bus_width == MMC_BUS_WIDTH_1) ddr = 0; /* no DDR for 1-bit width */ + mmc_select_powerclass(card, ext_csd_bits[idx][0]); err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx][0], @@ -825,6 +901,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } if (!err && ddr) { + mmc_select_powerclass(card, ext_csd_bits[idx][1]); err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx][1], diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index a788e01..e183e32 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -279,10 +279,15 @@ struct _mmc_csd { #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ #define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_POWER_CLASS 187 #define EXT_CSD_REV 192 /* RO */ #define EXT_CSD_STRUCTURE 194 /* RO */ #define EXT_CSD_CARD_TYPE 196 /* RO */ #define EXT_CSD_PART_SWITCH_TIME 199 /* RO */ +#define EXT_CSD_PWR_CL_52_195 200 /*RO*/ +#define EXT_CSD_PWR_CL_26_195 201 /*RO*/ +#define EXT_CSD_PWR_CL_52_360 202 /*RO*/ +#define EXT_CSD_PWR_CL_26_360 203 /*RO*/ #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ #define EXT_CSD_S_A_TIMEOUT 217 /* RO */ #define EXT_CSD_REL_WR_SEC_C 222 /* RO */ @@ -294,6 +299,10 @@ struct _mmc_csd { #define EXT_CSD_SEC_ERASE_MULT 230 /* RO */ #define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ #define EXT_CSD_TRIM_MULT 232 /* RO */ +#define EXT_CSD_PWR_CL_200_195 236 /*RO*/ +#define EXT_CSD_PWR_CL_200_360 237 /*RO*/ +#define EXT_CSD_PWR_CL_DDR_52_195 238 /*RO*/ +#define EXT_CSD_PWR_CL_DDR_52_360 239 /*RO*/ #define EXT_CSD_POWER_OFF_LONG_TIME 247 /*RO*/ #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ @@ -336,6 +345,10 @@ struct _mmc_csd { #define EXT_CSD_POWER_OFF_SHORT 2 #define EXT_CSD_POWER_OFF_LONG 3 +#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0/* 8 bit PWR CLS */ +#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F/* 8 bit PWR CLS */ +#define EXT_CSD_PWR_CL_8BIT_SHIFT 4 +#define EXT_CSD_PWR_CL_4BIT_SHIFT 0 /* * MMC_SWITCH access modes */