linux/drivers/memstick/host/jmb38x_ms.c
<<
>>
Prefs
   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
  24static bool no_dma;
  25module_param(no_dma, bool, 0644);
  26
  27enum {
  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
  51struct 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
  69struct 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
 150enum {
 151        CMD_READY    = 0x01,
 152        FIFO_READY   = 0x02,
 153        REG_DATA     = 0x04,
 154        DMA_DATA     = 0x08
 155};
 156
 157static 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
 195static 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
 221static 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
 274static 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
 300static 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) + 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);
 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
 367static 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
 470static 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
 520static 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
 595static 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
 610static 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
 627static void jmb38x_ms_dummy_submit(struct memstick_host *msh)
 628{
 629        return;
 630}
 631
 632static 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
 639static 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
 657reset_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
 673reset_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
 680static 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
 773static 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
 805static 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
 823static 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
 854static 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
 870static 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);
 907err_out_free:
 908        kfree(msh);
 909        return NULL;
 910}
 911
 912static 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
 921static 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);
 985err_out_int:
 986        pci_release_regions(pdev);
 987err_out:
 988        if (!pci_dev_busy)
 989                pci_disable_device(pdev);
 990        return rc;
 991}
 992
 993static 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
1033static 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
1040static 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
1049module_pci_driver(jmb38x_ms_driver);
1050
1051MODULE_AUTHOR("Alex Dubov");
1052MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");
1053MODULE_LICENSE("GPL");
1054MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);
1055