xillybus_of.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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/of_irq.h>
  18. #include <linux/of_address.h>
  19. #include <linux/of_device.h>
  20. #include <linux/of_platform.h>
  21. #include <linux/err.h>
  22. #include "xillybus.h"
  23. MODULE_DESCRIPTION("Xillybus driver for Open Firmware");
  24. MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
  25. MODULE_VERSION("1.06");
  26. MODULE_ALIAS("xillybus_of");
  27. MODULE_LICENSE("GPL v2");
  28. static const char xillyname[] = "xillybus_of";
  29. /* Match table for of_platform binding */
  30. static const struct of_device_id xillybus_of_match[] = {
  31. { .compatible = "xillybus,xillybus-1.00.a", },
  32. { .compatible = "xlnx,xillybus-1.00.a", }, /* Deprecated */
  33. {}
  34. };
  35. MODULE_DEVICE_TABLE(of, xillybus_of_match);
  36. static void xilly_dma_sync_single_for_cpu_of(struct xilly_endpoint *ep,
  37. dma_addr_t dma_handle,
  38. size_t size,
  39. int direction)
  40. {
  41. dma_sync_single_for_cpu(ep->dev, dma_handle, size, direction);
  42. }
  43. static void xilly_dma_sync_single_for_device_of(struct xilly_endpoint *ep,
  44. dma_addr_t dma_handle,
  45. size_t size,
  46. int direction)
  47. {
  48. dma_sync_single_for_device(ep->dev, dma_handle, size, direction);
  49. }
  50. static void xilly_dma_sync_single_nop(struct xilly_endpoint *ep,
  51. dma_addr_t dma_handle,
  52. size_t size,
  53. int direction)
  54. {
  55. }
  56. static void xilly_of_unmap(void *ptr)
  57. {
  58. struct xilly_mapping *data = ptr;
  59. dma_unmap_single(data->device, data->dma_addr,
  60. data->size, data->direction);
  61. kfree(ptr);
  62. }
  63. static int xilly_map_single_of(struct xilly_endpoint *ep,
  64. void *ptr,
  65. size_t size,
  66. int direction,
  67. dma_addr_t *ret_dma_handle
  68. )
  69. {
  70. dma_addr_t addr;
  71. struct xilly_mapping *this;
  72. int rc;
  73. this = kzalloc(sizeof(*this), GFP_KERNEL);
  74. if (!this)
  75. return -ENOMEM;
  76. addr = dma_map_single(ep->dev, ptr, size, direction);
  77. if (dma_mapping_error(ep->dev, addr)) {
  78. kfree(this);
  79. return -ENODEV;
  80. }
  81. this->device = ep->dev;
  82. this->dma_addr = addr;
  83. this->size = size;
  84. this->direction = direction;
  85. *ret_dma_handle = addr;
  86. rc = devm_add_action(ep->dev, xilly_of_unmap, this);
  87. if (rc) {
  88. dma_unmap_single(ep->dev, addr, size, direction);
  89. kfree(this);
  90. return rc;
  91. }
  92. return 0;
  93. }
  94. static struct xilly_endpoint_hardware of_hw = {
  95. .owner = THIS_MODULE,
  96. .hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of,
  97. .hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of,
  98. .map_single = xilly_map_single_of,
  99. };
  100. static struct xilly_endpoint_hardware of_hw_coherent = {
  101. .owner = THIS_MODULE,
  102. .hw_sync_sgl_for_cpu = xilly_dma_sync_single_nop,
  103. .hw_sync_sgl_for_device = xilly_dma_sync_single_nop,
  104. .map_single = xilly_map_single_of,
  105. };
  106. static int xilly_drv_probe(struct platform_device *op)
  107. {
  108. struct device *dev = &op->dev;
  109. struct xilly_endpoint *endpoint;
  110. int rc;
  111. int irq;
  112. struct resource res;
  113. struct xilly_endpoint_hardware *ephw = &of_hw;
  114. if (of_property_read_bool(dev->of_node, "dma-coherent"))
  115. ephw = &of_hw_coherent;
  116. endpoint = xillybus_init_endpoint(NULL, dev, ephw);
  117. if (!endpoint)
  118. return -ENOMEM;
  119. dev_set_drvdata(dev, endpoint);
  120. rc = of_address_to_resource(dev->of_node, 0, &res);
  121. endpoint->registers = devm_ioremap_resource(dev, &res);
  122. if (IS_ERR(endpoint->registers))
  123. return PTR_ERR(endpoint->registers);
  124. irq = irq_of_parse_and_map(dev->of_node, 0);
  125. rc = devm_request_irq(dev, irq, xillybus_isr, 0, xillyname, endpoint);
  126. if (rc) {
  127. dev_err(endpoint->dev,
  128. "Failed to register IRQ handler. Aborting.\n");
  129. return -ENODEV;
  130. }
  131. return xillybus_endpoint_discovery(endpoint);
  132. }
  133. static int xilly_drv_remove(struct platform_device *op)
  134. {
  135. struct device *dev = &op->dev;
  136. struct xilly_endpoint *endpoint = dev_get_drvdata(dev);
  137. xillybus_endpoint_remove(endpoint);
  138. return 0;
  139. }
  140. static struct platform_driver xillybus_platform_driver = {
  141. .probe = xilly_drv_probe,
  142. .remove = xilly_drv_remove,
  143. .driver = {
  144. .name = xillyname,
  145. .of_match_table = xillybus_of_match,
  146. },
  147. };
  148. module_platform_driver(xillybus_platform_driver);