xillybus_of.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * linux/drivers/misc/xillybus_of.c
  3. *
  4. * Copyright 2011 Xillybus Ltd, http://xillybus.com
  5. *
  6. * Driver for the Xillybus FPGA/host framework using Open Firmware.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the smems of the GNU General Public License as published by
  10. * the Free Software Foundation; version 2 of the License.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/device.h>
  14. #include <linux/slab.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/of.h>
  17. #include <linux/err.h>
  18. #include "xillybus.h"
  19. MODULE_DESCRIPTION("Xillybus driver for Open Firmware");
  20. MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
  21. MODULE_VERSION("1.06");
  22. MODULE_ALIAS("xillybus_of");
  23. MODULE_LICENSE("GPL v2");
  24. static const char xillyname[] = "xillybus_of";
  25. /* Match table for of_platform binding */
  26. static const struct of_device_id xillybus_of_match[] = {
  27. { .compatible = "xillybus,xillybus-1.00.a", },
  28. { .compatible = "xlnx,xillybus-1.00.a", }, /* Deprecated */
  29. {}
  30. };
  31. MODULE_DEVICE_TABLE(of, xillybus_of_match);
  32. static void xilly_dma_sync_single_for_cpu_of(struct xilly_endpoint *ep,
  33. dma_addr_t dma_handle,
  34. size_t size,
  35. int direction)
  36. {
  37. dma_sync_single_for_cpu(ep->dev, dma_handle, size, direction);
  38. }
  39. static void xilly_dma_sync_single_for_device_of(struct xilly_endpoint *ep,
  40. dma_addr_t dma_handle,
  41. size_t size,
  42. int direction)
  43. {
  44. dma_sync_single_for_device(ep->dev, dma_handle, size, direction);
  45. }
  46. static void xilly_dma_sync_single_nop(struct xilly_endpoint *ep,
  47. dma_addr_t dma_handle,
  48. size_t size,
  49. int direction)
  50. {
  51. }
  52. static void xilly_of_unmap(void *ptr)
  53. {
  54. struct xilly_mapping *data = ptr;
  55. dma_unmap_single(data->device, data->dma_addr,
  56. data->size, data->direction);
  57. kfree(ptr);
  58. }
  59. static int xilly_map_single_of(struct xilly_endpoint *ep,
  60. void *ptr,
  61. size_t size,
  62. int direction,
  63. dma_addr_t *ret_dma_handle
  64. )
  65. {
  66. dma_addr_t addr;
  67. struct xilly_mapping *this;
  68. this = kzalloc(sizeof(*this), GFP_KERNEL);
  69. if (!this)
  70. return -ENOMEM;
  71. addr = dma_map_single(ep->dev, ptr, size, direction);
  72. if (dma_mapping_error(ep->dev, addr)) {
  73. kfree(this);
  74. return -ENODEV;
  75. }
  76. this->device = ep->dev;
  77. this->dma_addr = addr;
  78. this->size = size;
  79. this->direction = direction;
  80. *ret_dma_handle = addr;
  81. return devm_add_action_or_reset(ep->dev, xilly_of_unmap, this);
  82. }
  83. static struct xilly_endpoint_hardware of_hw = {
  84. .owner = THIS_MODULE,
  85. .hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of,
  86. .hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of,
  87. .map_single = xilly_map_single_of,
  88. };
  89. static struct xilly_endpoint_hardware of_hw_coherent = {
  90. .owner = THIS_MODULE,
  91. .hw_sync_sgl_for_cpu = xilly_dma_sync_single_nop,
  92. .hw_sync_sgl_for_device = xilly_dma_sync_single_nop,
  93. .map_single = xilly_map_single_of,
  94. };
  95. static int xilly_drv_probe(struct platform_device *op)
  96. {
  97. struct device *dev = &op->dev;
  98. struct xilly_endpoint *endpoint;
  99. int rc;
  100. int irq;
  101. struct resource *res;
  102. struct xilly_endpoint_hardware *ephw = &of_hw;
  103. if (of_property_read_bool(dev->of_node, "dma-coherent"))
  104. ephw = &of_hw_coherent;
  105. endpoint = xillybus_init_endpoint(NULL, dev, ephw);
  106. if (!endpoint)
  107. return -ENOMEM;
  108. dev_set_drvdata(dev, endpoint);
  109. res = platform_get_resource(op, IORESOURCE_MEM, 0);
  110. endpoint->registers = devm_ioremap_resource(dev, res);
  111. if (IS_ERR(endpoint->registers))
  112. return PTR_ERR(endpoint->registers);
  113. irq = platform_get_irq(op, 0);
  114. rc = devm_request_irq(dev, irq, xillybus_isr, 0, xillyname, endpoint);
  115. if (rc) {
  116. dev_err(endpoint->dev,
  117. "Failed to register IRQ handler. Aborting.\n");
  118. return -ENODEV;
  119. }
  120. return xillybus_endpoint_discovery(endpoint);
  121. }
  122. static int xilly_drv_remove(struct platform_device *op)
  123. {
  124. struct device *dev = &op->dev;
  125. struct xilly_endpoint *endpoint = dev_get_drvdata(dev);
  126. xillybus_endpoint_remove(endpoint);
  127. return 0;
  128. }
  129. static struct platform_driver xillybus_platform_driver = {
  130. .probe = xilly_drv_probe,
  131. .remove = xilly_drv_remove,
  132. .driver = {
  133. .name = xillyname,
  134. .of_match_table = xillybus_of_match,
  135. },
  136. };
  137. module_platform_driver(xillybus_platform_driver);