1031 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * jmb38x_ms.c - JMicron jmb38x MemoryStick card reader4 *5 * Copyright (C) 2008 Alex Dubov <oakad@yahoo.com>6 */7 8#include <linux/spinlock.h>9#include <linux/interrupt.h>10#include <linux/pci.h>11#include <linux/dma-mapping.h>12#include <linux/delay.h>13#include <linux/highmem.h>14#include <linux/memstick.h>15#include <linux/slab.h>16#include <linux/module.h>17 18#define DRIVER_NAME "jmb38x_ms"19 20static bool no_dma;21module_param(no_dma, bool, 0644);22 23enum {24 DMA_ADDRESS = 0x00,25 BLOCK = 0x04,26 DMA_CONTROL = 0x08,27 TPC_P0 = 0x0c,28 TPC_P1 = 0x10,29 TPC = 0x14,30 HOST_CONTROL = 0x18,31 DATA = 0x1c,32 STATUS = 0x20,33 INT_STATUS = 0x24,34 INT_STATUS_ENABLE = 0x28,35 INT_SIGNAL_ENABLE = 0x2c,36 TIMER = 0x30,37 TIMER_CONTROL = 0x34,38 PAD_OUTPUT_ENABLE = 0x38,39 PAD_PU_PD = 0x3c,40 CLOCK_DELAY = 0x40,41 ADMA_ADDRESS = 0x44,42 CLOCK_CONTROL = 0x48,43 LED_CONTROL = 0x4c,44 VERSION = 0x5045};46 47struct jmb38x_ms_host {48 struct jmb38x_ms *chip;49 void __iomem *addr;50 spinlock_t lock;51 struct tasklet_struct notify;52 int id;53 char host_id[32];54 int irq;55 unsigned int block_pos;56 unsigned long timeout_jiffies;57 struct timer_list timer;58 struct memstick_host *msh;59 struct memstick_request *req;60 unsigned char cmd_flags;61 unsigned char io_pos;62 unsigned char ifmode;63 unsigned int io_word[2];64};65 66struct jmb38x_ms {67 struct pci_dev *pdev;68 int host_cnt;69 struct memstick_host *hosts[] __counted_by(host_cnt);70};71 72#define BLOCK_COUNT_MASK 0xffff000073#define BLOCK_SIZE_MASK 0x00000fff74 75#define DMA_CONTROL_ENABLE 0x0000000176 77#define TPC_DATA_SEL 0x0000800078#define TPC_DIR 0x0000400079#define TPC_WAIT_INT 0x0000200080#define TPC_GET_INT 0x0000080081#define TPC_CODE_SZ_MASK 0x0000070082#define TPC_DATA_SZ_MASK 0x0000000783 84#define HOST_CONTROL_TDELAY_EN 0x0004000085#define HOST_CONTROL_HW_OC_P 0x0001000086#define HOST_CONTROL_RESET_REQ 0x0000800087#define HOST_CONTROL_REI 0x0000400088#define HOST_CONTROL_LED 0x0000040089#define HOST_CONTROL_FAST_CLK 0x0000020090#define HOST_CONTROL_RESET 0x0000010091#define HOST_CONTROL_POWER_EN 0x0000008092#define HOST_CONTROL_CLOCK_EN 0x0000004093#define HOST_CONTROL_REO 0x0000000894#define HOST_CONTROL_IF_SHIFT 495 96#define HOST_CONTROL_IF_SERIAL 0x097#define HOST_CONTROL_IF_PAR4 0x198#define HOST_CONTROL_IF_PAR8 0x399 100#define STATUS_BUSY 0x00080000101#define STATUS_MS_DAT7 0x00040000102#define STATUS_MS_DAT6 0x00020000103#define STATUS_MS_DAT5 0x00010000104#define STATUS_MS_DAT4 0x00008000105#define STATUS_MS_DAT3 0x00004000106#define STATUS_MS_DAT2 0x00002000107#define STATUS_MS_DAT1 0x00001000108#define STATUS_MS_DAT0 0x00000800109#define STATUS_HAS_MEDIA 0x00000400110#define STATUS_FIFO_EMPTY 0x00000200111#define STATUS_FIFO_FULL 0x00000100112#define STATUS_MS_CED 0x00000080113#define STATUS_MS_ERR 0x00000040114#define STATUS_MS_BRQ 0x00000020115#define STATUS_MS_CNK 0x00000001116 117#define INT_STATUS_TPC_ERR 0x00080000118#define INT_STATUS_CRC_ERR 0x00040000119#define INT_STATUS_TIMER_TO 0x00020000120#define INT_STATUS_HSK_TO 0x00010000121#define INT_STATUS_ANY_ERR 0x00008000122#define INT_STATUS_FIFO_WRDY 0x00000080123#define INT_STATUS_FIFO_RRDY 0x00000040124#define INT_STATUS_MEDIA_OUT 0x00000010125#define INT_STATUS_MEDIA_IN 0x00000008126#define INT_STATUS_DMA_BOUNDARY 0x00000004127#define INT_STATUS_EOTRAN 0x00000002128#define INT_STATUS_EOTPC 0x00000001129 130#define INT_STATUS_ALL 0x000f801f131 132#define PAD_OUTPUT_ENABLE_MS 0x0F3F133 134#define PAD_PU_PD_OFF 0x7FFF0000135#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000136#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000137 138#define CLOCK_CONTROL_BY_MMIO 0x00000008139#define CLOCK_CONTROL_40MHZ 0x00000001140#define CLOCK_CONTROL_50MHZ 0x00000002141#define CLOCK_CONTROL_60MHZ 0x00000010142#define CLOCK_CONTROL_62_5MHZ 0x00000004143#define CLOCK_CONTROL_OFF 0x00000000144 145#define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0146 147enum {148 CMD_READY = 0x01,149 FIFO_READY = 0x02,150 REG_DATA = 0x04,151 DMA_DATA = 0x08152};153 154static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,155 unsigned char *buf, unsigned int length)156{157 unsigned int off = 0;158 159 while (host->io_pos && length) {160 buf[off++] = host->io_word[0] & 0xff;161 host->io_word[0] >>= 8;162 length--;163 host->io_pos--;164 }165 166 if (!length)167 return off;168 169 while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {170 if (length < 4)171 break;172 *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);173 length -= 4;174 off += 4;175 }176 177 if (length178 && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {179 host->io_word[0] = readl(host->addr + DATA);180 for (host->io_pos = 4; host->io_pos; --host->io_pos) {181 buf[off++] = host->io_word[0] & 0xff;182 host->io_word[0] >>= 8;183 length--;184 if (!length)185 break;186 }187 }188 189 return off;190}191 192static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host,193 unsigned char *buf,194 unsigned int length)195{196 unsigned int off = 0;197 198 while (host->io_pos > 4 && length) {199 buf[off++] = host->io_word[0] & 0xff;200 host->io_word[0] >>= 8;201 length--;202 host->io_pos--;203 }204 205 if (!length)206 return off;207 208 while (host->io_pos && length) {209 buf[off++] = host->io_word[1] & 0xff;210 host->io_word[1] >>= 8;211 length--;212 host->io_pos--;213 }214 215 return off;216}217 218static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host,219 unsigned char *buf,220 unsigned int length)221{222 unsigned int off = 0;223 224 if (host->io_pos) {225 while (host->io_pos < 4 && length) {226 host->io_word[0] |= buf[off++] << (host->io_pos * 8);227 host->io_pos++;228 length--;229 }230 }231 232 if (host->io_pos == 4233 && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {234 writel(host->io_word[0], host->addr + DATA);235 host->io_pos = 0;236 host->io_word[0] = 0;237 } else if (host->io_pos) {238 return off;239 }240 241 if (!length)242 return off;243 244 while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {245 if (length < 4)246 break;247 248 __raw_writel(*(unsigned int *)(buf + off),249 host->addr + DATA);250 length -= 4;251 off += 4;252 }253 254 switch (length) {255 case 3:256 host->io_word[0] |= buf[off + 2] << 16;257 host->io_pos++;258 fallthrough;259 case 2:260 host->io_word[0] |= buf[off + 1] << 8;261 host->io_pos++;262 fallthrough;263 case 1:264 host->io_word[0] |= buf[off];265 host->io_pos++;266 }267 268 off += host->io_pos;269 270 return off;271}272 273static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host,274 unsigned char *buf,275 unsigned int length)276{277 unsigned int off = 0;278 279 while (host->io_pos < 4 && length) {280 host->io_word[0] &= ~(0xff << (host->io_pos * 8));281 host->io_word[0] |= buf[off++] << (host->io_pos * 8);282 host->io_pos++;283 length--;284 }285 286 if (!length)287 return off;288 289 while (host->io_pos < 8 && length) {290 host->io_word[1] &= ~(0xff << (host->io_pos * 8));291 host->io_word[1] |= buf[off++] << (host->io_pos * 8);292 host->io_pos++;293 length--;294 }295 296 return off;297}298 299static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)300{301 unsigned int length;302 unsigned int off;303 unsigned int t_size, p_cnt;304 unsigned char *buf;305 struct page *pg;306 unsigned long flags = 0;307 308 if (host->req->long_data) {309 length = host->req->sg.length - host->block_pos;310 off = host->req->sg.offset + host->block_pos;311 } else {312 length = host->req->data_len - host->block_pos;313 off = 0;314 }315 316 while (length) {317 unsigned int p_off;318 319 if (host->req->long_data) {320 pg = nth_page(sg_page(&host->req->sg),321 off >> PAGE_SHIFT);322 p_off = offset_in_page(off);323 p_cnt = PAGE_SIZE - p_off;324 p_cnt = min(p_cnt, length);325 326 local_irq_save(flags);327 buf = kmap_atomic(pg) + p_off;328 } else {329 buf = host->req->data + host->block_pos;330 p_cnt = host->req->data_len - host->block_pos;331 }332 333 if (host->req->data_dir == WRITE)334 t_size = !(host->cmd_flags & REG_DATA)335 ? jmb38x_ms_write_data(host, buf, p_cnt)336 : jmb38x_ms_write_reg_data(host, buf, p_cnt);337 else338 t_size = !(host->cmd_flags & REG_DATA)339 ? jmb38x_ms_read_data(host, buf, p_cnt)340 : jmb38x_ms_read_reg_data(host, buf, p_cnt);341 342 if (host->req->long_data) {343 kunmap_atomic(buf - p_off);344 local_irq_restore(flags);345 }346 347 if (!t_size)348 break;349 host->block_pos += t_size;350 length -= t_size;351 off += t_size;352 }353 354 if (!length && host->req->data_dir == WRITE) {355 if (host->cmd_flags & REG_DATA) {356 writel(host->io_word[0], host->addr + TPC_P0);357 writel(host->io_word[1], host->addr + TPC_P1);358 } else if (host->io_pos) {359 writel(host->io_word[0], host->addr + DATA);360 }361 }362 363 return length;364}365 366static int jmb38x_ms_issue_cmd(struct memstick_host *msh)367{368 struct jmb38x_ms_host *host = memstick_priv(msh);369 unsigned int data_len, cmd, t_val;370 371 if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {372 dev_dbg(&msh->dev, "no media status\n");373 host->req->error = -ETIME;374 return host->req->error;375 }376 377 dev_dbg(&msh->dev, "control %08x\n", readl(host->addr + HOST_CONTROL));378 dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS));379 dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS));380 381 host->cmd_flags = 0;382 host->block_pos = 0;383 host->io_pos = 0;384 host->io_word[0] = 0;385 host->io_word[1] = 0;386 387 cmd = host->req->tpc << 16;388 cmd |= TPC_DATA_SEL;389 390 if (host->req->data_dir == READ)391 cmd |= TPC_DIR;392 393 if (host->req->need_card_int) {394 if (host->ifmode == MEMSTICK_SERIAL)395 cmd |= TPC_GET_INT;396 else397 cmd |= TPC_WAIT_INT;398 }399 400 if (!no_dma)401 host->cmd_flags |= DMA_DATA;402 403 if (host->req->long_data) {404 data_len = host->req->sg.length;405 } else {406 data_len = host->req->data_len;407 host->cmd_flags &= ~DMA_DATA;408 }409 410 if (data_len <= 8) {411 cmd &= ~(TPC_DATA_SEL | 0xf);412 host->cmd_flags |= REG_DATA;413 cmd |= data_len & 0xf;414 host->cmd_flags &= ~DMA_DATA;415 }416 417 if (host->cmd_flags & DMA_DATA) {418 if (1 != dma_map_sg(&host->chip->pdev->dev, &host->req->sg, 1,419 host->req->data_dir == READ420 ? DMA_FROM_DEVICE421 : DMA_TO_DEVICE)) {422 host->req->error = -ENOMEM;423 return host->req->error;424 }425 data_len = sg_dma_len(&host->req->sg);426 writel(sg_dma_address(&host->req->sg),427 host->addr + DMA_ADDRESS);428 writel(((1 << 16) & BLOCK_COUNT_MASK)429 | (data_len & BLOCK_SIZE_MASK),430 host->addr + BLOCK);431 writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);432 } else if (!(host->cmd_flags & REG_DATA)) {433 writel(((1 << 16) & BLOCK_COUNT_MASK)434 | (data_len & BLOCK_SIZE_MASK),435 host->addr + BLOCK);436 t_val = readl(host->addr + INT_STATUS_ENABLE);437 t_val |= host->req->data_dir == READ438 ? INT_STATUS_FIFO_RRDY439 : INT_STATUS_FIFO_WRDY;440 441 writel(t_val, host->addr + INT_STATUS_ENABLE);442 writel(t_val, host->addr + INT_SIGNAL_ENABLE);443 } else {444 cmd &= ~(TPC_DATA_SEL | 0xf);445 host->cmd_flags |= REG_DATA;446 cmd |= data_len & 0xf;447 448 if (host->req->data_dir == WRITE) {449 jmb38x_ms_transfer_data(host);450 writel(host->io_word[0], host->addr + TPC_P0);451 writel(host->io_word[1], host->addr + TPC_P1);452 }453 }454 455 mod_timer(&host->timer, jiffies + host->timeout_jiffies);456 writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),457 host->addr + HOST_CONTROL);458 host->req->error = 0;459 460 writel(cmd, host->addr + TPC);461 dev_dbg(&msh->dev, "executing TPC %08x, len %x\n", cmd, data_len);462 463 return 0;464}465 466static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)467{468 struct jmb38x_ms_host *host = memstick_priv(msh);469 unsigned int t_val = 0;470 int rc;471 472 del_timer(&host->timer);473 474 dev_dbg(&msh->dev, "c control %08x\n",475 readl(host->addr + HOST_CONTROL));476 dev_dbg(&msh->dev, "c status %08x\n",477 readl(host->addr + INT_STATUS));478 dev_dbg(&msh->dev, "c hstatus %08x\n", readl(host->addr + STATUS));479 480 host->req->int_reg = readl(host->addr + STATUS) & 0xff;481 482 writel(0, host->addr + BLOCK);483 writel(0, host->addr + DMA_CONTROL);484 485 if (host->cmd_flags & DMA_DATA) {486 dma_unmap_sg(&host->chip->pdev->dev, &host->req->sg, 1,487 host->req->data_dir == READ488 ? DMA_FROM_DEVICE : DMA_TO_DEVICE);489 } else {490 t_val = readl(host->addr + INT_STATUS_ENABLE);491 if (host->req->data_dir == READ)492 t_val &= ~INT_STATUS_FIFO_RRDY;493 else494 t_val &= ~INT_STATUS_FIFO_WRDY;495 496 writel(t_val, host->addr + INT_STATUS_ENABLE);497 writel(t_val, host->addr + INT_SIGNAL_ENABLE);498 }499 500 writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),501 host->addr + HOST_CONTROL);502 503 if (!last) {504 do {505 rc = memstick_next_req(msh, &host->req);506 } while (!rc && jmb38x_ms_issue_cmd(msh));507 } else {508 do {509 rc = memstick_next_req(msh, &host->req);510 if (!rc)511 host->req->error = -ETIME;512 } while (!rc);513 }514}515 516static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)517{518 struct memstick_host *msh = dev_id;519 struct jmb38x_ms_host *host = memstick_priv(msh);520 unsigned int irq_status;521 522 spin_lock(&host->lock);523 irq_status = readl(host->addr + INT_STATUS);524 dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status);525 if (irq_status == 0 || irq_status == (~0)) {526 spin_unlock(&host->lock);527 return IRQ_NONE;528 }529 530 if (host->req) {531 if (irq_status & INT_STATUS_ANY_ERR) {532 if (irq_status & INT_STATUS_CRC_ERR)533 host->req->error = -EILSEQ;534 else if (irq_status & INT_STATUS_TPC_ERR) {535 dev_dbg(&host->chip->pdev->dev, "TPC_ERR\n");536 jmb38x_ms_complete_cmd(msh, 0);537 } else538 host->req->error = -ETIME;539 } else {540 if (host->cmd_flags & DMA_DATA) {541 if (irq_status & INT_STATUS_EOTRAN)542 host->cmd_flags |= FIFO_READY;543 } else {544 if (irq_status & (INT_STATUS_FIFO_RRDY545 | INT_STATUS_FIFO_WRDY))546 jmb38x_ms_transfer_data(host);547 548 if (irq_status & INT_STATUS_EOTRAN) {549 jmb38x_ms_transfer_data(host);550 host->cmd_flags |= FIFO_READY;551 }552 }553 554 if (irq_status & INT_STATUS_EOTPC) {555 host->cmd_flags |= CMD_READY;556 if (host->cmd_flags & REG_DATA) {557 if (host->req->data_dir == READ) {558 host->io_word[0]559 = readl(host->addr560 + TPC_P0);561 host->io_word[1]562 = readl(host->addr563 + TPC_P1);564 host->io_pos = 8;565 566 jmb38x_ms_transfer_data(host);567 }568 host->cmd_flags |= FIFO_READY;569 }570 }571 }572 }573 574 if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) {575 dev_dbg(&host->chip->pdev->dev, "media changed\n");576 memstick_detect_change(msh);577 }578 579 writel(irq_status, host->addr + INT_STATUS);580 581 if (host->req582 && (((host->cmd_flags & CMD_READY)583 && (host->cmd_flags & FIFO_READY))584 || host->req->error))585 jmb38x_ms_complete_cmd(msh, 0);586 587 spin_unlock(&host->lock);588 return IRQ_HANDLED;589}590 591static void jmb38x_ms_abort(struct timer_list *t)592{593 struct jmb38x_ms_host *host = from_timer(host, t, timer);594 struct memstick_host *msh = host->msh;595 unsigned long flags;596 597 dev_dbg(&host->chip->pdev->dev, "abort\n");598 spin_lock_irqsave(&host->lock, flags);599 if (host->req) {600 host->req->error = -ETIME;601 jmb38x_ms_complete_cmd(msh, 0);602 }603 spin_unlock_irqrestore(&host->lock, flags);604}605 606static void jmb38x_ms_req_tasklet(unsigned long data)607{608 struct memstick_host *msh = (struct memstick_host *)data;609 struct jmb38x_ms_host *host = memstick_priv(msh);610 unsigned long flags;611 int rc;612 613 spin_lock_irqsave(&host->lock, flags);614 if (!host->req) {615 do {616 rc = memstick_next_req(msh, &host->req);617 dev_dbg(&host->chip->pdev->dev, "tasklet req %d\n", rc);618 } while (!rc && jmb38x_ms_issue_cmd(msh));619 }620 spin_unlock_irqrestore(&host->lock, flags);621}622 623static void jmb38x_ms_dummy_submit(struct memstick_host *msh)624{625 return;626}627 628static void jmb38x_ms_submit_req(struct memstick_host *msh)629{630 struct jmb38x_ms_host *host = memstick_priv(msh);631 632 tasklet_schedule(&host->notify);633}634 635static int jmb38x_ms_reset(struct jmb38x_ms_host *host)636{637 int cnt;638 639 writel(HOST_CONTROL_RESET_REQ | HOST_CONTROL_CLOCK_EN640 | readl(host->addr + HOST_CONTROL),641 host->addr + HOST_CONTROL);642 643 for (cnt = 0; cnt < 20; ++cnt) {644 if (!(HOST_CONTROL_RESET_REQ645 & readl(host->addr + HOST_CONTROL)))646 goto reset_next;647 648 ndelay(20);649 }650 dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n");651 652reset_next:653 writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN654 | readl(host->addr + HOST_CONTROL),655 host->addr + HOST_CONTROL);656 657 for (cnt = 0; cnt < 20; ++cnt) {658 if (!(HOST_CONTROL_RESET659 & readl(host->addr + HOST_CONTROL)))660 goto reset_ok;661 662 ndelay(20);663 }664 dev_dbg(&host->chip->pdev->dev, "reset timeout\n");665 return -EIO;666 667reset_ok:668 writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);669 writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);670 return 0;671}672 673static int jmb38x_ms_set_param(struct memstick_host *msh,674 enum memstick_param param,675 int value)676{677 struct jmb38x_ms_host *host = memstick_priv(msh);678 unsigned int host_ctl = readl(host->addr + HOST_CONTROL);679 unsigned int clock_ctl = CLOCK_CONTROL_BY_MMIO, clock_delay = 0;680 int rc = 0;681 682 switch (param) {683 case MEMSTICK_POWER:684 if (value == MEMSTICK_POWER_ON) {685 rc = jmb38x_ms_reset(host);686 if (rc)687 return rc;688 689 host_ctl = 7;690 host_ctl |= HOST_CONTROL_POWER_EN691 | HOST_CONTROL_CLOCK_EN;692 writel(host_ctl, host->addr + HOST_CONTROL);693 694 writel(host->id ? PAD_PU_PD_ON_MS_SOCK1695 : PAD_PU_PD_ON_MS_SOCK0,696 host->addr + PAD_PU_PD);697 698 writel(PAD_OUTPUT_ENABLE_MS,699 host->addr + PAD_OUTPUT_ENABLE);700 701 msleep(10);702 dev_dbg(&host->chip->pdev->dev, "power on\n");703 } else if (value == MEMSTICK_POWER_OFF) {704 host_ctl &= ~(HOST_CONTROL_POWER_EN705 | HOST_CONTROL_CLOCK_EN);706 writel(host_ctl, host->addr + HOST_CONTROL);707 writel(0, host->addr + PAD_OUTPUT_ENABLE);708 writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);709 dev_dbg(&host->chip->pdev->dev, "power off\n");710 } else711 return -EINVAL;712 break;713 case MEMSTICK_INTERFACE:714 dev_dbg(&host->chip->pdev->dev,715 "Set Host Interface Mode to %d\n", value);716 host_ctl &= ~(HOST_CONTROL_FAST_CLK | HOST_CONTROL_REI |717 HOST_CONTROL_REO);718 host_ctl |= HOST_CONTROL_TDELAY_EN | HOST_CONTROL_HW_OC_P;719 host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);720 721 if (value == MEMSTICK_SERIAL) {722 host_ctl |= HOST_CONTROL_IF_SERIAL723 << HOST_CONTROL_IF_SHIFT;724 host_ctl |= HOST_CONTROL_REI;725 clock_ctl |= CLOCK_CONTROL_40MHZ;726 clock_delay = 0;727 } else if (value == MEMSTICK_PAR4) {728 host_ctl |= HOST_CONTROL_FAST_CLK;729 host_ctl |= HOST_CONTROL_IF_PAR4730 << HOST_CONTROL_IF_SHIFT;731 host_ctl |= HOST_CONTROL_REO;732 clock_ctl |= CLOCK_CONTROL_40MHZ;733 clock_delay = 4;734 } else if (value == MEMSTICK_PAR8) {735 host_ctl |= HOST_CONTROL_FAST_CLK;736 host_ctl |= HOST_CONTROL_IF_PAR8737 << HOST_CONTROL_IF_SHIFT;738 clock_ctl |= CLOCK_CONTROL_50MHZ;739 clock_delay = 0;740 } else741 return -EINVAL;742 743 writel(host_ctl, host->addr + HOST_CONTROL);744 writel(CLOCK_CONTROL_OFF, host->addr + CLOCK_CONTROL);745 writel(clock_ctl, host->addr + CLOCK_CONTROL);746 pci_write_config_byte(host->chip->pdev,747 PCI_CTL_CLOCK_DLY_ADDR + 1,748 clock_delay);749 host->ifmode = value;750 break;751 }752 return 0;753}754 755#define PCI_PMOS0_CONTROL 0xae756#define PMOS0_ENABLE 0x01757#define PMOS0_OVERCURRENT_LEVEL_2_4V 0x06758#define PMOS0_EN_OVERCURRENT_DEBOUNCE 0x40759#define PMOS0_SW_LED_POLARITY_ENABLE 0x80760#define PMOS0_ACTIVE_BITS (PMOS0_ENABLE | PMOS0_EN_OVERCURRENT_DEBOUNCE | \761 PMOS0_OVERCURRENT_LEVEL_2_4V)762#define PCI_PMOS1_CONTROL 0xbd763#define PMOS1_ACTIVE_BITS 0x4a764#define PCI_CLOCK_CTL 0xb9765 766static int jmb38x_ms_pmos(struct pci_dev *pdev, int flag)767{768 unsigned char val;769 770 pci_read_config_byte(pdev, PCI_PMOS0_CONTROL, &val);771 if (flag)772 val |= PMOS0_ACTIVE_BITS;773 else774 val &= ~PMOS0_ACTIVE_BITS;775 pci_write_config_byte(pdev, PCI_PMOS0_CONTROL, val);776 dev_dbg(&pdev->dev, "JMB38x: set PMOS0 val 0x%x\n", val);777 778 if (pci_resource_flags(pdev, 1)) {779 pci_read_config_byte(pdev, PCI_PMOS1_CONTROL, &val);780 if (flag)781 val |= PMOS1_ACTIVE_BITS;782 else783 val &= ~PMOS1_ACTIVE_BITS;784 pci_write_config_byte(pdev, PCI_PMOS1_CONTROL, val);785 dev_dbg(&pdev->dev, "JMB38x: set PMOS1 val 0x%x\n", val);786 }787 788 pci_read_config_byte(pdev, PCI_CLOCK_CTL, &val);789 pci_write_config_byte(pdev, PCI_CLOCK_CTL, val & ~0x0f);790 pci_write_config_byte(pdev, PCI_CLOCK_CTL, val | 0x01);791 dev_dbg(&pdev->dev, "Clock Control by PCI config is disabled!\n");792 793 return 0;794}795 796static int __maybe_unused jmb38x_ms_suspend(struct device *dev)797{798 struct jmb38x_ms *jm = dev_get_drvdata(dev);799 800 int cnt;801 802 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {803 if (!jm->hosts[cnt])804 break;805 memstick_suspend_host(jm->hosts[cnt]);806 }807 808 device_wakeup_disable(dev);809 810 return 0;811}812 813static int __maybe_unused jmb38x_ms_resume(struct device *dev)814{815 struct jmb38x_ms *jm = dev_get_drvdata(dev);816 int rc;817 818 jmb38x_ms_pmos(to_pci_dev(dev), 1);819 820 for (rc = 0; rc < jm->host_cnt; ++rc) {821 if (!jm->hosts[rc])822 break;823 memstick_resume_host(jm->hosts[rc]);824 memstick_detect_change(jm->hosts[rc]);825 }826 827 return 0;828}829 830static int jmb38x_ms_count_slots(struct pci_dev *pdev)831{832 int cnt, rc = 0;833 834 for (cnt = 0; cnt < PCI_STD_NUM_BARS; ++cnt) {835 if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt)))836 break;837 838 if (256 != pci_resource_len(pdev, cnt))839 break;840 841 ++rc;842 }843 return rc;844}845 846static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)847{848 struct memstick_host *msh;849 struct jmb38x_ms_host *host;850 851 msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host),852 &jm->pdev->dev);853 if (!msh)854 return NULL;855 856 host = memstick_priv(msh);857 host->msh = msh;858 host->chip = jm;859 host->addr = ioremap(pci_resource_start(jm->pdev, cnt),860 pci_resource_len(jm->pdev, cnt));861 if (!host->addr)862 goto err_out_free;863 864 spin_lock_init(&host->lock);865 host->id = cnt;866 snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d",867 host->id);868 host->irq = jm->pdev->irq;869 host->timeout_jiffies = msecs_to_jiffies(1000);870 871 tasklet_init(&host->notify, jmb38x_ms_req_tasklet, (unsigned long)msh);872 msh->request = jmb38x_ms_submit_req;873 msh->set_param = jmb38x_ms_set_param;874 875 msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;876 877 timer_setup(&host->timer, jmb38x_ms_abort, 0);878 879 if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id,880 msh))881 return msh;882 883 iounmap(host->addr);884err_out_free:885 memstick_free_host(msh);886 return NULL;887}888 889static void jmb38x_ms_free_host(struct memstick_host *msh)890{891 struct jmb38x_ms_host *host = memstick_priv(msh);892 893 free_irq(host->irq, msh);894 iounmap(host->addr);895 memstick_free_host(msh);896}897 898static int jmb38x_ms_probe(struct pci_dev *pdev,899 const struct pci_device_id *dev_id)900{901 struct jmb38x_ms *jm;902 int pci_dev_busy = 0;903 int rc, cnt;904 905 rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));906 if (rc)907 return rc;908 909 rc = pci_enable_device(pdev);910 if (rc)911 return rc;912 913 pci_set_master(pdev);914 915 rc = pci_request_regions(pdev, DRIVER_NAME);916 if (rc) {917 pci_dev_busy = 1;918 goto err_out;919 }920 921 jmb38x_ms_pmos(pdev, 1);922 923 cnt = jmb38x_ms_count_slots(pdev);924 if (!cnt) {925 rc = -ENODEV;926 pci_dev_busy = 1;927 goto err_out_int;928 }929 930 jm = kzalloc(struct_size(jm, hosts, cnt), GFP_KERNEL);931 if (!jm) {932 rc = -ENOMEM;933 goto err_out_int;934 }935 936 jm->pdev = pdev;937 jm->host_cnt = cnt;938 pci_set_drvdata(pdev, jm);939 940 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {941 jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt);942 if (!jm->hosts[cnt])943 break;944 945 rc = memstick_add_host(jm->hosts[cnt]);946 947 if (rc) {948 jmb38x_ms_free_host(jm->hosts[cnt]);949 jm->hosts[cnt] = NULL;950 break;951 }952 }953 954 if (cnt)955 return 0;956 957 rc = -ENODEV;958 959 pci_set_drvdata(pdev, NULL);960 kfree(jm);961err_out_int:962 pci_release_regions(pdev);963err_out:964 if (!pci_dev_busy)965 pci_disable_device(pdev);966 return rc;967}968 969static void jmb38x_ms_remove(struct pci_dev *dev)970{971 struct jmb38x_ms *jm = pci_get_drvdata(dev);972 struct jmb38x_ms_host *host;973 int cnt;974 unsigned long flags;975 976 for (cnt = 0; cnt < jm->host_cnt; ++cnt) {977 if (!jm->hosts[cnt])978 break;979 980 host = memstick_priv(jm->hosts[cnt]);981 982 jm->hosts[cnt]->request = jmb38x_ms_dummy_submit;983 tasklet_kill(&host->notify);984 writel(0, host->addr + INT_SIGNAL_ENABLE);985 writel(0, host->addr + INT_STATUS_ENABLE);986 dev_dbg(&jm->pdev->dev, "interrupts off\n");987 spin_lock_irqsave(&host->lock, flags);988 if (host->req) {989 host->req->error = -ETIME;990 jmb38x_ms_complete_cmd(jm->hosts[cnt], 1);991 }992 spin_unlock_irqrestore(&host->lock, flags);993 994 memstick_remove_host(jm->hosts[cnt]);995 dev_dbg(&jm->pdev->dev, "host removed\n");996 997 jmb38x_ms_free_host(jm->hosts[cnt]);998 }999 1000 jmb38x_ms_pmos(dev, 0);1001 1002 pci_set_drvdata(dev, NULL);1003 pci_release_regions(dev);1004 pci_disable_device(dev);1005 kfree(jm);1006}1007 1008static struct pci_device_id jmb38x_ms_id_tbl [] = {1009 { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS) },1010 { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB385_MS) },1011 { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB390_MS) },1012 { }1013};1014 1015static SIMPLE_DEV_PM_OPS(jmb38x_ms_pm_ops, jmb38x_ms_suspend, jmb38x_ms_resume);1016 1017static struct pci_driver jmb38x_ms_driver = {1018 .name = DRIVER_NAME,1019 .id_table = jmb38x_ms_id_tbl,1020 .probe = jmb38x_ms_probe,1021 .remove = jmb38x_ms_remove,1022 .driver.pm = &jmb38x_ms_pm_ops,1023};1024 1025module_pci_driver(jmb38x_ms_driver);1026 1027MODULE_AUTHOR("Alex Dubov");1028MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");1029MODULE_LICENSE("GPL");1030MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);1031