sudmac.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Renesas SUDMAC support
  4. *
  5. * Copyright (C) 2013 Renesas Solutions Corp.
  6. *
  7. * based on drivers/dma/sh/shdma.c:
  8. * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  9. * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
  10. * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
  11. * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
  12. */
  13. #include <linux/dmaengine.h>
  14. #include <linux/err.h>
  15. #include <linux/init.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/module.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/slab.h>
  20. #include <linux/sudmac.h>
  21. struct sudmac_chan {
  22. struct shdma_chan shdma_chan;
  23. void __iomem *base;
  24. char dev_id[16]; /* unique name per DMAC of channel */
  25. u32 offset; /* for CFG, BA, BBC, CA, CBC, DEN */
  26. u32 cfg;
  27. u32 dint_end_bit;
  28. };
  29. struct sudmac_device {
  30. struct shdma_dev shdma_dev;
  31. struct sudmac_pdata *pdata;
  32. void __iomem *chan_reg;
  33. };
  34. struct sudmac_regs {
  35. u32 base_addr;
  36. u32 base_byte_count;
  37. };
  38. struct sudmac_desc {
  39. struct sudmac_regs hw;
  40. struct shdma_desc shdma_desc;
  41. };
  42. #define to_chan(schan) container_of(schan, struct sudmac_chan, shdma_chan)
  43. #define to_desc(sdesc) container_of(sdesc, struct sudmac_desc, shdma_desc)
  44. #define to_sdev(sc) container_of(sc->shdma_chan.dma_chan.device, \
  45. struct sudmac_device, shdma_dev.dma_dev)
  46. /* SUDMAC register */
  47. #define SUDMAC_CH0CFG 0x00
  48. #define SUDMAC_CH0BA 0x10
  49. #define SUDMAC_CH0BBC 0x18
  50. #define SUDMAC_CH0CA 0x20
  51. #define SUDMAC_CH0CBC 0x28
  52. #define SUDMAC_CH0DEN 0x30
  53. #define SUDMAC_DSTSCLR 0x38
  54. #define SUDMAC_DBUFCTRL 0x3C
  55. #define SUDMAC_DINTCTRL 0x40
  56. #define SUDMAC_DINTSTS 0x44
  57. #define SUDMAC_DINTSTSCLR 0x48
  58. #define SUDMAC_CH0SHCTRL 0x50
  59. /* Definitions for the sudmac_channel.config */
  60. #define SUDMAC_SENDBUFM 0x1000 /* b12: Transmit Buffer Mode */
  61. #define SUDMAC_RCVENDM 0x0100 /* b8: Receive Data Transfer End Mode */
  62. #define SUDMAC_LBA_WAIT 0x0030 /* b5-4: Local Bus Access Wait */
  63. /* Definitions for the sudmac_channel.dint_end_bit */
  64. #define SUDMAC_CH1ENDE 0x0002 /* b1: Ch1 DMA Transfer End Int Enable */
  65. #define SUDMAC_CH0ENDE 0x0001 /* b0: Ch0 DMA Transfer End Int Enable */
  66. #define SUDMAC_DRV_NAME "sudmac"
  67. static void sudmac_writel(struct sudmac_chan *sc, u32 data, u32 reg)
  68. {
  69. iowrite32(data, sc->base + reg);
  70. }
  71. static u32 sudmac_readl(struct sudmac_chan *sc, u32 reg)
  72. {
  73. return ioread32(sc->base + reg);
  74. }
  75. static bool sudmac_is_busy(struct sudmac_chan *sc)
  76. {
  77. u32 den = sudmac_readl(sc, SUDMAC_CH0DEN + sc->offset);
  78. if (den)
  79. return true; /* working */
  80. return false; /* waiting */
  81. }
  82. static void sudmac_set_reg(struct sudmac_chan *sc, struct sudmac_regs *hw,
  83. struct shdma_desc *sdesc)
  84. {
  85. sudmac_writel(sc, sc->cfg, SUDMAC_CH0CFG + sc->offset);
  86. sudmac_writel(sc, hw->base_addr, SUDMAC_CH0BA + sc->offset);
  87. sudmac_writel(sc, hw->base_byte_count, SUDMAC_CH0BBC + sc->offset);
  88. }
  89. static void sudmac_start(struct sudmac_chan *sc)
  90. {
  91. u32 dintctrl = sudmac_readl(sc, SUDMAC_DINTCTRL);
  92. sudmac_writel(sc, dintctrl | sc->dint_end_bit, SUDMAC_DINTCTRL);
  93. sudmac_writel(sc, 1, SUDMAC_CH0DEN + sc->offset);
  94. }
  95. static void sudmac_start_xfer(struct shdma_chan *schan,
  96. struct shdma_desc *sdesc)
  97. {
  98. struct sudmac_chan *sc = to_chan(schan);
  99. struct sudmac_desc *sd = to_desc(sdesc);
  100. sudmac_set_reg(sc, &sd->hw, sdesc);
  101. sudmac_start(sc);
  102. }
  103. static bool sudmac_channel_busy(struct shdma_chan *schan)
  104. {
  105. struct sudmac_chan *sc = to_chan(schan);
  106. return sudmac_is_busy(sc);
  107. }
  108. static void sudmac_setup_xfer(struct shdma_chan *schan, int slave_id)
  109. {
  110. }
  111. static const struct sudmac_slave_config *sudmac_find_slave(
  112. struct sudmac_chan *sc, int slave_id)
  113. {
  114. struct sudmac_device *sdev = to_sdev(sc);
  115. struct sudmac_pdata *pdata = sdev->pdata;
  116. const struct sudmac_slave_config *cfg;
  117. int i;
  118. for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
  119. if (cfg->slave_id == slave_id)
  120. return cfg;
  121. return NULL;
  122. }
  123. static int sudmac_set_slave(struct shdma_chan *schan, int slave_id,
  124. dma_addr_t slave_addr, bool try)
  125. {
  126. struct sudmac_chan *sc = to_chan(schan);
  127. const struct sudmac_slave_config *cfg = sudmac_find_slave(sc, slave_id);
  128. if (!cfg)
  129. return -ENODEV;
  130. return 0;
  131. }
  132. static inline void sudmac_dma_halt(struct sudmac_chan *sc)
  133. {
  134. u32 dintctrl = sudmac_readl(sc, SUDMAC_DINTCTRL);
  135. sudmac_writel(sc, 0, SUDMAC_CH0DEN + sc->offset);
  136. sudmac_writel(sc, dintctrl & ~sc->dint_end_bit, SUDMAC_DINTCTRL);
  137. sudmac_writel(sc, sc->dint_end_bit, SUDMAC_DINTSTSCLR);
  138. }
  139. static int sudmac_desc_setup(struct shdma_chan *schan,
  140. struct shdma_desc *sdesc,
  141. dma_addr_t src, dma_addr_t dst, size_t *len)
  142. {
  143. struct sudmac_chan *sc = to_chan(schan);
  144. struct sudmac_desc *sd = to_desc(sdesc);
  145. dev_dbg(sc->shdma_chan.dev, "%s: src=%pad, dst=%pad, len=%zu\n",
  146. __func__, &src, &dst, *len);
  147. if (*len > schan->max_xfer_len)
  148. *len = schan->max_xfer_len;
  149. if (dst)
  150. sd->hw.base_addr = dst;
  151. else if (src)
  152. sd->hw.base_addr = src;
  153. sd->hw.base_byte_count = *len;
  154. return 0;
  155. }
  156. static void sudmac_halt(struct shdma_chan *schan)
  157. {
  158. struct sudmac_chan *sc = to_chan(schan);
  159. sudmac_dma_halt(sc);
  160. }
  161. static bool sudmac_chan_irq(struct shdma_chan *schan, int irq)
  162. {
  163. struct sudmac_chan *sc = to_chan(schan);
  164. u32 dintsts = sudmac_readl(sc, SUDMAC_DINTSTS);
  165. if (!(dintsts & sc->dint_end_bit))
  166. return false;
  167. /* DMA stop */
  168. sudmac_dma_halt(sc);
  169. return true;
  170. }
  171. static size_t sudmac_get_partial(struct shdma_chan *schan,
  172. struct shdma_desc *sdesc)
  173. {
  174. struct sudmac_chan *sc = to_chan(schan);
  175. struct sudmac_desc *sd = to_desc(sdesc);
  176. u32 current_byte_count = sudmac_readl(sc, SUDMAC_CH0CBC + sc->offset);
  177. return sd->hw.base_byte_count - current_byte_count;
  178. }
  179. static bool sudmac_desc_completed(struct shdma_chan *schan,
  180. struct shdma_desc *sdesc)
  181. {
  182. struct sudmac_chan *sc = to_chan(schan);
  183. struct sudmac_desc *sd = to_desc(sdesc);
  184. u32 current_addr = sudmac_readl(sc, SUDMAC_CH0CA + sc->offset);
  185. return sd->hw.base_addr + sd->hw.base_byte_count == current_addr;
  186. }
  187. static int sudmac_chan_probe(struct sudmac_device *su_dev, int id, int irq,
  188. unsigned long flags)
  189. {
  190. struct shdma_dev *sdev = &su_dev->shdma_dev;
  191. struct platform_device *pdev = to_platform_device(sdev->dma_dev.dev);
  192. struct sudmac_chan *sc;
  193. struct shdma_chan *schan;
  194. int err;
  195. sc = devm_kzalloc(&pdev->dev, sizeof(struct sudmac_chan), GFP_KERNEL);
  196. if (!sc)
  197. return -ENOMEM;
  198. schan = &sc->shdma_chan;
  199. schan->max_xfer_len = 64 * 1024 * 1024 - 1;
  200. shdma_chan_probe(sdev, schan, id);
  201. sc->base = su_dev->chan_reg;
  202. /* get platform_data */
  203. sc->offset = su_dev->pdata->channel->offset;
  204. if (su_dev->pdata->channel->config & SUDMAC_TX_BUFFER_MODE)
  205. sc->cfg |= SUDMAC_SENDBUFM;
  206. if (su_dev->pdata->channel->config & SUDMAC_RX_END_MODE)
  207. sc->cfg |= SUDMAC_RCVENDM;
  208. sc->cfg |= (su_dev->pdata->channel->wait << 4) & SUDMAC_LBA_WAIT;
  209. if (su_dev->pdata->channel->dint_end_bit & SUDMAC_DMA_BIT_CH0)
  210. sc->dint_end_bit |= SUDMAC_CH0ENDE;
  211. if (su_dev->pdata->channel->dint_end_bit & SUDMAC_DMA_BIT_CH1)
  212. sc->dint_end_bit |= SUDMAC_CH1ENDE;
  213. /* set up channel irq */
  214. if (pdev->id >= 0)
  215. snprintf(sc->dev_id, sizeof(sc->dev_id), "sudmac%d.%d",
  216. pdev->id, id);
  217. else
  218. snprintf(sc->dev_id, sizeof(sc->dev_id), "sudmac%d", id);
  219. err = shdma_request_irq(schan, irq, flags, sc->dev_id);
  220. if (err) {
  221. dev_err(sdev->dma_dev.dev,
  222. "DMA channel %d request_irq failed %d\n", id, err);
  223. goto err_no_irq;
  224. }
  225. return 0;
  226. err_no_irq:
  227. /* remove from dmaengine device node */
  228. shdma_chan_remove(schan);
  229. return err;
  230. }
  231. static void sudmac_chan_remove(struct sudmac_device *su_dev)
  232. {
  233. struct shdma_chan *schan;
  234. int i;
  235. shdma_for_each_chan(schan, &su_dev->shdma_dev, i) {
  236. BUG_ON(!schan);
  237. shdma_chan_remove(schan);
  238. }
  239. }
  240. static dma_addr_t sudmac_slave_addr(struct shdma_chan *schan)
  241. {
  242. /* SUDMAC doesn't need the address */
  243. return 0;
  244. }
  245. static struct shdma_desc *sudmac_embedded_desc(void *buf, int i)
  246. {
  247. return &((struct sudmac_desc *)buf)[i].shdma_desc;
  248. }
  249. static const struct shdma_ops sudmac_shdma_ops = {
  250. .desc_completed = sudmac_desc_completed,
  251. .halt_channel = sudmac_halt,
  252. .channel_busy = sudmac_channel_busy,
  253. .slave_addr = sudmac_slave_addr,
  254. .desc_setup = sudmac_desc_setup,
  255. .set_slave = sudmac_set_slave,
  256. .setup_xfer = sudmac_setup_xfer,
  257. .start_xfer = sudmac_start_xfer,
  258. .embedded_desc = sudmac_embedded_desc,
  259. .chan_irq = sudmac_chan_irq,
  260. .get_partial = sudmac_get_partial,
  261. };
  262. static int sudmac_probe(struct platform_device *pdev)
  263. {
  264. struct sudmac_pdata *pdata = dev_get_platdata(&pdev->dev);
  265. int err, i;
  266. struct sudmac_device *su_dev;
  267. struct dma_device *dma_dev;
  268. struct resource *chan, *irq_res;
  269. /* get platform data */
  270. if (!pdata)
  271. return -ENODEV;
  272. irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  273. if (!irq_res)
  274. return -ENODEV;
  275. err = -ENOMEM;
  276. su_dev = devm_kzalloc(&pdev->dev, sizeof(struct sudmac_device),
  277. GFP_KERNEL);
  278. if (!su_dev)
  279. return err;
  280. dma_dev = &su_dev->shdma_dev.dma_dev;
  281. chan = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  282. su_dev->chan_reg = devm_ioremap_resource(&pdev->dev, chan);
  283. if (IS_ERR(su_dev->chan_reg))
  284. return PTR_ERR(su_dev->chan_reg);
  285. dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
  286. su_dev->shdma_dev.ops = &sudmac_shdma_ops;
  287. su_dev->shdma_dev.desc_size = sizeof(struct sudmac_desc);
  288. err = shdma_init(&pdev->dev, &su_dev->shdma_dev, pdata->channel_num);
  289. if (err < 0)
  290. return err;
  291. /* platform data */
  292. su_dev->pdata = dev_get_platdata(&pdev->dev);
  293. platform_set_drvdata(pdev, su_dev);
  294. /* Create DMA Channel */
  295. for (i = 0; i < pdata->channel_num; i++) {
  296. err = sudmac_chan_probe(su_dev, i, irq_res->start, IRQF_SHARED);
  297. if (err)
  298. goto chan_probe_err;
  299. }
  300. err = dma_async_device_register(&su_dev->shdma_dev.dma_dev);
  301. if (err < 0)
  302. goto chan_probe_err;
  303. return err;
  304. chan_probe_err:
  305. sudmac_chan_remove(su_dev);
  306. shdma_cleanup(&su_dev->shdma_dev);
  307. return err;
  308. }
  309. static int sudmac_remove(struct platform_device *pdev)
  310. {
  311. struct sudmac_device *su_dev = platform_get_drvdata(pdev);
  312. struct dma_device *dma_dev = &su_dev->shdma_dev.dma_dev;
  313. dma_async_device_unregister(dma_dev);
  314. sudmac_chan_remove(su_dev);
  315. shdma_cleanup(&su_dev->shdma_dev);
  316. return 0;
  317. }
  318. static struct platform_driver sudmac_driver = {
  319. .driver = {
  320. .name = SUDMAC_DRV_NAME,
  321. },
  322. .probe = sudmac_probe,
  323. .remove = sudmac_remove,
  324. };
  325. module_platform_driver(sudmac_driver);
  326. MODULE_AUTHOR("Yoshihiro Shimoda");
  327. MODULE_DESCRIPTION("Renesas SUDMAC driver");
  328. MODULE_LICENSE("GPL v2");
  329. MODULE_ALIAS("platform:" SUDMAC_DRV_NAME);