fifo.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. * Renesas USB driver
  3. *
  4. * Copyright (C) 2011 Renesas Solutions Corp.
  5. * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. *
  16. */
  17. #include <linux/delay.h>
  18. #include <linux/io.h>
  19. #include "./common.h"
  20. #include "./pipe.h"
  21. /*
  22. * packet info function
  23. */
  24. static int usbhsf_null_handle(struct usbhs_pkt *pkt)
  25. {
  26. struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe);
  27. struct device *dev = usbhs_priv_to_dev(priv);
  28. dev_err(dev, "null handler\n");
  29. return -EINVAL;
  30. }
  31. static struct usbhs_pkt_handle usbhsf_null_handler = {
  32. .prepare = usbhsf_null_handle,
  33. .try_run = usbhsf_null_handle,
  34. };
  35. void usbhs_pkt_init(struct usbhs_pkt *pkt)
  36. {
  37. INIT_LIST_HEAD(&pkt->node);
  38. }
  39. void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
  40. struct usbhs_pkt_handle *handler,
  41. void *buf, int len, int zero)
  42. {
  43. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  44. struct device *dev = usbhs_priv_to_dev(priv);
  45. if (!handler) {
  46. dev_err(dev, "no handler function\n");
  47. handler = &usbhsf_null_handler;
  48. }
  49. list_del_init(&pkt->node);
  50. list_add_tail(&pkt->node, &pipe->list);
  51. pkt->pipe = pipe;
  52. pkt->buf = buf;
  53. pkt->handler = handler;
  54. pkt->length = len;
  55. pkt->zero = zero;
  56. pkt->actual = 0;
  57. }
  58. void usbhs_pkt_pop(struct usbhs_pkt *pkt)
  59. {
  60. list_del_init(&pkt->node);
  61. }
  62. struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe)
  63. {
  64. if (list_empty(&pipe->list))
  65. return NULL;
  66. return list_entry(pipe->list.next, struct usbhs_pkt, node);
  67. }
  68. /*
  69. * irq enable/disable function
  70. */
  71. #define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
  72. #define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
  73. #define usbhsf_irq_callback_ctrl(pipe, status, enable) \
  74. ({ \
  75. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \
  76. struct usbhs_mod *mod = usbhs_mod_get_current(priv); \
  77. u16 status = (1 << usbhs_pipe_number(pipe)); \
  78. if (!mod) \
  79. return; \
  80. if (enable) \
  81. mod->irq_##status |= status; \
  82. else \
  83. mod->irq_##status &= ~status; \
  84. usbhs_irq_callback_update(priv, mod); \
  85. })
  86. static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
  87. {
  88. /*
  89. * And DCP pipe can NOT use "ready interrupt" for "send"
  90. * it should use "empty" interrupt.
  91. * see
  92. * "Operation" - "Interrupt Function" - "BRDY Interrupt"
  93. *
  94. * on the other hand, normal pipe can use "ready interrupt" for "send"
  95. * even though it is single/double buffer
  96. */
  97. if (usbhs_pipe_is_dcp(pipe))
  98. usbhsf_irq_empty_ctrl(pipe, enable);
  99. else
  100. usbhsf_irq_ready_ctrl(pipe, enable);
  101. }
  102. static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
  103. {
  104. usbhsf_irq_ready_ctrl(pipe, enable);
  105. }
  106. /*
  107. * FIFO ctrl
  108. */
  109. static void usbhsf_send_terminator(struct usbhs_pipe *pipe)
  110. {
  111. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  112. usbhs_bset(priv, CFIFOCTR, BVAL, BVAL);
  113. }
  114. static int usbhsf_fifo_barrier(struct usbhs_priv *priv)
  115. {
  116. int timeout = 1024;
  117. do {
  118. /* The FIFO port is accessible */
  119. if (usbhs_read(priv, CFIFOCTR) & FRDY)
  120. return 0;
  121. udelay(10);
  122. } while (timeout--);
  123. return -EBUSY;
  124. }
  125. static void usbhsf_fifo_clear(struct usbhs_pipe *pipe)
  126. {
  127. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  128. if (!usbhs_pipe_is_dcp(pipe))
  129. usbhsf_fifo_barrier(priv);
  130. usbhs_write(priv, CFIFOCTR, BCLR);
  131. }
  132. static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv)
  133. {
  134. return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
  135. }
  136. static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write)
  137. {
  138. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  139. struct device *dev = usbhs_priv_to_dev(priv);
  140. int timeout = 1024;
  141. u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */
  142. u16 base = usbhs_pipe_number(pipe); /* CURPIPE */
  143. if (usbhs_pipe_is_dcp(pipe))
  144. base |= (1 == write) << 5; /* ISEL */
  145. /* "base" will be used below */
  146. usbhs_write(priv, CFIFOSEL, base | MBW_32);
  147. /* check ISEL and CURPIPE value */
  148. while (timeout--) {
  149. if (base == (mask & usbhs_read(priv, CFIFOSEL)))
  150. return 0;
  151. udelay(10);
  152. }
  153. dev_err(dev, "fifo select error\n");
  154. return -EIO;
  155. }
  156. /*
  157. * PIO fifo functions
  158. */
  159. static int usbhsf_try_push(struct usbhs_pkt *pkt)
  160. {
  161. struct usbhs_pipe *pipe = pkt->pipe;
  162. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  163. struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
  164. struct device *dev = usbhs_priv_to_dev(priv);
  165. void __iomem *addr = priv->base + CFIFO;
  166. u8 *buf;
  167. int maxp = usbhs_pipe_get_maxpacket(pipe);
  168. int total_len;
  169. int i, ret, len;
  170. int is_short, is_done;
  171. ret = usbhsf_fifo_select(pipe, 1);
  172. if (ret < 0)
  173. goto usbhs_fifo_write_busy;
  174. ret = usbhs_pipe_is_accessible(pipe);
  175. if (ret < 0)
  176. goto usbhs_fifo_write_busy;
  177. ret = usbhsf_fifo_barrier(priv);
  178. if (ret < 0)
  179. goto usbhs_fifo_write_busy;
  180. buf = pkt->buf + pkt->actual;
  181. len = pkt->length - pkt->actual;
  182. len = min(len, maxp);
  183. total_len = len;
  184. is_short = total_len < maxp;
  185. /*
  186. * FIXME
  187. *
  188. * 32-bit access only
  189. */
  190. if (len >= 4 && !((unsigned long)buf & 0x03)) {
  191. iowrite32_rep(addr, buf, len / 4);
  192. len %= 4;
  193. buf += total_len - len;
  194. }
  195. /* the rest operation */
  196. for (i = 0; i < len; i++)
  197. iowrite8(buf[i], addr + (0x03 - (i & 0x03)));
  198. /*
  199. * variable update
  200. */
  201. pkt->actual += total_len;
  202. if (pkt->actual < pkt->length)
  203. is_done = 0; /* there are remainder data */
  204. else if (is_short)
  205. is_done = 1; /* short packet */
  206. else
  207. is_done = !pkt->zero; /* send zero packet ? */
  208. /*
  209. * pipe/irq handling
  210. */
  211. if (is_short)
  212. usbhsf_send_terminator(pipe);
  213. usbhsf_tx_irq_ctrl(pipe, !is_done);
  214. usbhs_pipe_enable(pipe);
  215. dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n",
  216. usbhs_pipe_number(pipe),
  217. pkt->length, pkt->actual, is_done, pkt->zero);
  218. /*
  219. * Transmission end
  220. */
  221. if (is_done) {
  222. if (usbhs_pipe_is_dcp(pipe))
  223. usbhs_dcp_control_transfer_done(pipe);
  224. info->done(pkt);
  225. }
  226. return 0;
  227. usbhs_fifo_write_busy:
  228. /*
  229. * pipe is busy.
  230. * retry in interrupt
  231. */
  232. usbhsf_tx_irq_ctrl(pipe, 1);
  233. return ret;
  234. }
  235. struct usbhs_pkt_handle usbhs_fifo_push_handler = {
  236. .prepare = usbhsf_try_push,
  237. .try_run = usbhsf_try_push,
  238. };
  239. static int usbhsf_prepare_pop(struct usbhs_pkt *pkt)
  240. {
  241. struct usbhs_pipe *pipe = pkt->pipe;
  242. int ret;
  243. /*
  244. * select pipe and enable it to prepare packet receive
  245. */
  246. ret = usbhsf_fifo_select(pipe, 0);
  247. if (ret < 0)
  248. return ret;
  249. usbhs_pipe_enable(pipe);
  250. usbhsf_rx_irq_ctrl(pipe, 1);
  251. return ret;
  252. }
  253. static int usbhsf_try_pop(struct usbhs_pkt *pkt)
  254. {
  255. struct usbhs_pipe *pipe = pkt->pipe;
  256. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  257. struct device *dev = usbhs_priv_to_dev(priv);
  258. void __iomem *addr = priv->base + CFIFO;
  259. u8 *buf;
  260. u32 data = 0;
  261. int maxp = usbhs_pipe_get_maxpacket(pipe);
  262. int rcv_len, len;
  263. int i, ret;
  264. int total_len = 0;
  265. int is_done = 0;
  266. ret = usbhsf_fifo_select(pipe, 0);
  267. if (ret < 0)
  268. return ret;
  269. ret = usbhsf_fifo_barrier(priv);
  270. if (ret < 0)
  271. return ret;
  272. rcv_len = usbhsf_fifo_rcv_len(priv);
  273. buf = pkt->buf + pkt->actual;
  274. len = pkt->length - pkt->actual;
  275. len = min(len, rcv_len);
  276. total_len = len;
  277. /*
  278. * Buffer clear if Zero-Length packet
  279. *
  280. * see
  281. * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
  282. */
  283. if (0 == rcv_len) {
  284. usbhsf_fifo_clear(pipe);
  285. goto usbhs_fifo_read_end;
  286. }
  287. /*
  288. * FIXME
  289. *
  290. * 32-bit access only
  291. */
  292. if (len >= 4 && !((unsigned long)buf & 0x03)) {
  293. ioread32_rep(addr, buf, len / 4);
  294. len %= 4;
  295. buf += total_len - len;
  296. }
  297. /* the rest operation */
  298. for (i = 0; i < len; i++) {
  299. if (!(i & 0x03))
  300. data = ioread32(addr);
  301. buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
  302. }
  303. pkt->actual += total_len;
  304. usbhs_fifo_read_end:
  305. if ((pkt->actual == pkt->length) || /* receive all data */
  306. (total_len < maxp)) /* short packet */
  307. is_done = 1;
  308. dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n",
  309. usbhs_pipe_number(pipe),
  310. pkt->length, pkt->actual, is_done, pkt->zero);
  311. if (is_done) {
  312. struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
  313. usbhsf_rx_irq_ctrl(pipe, 0);
  314. usbhs_pipe_disable(pipe);
  315. info->done(pkt);
  316. }
  317. return 0;
  318. }
  319. struct usbhs_pkt_handle usbhs_fifo_pop_handler = {
  320. .prepare = usbhsf_prepare_pop,
  321. .try_run = usbhsf_try_pop,
  322. };
  323. /*
  324. * handler function
  325. */
  326. static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt)
  327. {
  328. struct usbhs_pipe *pipe = pkt->pipe;
  329. struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  330. struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
  331. usbhs_dcp_control_transfer_done(pipe);
  332. info->done(pkt);
  333. return 0;
  334. }
  335. struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = {
  336. .prepare = usbhsf_ctrl_stage_end,
  337. .try_run = usbhsf_ctrl_stage_end,
  338. };
  339. /*
  340. * irq functions
  341. */
  342. static int usbhsf_irq_empty(struct usbhs_priv *priv,
  343. struct usbhs_irq_state *irq_state)
  344. {
  345. struct usbhs_pipe *pipe;
  346. struct usbhs_pkt *pkt;
  347. struct device *dev = usbhs_priv_to_dev(priv);
  348. int i, ret;
  349. if (!irq_state->bempsts) {
  350. dev_err(dev, "debug %s !!\n", __func__);
  351. return -EIO;
  352. }
  353. dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts);
  354. /*
  355. * search interrupted "pipe"
  356. * not "uep".
  357. */
  358. usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
  359. if (!(irq_state->bempsts & (1 << i)))
  360. continue;
  361. pkt = usbhs_pkt_get(pipe);
  362. ret = usbhs_pkt_run(pkt);
  363. if (ret < 0)
  364. dev_err(dev, "irq_empty run_error %d : %d\n", i, ret);
  365. }
  366. return 0;
  367. }
  368. static int usbhsf_irq_ready(struct usbhs_priv *priv,
  369. struct usbhs_irq_state *irq_state)
  370. {
  371. struct usbhs_pipe *pipe;
  372. struct usbhs_pkt *pkt;
  373. struct device *dev = usbhs_priv_to_dev(priv);
  374. int i, ret;
  375. if (!irq_state->brdysts) {
  376. dev_err(dev, "debug %s !!\n", __func__);
  377. return -EIO;
  378. }
  379. dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts);
  380. /*
  381. * search interrupted "pipe"
  382. * not "uep".
  383. */
  384. usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
  385. if (!(irq_state->brdysts & (1 << i)))
  386. continue;
  387. pkt = usbhs_pkt_get(pipe);
  388. ret = usbhs_pkt_run(pkt);
  389. if (ret < 0)
  390. dev_err(dev, "irq_ready run_error %d : %d\n", i, ret);
  391. }
  392. return 0;
  393. }
  394. /*
  395. * fifo init
  396. */
  397. void usbhs_fifo_init(struct usbhs_priv *priv)
  398. {
  399. struct usbhs_mod *mod = usbhs_mod_get_current(priv);
  400. mod->irq_empty = usbhsf_irq_empty;
  401. mod->irq_ready = usbhsf_irq_ready;
  402. mod->irq_bempsts = 0;
  403. mod->irq_brdysts = 0;
  404. }
  405. void usbhs_fifo_quit(struct usbhs_priv *priv)
  406. {
  407. struct usbhs_mod *mod = usbhs_mod_get_current(priv);
  408. mod->irq_empty = NULL;
  409. mod->irq_ready = NULL;
  410. mod->irq_bempsts = 0;
  411. mod->irq_brdysts = 0;
  412. }