Lines 7-23
Link Here
|
7 |
* it under the terms of the GNU General Public License version 2 as |
7 |
* it under the terms of the GNU General Public License version 2 as |
8 |
* published by the Free Software Foundation. |
8 |
* published by the Free Software Foundation. |
9 |
* |
9 |
* |
|
|
10 |
* Special thanks to Brad Campbell for extensive testing of this driver. |
11 |
* |
10 |
*/ |
12 |
*/ |
11 |
|
13 |
|
12 |
|
14 |
|
13 |
#include <linux/tifm.h> |
15 |
#include "linux/tifm.h" |
14 |
#include <linux/mmc/protocol.h> |
16 |
#include <linux/mmc/protocol.h> |
15 |
#include <linux/mmc/host.h> |
17 |
#include <linux/mmc/host.h> |
16 |
#include <linux/highmem.h> |
18 |
#include <linux/highmem.h> |
|
|
19 |
#include <linux/scatterlist.h> |
17 |
#include <asm/io.h> |
20 |
#include <asm/io.h> |
18 |
|
21 |
|
19 |
#define DRIVER_NAME "tifm_sd" |
22 |
#define DRIVER_NAME "tifm_sd" |
20 |
#define DRIVER_VERSION "0.7" |
23 |
#define DRIVER_VERSION "0.8" |
21 |
|
24 |
|
22 |
static int no_dma = 0; |
25 |
static int no_dma = 0; |
23 |
static int fixed_timeout = 0; |
26 |
static int fixed_timeout = 0; |
Lines 36-44
module_param(fixed_timeout, bool, 0644);
Link Here
|
36 |
#define TIFM_MMCSD_INAB 0x0080 /* abort / initialize command */ |
39 |
#define TIFM_MMCSD_INAB 0x0080 /* abort / initialize command */ |
37 |
#define TIFM_MMCSD_READ 0x8000 |
40 |
#define TIFM_MMCSD_READ 0x8000 |
38 |
|
41 |
|
39 |
#define TIFM_MMCSD_DATAMASK 0x401d /* set bits: CERR, EOFB, BRS, CB, EOC */ |
|
|
40 |
#define TIFM_MMCSD_ERRMASK 0x01e0 /* set bits: CCRC, CTO, DCRC, DTO */ |
42 |
#define TIFM_MMCSD_ERRMASK 0x01e0 /* set bits: CCRC, CTO, DCRC, DTO */ |
41 |
#define TIFM_MMCSD_EOC 0x0001 /* end of command phase */ |
43 |
#define TIFM_MMCSD_EOC 0x0001 /* end of command phase */ |
|
|
44 |
#define TIFM_MMCSD_CD 0x0002 /* card detect */ |
42 |
#define TIFM_MMCSD_CB 0x0004 /* card enter busy state */ |
45 |
#define TIFM_MMCSD_CB 0x0004 /* card enter busy state */ |
43 |
#define TIFM_MMCSD_BRS 0x0008 /* block received/sent */ |
46 |
#define TIFM_MMCSD_BRS 0x0008 /* block received/sent */ |
44 |
#define TIFM_MMCSD_EOFB 0x0010 /* card exit busy state */ |
47 |
#define TIFM_MMCSD_EOFB 0x0010 /* card exit busy state */ |
Lines 48-55
module_param(fixed_timeout, bool, 0644);
Link Here
|
48 |
#define TIFM_MMCSD_CCRC 0x0100 /* command crc error */ |
51 |
#define TIFM_MMCSD_CCRC 0x0100 /* command crc error */ |
49 |
#define TIFM_MMCSD_AF 0x0400 /* fifo almost full */ |
52 |
#define TIFM_MMCSD_AF 0x0400 /* fifo almost full */ |
50 |
#define TIFM_MMCSD_AE 0x0800 /* fifo almost empty */ |
53 |
#define TIFM_MMCSD_AE 0x0800 /* fifo almost empty */ |
|
|
54 |
#define TIFM_MMCSD_OCRB 0x1000 /* OCR busy */ |
55 |
#define TIFM_MMCSD_CIRQ 0x2000 /* card irq (cmd40/sdio) */ |
51 |
#define TIFM_MMCSD_CERR 0x4000 /* card status error */ |
56 |
#define TIFM_MMCSD_CERR 0x4000 /* card status error */ |
52 |
|
57 |
|
|
|
58 |
#define TIFM_MMCSD_ODTO 0x0040 /* open drain / extended timeout */ |
59 |
#define TIFM_MMCSD_CARD_RO 0x0200 /* card is read-only */ |
60 |
|
53 |
#define TIFM_MMCSD_FIFO_SIZE 0x0020 |
61 |
#define TIFM_MMCSD_FIFO_SIZE 0x0020 |
54 |
|
62 |
|
55 |
#define TIFM_MMCSD_RSP_R0 0x0000 |
63 |
#define TIFM_MMCSD_RSP_R0 0x0000 |
Lines 67-163
module_param(fixed_timeout, bool, 0644);
Link Here
|
67 |
#define TIFM_MMCSD_CMD_AC 0x2000 |
75 |
#define TIFM_MMCSD_CMD_AC 0x2000 |
68 |
#define TIFM_MMCSD_CMD_ADTC 0x3000 |
76 |
#define TIFM_MMCSD_CMD_ADTC 0x3000 |
69 |
|
77 |
|
70 |
typedef enum { |
78 |
#define TIFM_MMCSD_MAX_BLOCK_SIZE 0x0800UL |
71 |
IDLE = 0, |
|
|
72 |
CMD, /* main command ended */ |
73 |
BRS, /* block transfer finished */ |
74 |
SCMD, /* stop command ended */ |
75 |
CARD, /* card left busy state */ |
76 |
FIFO, /* FIFO operation completed (uncertain) */ |
77 |
READY |
78 |
} card_state_t; |
79 |
|
79 |
|
80 |
enum { |
80 |
enum { |
81 |
FIFO_RDY = 0x0001, /* hardware dependent value */ |
81 |
CMD_READY = 0x0001, |
82 |
EJECT = 0x0004, |
82 |
FIFO_READY = 0x0002, |
83 |
EJECT_DONE = 0x0008, |
83 |
BRS_READY = 0x0004, |
84 |
CARD_BUSY = 0x0010, |
84 |
SCMD_ACTIVE = 0x0008, |
85 |
OPENDRAIN = 0x0040, /* hardware dependent value */ |
85 |
SCMD_READY = 0x0010, |
86 |
CARD_EVENT = 0x0100, /* hardware dependent value */ |
86 |
CARD_BUSY = 0x0020, |
87 |
CARD_RO = 0x0200, /* hardware dependent value */ |
87 |
DATA_CARRY = 0x0040 |
88 |
FIFO_EVENT = 0x10000 }; /* hardware dependent value */ |
88 |
}; |
89 |
|
89 |
|
90 |
struct tifm_sd { |
90 |
struct tifm_sd { |
91 |
struct tifm_dev *dev; |
91 |
struct tifm_dev *dev; |
92 |
|
92 |
|
93 |
unsigned int flags; |
93 |
unsigned short eject:1, |
94 |
card_state_t state; |
94 |
open_drain:1, |
95 |
unsigned int clk_freq; |
95 |
no_dma:1; |
96 |
unsigned int clk_div; |
96 |
unsigned short cmd_flags; |
97 |
unsigned long timeout_jiffies; |
97 |
|
|
|
98 |
unsigned int clk_freq; |
99 |
unsigned int clk_div; |
100 |
unsigned long timeout_jiffies; |
98 |
|
101 |
|
99 |
struct tasklet_struct finish_tasklet; |
102 |
struct tasklet_struct finish_tasklet; |
100 |
struct timer_list timer; |
103 |
struct timer_list timer; |
101 |
struct mmc_request *req; |
104 |
struct mmc_request *req; |
102 |
wait_queue_head_t notify; |
|
|
103 |
|
104 |
size_t written_blocks; |
105 |
size_t buffer_size; |
106 |
size_t buffer_pos; |
107 |
|
105 |
|
|
|
106 |
int sg_len; |
107 |
int sg_pos; |
108 |
unsigned int block_pos; |
109 |
struct scatterlist bounce_buf; |
110 |
unsigned char bounce_buf_data[TIFM_MMCSD_MAX_BLOCK_SIZE]; |
108 |
}; |
111 |
}; |
109 |
|
112 |
|
110 |
static char* tifm_sd_data_buffer(struct mmc_data *data) |
113 |
/* for some reason, host won't respond correctly to readw/writew */ |
|
|
114 |
static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg, |
115 |
unsigned int off, unsigned int cnt) |
111 |
{ |
116 |
{ |
112 |
return page_address(data->sg->page) + data->sg->offset; |
117 |
struct tifm_dev *sock = host->dev; |
|
|
118 |
unsigned char *buf; |
119 |
unsigned int pos = 0, val; |
120 |
|
121 |
buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + off; |
122 |
if (host->cmd_flags & DATA_CARRY) { |
123 |
buf[pos++] = host->bounce_buf_data[0]; |
124 |
host->cmd_flags &= ~DATA_CARRY; |
125 |
} |
126 |
|
127 |
while (pos < cnt) { |
128 |
val = readl(sock->addr + SOCK_MMCSD_DATA); |
129 |
buf[pos++] = val & 0xff; |
130 |
if (pos == cnt) { |
131 |
host->bounce_buf_data[0] = (val >> 8) & 0xff; |
132 |
host->cmd_flags |= DATA_CARRY; |
133 |
break; |
134 |
} |
135 |
buf[pos++] = (val >> 8) & 0xff; |
136 |
} |
137 |
kunmap_atomic(buf - off, KM_BIO_DST_IRQ); |
113 |
} |
138 |
} |
114 |
|
139 |
|
115 |
static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, |
140 |
static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, |
116 |
unsigned int host_status) |
141 |
unsigned int off, unsigned int cnt) |
117 |
{ |
142 |
{ |
118 |
struct mmc_command *cmd = host->req->cmd; |
143 |
struct tifm_dev *sock = host->dev; |
119 |
unsigned int t_val = 0, cnt = 0; |
144 |
unsigned char *buf; |
120 |
char *buffer; |
145 |
unsigned int pos = 0, val; |
121 |
|
146 |
|
122 |
if (host_status & TIFM_MMCSD_BRS) { |
147 |
buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + off; |
123 |
/* in non-dma rx mode BRS fires when fifo is still not empty */ |
148 |
if (host->cmd_flags & DATA_CARRY) { |
124 |
if (no_dma && (cmd->data->flags & MMC_DATA_READ)) { |
149 |
val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00); |
125 |
buffer = tifm_sd_data_buffer(host->req->data); |
150 |
writel(val, sock->addr + SOCK_MMCSD_DATA); |
126 |
while (host->buffer_size > host->buffer_pos) { |
151 |
host->cmd_flags &= ~DATA_CARRY; |
127 |
t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
152 |
} |
128 |
buffer[host->buffer_pos++] = t_val & 0xff; |
153 |
|
129 |
buffer[host->buffer_pos++] = |
154 |
while (pos < cnt) { |
130 |
(t_val >> 8) & 0xff; |
155 |
val = buf[pos++]; |
131 |
} |
156 |
if (pos == cnt) { |
|
|
157 |
host->bounce_buf_data[0] = val & 0xff; |
158 |
host->cmd_flags |= DATA_CARRY; |
159 |
break; |
132 |
} |
160 |
} |
133 |
return 1; |
161 |
val |= (buf[pos++] << 8) & 0xff00; |
134 |
} else if (no_dma) { |
162 |
writel(val, sock->addr + SOCK_MMCSD_DATA); |
135 |
buffer = tifm_sd_data_buffer(host->req->data); |
163 |
} |
136 |
if ((cmd->data->flags & MMC_DATA_READ) && |
164 |
kunmap_atomic(buf - off, KM_BIO_SRC_IRQ); |
137 |
(host_status & TIFM_MMCSD_AF)) { |
165 |
} |
138 |
for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
166 |
|
139 |
t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
167 |
static void tifm_sd_transfer_data(struct tifm_sd *host) |
140 |
if (host->buffer_size > host->buffer_pos) { |
168 |
{ |
141 |
buffer[host->buffer_pos++] = |
169 |
struct mmc_data *r_data = host->req->cmd->data; |
142 |
t_val & 0xff; |
170 |
struct scatterlist *sg = r_data->sg; |
143 |
buffer[host->buffer_pos++] = |
171 |
unsigned int off, cnt, t_size = TIFM_MMCSD_FIFO_SIZE * 2; |
144 |
(t_val >> 8) & 0xff; |
172 |
unsigned int p_off, p_cnt; |
145 |
} |
173 |
struct page *pg; |
146 |
} |
174 |
|
147 |
} else if ((cmd->data->flags & MMC_DATA_WRITE) |
175 |
if (host->sg_pos == host->sg_len) |
148 |
&& (host_status & TIFM_MMCSD_AE)) { |
176 |
return; |
149 |
for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
177 |
while (t_size) { |
150 |
if (host->buffer_size > host->buffer_pos) { |
178 |
cnt = sg[host->sg_pos].length - host->block_pos; |
151 |
t_val = buffer[host->buffer_pos++] |
179 |
if (!cnt) { |
152 |
& 0x00ff; |
180 |
host->block_pos = 0; |
153 |
t_val |= ((buffer[host->buffer_pos++]) |
181 |
host->sg_pos++; |
154 |
<< 8) & 0xff00; |
182 |
if (host->sg_pos == host->sg_len) { |
155 |
writel(t_val, |
183 |
if ((r_data->flags & MMC_DATA_WRITE) |
156 |
sock->addr + SOCK_MMCSD_DATA); |
184 |
&& DATA_CARRY) |
157 |
} |
185 |
writel(host->bounce_buf_data[0], |
|
|
186 |
host->dev->addr |
187 |
+ SOCK_MMCSD_DATA); |
188 |
|
189 |
return; |
158 |
} |
190 |
} |
|
|
191 |
cnt = sg[host->sg_pos].length; |
159 |
} |
192 |
} |
|
|
193 |
off = sg[host->sg_pos].offset + host->block_pos; |
194 |
|
195 |
pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT); |
196 |
p_off = offset_in_page(off); |
197 |
p_cnt = PAGE_SIZE - p_off; |
198 |
p_cnt = min(p_cnt, cnt); |
199 |
p_cnt = min(p_cnt, t_size); |
200 |
|
201 |
if (r_data->flags & MMC_DATA_READ) |
202 |
tifm_sd_read_fifo(host, pg, p_off, p_cnt); |
203 |
else if (r_data->flags & MMC_DATA_WRITE) |
204 |
tifm_sd_write_fifo(host, pg, p_off, p_cnt); |
205 |
|
206 |
t_size -= p_cnt; |
207 |
host->block_pos += p_cnt; |
160 |
} |
208 |
} |
|
|
209 |
} |
210 |
|
211 |
static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off, |
212 |
struct page *src, unsigned int src_off, |
213 |
unsigned int count) |
214 |
{ |
215 |
unsigned char *src_buf = kmap_atomic(src, KM_BIO_SRC_IRQ) + src_off; |
216 |
unsigned char *dst_buf = kmap_atomic(dst, KM_BIO_DST_IRQ) + dst_off; |
217 |
|
218 |
memcpy(dst_buf, src_buf, count); |
219 |
|
220 |
kunmap_atomic(dst_buf - dst_off, KM_BIO_DST_IRQ); |
221 |
kunmap_atomic(src_buf - src_off, KM_BIO_SRC_IRQ); |
222 |
} |
223 |
|
224 |
static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data) |
225 |
{ |
226 |
struct scatterlist *sg = r_data->sg; |
227 |
unsigned int t_size = r_data->blksz; |
228 |
unsigned int off, cnt; |
229 |
unsigned int p_off, p_cnt; |
230 |
struct page *pg; |
231 |
|
232 |
dev_dbg(&host->dev->dev, "bouncing block\n"); |
233 |
while (t_size) { |
234 |
cnt = sg[host->sg_pos].length - host->block_pos; |
235 |
if (!cnt) { |
236 |
host->block_pos = 0; |
237 |
host->sg_pos++; |
238 |
if (host->sg_pos == host->sg_len) |
239 |
return; |
240 |
cnt = sg[host->sg_pos].length; |
241 |
} |
242 |
off = sg[host->sg_pos].offset + host->block_pos; |
243 |
|
244 |
pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT); |
245 |
p_off = offset_in_page(off); |
246 |
p_cnt = PAGE_SIZE - p_off; |
247 |
p_cnt = min(p_cnt, cnt); |
248 |
p_cnt = min(p_cnt, t_size); |
249 |
|
250 |
if (r_data->flags & MMC_DATA_WRITE) |
251 |
tifm_sd_copy_page(host->bounce_buf.page, |
252 |
r_data->blksz - t_size, |
253 |
pg, p_off, p_cnt); |
254 |
else if (r_data->flags & MMC_DATA_READ) |
255 |
tifm_sd_copy_page(pg, p_off, host->bounce_buf.page, |
256 |
r_data->blksz - t_size, p_cnt); |
257 |
|
258 |
t_size -= p_cnt; |
259 |
host->block_pos += p_cnt; |
260 |
} |
261 |
} |
262 |
|
263 |
int tifm_sd_set_dma_data(struct tifm_sd *host, struct mmc_data *r_data) |
264 |
{ |
265 |
struct tifm_dev *sock = host->dev; |
266 |
unsigned int t_size = TIFM_DMA_TSIZE * r_data->blksz; |
267 |
unsigned int dma_len, dma_blk_cnt, dma_off; |
268 |
struct scatterlist *sg = NULL; |
269 |
unsigned long flags; |
270 |
|
271 |
if (host->sg_pos == host->sg_len) |
272 |
return 1; |
273 |
|
274 |
if (host->cmd_flags & DATA_CARRY) { |
275 |
host->cmd_flags &= ~DATA_CARRY; |
276 |
local_irq_save(flags); |
277 |
tifm_sd_bounce_block(host, r_data); |
278 |
local_irq_restore(flags); |
279 |
if (host->sg_pos == host->sg_len) |
280 |
return 1; |
281 |
} |
282 |
|
283 |
dma_len = sg_dma_len(&r_data->sg[host->sg_pos]) - host->block_pos; |
284 |
if (!dma_len) { |
285 |
host->block_pos = 0; |
286 |
host->sg_pos++; |
287 |
if (host->sg_pos == host->sg_len) |
288 |
return 1; |
289 |
dma_len = sg_dma_len(&r_data->sg[host->sg_pos]); |
290 |
} |
291 |
|
292 |
if (dma_len < t_size) { |
293 |
dma_blk_cnt = dma_len / r_data->blksz; |
294 |
dma_off = host->block_pos; |
295 |
host->block_pos += dma_blk_cnt * r_data->blksz; |
296 |
} else { |
297 |
dma_blk_cnt = TIFM_DMA_TSIZE; |
298 |
dma_off = host->block_pos; |
299 |
host->block_pos += t_size; |
300 |
} |
301 |
|
302 |
if (dma_blk_cnt) |
303 |
sg = &r_data->sg[host->sg_pos]; |
304 |
else if (dma_len) { |
305 |
if (r_data->flags & MMC_DATA_WRITE) { |
306 |
local_irq_save(flags); |
307 |
tifm_sd_bounce_block(host, r_data); |
308 |
local_irq_restore(flags); |
309 |
} else |
310 |
host->cmd_flags |= DATA_CARRY; |
311 |
|
312 |
sg = &host->bounce_buf; |
313 |
dma_off = 0; |
314 |
dma_blk_cnt = 1; |
315 |
} else |
316 |
return 1; |
317 |
|
318 |
dev_dbg(&sock->dev, "setting dma for %d blocks\n", dma_blk_cnt); |
319 |
writel(sg_dma_address(sg) + dma_off, sock->addr + SOCK_DMA_ADDRESS); |
320 |
if (r_data->flags & MMC_DATA_WRITE) |
321 |
writel((dma_blk_cnt << 8) | TIFM_DMA_TX | TIFM_DMA_EN, |
322 |
sock->addr + SOCK_DMA_CONTROL); |
323 |
else |
324 |
writel((dma_blk_cnt << 8) | TIFM_DMA_EN, |
325 |
sock->addr + SOCK_DMA_CONTROL); |
326 |
|
161 |
return 0; |
327 |
return 0; |
162 |
} |
328 |
} |
163 |
|
329 |
|
Lines 206-213
static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
Link Here
|
206 |
static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd) |
372 |
static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd) |
207 |
{ |
373 |
{ |
208 |
struct tifm_dev *sock = host->dev; |
374 |
struct tifm_dev *sock = host->dev; |
209 |
unsigned int cmd_mask = tifm_sd_op_flags(cmd) | |
375 |
unsigned int cmd_mask = tifm_sd_op_flags(cmd); |
210 |
(host->flags & OPENDRAIN); |
376 |
|
|
|
377 |
if (host->open_drain) |
378 |
cmd_mask |= TIFM_MMCSD_ODTO; |
211 |
|
379 |
|
212 |
if (cmd->data && (cmd->data->flags & MMC_DATA_READ)) |
380 |
if (cmd->data && (cmd->data->flags & MMC_DATA_READ)) |
213 |
cmd_mask |= TIFM_MMCSD_READ; |
381 |
cmd_mask |= TIFM_MMCSD_READ; |
Lines 232-422
static void tifm_sd_fetch_resp(struct mmc_command *cmd, struct tifm_dev *sock)
Link Here
|
232 |
| readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00); |
400 |
| readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00); |
233 |
} |
401 |
} |
234 |
|
402 |
|
235 |
static void tifm_sd_process_cmd(struct tifm_dev *sock, struct tifm_sd *host, |
403 |
static void tifm_sd_check_status(struct tifm_sd *host) |
236 |
unsigned int host_status) |
|
|
237 |
{ |
404 |
{ |
|
|
405 |
struct tifm_dev *sock = host->dev; |
238 |
struct mmc_command *cmd = host->req->cmd; |
406 |
struct mmc_command *cmd = host->req->cmd; |
239 |
|
407 |
|
240 |
change_state: |
408 |
if (cmd->error != MMC_ERR_NONE) |
241 |
switch (host->state) { |
409 |
goto finish_request; |
242 |
case IDLE: |
410 |
|
|
|
411 |
if (!(host->cmd_flags & CMD_READY)) |
243 |
return; |
412 |
return; |
244 |
case CMD: |
413 |
|
245 |
if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) { |
414 |
if (cmd->data) { |
246 |
tifm_sd_fetch_resp(cmd, sock); |
415 |
if (cmd->data->error != MMC_ERR_NONE) { |
247 |
if (cmd->data) { |
416 |
if ((host->cmd_flags & SCMD_ACTIVE) |
248 |
host->state = BRS; |
417 |
&& !(host->cmd_flags & SCMD_READY)) |
249 |
} else { |
418 |
return; |
250 |
host->state = READY; |
419 |
|
251 |
} |
420 |
goto finish_request; |
252 |
goto change_state; |
|
|
253 |
} |
254 |
break; |
255 |
case BRS: |
256 |
if (tifm_sd_transfer_data(sock, host, host_status)) { |
257 |
if (cmd->data->flags & MMC_DATA_WRITE) { |
258 |
host->state = CARD; |
259 |
} else { |
260 |
if (no_dma) { |
261 |
if (host->req->stop) { |
262 |
tifm_sd_exec(host, host->req->stop); |
263 |
host->state = SCMD; |
264 |
} else { |
265 |
host->state = READY; |
266 |
} |
267 |
} else { |
268 |
host->state = FIFO; |
269 |
} |
270 |
} |
271 |
goto change_state; |
272 |
} |
273 |
break; |
274 |
case SCMD: |
275 |
if (host_status & TIFM_MMCSD_EOC) { |
276 |
tifm_sd_fetch_resp(host->req->stop, sock); |
277 |
host->state = READY; |
278 |
goto change_state; |
279 |
} |
421 |
} |
280 |
break; |
422 |
|
281 |
case CARD: |
423 |
if (!(host->cmd_flags & BRS_READY)) |
282 |
dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n", |
424 |
return; |
283 |
host->written_blocks); |
425 |
|
284 |
if (!(host->flags & CARD_BUSY) |
426 |
if (!(host->no_dma || (host->cmd_flags & FIFO_READY))) |
285 |
&& (host->written_blocks == cmd->data->blocks)) { |
427 |
return; |
286 |
if (no_dma) { |
428 |
|
287 |
if (host->req->stop) { |
429 |
if (cmd->data->flags & MMC_DATA_WRITE) { |
|
|
430 |
if (host->req->stop) { |
431 |
if (!(host->cmd_flags & SCMD_ACTIVE)) { |
432 |
host->cmd_flags |= SCMD_ACTIVE; |
433 |
writel(TIFM_MMCSD_EOFB |
434 |
| readl(sock->addr |
435 |
+ SOCK_MMCSD_INT_ENABLE), |
436 |
sock->addr |
437 |
+ SOCK_MMCSD_INT_ENABLE); |
288 |
tifm_sd_exec(host, host->req->stop); |
438 |
tifm_sd_exec(host, host->req->stop); |
289 |
host->state = SCMD; |
439 |
return; |
290 |
} else { |
440 |
} else { |
291 |
host->state = READY; |
441 |
if (!(host->cmd_flags & SCMD_READY) |
|
|
442 |
|| (host->cmd_flags & CARD_BUSY)) |
443 |
return; |
444 |
writel((~TIFM_MMCSD_EOFB) |
445 |
& readl(sock->addr |
446 |
+ SOCK_MMCSD_INT_ENABLE), |
447 |
sock->addr |
448 |
+ SOCK_MMCSD_INT_ENABLE); |
292 |
} |
449 |
} |
293 |
} else { |
450 |
} else { |
294 |
host->state = FIFO; |
451 |
if (host->cmd_flags & CARD_BUSY) |
|
|
452 |
return; |
453 |
writel((~TIFM_MMCSD_EOFB) |
454 |
& readl(sock->addr |
455 |
+ SOCK_MMCSD_INT_ENABLE), |
456 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
295 |
} |
457 |
} |
296 |
goto change_state; |
458 |
} else { |
297 |
} |
|
|
298 |
break; |
299 |
case FIFO: |
300 |
if (host->flags & FIFO_RDY) { |
301 |
host->flags &= ~FIFO_RDY; |
302 |
if (host->req->stop) { |
459 |
if (host->req->stop) { |
303 |
tifm_sd_exec(host, host->req->stop); |
460 |
if (!(host->cmd_flags & SCMD_ACTIVE)) { |
304 |
host->state = SCMD; |
461 |
host->cmd_flags |= SCMD_ACTIVE; |
305 |
} else { |
462 |
tifm_sd_exec(host, host->req->stop); |
306 |
host->state = READY; |
463 |
return; |
|
|
464 |
} else { |
465 |
if (!(host->cmd_flags & SCMD_READY)) |
466 |
return; |
467 |
} |
307 |
} |
468 |
} |
308 |
goto change_state; |
|
|
309 |
} |
469 |
} |
310 |
break; |
|
|
311 |
case READY: |
312 |
tasklet_schedule(&host->finish_tasklet); |
313 |
return; |
314 |
} |
470 |
} |
315 |
|
471 |
finish_request: |
|
|
472 |
tasklet_schedule(&host->finish_tasklet); |
316 |
} |
473 |
} |
317 |
|
474 |
|
318 |
/* Called from interrupt handler */ |
475 |
/* Called from interrupt handler */ |
319 |
static void tifm_sd_signal_irq(struct tifm_dev *sock, |
476 |
static void tifm_sd_data_event(struct tifm_dev *sock) |
320 |
unsigned int sock_irq_status) |
|
|
321 |
{ |
477 |
{ |
322 |
struct tifm_sd *host; |
478 |
struct tifm_sd *host; |
323 |
unsigned int host_status = 0, fifo_status = 0; |
479 |
unsigned int fifo_status = 0; |
324 |
int error_code = 0; |
480 |
struct mmc_data *r_data = NULL; |
325 |
|
481 |
|
326 |
spin_lock(&sock->lock); |
482 |
spin_lock(&sock->lock); |
327 |
host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); |
483 |
host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); |
|
|
484 |
fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); |
485 |
dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n", |
486 |
fifo_status, host->cmd_flags); |
328 |
|
487 |
|
329 |
if (sock_irq_status & FIFO_EVENT) { |
488 |
if (host->req) { |
330 |
fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); |
489 |
r_data = host->req->cmd->data; |
331 |
writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS); |
|
|
332 |
|
490 |
|
333 |
host->flags |= fifo_status & FIFO_RDY; |
491 |
if (r_data && (fifo_status & TIFM_FIFO_READY)) { |
|
|
492 |
if (tifm_sd_set_dma_data(host, r_data)) { |
493 |
host->cmd_flags |= FIFO_READY; |
494 |
tifm_sd_check_status(host); |
495 |
} |
496 |
} |
334 |
} |
497 |
} |
335 |
|
498 |
|
336 |
if (sock_irq_status & CARD_EVENT) { |
499 |
writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS); |
337 |
host_status = readl(sock->addr + SOCK_MMCSD_STATUS); |
500 |
spin_unlock(&sock->lock); |
338 |
writel(host_status, sock->addr + SOCK_MMCSD_STATUS); |
501 |
} |
339 |
|
502 |
|
340 |
if (!host->req) |
503 |
/* Called from interrupt handler */ |
341 |
goto done; |
504 |
static void tifm_sd_card_event(struct tifm_dev *sock) |
|
|
505 |
{ |
506 |
struct tifm_sd *host; |
507 |
unsigned int host_status = 0; |
508 |
int cmd_error = MMC_ERR_NONE; |
509 |
struct mmc_command *cmd = NULL; |
510 |
unsigned long flags; |
511 |
|
512 |
spin_lock(&sock->lock); |
513 |
host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); |
514 |
host_status = readl(sock->addr + SOCK_MMCSD_STATUS); |
515 |
dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n", |
516 |
host_status, host->cmd_flags); |
517 |
|
518 |
if (host->req) { |
519 |
cmd = host->req->cmd; |
342 |
|
520 |
|
343 |
if (host_status & TIFM_MMCSD_ERRMASK) { |
521 |
if (host_status & TIFM_MMCSD_ERRMASK) { |
344 |
if (host_status & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO)) |
522 |
writel(host_status & TIFM_MMCSD_ERRMASK, |
345 |
error_code = MMC_ERR_TIMEOUT; |
523 |
sock->addr + SOCK_MMCSD_STATUS); |
346 |
else if (host_status |
524 |
if (host_status & TIFM_MMCSD_CTO) |
347 |
& (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC)) |
525 |
cmd_error = MMC_ERR_TIMEOUT; |
348 |
error_code = MMC_ERR_BADCRC; |
526 |
else if (host_status & TIFM_MMCSD_CCRC) |
|
|
527 |
cmd_error = MMC_ERR_BADCRC; |
528 |
|
529 |
if (cmd->data) { |
530 |
if (host_status & TIFM_MMCSD_DTO) |
531 |
cmd->data->error = MMC_ERR_TIMEOUT; |
532 |
else if (host_status & TIFM_MMCSD_DCRC) |
533 |
cmd->data->error = MMC_ERR_BADCRC; |
534 |
} |
349 |
|
535 |
|
350 |
writel(TIFM_FIFO_INT_SETALL, |
536 |
writel(TIFM_FIFO_INT_SETALL, |
351 |
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
537 |
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
352 |
writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); |
538 |
writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); |
353 |
|
539 |
|
354 |
if (host->req->stop) { |
540 |
if (host->req->stop) { |
355 |
if (host->state == SCMD) { |
541 |
if (host->cmd_flags & SCMD_ACTIVE) { |
356 |
host->req->stop->error = error_code; |
542 |
host->req->stop->error = cmd_error; |
357 |
} else if (host->state == BRS |
543 |
host->cmd_flags |= SCMD_READY; |
358 |
|| host->state == CARD |
|
|
359 |
|| host->state == FIFO) { |
360 |
host->req->cmd->error = error_code; |
361 |
tifm_sd_exec(host, host->req->stop); |
362 |
host->state = SCMD; |
363 |
goto done; |
364 |
} else { |
544 |
} else { |
365 |
host->req->cmd->error = error_code; |
545 |
cmd->error = cmd_error; |
|
|
546 |
//host->cmd_flags |= SCMD_ACTIVE; |
547 |
//tifm_sd_exec(host, host->req->stop); |
548 |
tifm_sd_check_status(host); |
549 |
goto done; |
550 |
} |
551 |
} else |
552 |
cmd->error = cmd_error; |
553 |
} else { |
554 |
if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) { |
555 |
if (!(host->cmd_flags & CMD_READY)) { |
556 |
host->cmd_flags |= CMD_READY; |
557 |
tifm_sd_fetch_resp(cmd, sock); |
558 |
} else if (host->cmd_flags & SCMD_ACTIVE) { |
559 |
host->cmd_flags |= SCMD_READY; |
560 |
tifm_sd_fetch_resp(host->req->stop, |
561 |
sock); |
366 |
} |
562 |
} |
367 |
} else { |
|
|
368 |
host->req->cmd->error = error_code; |
369 |
} |
563 |
} |
370 |
host->state = READY; |
564 |
if (host_status & TIFM_MMCSD_BRS) |
|
|
565 |
host->cmd_flags |= BRS_READY; |
371 |
} |
566 |
} |
372 |
|
567 |
|
373 |
if (host_status & TIFM_MMCSD_CB) |
568 |
if (host->no_dma && cmd->data) { |
374 |
host->flags |= CARD_BUSY; |
569 |
if (host_status & TIFM_MMCSD_AE) |
375 |
if ((host_status & TIFM_MMCSD_EOFB) |
570 |
writel(host_status & TIFM_MMCSD_AE, |
376 |
&& (host->flags & CARD_BUSY)) { |
571 |
sock->addr + SOCK_MMCSD_STATUS); |
377 |
host->written_blocks++; |
572 |
|
378 |
host->flags &= ~CARD_BUSY; |
573 |
if (host_status & (TIFM_MMCSD_AE | TIFM_MMCSD_AF |
|
|
574 |
| TIFM_MMCSD_BRS)) { |
575 |
local_irq_save(flags); |
576 |
tifm_sd_transfer_data(host); |
577 |
local_irq_restore(flags); |
578 |
host_status &= ~TIFM_MMCSD_AE; |
579 |
} |
379 |
} |
580 |
} |
380 |
} |
|
|
381 |
|
382 |
if (host->req) |
383 |
tifm_sd_process_cmd(sock, host, host_status); |
384 |
done: |
385 |
dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n", |
386 |
host_status, fifo_status); |
387 |
spin_unlock(&sock->lock); |
388 |
} |
389 |
|
390 |
static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd) |
391 |
{ |
392 |
struct tifm_dev *sock = host->dev; |
393 |
unsigned int dest_cnt; |
394 |
|
395 |
/* DMA style IO */ |
396 |
dev_dbg(&sock->dev, "setting dma for %d blocks\n", |
397 |
cmd->data->blocks); |
398 |
writel(TIFM_FIFO_INT_SETALL, |
399 |
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
400 |
writel(ilog2(cmd->data->blksz) - 2, |
401 |
sock->addr + SOCK_FIFO_PAGE_SIZE); |
402 |
writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); |
403 |
writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); |
404 |
|
405 |
dest_cnt = (cmd->data->blocks) << 8; |
406 |
|
407 |
writel(sg_dma_address(cmd->data->sg), sock->addr + SOCK_DMA_ADDRESS); |
408 |
|
581 |
|
409 |
writel(cmd->data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS); |
582 |
if (host_status & TIFM_MMCSD_EOFB) |
410 |
writel(cmd->data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN); |
583 |
host->cmd_flags &= ~CARD_BUSY; |
|
|
584 |
else if (host_status & TIFM_MMCSD_CB) |
585 |
host->cmd_flags |= CARD_BUSY; |
411 |
|
586 |
|
412 |
if (cmd->data->flags & MMC_DATA_WRITE) { |
587 |
tifm_sd_check_status(host); |
413 |
writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
|
|
414 |
writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN, |
415 |
sock->addr + SOCK_DMA_CONTROL); |
416 |
} else { |
417 |
writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
418 |
writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL); |
419 |
} |
588 |
} |
|
|
589 |
done: |
590 |
writel(host_status, sock->addr + SOCK_MMCSD_STATUS); |
591 |
spin_unlock(&sock->lock); |
420 |
} |
592 |
} |
421 |
|
593 |
|
422 |
static void tifm_sd_set_data_timeout(struct tifm_sd *host, |
594 |
static void tifm_sd_set_data_timeout(struct tifm_sd *host, |
Lines 452-597
static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
Link Here
|
452 |
struct tifm_sd *host = mmc_priv(mmc); |
624 |
struct tifm_sd *host = mmc_priv(mmc); |
453 |
struct tifm_dev *sock = host->dev; |
625 |
struct tifm_dev *sock = host->dev; |
454 |
unsigned long flags; |
626 |
unsigned long flags; |
455 |
int sg_count = 0; |
|
|
456 |
struct mmc_data *r_data = mrq->cmd->data; |
627 |
struct mmc_data *r_data = mrq->cmd->data; |
457 |
|
628 |
|
458 |
spin_lock_irqsave(&sock->lock, flags); |
629 |
spin_lock_irqsave(&sock->lock, flags); |
459 |
if (host->flags & EJECT) { |
630 |
if (host->eject) { |
460 |
spin_unlock_irqrestore(&sock->lock, flags); |
631 |
spin_unlock_irqrestore(&sock->lock, flags); |
461 |
goto err_out; |
632 |
goto err_out; |
462 |
} |
633 |
} |
463 |
|
634 |
|
464 |
if (host->req) { |
635 |
if (host->req) { |
465 |
printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n"); |
636 |
printk(KERN_ERR "%s : unfinished request detected\n", |
|
|
637 |
sock->dev.bus_id); |
466 |
spin_unlock_irqrestore(&sock->lock, flags); |
638 |
spin_unlock_irqrestore(&sock->lock, flags); |
467 |
goto err_out; |
639 |
goto err_out; |
468 |
} |
640 |
} |
469 |
|
641 |
|
|
|
642 |
host->cmd_flags = 0; |
643 |
host->block_pos = 0; |
644 |
host->sg_pos = 0; |
645 |
|
470 |
if (r_data) { |
646 |
if (r_data) { |
471 |
tifm_sd_set_data_timeout(host, r_data); |
647 |
tifm_sd_set_data_timeout(host, r_data); |
472 |
|
648 |
|
473 |
sg_count = tifm_map_sg(sock, r_data->sg, r_data->sg_len, |
649 |
if ((r_data->flags & MMC_DATA_WRITE) && !mrq->stop) |
474 |
mrq->cmd->flags & MMC_DATA_WRITE |
650 |
writel(TIFM_MMCSD_EOFB |
475 |
? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); |
651 |
| readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
476 |
if (sg_count != 1) { |
652 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
477 |
printk(KERN_ERR DRIVER_NAME |
|
|
478 |
": scatterlist map failed\n"); |
479 |
spin_unlock_irqrestore(&sock->lock, flags); |
480 |
goto err_out; |
481 |
} |
482 |
|
483 |
host->written_blocks = 0; |
484 |
host->flags &= ~CARD_BUSY; |
485 |
tifm_sd_prepare_data(host, mrq->cmd); |
486 |
} |
487 |
|
488 |
host->req = mrq; |
489 |
mod_timer(&host->timer, jiffies + host->timeout_jiffies); |
490 |
host->state = CMD; |
491 |
writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), |
492 |
sock->addr + SOCK_CONTROL); |
493 |
tifm_sd_exec(host, mrq->cmd); |
494 |
spin_unlock_irqrestore(&sock->lock, flags); |
495 |
return; |
496 |
|
497 |
err_out: |
498 |
if (sg_count > 0) |
499 |
tifm_unmap_sg(sock, r_data->sg, r_data->sg_len, |
500 |
(r_data->flags & MMC_DATA_WRITE) |
501 |
? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); |
502 |
|
503 |
mrq->cmd->error = MMC_ERR_TIMEOUT; |
504 |
mmc_request_done(mmc, mrq); |
505 |
} |
506 |
|
507 |
static void tifm_sd_end_cmd(unsigned long data) |
508 |
{ |
509 |
struct tifm_sd *host = (struct tifm_sd*)data; |
510 |
struct tifm_dev *sock = host->dev; |
511 |
struct mmc_host *mmc = tifm_get_drvdata(sock); |
512 |
struct mmc_request *mrq; |
513 |
struct mmc_data *r_data = NULL; |
514 |
unsigned long flags; |
515 |
|
516 |
spin_lock_irqsave(&sock->lock, flags); |
517 |
|
518 |
del_timer(&host->timer); |
519 |
mrq = host->req; |
520 |
host->req = NULL; |
521 |
host->state = IDLE; |
522 |
|
653 |
|
523 |
if (!mrq) { |
654 |
if (host->no_dma) { |
524 |
printk(KERN_ERR DRIVER_NAME ": no request to complete?\n"); |
655 |
writel(TIFM_MMCSD_BUFINT |
525 |
spin_unlock_irqrestore(&sock->lock, flags); |
656 |
| readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
526 |
return; |
657 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
527 |
} |
658 |
writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) |
|
|
659 |
| (TIFM_MMCSD_FIFO_SIZE - 1), |
660 |
sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
528 |
|
661 |
|
529 |
r_data = mrq->cmd->data; |
662 |
host->sg_len = r_data->sg_len; |
530 |
if (r_data) { |
|
|
531 |
if (r_data->flags & MMC_DATA_WRITE) { |
532 |
r_data->bytes_xfered = host->written_blocks |
533 |
* r_data->blksz; |
534 |
} else { |
663 |
} else { |
535 |
r_data->bytes_xfered = r_data->blocks - |
664 |
sg_init_one(&host->bounce_buf, host->bounce_buf_data, |
536 |
readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; |
665 |
r_data->blksz); |
537 |
r_data->bytes_xfered *= r_data->blksz; |
666 |
|
538 |
r_data->bytes_xfered += r_data->blksz - |
667 |
if(1 != tifm_map_sg(sock, &host->bounce_buf, 1, |
539 |
readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; |
668 |
r_data->flags & MMC_DATA_WRITE |
540 |
} |
669 |
? PCI_DMA_TODEVICE |
541 |
tifm_unmap_sg(sock, r_data->sg, r_data->sg_len, |
670 |
: PCI_DMA_FROMDEVICE)) { |
542 |
(r_data->flags & MMC_DATA_WRITE) |
671 |
printk(KERN_ERR "%s : scatterlist map failed\n", |
543 |
? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); |
672 |
sock->dev.bus_id); |
544 |
} |
673 |
spin_unlock_irqrestore(&sock->lock, flags); |
545 |
|
674 |
goto err_out; |
546 |
writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
675 |
} |
547 |
sock->addr + SOCK_CONTROL); |
676 |
host->sg_len = tifm_map_sg(sock, r_data->sg, |
548 |
|
677 |
r_data->sg_len, |
549 |
spin_unlock_irqrestore(&sock->lock, flags); |
678 |
r_data->flags |
550 |
mmc_request_done(mmc, mrq); |
679 |
& MMC_DATA_WRITE |
551 |
} |
680 |
? PCI_DMA_TODEVICE |
552 |
|
681 |
: PCI_DMA_FROMDEVICE); |
553 |
static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) |
682 |
if (host->sg_len < 1) { |
554 |
{ |
683 |
printk(KERN_ERR "%s : scatterlist map failed\n", |
555 |
struct tifm_sd *host = mmc_priv(mmc); |
684 |
sock->dev.bus_id); |
556 |
struct tifm_dev *sock = host->dev; |
685 |
tifm_unmap_sg(sock, &host->bounce_buf, 1, |
557 |
unsigned long flags; |
686 |
r_data->flags & MMC_DATA_WRITE |
558 |
struct mmc_data *r_data = mrq->cmd->data; |
687 |
? PCI_DMA_TODEVICE |
559 |
|
688 |
: PCI_DMA_FROMDEVICE); |
560 |
spin_lock_irqsave(&sock->lock, flags); |
689 |
spin_unlock_irqrestore(&sock->lock, flags); |
561 |
if (host->flags & EJECT) { |
690 |
goto err_out; |
562 |
spin_unlock_irqrestore(&sock->lock, flags); |
691 |
} |
563 |
goto err_out; |
|
|
564 |
} |
565 |
|
566 |
if (host->req) { |
567 |
printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n"); |
568 |
spin_unlock_irqrestore(&sock->lock, flags); |
569 |
goto err_out; |
570 |
} |
571 |
|
692 |
|
572 |
if (r_data) { |
693 |
writel(TIFM_FIFO_INT_SETALL, |
573 |
tifm_sd_set_data_timeout(host, r_data); |
694 |
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
|
|
695 |
writel(ilog2(r_data->blksz) - 2, |
696 |
sock->addr + SOCK_FIFO_PAGE_SIZE); |
697 |
writel(TIFM_FIFO_ENABLE, |
698 |
sock->addr + SOCK_FIFO_CONTROL); |
699 |
writel(TIFM_FIFO_INTMASK, |
700 |
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); |
701 |
|
702 |
if (r_data->flags & MMC_DATA_WRITE) |
703 |
writel(TIFM_MMCSD_TXDE, |
704 |
sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
705 |
else |
706 |
writel(TIFM_MMCSD_RXDE, |
707 |
sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
708 |
|
709 |
tifm_sd_set_dma_data(host, r_data); |
710 |
} |
574 |
|
711 |
|
575 |
host->buffer_size = mrq->cmd->data->blocks |
712 |
writel(r_data->blocks - 1, |
576 |
* mrq->cmd->data->blksz; |
713 |
sock->addr + SOCK_MMCSD_NUM_BLOCKS); |
577 |
|
714 |
writel(r_data->blksz - 1, |
578 |
writel(TIFM_MMCSD_BUFINT |
715 |
sock->addr + SOCK_MMCSD_BLOCK_LEN); |
579 |
| readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
|
|
580 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
581 |
writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) |
582 |
| (TIFM_MMCSD_FIFO_SIZE - 1), |
583 |
sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
584 |
|
585 |
host->written_blocks = 0; |
586 |
host->flags &= ~CARD_BUSY; |
587 |
host->buffer_pos = 0; |
588 |
writel(r_data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS); |
589 |
writel(r_data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN); |
590 |
} |
716 |
} |
591 |
|
717 |
|
592 |
host->req = mrq; |
718 |
host->req = mrq; |
593 |
mod_timer(&host->timer, jiffies + host->timeout_jiffies); |
719 |
mod_timer(&host->timer, jiffies + host->timeout_jiffies); |
594 |
host->state = CMD; |
|
|
595 |
writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), |
720 |
writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), |
596 |
sock->addr + SOCK_CONTROL); |
721 |
sock->addr + SOCK_CONTROL); |
597 |
tifm_sd_exec(host, mrq->cmd); |
722 |
tifm_sd_exec(host, mrq->cmd); |
Lines 603-609
err_out:
Link Here
|
603 |
mmc_request_done(mmc, mrq); |
728 |
mmc_request_done(mmc, mrq); |
604 |
} |
729 |
} |
605 |
|
730 |
|
606 |
static void tifm_sd_end_cmd_nodma(unsigned long data) |
731 |
static void tifm_sd_end_cmd(unsigned long data) |
607 |
{ |
732 |
{ |
608 |
struct tifm_sd *host = (struct tifm_sd*)data; |
733 |
struct tifm_sd *host = (struct tifm_sd*)data; |
609 |
struct tifm_dev *sock = host->dev; |
734 |
struct tifm_dev *sock = host->dev; |
Lines 617-684
static void tifm_sd_end_cmd_nodma(unsigned long data)
Link Here
|
617 |
del_timer(&host->timer); |
742 |
del_timer(&host->timer); |
618 |
mrq = host->req; |
743 |
mrq = host->req; |
619 |
host->req = NULL; |
744 |
host->req = NULL; |
620 |
host->state = IDLE; |
|
|
621 |
|
745 |
|
622 |
if (!mrq) { |
746 |
if (!mrq) { |
623 |
printk(KERN_ERR DRIVER_NAME ": no request to complete?\n"); |
747 |
printk(KERN_ERR " %s : no request to complete?\n", |
|
|
748 |
sock->dev.bus_id); |
624 |
spin_unlock_irqrestore(&sock->lock, flags); |
749 |
spin_unlock_irqrestore(&sock->lock, flags); |
625 |
return; |
750 |
return; |
626 |
} |
751 |
} |
627 |
|
752 |
|
628 |
r_data = mrq->cmd->data; |
753 |
r_data = mrq->cmd->data; |
629 |
if (r_data) { |
754 |
if (r_data) { |
630 |
writel((~TIFM_MMCSD_BUFINT) & |
755 |
if (host->no_dma) { |
631 |
readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
756 |
writel((~TIFM_MMCSD_BUFINT) |
632 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
757 |
& readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
633 |
|
758 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
634 |
if (r_data->flags & MMC_DATA_WRITE) { |
|
|
635 |
r_data->bytes_xfered = host->written_blocks |
636 |
* r_data->blksz; |
637 |
} else { |
759 |
} else { |
638 |
r_data->bytes_xfered = r_data->blocks - |
760 |
tifm_unmap_sg(sock, &host->bounce_buf, 1, |
639 |
readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; |
761 |
(r_data->flags & MMC_DATA_WRITE) |
640 |
r_data->bytes_xfered *= r_data->blksz; |
762 |
? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); |
641 |
r_data->bytes_xfered += r_data->blksz - |
763 |
tifm_unmap_sg(sock, r_data->sg, r_data->sg_len, |
642 |
readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; |
764 |
(r_data->flags & MMC_DATA_WRITE) |
|
|
765 |
? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); |
643 |
} |
766 |
} |
644 |
host->buffer_pos = 0; |
767 |
|
645 |
host->buffer_size = 0; |
768 |
r_data->bytes_xfered = r_data->blocks |
|
|
769 |
- readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; |
770 |
r_data->bytes_xfered *= r_data->blksz; |
771 |
r_data->bytes_xfered += r_data->blksz |
772 |
- readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; |
646 |
} |
773 |
} |
647 |
|
774 |
|
648 |
writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
775 |
writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
649 |
sock->addr + SOCK_CONTROL); |
776 |
sock->addr + SOCK_CONTROL); |
650 |
|
777 |
|
651 |
spin_unlock_irqrestore(&sock->lock, flags); |
778 |
spin_unlock_irqrestore(&sock->lock, flags); |
652 |
|
|
|
653 |
mmc_request_done(mmc, mrq); |
779 |
mmc_request_done(mmc, mrq); |
654 |
} |
780 |
} |
655 |
|
781 |
|
656 |
static void tifm_sd_terminate(struct tifm_sd *host) |
|
|
657 |
{ |
658 |
struct tifm_dev *sock = host->dev; |
659 |
unsigned long flags; |
660 |
|
661 |
writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); |
662 |
mmiowb(); |
663 |
spin_lock_irqsave(&sock->lock, flags); |
664 |
host->flags |= EJECT; |
665 |
if (host->req) { |
666 |
writel(TIFM_FIFO_INT_SETALL, |
667 |
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
668 |
writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); |
669 |
tasklet_schedule(&host->finish_tasklet); |
670 |
} |
671 |
spin_unlock_irqrestore(&sock->lock, flags); |
672 |
} |
673 |
|
674 |
static void tifm_sd_abort(unsigned long data) |
782 |
static void tifm_sd_abort(unsigned long data) |
675 |
{ |
783 |
{ |
676 |
struct tifm_sd *host = (struct tifm_sd*)data; |
784 |
struct tifm_sd *host = (struct tifm_sd*)data; |
677 |
|
785 |
|
678 |
printk(KERN_ERR DRIVER_NAME |
786 |
printk(KERN_ERR |
679 |
": card failed to respond for a long period of time"); |
787 |
"%s : card failed to respond for a long period of time " |
|
|
788 |
"(%x, %x)\n", |
789 |
host->dev->dev.bus_id, host->req->cmd->opcode, host->cmd_flags); |
680 |
|
790 |
|
681 |
tifm_sd_terminate(host); |
|
|
682 |
tifm_eject(host->dev); |
791 |
tifm_eject(host->dev); |
683 |
} |
792 |
} |
684 |
|
793 |
|
Lines 691-698
static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
Link Here
|
691 |
|
800 |
|
692 |
spin_lock_irqsave(&sock->lock, flags); |
801 |
spin_lock_irqsave(&sock->lock, flags); |
693 |
|
802 |
|
694 |
dev_dbg(&sock->dev, "Setting bus width %d, power %d\n", ios->bus_width, |
803 |
dev_dbg(&sock->dev, "ios: clock = %u, vdd = %x, bus_mode = %x, " |
695 |
ios->power_mode); |
804 |
"chip_select = %x, power_mode = %x, bus_width = %x\n", |
|
|
805 |
ios->clock, ios->vdd, ios->bus_mode, ios->chip_select, |
806 |
ios->power_mode, ios->bus_width); |
807 |
|
696 |
if (ios->bus_width == MMC_BUS_WIDTH_4) { |
808 |
if (ios->bus_width == MMC_BUS_WIDTH_4) { |
697 |
writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG), |
809 |
writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG), |
698 |
sock->addr + SOCK_MMCSD_CONFIG); |
810 |
sock->addr + SOCK_MMCSD_CONFIG); |
Lines 737-777
static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
Link Here
|
737 |
& readl(sock->addr + SOCK_MMCSD_CONFIG)), |
849 |
& readl(sock->addr + SOCK_MMCSD_CONFIG)), |
738 |
sock->addr + SOCK_MMCSD_CONFIG); |
850 |
sock->addr + SOCK_MMCSD_CONFIG); |
739 |
|
851 |
|
740 |
if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) |
852 |
host->open_drain = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN); |
741 |
host->flags |= OPENDRAIN; |
|
|
742 |
else |
743 |
host->flags &= ~OPENDRAIN; |
744 |
|
853 |
|
745 |
/* chip_select : maybe later */ |
854 |
/* chip_select : maybe later */ |
746 |
//vdd |
855 |
//vdd |
747 |
//power is set before probe / after remove |
856 |
//power is set before probe / after remove |
748 |
//I believe, power_off when already marked for eject is sufficient to |
|
|
749 |
// allow removal. |
750 |
if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) { |
751 |
host->flags |= EJECT_DONE; |
752 |
wake_up_all(&host->notify); |
753 |
} |
754 |
|
857 |
|
755 |
spin_unlock_irqrestore(&sock->lock, flags); |
858 |
spin_unlock_irqrestore(&sock->lock, flags); |
756 |
} |
859 |
} |
757 |
|
860 |
|
758 |
static int tifm_sd_ro(struct mmc_host *mmc) |
861 |
static int tifm_sd_ro(struct mmc_host *mmc) |
759 |
{ |
862 |
{ |
760 |
int rc; |
863 |
int rc = 0; |
761 |
struct tifm_sd *host = mmc_priv(mmc); |
864 |
struct tifm_sd *host = mmc_priv(mmc); |
762 |
struct tifm_dev *sock = host->dev; |
865 |
struct tifm_dev *sock = host->dev; |
763 |
unsigned long flags; |
866 |
unsigned long flags; |
764 |
|
867 |
|
765 |
spin_lock_irqsave(&sock->lock, flags); |
868 |
spin_lock_irqsave(&sock->lock, flags); |
766 |
|
869 |
if (TIFM_MMCSD_CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE)) |
767 |
host->flags |= (CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE)); |
870 |
rc = 1; |
768 |
rc = (host->flags & CARD_RO) ? 1 : 0; |
|
|
769 |
|
770 |
spin_unlock_irqrestore(&sock->lock, flags); |
871 |
spin_unlock_irqrestore(&sock->lock, flags); |
771 |
return rc; |
872 |
return rc; |
772 |
} |
873 |
} |
773 |
|
874 |
|
774 |
static struct mmc_host_ops tifm_sd_ops = { |
875 |
static const struct mmc_host_ops tifm_sd_ops = { |
775 |
.request = tifm_sd_request, |
876 |
.request = tifm_sd_request, |
776 |
.set_ios = tifm_sd_ios, |
877 |
.set_ios = tifm_sd_ios, |
777 |
.get_ro = tifm_sd_ro |
878 |
.get_ro = tifm_sd_ro |
Lines 792-798
static int tifm_sd_initialize_host(struct tifm_sd *host)
Link Here
|
792 |
sock->addr + SOCK_MMCSD_CONFIG); |
893 |
sock->addr + SOCK_MMCSD_CONFIG); |
793 |
|
894 |
|
794 |
/* wait up to 0.51 sec for reset */ |
895 |
/* wait up to 0.51 sec for reset */ |
795 |
for (rc = 2; rc <= 256; rc <<= 1) { |
896 |
for (rc = 32; rc <= 256; rc <<= 1) { |
796 |
if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { |
897 |
if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { |
797 |
rc = 0; |
898 |
rc = 0; |
798 |
break; |
899 |
break; |
Lines 801-808
static int tifm_sd_initialize_host(struct tifm_sd *host)
Link Here
|
801 |
} |
902 |
} |
802 |
|
903 |
|
803 |
if (rc) { |
904 |
if (rc) { |
804 |
printk(KERN_ERR DRIVER_NAME |
905 |
printk(KERN_ERR "%s : controller failed to reset\n", |
805 |
": controller failed to reset\n"); |
906 |
sock->dev.bus_id); |
806 |
return -ENODEV; |
907 |
return -ENODEV; |
807 |
} |
908 |
} |
808 |
|
909 |
|
Lines 815-822
static int tifm_sd_initialize_host(struct tifm_sd *host)
Link Here
|
815 |
writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); |
916 |
writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); |
816 |
writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); |
917 |
writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); |
817 |
|
918 |
|
818 |
/* INAB should take much less than reset */ |
919 |
for (rc = 16; rc <= 64; rc <<= 1) { |
819 |
for (rc = 1; rc <= 16; rc <<= 1) { |
|
|
820 |
host_status = readl(sock->addr + SOCK_MMCSD_STATUS); |
920 |
host_status = readl(sock->addr + SOCK_MMCSD_STATUS); |
821 |
writel(host_status, sock->addr + SOCK_MMCSD_STATUS); |
921 |
writel(host_status, sock->addr + SOCK_MMCSD_STATUS); |
822 |
if (!(host_status & TIFM_MMCSD_ERRMASK) |
922 |
if (!(host_status & TIFM_MMCSD_ERRMASK) |
Lines 828-839
static int tifm_sd_initialize_host(struct tifm_sd *host)
Link Here
|
828 |
} |
928 |
} |
829 |
|
929 |
|
830 |
if (rc) { |
930 |
if (rc) { |
831 |
printk(KERN_ERR DRIVER_NAME |
931 |
printk(KERN_ERR |
832 |
": card not ready - probe failed on initialization\n"); |
932 |
"%s : card not ready - probe failed on initialization\n", |
|
|
933 |
sock->dev.bus_id); |
833 |
return -ENODEV; |
934 |
return -ENODEV; |
834 |
} |
935 |
} |
835 |
|
936 |
|
836 |
writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK, |
937 |
writel(TIFM_MMCSD_CERR | TIFM_MMCSD_BRS | TIFM_MMCSD_EOC |
|
|
938 |
| TIFM_MMCSD_ERRMASK, |
837 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
939 |
sock->addr + SOCK_MMCSD_INT_ENABLE); |
838 |
mmiowb(); |
940 |
mmiowb(); |
839 |
|
941 |
|
Lines 848-854
static int tifm_sd_probe(struct tifm_dev *sock)
Link Here
|
848 |
|
950 |
|
849 |
if (!(TIFM_SOCK_STATE_OCCUPIED |
951 |
if (!(TIFM_SOCK_STATE_OCCUPIED |
850 |
& readl(sock->addr + SOCK_PRESENT_STATE))) { |
952 |
& readl(sock->addr + SOCK_PRESENT_STATE))) { |
851 |
printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n"); |
953 |
printk(KERN_WARNING "%s : card gone, unexpectedly\n", |
|
|
954 |
sock->dev.bus_id); |
852 |
return rc; |
955 |
return rc; |
853 |
} |
956 |
} |
854 |
|
957 |
|
Lines 857-897
static int tifm_sd_probe(struct tifm_dev *sock)
Link Here
|
857 |
return -ENOMEM; |
960 |
return -ENOMEM; |
858 |
|
961 |
|
859 |
host = mmc_priv(mmc); |
962 |
host = mmc_priv(mmc); |
|
|
963 |
host->no_dma = no_dma; |
860 |
tifm_set_drvdata(sock, mmc); |
964 |
tifm_set_drvdata(sock, mmc); |
861 |
host->dev = sock; |
965 |
host->dev = sock; |
862 |
host->timeout_jiffies = msecs_to_jiffies(1000); |
966 |
host->timeout_jiffies = msecs_to_jiffies(1000); |
863 |
|
967 |
|
864 |
init_waitqueue_head(&host->notify); |
968 |
tasklet_init(&host->finish_tasklet, tifm_sd_end_cmd, |
865 |
tasklet_init(&host->finish_tasklet, |
|
|
866 |
no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, |
867 |
(unsigned long)host); |
969 |
(unsigned long)host); |
868 |
setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host); |
970 |
setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host); |
869 |
|
971 |
|
870 |
tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request; |
|
|
871 |
mmc->ops = &tifm_sd_ops; |
972 |
mmc->ops = &tifm_sd_ops; |
872 |
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
973 |
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
873 |
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; |
974 |
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; |
874 |
mmc->f_min = 20000000 / 60; |
975 |
mmc->f_min = 20000000 / 60; |
875 |
mmc->f_max = 24000000; |
976 |
mmc->f_max = 24000000; |
876 |
mmc->max_hw_segs = 1; |
977 |
#if 0 |
877 |
mmc->max_phys_segs = 1; |
978 |
mmc->max_seg_size = 2048 * 2048; |
878 |
// limited by DMA counter - it's safer to stick with |
979 |
mmc->max_hw_segs = 2048; |
879 |
// block counter has 11 bits though |
980 |
mmc->max_phys_segs = 2048; |
880 |
mmc->max_blk_count = 256; |
981 |
mmc->max_sectors = 2048; |
881 |
// 2k maximum hw block length |
982 |
#endif |
882 |
mmc->max_blk_size = 2048; |
983 |
mmc->max_blk_count = 2048; |
883 |
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
984 |
mmc->max_hw_segs = mmc->max_blk_count; |
884 |
mmc->max_seg_size = mmc->max_req_size; |
985 |
mmc->max_phys_segs = mmc->max_hw_segs; |
885 |
sock->signal_irq = tifm_sd_signal_irq; |
986 |
mmc->max_blk_size = min(2048UL, PAGE_SIZE); |
|
|
987 |
mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size; |
988 |
mmc->max_req_size = mmc->max_seg_size; |
989 |
|
990 |
sock->card_event = tifm_sd_card_event; |
991 |
sock->data_event = tifm_sd_data_event; |
886 |
rc = tifm_sd_initialize_host(host); |
992 |
rc = tifm_sd_initialize_host(host); |
887 |
|
993 |
|
888 |
if (!rc) |
994 |
if (!rc) |
889 |
rc = mmc_add_host(mmc); |
995 |
rc = mmc_add_host(mmc); |
890 |
if (rc) |
996 |
if (!rc) |
891 |
goto out_free_mmc; |
997 |
return 0; |
892 |
|
998 |
|
893 |
return 0; |
|
|
894 |
out_free_mmc: |
895 |
mmc_free_host(mmc); |
999 |
mmc_free_host(mmc); |
896 |
return rc; |
1000 |
return rc; |
897 |
} |
1001 |
} |
Lines 900-918
static void tifm_sd_remove(struct tifm_dev *sock)
Link Here
|
900 |
{ |
1004 |
{ |
901 |
struct mmc_host *mmc = tifm_get_drvdata(sock); |
1005 |
struct mmc_host *mmc = tifm_get_drvdata(sock); |
902 |
struct tifm_sd *host = mmc_priv(mmc); |
1006 |
struct tifm_sd *host = mmc_priv(mmc); |
|
|
1007 |
unsigned long flags; |
1008 |
|
1009 |
spin_lock_irqsave(&sock->lock, flags); |
1010 |
host->eject = 1; |
1011 |
writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); |
1012 |
mmiowb(); |
1013 |
spin_unlock_irqrestore(&sock->lock, flags); |
903 |
|
1014 |
|
904 |
del_timer_sync(&host->timer); |
|
|
905 |
tifm_sd_terminate(host); |
906 |
wait_event_timeout(host->notify, host->flags & EJECT_DONE, |
907 |
host->timeout_jiffies); |
908 |
tasklet_kill(&host->finish_tasklet); |
1015 |
tasklet_kill(&host->finish_tasklet); |
|
|
1016 |
|
1017 |
spin_lock_irqsave(&sock->lock, flags); |
1018 |
if (host->req) { |
1019 |
writel(TIFM_FIFO_INT_SETALL, |
1020 |
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
1021 |
writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); |
1022 |
host->req->cmd->error = MMC_ERR_TIMEOUT; |
1023 |
if (host->req->stop) |
1024 |
host->req->stop->error = MMC_ERR_TIMEOUT; |
1025 |
tasklet_schedule(&host->finish_tasklet); |
1026 |
} |
1027 |
spin_unlock_irqrestore(&sock->lock, flags); |
909 |
mmc_remove_host(mmc); |
1028 |
mmc_remove_host(mmc); |
|
|
1029 |
dev_dbg(&sock->dev, "after remove\n"); |
910 |
|
1030 |
|
911 |
/* The meaning of the bit majority in this constant is unknown. */ |
1031 |
/* The meaning of the bit majority in this constant is unknown. */ |
912 |
writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), |
1032 |
writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), |
913 |
sock->addr + SOCK_CONTROL); |
1033 |
sock->addr + SOCK_CONTROL); |
914 |
|
1034 |
|
915 |
tifm_set_drvdata(sock, NULL); |
|
|
916 |
mmc_free_host(mmc); |
1035 |
mmc_free_host(mmc); |
917 |
} |
1036 |
} |
918 |
|
1037 |
|
Lines 934-947
static int tifm_sd_resume(struct tifm_dev *sock)
Link Here
|
934 |
{ |
1053 |
{ |
935 |
struct mmc_host *mmc = tifm_get_drvdata(sock); |
1054 |
struct mmc_host *mmc = tifm_get_drvdata(sock); |
936 |
struct tifm_sd *host = mmc_priv(mmc); |
1055 |
struct tifm_sd *host = mmc_priv(mmc); |
|
|
1056 |
int rc; |
937 |
|
1057 |
|
938 |
if (sock->media_id != FM_SD |
1058 |
rc = tifm_sd_initialize_host(host); |
939 |
|| tifm_sd_initialize_host(host)) { |
1059 |
dev_dbg(&sock->dev, "resume initialize %d\n", rc); |
940 |
tifm_eject(sock); |
1060 |
|
941 |
return 0; |
1061 |
if (rc) |
942 |
} else { |
1062 |
host->eject = 1; |
943 |
return mmc_resume_host(mmc); |
1063 |
else |
944 |
} |
1064 |
rc = mmc_resume_host(mmc); |
|
|
1065 |
|
1066 |
return rc; |
945 |
} |
1067 |
} |
946 |
|
1068 |
|
947 |
#else |
1069 |
#else |
Lines 951-958
static int tifm_sd_resume(struct tifm_dev *sock)
Link Here
|
951 |
|
1073 |
|
952 |
#endif /* CONFIG_PM */ |
1074 |
#endif /* CONFIG_PM */ |
953 |
|
1075 |
|
954 |
static tifm_media_id tifm_sd_id_tbl[] = { |
1076 |
static struct tifm_device_id tifm_sd_id_tbl[] = { |
955 |
FM_SD, 0 |
1077 |
{ TIFM_TYPE_SD }, { } |
956 |
}; |
1078 |
}; |
957 |
|
1079 |
|
958 |
static struct tifm_driver tifm_sd_driver = { |
1080 |
static struct tifm_driver tifm_sd_driver = { |