From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755615AbcETCqO (ORCPT ); Thu, 19 May 2016 22:46:14 -0400 Received: from mailout2.samsung.com ([203.254.224.25]:53698 "EHLO mailout2.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755589AbcETCqL (ORCPT ); Thu, 19 May 2016 22:46:11 -0400 X-AuditID: cbfee68f-f79d26d0000014f6-2f-573e7a685193 Message-id: <573E7A67.6050508@samsung.com> Date: Fri, 20 May 2016 11:45:59 +0900 From: Jaehoon Chung User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-version: 1.0 To: Shawn Lin , Ulf Hansson Cc: Adrian Hunter , Rob Herring , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, Heiko Stuebner , linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org Subject: Re: [PATCH v3 3/5] mmc: core: implement enhanced strobe support References: <1462871343-32361-1-git-send-email-shawn.lin@rock-chips.com> <1462871391-32484-1-git-send-email-shawn.lin@rock-chips.com> In-reply-to: <1462871391-32484-1-git-send-email-shawn.lin@rock-chips.com> Content-type: text/plain; charset=windows-1252 Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrGIsWRmVeSWpSXmKPExsWyRsSkWDejyi7cYOZ7TouTT9awWcw/co7V 4v+j16wWl3fNYbM48r+f0eLTg//MFq17j7Bb3HmyntXi+NpwB06PxXteMnlsWtXJ5nHn2h42 j81L6j3+ztrP4rH92jxmj8+b5ALYo7hsUlJzMstSi/TtErgyJkxdwFQw3bti9tefzA2Mf6y7 GDk5JARMJA7d3MMGYYtJXLi3Hsjm4hASWMEocfnuRDaYom0/tjBDJGYxSqz9sZkJwnnAKHFr 320WkCpeAS2J/5svMIPYLAKqElPWXAez2QR0JLZ/O84EYosKhEk8WLeXFaJeUOLH5HtgvSIC fhJbd2wFW80s8I5RouvOH7AGYQEPievXNrNDbGtnlPj88Cw7SIJTwFPi+oUlQB0cQB16Evcv aoGEmQXkJTaveQt2qoTAR3aJHxe3sUJcJCDxbfIhFpB6CQFZiU0HmCFek5Q4uOIGywRGsVlI bpqFMHUWkqkLGJlXMYqmFiQXFCelFxnrFSfmFpfmpesl5+duYgRG5+l/z/p3MN49YH2IUYCD UYmH94CDXbgQa2JZcWXuIUZToCMmMkuJJucDU0BeSbyhsZmRhamJqbGRuaWZkjjvQqmfwUIC 6YklqdmpqQWpRfFFpTmpxYcYmTg4pRoYNzqJnnDeJvZ6XRv7Es329tRXvj+cwyx//Ggyqg+5 0xFe7v8k4lr4/7YvXsdNuK+4bgn/2ZK2cnpYbfjiSVGyh+fdtJCcKmN54fDbP5bJSunFh9Qm V23/IdPze/nHj7ErRFR5GDXF163VfcgVaHRVJi9dvOrpGf6vRek7rybP5zjydo6NWXa9Ektx RqKhFnNRcSIA+klXHMkCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpmleLIzCtJLcpLzFFi42I5/e+xoG5GlV24Qc8UZouTT9awWcw/co7V 4v+j16wWl3fNYbM48r+f0eLTg//MFq17j7Bb3HmyntXi+NpwB06PxXteMnlsWtXJ5nHn2h42 j81L6j3+ztrP4rH92jxmj8+b5ALYoxoYbTJSE1NSixRS85LzUzLz0m2VvIPjneNNzQwMdQ0t LcyVFPISc1NtlVx8AnTdMnOALlNSKEvMKQUKBSQWFyvp22GaEBripmsB0xih6xsSBNdjZIAG EtYwZkyYuoCpYLp3xeyvP5kbGP9YdzFyckgImEhs+7GFGcIWk7hwbz1bFyMXh5DALEaJtT82 M0E4Dxglbu27zQJSxSugJfF/8wWwDhYBVYkpa66D2WwCOhLbvx1nArFFBcIkHqzbywpRLyjx Y/I9sF4RAT+JrTu2gm1gFnjHKNF15w9Yg7CAh8T1a5vZIba1M0p8fniWHSTBKeApcf3CEqAO DqAOPYn7F7VAwswC8hKb17xlnsAIdCfCjlkIVbOQVC1gZF7FKJFakFxQnJSea5iXWq5XnJhb XJqXrpecn7uJEZwAnkntYDy4y/0QowAHoxIPb4adXbgQa2JZcWXuIUYJDmYlEV7fCqAQb0pi ZVVqUX58UWlOavEhRlNgIExklhJNzgcmp7ySeENjEzMjSyNzQwsjY3Mlcd7H/9eFCQmkJ5ak ZqemFqQWwfQxcXBKNTBOWOVrf2VH0KuVkssdPTcYsa5rdTrG7ftd7bPjvYkyz1NudDS3aTyK ctLJWdRnljxtBp+uQty+6QyfD8saX9/Mvsxs/fl1BbX18WZ38tw5/Cf+/rMsfdfZe/lJEsWO B60dPK8vy3V7zpxjIB4yVVV4+c8zJSEnUxdmb69U8p3c3sWkLGq54IsSS3FGoqEWc1FxIgC8 ubPuFgMAAA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 05/10/2016 06:09 PM, Shawn Lin wrote: > Controllers use data strobe line to latch data from devices > under hs400 mode, but not for cmd line. So since emmc 5.1, JEDEC > introduces enhanced strobe mode for latching cmd response from > emmc devices to host controllers. This new feature is optional, > so it depends both on device's cap and host's cap to decide > whether to use it or not. > > Signed-off-by: Shawn Lin > --- > > Changes in v3: None > Changes in v2: None > > drivers/mmc/core/bus.c | 3 +- > drivers/mmc/core/core.c | 8 +++++ > drivers/mmc/core/mmc.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++-- > include/linux/mmc/card.h | 1 + > include/linux/mmc/host.h | 11 +++++++ > include/linux/mmc/mmc.h | 3 ++ > 6 files changed, 102 insertions(+), 3 deletions(-) > > diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c > index 4bc48f1..7e94b9d 100644 > --- a/drivers/mmc/core/bus.c > +++ b/drivers/mmc/core/bus.c > @@ -332,12 +332,13 @@ int mmc_add_card(struct mmc_card *card) > mmc_card_ddr52(card) ? "DDR " : "", > type); > } else { > - pr_info("%s: new %s%s%s%s%s card at address %04x\n", > + pr_info("%s: new %s%s%s%s%s%s card at address %04x\n", > mmc_hostname(card->host), > mmc_card_uhs(card) ? "ultra high speed " : > (mmc_card_hs(card) ? "high speed " : ""), > mmc_card_hs400(card) ? "HS400 " : > (mmc_card_hs200(card) ? "HS200 " : ""), > + mmc_card_hs400es(card) ? "Enhanced strobe" : "", > mmc_card_ddr52(card) ? "DDR " : "", > uhs_bus_speed_mode, type, card->rca); > } > diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c > index 99275e4..a559501 100644 > --- a/drivers/mmc/core/core.c > +++ b/drivers/mmc/core/core.c > @@ -1127,6 +1127,14 @@ void mmc_set_initial_state(struct mmc_host *host) > host->ios.bus_width = MMC_BUS_WIDTH_1; > host->ios.timing = MMC_TIMING_LEGACY; > host->ios.drv_type = 0; > + host->ios.enhanced_strobe = false; > + > + /* > + * Make sure we are in non-enhanced strobe mode before we > + * actually enable it in ext_csd. > + */ > + if (host->ops->hs400_enhanced_strobe) > + host->ops->hs400_enhanced_strobe(host, &host->ios); > > mmc_set_ios(host); > } > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c > index f99c47e..c2d1981 100644 > --- a/drivers/mmc/core/mmc.c > +++ b/drivers/mmc/core/mmc.c > @@ -235,6 +235,11 @@ static void mmc_select_card_type(struct mmc_card *card) > avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V; > } > > + if ((caps2 & MMC_CAP2_HS400_ES) && > + card->ext_csd.strobe_support && > + (card_type & EXT_CSD_CARD_TYPE_HS400)) > + avail_type |= EXT_CSD_CARD_TYPE_HS400ES; Does it need to check whether support HS400_1.8V/1.2V or not? It should be more stable than now. if (avail_type & (EXT_CSD_CARD_TYPE_HS400_1.8V | EXT_CSD_CARD_TYPE_HS400_1.2V)) { if ((cap2 & MMC_CAP2_HS400_ES) && ... } how about this? Best Regards, Jaehoon Chung > + > card->ext_csd.hs_max_dtr = hs_max_dtr; > card->ext_csd.hs200_max_dtr = hs200_max_dtr; > card->mmc_avail_type = avail_type; > @@ -383,6 +388,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) > mmc_card_set_blockaddr(card); > } > > + card->ext_csd.strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT]; > card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; > mmc_select_card_type(card); > > @@ -1216,6 +1222,73 @@ out_err: > return err; > } > > +static int mmc_select_hs400es(struct mmc_card *card) > +{ > + struct mmc_host *host = card->host; > + int err = 0; > + u8 val; > + > + err = mmc_select_bus_width(card); > + if (IS_ERR_VALUE(err)) > + goto out_err; > + > + /* Switch card to HS mode */ > + err = mmc_select_hs(card); > + if (err) { > + pr_err("%s: switch to high-speed failed, err:%d\n", > + mmc_hostname(host), err); > + goto out_err; > + } > + > + err = mmc_switch_status(card); > + if (err) > + goto out_err; > + > + /* Switch card to DDR with strobe bit */ > + val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE; > + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, > + EXT_CSD_BUS_WIDTH, > + val, > + card->ext_csd.generic_cmd6_time); > + if (err) { > + pr_err("%s: switch to bus width for hs400es failed, err:%d\n", > + mmc_hostname(host), err); > + goto out_err; > + } > + > + /* Switch card to HS400 */ > + val = EXT_CSD_TIMING_HS400 | > + card->drive_strength << EXT_CSD_DRV_STR_SHIFT; > + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, > + EXT_CSD_HS_TIMING, val, > + card->ext_csd.generic_cmd6_time, > + true, false, true); > + if (err) { > + pr_err("%s: switch to hs400es failed, err:%d\n", > + mmc_hostname(host), err); > + goto out_err; > + } > + > + /* Set host controller to HS400 timing and frequency */ > + mmc_set_timing(host, MMC_TIMING_MMC_HS400); > + > + /* Controller enable enhanced strobe function */ > + host->ios.enhanced_strobe = true; > + if (host->ops->hs400_enhanced_strobe) > + host->ops->hs400_enhanced_strobe(host, &host->ios); > + > + err = mmc_switch_status(card); > + if (err) > + goto out_err; > + > + return 0; > + > +out_err: > + pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), > + __func__, err); > + return err; > +} > + > static void mmc_select_driver_type(struct mmc_card *card) > { > int card_drv_type, drive_strength, drv_type; > @@ -1297,7 +1370,7 @@ err: > } > > /* > - * Activate High Speed or HS200 mode if supported. > + * Activate High Speed, HS200 or HS400ES mode if supported. > */ > static int mmc_select_timing(struct mmc_card *card) > { > @@ -1306,7 +1379,9 @@ static int mmc_select_timing(struct mmc_card *card) > if (!mmc_can_ext_csd(card)) > goto bus_speed; > > - if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) > + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400ES) > + err = mmc_select_hs400es(card); > + else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) > err = mmc_select_hs200(card); > else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) > err = mmc_select_hs(card); > diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h > index eb0151b..22defc2 100644 > --- a/include/linux/mmc/card.h > +++ b/include/linux/mmc/card.h > @@ -95,6 +95,7 @@ struct mmc_ext_csd { > u8 raw_partition_support; /* 160 */ > u8 raw_rpmb_size_mult; /* 168 */ > u8 raw_erased_mem_count; /* 181 */ > + u8 strobe_support; /* 184 */ > u8 raw_ext_csd_structure; /* 194 */ > u8 raw_card_type; /* 196 */ > u8 raw_driver_strength; /* 197 */ > diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h > index 2a06fb0..f98bd0e 100644 > --- a/include/linux/mmc/host.h > +++ b/include/linux/mmc/host.h > @@ -19,6 +19,7 @@ > > #include > #include > +#include > #include > > struct mmc_ios { > @@ -77,6 +78,8 @@ struct mmc_ios { > #define MMC_SET_DRIVER_TYPE_A 1 > #define MMC_SET_DRIVER_TYPE_C 2 > #define MMC_SET_DRIVER_TYPE_D 3 > + > + bool enhanced_strobe; /* hs400es selection */ > }; > > struct mmc_host_ops { > @@ -143,6 +146,9 @@ struct mmc_host_ops { > > /* Prepare HS400 target operating frequency depending host driver */ > int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios); > + /* Prepare enhanced strobe depending host driver */ > + void (*hs400_enhanced_strobe)(struct mmc_host *host, > + struct mmc_ios *ios); > int (*select_drive_strength)(struct mmc_card *card, > unsigned int max_dtr, int host_drv, > int card_drv, int *drv_type); > @@ -513,6 +519,11 @@ static inline bool mmc_card_hs400(struct mmc_card *card) > return card->host->ios.timing == MMC_TIMING_MMC_HS400; > } > > +static inline bool mmc_card_hs400es(struct mmc_card *card) > +{ > + return card->host->ios.enhanced_strobe == true; > +} > + > void mmc_retune_timer_stop(struct mmc_host *host); > > static inline void mmc_retune_needed(struct mmc_host *host) > diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h > index 15f2c4a..c376209 100644 > --- a/include/linux/mmc/mmc.h > +++ b/include/linux/mmc/mmc.h > @@ -297,6 +297,7 @@ struct _mmc_csd { > #define EXT_CSD_PART_CONFIG 179 /* R/W */ > #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ > #define EXT_CSD_BUS_WIDTH 183 /* R/W */ > +#define EXT_CSD_STROBE_SUPPORT 184 /* RO */ > #define EXT_CSD_HS_TIMING 185 /* R/W */ > #define EXT_CSD_POWER_CLASS 187 /* R/W */ > #define EXT_CSD_REV 192 /* RO */ > @@ -380,12 +381,14 @@ struct _mmc_csd { > #define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */ > #define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \ > EXT_CSD_CARD_TYPE_HS400_1_2V) > +#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */ > > #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ > #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ > #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ > #define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ > #define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ > +#define EXT_CSD_BUS_WIDTH_STROBE BIT(7) /* Enhanced strobe mode */ > > #define EXT_CSD_TIMING_BC 0 /* Backwards compatility */ > #define EXT_CSD_TIMING_HS 1 /* High speed */ >