Commit 92b22d935fed1e4d88b9b6f9a674ab2a4272ee78

Authored by Alex Dubov
Committed by Linus Torvalds
1 parent 2a4f2568c2

tifm: fix the MemoryStick host fifo handling code

Additional input received from JMicron on MemoryStick host interfaces showed
that some assumtions in fifo handling code were incorrect.  This patch also
fixes data corruption used to occure during PIO transfers.

Signed-off-by: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 264 additions and 262 deletions Side-by-side Diff

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