jmb38x_ms.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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. #include <linux/spinlock.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/pci.h>
  14. #include <linux/delay.h>
  15. #include <linux/highmem.h>
  16. #include <linux/memstick.h>
  17. #define DRIVER_NAME "jmb38x_ms"
  18. static int no_dma;
  19. module_param(no_dma, bool, 0644);
  20. enum {
  21. DMA_ADDRESS = 0x00,
  22. BLOCK = 0x04,
  23. DMA_CONTROL = 0x08,
  24. TPC_P0 = 0x0c,
  25. TPC_P1 = 0x10,
  26. TPC = 0x14,
  27. HOST_CONTROL = 0x18,
  28. DATA = 0x1c,
  29. STATUS = 0x20,
  30. INT_STATUS = 0x24,
  31. INT_STATUS_ENABLE = 0x28,
  32. INT_SIGNAL_ENABLE = 0x2c,
  33. TIMER = 0x30,
  34. TIMER_CONTROL = 0x34,
  35. PAD_OUTPUT_ENABLE = 0x38,
  36. PAD_PU_PD = 0x3c,
  37. CLOCK_DELAY = 0x40,
  38. ADMA_ADDRESS = 0x44,
  39. CLOCK_CONTROL = 0x48,
  40. LED_CONTROL = 0x4c,
  41. VERSION = 0x50
  42. };
  43. struct jmb38x_ms_host {
  44. struct jmb38x_ms *chip;
  45. void __iomem *addr;
  46. spinlock_t lock;
  47. int id;
  48. char host_id[DEVICE_ID_SIZE];
  49. int irq;
  50. unsigned int block_pos;
  51. unsigned long timeout_jiffies;
  52. struct timer_list timer;
  53. struct memstick_request *req;
  54. unsigned char eject:1,
  55. use_dma:1;
  56. unsigned char cmd_flags;
  57. unsigned char io_pos;
  58. unsigned int io_word[2];
  59. };
  60. struct jmb38x_ms {
  61. struct pci_dev *pdev;
  62. int host_cnt;
  63. struct memstick_host *hosts[];
  64. };
  65. #define BLOCK_COUNT_MASK 0xffff0000
  66. #define BLOCK_SIZE_MASK 0x00000fff
  67. #define DMA_CONTROL_ENABLE 0x00000001
  68. #define TPC_DATA_SEL 0x00008000
  69. #define TPC_DIR 0x00004000
  70. #define TPC_WAIT_INT 0x00002000
  71. #define TPC_GET_INT 0x00000800
  72. #define TPC_CODE_SZ_MASK 0x00000700
  73. #define TPC_DATA_SZ_MASK 0x00000007
  74. #define HOST_CONTROL_RESET_REQ 0x00008000
  75. #define HOST_CONTROL_REI 0x00004000
  76. #define HOST_CONTROL_LED 0x00000400
  77. #define HOST_CONTROL_FAST_CLK 0x00000200
  78. #define HOST_CONTROL_RESET 0x00000100
  79. #define HOST_CONTROL_POWER_EN 0x00000080
  80. #define HOST_CONTROL_CLOCK_EN 0x00000040
  81. #define HOST_CONTROL_IF_SHIFT 4
  82. #define HOST_CONTROL_IF_SERIAL 0x0
  83. #define HOST_CONTROL_IF_PAR4 0x1
  84. #define HOST_CONTROL_IF_PAR8 0x3
  85. #define STATUS_HAS_MEDIA 0x00000400
  86. #define STATUS_FIFO_EMPTY 0x00000200
  87. #define STATUS_FIFO_FULL 0x00000100
  88. #define INT_STATUS_TPC_ERR 0x00080000
  89. #define INT_STATUS_CRC_ERR 0x00040000
  90. #define INT_STATUS_TIMER_TO 0x00020000
  91. #define INT_STATUS_HSK_TO 0x00010000
  92. #define INT_STATUS_ANY_ERR 0x00008000
  93. #define INT_STATUS_FIFO_WRDY 0x00000080
  94. #define INT_STATUS_FIFO_RRDY 0x00000040
  95. #define INT_STATUS_MEDIA_OUT 0x00000010
  96. #define INT_STATUS_MEDIA_IN 0x00000008
  97. #define INT_STATUS_DMA_BOUNDARY 0x00000004
  98. #define INT_STATUS_EOTRAN 0x00000002
  99. #define INT_STATUS_EOTPC 0x00000001
  100. #define INT_STATUS_ALL 0x000f801f
  101. #define PAD_OUTPUT_ENABLE_MS 0x0F3F
  102. #define PAD_PU_PD_OFF 0x7FFF0000
  103. #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
  104. #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
  105. enum {
  106. CMD_READY = 0x01,
  107. FIFO_READY = 0x02,
  108. REG_DATA = 0x04,
  109. AUTO_GET_INT = 0x08
  110. };
  111. static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,
  112. unsigned char *buf, unsigned int length)
  113. {
  114. unsigned int off = 0;
  115. while (host->io_pos && length) {
  116. buf[off++] = host->io_word[0] & 0xff;
  117. host->io_word[0] >>= 8;
  118. length--;
  119. host->io_pos--;
  120. }
  121. if (!length)
  122. return off;
  123. while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
  124. if (length < 4)
  125. break;
  126. *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);
  127. length -= 4;
  128. off += 4;
  129. }
  130. if (length
  131. && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
  132. host->io_word[0] = readl(host->addr + DATA);
  133. for (host->io_pos = 4; host->io_pos; --host->io_pos) {
  134. buf[off++] = host->io_word[0] & 0xff;
  135. host->io_word[0] >>= 8;
  136. length--;
  137. if (!length)
  138. break;
  139. }
  140. }
  141. return off;
  142. }
  143. static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host,
  144. unsigned char *buf,
  145. unsigned int length)
  146. {
  147. unsigned int off = 0;
  148. while (host->io_pos > 4 && length) {
  149. buf[off++] = host->io_word[0] & 0xff;
  150. host->io_word[0] >>= 8;
  151. length--;
  152. host->io_pos--;
  153. }
  154. if (!length)
  155. return off;
  156. while (host->io_pos && length) {
  157. buf[off++] = host->io_word[1] & 0xff;
  158. host->io_word[1] >>= 8;
  159. length--;
  160. host->io_pos--;
  161. }
  162. return off;
  163. }
  164. static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host,
  165. unsigned char *buf,
  166. unsigned int length)
  167. {
  168. unsigned int off = 0;
  169. if (host->io_pos) {
  170. while (host->io_pos < 4 && length) {
  171. host->io_word[0] |= buf[off++] << (host->io_pos * 8);
  172. host->io_pos++;
  173. length--;
  174. }
  175. }
  176. if (host->io_pos == 4
  177. && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
  178. writel(host->io_word[0], host->addr + DATA);
  179. host->io_pos = 0;
  180. host->io_word[0] = 0;
  181. } else if (host->io_pos) {
  182. return off;
  183. }
  184. if (!length)
  185. return off;
  186. while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
  187. if (length < 4)
  188. break;
  189. __raw_writel(*(unsigned int *)(buf + off),
  190. host->addr + DATA);
  191. length -= 4;
  192. off += 4;
  193. }
  194. switch (length) {
  195. case 3:
  196. host->io_word[0] |= buf[off + 2] << 16;
  197. host->io_pos++;
  198. case 2:
  199. host->io_word[0] |= buf[off + 1] << 8;
  200. host->io_pos++;
  201. case 1:
  202. host->io_word[0] |= buf[off];
  203. host->io_pos++;
  204. }
  205. off += host->io_pos;
  206. return off;
  207. }
  208. static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host,
  209. unsigned char *buf,
  210. unsigned int length)
  211. {
  212. unsigned int off = 0;
  213. while (host->io_pos < 4 && length) {
  214. host->io_word[0] &= ~(0xff << (host->io_pos * 8));
  215. host->io_word[0] |= buf[off++] << (host->io_pos * 8);
  216. host->io_pos++;
  217. length--;
  218. }
  219. if (!length)
  220. return off;
  221. while (host->io_pos < 8 && length) {
  222. host->io_word[1] &= ~(0xff << (host->io_pos * 8));
  223. host->io_word[1] |= buf[off++] << (host->io_pos * 8);
  224. host->io_pos++;
  225. length--;
  226. }
  227. return off;
  228. }
  229. static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
  230. {
  231. unsigned int length;
  232. unsigned int off;
  233. unsigned int t_size, p_off, p_cnt;
  234. unsigned char *buf;
  235. struct page *pg;
  236. unsigned long flags = 0;
  237. if (host->req->long_data) {
  238. length = host->req->sg.length - host->block_pos;
  239. off = host->req->sg.offset + host->block_pos;
  240. } else {
  241. length = host->req->data_len - host->block_pos;
  242. off = 0;
  243. }
  244. while (length) {
  245. if (host->req->long_data) {
  246. pg = nth_page(sg_page(&host->req->sg),
  247. off >> PAGE_SHIFT);
  248. p_off = offset_in_page(off);
  249. p_cnt = PAGE_SIZE - p_off;
  250. p_cnt = min(p_cnt, length);
  251. local_irq_save(flags);
  252. buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
  253. } else {
  254. buf = host->req->data + host->block_pos;
  255. p_cnt = host->req->data_len - host->block_pos;
  256. }
  257. if (host->req->data_dir == WRITE)
  258. t_size = !(host->cmd_flags & REG_DATA)
  259. ? jmb38x_ms_write_data(host, buf, p_cnt)
  260. : jmb38x_ms_write_reg_data(host, buf, p_cnt);
  261. else
  262. t_size = !(host->cmd_flags & REG_DATA)
  263. ? jmb38x_ms_read_data(host, buf, p_cnt)
  264. : jmb38x_ms_read_reg_data(host, buf, p_cnt);
  265. if (host->req->long_data) {
  266. kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
  267. local_irq_restore(flags);
  268. }
  269. if (!t_size)
  270. break;
  271. host->block_pos += t_size;
  272. length -= t_size;
  273. off += t_size;
  274. }
  275. if (!length && host->req->data_dir == WRITE) {
  276. if (host->cmd_flags & REG_DATA) {
  277. writel(host->io_word[0], host->addr + TPC_P0);
  278. writel(host->io_word[1], host->addr + TPC_P1);
  279. } else if (host->io_pos) {
  280. writel(host->io_word[0], host->addr + DATA);
  281. }
  282. }
  283. return length;
  284. }
  285. static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
  286. {
  287. struct jmb38x_ms_host *host = memstick_priv(msh);
  288. unsigned char *data;
  289. unsigned int data_len, cmd, t_val;
  290. if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
  291. dev_dbg(msh->cdev.dev, "no media status\n");
  292. host->req->error = -ETIME;
  293. return host->req->error;
  294. }
  295. dev_dbg(msh->cdev.dev, "control %08x\n",
  296. readl(host->addr + HOST_CONTROL));
  297. dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS));
  298. dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS));
  299. host->cmd_flags = 0;
  300. host->block_pos = 0;
  301. host->io_pos = 0;
  302. host->io_word[0] = 0;
  303. host->io_word[1] = 0;
  304. cmd = host->req->tpc << 16;
  305. cmd |= TPC_DATA_SEL;
  306. if (host->req->data_dir == READ)
  307. cmd |= TPC_DIR;
  308. if (host->req->need_card_int)
  309. cmd |= TPC_WAIT_INT;
  310. if (host->req->get_int_reg)
  311. cmd |= TPC_GET_INT;
  312. data = host->req->data;
  313. host->use_dma = !no_dma;
  314. if (host->req->long_data) {
  315. data_len = host->req->sg.length;
  316. } else {
  317. data_len = host->req->data_len;
  318. host->use_dma = 0;
  319. }
  320. if (data_len <= 8) {
  321. cmd &= ~(TPC_DATA_SEL | 0xf);
  322. host->cmd_flags |= REG_DATA;
  323. cmd |= data_len & 0xf;
  324. host->use_dma = 0;
  325. }
  326. if (host->use_dma) {
  327. if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
  328. host->req->data_dir == READ
  329. ? PCI_DMA_FROMDEVICE
  330. : PCI_DMA_TODEVICE)) {
  331. host->req->error = -ENOMEM;
  332. return host->req->error;
  333. }
  334. data_len = sg_dma_len(&host->req->sg);
  335. writel(sg_dma_address(&host->req->sg),
  336. host->addr + DMA_ADDRESS);
  337. writel(((1 << 16) & BLOCK_COUNT_MASK)
  338. | (data_len & BLOCK_SIZE_MASK),
  339. host->addr + BLOCK);
  340. writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);
  341. } else if (!(host->cmd_flags & REG_DATA)) {
  342. writel(((1 << 16) & BLOCK_COUNT_MASK)
  343. | (data_len & BLOCK_SIZE_MASK),
  344. host->addr + BLOCK);
  345. t_val = readl(host->addr + INT_STATUS_ENABLE);
  346. t_val |= host->req->data_dir == READ
  347. ? INT_STATUS_FIFO_RRDY
  348. : INT_STATUS_FIFO_WRDY;
  349. writel(t_val, host->addr + INT_STATUS_ENABLE);
  350. writel(t_val, host->addr + INT_SIGNAL_ENABLE);
  351. } else {
  352. cmd &= ~(TPC_DATA_SEL | 0xf);
  353. host->cmd_flags |= REG_DATA;
  354. cmd |= data_len & 0xf;
  355. if (host->req->data_dir == WRITE) {
  356. jmb38x_ms_transfer_data(host);
  357. writel(host->io_word[0], host->addr + TPC_P0);
  358. writel(host->io_word[1], host->addr + TPC_P1);
  359. }
  360. }
  361. mod_timer(&host->timer, jiffies + host->timeout_jiffies);
  362. writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),
  363. host->addr + HOST_CONTROL);
  364. host->req->error = 0;
  365. writel(cmd, host->addr + TPC);
  366. dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len);
  367. return 0;
  368. }
  369. static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
  370. {
  371. struct jmb38x_ms_host *host = memstick_priv(msh);
  372. unsigned int t_val = 0;
  373. int rc;
  374. del_timer(&host->timer);
  375. dev_dbg(msh->cdev.dev, "c control %08x\n",
  376. readl(host->addr + HOST_CONTROL));
  377. dev_dbg(msh->cdev.dev, "c status %08x\n",
  378. readl(host->addr + INT_STATUS));
  379. dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
  380. if (host->req->get_int_reg) {
  381. t_val = readl(host->addr + TPC_P0);
  382. host->req->int_reg = (t_val & 0xff);
  383. }
  384. if (host->use_dma) {
  385. writel(0, host->addr + DMA_CONTROL);
  386. pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
  387. host->req->data_dir == READ
  388. ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
  389. } else {
  390. t_val = readl(host->addr + INT_STATUS_ENABLE);
  391. if (host->req->data_dir == READ)
  392. t_val &= ~INT_STATUS_FIFO_RRDY;
  393. else
  394. t_val &= ~INT_STATUS_FIFO_WRDY;
  395. writel(t_val, host->addr + INT_STATUS_ENABLE);
  396. writel(t_val, host->addr + INT_SIGNAL_ENABLE);
  397. }
  398. writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),
  399. host->addr + HOST_CONTROL);
  400. if (!last) {
  401. do {
  402. rc = memstick_next_req(msh, &host->req);
  403. } while (!rc && jmb38x_ms_issue_cmd(msh));
  404. } else {
  405. do {
  406. rc = memstick_next_req(msh, &host->req);
  407. if (!rc)
  408. host->req->error = -ETIME;
  409. } while (!rc);
  410. }
  411. }
  412. static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)
  413. {
  414. struct memstick_host *msh = dev_id;
  415. struct jmb38x_ms_host *host = memstick_priv(msh);
  416. unsigned int irq_status;
  417. spin_lock(&host->lock);
  418. irq_status = readl(host->addr + INT_STATUS);
  419. dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status);
  420. if (irq_status == 0 || irq_status == (~0)) {
  421. spin_unlock(&host->lock);
  422. return IRQ_NONE;
  423. }
  424. if (host->req) {
  425. if (irq_status & INT_STATUS_ANY_ERR) {
  426. if (irq_status & INT_STATUS_CRC_ERR)
  427. host->req->error = -EILSEQ;
  428. else
  429. host->req->error = -ETIME;
  430. } else {
  431. if (host->use_dma) {
  432. if (irq_status & INT_STATUS_EOTRAN)
  433. host->cmd_flags |= FIFO_READY;
  434. } else {
  435. if (irq_status & (INT_STATUS_FIFO_RRDY
  436. | INT_STATUS_FIFO_WRDY))
  437. jmb38x_ms_transfer_data(host);
  438. if (irq_status & INT_STATUS_EOTRAN) {
  439. jmb38x_ms_transfer_data(host);
  440. host->cmd_flags |= FIFO_READY;
  441. }
  442. }
  443. if (irq_status & INT_STATUS_EOTPC) {
  444. host->cmd_flags |= CMD_READY;
  445. if (host->cmd_flags & REG_DATA) {
  446. if (host->req->data_dir == READ) {
  447. host->io_word[0]
  448. = readl(host->addr
  449. + TPC_P0);
  450. host->io_word[1]
  451. = readl(host->addr
  452. + TPC_P1);
  453. host->io_pos = 8;
  454. jmb38x_ms_transfer_data(host);
  455. }
  456. host->cmd_flags |= FIFO_READY;
  457. }
  458. }
  459. }
  460. }
  461. if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) {
  462. dev_dbg(&host->chip->pdev->dev, "media changed\n");
  463. memstick_detect_change(msh);
  464. }
  465. writel(irq_status, host->addr + INT_STATUS);
  466. if (host->req
  467. && (((host->cmd_flags & CMD_READY)
  468. && (host->cmd_flags & FIFO_READY))
  469. || host->req->error))
  470. jmb38x_ms_complete_cmd(msh, 0);
  471. spin_unlock(&host->lock);
  472. return IRQ_HANDLED;
  473. }
  474. static void jmb38x_ms_abort(unsigned long data)
  475. {
  476. struct memstick_host *msh = (struct memstick_host *)data;
  477. struct jmb38x_ms_host *host = memstick_priv(msh);
  478. unsigned long flags;
  479. dev_dbg(&host->chip->pdev->dev, "abort\n");
  480. spin_lock_irqsave(&host->lock, flags);
  481. if (host->req) {
  482. host->req->error = -ETIME;
  483. jmb38x_ms_complete_cmd(msh, 0);
  484. }
  485. spin_unlock_irqrestore(&host->lock, flags);
  486. }
  487. static void jmb38x_ms_request(struct memstick_host *msh)
  488. {
  489. struct jmb38x_ms_host *host = memstick_priv(msh);
  490. unsigned long flags;
  491. int rc;
  492. spin_lock_irqsave(&host->lock, flags);
  493. if (host->req) {
  494. spin_unlock_irqrestore(&host->lock, flags);
  495. BUG();
  496. return;
  497. }
  498. do {
  499. rc = memstick_next_req(msh, &host->req);
  500. } while (!rc && jmb38x_ms_issue_cmd(msh));
  501. spin_unlock_irqrestore(&host->lock, flags);
  502. }
  503. static void jmb38x_ms_reset(struct jmb38x_ms_host *host)
  504. {
  505. unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
  506. writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET,
  507. host->addr + HOST_CONTROL);
  508. while (HOST_CONTROL_RESET_REQ
  509. & (host_ctl = readl(host->addr + HOST_CONTROL))) {
  510. ndelay(100);
  511. dev_dbg(&host->chip->pdev->dev, "reset\n");
  512. }
  513. writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
  514. writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
  515. dev_dbg(&host->chip->pdev->dev, "reset\n");
  516. }
  517. static void jmb38x_ms_set_param(struct memstick_host *msh,
  518. enum memstick_param param,
  519. int value)
  520. {
  521. struct jmb38x_ms_host *host = memstick_priv(msh);
  522. unsigned int host_ctl;
  523. unsigned long flags;
  524. spin_lock_irqsave(&host->lock, flags);
  525. switch (param) {
  526. case MEMSTICK_POWER:
  527. if (value == MEMSTICK_POWER_ON) {
  528. jmb38x_ms_reset(host);
  529. writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
  530. : PAD_PU_PD_ON_MS_SOCK0,
  531. host->addr + PAD_PU_PD);
  532. writel(PAD_OUTPUT_ENABLE_MS,
  533. host->addr + PAD_OUTPUT_ENABLE);
  534. host_ctl = readl(host->addr + HOST_CONTROL);
  535. host_ctl |= 7;
  536. writel(host_ctl | (HOST_CONTROL_POWER_EN
  537. | HOST_CONTROL_CLOCK_EN),
  538. host->addr + HOST_CONTROL);
  539. dev_dbg(&host->chip->pdev->dev, "power on\n");
  540. } else if (value == MEMSTICK_POWER_OFF) {
  541. writel(readl(host->addr + HOST_CONTROL)
  542. & ~(HOST_CONTROL_POWER_EN
  543. | HOST_CONTROL_CLOCK_EN),
  544. host->addr + HOST_CONTROL);
  545. writel(0, host->addr + PAD_OUTPUT_ENABLE);
  546. writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
  547. dev_dbg(&host->chip->pdev->dev, "power off\n");
  548. }
  549. break;
  550. case MEMSTICK_INTERFACE:
  551. /* jmb38x_ms_reset(host); */
  552. host_ctl = readl(host->addr + HOST_CONTROL);
  553. host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
  554. /* host_ctl |= 7; */
  555. if (value == MEMSTICK_SERIAL) {
  556. host_ctl &= ~HOST_CONTROL_FAST_CLK;
  557. host_ctl |= HOST_CONTROL_IF_SERIAL
  558. << HOST_CONTROL_IF_SHIFT;
  559. host_ctl |= HOST_CONTROL_REI;
  560. writel(0, host->addr + CLOCK_DELAY);
  561. } else if (value == MEMSTICK_PAR4) {
  562. host_ctl |= HOST_CONTROL_FAST_CLK;
  563. host_ctl |= HOST_CONTROL_IF_PAR4
  564. << HOST_CONTROL_IF_SHIFT;
  565. host_ctl &= ~HOST_CONTROL_REI;
  566. writel(4, host->addr + CLOCK_DELAY);
  567. } else if (value == MEMSTICK_PAR8) {
  568. host_ctl |= HOST_CONTROL_FAST_CLK;
  569. host_ctl |= HOST_CONTROL_IF_PAR8
  570. << HOST_CONTROL_IF_SHIFT;
  571. host_ctl &= ~HOST_CONTROL_REI;
  572. writel(4, host->addr + CLOCK_DELAY);
  573. }
  574. writel(host_ctl, host->addr + HOST_CONTROL);
  575. break;
  576. };
  577. spin_unlock_irqrestore(&host->lock, flags);
  578. }
  579. #ifdef CONFIG_PM
  580. static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state)
  581. {
  582. struct jmb38x_ms *jm = pci_get_drvdata(dev);
  583. int cnt;
  584. for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
  585. if (!jm->hosts[cnt])
  586. break;
  587. memstick_suspend_host(jm->hosts[cnt]);
  588. }
  589. pci_save_state(dev);
  590. pci_enable_wake(dev, pci_choose_state(dev, state), 0);
  591. pci_disable_device(dev);
  592. pci_set_power_state(dev, pci_choose_state(dev, state));
  593. return 0;
  594. }
  595. static int jmb38x_ms_resume(struct pci_dev *dev)
  596. {
  597. struct jmb38x_ms *jm = pci_get_drvdata(dev);
  598. int rc;
  599. pci_set_power_state(dev, PCI_D0);
  600. pci_restore_state(dev);
  601. rc = pci_enable_device(dev);
  602. if (rc)
  603. return rc;
  604. pci_set_master(dev);
  605. pci_read_config_dword(dev, 0xac, &rc);
  606. pci_write_config_dword(dev, 0xac, rc | 0x00470000);
  607. for (rc = 0; rc < jm->host_cnt; ++rc) {
  608. if (!jm->hosts[rc])
  609. break;
  610. memstick_resume_host(jm->hosts[rc]);
  611. memstick_detect_change(jm->hosts[rc]);
  612. }
  613. return 0;
  614. }
  615. #else
  616. #define jmb38x_ms_suspend NULL
  617. #define jmb38x_ms_resume NULL
  618. #endif /* CONFIG_PM */
  619. static int jmb38x_ms_count_slots(struct pci_dev *pdev)
  620. {
  621. int cnt, rc = 0;
  622. for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) {
  623. if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt)))
  624. break;
  625. if (256 != pci_resource_len(pdev, cnt))
  626. break;
  627. ++rc;
  628. }
  629. return rc;
  630. }
  631. static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
  632. {
  633. struct memstick_host *msh;
  634. struct jmb38x_ms_host *host;
  635. msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host),
  636. &jm->pdev->dev);
  637. if (!msh)
  638. return NULL;
  639. host = memstick_priv(msh);
  640. host->chip = jm;
  641. host->addr = ioremap(pci_resource_start(jm->pdev, cnt),
  642. pci_resource_len(jm->pdev, cnt));
  643. if (!host->addr)
  644. goto err_out_free;
  645. spin_lock_init(&host->lock);
  646. host->id = cnt;
  647. snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
  648. host->id);
  649. host->irq = jm->pdev->irq;
  650. host->timeout_jiffies = msecs_to_jiffies(4000);
  651. msh->request = jmb38x_ms_request;
  652. msh->set_param = jmb38x_ms_set_param;
  653. /*
  654. msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4
  655. | MEMSTICK_CAP_PAR8;
  656. */
  657. msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
  658. setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh);
  659. if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id,
  660. msh))
  661. return msh;
  662. iounmap(host->addr);
  663. err_out_free:
  664. kfree(msh);
  665. return NULL;
  666. }
  667. static void jmb38x_ms_free_host(struct memstick_host *msh)
  668. {
  669. struct jmb38x_ms_host *host = memstick_priv(msh);
  670. free_irq(host->irq, msh);
  671. iounmap(host->addr);
  672. memstick_free_host(msh);
  673. }
  674. static int jmb38x_ms_probe(struct pci_dev *pdev,
  675. const struct pci_device_id *dev_id)
  676. {
  677. struct jmb38x_ms *jm;
  678. int pci_dev_busy = 0;
  679. int rc, cnt;
  680. rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
  681. if (rc)
  682. return rc;
  683. rc = pci_enable_device(pdev);
  684. if (rc)
  685. return rc;
  686. pci_set_master(pdev);
  687. rc = pci_request_regions(pdev, DRIVER_NAME);
  688. if (rc) {
  689. pci_dev_busy = 1;
  690. goto err_out;
  691. }
  692. pci_read_config_dword(pdev, 0xac, &rc);
  693. pci_write_config_dword(pdev, 0xac, rc | 0x00470000);
  694. cnt = jmb38x_ms_count_slots(pdev);
  695. if (!cnt) {
  696. rc = -ENODEV;
  697. pci_dev_busy = 1;
  698. goto err_out;
  699. }
  700. jm = kzalloc(sizeof(struct jmb38x_ms)
  701. + cnt * sizeof(struct memstick_host *), GFP_KERNEL);
  702. if (!jm) {
  703. rc = -ENOMEM;
  704. goto err_out_int;
  705. }
  706. jm->pdev = pdev;
  707. jm->host_cnt = cnt;
  708. pci_set_drvdata(pdev, jm);
  709. for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
  710. jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt);
  711. if (!jm->hosts[cnt])
  712. break;
  713. rc = memstick_add_host(jm->hosts[cnt]);
  714. if (rc) {
  715. jmb38x_ms_free_host(jm->hosts[cnt]);
  716. jm->hosts[cnt] = NULL;
  717. break;
  718. }
  719. }
  720. if (cnt)
  721. return 0;
  722. rc = -ENODEV;
  723. pci_set_drvdata(pdev, NULL);
  724. kfree(jm);
  725. err_out_int:
  726. pci_release_regions(pdev);
  727. err_out:
  728. if (!pci_dev_busy)
  729. pci_disable_device(pdev);
  730. return rc;
  731. }
  732. static void jmb38x_ms_remove(struct pci_dev *dev)
  733. {
  734. struct jmb38x_ms *jm = pci_get_drvdata(dev);
  735. struct jmb38x_ms_host *host;
  736. int cnt;
  737. unsigned long flags;
  738. for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
  739. if (!jm->hosts[cnt])
  740. break;
  741. host = memstick_priv(jm->hosts[cnt]);
  742. writel(0, host->addr + INT_SIGNAL_ENABLE);
  743. writel(0, host->addr + INT_STATUS_ENABLE);
  744. mmiowb();
  745. dev_dbg(&jm->pdev->dev, "interrupts off\n");
  746. spin_lock_irqsave(&host->lock, flags);
  747. if (host->req) {
  748. host->req->error = -ETIME;
  749. jmb38x_ms_complete_cmd(jm->hosts[cnt], 1);
  750. }
  751. spin_unlock_irqrestore(&host->lock, flags);
  752. memstick_remove_host(jm->hosts[cnt]);
  753. dev_dbg(&jm->pdev->dev, "host removed\n");
  754. jmb38x_ms_free_host(jm->hosts[cnt]);
  755. }
  756. pci_set_drvdata(dev, NULL);
  757. pci_release_regions(dev);
  758. pci_disable_device(dev);
  759. kfree(jm);
  760. }
  761. static struct pci_device_id jmb38x_ms_id_tbl [] = {
  762. { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID,
  763. PCI_ANY_ID, 0, 0, 0 },
  764. { }
  765. };
  766. static struct pci_driver jmb38x_ms_driver = {
  767. .name = DRIVER_NAME,
  768. .id_table = jmb38x_ms_id_tbl,
  769. .probe = jmb38x_ms_probe,
  770. .remove = jmb38x_ms_remove,
  771. .suspend = jmb38x_ms_suspend,
  772. .resume = jmb38x_ms_resume
  773. };
  774. static int __init jmb38x_ms_init(void)
  775. {
  776. return pci_register_driver(&jmb38x_ms_driver);
  777. }
  778. static void __exit jmb38x_ms_exit(void)
  779. {
  780. pci_unregister_driver(&jmb38x_ms_driver);
  781. }
  782. MODULE_AUTHOR("Alex Dubov");
  783. MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");
  784. MODULE_LICENSE("GPL");
  785. MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);
  786. module_init(jmb38x_ms_init);
  787. module_exit(jmb38x_ms_exit);