- patches.apparmor/remove_suid_new_case_in_2.6.22.diff: Merge fix.
[linux-flexiantxendom0-3.2.10.git] / drivers / mmc / core / mmc_ops.c
1 /*
2  *  linux/drivers/mmc/mmc_ops.h
3  *
4  *  Copyright 2006-2007 Pierre Ossman
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or (at
9  * your option) any later version.
10  */
11
12 #include <linux/types.h>
13 #include <asm/scatterlist.h>
14 #include <linux/scatterlist.h>
15
16 #include <linux/mmc/host.h>
17 #include <linux/mmc/card.h>
18 #include <linux/mmc/mmc.h>
19
20 #include "core.h"
21 #include "mmc_ops.h"
22
23 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
24 {
25         int err;
26         struct mmc_command cmd;
27
28         BUG_ON(!host);
29
30         memset(&cmd, 0, sizeof(struct mmc_command));
31
32         cmd.opcode = MMC_SELECT_CARD;
33
34         if (card) {
35                 cmd.arg = card->rca << 16;
36                 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
37         } else {
38                 cmd.arg = 0;
39                 cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
40         }
41
42         err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
43         if (err != MMC_ERR_NONE)
44                 return err;
45
46         return MMC_ERR_NONE;
47 }
48
49 int mmc_select_card(struct mmc_card *card)
50 {
51         BUG_ON(!card);
52
53         return _mmc_select_card(card->host, card);
54 }
55
56 int mmc_deselect_cards(struct mmc_host *host)
57 {
58         return _mmc_select_card(host, NULL);
59 }
60
61 int mmc_go_idle(struct mmc_host *host)
62 {
63         int err;
64         struct mmc_command cmd;
65
66         mmc_set_chip_select(host, MMC_CS_HIGH);
67
68         mmc_delay(1);
69
70         memset(&cmd, 0, sizeof(struct mmc_command));
71
72         cmd.opcode = MMC_GO_IDLE_STATE;
73         cmd.arg = 0;
74         cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
75
76         err = mmc_wait_for_cmd(host, &cmd, 0);
77
78         mmc_delay(1);
79
80         mmc_set_chip_select(host, MMC_CS_DONTCARE);
81
82         mmc_delay(1);
83
84         return err;
85 }
86
87 int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
88 {
89         struct mmc_command cmd;
90         int i, err = 0;
91
92         BUG_ON(!host);
93
94         memset(&cmd, 0, sizeof(struct mmc_command));
95
96         cmd.opcode = MMC_SEND_OP_COND;
97         cmd.arg = ocr;
98         cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
99
100         for (i = 100; i; i--) {
101                 err = mmc_wait_for_cmd(host, &cmd, 0);
102                 if (err != MMC_ERR_NONE)
103                         break;
104
105                 if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
106                         break;
107
108                 err = MMC_ERR_TIMEOUT;
109
110                 mmc_delay(10);
111         }
112
113         if (rocr)
114                 *rocr = cmd.resp[0];
115
116         return err;
117 }
118
119 int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
120 {
121         int err;
122         struct mmc_command cmd;
123
124         BUG_ON(!host);
125         BUG_ON(!cid);
126
127         memset(&cmd, 0, sizeof(struct mmc_command));
128
129         cmd.opcode = MMC_ALL_SEND_CID;
130         cmd.arg = 0;
131         cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
132
133         err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
134         if (err != MMC_ERR_NONE)
135                 return err;
136
137         memcpy(cid, cmd.resp, sizeof(u32) * 4);
138
139         return MMC_ERR_NONE;
140 }
141
142 int mmc_set_relative_addr(struct mmc_card *card)
143 {
144         int err;
145         struct mmc_command cmd;
146
147         BUG_ON(!card);
148         BUG_ON(!card->host);
149
150         memset(&cmd, 0, sizeof(struct mmc_command));
151
152         cmd.opcode = MMC_SET_RELATIVE_ADDR;
153         cmd.arg = card->rca << 16;
154         cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
155
156         err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
157         if (err != MMC_ERR_NONE)
158                 return err;
159
160         return MMC_ERR_NONE;
161 }
162
163 int mmc_send_csd(struct mmc_card *card, u32 *csd)
164 {
165         int err;
166         struct mmc_command cmd;
167
168         BUG_ON(!card);
169         BUG_ON(!card->host);
170         BUG_ON(!csd);
171
172         memset(&cmd, 0, sizeof(struct mmc_command));
173
174         cmd.opcode = MMC_SEND_CSD;
175         cmd.arg = card->rca << 16;
176         cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
177
178         err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
179         if (err != MMC_ERR_NONE)
180                 return err;
181
182         memcpy(csd, cmd.resp, sizeof(u32) * 4);
183
184         return MMC_ERR_NONE;
185 }
186
187 int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
188 {
189         struct mmc_request mrq;
190         struct mmc_command cmd;
191         struct mmc_data data;
192         struct scatterlist sg;
193
194         BUG_ON(!card);
195         BUG_ON(!card->host);
196         BUG_ON(!ext_csd);
197
198         memset(&mrq, 0, sizeof(struct mmc_request));
199         memset(&cmd, 0, sizeof(struct mmc_command));
200         memset(&data, 0, sizeof(struct mmc_data));
201
202         mrq.cmd = &cmd;
203         mrq.data = &data;
204
205         cmd.opcode = MMC_SEND_EXT_CSD;
206         cmd.arg = 0;
207         cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
208
209         data.blksz = 512;
210         data.blocks = 1;
211         data.flags = MMC_DATA_READ;
212         data.sg = &sg;
213         data.sg_len = 1;
214
215         sg_init_one(&sg, ext_csd, 512);
216
217         mmc_set_data_timeout(&data, card, 0);
218
219         mmc_wait_for_req(card->host, &mrq);
220
221         if (cmd.error != MMC_ERR_NONE)
222                 return cmd.error;
223         if (data.error != MMC_ERR_NONE)
224                 return data.error;
225
226         return MMC_ERR_NONE;
227 }
228
229 int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
230 {
231         int err;
232         struct mmc_command cmd;
233
234         BUG_ON(!card);
235         BUG_ON(!card->host);
236
237         memset(&cmd, 0, sizeof(struct mmc_command));
238
239         cmd.opcode = MMC_SWITCH;
240         cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
241                   (index << 16) |
242                   (value << 8) |
243                   set;
244         cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
245
246         err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
247         if (err != MMC_ERR_NONE)
248                 return err;
249
250         return MMC_ERR_NONE;
251 }
252
253 int mmc_send_status(struct mmc_card *card, u32 *status)
254 {
255         int err;
256         struct mmc_command cmd;
257
258         BUG_ON(!card);
259         BUG_ON(!card->host);
260
261         memset(&cmd, 0, sizeof(struct mmc_command));
262
263         cmd.opcode = MMC_SEND_STATUS;
264         cmd.arg = card->rca << 16;
265         cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
266
267         err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
268         if (err != MMC_ERR_NONE)
269                 return err;
270
271         if (status)
272                 *status = cmd.resp[0];
273
274         return MMC_ERR_NONE;
275 }
276