mpc52xx_lpbfifo.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /*
  2. * LocalPlus Bus FIFO driver for the Freescale MPC52xx.
  3. *
  4. * Copyright (C) 2009 Secret Lab Technologies Ltd.
  5. *
  6. * This file is released under the GPLv2
  7. *
  8. * Todo:
  9. * - Add support for multiple requests to be queued.
  10. */
  11. #include <linux/interrupt.h>
  12. #include <linux/kernel.h>
  13. #include <linux/of.h>
  14. #include <linux/of_platform.h>
  15. #include <linux/spinlock.h>
  16. #include <linux/module.h>
  17. #include <asm/io.h>
  18. #include <asm/prom.h>
  19. #include <asm/mpc52xx.h>
  20. #include <asm/time.h>
  21. #include <sysdev/bestcomm/bestcomm.h>
  22. #include <sysdev/bestcomm/bestcomm_priv.h>
  23. #include <sysdev/bestcomm/gen_bd.h>
  24. MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
  25. MODULE_DESCRIPTION("MPC5200 LocalPlus FIFO device driver");
  26. MODULE_LICENSE("GPL");
  27. #define LPBFIFO_REG_PACKET_SIZE (0x00)
  28. #define LPBFIFO_REG_START_ADDRESS (0x04)
  29. #define LPBFIFO_REG_CONTROL (0x08)
  30. #define LPBFIFO_REG_ENABLE (0x0C)
  31. #define LPBFIFO_REG_BYTES_DONE_STATUS (0x14)
  32. #define LPBFIFO_REG_FIFO_DATA (0x40)
  33. #define LPBFIFO_REG_FIFO_STATUS (0x44)
  34. #define LPBFIFO_REG_FIFO_CONTROL (0x48)
  35. #define LPBFIFO_REG_FIFO_ALARM (0x4C)
  36. struct mpc52xx_lpbfifo {
  37. struct device *dev;
  38. phys_addr_t regs_phys;
  39. void __iomem *regs;
  40. int irq;
  41. spinlock_t lock;
  42. struct bcom_task *bcom_tx_task;
  43. struct bcom_task *bcom_rx_task;
  44. struct bcom_task *bcom_cur_task;
  45. /* Current state data */
  46. struct mpc52xx_lpbfifo_request *req;
  47. int dma_irqs_enabled;
  48. };
  49. /* The MPC5200 has only one fifo, so only need one instance structure */
  50. static struct mpc52xx_lpbfifo lpbfifo;
  51. /**
  52. * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transferred
  53. */
  54. static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req)
  55. {
  56. size_t transfer_size = req->size - req->pos;
  57. struct bcom_bd *bd;
  58. void __iomem *reg;
  59. u32 *data;
  60. int i;
  61. int bit_fields;
  62. int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA);
  63. int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE;
  64. int poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA;
  65. /* Set and clear the reset bits; is good practice in User Manual */
  66. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000);
  67. /* set master enable bit */
  68. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000001);
  69. if (!dma) {
  70. /* While the FIFO can be setup for transfer sizes as large as
  71. * 16M-1, the FIFO itself is only 512 bytes deep and it does
  72. * not generate interrupts for FIFO full events (only transfer
  73. * complete will raise an IRQ). Therefore when not using
  74. * Bestcomm to drive the FIFO it needs to either be polled, or
  75. * transfers need to constrained to the size of the fifo.
  76. *
  77. * This driver restricts the size of the transfer
  78. */
  79. if (transfer_size > 512)
  80. transfer_size = 512;
  81. /* Load the FIFO with data */
  82. if (write) {
  83. reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA;
  84. data = req->data + req->pos;
  85. for (i = 0; i < transfer_size; i += 4)
  86. out_be32(reg, *data++);
  87. }
  88. /* Unmask both error and completion irqs */
  89. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000301);
  90. } else {
  91. /* Choose the correct direction
  92. *
  93. * Configure the watermarks so DMA will always complete correctly.
  94. * It may be worth experimenting with the ALARM value to see if
  95. * there is a performance impacit. However, if it is wrong there
  96. * is a risk of DMA not transferring the last chunk of data
  97. */
  98. if (write) {
  99. out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1e4);
  100. out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 7);
  101. lpbfifo.bcom_cur_task = lpbfifo.bcom_tx_task;
  102. } else {
  103. out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1ff);
  104. out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 0);
  105. lpbfifo.bcom_cur_task = lpbfifo.bcom_rx_task;
  106. if (poll_dma) {
  107. if (lpbfifo.dma_irqs_enabled) {
  108. disable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task));
  109. lpbfifo.dma_irqs_enabled = 0;
  110. }
  111. } else {
  112. if (!lpbfifo.dma_irqs_enabled) {
  113. enable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task));
  114. lpbfifo.dma_irqs_enabled = 1;
  115. }
  116. }
  117. }
  118. bd = bcom_prepare_next_buffer(lpbfifo.bcom_cur_task);
  119. bd->status = transfer_size;
  120. if (!write) {
  121. /*
  122. * In the DMA read case, the DMA doesn't complete,
  123. * possibly due to incorrect watermarks in the ALARM
  124. * and CONTROL regs. For now instead of trying to
  125. * determine the right watermarks that will make this
  126. * work, just increase the number of bytes the FIFO is
  127. * expecting.
  128. *
  129. * When submitting another operation, the FIFO will get
  130. * reset, so the condition of the FIFO waiting for a
  131. * non-existent 4 bytes will get cleared.
  132. */
  133. transfer_size += 4; /* BLECH! */
  134. }
  135. bd->data[0] = req->data_phys + req->pos;
  136. bcom_submit_next_buffer(lpbfifo.bcom_cur_task, NULL);
  137. /* error irq & master enabled bit */
  138. bit_fields = 0x00000201;
  139. /* Unmask irqs */
  140. if (write && (!poll_dma))
  141. bit_fields |= 0x00000100; /* completion irq too */
  142. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, bit_fields);
  143. }
  144. /* Set transfer size, width, chip select and READ mode */
  145. out_be32(lpbfifo.regs + LPBFIFO_REG_START_ADDRESS,
  146. req->offset + req->pos);
  147. out_be32(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, transfer_size);
  148. bit_fields = req->cs << 24 | 0x000008;
  149. if (!write)
  150. bit_fields |= 0x010000; /* read mode */
  151. out_be32(lpbfifo.regs + LPBFIFO_REG_CONTROL, bit_fields);
  152. /* Kick it off */
  153. out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01);
  154. if (dma)
  155. bcom_enable(lpbfifo.bcom_cur_task);
  156. }
  157. /**
  158. * mpc52xx_lpbfifo_irq - IRQ handler for LPB FIFO
  159. *
  160. * On transmit, the dma completion irq triggers before the fifo completion
  161. * triggers. Handle the dma completion here instead of the LPB FIFO Bestcomm
  162. * task completion irq because everything is not really done until the LPB FIFO
  163. * completion irq triggers.
  164. *
  165. * In other words:
  166. * For DMA, on receive, the "Fat Lady" is the bestcom completion irq. on
  167. * transmit, the fifo completion irq is the "Fat Lady". The opera (or in this
  168. * case the DMA/FIFO operation) is not finished until the "Fat Lady" sings.
  169. *
  170. * Reasons for entering this routine:
  171. * 1) PIO mode rx and tx completion irq
  172. * 2) DMA interrupt mode tx completion irq
  173. * 3) DMA polled mode tx
  174. *
  175. * Exit conditions:
  176. * 1) Transfer aborted
  177. * 2) FIFO complete without DMA; more data to do
  178. * 3) FIFO complete without DMA; all data transferred
  179. * 4) FIFO complete using DMA
  180. *
  181. * Condition 1 can occur regardless of whether or not DMA is used.
  182. * It requires executing the callback to report the error and exiting
  183. * immediately.
  184. *
  185. * Condition 2 requires programming the FIFO with the next block of data
  186. *
  187. * Condition 3 requires executing the callback to report completion
  188. *
  189. * Condition 4 means the same as 3, except that we also retrieve the bcom
  190. * buffer so DMA doesn't get clogged up.
  191. *
  192. * To make things trickier, the spinlock must be dropped before
  193. * executing the callback, otherwise we could end up with a deadlock
  194. * or nested spinlock condition. The out path is non-trivial, so
  195. * extra fiddling is done to make sure all paths lead to the same
  196. * outbound code.
  197. */
  198. static irqreturn_t mpc52xx_lpbfifo_irq(int irq, void *dev_id)
  199. {
  200. struct mpc52xx_lpbfifo_request *req;
  201. u32 status = in_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS);
  202. void __iomem *reg;
  203. u32 *data;
  204. int count, i;
  205. int do_callback = 0;
  206. u32 ts;
  207. unsigned long flags;
  208. int dma, write, poll_dma;
  209. spin_lock_irqsave(&lpbfifo.lock, flags);
  210. ts = get_tbl();
  211. req = lpbfifo.req;
  212. if (!req) {
  213. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  214. pr_err("bogus LPBFIFO IRQ\n");
  215. return IRQ_HANDLED;
  216. }
  217. dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA);
  218. write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE;
  219. poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA;
  220. if (dma && !write) {
  221. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  222. pr_err("bogus LPBFIFO IRQ (dma and not writting)\n");
  223. return IRQ_HANDLED;
  224. }
  225. if ((status & 0x01) == 0) {
  226. goto out;
  227. }
  228. /* check abort bit */
  229. if (status & 0x10) {
  230. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000);
  231. do_callback = 1;
  232. goto out;
  233. }
  234. /* Read result from hardware */
  235. count = in_be32(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS);
  236. count &= 0x00ffffff;
  237. if (!dma && !write) {
  238. /* copy the data out of the FIFO */
  239. reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA;
  240. data = req->data + req->pos;
  241. for (i = 0; i < count; i += 4)
  242. *data++ = in_be32(reg);
  243. }
  244. /* Update transfer position and count */
  245. req->pos += count;
  246. /* Decide what to do next */
  247. if (req->size - req->pos)
  248. mpc52xx_lpbfifo_kick(req); /* more work to do */
  249. else
  250. do_callback = 1;
  251. out:
  252. /* Clear the IRQ */
  253. out_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS, 0x01);
  254. if (dma && (status & 0x11)) {
  255. /*
  256. * Count the DMA as complete only when the FIFO completion
  257. * status or abort bits are set.
  258. *
  259. * (status & 0x01) should always be the case except sometimes
  260. * when using polled DMA.
  261. *
  262. * (status & 0x10) {transfer aborted}: This case needs more
  263. * testing.
  264. */
  265. bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL);
  266. }
  267. req->last_byte = ((u8 *)req->data)[req->size - 1];
  268. /* When the do_callback flag is set; it means the transfer is finished
  269. * so set the FIFO as idle */
  270. if (do_callback)
  271. lpbfifo.req = NULL;
  272. if (irq != 0) /* don't increment on polled case */
  273. req->irq_count++;
  274. req->irq_ticks += get_tbl() - ts;
  275. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  276. /* Spinlock is released; it is now safe to call the callback */
  277. if (do_callback && req->callback)
  278. req->callback(req);
  279. return IRQ_HANDLED;
  280. }
  281. /**
  282. * mpc52xx_lpbfifo_bcom_irq - IRQ handler for LPB FIFO Bestcomm task
  283. *
  284. * Only used when receiving data.
  285. */
  286. static irqreturn_t mpc52xx_lpbfifo_bcom_irq(int irq, void *dev_id)
  287. {
  288. struct mpc52xx_lpbfifo_request *req;
  289. unsigned long flags;
  290. u32 status;
  291. u32 ts;
  292. spin_lock_irqsave(&lpbfifo.lock, flags);
  293. ts = get_tbl();
  294. req = lpbfifo.req;
  295. if (!req || (req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA)) {
  296. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  297. return IRQ_HANDLED;
  298. }
  299. if (irq != 0) /* don't increment on polled case */
  300. req->irq_count++;
  301. if (!bcom_buffer_done(lpbfifo.bcom_cur_task)) {
  302. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  303. req->buffer_not_done_cnt++;
  304. if ((req->buffer_not_done_cnt % 1000) == 0)
  305. pr_err("transfer stalled\n");
  306. return IRQ_HANDLED;
  307. }
  308. bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL);
  309. req->last_byte = ((u8 *)req->data)[req->size - 1];
  310. req->pos = status & 0x00ffffff;
  311. /* Mark the FIFO as idle */
  312. lpbfifo.req = NULL;
  313. /* Release the lock before calling out to the callback. */
  314. req->irq_ticks += get_tbl() - ts;
  315. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  316. if (req->callback)
  317. req->callback(req);
  318. return IRQ_HANDLED;
  319. }
  320. /**
  321. * mpc52xx_lpbfifo_bcom_poll - Poll for DMA completion
  322. */
  323. void mpc52xx_lpbfifo_poll(void)
  324. {
  325. struct mpc52xx_lpbfifo_request *req = lpbfifo.req;
  326. int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA);
  327. int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE;
  328. /*
  329. * For more information, see comments on the "Fat Lady"
  330. */
  331. if (dma && write)
  332. mpc52xx_lpbfifo_irq(0, NULL);
  333. else
  334. mpc52xx_lpbfifo_bcom_irq(0, NULL);
  335. }
  336. EXPORT_SYMBOL(mpc52xx_lpbfifo_poll);
  337. /**
  338. * mpc52xx_lpbfifo_submit - Submit an LPB FIFO transfer request.
  339. * @req: Pointer to request structure
  340. */
  341. int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req)
  342. {
  343. unsigned long flags;
  344. if (!lpbfifo.regs)
  345. return -ENODEV;
  346. spin_lock_irqsave(&lpbfifo.lock, flags);
  347. /* If the req pointer is already set, then a transfer is in progress */
  348. if (lpbfifo.req) {
  349. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  350. return -EBUSY;
  351. }
  352. /* Setup the transfer */
  353. lpbfifo.req = req;
  354. req->irq_count = 0;
  355. req->irq_ticks = 0;
  356. req->buffer_not_done_cnt = 0;
  357. req->pos = 0;
  358. mpc52xx_lpbfifo_kick(req);
  359. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  360. return 0;
  361. }
  362. EXPORT_SYMBOL(mpc52xx_lpbfifo_submit);
  363. void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req)
  364. {
  365. unsigned long flags;
  366. spin_lock_irqsave(&lpbfifo.lock, flags);
  367. if (lpbfifo.req == req) {
  368. /* Put it into reset and clear the state */
  369. bcom_gen_bd_rx_reset(lpbfifo.bcom_rx_task);
  370. bcom_gen_bd_tx_reset(lpbfifo.bcom_tx_task);
  371. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000);
  372. lpbfifo.req = NULL;
  373. }
  374. spin_unlock_irqrestore(&lpbfifo.lock, flags);
  375. }
  376. EXPORT_SYMBOL(mpc52xx_lpbfifo_abort);
  377. static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op)
  378. {
  379. struct resource res;
  380. int rc = -ENOMEM;
  381. if (lpbfifo.dev != NULL)
  382. return -ENOSPC;
  383. lpbfifo.irq = irq_of_parse_and_map(op->dev.of_node, 0);
  384. if (!lpbfifo.irq)
  385. return -ENODEV;
  386. if (of_address_to_resource(op->dev.of_node, 0, &res))
  387. return -ENODEV;
  388. lpbfifo.regs_phys = res.start;
  389. lpbfifo.regs = of_iomap(op->dev.of_node, 0);
  390. if (!lpbfifo.regs)
  391. return -ENOMEM;
  392. spin_lock_init(&lpbfifo.lock);
  393. /* Put FIFO into reset */
  394. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000);
  395. /* Register the interrupt handler */
  396. rc = request_irq(lpbfifo.irq, mpc52xx_lpbfifo_irq, 0,
  397. "mpc52xx-lpbfifo", &lpbfifo);
  398. if (rc)
  399. goto err_irq;
  400. /* Request the Bestcomm receive (fifo --> memory) task and IRQ */
  401. lpbfifo.bcom_rx_task =
  402. bcom_gen_bd_rx_init(2, res.start + LPBFIFO_REG_FIFO_DATA,
  403. BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC,
  404. 16*1024*1024);
  405. if (!lpbfifo.bcom_rx_task)
  406. goto err_bcom_rx;
  407. rc = request_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task),
  408. mpc52xx_lpbfifo_bcom_irq, 0,
  409. "mpc52xx-lpbfifo-rx", &lpbfifo);
  410. if (rc)
  411. goto err_bcom_rx_irq;
  412. lpbfifo.dma_irqs_enabled = 1;
  413. /* Request the Bestcomm transmit (memory --> fifo) task and IRQ */
  414. lpbfifo.bcom_tx_task =
  415. bcom_gen_bd_tx_init(2, res.start + LPBFIFO_REG_FIFO_DATA,
  416. BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC);
  417. if (!lpbfifo.bcom_tx_task)
  418. goto err_bcom_tx;
  419. lpbfifo.dev = &op->dev;
  420. return 0;
  421. err_bcom_tx:
  422. free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo);
  423. err_bcom_rx_irq:
  424. bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task);
  425. err_bcom_rx:
  426. err_irq:
  427. iounmap(lpbfifo.regs);
  428. lpbfifo.regs = NULL;
  429. dev_err(&op->dev, "mpc52xx_lpbfifo_probe() failed\n");
  430. return -ENODEV;
  431. }
  432. static int __devexit mpc52xx_lpbfifo_remove(struct platform_device *op)
  433. {
  434. if (lpbfifo.dev != &op->dev)
  435. return 0;
  436. /* Put FIFO in reset */
  437. out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000);
  438. /* Release the bestcomm transmit task */
  439. free_irq(bcom_get_task_irq(lpbfifo.bcom_tx_task), &lpbfifo);
  440. bcom_gen_bd_tx_release(lpbfifo.bcom_tx_task);
  441. /* Release the bestcomm receive task */
  442. free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo);
  443. bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task);
  444. free_irq(lpbfifo.irq, &lpbfifo);
  445. iounmap(lpbfifo.regs);
  446. lpbfifo.regs = NULL;
  447. lpbfifo.dev = NULL;
  448. return 0;
  449. }
  450. static struct of_device_id mpc52xx_lpbfifo_match[] __devinitconst = {
  451. { .compatible = "fsl,mpc5200-lpbfifo", },
  452. {},
  453. };
  454. static struct platform_driver mpc52xx_lpbfifo_driver = {
  455. .driver = {
  456. .name = "mpc52xx-lpbfifo",
  457. .owner = THIS_MODULE,
  458. .of_match_table = mpc52xx_lpbfifo_match,
  459. },
  460. .probe = mpc52xx_lpbfifo_probe,
  461. .remove = __devexit_p(mpc52xx_lpbfifo_remove),
  462. };
  463. /***********************************************************************
  464. * Module init/exit
  465. */
  466. static int __init mpc52xx_lpbfifo_init(void)
  467. {
  468. return platform_driver_register(&mpc52xx_lpbfifo_driver);
  469. }
  470. module_init(mpc52xx_lpbfifo_init);
  471. static void __exit mpc52xx_lpbfifo_exit(void)
  472. {
  473. platform_driver_unregister(&mpc52xx_lpbfifo_driver);
  474. }
  475. module_exit(mpc52xx_lpbfifo_exit);