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