2019-06-01 10:08:17 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2013-06-24 18:55:47 +03:00
/*
* linux / drivers / misc / xillybus_of . c
*
* Copyright 2011 Xillybus Ltd , http : //xillybus.com
*
* Driver for the Xillybus FPGA / host framework using Open Firmware .
*/
# include <linux/module.h>
# include <linux/device.h>
# include <linux/slab.h>
# include <linux/platform_device.h>
# include <linux/of.h>
2014-05-11 19:53:46 +03:00
# include <linux/err.h>
2013-06-24 18:55:47 +03:00
# include "xillybus.h"
MODULE_DESCRIPTION ( " Xillybus driver for Open Firmware " ) ;
MODULE_AUTHOR ( " Eli Billauer, Xillybus Ltd. " ) ;
MODULE_VERSION ( " 1.06 " ) ;
MODULE_ALIAS ( " xillybus_of " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2013-07-27 00:24:00 +03:00
static const char xillyname [ ] = " xillybus_of " ;
2013-06-24 18:55:47 +03:00
/* Match table for of_platform binding */
2015-03-16 20:17:13 +01:00
static const struct of_device_id xillybus_of_match [ ] = {
2013-12-30 23:16:24 +02:00
{ . compatible = " xillybus,xillybus-1.00.a " , } ,
{ . compatible = " xlnx,xillybus-1.00.a " , } , /* Deprecated */
2013-06-24 18:55:47 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( of , xillybus_of_match ) ;
static void xilly_dma_sync_single_for_cpu_of ( struct xilly_endpoint * ep ,
dma_addr_t dma_handle ,
size_t size ,
int direction )
{
dma_sync_single_for_cpu ( ep - > dev , dma_handle , size , direction ) ;
}
static void xilly_dma_sync_single_for_device_of ( struct xilly_endpoint * ep ,
dma_addr_t dma_handle ,
size_t size ,
int direction )
{
dma_sync_single_for_device ( ep - > dev , dma_handle , size , direction ) ;
}
2013-12-30 23:16:25 +02:00
static void xilly_dma_sync_single_nop ( struct xilly_endpoint * ep ,
dma_addr_t dma_handle ,
size_t size ,
int direction )
{
}
2014-06-21 14:07:12 +03:00
static void xilly_of_unmap ( void * ptr )
2013-06-24 18:55:47 +03:00
{
2014-06-21 14:07:12 +03:00
struct xilly_mapping * data = ptr ;
2013-06-24 18:55:47 +03:00
2014-06-21 14:07:12 +03:00
dma_unmap_single ( data - > device , data - > dma_addr ,
data - > size , data - > direction ) ;
kfree ( ptr ) ;
}
static int xilly_map_single_of ( struct xilly_endpoint * ep ,
void * ptr ,
size_t size ,
int direction ,
dma_addr_t * ret_dma_handle
)
{
dma_addr_t addr ;
struct xilly_mapping * this ;
2013-06-24 18:55:47 +03:00
2014-06-21 14:07:12 +03:00
this = kzalloc ( sizeof ( * this ) , GFP_KERNEL ) ;
2013-06-24 18:55:47 +03:00
if ( ! this )
2014-06-21 14:07:12 +03:00
return - ENOMEM ;
2013-06-24 18:55:47 +03:00
addr = dma_map_single ( ep - > dev , ptr , size , direction ) ;
if ( dma_mapping_error ( ep - > dev , addr ) ) {
kfree ( this ) ;
2014-06-21 14:07:12 +03:00
return - ENODEV ;
2013-06-24 18:55:47 +03:00
}
2014-06-21 14:07:12 +03:00
this - > device = ep - > dev ;
2013-06-24 18:55:47 +03:00
this - > dma_addr = addr ;
this - > size = size ;
2014-06-21 14:07:12 +03:00
this - > direction = direction ;
2013-06-24 18:55:47 +03:00
2014-06-21 14:07:12 +03:00
* ret_dma_handle = addr ;
2013-06-24 18:55:47 +03:00
2016-04-30 17:13:20 +01:00
return devm_add_action_or_reset ( ep - > dev , xilly_of_unmap , this ) ;
2013-06-24 18:55:47 +03:00
}
static struct xilly_endpoint_hardware of_hw = {
. owner = THIS_MODULE ,
2013-07-31 11:22:43 +03:00
. hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of ,
. hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of ,
2013-06-24 18:55:47 +03:00
. map_single = xilly_map_single_of ,
} ;
2013-12-30 23:16:25 +02:00
static struct xilly_endpoint_hardware of_hw_coherent = {
. owner = THIS_MODULE ,
. hw_sync_sgl_for_cpu = xilly_dma_sync_single_nop ,
. hw_sync_sgl_for_device = xilly_dma_sync_single_nop ,
. map_single = xilly_map_single_of ,
} ;
2013-06-24 18:55:47 +03:00
static int xilly_drv_probe ( struct platform_device * op )
{
struct device * dev = & op - > dev ;
struct xilly_endpoint * endpoint ;
2014-09-04 17:47:48 +03:00
int rc ;
2013-06-24 18:55:47 +03:00
int irq ;
2018-01-04 16:45:39 -06:00
struct resource * res ;
2013-12-30 23:16:25 +02:00
struct xilly_endpoint_hardware * ephw = & of_hw ;
if ( of_property_read_bool ( dev - > of_node , " dma-coherent " ) )
ephw = & of_hw_coherent ;
2013-06-24 18:55:47 +03:00
2013-12-30 23:16:25 +02:00
endpoint = xillybus_init_endpoint ( NULL , dev , ephw ) ;
2013-06-24 18:55:47 +03:00
if ( ! endpoint )
return - ENOMEM ;
dev_set_drvdata ( dev , endpoint ) ;
2018-01-04 16:45:39 -06:00
res = platform_get_resource ( op , IORESOURCE_MEM , 0 ) ;
endpoint - > registers = devm_ioremap_resource ( dev , res ) ;
2013-06-24 18:55:47 +03:00
2014-05-11 19:53:46 +03:00
if ( IS_ERR ( endpoint - > registers ) )
return PTR_ERR ( endpoint - > registers ) ;
2013-06-24 18:55:47 +03:00
2018-01-04 16:45:39 -06:00
irq = platform_get_irq ( op , 0 ) ;
2013-06-24 18:55:47 +03:00
2014-05-11 19:53:46 +03:00
rc = devm_request_irq ( dev , irq , xillybus_isr , 0 , xillyname , endpoint ) ;
2013-06-24 18:55:47 +03:00
if ( rc ) {
2013-10-19 01:02:27 +03:00
dev_err ( endpoint - > dev ,
" Failed to register IRQ handler. Aborting. \n " ) ;
2014-05-11 19:53:46 +03:00
return - ENODEV ;
2013-06-24 18:55:47 +03:00
}
2014-06-21 14:07:12 +03:00
return xillybus_endpoint_discovery ( endpoint ) ;
2013-06-24 18:55:47 +03:00
}
static int xilly_drv_remove ( struct platform_device * op )
{
struct device * dev = & op - > dev ;
struct xilly_endpoint * endpoint = dev_get_drvdata ( dev ) ;
xillybus_endpoint_remove ( endpoint ) ;
return 0 ;
}
static struct platform_driver xillybus_platform_driver = {
. probe = xilly_drv_probe ,
. remove = xilly_drv_remove ,
. driver = {
. name = xillyname ,
. of_match_table = xillybus_of_match ,
} ,
} ;
2013-10-10 09:30:04 +05:30
module_platform_driver ( xillybus_platform_driver ) ;