From patchwork Tue Mar 10 09:36:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avi Shchislowski X-Patchwork-Id: 5976161 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4C568BF440 for ; Tue, 10 Mar 2015 10:10:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D21AB201F4 for ; Tue, 10 Mar 2015 10:10:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3D19F20131 for ; Tue, 10 Mar 2015 10:10:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751057AbbCJKKP (ORCPT ); Tue, 10 Mar 2015 06:10:15 -0400 Received: from mail-bn1bon0070.outbound.protection.outlook.com ([157.56.111.70]:7641 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751503AbbCJKKM (ORCPT ); Tue, 10 Mar 2015 06:10:12 -0400 X-Greylist: delayed 1065 seconds by postgrey-1.27 at vger.kernel.org; Tue, 10 Mar 2015 06:10:12 EDT Received: from BY2PR02CA0072.namprd02.prod.outlook.com (10.242.32.30) by BY2PR02MB041.namprd02.prod.outlook.com (10.242.44.20) with Microsoft SMTP Server (TLS) id 15.1.106.15; Tue, 10 Mar 2015 09:36:58 +0000 Received: from BN1BFFO11FD037.protection.gbl (2a01:111:f400:7c10::1:104) by BY2PR02CA0072.outlook.office365.com (2a01:111:e400:2c2a::30) with Microsoft SMTP Server (TLS) id 15.1.106.15 via Frontend Transport; Tue, 10 Mar 2015 09:36:58 +0000 Received: from milsmgep12.sandisk.com (63.163.107.173) by BN1BFFO11FD037.mail.protection.outlook.com (10.58.144.100) with Microsoft SMTP Server id 15.1.112.13 via Frontend Transport; Tue, 10 Mar 2015 09:36:56 +0000 Received: from MILHUBIP03.sdcorp.global.sandisk.com ( [172.22.12.162]) by milsmgep12.sandisk.com (Symantec Messaging Gateway) with SMTP id 71.61.14695.73BBEF45; Tue, 10 Mar 2015 02:36:55 -0700 (PDT) Received: from milsmgip11.sandisk.com (10.177.8.100) by MILHUBIP03.sdcorp.global.sandisk.com (10.177.9.96) with Microsoft SMTP Server id 14.3.195.1; Tue, 10 Mar 2015 02:36:55 -0700 X-AuditID: ac160a69-f79656d000003967-14-54febb373d20 Received: from KFAC110926.sdcorp.global.sandisk.com ( [10.177.8.100]) by milsmgip11.sandisk.com (Symantec Messaging Gateway) with SMTP id D6.5B.19112.53BBEF45; Tue, 10 Mar 2015 02:36:55 -0700 (PDT) From: Avi Shchislowski To: CC: , , , Alex Lemberg , "Avi Shchislowski" Subject: [PATCH] mmc: sleep notification Date: Tue, 10 Mar 2015 11:36:37 +0200 Message-ID: <1425980197-823-1-git-send-email-avi.shchislowski@sandisk.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrCLMWRmVeSWpSXmKPExsWyRoxnka757n8hBofWylhMuLyd0eLI/35G i+Nrwx2YPe5c28PmcePVQiaPz5vkApijuGxSUnMyy1KL9O0SuDKmPm9jL/icXvFoeVQD496Q LkZODgkBE4n30z+wQ9hiEhfurWfrYuTiEBI4wShxt/cPlLODUWJu/xc2mI7FvetZIRIngRK9 s5lAEmwCphIz25YC2RwcIgIyEo0HjEFqmAXWMkp03lzODhIXFtCQWLvNFqScRUBVYsO3j2Ct vAJeEm2HLoO1SggoSMyZZAMRFpQ4OfMJC4jNLKAp0br9NzuELS/RvHU2M8Q5i1glDndag9hC QDUnFy5nm8AoNAtJ+ywk7bOQtC9gZF7FKJabmVOcm55aYGikV5yYl5JZnK2XnJ+7iREc1lyZ OxhXTDI/xCjAwajEw7vC8F+IEGtiWXFl7iFGCQ5mJRHehO1AId6UxMqq1KL8+KLSnNTiQ4zS HCxK4ryC07P8hQTSE0tSs1NTC1KLYLJMHJxSDYwNbHwrzye0nLxdPy+KecU8//OmRz8Zz7fv PqufUFKiundbgvsTXrvA2gXqO3ttJlq8nHZ008kuv+n1gipHmh8w8Vq5Gk9TXLjuzgLLu543 P+2MK/8eu1U64U3x7poQ1nVFsQHvNi7Y8rKhzl9t4ly3L0/SHfzm8QkyWWj7Wqp/VljxIdiy KEGJpTgj0VCLuag4EQAWs+l8ZwIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrBJMWRmVeSWpSXmKPExsXCtZEjRdd8978Qg13NghY3H/xgs9i5dx2T xYTL2xktjvzvZ7Q4vjbcgdXjzrU9bB43Xi1k8pi25jyTx+dNcgEsUVw2Kak5mWWpRfp2CVwZ U5+3sRd8Tq94tDyqgXFvSBcjJ4eEgInE4t71rBC2mMSFe+vZuhi5OIQEjjNKTP56lQ0kwSZg KjGzbSkTiC0iICXR87SZGaSIWWA1o8SDF1OAHA4OYQENibXbbEFqWARUJTZ8+whWzyvgJXGi 9wYrSImEgILEnEk2EGFBiZMzn7CAhJkF1CXWzxMCCTMLyEs0b53NPIGRdxaSqlkIVbOQVC1g ZF7FKJabmVOcm55ZYGioV5yYl5JZnK2XnJ+7iREcdpyROxifTjQ/xMjEwSnVwLhil1rJ7NVP SuSXaG8Oms9QXiT528tQ4Bu3T8qx5Gg1Yz3HU2tXv1d876rz6fGV19WMnqrcwm+CVzo/NBcP qT50mfX4ybObjISPMKlFXnsQJTBbenODzdvwpYwFH1bxyQTrJHJ8r6u59Ggi979NrNq/3H77 Pq7iLD9elDNvi7p3XJnNdZvaZ0osxRmJhlrMRcWJAPJ78lXrAQAA X-EOPAttributedMessage: 0 Received-SPF: Pass (protection.outlook.com: domain of sandisk.com designates 63.163.107.173 as permitted sender) receiver=protection.outlook.com; client-ip=63.163.107.173; helo=milsmgep12.sandisk.com; Authentication-Results: spf=pass (sender IP is 63.163.107.173) smtp.mailfrom=Avi.Shchislowski@sandisk.com; vger.kernel.org; dkim=none (message not signed) header.d=none; X-Forefront-Antispam-Report: CIP:63.163.107.173; CTRY:US; IPV:NLI; EFV:NLI; BMV:1; SFV:NSPM; SFS:(10009020)(6009001)(438002)(189002)(199003)(33646002)(47776003)(5820100001)(19580405001)(23676002)(50466002)(92566002)(5890100001)(2351001)(229853001)(19580395003)(50226001)(110136001)(106466001)(87936001)(86362001)(50986999)(77096005)(62966003)(575784001)(46102003)(77156002)(36756003); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR02MB041; H:milsmgep12.sandisk.com; FPR:; SPF:Pass; MLV:sfv; MX:1; A:1; LANG:en; X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR02MB041; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(5002009)(5005006); SRVR:BY2PR02MB041; BCL:0; PCL:0; RULEID:; SRVR:BY2PR02MB041; X-Forefront-PRVS: 051158ECBB X-OriginatorOrg: sandisk.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Mar 2015 09:36:56.2015 (UTC) X-MS-Exchange-CrossTenant-Id: fcd9ea9c-ae8c-460c-ab3c-3db42d7ac64d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=fcd9ea9c-ae8c-460c-ab3c-3db42d7ac64d; Ip=[63.163.107.173]; Helo=[milsmgep12.sandisk.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR02MB041 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch is implements the new additional state of Power_Off_Notification – SLEEP_NOTIFICATION. Until now, the implementation of Power_Off_Notification supported only three modes – POWERED_ON (0x01), POWER_OFF_SHORT (0x02) and POWER_OFF_LONG (0x03). As part of eMMC5.0 before moving to Sleep state hosts may set the POWER_OFF_NOTIFICATION byte to SLEEP_NOTIFICATION (0x04). After setting SLEEP_NOTIFICATION, host should wait for the busy line to be de-asserted. The max timeout allowed for busy line de-assertion defined in SLEEP_NOTIFICATION_TIME byte in EXT_CSD [216]. HPI may interrupt the SLEEP_NOTIFICATION operation. In that case POWER_OFF_NOTIFICATION byte will restore to POWERED_ON. Signed-off-by: Alex Lemberg Signed-off-by: Avi Shchislowski --- drivers/mmc/card/block.c | 19 +++++- drivers/mmc/core/core.c | 16 +++++- drivers/mmc/core/core.h | 2 + drivers/mmc/core/mmc.c | 143 +++++++++++++++++++++++++++++++++++++++++++--- include/linux/mmc/card.h | 6 ++ include/linux/mmc/host.h | 1 + include/linux/mmc/mmc.h | 2 + 7 files changed, 180 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 4409d79..f511ecc3 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2010,9 +2010,26 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) unsigned long flags; unsigned int cmd_flags = req ? req->cmd_flags : 0; - if (req && !mq->mqrq_prev->req) + if (unlikely(req && mmc_card_mmc(card) && + (card->ext_csd.power_off_notification == + EXT_CSD_SLEEP_NOTIFICATION))) { + /* restoring the power_off_notification + * field's state to as it was before so + * that the sleep notification will be + * able to resume later + */ + card->ext_csd.power_off_notification = EXT_CSD_POWER_ON; + } + + if (req && !mq->mqrq_prev->req) { /* claim host only for the first request */ mmc_get_card(card); + if (unlikely(req && + mmc_card_doing_sleep_notify(card))) { + mmc_interrupt_hpi(card); + mmc_card_clr_sleep_notify(card); + } + } ret = mmc_blk_part_switch(card, md); if (ret) { diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5bda29b..a090593 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -271,7 +271,8 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) BUG_ON(!card); - if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card)) + if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card) || + mmc_card_doing_sleep_notify(card)) return; err = mmc_read_bkops_status(card); @@ -2630,6 +2631,19 @@ int mmc_pm_notify(struct notifier_block *notify_block, err = host->bus_ops->pre_suspend(host); if (!err) break; + if (host->card && host->bus_ops->suspend) { + err = mmc_sleep_notify(host->card); + /* We assume that HPI was sent + * in case of -ETIMEDOUT error, + * so suspend flow can be continued + */ + if (err && err != -ETIMEDOUT) { + pr_err("%s:sleep notify err=%d\n", + __func__, err); + return -EBUSY; + } + break; + } /* Calling bus_ops->remove() with a claimed host can deadlock */ host->bus_ops->remove(host); diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index d76597c..b6b4431 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -14,6 +14,7 @@ #include #define MMC_CMD_RETRIES 3 +#define MMC_SLEEP_NOTIFY_MAX_TIME 0x17 struct mmc_bus_ops { void (*remove)(struct mmc_host *); @@ -33,6 +34,7 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); void mmc_detach_bus(struct mmc_host *host); void mmc_init_erase(struct mmc_card *card); +int mmc_sleep_notify(struct mmc_card *card); void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 02ad792..1d97d24 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -57,6 +57,11 @@ static const unsigned int tacc_mant[] = { __res & __mask; \ }) +#define GET_SLEEP_NOTIFY_TIME(value) \ + (10 * (1 << (unsigned int)(value))) +#define GET_SLEEP_NOTIFY_TIME_MSEC(value) \ + (DIV_ROUND_UP(GET_SLEEP_NOTIFY_TIME(value), 1000)) + /* * Given the decoded CSD structure, decode the raw CID to our CID structure. */ @@ -571,6 +576,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) card->ext_csd.ffu_capable = (ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) && !(ext_csd[EXT_CSD_FW_CONFIG] & 0x1); + card->ext_csd.sleep_notify_time = + ext_csd[EXT_CSD_SLEEP_NOTIFICATION_TIME]; } out: return err; @@ -1468,6 +1475,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->ext_csd.hpi_en = 1; } + /* sleep notify enable/disable for eMMC 5.0 and above */ + if ((card->ext_csd.rev >= 7) && card->ext_csd.hpi_en && + (card->host->caps2 & MMC_CAP2_SLEEP_NOTIFY) && + card->ext_csd.sleep_notify_time > 0 && + card->ext_csd.sleep_notify_time <= + MMC_SLEEP_NOTIFY_MAX_TIME) { + card->can_sleep_notify = 1; + } + /* * If cache size is higher than 0, this indicates * the existence of cache and it can be turned on. @@ -1576,6 +1592,33 @@ static int mmc_sleep(struct mmc_host *host) return err; } +/* + * check if device is in program state (busy) + */ +static bool mmc_device_prg_state(struct mmc_card *card) +{ + int rc; + u32 status; + bool state; + + mmc_get_card(card); + rc = mmc_send_status(card, &status); + if (rc) { + pr_err("%s: Get card status fail. rc=%d\n", + mmc_hostname(card->host), rc); + state = false; + goto out; + } + + if (R1_CURRENT_STATE(status) == R1_STATE_PRG) + state = true; + else + state = false; +out: + mmc_put_card(card); + return state; +} + static int mmc_can_poweroff_notify(const struct mmc_card *card) { return card && @@ -1585,22 +1628,108 @@ static int mmc_can_poweroff_notify(const struct mmc_card *card) static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) { - unsigned int timeout = card->ext_csd.generic_cmd6_time; + unsigned int timeout_ms = card->ext_csd.generic_cmd6_time; int err; + bool use_busy_signal; /* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */ if (notify_type == EXT_CSD_POWER_OFF_LONG) - timeout = card->ext_csd.power_off_longtime; + timeout_ms = card->ext_csd.power_off_longtime; + else if (notify_type == EXT_CSD_SLEEP_NOTIFICATION) { + /* calculate the maximum timeout for the + * switch command when notifying the device + * that it is about to move to sleep */ + timeout_ms = GET_SLEEP_NOTIFY_TIME_MSEC( + card->ext_csd.sleep_notify_time); + } + /* do not wait on busy signal in case of + * Sleep Notification - to let host get + * another requests + */ + use_busy_signal = (notify_type == EXT_CSD_SLEEP_NOTIFICATION) ? + false : true; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, - notify_type, timeout, true, false, false); - if (err) + notify_type, timeout_ms, + use_busy_signal, false, false); + if (!err) { + card->ext_csd.power_off_notification = notify_type; + } else { pr_err("%s: Power Off Notification timed out, %u\n", - mmc_hostname(card->host), timeout); + mmc_hostname(card->host), timeout_ms); + } + + return err; +} - /* Disable the power off notification after the switch operation. */ - card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION; +int mmc_sleep_notify(struct mmc_card *card) +{ + int err = 0; + bool is_busy = 0; + unsigned long prg_wait = 0; + + if (!card->can_sleep_notify || !mmc_can_poweroff_notify(card)) + return 0; + + if (!mmc_card_doing_sleep_notify(card)) { + mmc_get_card(card); + mmc_card_set_sleep_notify(card); + err = mmc_poweroff_notify(card, + EXT_CSD_SLEEP_NOTIFICATION); + mmc_put_card(card); + if (err) { + pr_err("%s: mmc_poweroff_notify failed with %d\n", + __func__, err); + goto out; + } + + prg_wait = jiffies + + msecs_to_jiffies(GET_SLEEP_NOTIFY_TIME_MSEC( + card->ext_csd.sleep_notify_time)); + } + + /* + * Loop will run until: + * 1. Device is no more in Busy state + * 2. Sleep notification is not interrupted by HPI & IO request + */ + do { + /* added some delay to avoid sending card status too often */ + msleep(20); + err = 0; + /* Stop polling in case sleep notification was HPIed already */ + if (!mmc_card_doing_sleep_notify(card)) { + is_busy = mmc_device_prg_state(card); + if (is_busy) + err = -EBUSY; + break; + } + is_busy = mmc_device_prg_state(card); + if (is_busy && time_after(jiffies, prg_wait)) { + /* + * making sure we are still in busy before + * sending HPI due to timeout error + */ + is_busy = mmc_device_prg_state(card); + if (is_busy) { + if (mmc_card_doing_sleep_notify(card)) { + card->ext_csd.power_off_notification = + EXT_CSD_POWER_ON; + mmc_interrupt_hpi(card); + } + err = -ETIMEDOUT; + break; + } + } + } while (is_busy); + +out: + mmc_card_clr_sleep_notify(card); + if (err) { + pr_err("%s: mmc_poweroff_notify for sleep failed with %d\n", + mmc_hostname(card->host), err); + } return err; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 4d69c00..6998344 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -62,6 +62,7 @@ struct mmc_ext_csd { unsigned int sa_timeout; /* Units: 100ns */ unsigned int generic_cmd6_time; /* Units: 10ms */ unsigned int power_off_longtime; /* Units: ms */ + unsigned int sleep_notify_time; /* Units: us */ u8 power_off_notification; /* state */ unsigned int hs_max_dtr; unsigned int hs200_max_dtr; @@ -262,6 +263,7 @@ struct mmc_card { #define MMC_CARD_REMOVED (1<<4) /* card has been removed */ #define MMC_STATE_DOING_BKOPS (1<<5) /* card is doing BKOPS */ #define MMC_STATE_SUSPENDED (1<<6) /* card is suspended */ +#define MMC_STATE_SLEEP_NOTIFY (1<<7) /* card in sleep notify */ unsigned int quirks; /* card quirks */ #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ @@ -309,6 +311,7 @@ struct mmc_card { struct dentry *debugfs_root; struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */ unsigned int nr_parts; + u8 can_sleep_notify; /* sleep_notify on/off */ }; /* @@ -427,6 +430,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) #define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED) +#define mmc_card_doing_sleep_notify(c) ((c)->state & MMC_STATE_SLEEP_NOTIFY) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) @@ -437,6 +441,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS) #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED) #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED) +#define mmc_card_set_sleep_notify(c) ((c)->state |= MMC_STATE_SLEEP_NOTIFY) +#define mmc_card_clr_sleep_notify(c) ((c)->state &= ~MMC_STATE_SLEEP_NOTIFY) /* * Quirk add/remove for MMC products. diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 9f32270..4c0542a 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -291,6 +291,7 @@ struct mmc_host { MMC_CAP2_HS400_1_2V) #define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V) #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) +#define MMC_CAP2_SLEEP_NOTIFY (1 << 18) /* sleep notify supported */ mmc_pm_flag_t pm_caps; /* supported pm features */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 49ad7a9..69bda9a 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -314,6 +314,7 @@ struct _mmc_csd { #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_SLEEP_NOTIFICATION_TIME 216 /* RO */ #define EXT_CSD_S_A_TIMEOUT 217 /* RO */ #define EXT_CSD_REL_WR_SEC_C 222 /* RO */ #define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ @@ -408,6 +409,7 @@ struct _mmc_csd { #define EXT_CSD_POWER_ON 1 #define EXT_CSD_POWER_OFF_SHORT 2 #define EXT_CSD_POWER_OFF_LONG 3 +#define EXT_CSD_SLEEP_NOTIFICATION 4 #define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */ #define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */