~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/memstick/host/jmb38x_ms.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  jmb38x_ms.c - JMicron jmb38x MemoryStick card reader
 
3
 *
 
4
 *  Copyright (C) 2008 Alex Dubov <oakad@yahoo.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License version 2 as
 
8
 * published by the Free Software Foundation.
 
9
 *
 
10
 */
 
11
 
 
12
#include <linux/spinlock.h>
 
13
#include <linux/interrupt.h>
 
14
#include <linux/pci.h>
 
15
#include <linux/dma-mapping.h>
 
16
#include <linux/delay.h>
 
17
#include <linux/highmem.h>
 
18
#include <linux/memstick.h>
 
19
#include <linux/slab.h>
 
20
#include <linux/module.h>
 
21
 
 
22
#define DRIVER_NAME "jmb38x_ms"
 
23
 
 
24
static int no_dma;
 
25
module_param(no_dma, bool, 0644);
 
26
 
 
27
enum {
 
28
        DMA_ADDRESS       = 0x00,
 
29
        BLOCK             = 0x04,
 
30
        DMA_CONTROL       = 0x08,
 
31
        TPC_P0            = 0x0c,
 
32
        TPC_P1            = 0x10,
 
33
        TPC               = 0x14,
 
34
        HOST_CONTROL      = 0x18,
 
35
        DATA              = 0x1c,
 
36
        STATUS            = 0x20,
 
37
        INT_STATUS        = 0x24,
 
38
        INT_STATUS_ENABLE = 0x28,
 
39
        INT_SIGNAL_ENABLE = 0x2c,
 
40
        TIMER             = 0x30,
 
41
        TIMER_CONTROL     = 0x34,
 
42
        PAD_OUTPUT_ENABLE = 0x38,
 
43
        PAD_PU_PD         = 0x3c,
 
44
        CLOCK_DELAY       = 0x40,
 
45
        ADMA_ADDRESS      = 0x44,
 
46
        CLOCK_CONTROL     = 0x48,
 
47
        LED_CONTROL       = 0x4c,
 
48
        VERSION           = 0x50
 
49
};
 
50
 
 
51
struct jmb38x_ms_host {
 
52
        struct jmb38x_ms        *chip;
 
53
        void __iomem            *addr;
 
54
        spinlock_t              lock;
 
55
        struct tasklet_struct   notify;
 
56
        int                     id;
 
57
        char                    host_id[32];
 
58
        int                     irq;
 
59
        unsigned int            block_pos;
 
60
        unsigned long           timeout_jiffies;
 
61
        struct timer_list       timer;
 
62
        struct memstick_request *req;
 
63
        unsigned char           cmd_flags;
 
64
        unsigned char           io_pos;
 
65
        unsigned char           ifmode;
 
66
        unsigned int            io_word[2];
 
67
};
 
68
 
 
69
struct jmb38x_ms {
 
70
        struct pci_dev        *pdev;
 
71
        int                   host_cnt;
 
72
        struct memstick_host  *hosts[];
 
73
};
 
74
 
 
75
#define BLOCK_COUNT_MASK       0xffff0000
 
76
#define BLOCK_SIZE_MASK        0x00000fff
 
77
 
 
78
#define DMA_CONTROL_ENABLE     0x00000001
 
79
 
 
80
#define TPC_DATA_SEL           0x00008000
 
81
#define TPC_DIR                0x00004000
 
82
#define TPC_WAIT_INT           0x00002000
 
83
#define TPC_GET_INT            0x00000800
 
84
#define TPC_CODE_SZ_MASK       0x00000700
 
85
#define TPC_DATA_SZ_MASK       0x00000007
 
86
 
 
87
#define HOST_CONTROL_TDELAY_EN 0x00040000
 
88
#define HOST_CONTROL_HW_OC_P   0x00010000
 
89
#define HOST_CONTROL_RESET_REQ 0x00008000
 
90
#define HOST_CONTROL_REI       0x00004000
 
91
#define HOST_CONTROL_LED       0x00000400
 
92
#define HOST_CONTROL_FAST_CLK  0x00000200
 
93
#define HOST_CONTROL_RESET     0x00000100
 
94
#define HOST_CONTROL_POWER_EN  0x00000080
 
95
#define HOST_CONTROL_CLOCK_EN  0x00000040
 
96
#define HOST_CONTROL_REO       0x00000008
 
97
#define HOST_CONTROL_IF_SHIFT  4
 
98
 
 
99
#define HOST_CONTROL_IF_SERIAL 0x0
 
100
#define HOST_CONTROL_IF_PAR4   0x1
 
101
#define HOST_CONTROL_IF_PAR8   0x3
 
102
 
 
103
#define STATUS_BUSY             0x00080000
 
104
#define STATUS_MS_DAT7          0x00040000
 
105
#define STATUS_MS_DAT6          0x00020000
 
106
#define STATUS_MS_DAT5          0x00010000
 
107
#define STATUS_MS_DAT4          0x00008000
 
108
#define STATUS_MS_DAT3          0x00004000
 
109
#define STATUS_MS_DAT2          0x00002000
 
110
#define STATUS_MS_DAT1          0x00001000
 
111
#define STATUS_MS_DAT0          0x00000800
 
112
#define STATUS_HAS_MEDIA        0x00000400
 
113
#define STATUS_FIFO_EMPTY       0x00000200
 
114
#define STATUS_FIFO_FULL        0x00000100
 
115
#define STATUS_MS_CED           0x00000080
 
116
#define STATUS_MS_ERR           0x00000040
 
117
#define STATUS_MS_BRQ           0x00000020
 
118
#define STATUS_MS_CNK           0x00000001
 
119
 
 
120
#define INT_STATUS_TPC_ERR      0x00080000
 
121
#define INT_STATUS_CRC_ERR      0x00040000
 
122
#define INT_STATUS_TIMER_TO     0x00020000
 
123
#define INT_STATUS_HSK_TO       0x00010000
 
124
#define INT_STATUS_ANY_ERR      0x00008000
 
125
#define INT_STATUS_FIFO_WRDY    0x00000080
 
126
#define INT_STATUS_FIFO_RRDY    0x00000040
 
127
#define INT_STATUS_MEDIA_OUT    0x00000010
 
128
#define INT_STATUS_MEDIA_IN     0x00000008
 
129
#define INT_STATUS_DMA_BOUNDARY 0x00000004
 
130
#define INT_STATUS_EOTRAN       0x00000002
 
131
#define INT_STATUS_EOTPC        0x00000001
 
132
 
 
133
#define INT_STATUS_ALL          0x000f801f
 
134
 
 
135
#define PAD_OUTPUT_ENABLE_MS  0x0F3F
 
136
 
 
137
#define PAD_PU_PD_OFF         0x7FFF0000
 
138
#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
 
139
#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
 
140
 
 
141
#define CLOCK_CONTROL_BY_MMIO 0x00000008
 
142
#define CLOCK_CONTROL_40MHZ   0x00000001
 
143
#define CLOCK_CONTROL_50MHZ   0x00000002
 
144
#define CLOCK_CONTROL_60MHZ   0x00000010
 
145
#define CLOCK_CONTROL_62_5MHZ 0x00000004
 
146
#define CLOCK_CONTROL_OFF     0x00000000
 
147
 
 
148
#define PCI_CTL_CLOCK_DLY_ADDR   0x000000b0
 
149
 
 
150
enum {
 
151
        CMD_READY    = 0x01,
 
152
        FIFO_READY   = 0x02,
 
153
        REG_DATA     = 0x04,
 
154
        DMA_DATA     = 0x08
 
155
};
 
156
 
 
157
static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,
 
158
                                        unsigned char *buf, unsigned int length)
 
159
{
 
160
        unsigned int off = 0;
 
161
 
 
162
        while (host->io_pos && length) {
 
163
                buf[off++] = host->io_word[0] & 0xff;
 
164
                host->io_word[0] >>= 8;
 
165
                length--;
 
166
                host->io_pos--;
 
167
        }
 
168
 
 
169
        if (!length)
 
170
                return off;
 
171
 
 
172
        while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
 
173
                if (length < 4)
 
174
                        break;
 
175
                *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);
 
176
                length -= 4;
 
177
                off += 4;
 
178
        }
 
179
 
 
180
        if (length
 
181
            && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
 
182
                host->io_word[0] = readl(host->addr + DATA);
 
183
                for (host->io_pos = 4; host->io_pos; --host->io_pos) {
 
184
                        buf[off++] = host->io_word[0] & 0xff;
 
185
                        host->io_word[0] >>= 8;
 
186
                        length--;
 
187
                        if (!length)
 
188
                                break;
 
189
                }
 
190
        }
 
191
 
 
192
        return off;
 
193
}
 
194
 
 
195
static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host,
 
196
                                            unsigned char *buf,
 
197
                                            unsigned int length)
 
198
{
 
199
        unsigned int off = 0;
 
200
 
 
201
        while (host->io_pos > 4 && length) {
 
202
                buf[off++] = host->io_word[0] & 0xff;
 
203
                host->io_word[0] >>= 8;
 
204
                length--;
 
205
                host->io_pos--;
 
206
        }
 
207
 
 
208
        if (!length)
 
209
                return off;
 
210
 
 
211
        while (host->io_pos && length) {
 
212
                buf[off++] = host->io_word[1] & 0xff;
 
213
                host->io_word[1] >>= 8;
 
214
                length--;
 
215
                host->io_pos--;
 
216
        }
 
217
 
 
218
        return off;
 
219
}
 
220
 
 
221
static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host,
 
222
                                         unsigned char *buf,
 
223
                                         unsigned int length)
 
224
{
 
225
        unsigned int off = 0;
 
226
 
 
227
        if (host->io_pos) {
 
228
                while (host->io_pos < 4 && length) {
 
229
                        host->io_word[0] |=  buf[off++] << (host->io_pos * 8);
 
230
                        host->io_pos++;
 
231
                        length--;
 
232
                }
 
233
        }
 
234
 
 
235
        if (host->io_pos == 4
 
236
            && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
 
237
                writel(host->io_word[0], host->addr + DATA);
 
238
                host->io_pos = 0;
 
239
                host->io_word[0] = 0;
 
240
        } else if (host->io_pos) {
 
241
                return off;
 
242
        }
 
243
 
 
244
        if (!length)
 
245
                return off;
 
246
 
 
247
        while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
 
248
                if (length < 4)
 
249
                        break;
 
250
 
 
251
                __raw_writel(*(unsigned int *)(buf + off),
 
252
                             host->addr + DATA);
 
253
                length -= 4;
 
254
                off += 4;
 
255
        }
 
256
 
 
257
        switch (length) {
 
258
        case 3:
 
259
                host->io_word[0] |= buf[off + 2] << 16;
 
260
                host->io_pos++;
 
261
        case 2:
 
262
                host->io_word[0] |= buf[off + 1] << 8;
 
263
                host->io_pos++;
 
264
        case 1:
 
265
                host->io_word[0] |= buf[off];
 
266
                host->io_pos++;
 
267
        }
 
268
 
 
269
        off += host->io_pos;
 
270
 
 
271
        return off;
 
272
}
 
273
 
 
274
static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host,
 
275
                                             unsigned char *buf,
 
276
                                             unsigned int length)
 
277
{
 
278
        unsigned int off = 0;
 
279
 
 
280
        while (host->io_pos < 4 && length) {
 
281
                host->io_word[0] &= ~(0xff << (host->io_pos * 8));
 
282
                host->io_word[0] |=  buf[off++] << (host->io_pos * 8);
 
283
                host->io_pos++;
 
284
                length--;
 
285
        }
 
286
 
 
287
        if (!length)
 
288
                return off;
 
289
 
 
290
        while (host->io_pos < 8 && length) {
 
291
                host->io_word[1] &= ~(0xff << (host->io_pos * 8));
 
292
                host->io_word[1] |=  buf[off++] << (host->io_pos * 8);
 
293
                host->io_pos++;
 
294
                length--;
 
295
        }
 
296
 
 
297
        return off;
 
298
}
 
299
 
 
300
static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
 
301
{
 
302
        unsigned int length;
 
303
        unsigned int off;
 
304
        unsigned int t_size, p_cnt;
 
305
        unsigned char *buf;
 
306
        struct page *pg;
 
307
        unsigned long flags = 0;
 
308
 
 
309
        if (host->req->long_data) {
 
310
                length = host->req->sg.length - host->block_pos;
 
311
                off = host->req->sg.offset + host->block_pos;
 
312
        } else {
 
313
                length = host->req->data_len - host->block_pos;
 
314
                off = 0;
 
315
        }
 
316
 
 
317
        while (length) {
 
318
                unsigned int uninitialized_var(p_off);
 
319
 
 
320
                if (host->req->long_data) {
 
321
                        pg = nth_page(sg_page(&host->req->sg),
 
322
                                      off >> PAGE_SHIFT);
 
323
                        p_off = offset_in_page(off);
 
324
                        p_cnt = PAGE_SIZE - p_off;
 
325
                        p_cnt = min(p_cnt, length);
 
326
 
 
327
                        local_irq_save(flags);
 
328
                        buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
 
329
                } else {
 
330
                        buf = host->req->data + host->block_pos;
 
331
                        p_cnt = host->req->data_len - host->block_pos;
 
332
                }
 
333
 
 
334
                if (host->req->data_dir == WRITE)
 
335
                        t_size = !(host->cmd_flags & REG_DATA)
 
336
                                 ? jmb38x_ms_write_data(host, buf, p_cnt)
 
337
                                 : jmb38x_ms_write_reg_data(host, buf, p_cnt);
 
338
                else
 
339
                        t_size = !(host->cmd_flags & REG_DATA)
 
340
                                 ? jmb38x_ms_read_data(host, buf, p_cnt)
 
341
                                 : jmb38x_ms_read_reg_data(host, buf, p_cnt);
 
342
 
 
343
                if (host->req->long_data) {
 
344
                        kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
 
345
                        local_irq_restore(flags);
 
346
                }
 
347
 
 
348
                if (!t_size)
 
349
                        break;
 
350
                host->block_pos += t_size;
 
351
                length -= t_size;
 
352
                off += t_size;
 
353
        }
 
354
 
 
355
        if (!length && host->req->data_dir == WRITE) {
 
356
                if (host->cmd_flags & REG_DATA) {
 
357
                        writel(host->io_word[0], host->addr + TPC_P0);
 
358
                        writel(host->io_word[1], host->addr + TPC_P1);
 
359
                } else if (host->io_pos) {
 
360
                        writel(host->io_word[0], host->addr + DATA);
 
361
                }
 
362
        }
 
363
 
 
364
        return length;
 
365
}
 
366
 
 
367
static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
 
368
{
 
369
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
370
        unsigned char *data;
 
371
        unsigned int data_len, cmd, t_val;
 
372
 
 
373
        if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
 
374
                dev_dbg(&msh->dev, "no media status\n");
 
375
                host->req->error = -ETIME;
 
376
                return host->req->error;
 
377
        }
 
378
 
 
379
        dev_dbg(&msh->dev, "control %08x\n", readl(host->addr + HOST_CONTROL));
 
380
        dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS));
 
381
        dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS));
 
382
 
 
383
        host->cmd_flags = 0;
 
384
        host->block_pos = 0;
 
385
        host->io_pos = 0;
 
386
        host->io_word[0] = 0;
 
387
        host->io_word[1] = 0;
 
388
 
 
389
        cmd = host->req->tpc << 16;
 
390
        cmd |= TPC_DATA_SEL;
 
391
 
 
392
        if (host->req->data_dir == READ)
 
393
                cmd |= TPC_DIR;
 
394
 
 
395
        if (host->req->need_card_int) {
 
396
                if (host->ifmode == MEMSTICK_SERIAL)
 
397
                        cmd |= TPC_GET_INT;
 
398
                else
 
399
                        cmd |= TPC_WAIT_INT;
 
400
        }
 
401
 
 
402
        data = host->req->data;
 
403
 
 
404
        if (!no_dma)
 
405
                host->cmd_flags |= DMA_DATA;
 
406
 
 
407
        if (host->req->long_data) {
 
408
                data_len = host->req->sg.length;
 
409
        } else {
 
410
                data_len = host->req->data_len;
 
411
                host->cmd_flags &= ~DMA_DATA;
 
412
        }
 
413
 
 
414
        if (data_len <= 8) {
 
415
                cmd &= ~(TPC_DATA_SEL | 0xf);
 
416
                host->cmd_flags |= REG_DATA;
 
417
                cmd |= data_len & 0xf;
 
418
                host->cmd_flags &= ~DMA_DATA;
 
419
        }
 
420
 
 
421
        if (host->cmd_flags & DMA_DATA) {
 
422
                if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
 
423
                                    host->req->data_dir == READ
 
424
                                    ? PCI_DMA_FROMDEVICE
 
425
                                    : PCI_DMA_TODEVICE)) {
 
426
                        host->req->error = -ENOMEM;
 
427
                        return host->req->error;
 
428
                }
 
429
                data_len = sg_dma_len(&host->req->sg);
 
430
                writel(sg_dma_address(&host->req->sg),
 
431
                       host->addr + DMA_ADDRESS);
 
432
                writel(((1 << 16) & BLOCK_COUNT_MASK)
 
433
                       | (data_len & BLOCK_SIZE_MASK),
 
434
                       host->addr + BLOCK);
 
435
                writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);
 
436
        } else if (!(host->cmd_flags & REG_DATA)) {
 
437
                writel(((1 << 16) & BLOCK_COUNT_MASK)
 
438
                       | (data_len & BLOCK_SIZE_MASK),
 
439
                       host->addr + BLOCK);
 
440
                        t_val = readl(host->addr + INT_STATUS_ENABLE);
 
441
                        t_val |= host->req->data_dir == READ
 
442
                                 ? INT_STATUS_FIFO_RRDY
 
443
                                 : INT_STATUS_FIFO_WRDY;
 
444
 
 
445
                        writel(t_val, host->addr + INT_STATUS_ENABLE);
 
446
                        writel(t_val, host->addr + INT_SIGNAL_ENABLE);
 
447
        } else {
 
448
                cmd &= ~(TPC_DATA_SEL | 0xf);
 
449
                host->cmd_flags |= REG_DATA;
 
450
                cmd |= data_len & 0xf;
 
451
 
 
452
                if (host->req->data_dir == WRITE) {
 
453
                        jmb38x_ms_transfer_data(host);
 
454
                        writel(host->io_word[0], host->addr + TPC_P0);
 
455
                        writel(host->io_word[1], host->addr + TPC_P1);
 
456
                }
 
457
        }
 
458
 
 
459
        mod_timer(&host->timer, jiffies + host->timeout_jiffies);
 
460
        writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),
 
461
               host->addr + HOST_CONTROL);
 
462
        host->req->error = 0;
 
463
 
 
464
        writel(cmd, host->addr + TPC);
 
465
        dev_dbg(&msh->dev, "executing TPC %08x, len %x\n", cmd, data_len);
 
466
 
 
467
        return 0;
 
468
}
 
469
 
 
470
static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
 
471
{
 
472
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
473
        unsigned int t_val = 0;
 
474
        int rc;
 
475
 
 
476
        del_timer(&host->timer);
 
477
 
 
478
        dev_dbg(&msh->dev, "c control %08x\n",
 
479
                readl(host->addr + HOST_CONTROL));
 
480
        dev_dbg(&msh->dev, "c status %08x\n",
 
481
                readl(host->addr + INT_STATUS));
 
482
        dev_dbg(&msh->dev, "c hstatus %08x\n", readl(host->addr + STATUS));
 
483
 
 
484
        host->req->int_reg = readl(host->addr + STATUS) & 0xff;
 
485
 
 
486
        writel(0, host->addr + BLOCK);
 
487
        writel(0, host->addr + DMA_CONTROL);
 
488
 
 
489
        if (host->cmd_flags & DMA_DATA) {
 
490
                pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
 
491
                             host->req->data_dir == READ
 
492
                             ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
 
493
        } else {
 
494
                t_val = readl(host->addr + INT_STATUS_ENABLE);
 
495
                if (host->req->data_dir == READ)
 
496
                        t_val &= ~INT_STATUS_FIFO_RRDY;
 
497
                else
 
498
                        t_val &= ~INT_STATUS_FIFO_WRDY;
 
499
 
 
500
                writel(t_val, host->addr + INT_STATUS_ENABLE);
 
501
                writel(t_val, host->addr + INT_SIGNAL_ENABLE);
 
502
        }
 
503
 
 
504
        writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),
 
505
               host->addr + HOST_CONTROL);
 
506
 
 
507
        if (!last) {
 
508
                do {
 
509
                        rc = memstick_next_req(msh, &host->req);
 
510
                } while (!rc && jmb38x_ms_issue_cmd(msh));
 
511
        } else {
 
512
                do {
 
513
                        rc = memstick_next_req(msh, &host->req);
 
514
                        if (!rc)
 
515
                                host->req->error = -ETIME;
 
516
                } while (!rc);
 
517
        }
 
518
}
 
519
 
 
520
static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)
 
521
{
 
522
        struct memstick_host *msh = dev_id;
 
523
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
524
        unsigned int irq_status;
 
525
 
 
526
        spin_lock(&host->lock);
 
527
        irq_status = readl(host->addr + INT_STATUS);
 
528
        dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status);
 
529
        if (irq_status == 0 || irq_status == (~0)) {
 
530
                spin_unlock(&host->lock);
 
531
                return IRQ_NONE;
 
532
        }
 
533
 
 
534
        if (host->req) {
 
535
                if (irq_status & INT_STATUS_ANY_ERR) {
 
536
                        if (irq_status & INT_STATUS_CRC_ERR)
 
537
                                host->req->error = -EILSEQ;
 
538
                        else if (irq_status & INT_STATUS_TPC_ERR) {
 
539
                                dev_dbg(&host->chip->pdev->dev, "TPC_ERR\n");
 
540
                                jmb38x_ms_complete_cmd(msh, 0);
 
541
                        } else
 
542
                                host->req->error = -ETIME;
 
543
                } else {
 
544
                        if (host->cmd_flags & DMA_DATA) {
 
545
                                if (irq_status & INT_STATUS_EOTRAN)
 
546
                                        host->cmd_flags |= FIFO_READY;
 
547
                        } else {
 
548
                                if (irq_status & (INT_STATUS_FIFO_RRDY
 
549
                                                  | INT_STATUS_FIFO_WRDY))
 
550
                                        jmb38x_ms_transfer_data(host);
 
551
 
 
552
                                if (irq_status & INT_STATUS_EOTRAN) {
 
553
                                        jmb38x_ms_transfer_data(host);
 
554
                                        host->cmd_flags |= FIFO_READY;
 
555
                                }
 
556
                        }
 
557
 
 
558
                        if (irq_status & INT_STATUS_EOTPC) {
 
559
                                host->cmd_flags |= CMD_READY;
 
560
                                if (host->cmd_flags & REG_DATA) {
 
561
                                        if (host->req->data_dir == READ) {
 
562
                                                host->io_word[0]
 
563
                                                        = readl(host->addr
 
564
                                                                + TPC_P0);
 
565
                                                host->io_word[1]
 
566
                                                        = readl(host->addr
 
567
                                                                + TPC_P1);
 
568
                                                host->io_pos = 8;
 
569
 
 
570
                                                jmb38x_ms_transfer_data(host);
 
571
                                        }
 
572
                                        host->cmd_flags |= FIFO_READY;
 
573
                                }
 
574
                        }
 
575
                }
 
576
        }
 
577
 
 
578
        if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) {
 
579
                dev_dbg(&host->chip->pdev->dev, "media changed\n");
 
580
                memstick_detect_change(msh);
 
581
        }
 
582
 
 
583
        writel(irq_status, host->addr + INT_STATUS);
 
584
 
 
585
        if (host->req
 
586
            && (((host->cmd_flags & CMD_READY)
 
587
                 && (host->cmd_flags & FIFO_READY))
 
588
                || host->req->error))
 
589
                jmb38x_ms_complete_cmd(msh, 0);
 
590
 
 
591
        spin_unlock(&host->lock);
 
592
        return IRQ_HANDLED;
 
593
}
 
594
 
 
595
static void jmb38x_ms_abort(unsigned long data)
 
596
{
 
597
        struct memstick_host *msh = (struct memstick_host *)data;
 
598
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
599
        unsigned long flags;
 
600
 
 
601
        dev_dbg(&host->chip->pdev->dev, "abort\n");
 
602
        spin_lock_irqsave(&host->lock, flags);
 
603
        if (host->req) {
 
604
                host->req->error = -ETIME;
 
605
                jmb38x_ms_complete_cmd(msh, 0);
 
606
        }
 
607
        spin_unlock_irqrestore(&host->lock, flags);
 
608
}
 
609
 
 
610
static void jmb38x_ms_req_tasklet(unsigned long data)
 
611
{
 
612
        struct memstick_host *msh = (struct memstick_host *)data;
 
613
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
614
        unsigned long flags;
 
615
        int rc;
 
616
 
 
617
        spin_lock_irqsave(&host->lock, flags);
 
618
        if (!host->req) {
 
619
                do {
 
620
                        rc = memstick_next_req(msh, &host->req);
 
621
                        dev_dbg(&host->chip->pdev->dev, "tasklet req %d\n", rc);
 
622
                } while (!rc && jmb38x_ms_issue_cmd(msh));
 
623
        }
 
624
        spin_unlock_irqrestore(&host->lock, flags);
 
625
}
 
626
 
 
627
static void jmb38x_ms_dummy_submit(struct memstick_host *msh)
 
628
{
 
629
        return;
 
630
}
 
631
 
 
632
static void jmb38x_ms_submit_req(struct memstick_host *msh)
 
633
{
 
634
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
635
 
 
636
        tasklet_schedule(&host->notify);
 
637
}
 
638
 
 
639
static int jmb38x_ms_reset(struct jmb38x_ms_host *host)
 
640
{
 
641
        int cnt;
 
642
 
 
643
        writel(HOST_CONTROL_RESET_REQ | HOST_CONTROL_CLOCK_EN
 
644
               | readl(host->addr + HOST_CONTROL),
 
645
               host->addr + HOST_CONTROL);
 
646
        mmiowb();
 
647
 
 
648
        for (cnt = 0; cnt < 20; ++cnt) {
 
649
                if (!(HOST_CONTROL_RESET_REQ
 
650
                      & readl(host->addr + HOST_CONTROL)))
 
651
                        goto reset_next;
 
652
 
 
653
                ndelay(20);
 
654
        }
 
655
        dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n");
 
656
 
 
657
reset_next:
 
658
        writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN
 
659
               | readl(host->addr + HOST_CONTROL),
 
660
               host->addr + HOST_CONTROL);
 
661
        mmiowb();
 
662
 
 
663
        for (cnt = 0; cnt < 20; ++cnt) {
 
664
                if (!(HOST_CONTROL_RESET
 
665
                      & readl(host->addr + HOST_CONTROL)))
 
666
                        goto reset_ok;
 
667
 
 
668
                ndelay(20);
 
669
        }
 
670
        dev_dbg(&host->chip->pdev->dev, "reset timeout\n");
 
671
        return -EIO;
 
672
 
 
673
reset_ok:
 
674
        mmiowb();
 
675
        writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
 
676
        writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
 
677
        return 0;
 
678
}
 
679
 
 
680
static int jmb38x_ms_set_param(struct memstick_host *msh,
 
681
                               enum memstick_param param,
 
682
                               int value)
 
683
{
 
684
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
685
        unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
 
686
        unsigned int clock_ctl = CLOCK_CONTROL_BY_MMIO, clock_delay = 0;
 
687
        int rc = 0;
 
688
 
 
689
        switch (param) {
 
690
        case MEMSTICK_POWER:
 
691
                if (value == MEMSTICK_POWER_ON) {
 
692
                        rc = jmb38x_ms_reset(host);
 
693
                        if (rc)
 
694
                                return rc;
 
695
 
 
696
                        host_ctl = 7;
 
697
                        host_ctl |= HOST_CONTROL_POWER_EN
 
698
                                 | HOST_CONTROL_CLOCK_EN;
 
699
                        writel(host_ctl, host->addr + HOST_CONTROL);
 
700
 
 
701
                        writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
 
702
                                        : PAD_PU_PD_ON_MS_SOCK0,
 
703
                               host->addr + PAD_PU_PD);
 
704
 
 
705
                        writel(PAD_OUTPUT_ENABLE_MS,
 
706
                               host->addr + PAD_OUTPUT_ENABLE);
 
707
 
 
708
                        msleep(10);
 
709
                        dev_dbg(&host->chip->pdev->dev, "power on\n");
 
710
                } else if (value == MEMSTICK_POWER_OFF) {
 
711
                        host_ctl &= ~(HOST_CONTROL_POWER_EN
 
712
                                      | HOST_CONTROL_CLOCK_EN);
 
713
                        writel(host_ctl, host->addr +  HOST_CONTROL);
 
714
                        writel(0, host->addr + PAD_OUTPUT_ENABLE);
 
715
                        writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
 
716
                        dev_dbg(&host->chip->pdev->dev, "power off\n");
 
717
                } else
 
718
                        return -EINVAL;
 
719
                break;
 
720
        case MEMSTICK_INTERFACE:
 
721
                dev_dbg(&host->chip->pdev->dev,
 
722
                        "Set Host Interface Mode to %d\n", value);
 
723
                host_ctl &= ~(HOST_CONTROL_FAST_CLK | HOST_CONTROL_REI |
 
724
                              HOST_CONTROL_REO);
 
725
                host_ctl |= HOST_CONTROL_TDELAY_EN | HOST_CONTROL_HW_OC_P;
 
726
                host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
 
727
 
 
728
                if (value == MEMSTICK_SERIAL) {
 
729
                        host_ctl |= HOST_CONTROL_IF_SERIAL
 
730
                                    << HOST_CONTROL_IF_SHIFT;
 
731
                        host_ctl |= HOST_CONTROL_REI;
 
732
                        clock_ctl |= CLOCK_CONTROL_40MHZ;
 
733
                        clock_delay = 0;
 
734
                } else if (value == MEMSTICK_PAR4) {
 
735
                        host_ctl |= HOST_CONTROL_FAST_CLK;
 
736
                        host_ctl |= HOST_CONTROL_IF_PAR4
 
737
                                    << HOST_CONTROL_IF_SHIFT;
 
738
                        host_ctl |= HOST_CONTROL_REO;
 
739
                        clock_ctl |= CLOCK_CONTROL_40MHZ;
 
740
                        clock_delay = 4;
 
741
                } else if (value == MEMSTICK_PAR8) {
 
742
                        host_ctl |= HOST_CONTROL_FAST_CLK;
 
743
                        host_ctl |= HOST_CONTROL_IF_PAR8
 
744
                                    << HOST_CONTROL_IF_SHIFT;
 
745
                        clock_ctl |= CLOCK_CONTROL_50MHZ;
 
746
                        clock_delay = 0;
 
747
                } else
 
748
                        return -EINVAL;
 
749
 
 
750
                writel(host_ctl, host->addr + HOST_CONTROL);
 
751
                writel(CLOCK_CONTROL_OFF, host->addr + CLOCK_CONTROL);
 
752
                writel(clock_ctl, host->addr + CLOCK_CONTROL);
 
753
                pci_write_config_byte(host->chip->pdev,
 
754
                                      PCI_CTL_CLOCK_DLY_ADDR + 1,
 
755
                                      clock_delay);
 
756
                host->ifmode = value;
 
757
                break;
 
758
        };
 
759
        return 0;
 
760
}
 
761
 
 
762
#define PCI_PMOS0_CONTROL               0xae
 
763
#define  PMOS0_ENABLE                   0x01
 
764
#define  PMOS0_OVERCURRENT_LEVEL_2_4V   0x06
 
765
#define  PMOS0_EN_OVERCURRENT_DEBOUNCE  0x40
 
766
#define  PMOS0_SW_LED_POLARITY_ENABLE   0x80
 
767
#define  PMOS0_ACTIVE_BITS (PMOS0_ENABLE | PMOS0_EN_OVERCURRENT_DEBOUNCE | \
 
768
                            PMOS0_OVERCURRENT_LEVEL_2_4V)
 
769
#define PCI_PMOS1_CONTROL               0xbd
 
770
#define  PMOS1_ACTIVE_BITS              0x4a
 
771
#define PCI_CLOCK_CTL                   0xb9
 
772
 
 
773
static int jmb38x_ms_pmos(struct pci_dev *pdev, int flag)
 
774
{
 
775
        unsigned char val;
 
776
 
 
777
        pci_read_config_byte(pdev, PCI_PMOS0_CONTROL, &val);
 
778
        if (flag)
 
779
                val |= PMOS0_ACTIVE_BITS;
 
780
        else
 
781
                val &= ~PMOS0_ACTIVE_BITS;
 
782
        pci_write_config_byte(pdev, PCI_PMOS0_CONTROL, val);
 
783
        dev_dbg(&pdev->dev, "JMB38x: set PMOS0 val 0x%x\n", val);
 
784
 
 
785
        if (pci_resource_flags(pdev, 1)) {
 
786
                pci_read_config_byte(pdev, PCI_PMOS1_CONTROL, &val);
 
787
                if (flag)
 
788
                        val |= PMOS1_ACTIVE_BITS;
 
789
                else
 
790
                        val &= ~PMOS1_ACTIVE_BITS;
 
791
                pci_write_config_byte(pdev, PCI_PMOS1_CONTROL, val);
 
792
                dev_dbg(&pdev->dev, "JMB38x: set PMOS1 val 0x%x\n", val);
 
793
        }
 
794
 
 
795
        pci_read_config_byte(pdev, PCI_CLOCK_CTL, &val);
 
796
        pci_write_config_byte(pdev, PCI_CLOCK_CTL, val & ~0x0f);
 
797
        pci_write_config_byte(pdev, PCI_CLOCK_CTL, val | 0x01);
 
798
        dev_dbg(&pdev->dev, "Clock Control by PCI config is disabled!\n");
 
799
 
 
800
        return 0;
 
801
}
 
802
 
 
803
#ifdef CONFIG_PM
 
804
 
 
805
static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state)
 
806
{
 
807
        struct jmb38x_ms *jm = pci_get_drvdata(dev);
 
808
        int cnt;
 
809
 
 
810
        for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
 
811
                if (!jm->hosts[cnt])
 
812
                        break;
 
813
                memstick_suspend_host(jm->hosts[cnt]);
 
814
        }
 
815
 
 
816
        pci_save_state(dev);
 
817
        pci_enable_wake(dev, pci_choose_state(dev, state), 0);
 
818
        pci_disable_device(dev);
 
819
        pci_set_power_state(dev, pci_choose_state(dev, state));
 
820
        return 0;
 
821
}
 
822
 
 
823
static int jmb38x_ms_resume(struct pci_dev *dev)
 
824
{
 
825
        struct jmb38x_ms *jm = pci_get_drvdata(dev);
 
826
        int rc;
 
827
 
 
828
        pci_set_power_state(dev, PCI_D0);
 
829
        pci_restore_state(dev);
 
830
        rc = pci_enable_device(dev);
 
831
        if (rc)
 
832
                return rc;
 
833
        pci_set_master(dev);
 
834
 
 
835
        jmb38x_ms_pmos(dev, 1);
 
836
 
 
837
        for (rc = 0; rc < jm->host_cnt; ++rc) {
 
838
                if (!jm->hosts[rc])
 
839
                        break;
 
840
                memstick_resume_host(jm->hosts[rc]);
 
841
                memstick_detect_change(jm->hosts[rc]);
 
842
        }
 
843
 
 
844
        return 0;
 
845
}
 
846
 
 
847
#else
 
848
 
 
849
#define jmb38x_ms_suspend NULL
 
850
#define jmb38x_ms_resume NULL
 
851
 
 
852
#endif /* CONFIG_PM */
 
853
 
 
854
static int jmb38x_ms_count_slots(struct pci_dev *pdev)
 
855
{
 
856
        int cnt, rc = 0;
 
857
 
 
858
        for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) {
 
859
                if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt)))
 
860
                        break;
 
861
 
 
862
                if (256 != pci_resource_len(pdev, cnt))
 
863
                        break;
 
864
 
 
865
                ++rc;
 
866
        }
 
867
        return rc;
 
868
}
 
869
 
 
870
static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
 
871
{
 
872
        struct memstick_host *msh;
 
873
        struct jmb38x_ms_host *host;
 
874
 
 
875
        msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host),
 
876
                                  &jm->pdev->dev);
 
877
        if (!msh)
 
878
                return NULL;
 
879
 
 
880
        host = memstick_priv(msh);
 
881
        host->chip = jm;
 
882
        host->addr = ioremap(pci_resource_start(jm->pdev, cnt),
 
883
                             pci_resource_len(jm->pdev, cnt));
 
884
        if (!host->addr)
 
885
                goto err_out_free;
 
886
 
 
887
        spin_lock_init(&host->lock);
 
888
        host->id = cnt;
 
889
        snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d",
 
890
                 host->id);
 
891
        host->irq = jm->pdev->irq;
 
892
        host->timeout_jiffies = msecs_to_jiffies(1000);
 
893
 
 
894
        tasklet_init(&host->notify, jmb38x_ms_req_tasklet, (unsigned long)msh);
 
895
        msh->request = jmb38x_ms_submit_req;
 
896
        msh->set_param = jmb38x_ms_set_param;
 
897
 
 
898
        msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
 
899
 
 
900
        setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh);
 
901
 
 
902
        if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id,
 
903
                         msh))
 
904
                return msh;
 
905
 
 
906
        iounmap(host->addr);
 
907
err_out_free:
 
908
        kfree(msh);
 
909
        return NULL;
 
910
}
 
911
 
 
912
static void jmb38x_ms_free_host(struct memstick_host *msh)
 
913
{
 
914
        struct jmb38x_ms_host *host = memstick_priv(msh);
 
915
 
 
916
        free_irq(host->irq, msh);
 
917
        iounmap(host->addr);
 
918
        memstick_free_host(msh);
 
919
}
 
920
 
 
921
static int jmb38x_ms_probe(struct pci_dev *pdev,
 
922
                           const struct pci_device_id *dev_id)
 
923
{
 
924
        struct jmb38x_ms *jm;
 
925
        int pci_dev_busy = 0;
 
926
        int rc, cnt;
 
927
 
 
928
        rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 
929
        if (rc)
 
930
                return rc;
 
931
 
 
932
        rc = pci_enable_device(pdev);
 
933
        if (rc)
 
934
                return rc;
 
935
 
 
936
        pci_set_master(pdev);
 
937
 
 
938
        rc = pci_request_regions(pdev, DRIVER_NAME);
 
939
        if (rc) {
 
940
                pci_dev_busy = 1;
 
941
                goto err_out;
 
942
        }
 
943
 
 
944
        jmb38x_ms_pmos(pdev, 1);
 
945
 
 
946
        cnt = jmb38x_ms_count_slots(pdev);
 
947
        if (!cnt) {
 
948
                rc = -ENODEV;
 
949
                pci_dev_busy = 1;
 
950
                goto err_out;
 
951
        }
 
952
 
 
953
        jm = kzalloc(sizeof(struct jmb38x_ms)
 
954
                     + cnt * sizeof(struct memstick_host *), GFP_KERNEL);
 
955
        if (!jm) {
 
956
                rc = -ENOMEM;
 
957
                goto err_out_int;
 
958
        }
 
959
 
 
960
        jm->pdev = pdev;
 
961
        jm->host_cnt = cnt;
 
962
        pci_set_drvdata(pdev, jm);
 
963
 
 
964
        for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
 
965
                jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt);
 
966
                if (!jm->hosts[cnt])
 
967
                        break;
 
968
 
 
969
                rc = memstick_add_host(jm->hosts[cnt]);
 
970
 
 
971
                if (rc) {
 
972
                        jmb38x_ms_free_host(jm->hosts[cnt]);
 
973
                        jm->hosts[cnt] = NULL;
 
974
                        break;
 
975
                }
 
976
        }
 
977
 
 
978
        if (cnt)
 
979
                return 0;
 
980
 
 
981
        rc = -ENODEV;
 
982
 
 
983
        pci_set_drvdata(pdev, NULL);
 
984
        kfree(jm);
 
985
err_out_int:
 
986
        pci_release_regions(pdev);
 
987
err_out:
 
988
        if (!pci_dev_busy)
 
989
                pci_disable_device(pdev);
 
990
        return rc;
 
991
}
 
992
 
 
993
static void jmb38x_ms_remove(struct pci_dev *dev)
 
994
{
 
995
        struct jmb38x_ms *jm = pci_get_drvdata(dev);
 
996
        struct jmb38x_ms_host *host;
 
997
        int cnt;
 
998
        unsigned long flags;
 
999
 
 
1000
        for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
 
1001
                if (!jm->hosts[cnt])
 
1002
                        break;
 
1003
 
 
1004
                host = memstick_priv(jm->hosts[cnt]);
 
1005
 
 
1006
                jm->hosts[cnt]->request = jmb38x_ms_dummy_submit;
 
1007
                tasklet_kill(&host->notify);
 
1008
                writel(0, host->addr + INT_SIGNAL_ENABLE);
 
1009
                writel(0, host->addr + INT_STATUS_ENABLE);
 
1010
                mmiowb();
 
1011
                dev_dbg(&jm->pdev->dev, "interrupts off\n");
 
1012
                spin_lock_irqsave(&host->lock, flags);
 
1013
                if (host->req) {
 
1014
                        host->req->error = -ETIME;
 
1015
                        jmb38x_ms_complete_cmd(jm->hosts[cnt], 1);
 
1016
                }
 
1017
                spin_unlock_irqrestore(&host->lock, flags);
 
1018
 
 
1019
                memstick_remove_host(jm->hosts[cnt]);
 
1020
                dev_dbg(&jm->pdev->dev, "host removed\n");
 
1021
 
 
1022
                jmb38x_ms_free_host(jm->hosts[cnt]);
 
1023
        }
 
1024
 
 
1025
        jmb38x_ms_pmos(dev, 0);
 
1026
 
 
1027
        pci_set_drvdata(dev, NULL);
 
1028
        pci_release_regions(dev);
 
1029
        pci_disable_device(dev);
 
1030
        kfree(jm);
 
1031
}
 
1032
 
 
1033
static struct pci_device_id jmb38x_ms_id_tbl [] = {
 
1034
        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS) },
 
1035
        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB385_MS) },
 
1036
        { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB390_MS) },
 
1037
        { }
 
1038
};
 
1039
 
 
1040
static struct pci_driver jmb38x_ms_driver = {
 
1041
        .name = DRIVER_NAME,
 
1042
        .id_table = jmb38x_ms_id_tbl,
 
1043
        .probe = jmb38x_ms_probe,
 
1044
        .remove = jmb38x_ms_remove,
 
1045
        .suspend = jmb38x_ms_suspend,
 
1046
        .resume = jmb38x_ms_resume
 
1047
};
 
1048
 
 
1049
static int __init jmb38x_ms_init(void)
 
1050
{
 
1051
        return pci_register_driver(&jmb38x_ms_driver);
 
1052
}
 
1053
 
 
1054
static void __exit jmb38x_ms_exit(void)
 
1055
{
 
1056
        pci_unregister_driver(&jmb38x_ms_driver);
 
1057
}
 
1058
 
 
1059
MODULE_AUTHOR("Alex Dubov");
 
1060
MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");
 
1061
MODULE_LICENSE("GPL");
 
1062
MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);
 
1063
 
 
1064
module_init(jmb38x_ms_init);
 
1065
module_exit(jmb38x_ms_exit);