aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/memstick/host/tifm_ms.c524
-rw-r--r--include/linux/tifm.h2
2 files changed, 264 insertions, 262 deletions
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index c62e709ca771..b88f5b30efbf 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -24,275 +24,289 @@
24static int no_dma; 24static int no_dma;
25module_param(no_dma, bool, 0644); 25module_param(no_dma, bool, 0644);
26 26
27#define TIFM_MS_TIMEOUT 0x00100 27/*
28#define TIFM_MS_BADCRC 0x00200 28 * Some control bits of TIFM appear to conform to Sony's reference design,
29#define TIFM_MS_EOTPC 0x01000 29 * so I'm just assuming they all are.
30#define TIFM_MS_INT 0x02000 30 */
31
32/* The meaning of the bit majority in this constant is unknown. */
33#define TIFM_MS_SERIAL 0x04010
34 31
35#define TIFM_MS_SYS_LATCH 0x00100 32#define TIFM_MS_STAT_DRQ 0x04000
36#define TIFM_MS_SYS_NOT_RDY 0x00800 33#define TIFM_MS_STAT_MSINT 0x02000
37#define TIFM_MS_SYS_DATA 0x10000 34#define TIFM_MS_STAT_RDY 0x01000
35#define TIFM_MS_STAT_CRC 0x00200
36#define TIFM_MS_STAT_TOE 0x00100
37#define TIFM_MS_STAT_EMP 0x00020
38#define TIFM_MS_STAT_FUL 0x00010
39#define TIFM_MS_STAT_CED 0x00008
40#define TIFM_MS_STAT_ERR 0x00004
41#define TIFM_MS_STAT_BRQ 0x00002
42#define TIFM_MS_STAT_CNK 0x00001
43
44#define TIFM_MS_SYS_DMA 0x10000
45#define TIFM_MS_SYS_RESET 0x08000
46#define TIFM_MS_SYS_SRAC 0x04000
47#define TIFM_MS_SYS_INTEN 0x02000
48#define TIFM_MS_SYS_NOCRC 0x01000
49#define TIFM_MS_SYS_INTCLR 0x00800
50#define TIFM_MS_SYS_MSIEN 0x00400
51#define TIFM_MS_SYS_FCLR 0x00200
52#define TIFM_MS_SYS_FDIR 0x00100
53#define TIFM_MS_SYS_DAM 0x00080
54#define TIFM_MS_SYS_DRM 0x00040
55#define TIFM_MS_SYS_DRQSL 0x00020
56#define TIFM_MS_SYS_REI 0x00010
57#define TIFM_MS_SYS_REO 0x00008
58#define TIFM_MS_SYS_BSY_MASK 0x00007
59
60#define TIFM_MS_SYS_FIFO (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \
61 | TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK)
38 62
39/* Hardware flags */ 63/* Hardware flags */
40enum { 64enum {
41 CMD_READY = 0x0001, 65 CMD_READY = 0x01,
42 FIFO_READY = 0x0002, 66 FIFO_READY = 0x02,
43 CARD_READY = 0x0004, 67 CARD_INT = 0x04
44 DATA_CARRY = 0x0008
45}; 68};
46 69
47struct tifm_ms { 70struct tifm_ms {
48 struct tifm_dev *dev; 71 struct tifm_dev *dev;
49 unsigned short eject:1, 72 struct timer_list timer;
50 no_dma:1; 73 struct memstick_request *req;
51 unsigned short cmd_flags;
52 unsigned int mode_mask; 74 unsigned int mode_mask;
53 unsigned int block_pos; 75 unsigned int block_pos;
54 unsigned long timeout_jiffies; 76 unsigned long timeout_jiffies;
55 77 unsigned char eject:1,
56 struct timer_list timer; 78 use_dma:1;
57 struct memstick_request *req; 79 unsigned char cmd_flags;
80 unsigned char io_pos;
58 unsigned int io_word; 81 unsigned int io_word;
59}; 82};
60 83
61static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset, 84static unsigned int tifm_ms_read_data(struct tifm_ms *host,
62 struct page *pg, unsigned int page_off, 85 unsigned char *buf, unsigned int length)
63 unsigned int length)
64{ 86{
65 struct tifm_dev *sock = host->dev; 87 struct tifm_dev *sock = host->dev;
66 unsigned int cnt = 0, off = 0; 88 unsigned int off = 0;
67 unsigned char *buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + page_off; 89
90 while (host->io_pos && length) {
91 buf[off++] = host->io_word & 0xff;
92 host->io_word >>= 8;
93 length--;
94 host->io_pos--;
95 }
96
97 if (!length)
98 return off;
99
100 while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
101 if (length < 4)
102 break;
103 *(unsigned int *)(buf + off) = __raw_readl(sock->addr
104 + SOCK_MS_DATA);
105 length -= 4;
106 off += 4;
107 }
68 108
69 if (host->cmd_flags & DATA_CARRY) { 109 if (length
70 while ((fifo_offset & 3) && length) { 110 && !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
111 host->io_word = readl(sock->addr + SOCK_MS_DATA);
112 for (host->io_pos = 4; host->io_pos; --host->io_pos) {
71 buf[off++] = host->io_word & 0xff; 113 buf[off++] = host->io_word & 0xff;
72 host->io_word >>= 8; 114 host->io_word >>= 8;
73 length--; 115 length--;
74 fifo_offset++; 116 if (!length)
117 break;
75 } 118 }
76 if (!(fifo_offset & 3))
77 host->cmd_flags &= ~DATA_CARRY;
78 if (!length)
79 return;
80 } 119 }
81 120
82 do { 121 return off;
83 host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS
84 + fifo_offset);
85 cnt = 4;
86 while (length && cnt) {
87 buf[off++] = (host->io_word >> 8) & 0xff;
88 cnt--;
89 length--;
90 }
91 fifo_offset += 4 - cnt;
92 } while (length);
93
94 if (cnt)
95 host->cmd_flags |= DATA_CARRY;
96
97 kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ);
98} 122}
99 123
100static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset, 124static unsigned int tifm_ms_write_data(struct tifm_ms *host,
101 struct page *pg, unsigned int page_off, 125 unsigned char *buf, unsigned int length)
102 unsigned int length)
103{ 126{
104 struct tifm_dev *sock = host->dev; 127 struct tifm_dev *sock = host->dev;
105 unsigned int cnt = 0, off = 0; 128 unsigned int off = 0;
106 unsigned char *buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + page_off;
107 129
108 if (host->cmd_flags & DATA_CARRY) { 130 if (host->io_pos) {
109 while (fifo_offset & 3) { 131 while (host->io_pos < 4 && length) {
110 host->io_word |= buf[off++] << (8 * (fifo_offset & 3)); 132 host->io_word |= buf[off++] << (host->io_pos * 8);
133 host->io_pos++;
111 length--; 134 length--;
112 fifo_offset++;
113 }
114 if (!(fifo_offset & 3)) {
115 writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
116 + fifo_offset - 4);
117
118 host->cmd_flags &= ~DATA_CARRY;
119 } 135 }
120 if (!length)
121 return;
122 } 136 }
123 137
124 do { 138 if (host->io_pos == 4
125 cnt = 4; 139 && !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
140 writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
141 sock->addr + SOCK_MS_SYSTEM);
142 writel(host->io_word, sock->addr + SOCK_MS_DATA);
143 host->io_pos = 0;
126 host->io_word = 0; 144 host->io_word = 0;
127 while (length && cnt) { 145 } else if (host->io_pos) {
128 host->io_word |= buf[off++] << (4 - cnt); 146 return off;
129 cnt--; 147 }
130 length--;
131 }
132 fifo_offset += 4 - cnt;
133 if (!cnt)
134 writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
135 + fifo_offset - 4);
136
137 } while (length);
138
139 if (cnt)
140 host->cmd_flags |= DATA_CARRY;
141 148
142 kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ); 149 if (!length)
143} 150 return off;
144 151
145static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length) 152 while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
146{ 153 if (length < 4)
147 unsigned int t_size; 154 break;
148 unsigned int off = host->req->sg.offset + host->block_pos; 155 writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
149 unsigned int p_off, p_cnt; 156 sock->addr + SOCK_MS_SYSTEM);
150 struct page *pg; 157 __raw_writel(*(unsigned int *)(buf + off),
151 unsigned long flags; 158 sock->addr + SOCK_MS_DATA);
159 length -= 4;
160 off += 4;
161 }
152 162
153 dev_dbg(&host->dev->dev, "moving block\n"); 163 switch (length) {
154 local_irq_save(flags); 164 case 3:
155 t_size = length; 165 host->io_word |= buf[off + 2] << 16;
156 while (t_size) { 166 host->io_pos++;
157 pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT); 167 case 2:
158 p_off = offset_in_page(off); 168 host->io_word |= buf[off + 1] << 8;
159 p_cnt = PAGE_SIZE - p_off; 169 host->io_pos++;
160 p_cnt = min(p_cnt, t_size); 170 case 1:
171 host->io_word |= buf[off];
172 host->io_pos++;
173 }
161 174
162 if (host->req->data_dir == WRITE) 175 off += host->io_pos;
163 tifm_ms_write_fifo(host, length - t_size,
164 pg, p_off, p_cnt);
165 else
166 tifm_ms_read_fifo(host, length - t_size,
167 pg, p_off, p_cnt);
168 176
169 t_size -= p_cnt; 177 return off;
170 }
171 local_irq_restore(flags);
172} 178}
173 179
174static int tifm_ms_transfer_data(struct tifm_ms *host, int skip) 180static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
175{ 181{
176 struct tifm_dev *sock = host->dev; 182 struct tifm_dev *sock = host->dev;
177 unsigned int length = host->req->sg.length - host->block_pos; 183 unsigned int length;
184 unsigned int off;
185 unsigned int t_size, p_off, p_cnt;
186 unsigned char *buf;
187 struct page *pg;
188 unsigned long flags = 0;
178 189
179 if (!length) 190 if (host->req->long_data) {
180 return 1; 191 length = host->req->sg.length - host->block_pos;
192 off = host->req->sg.offset + host->block_pos;
193 } else {
194 length = host->req->data_len - host->block_pos;
195 off = 0;
196 }
197 dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length,
198 host->block_pos);
199
200 while (length) {
201 if (host->req->long_data) {
202 pg = nth_page(sg_page(&host->req->sg),
203 off >> PAGE_SHIFT);
204 p_off = offset_in_page(off);
205 p_cnt = PAGE_SIZE - p_off;
206 p_cnt = min(p_cnt, length);
207
208 local_irq_save(flags);
209 buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
210 } else {
211 buf = host->req->data + host->block_pos;
212 p_cnt = host->req->data_len - host->block_pos;
213 }
181 214
182 if (length > TIFM_FIFO_SIZE) 215 t_size = host->req->data_dir == WRITE
183 length = TIFM_FIFO_SIZE; 216 ? tifm_ms_write_data(host, buf, p_cnt)
217 : tifm_ms_read_data(host, buf, p_cnt);
184 218
185 if (!skip) { 219 if (host->req->long_data) {
186 tifm_ms_move_block(host, length); 220 kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
187 host->block_pos += length; 221 local_irq_restore(flags);
188 } 222 }
189 223
190 if ((host->req->data_dir == READ) 224 if (!t_size)
191 && (host->block_pos == host->req->sg.length)) 225 break;
192 return 1; 226 host->block_pos += t_size;
227 length -= t_size;
228 off += t_size;
229 }
193 230
194 writel(ilog2(length) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE); 231 dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length);
195 if (host->req->data_dir == WRITE) 232 if (!length && (host->req->data_dir == WRITE)) {
196 writel((1 << 8) | TIFM_DMA_TX, sock->addr + SOCK_DMA_CONTROL); 233 if (host->io_pos) {
197 else 234 writel(TIFM_MS_SYS_FDIR
198 writel((1 << 8), sock->addr + SOCK_DMA_CONTROL); 235 | readl(sock->addr + SOCK_MS_SYSTEM),
236 sock->addr + SOCK_MS_SYSTEM);
237 writel(host->io_word, sock->addr + SOCK_MS_DATA);
238 }
239 writel(TIFM_MS_SYS_FDIR
240 | readl(sock->addr + SOCK_MS_SYSTEM),
241 sock->addr + SOCK_MS_SYSTEM);
242 writel(0, sock->addr + SOCK_MS_DATA);
243 } else {
244 readl(sock->addr + SOCK_MS_DATA);
245 }
199 246
200 return 0; 247 return length;
201} 248}
202 249
203static int tifm_ms_issue_cmd(struct tifm_ms *host) 250static int tifm_ms_issue_cmd(struct tifm_ms *host)
204{ 251{
205 struct tifm_dev *sock = host->dev; 252 struct tifm_dev *sock = host->dev;
206 unsigned char *data; 253 unsigned char *data;
207 unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0; 254 unsigned int data_len, cmd, sys_param;
208 255
209 host->cmd_flags = 0; 256 host->cmd_flags = 0;
257 host->block_pos = 0;
258 host->io_pos = 0;
259 host->io_word = 0;
260 host->cmd_flags = 0;
210 261
211 if (host->req->long_data) { 262 data = host->req->data;
212 if (!host->no_dma) {
213 if (1 != tifm_map_sg(sock, &host->req->sg, 1,
214 host->req->data_dir == READ
215 ? PCI_DMA_FROMDEVICE
216 : PCI_DMA_TODEVICE)) {
217 host->req->error = -ENOMEM;
218 return host->req->error;
219 }
220 data_len = sg_dma_len(&host->req->sg);
221 } else
222 data_len = host->req->sg.length;
223
224 writel(TIFM_FIFO_INT_SETALL,
225 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
226 writel(TIFM_FIFO_ENABLE,
227 sock->addr + SOCK_FIFO_CONTROL);
228 writel(TIFM_FIFO_INTMASK,
229 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
230 263
231 if (!host->no_dma) { 264 host->use_dma = !no_dma;
232 writel(ilog2(data_len) - 2,
233 sock->addr + SOCK_FIFO_PAGE_SIZE);
234 writel(sg_dma_address(&host->req->sg),
235 sock->addr + SOCK_DMA_ADDRESS);
236 if (host->req->data_dir == WRITE)
237 writel((1 << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
238 sock->addr + SOCK_DMA_CONTROL);
239 else
240 writel((1 << 8) | TIFM_DMA_EN,
241 sock->addr + SOCK_DMA_CONTROL);
242 } else {
243 tifm_ms_transfer_data(host,
244 host->req->data_dir == READ);
245 }
246 265
247 cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM); 266 if (host->req->long_data) {
248 cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY; 267 data_len = host->req->sg.length;
249 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); 268 if (!is_power_of_2(data_len))
269 host->use_dma = 0;
250 } else { 270 } else {
251 data = host->req->data;
252 data_len = host->req->data_len; 271 data_len = host->req->data_len;
272 host->use_dma = 0;
273 }
253 274
254 cmd_mask = host->mode_mask | 0x2607; /* unknown constant */ 275 writel(TIFM_FIFO_INT_SETALL,
255 276 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
256 if (host->req->data_dir == WRITE) { 277 writel(TIFM_FIFO_ENABLE,
257 cmd_mask |= TIFM_MS_SYS_LATCH; 278 sock->addr + SOCK_FIFO_CONTROL);
258 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); 279
259 for (cnt = 0; (data_len - cnt) >= 4; cnt += 4) { 280 if (host->use_dma) {
260 writel(TIFM_MS_SYS_LATCH 281 if (1 != tifm_map_sg(sock, &host->req->sg, 1,
261 | readl(sock->addr + SOCK_MS_SYSTEM), 282 host->req->data_dir == READ
262 sock->addr + SOCK_MS_SYSTEM); 283 ? PCI_DMA_FROMDEVICE
263 __raw_writel(*(unsigned int *)(data + cnt), 284 : PCI_DMA_TODEVICE)) {
264 sock->addr + SOCK_MS_DATA); 285 host->req->error = -ENOMEM;
265 dev_dbg(&sock->dev, "writing %x\n", 286 return host->req->error;
266 *(int *)(data + cnt)); 287 }
267 } 288 data_len = sg_dma_len(&host->req->sg);
268 switch (data_len - cnt) {
269 case 3:
270 tval |= data[cnt + 2] << 16;
271 case 2:
272 tval |= data[cnt + 1] << 8;
273 case 1:
274 tval |= data[cnt];
275 writel(TIFM_MS_SYS_LATCH
276 | readl(sock->addr + SOCK_MS_SYSTEM),
277 sock->addr + SOCK_MS_SYSTEM);
278 writel(tval, sock->addr + SOCK_MS_DATA);
279 dev_dbg(&sock->dev, "writing %x\n", tval);
280 }
281 289
282 writel(TIFM_MS_SYS_LATCH 290 writel(ilog2(data_len) - 2,
283 | readl(sock->addr + SOCK_MS_SYSTEM), 291 sock->addr + SOCK_FIFO_PAGE_SIZE);
284 sock->addr + SOCK_MS_SYSTEM); 292 writel(TIFM_FIFO_INTMASK,
285 writel(0, sock->addr + SOCK_MS_DATA); 293 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
286 dev_dbg(&sock->dev, "writing %x\n", 0); 294 sys_param = TIFM_DMA_EN | (1 << 8);
295 if (host->req->data_dir == WRITE)
296 sys_param |= TIFM_DMA_TX;
287 297
288 } else 298 writel(TIFM_FIFO_INTMASK,
289 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); 299 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
290 300
291 cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM); 301 writel(sg_dma_address(&host->req->sg),
292 cmd_mask &= ~TIFM_MS_SYS_DATA; 302 sock->addr + SOCK_DMA_ADDRESS);
293 cmd_mask |= TIFM_MS_SYS_NOT_RDY; 303 writel(sys_param, sock->addr + SOCK_DMA_CONTROL);
294 dev_dbg(&sock->dev, "mask %x\n", cmd_mask); 304 } else {
295 writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); 305 writel(host->mode_mask | TIFM_MS_SYS_FIFO,
306 sock->addr + SOCK_MS_SYSTEM);
307
308 writel(TIFM_FIFO_MORE,
309 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
296 } 310 }
297 311
298 mod_timer(&host->timer, jiffies + host->timeout_jiffies); 312 mod_timer(&host->timer, jiffies + host->timeout_jiffies);
@@ -300,11 +314,21 @@ static int tifm_ms_issue_cmd(struct tifm_ms *host)
300 sock->addr + SOCK_CONTROL); 314 sock->addr + SOCK_CONTROL);
301 host->req->error = 0; 315 host->req->error = 0;
302 316
317 sys_param = readl(sock->addr + SOCK_MS_SYSTEM);
318 sys_param |= TIFM_MS_SYS_INTCLR;
319
320 if (host->use_dma)
321 sys_param |= TIFM_MS_SYS_DMA;
322 else
323 sys_param &= ~TIFM_MS_SYS_DMA;
324
325 writel(sys_param, sock->addr + SOCK_MS_SYSTEM);
326
303 cmd = (host->req->tpc & 0xf) << 12; 327 cmd = (host->req->tpc & 0xf) << 12;
304 cmd |= data_len; 328 cmd |= data_len;
305 writel(cmd, sock->addr + SOCK_MS_COMMAND); 329 writel(cmd, sock->addr + SOCK_MS_COMMAND);
306 330
307 dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask); 331 dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param);
308 return 0; 332 return 0;
309} 333}
310 334
@@ -312,47 +336,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host)
312{ 336{
313 struct tifm_dev *sock = host->dev; 337 struct tifm_dev *sock = host->dev;
314 struct memstick_host *msh = tifm_get_drvdata(sock); 338 struct memstick_host *msh = tifm_get_drvdata(sock);
315 unsigned int tval = 0, data_len;
316 unsigned char *data;
317 int rc; 339 int rc;
318 340
319 del_timer(&host->timer); 341 del_timer(&host->timer);
320 if (host->req->long_data) {
321 if (!host->no_dma)
322 tifm_unmap_sg(sock, &host->req->sg, 1,
323 host->req->data_dir == READ
324 ? PCI_DMA_FROMDEVICE
325 : PCI_DMA_TODEVICE);
326 } else {
327 writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM),
328 sock->addr + SOCK_MS_SYSTEM);
329
330 data = host->req->data;
331 data_len = host->req->data_len;
332 342
333 if (host->req->data_dir == READ) { 343 if (host->use_dma)
334 for (rc = 0; (data_len - rc) >= 4; rc += 4) 344 tifm_unmap_sg(sock, &host->req->sg, 1,
335 *(int *)(data + rc) 345 host->req->data_dir == READ
336 = __raw_readl(sock->addr 346 ? PCI_DMA_FROMDEVICE
337 + SOCK_MS_DATA); 347 : PCI_DMA_TODEVICE);
338
339 if (data_len - rc)
340 tval = readl(sock->addr + SOCK_MS_DATA);
341 switch (data_len - rc) {
342 case 3:
343 data[rc + 2] = (tval >> 16) & 0xff;
344 case 2:
345 data[rc + 1] = (tval >> 8) & 0xff;
346 case 1:
347 data[rc] = tval & 0xff;
348 }
349 readl(sock->addr + SOCK_MS_DATA);
350 }
351 }
352 348
353 writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), 349 writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
354 sock->addr + SOCK_CONTROL); 350 sock->addr + SOCK_CONTROL);
355 351
352 dev_dbg(&sock->dev, "TPC complete\n");
356 do { 353 do {
357 rc = memstick_next_req(msh, &host->req); 354 rc = memstick_next_req(msh, &host->req);
358 } while (!rc && tifm_ms_issue_cmd(host)); 355 } while (!rc && tifm_ms_issue_cmd(host));
@@ -363,11 +360,10 @@ static int tifm_ms_check_status(struct tifm_ms *host)
363 if (!host->req->error) { 360 if (!host->req->error) {
364 if (!(host->cmd_flags & CMD_READY)) 361 if (!(host->cmd_flags & CMD_READY))
365 return 1; 362 return 1;
366 if (host->req->long_data 363 if (!(host->cmd_flags & FIFO_READY))
367 && !(host->cmd_flags & FIFO_READY))
368 return 1; 364 return 1;
369 if (host->req->need_card_int 365 if (host->req->need_card_int
370 && !(host->cmd_flags & CARD_READY)) 366 && !(host->cmd_flags & CARD_INT))
371 return 1; 367 return 1;
372 } 368 }
373 return 0; 369 return 0;
@@ -377,18 +373,24 @@ static int tifm_ms_check_status(struct tifm_ms *host)
377static void tifm_ms_data_event(struct tifm_dev *sock) 373static void tifm_ms_data_event(struct tifm_dev *sock)
378{ 374{
379 struct tifm_ms *host; 375 struct tifm_ms *host;
380 unsigned int fifo_status = 0; 376 unsigned int fifo_status = 0, host_status = 0;
381 int rc = 1; 377 int rc = 1;
382 378
383 spin_lock(&sock->lock); 379 spin_lock(&sock->lock);
384 host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock)); 380 host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
385 fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); 381 fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
386 dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n", 382 host_status = readl(sock->addr + SOCK_MS_STATUS);
387 fifo_status, host->cmd_flags); 383 dev_dbg(&sock->dev,
384 "data event: fifo_status %x, host_status %x, flags %x\n",
385 fifo_status, host_status, host->cmd_flags);
388 386
389 if (host->req) { 387 if (host->req) {
390 if (fifo_status & TIFM_FIFO_READY) { 388 if (host->use_dma && (fifo_status & 1)) {
391 if (!host->no_dma || tifm_ms_transfer_data(host, 0)) { 389 host->cmd_flags |= FIFO_READY;
390 rc = tifm_ms_check_status(host);
391 }
392 if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) {
393 if (!tifm_ms_transfer_data(host)) {
392 host->cmd_flags |= FIFO_READY; 394 host->cmd_flags |= FIFO_READY;
393 rc = tifm_ms_check_status(host); 395 rc = tifm_ms_check_status(host);
394 } 396 }
@@ -417,9 +419,9 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
417 host_status, host->cmd_flags); 419 host_status, host->cmd_flags);
418 420
419 if (host->req) { 421 if (host->req) {
420 if (host_status & TIFM_MS_TIMEOUT) 422 if (host_status & TIFM_MS_STAT_TOE)
421 host->req->error = -ETIME; 423 host->req->error = -ETIME;
422 else if (host_status & TIFM_MS_BADCRC) 424 else if (host_status & TIFM_MS_STAT_CRC)
423 host->req->error = -EILSEQ; 425 host->req->error = -EILSEQ;
424 426
425 if (host->req->error) { 427 if (host->req->error) {
@@ -428,18 +430,17 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
428 writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); 430 writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
429 } 431 }
430 432
431 if (host_status & TIFM_MS_EOTPC) 433 if (host_status & TIFM_MS_STAT_RDY)
432 host->cmd_flags |= CMD_READY; 434 host->cmd_flags |= CMD_READY;
433 if (host_status & TIFM_MS_INT) 435
434 host->cmd_flags |= CARD_READY; 436 if (host_status & TIFM_MS_STAT_MSINT)
437 host->cmd_flags |= CARD_INT;
435 438
436 rc = tifm_ms_check_status(host); 439 rc = tifm_ms_check_status(host);
437 440
438 } 441 }
439 442
440 writel(TIFM_MS_SYS_NOT_RDY | readl(sock->addr + SOCK_MS_SYSTEM), 443 writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM),
441 sock->addr + SOCK_MS_SYSTEM);
442 writel((~TIFM_MS_SYS_DATA) & readl(sock->addr + SOCK_MS_SYSTEM),
443 sock->addr + SOCK_MS_SYSTEM); 444 sock->addr + SOCK_MS_SYSTEM);
444 445
445 if (!rc) 446 if (!rc)
@@ -499,7 +500,7 @@ static void tifm_ms_set_param(struct memstick_host *msh,
499 break; 500 break;
500 case MEMSTICK_INTERFACE: 501 case MEMSTICK_INTERFACE:
501 if (value == MEMSTICK_SERIAL) { 502 if (value == MEMSTICK_SERIAL) {
502 host->mode_mask = TIFM_MS_SERIAL; 503 host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
503 writel((~TIFM_CTRL_FAST_CLK) 504 writel((~TIFM_CTRL_FAST_CLK)
504 & readl(sock->addr + SOCK_CONTROL), 505 & readl(sock->addr + SOCK_CONTROL),
505 sock->addr + SOCK_CONTROL); 506 sock->addr + SOCK_CONTROL);
@@ -535,9 +536,10 @@ static int tifm_ms_initialize_host(struct tifm_ms *host)
535 struct tifm_dev *sock = host->dev; 536 struct tifm_dev *sock = host->dev;
536 struct memstick_host *msh = tifm_get_drvdata(sock); 537 struct memstick_host *msh = tifm_get_drvdata(sock);
537 538
538 host->mode_mask = TIFM_MS_SERIAL; 539 host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
539 writel(0x8000, sock->addr + SOCK_MS_SYSTEM); 540 writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM);
540 writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM); 541 writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
542 sock->addr + SOCK_MS_SYSTEM);
541 writel(0xffffffff, sock->addr + SOCK_MS_STATUS); 543 writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
542 if (tifm_has_ms_pif(sock)) 544 if (tifm_has_ms_pif(sock))
543 msh->caps |= MEMSTICK_CAP_PAR4; 545 msh->caps |= MEMSTICK_CAP_PAR4;
@@ -566,7 +568,6 @@ static int tifm_ms_probe(struct tifm_dev *sock)
566 tifm_set_drvdata(sock, msh); 568 tifm_set_drvdata(sock, msh);
567 host->dev = sock; 569 host->dev = sock;
568 host->timeout_jiffies = msecs_to_jiffies(1000); 570 host->timeout_jiffies = msecs_to_jiffies(1000);
569 host->no_dma = no_dma;
570 571
571 setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); 572 setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
572 573
@@ -599,7 +600,7 @@ static void tifm_ms_remove(struct tifm_dev *sock)
599 writel(TIFM_FIFO_INT_SETALL, 600 writel(TIFM_FIFO_INT_SETALL,
600 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); 601 sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
601 writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); 602 writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
602 if (host->req->long_data && !host->no_dma) 603 if (host->use_dma)
603 tifm_unmap_sg(sock, &host->req->sg, 1, 604 tifm_unmap_sg(sock, &host->req->sg, 1,
604 host->req->data_dir == READ 605 host->req->data_dir == READ
605 ? PCI_DMA_TODEVICE 606 ? PCI_DMA_TODEVICE
@@ -616,7 +617,8 @@ static void tifm_ms_remove(struct tifm_dev *sock)
616 617
617 memstick_remove_host(msh); 618 memstick_remove_host(msh);
618 619
619 writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM); 620 writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
621 sock->addr + SOCK_MS_SYSTEM);
620 writel(0xffffffff, sock->addr + SOCK_MS_STATUS); 622 writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
621 623
622 memstick_free_host(msh); 624 memstick_free_host(msh);
diff --git a/include/linux/tifm.h b/include/linux/tifm.h
index da76ed85f595..848c0f392541 100644
--- a/include/linux/tifm.h
+++ b/include/linux/tifm.h
@@ -70,9 +70,9 @@ enum {
70 70
71#define TIFM_FIFO_ENABLE 0x00000001 71#define TIFM_FIFO_ENABLE 0x00000001
72#define TIFM_FIFO_READY 0x00000001 72#define TIFM_FIFO_READY 0x00000001
73#define TIFM_FIFO_MORE 0x00000008
73#define TIFM_FIFO_INT_SETALL 0x0000ffff 74#define TIFM_FIFO_INT_SETALL 0x0000ffff
74#define TIFM_FIFO_INTMASK 0x00000005 75#define TIFM_FIFO_INTMASK 0x00000005
75#define TIFM_FIFO_SIZE 0x00000200
76 76
77#define TIFM_DMA_RESET 0x00000002 77#define TIFM_DMA_RESET 0x00000002
78#define TIFM_DMA_TX 0x00008000 78#define TIFM_DMA_TX 0x00008000