aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorGirish K S <girish.shivananjappa@linaro.org>2011-11-15 01:25:46 -0500
committerChris Ball <cjb@laptop.org>2011-12-10 16:18:36 -0500
commita80f16276388a177199204aa5b60f328d4464110 (patch)
treea028c1fc5ff89cb3120159e720840e21241520f6 /drivers/mmc
parent96a85d548bf960ec8e8a0c3bca2b2e88e41549db (diff)
mmc: core: Fix power_off_notify during suspend
The eMMC 4.5 devices respond to only RESET and AWAKE command in the sleep state. Hence the mmc switch command to notify power off state should be sent before the device enters sleep state. This patch fixes the same. Signed-off-by: Girish K S <girish.shivananjappa@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c81
-rw-r--r--drivers/mmc/core/mmc.c2
2 files changed, 50 insertions, 33 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 74a012ad2bab..7ee2e07f36f4 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1225,6 +1225,46 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
1225 mmc_host_clk_release(host); 1225 mmc_host_clk_release(host);
1226} 1226}
1227 1227
1228static void mmc_poweroff_notify(struct mmc_host *host)
1229{
1230 struct mmc_card *card;
1231 unsigned int timeout;
1232 unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION;
1233 int err = 0;
1234
1235 card = host->card;
1236
1237 /*
1238 * Send power notify command only if card
1239 * is mmc and notify state is powered ON
1240 */
1241 if (card && mmc_card_mmc(card) &&
1242 (card->poweroff_notify_state == MMC_POWERED_ON)) {
1243
1244 if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
1245 notify_type = EXT_CSD_POWER_OFF_SHORT;
1246 timeout = card->ext_csd.generic_cmd6_time;
1247 card->poweroff_notify_state = MMC_POWEROFF_SHORT;
1248 } else {
1249 notify_type = EXT_CSD_POWER_OFF_LONG;
1250 timeout = card->ext_csd.power_off_longtime;
1251 card->poweroff_notify_state = MMC_POWEROFF_LONG;
1252 }
1253
1254 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
1255 EXT_CSD_POWER_OFF_NOTIFICATION,
1256 notify_type, timeout);
1257
1258 if (err && err != -EBADMSG)
1259 pr_err("Device failed to respond within %d poweroff "
1260 "time. Forcefully powering down the device\n",
1261 timeout);
1262
1263 /* Set the card state to no notification after the poweroff */
1264 card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
1265 }
1266}
1267
1228/* 1268/*
1229 * Apply power to the MMC stack. This is a two-stage process. 1269 * Apply power to the MMC stack. This is a two-stage process.
1230 * First, we enable power to the card without the clock running. 1270 * First, we enable power to the card without the clock running.
@@ -1281,42 +1321,12 @@ static void mmc_power_up(struct mmc_host *host)
1281 1321
1282void mmc_power_off(struct mmc_host *host) 1322void mmc_power_off(struct mmc_host *host)
1283{ 1323{
1284 struct mmc_card *card;
1285 unsigned int notify_type;
1286 unsigned int timeout;
1287 int err;
1288
1289 mmc_host_clk_hold(host); 1324 mmc_host_clk_hold(host);
1290 1325
1291 card = host->card;
1292 host->ios.clock = 0; 1326 host->ios.clock = 0;
1293 host->ios.vdd = 0; 1327 host->ios.vdd = 0;
1294 1328
1295 if (card && mmc_card_mmc(card) && 1329 mmc_poweroff_notify(host);
1296 (card->poweroff_notify_state == MMC_POWERED_ON)) {
1297
1298 if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
1299 notify_type = EXT_CSD_POWER_OFF_SHORT;
1300 timeout = card->ext_csd.generic_cmd6_time;
1301 card->poweroff_notify_state = MMC_POWEROFF_SHORT;
1302 } else {
1303 notify_type = EXT_CSD_POWER_OFF_LONG;
1304 timeout = card->ext_csd.power_off_longtime;
1305 card->poweroff_notify_state = MMC_POWEROFF_LONG;
1306 }
1307
1308 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
1309 EXT_CSD_POWER_OFF_NOTIFICATION,
1310 notify_type, timeout);
1311
1312 if (err && err != -EBADMSG)
1313 pr_err("Device failed to respond within %d poweroff "
1314 "time. Forcefully powering down the device\n",
1315 timeout);
1316
1317 /* Set the card state to no notification after the poweroff */
1318 card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
1319 }
1320 1330
1321 /* 1331 /*
1322 * Reset ocr mask to be the highest possible voltage supported for 1332 * Reset ocr mask to be the highest possible voltage supported for
@@ -2314,8 +2324,15 @@ int mmc_suspend_host(struct mmc_host *host)
2314 * pre-claim the host. 2324 * pre-claim the host.
2315 */ 2325 */
2316 if (mmc_try_claim_host(host)) { 2326 if (mmc_try_claim_host(host)) {
2317 if (host->bus_ops->suspend) 2327 if (host->bus_ops->suspend) {
2328 /*
2329 * For eMMC 4.5 device send notify command
2330 * before sleep, because in sleep state eMMC 4.5
2331 * devices respond to only RESET and AWAKE cmd
2332 */
2333 mmc_poweroff_notify(host);
2318 err = host->bus_ops->suspend(host); 2334 err = host->bus_ops->suspend(host);
2335 }
2319 if (err == -ENOSYS || !host->bus_ops->resume) { 2336 if (err == -ENOSYS || !host->bus_ops->resume) {
2320 /* 2337 /*
2321 * We simply "remove" the card in this case. 2338 * We simply "remove" the card in this case.
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 90de9ba36d2f..d240427c1246 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -876,7 +876,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
876 * set the notification byte in the ext_csd register of device 876 * set the notification byte in the ext_csd register of device
877 */ 877 */
878 if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) && 878 if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) &&
879 (card->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)) { 879 (card->ext_csd.rev >= 6)) {
880 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 880 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
881 EXT_CSD_POWER_OFF_NOTIFICATION, 881 EXT_CSD_POWER_OFF_NOTIFICATION,
882 EXT_CSD_POWER_ON, 882 EXT_CSD_POWER_ON,