2 * linux/drivers/misc/xillybus_of.c
4 * Copyright 2011 Xillybus Ltd, http://xillybus.com
6 * Driver for the Xillybus FPGA/host framework using Open Firmware.
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.
13 #include <linux/module.h>
14 #include <linux/device.h>
15 #include <linux/slab.h>
16 #include <linux/platform_device.h>
18 #include <linux/of_irq.h>
19 #include <linux/of_address.h>
20 #include <linux/of_device.h>
21 #include <linux/of_platform.h>
22 #include <linux/err.h>
25 MODULE_DESCRIPTION("Xillybus driver for Open Firmware");
26 MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
27 MODULE_VERSION("1.06");
28 MODULE_ALIAS("xillybus_of");
29 MODULE_LICENSE("GPL v2");
31 static const char xillyname
[] = "xillybus_of";
33 /* Match table for of_platform binding */
34 static struct of_device_id xillybus_of_match
[] = {
35 { .compatible
= "xillybus,xillybus-1.00.a", },
36 { .compatible
= "xlnx,xillybus-1.00.a", }, /* Deprecated */
40 MODULE_DEVICE_TABLE(of
, xillybus_of_match
);
42 static void xilly_dma_sync_single_for_cpu_of(struct xilly_endpoint
*ep
,
43 dma_addr_t dma_handle
,
47 dma_sync_single_for_cpu(ep
->dev
, dma_handle
, size
, direction
);
50 static void xilly_dma_sync_single_for_device_of(struct xilly_endpoint
*ep
,
51 dma_addr_t dma_handle
,
55 dma_sync_single_for_device(ep
->dev
, dma_handle
, size
, direction
);
58 static void xilly_dma_sync_single_nop(struct xilly_endpoint
*ep
,
59 dma_addr_t dma_handle
,
65 static void xilly_of_unmap(void *ptr
)
67 struct xilly_mapping
*data
= ptr
;
69 dma_unmap_single(data
->device
, data
->dma_addr
,
70 data
->size
, data
->direction
);
75 static int xilly_map_single_of(struct xilly_endpoint
*ep
,
79 dma_addr_t
*ret_dma_handle
83 struct xilly_mapping
*this;
86 this = kzalloc(sizeof(*this), GFP_KERNEL
);
90 addr
= dma_map_single(ep
->dev
, ptr
, size
, direction
);
92 if (dma_mapping_error(ep
->dev
, addr
)) {
97 this->device
= ep
->dev
;
98 this->dma_addr
= addr
;
100 this->direction
= direction
;
102 *ret_dma_handle
= addr
;
104 rc
= devm_add_action(ep
->dev
, xilly_of_unmap
, this);
107 dma_unmap_single(ep
->dev
, addr
, size
, direction
);
115 static struct xilly_endpoint_hardware of_hw
= {
116 .owner
= THIS_MODULE
,
117 .hw_sync_sgl_for_cpu
= xilly_dma_sync_single_for_cpu_of
,
118 .hw_sync_sgl_for_device
= xilly_dma_sync_single_for_device_of
,
119 .map_single
= xilly_map_single_of
,
122 static struct xilly_endpoint_hardware of_hw_coherent
= {
123 .owner
= THIS_MODULE
,
124 .hw_sync_sgl_for_cpu
= xilly_dma_sync_single_nop
,
125 .hw_sync_sgl_for_device
= xilly_dma_sync_single_nop
,
126 .map_single
= xilly_map_single_of
,
129 static int xilly_drv_probe(struct platform_device
*op
)
131 struct device
*dev
= &op
->dev
;
132 struct xilly_endpoint
*endpoint
;
136 struct xilly_endpoint_hardware
*ephw
= &of_hw
;
138 if (of_property_read_bool(dev
->of_node
, "dma-coherent"))
139 ephw
= &of_hw_coherent
;
141 endpoint
= xillybus_init_endpoint(NULL
, dev
, ephw
);
146 dev_set_drvdata(dev
, endpoint
);
148 rc
= of_address_to_resource(dev
->of_node
, 0, &res
);
149 endpoint
->registers
= devm_ioremap_resource(dev
, &res
);
151 if (IS_ERR(endpoint
->registers
))
152 return PTR_ERR(endpoint
->registers
);
154 irq
= irq_of_parse_and_map(dev
->of_node
, 0);
156 rc
= devm_request_irq(dev
, irq
, xillybus_isr
, 0, xillyname
, endpoint
);
159 dev_err(endpoint
->dev
,
160 "Failed to register IRQ handler. Aborting.\n");
164 return xillybus_endpoint_discovery(endpoint
);
167 static int xilly_drv_remove(struct platform_device
*op
)
169 struct device
*dev
= &op
->dev
;
170 struct xilly_endpoint
*endpoint
= dev_get_drvdata(dev
);
172 xillybus_endpoint_remove(endpoint
);
177 static struct platform_driver xillybus_platform_driver
= {
178 .probe
= xilly_drv_probe
,
179 .remove
= xilly_drv_remove
,
182 .of_match_table
= xillybus_of_match
,
186 module_platform_driver(xillybus_platform_driver
);