1a6377d90SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 27051924fSEli Billauer /* 37051924fSEli Billauer * linux/drivers/misc/xillybus_of.c 47051924fSEli Billauer * 57051924fSEli Billauer * Copyright 2011 Xillybus Ltd, http://xillybus.com 67051924fSEli Billauer * 77051924fSEli Billauer * Driver for the Xillybus FPGA/host framework using Open Firmware. 87051924fSEli Billauer */ 97051924fSEli Billauer 107051924fSEli Billauer #include <linux/module.h> 117051924fSEli Billauer #include <linux/device.h> 127051924fSEli Billauer #include <linux/slab.h> 137051924fSEli Billauer #include <linux/platform_device.h> 147051924fSEli Billauer #include <linux/of.h> 157051924fSEli Billauer #include <linux/err.h> 167051924fSEli Billauer #include "xillybus.h" 177051924fSEli Billauer 187051924fSEli Billauer MODULE_DESCRIPTION("Xillybus driver for Open Firmware"); 197051924fSEli Billauer MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); 207051924fSEli Billauer MODULE_VERSION("1.06"); 217051924fSEli Billauer MODULE_ALIAS("xillybus_of"); 227051924fSEli Billauer MODULE_LICENSE("GPL v2"); 237051924fSEli Billauer 247051924fSEli Billauer static const char xillyname[] = "xillybus_of"; 257051924fSEli Billauer 267051924fSEli Billauer /* Match table for of_platform binding */ 27da2ff527SFabian Frederick static const struct of_device_id xillybus_of_match[] = { 287051924fSEli Billauer { .compatible = "xillybus,xillybus-1.00.a", }, 297051924fSEli Billauer { .compatible = "xlnx,xillybus-1.00.a", }, /* Deprecated */ 307051924fSEli Billauer {} 317051924fSEli Billauer }; 327051924fSEli Billauer 337051924fSEli Billauer MODULE_DEVICE_TABLE(of, xillybus_of_match); 347051924fSEli Billauer 357051924fSEli Billauer static void xilly_dma_sync_single_for_cpu_of(struct xilly_endpoint *ep, 367051924fSEli Billauer dma_addr_t dma_handle, 377051924fSEli Billauer size_t size, 387051924fSEli Billauer int direction) 397051924fSEli Billauer { 407051924fSEli Billauer dma_sync_single_for_cpu(ep->dev, dma_handle, size, direction); 417051924fSEli Billauer } 427051924fSEli Billauer 437051924fSEli Billauer static void xilly_dma_sync_single_for_device_of(struct xilly_endpoint *ep, 447051924fSEli Billauer dma_addr_t dma_handle, 457051924fSEli Billauer size_t size, 467051924fSEli Billauer int direction) 477051924fSEli Billauer { 487051924fSEli Billauer dma_sync_single_for_device(ep->dev, dma_handle, size, direction); 497051924fSEli Billauer } 507051924fSEli Billauer 517051924fSEli Billauer static void xilly_dma_sync_single_nop(struct xilly_endpoint *ep, 527051924fSEli Billauer dma_addr_t dma_handle, 537051924fSEli Billauer size_t size, 547051924fSEli Billauer int direction) 557051924fSEli Billauer { 567051924fSEli Billauer } 577051924fSEli Billauer 587051924fSEli Billauer static void xilly_of_unmap(void *ptr) 597051924fSEli Billauer { 607051924fSEli Billauer struct xilly_mapping *data = ptr; 617051924fSEli Billauer 627051924fSEli Billauer dma_unmap_single(data->device, data->dma_addr, 637051924fSEli Billauer data->size, data->direction); 647051924fSEli Billauer 657051924fSEli Billauer kfree(ptr); 667051924fSEli Billauer } 677051924fSEli Billauer 687051924fSEli Billauer static int xilly_map_single_of(struct xilly_endpoint *ep, 697051924fSEli Billauer void *ptr, 707051924fSEli Billauer size_t size, 717051924fSEli Billauer int direction, 727051924fSEli Billauer dma_addr_t *ret_dma_handle 737051924fSEli Billauer ) 747051924fSEli Billauer { 757051924fSEli Billauer dma_addr_t addr; 767051924fSEli Billauer struct xilly_mapping *this; 777051924fSEli Billauer 787051924fSEli Billauer this = kzalloc(sizeof(*this), GFP_KERNEL); 797051924fSEli Billauer if (!this) 807051924fSEli Billauer return -ENOMEM; 817051924fSEli Billauer 827051924fSEli Billauer addr = dma_map_single(ep->dev, ptr, size, direction); 837051924fSEli Billauer 847051924fSEli Billauer if (dma_mapping_error(ep->dev, addr)) { 857051924fSEli Billauer kfree(this); 867051924fSEli Billauer return -ENODEV; 877051924fSEli Billauer } 887051924fSEli Billauer 897051924fSEli Billauer this->device = ep->dev; 907051924fSEli Billauer this->dma_addr = addr; 917051924fSEli Billauer this->size = size; 927051924fSEli Billauer this->direction = direction; 937051924fSEli Billauer 947051924fSEli Billauer *ret_dma_handle = addr; 957051924fSEli Billauer 96bd83a4abSSudip Mukherjee return devm_add_action_or_reset(ep->dev, xilly_of_unmap, this); 977051924fSEli Billauer } 987051924fSEli Billauer 997051924fSEli Billauer static struct xilly_endpoint_hardware of_hw = { 1007051924fSEli Billauer .owner = THIS_MODULE, 1017051924fSEli Billauer .hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of, 1027051924fSEli Billauer .hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of, 1037051924fSEli Billauer .map_single = xilly_map_single_of, 1047051924fSEli Billauer }; 1057051924fSEli Billauer 1067051924fSEli Billauer static struct xilly_endpoint_hardware of_hw_coherent = { 1077051924fSEli Billauer .owner = THIS_MODULE, 1087051924fSEli Billauer .hw_sync_sgl_for_cpu = xilly_dma_sync_single_nop, 1097051924fSEli Billauer .hw_sync_sgl_for_device = xilly_dma_sync_single_nop, 1107051924fSEli Billauer .map_single = xilly_map_single_of, 1117051924fSEli Billauer }; 1127051924fSEli Billauer 1137051924fSEli Billauer static int xilly_drv_probe(struct platform_device *op) 1147051924fSEli Billauer { 1157051924fSEli Billauer struct device *dev = &op->dev; 1167051924fSEli Billauer struct xilly_endpoint *endpoint; 1177051924fSEli Billauer int rc; 1187051924fSEli Billauer int irq; 1197051924fSEli Billauer struct xilly_endpoint_hardware *ephw = &of_hw; 1207051924fSEli Billauer 1217051924fSEli Billauer if (of_property_read_bool(dev->of_node, "dma-coherent")) 1227051924fSEli Billauer ephw = &of_hw_coherent; 1237051924fSEli Billauer 1247051924fSEli Billauer endpoint = xillybus_init_endpoint(NULL, dev, ephw); 1257051924fSEli Billauer 1267051924fSEli Billauer if (!endpoint) 1277051924fSEli Billauer return -ENOMEM; 1287051924fSEli Billauer 1297051924fSEli Billauer dev_set_drvdata(dev, endpoint); 1307051924fSEli Billauer 131*482c86ccSYueHaibing endpoint->registers = devm_platform_ioremap_resource(op, 0); 1327051924fSEli Billauer if (IS_ERR(endpoint->registers)) 1337051924fSEli Billauer return PTR_ERR(endpoint->registers); 1347051924fSEli Billauer 13574d83a5dSRob Herring irq = platform_get_irq(op, 0); 1367051924fSEli Billauer 1377051924fSEli Billauer rc = devm_request_irq(dev, irq, xillybus_isr, 0, xillyname, endpoint); 1387051924fSEli Billauer 1397051924fSEli Billauer if (rc) { 1407051924fSEli Billauer dev_err(endpoint->dev, 1417051924fSEli Billauer "Failed to register IRQ handler. Aborting.\n"); 1427051924fSEli Billauer return -ENODEV; 1437051924fSEli Billauer } 1447051924fSEli Billauer 1457051924fSEli Billauer return xillybus_endpoint_discovery(endpoint); 1467051924fSEli Billauer } 1477051924fSEli Billauer 1487051924fSEli Billauer static int xilly_drv_remove(struct platform_device *op) 1497051924fSEli Billauer { 1507051924fSEli Billauer struct device *dev = &op->dev; 1517051924fSEli Billauer struct xilly_endpoint *endpoint = dev_get_drvdata(dev); 1527051924fSEli Billauer 1537051924fSEli Billauer xillybus_endpoint_remove(endpoint); 1547051924fSEli Billauer 1557051924fSEli Billauer return 0; 1567051924fSEli Billauer } 1577051924fSEli Billauer 1587051924fSEli Billauer static struct platform_driver xillybus_platform_driver = { 1597051924fSEli Billauer .probe = xilly_drv_probe, 1607051924fSEli Billauer .remove = xilly_drv_remove, 1617051924fSEli Billauer .driver = { 1627051924fSEli Billauer .name = xillyname, 1637051924fSEli Billauer .of_match_table = xillybus_of_match, 1647051924fSEli Billauer }, 1657051924fSEli Billauer }; 1667051924fSEli Billauer 1677051924fSEli Billauer module_platform_driver(xillybus_platform_driver); 168