rzn1-dmamux.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2022 Schneider-Electric
  4. * Author: Miquel Raynal <[email protected]
  5. * Based on TI crossbar driver written by Peter Ujfalusi <[email protected]>
  6. */
  7. #include <linux/bitops.h>
  8. #include <linux/of_device.h>
  9. #include <linux/of_dma.h>
  10. #include <linux/slab.h>
  11. #include <linux/soc/renesas/r9a06g032-sysctrl.h>
  12. #include <linux/types.h>
  13. #define RNZ1_DMAMUX_NCELLS 6
  14. #define RZN1_DMAMUX_MAX_LINES 64
  15. #define RZN1_DMAMUX_LINES_PER_CTLR 16
  16. struct rzn1_dmamux_data {
  17. struct dma_router dmarouter;
  18. DECLARE_BITMAP(used_chans, 2 * RZN1_DMAMUX_LINES_PER_CTLR);
  19. };
  20. struct rzn1_dmamux_map {
  21. unsigned int req_idx;
  22. };
  23. static void rzn1_dmamux_free(struct device *dev, void *route_data)
  24. {
  25. struct rzn1_dmamux_data *dmamux = dev_get_drvdata(dev);
  26. struct rzn1_dmamux_map *map = route_data;
  27. dev_dbg(dev, "Unmapping DMAMUX request %u\n", map->req_idx);
  28. clear_bit(map->req_idx, dmamux->used_chans);
  29. kfree(map);
  30. }
  31. static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec,
  32. struct of_dma *ofdma)
  33. {
  34. struct platform_device *pdev = of_find_device_by_node(ofdma->of_node);
  35. struct rzn1_dmamux_data *dmamux = platform_get_drvdata(pdev);
  36. struct rzn1_dmamux_map *map;
  37. unsigned int dmac_idx, chan, val;
  38. u32 mask;
  39. int ret;
  40. if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS)
  41. return ERR_PTR(-EINVAL);
  42. map = kzalloc(sizeof(*map), GFP_KERNEL);
  43. if (!map)
  44. return ERR_PTR(-ENOMEM);
  45. chan = dma_spec->args[0];
  46. map->req_idx = dma_spec->args[4];
  47. val = dma_spec->args[5];
  48. dma_spec->args_count -= 2;
  49. if (chan >= RZN1_DMAMUX_LINES_PER_CTLR) {
  50. dev_err(&pdev->dev, "Invalid DMA request line: %u\n", chan);
  51. ret = -EINVAL;
  52. goto free_map;
  53. }
  54. if (map->req_idx >= RZN1_DMAMUX_MAX_LINES ||
  55. (map->req_idx % RZN1_DMAMUX_LINES_PER_CTLR) != chan) {
  56. dev_err(&pdev->dev, "Invalid MUX request line: %u\n", map->req_idx);
  57. ret = -EINVAL;
  58. goto free_map;
  59. }
  60. dmac_idx = map->req_idx >= RZN1_DMAMUX_LINES_PER_CTLR ? 1 : 0;
  61. dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", dmac_idx);
  62. if (!dma_spec->np) {
  63. dev_err(&pdev->dev, "Can't get DMA master\n");
  64. ret = -EINVAL;
  65. goto free_map;
  66. }
  67. dev_dbg(&pdev->dev, "Mapping DMAMUX request %u to DMAC%u request %u\n",
  68. map->req_idx, dmac_idx, chan);
  69. if (test_and_set_bit(map->req_idx, dmamux->used_chans)) {
  70. ret = -EBUSY;
  71. goto free_map;
  72. }
  73. mask = BIT(map->req_idx);
  74. ret = r9a06g032_sysctrl_set_dmamux(mask, val ? mask : 0);
  75. if (ret)
  76. goto clear_bitmap;
  77. return map;
  78. clear_bitmap:
  79. clear_bit(map->req_idx, dmamux->used_chans);
  80. free_map:
  81. kfree(map);
  82. return ERR_PTR(ret);
  83. }
  84. #ifdef CONFIG_OF
  85. static const struct of_device_id rzn1_dmac_match[] = {
  86. { .compatible = "renesas,rzn1-dma" },
  87. {}
  88. };
  89. #endif
  90. static int rzn1_dmamux_probe(struct platform_device *pdev)
  91. {
  92. struct device_node *mux_node = pdev->dev.of_node;
  93. const struct of_device_id *match;
  94. struct device_node *dmac_node;
  95. struct rzn1_dmamux_data *dmamux;
  96. dmamux = devm_kzalloc(&pdev->dev, sizeof(*dmamux), GFP_KERNEL);
  97. if (!dmamux)
  98. return -ENOMEM;
  99. dmac_node = of_parse_phandle(mux_node, "dma-masters", 0);
  100. if (!dmac_node)
  101. return dev_err_probe(&pdev->dev, -ENODEV, "Can't get DMA master node\n");
  102. match = of_match_node(rzn1_dmac_match, dmac_node);
  103. of_node_put(dmac_node);
  104. if (!match)
  105. return dev_err_probe(&pdev->dev, -EINVAL, "DMA master is not supported\n");
  106. dmamux->dmarouter.dev = &pdev->dev;
  107. dmamux->dmarouter.route_free = rzn1_dmamux_free;
  108. platform_set_drvdata(pdev, dmamux);
  109. return of_dma_router_register(mux_node, rzn1_dmamux_route_allocate,
  110. &dmamux->dmarouter);
  111. }
  112. static const struct of_device_id rzn1_dmamux_match[] = {
  113. { .compatible = "renesas,rzn1-dmamux" },
  114. {}
  115. };
  116. MODULE_DEVICE_TABLE(of, rzn1_dmamux_match);
  117. static struct platform_driver rzn1_dmamux_driver = {
  118. .driver = {
  119. .name = "renesas,rzn1-dmamux",
  120. .of_match_table = rzn1_dmamux_match,
  121. },
  122. .probe = rzn1_dmamux_probe,
  123. };
  124. module_platform_driver(rzn1_dmamux_driver);
  125. MODULE_LICENSE("GPL");
  126. MODULE_AUTHOR("Miquel Raynal <[email protected]");
  127. MODULE_DESCRIPTION("Renesas RZ/N1 DMAMUX driver");