aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Langdale <philipl@overt.org>2006-10-21 06:35:02 -0400
committerPierre Ossman <drzeus@drzeus.cx>2006-12-01 12:21:32 -0500
commitbce40a36de574376f41f1ff3c4d212a7da2a3c90 (patch)
treef866c1d744db98d897d8e2684f7f47b56e75cb9b
parent9c9c26188ff9fa5f44ba5a00e01b54b539f83d1d (diff)
[PATCH] mmc: Add support for mmc v4 high speed mode
This adds support for the high-speed modes defined by mmc v4 (assuming the host controller is up to it). On a TI sdhci controller, it improves read speed from 1.3MBps to 2.3MBps. The TI controller can only go up to 24MHz, but everything helps. Another person has taken this basic patch and used it on a Nokia 770 to get a bigger boost because that controller can run at 48MHZ. Signed-off-by: Philip Langdale <philipl@overt.org> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
-rw-r--r--drivers/mmc/mmc.c121
-rw-r--r--include/linux/mmc/card.h8
-rw-r--r--include/linux/mmc/protocol.h47
3 files changed, 171 insertions, 5 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 766bc54406e5..2d5b93000dee 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -4,6 +4,7 @@
4 * Copyright (C) 2003-2004 Russell King, All Rights Reserved. 4 * Copyright (C) 2003-2004 Russell King, All Rights Reserved.
5 * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. 5 * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
6 * SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved. 6 * SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
7 * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
@@ -953,6 +954,114 @@ static void mmc_read_csds(struct mmc_host *host)
953 } 954 }
954} 955}
955 956
957static void mmc_process_ext_csds(struct mmc_host *host)
958{
959 int err;
960 struct mmc_card *card;
961
962 struct mmc_request mrq;
963 struct mmc_command cmd;
964 struct mmc_data data;
965
966 struct scatterlist sg;
967
968 /*
969 * As the ext_csd is so large and mostly unused, we don't store the
970 * raw block in mmc_card.
971 */
972 u8 *ext_csd;
973 ext_csd = kmalloc(512, GFP_KERNEL);
974 if (!ext_csd) {
975 printk("%s: could not allocate a buffer to receive the ext_csd."
976 "mmc v4 cards will be treated as v3.\n",
977 mmc_hostname(host));
978 return;
979 }
980
981 list_for_each_entry(card, &host->cards, node) {
982 if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
983 continue;
984 if (mmc_card_sd(card))
985 continue;
986 if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
987 continue;
988
989 err = mmc_select_card(host, card);
990 if (err != MMC_ERR_NONE) {
991 mmc_card_set_dead(card);
992 continue;
993 }
994
995 memset(&cmd, 0, sizeof(struct mmc_command));
996
997 cmd.opcode = MMC_SEND_EXT_CSD;
998 cmd.arg = 0;
999 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
1000
1001 memset(&data, 0, sizeof(struct mmc_data));
1002
1003 mmc_set_data_timeout(&data, card, 0);
1004
1005 data.blksz = 512;
1006 data.blocks = 1;
1007 data.flags = MMC_DATA_READ;
1008 data.sg = &sg;
1009 data.sg_len = 1;
1010
1011 memset(&mrq, 0, sizeof(struct mmc_request));
1012
1013 mrq.cmd = &cmd;
1014 mrq.data = &data;
1015
1016 sg_init_one(&sg, ext_csd, 512);
1017
1018 mmc_wait_for_req(host, &mrq);
1019
1020 if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
1021 mmc_card_set_dead(card);
1022 continue;
1023 }
1024
1025 switch (ext_csd[EXT_CSD_CARD_TYPE]) {
1026 case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
1027 card->ext_csd.hs_max_dtr = 52000000;
1028 break;
1029 case EXT_CSD_CARD_TYPE_26:
1030 card->ext_csd.hs_max_dtr = 26000000;
1031 break;
1032 default:
1033 /* MMC v4 spec says this cannot happen */
1034 printk("%s: card is mmc v4 but doesn't support "
1035 "any high-speed modes.\n",
1036 mmc_hostname(card->host));
1037 mmc_card_set_bad(card);
1038 continue;
1039 }
1040
1041 /* Activate highspeed support. */
1042 cmd.opcode = MMC_SWITCH;
1043 cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
1044 (EXT_CSD_HS_TIMING << 16) |
1045 (1 << 8) |
1046 EXT_CSD_CMD_SET_NORMAL;
1047 cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
1048
1049 err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
1050 if (err != MMC_ERR_NONE) {
1051 printk("%s: failed to switch card to mmc v4 "
1052 "high-speed mode.\n",
1053 mmc_hostname(card->host));
1054 continue;
1055 }
1056
1057 mmc_card_set_highspeed(card);
1058 }
1059
1060 kfree(ext_csd);
1061
1062 mmc_deselect_cards(host);
1063}
1064
956static void mmc_read_scrs(struct mmc_host *host) 1065static void mmc_read_scrs(struct mmc_host *host)
957{ 1066{
958 int err; 1067 int err;
@@ -1031,8 +1140,14 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host)
1031 unsigned int max_dtr = host->f_max; 1140 unsigned int max_dtr = host->f_max;
1032 1141
1033 list_for_each_entry(card, &host->cards, node) 1142 list_for_each_entry(card, &host->cards, node)
1034 if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr) 1143 if (!mmc_card_dead(card)) {
1035 max_dtr = card->csd.max_dtr; 1144 if (mmc_card_highspeed(card)) {
1145 if (max_dtr > card->ext_csd.hs_max_dtr)
1146 max_dtr = card->ext_csd.hs_max_dtr;
1147 } else if (max_dtr > card->csd.max_dtr) {
1148 max_dtr = card->csd.max_dtr;
1149 }
1150 }
1036 1151
1037 pr_debug("%s: selected %d.%03dMHz transfer rate\n", 1152 pr_debug("%s: selected %d.%03dMHz transfer rate\n",
1038 mmc_hostname(host), 1153 mmc_hostname(host),
@@ -1152,6 +1267,8 @@ static void mmc_setup(struct mmc_host *host)
1152 1267
1153 if (host->mode == MMC_MODE_SD) 1268 if (host->mode == MMC_MODE_SD)
1154 mmc_read_scrs(host); 1269 mmc_read_scrs(host);
1270 else
1271 mmc_process_ext_csds(host);
1155} 1272}
1156 1273
1157 1274
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 991a37382a22..ce25256f80d5 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -39,6 +39,10 @@ struct mmc_csd {
39 write_misalign:1; 39 write_misalign:1;
40}; 40};
41 41
42struct mmc_ext_csd {
43 unsigned int hs_max_dtr;
44};
45
42struct sd_scr { 46struct sd_scr {
43 unsigned char sda_vsn; 47 unsigned char sda_vsn;
44 unsigned char bus_widths; 48 unsigned char bus_widths;
@@ -62,11 +66,13 @@ struct mmc_card {
62#define MMC_STATE_BAD (1<<2) /* unrecognised device */ 66#define MMC_STATE_BAD (1<<2) /* unrecognised device */
63#define MMC_STATE_SDCARD (1<<3) /* is an SD card */ 67#define MMC_STATE_SDCARD (1<<3) /* is an SD card */
64#define MMC_STATE_READONLY (1<<4) /* card is read-only */ 68#define MMC_STATE_READONLY (1<<4) /* card is read-only */
69#define MMC_STATE_HIGHSPEED (1<<5) /* card is in mmc4 highspeed mode */
65 u32 raw_cid[4]; /* raw card CID */ 70 u32 raw_cid[4]; /* raw card CID */
66 u32 raw_csd[4]; /* raw card CSD */ 71 u32 raw_csd[4]; /* raw card CSD */
67 u32 raw_scr[2]; /* raw card SCR */ 72 u32 raw_scr[2]; /* raw card SCR */
68 struct mmc_cid cid; /* card identification */ 73 struct mmc_cid cid; /* card identification */
69 struct mmc_csd csd; /* card specific */ 74 struct mmc_csd csd; /* card specific */
75 struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */
70 struct sd_scr scr; /* extra SD information */ 76 struct sd_scr scr; /* extra SD information */
71}; 77};
72 78
@@ -75,12 +81,14 @@ struct mmc_card {
75#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD) 81#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD)
76#define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) 82#define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD)
77#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) 83#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
84#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
78 85
79#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) 86#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
80#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) 87#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD)
81#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD) 88#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD)
82#define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) 89#define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD)
83#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) 90#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
91#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
84 92
85#define mmc_card_name(c) ((c)->cid.prod_name) 93#define mmc_card_name(c) ((c)->cid.prod_name)
86#define mmc_card_id(c) ((c)->dev.bus_id) 94#define mmc_card_id(c) ((c)->dev.bus_id)
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 08dec8d9e703..311b6547f561 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -25,14 +25,16 @@
25#ifndef MMC_MMC_PROTOCOL_H 25#ifndef MMC_MMC_PROTOCOL_H
26#define MMC_MMC_PROTOCOL_H 26#define MMC_MMC_PROTOCOL_H
27 27
28/* Standard MMC commands (3.1) type argument response */ 28/* Standard MMC commands (4.1) type argument response */
29 /* class 1 */ 29 /* class 1 */
30#define MMC_GO_IDLE_STATE 0 /* bc */ 30#define MMC_GO_IDLE_STATE 0 /* bc */
31#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ 31#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
32#define MMC_ALL_SEND_CID 2 /* bcr R2 */ 32#define MMC_ALL_SEND_CID 2 /* bcr R2 */
33#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ 33#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
34#define MMC_SET_DSR 4 /* bc [31:16] RCA */ 34#define MMC_SET_DSR 4 /* bc [31:16] RCA */
35#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
35#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ 36#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
37#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
36#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ 38#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
37#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ 39#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
38#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ 40#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
@@ -88,6 +90,17 @@
88#define SD_APP_SEND_SCR 51 /* adtc R1 */ 90#define SD_APP_SEND_SCR 51 /* adtc R1 */
89 91
90/* 92/*
93 * MMC_SWITCH argument format:
94 *
95 * [31:26] Always 0
96 * [25:24] Access Mode
97 * [23:16] Location of target Byte in EXT_CSD
98 * [15:08] Value Byte
99 * [07:03] Always 0
100 * [02:00] Command Set
101 */
102
103/*
91 MMC status in R1 104 MMC status in R1
92 Type 105 Type
93 e : error bit 106 e : error bit
@@ -230,13 +243,41 @@ struct _mmc_csd {
230 243
231#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ 244#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
232#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ 245#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
233#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */ 246#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
247#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
234 248
235#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ 249#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
236#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ 250#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
237#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ 251#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
238#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */ 252#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
253#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
254
255/*
256 * EXT_CSD fields
257 */
258
259#define EXT_CSD_HS_TIMING 185 /* R/W */
260#define EXT_CSD_CARD_TYPE 196 /* RO */
261
262/*
263 * EXT_CSD field definitions
264 */
265
266#define EXT_CSD_CMD_SET_NORMAL (1<<0)
267#define EXT_CSD_CMD_SET_SECURE (1<<1)
268#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
269
270#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
271#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
272
273/*
274 * MMC_SWITCH access modes
275 */
239 276
277#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
278#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
279#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
280#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
240 281
241/* 282/*
242 * SD bus widths 283 * SD bus widths