2013-06-05 15:26:46 +03:00
/*
* PCI driver for the Synopsys DesignWare DMA Controller
*
* Copyright ( C ) 2013 Intel Corporation
* Author : Andy Shevchenko < andriy . shevchenko @ linux . intel . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/device.h>
# include "internal.h"
2019-01-07 13:07:38 +02:00
struct dw_dma_pci_data {
const struct dw_dma_platform_data * pdata ;
int ( * probe ) ( struct dw_dma_chip * chip ) ;
} ;
static const struct dw_dma_pci_data dw_pci_data = {
. probe = dw_dma_probe ,
} ;
static const struct dw_dma_platform_data idma32_pdata = {
2017-01-17 13:57:32 +02:00
. nr_channels = 8 ,
. chan_allocation_order = CHAN_ALLOCATION_ASCENDING ,
. chan_priority = CHAN_PRIORITY_ASCENDING ,
. block_size = 131071 ,
. nr_masters = 1 ,
. data_width = { 4 } ,
2019-01-07 13:07:35 +02:00
. multi_block = { 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 } ,
2017-01-17 13:57:32 +02:00
} ;
2019-01-07 13:07:38 +02:00
static const struct dw_dma_pci_data idma32_pci_data = {
. pdata = & idma32_pdata ,
. probe = idma32_dma_probe ,
} ;
2013-06-05 15:26:46 +03:00
static int dw_pci_probe ( struct pci_dev * pdev , const struct pci_device_id * pid )
{
2019-01-07 13:07:38 +02:00
const struct dw_dma_pci_data * data = ( void * ) pid - > driver_data ;
2013-06-05 15:26:46 +03:00
struct dw_dma_chip * chip ;
int ret ;
ret = pcim_enable_device ( pdev ) ;
if ( ret )
return ret ;
ret = pcim_iomap_regions ( pdev , 1 < < 0 , pci_name ( pdev ) ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " I/O memory remapping failed \n " ) ;
return ret ;
}
pci_set_master ( pdev ) ;
pci_try_set_mwi ( pdev ) ;
ret = pci_set_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ;
if ( ret )
return ret ;
ret = pci_set_consistent_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ;
if ( ret )
return ret ;
chip = devm_kzalloc ( & pdev - > dev , sizeof ( * chip ) , GFP_KERNEL ) ;
if ( ! chip )
return - ENOMEM ;
chip - > dev = & pdev - > dev ;
2017-01-17 13:57:26 +02:00
chip - > id = pdev - > devfn ;
2013-06-05 15:26:46 +03:00
chip - > regs = pcim_iomap_table ( pdev ) [ 0 ] ;
chip - > irq = pdev - > irq ;
2019-01-07 13:07:38 +02:00
chip - > pdata = data - > pdata ;
2013-06-05 15:26:46 +03:00
2019-01-07 13:07:38 +02:00
ret = data - > probe ( chip ) ;
2013-06-05 15:26:46 +03:00
if ( ret )
return ret ;
pci_set_drvdata ( pdev , chip ) ;
return 0 ;
}
static void dw_pci_remove ( struct pci_dev * pdev )
{
struct dw_dma_chip * chip = pci_get_drvdata ( pdev ) ;
int ret ;
ret = dw_dma_remove ( chip ) ;
if ( ret )
dev_warn ( & pdev - > dev , " can't remove device properly: %d \n " , ret ) ;
}
2014-03-15 02:02:39 +08:00
# ifdef CONFIG_PM_SLEEP
static int dw_pci_suspend_late ( struct device * dev )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
struct dw_dma_chip * chip = pci_get_drvdata ( pci ) ;
2019-01-07 13:07:38 +02:00
return do_dw_dma_disable ( chip ) ;
2014-03-15 02:02:39 +08:00
} ;
static int dw_pci_resume_early ( struct device * dev )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
struct dw_dma_chip * chip = pci_get_drvdata ( pci ) ;
2019-01-07 13:07:38 +02:00
return do_dw_dma_enable ( chip ) ;
2014-03-15 02:02:39 +08:00
} ;
2014-04-15 16:18:42 +03:00
# endif /* CONFIG_PM_SLEEP */
2014-03-15 02:02:39 +08:00
static const struct dev_pm_ops dw_pci_dev_pm_ops = {
2014-04-15 16:18:42 +03:00
SET_LATE_SYSTEM_SLEEP_PM_OPS ( dw_pci_suspend_late , dw_pci_resume_early )
2014-03-15 02:02:39 +08:00
} ;
2014-05-09 14:59:36 +09:00
static const struct pci_device_id dw_pci_id_table [ ] = {
2017-01-02 17:26:21 +02:00
/* Medfield (GPDMA) */
2019-01-07 13:07:38 +02:00
{ PCI_VDEVICE ( INTEL , 0x0827 ) , ( kernel_ulong_t ) & dw_pci_data } ,
2013-06-05 15:26:46 +03:00
/* BayTrail */
2019-01-07 13:07:38 +02:00
{ PCI_VDEVICE ( INTEL , 0x0f06 ) , ( kernel_ulong_t ) & dw_pci_data } ,
{ PCI_VDEVICE ( INTEL , 0x0f40 ) , ( kernel_ulong_t ) & dw_pci_data } ,
2014-02-06 13:26:55 +02:00
2019-01-07 13:07:38 +02:00
/* Merrifield */
{ PCI_VDEVICE ( INTEL , 0x11a2 ) , ( kernel_ulong_t ) & idma32_pci_data } ,
2017-01-17 13:57:32 +02:00
2014-08-19 20:29:18 +03:00
/* Braswell */
2019-01-07 13:07:38 +02:00
{ PCI_VDEVICE ( INTEL , 0x2286 ) , ( kernel_ulong_t ) & dw_pci_data } ,
{ PCI_VDEVICE ( INTEL , 0x22c0 ) , ( kernel_ulong_t ) & dw_pci_data } ,
2014-08-19 20:29:18 +03:00
2014-02-06 13:26:55 +02:00
/* Haswell */
2019-01-07 13:07:38 +02:00
{ PCI_VDEVICE ( INTEL , 0x9c60 ) , ( kernel_ulong_t ) & dw_pci_data } ,
2016-01-29 16:27:07 +02:00
/* Broadwell */
2019-01-07 13:07:38 +02:00
{ PCI_VDEVICE ( INTEL , 0x9ce0 ) , ( kernel_ulong_t ) & dw_pci_data } ,
2016-01-29 16:27:07 +02:00
2013-06-05 15:26:46 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( pci , dw_pci_id_table ) ;
static struct pci_driver dw_pci_driver = {
. name = " dw_dmac_pci " ,
. id_table = dw_pci_id_table ,
. probe = dw_pci_probe ,
. remove = dw_pci_remove ,
2014-03-15 02:02:39 +08:00
. driver = {
. pm = & dw_pci_dev_pm_ops ,
} ,
2013-06-05 15:26:46 +03:00
} ;
module_pci_driver ( dw_pci_driver ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " Synopsys DesignWare DMA Controller PCI driver " ) ;
MODULE_AUTHOR ( " Andy Shevchenko <andriy.shevchenko@linux.intel.com> " ) ;