xillybus_of.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. this = kzalloc(sizeof(*this), GFP_KERNEL);
  73. if (!this)
  74. return -ENOMEM;
  75. addr = dma_map_single(ep->dev, ptr, size, direction);
  76. if (dma_mapping_error(ep->dev, addr)) {
  77. kfree(this);
  78. return -ENODEV;
  79. }
  80. this->device = ep->dev;
  81. this->dma_addr = addr;
  82. this->size = size;
  83. this->direction = direction;
  84. *ret_dma_handle = addr;
  85. return devm_add_action_or_reset(ep->dev, xilly_of_unmap, this);
  86. }
  87. static struct xilly_endpoint_hardware of_hw = {
  88. .owner = THIS_MODULE,
  89. .hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of,
  90. .hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of,
  91. .map_single = xilly_map_single_of,
  92. };
  93. static struct xilly_endpoint_hardware of_hw_coherent = {
  94. .owner = THIS_MODULE,
  95. .hw_sync_sgl_for_cpu = xilly_dma_sync_single_nop,
  96. .hw_sync_sgl_for_device = xilly_dma_sync_single_nop,
  97. .map_single = xilly_map_single_of,
  98. };
  99. static int xilly_drv_probe(struct platform_device *op)
  100. {
  101. struct device *dev = &op->dev;
  102. struct xilly_endpoint *endpoint;
  103. int rc;
  104. int irq;
  105. struct resource res;
  106. struct xilly_endpoint_hardware *ephw = &of_hw;
  107. if (of_property_read_bool(dev->of_node, "dma-coherent"))
  108. ephw = &of_hw_coherent;
  109. endpoint = xillybus_init_endpoint(NULL, dev, ephw);
  110. if (!endpoint)
  111. return -ENOMEM;
  112. dev_set_drvdata(dev, endpoint);
  113. rc = of_address_to_resource(dev->of_node, 0, &res);
  114. endpoint->registers = devm_ioremap_resource(dev, &res);
  115. if (IS_ERR(endpoint->registers))
  116. return PTR_ERR(endpoint->registers);
  117. irq = irq_of_parse_and_map(dev->of_node, 0);
  118. rc = devm_request_irq(dev, irq, xillybus_isr, 0, xillyname, endpoint);
  119. if (rc) {
  120. dev_err(endpoint->dev,
  121. "Failed to register IRQ handler. Aborting.\n");
  122. return -ENODEV;
  123. }
  124. return xillybus_endpoint_discovery(endpoint);
  125. }
  126. static int xilly_drv_remove(struct platform_device *op)
  127. {
  128. struct device *dev = &op->dev;
  129. struct xilly_endpoint *endpoint = dev_get_drvdata(dev);
  130. xillybus_endpoint_remove(endpoint);
  131. return 0;
  132. }
  133. static struct platform_driver xillybus_platform_driver = {
  134. .probe = xilly_drv_probe,
  135. .remove = xilly_drv_remove,
  136. .driver = {
  137. .name = xillyname,
  138. .of_match_table = xillybus_of_match,
  139. },
  140. };
  141. module_platform_driver(xillybus_platform_driver);