2019-01-07 13:07:41 +02:00
// SPDX-License-Identifier: GPL-2.0
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 >
*/
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/device.h>
# include "internal.h"
static int dw_pci_probe ( struct pci_dev * pdev , const struct pci_device_id * pid )
{
2019-08-20 16:15:39 +03:00
const struct dw_dma_chip_pdata * drv_data = ( void * ) pid - > driver_data ;
struct dw_dma_chip_pdata * 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 ;
2019-06-14 14:06:04 +03:00
data = devm_kmemdup ( & pdev - > dev , drv_data , sizeof ( * drv_data ) , GFP_KERNEL ) ;
if ( ! data )
return - ENOMEM ;
2013-06-05 15:26:46 +03:00
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-06-14 14:06:04 +03:00
data - > chip = chip ;
2019-01-07 13:07:38 +02:00
ret = data - > probe ( chip ) ;
2013-06-05 15:26:46 +03:00
if ( ret )
return ret ;
2019-06-14 14:06:04 +03:00
pci_set_drvdata ( pdev , data ) ;
2013-06-05 15:26:46 +03:00
return 0 ;
}
static void dw_pci_remove ( struct pci_dev * pdev )
{
2019-08-20 16:15:39 +03:00
struct dw_dma_chip_pdata * data = pci_get_drvdata ( pdev ) ;
2019-06-14 14:06:04 +03:00
struct dw_dma_chip * chip = data - > chip ;
2013-06-05 15:26:46 +03:00
int ret ;
2019-06-14 14:06:04 +03:00
ret = data - > remove ( chip ) ;
2013-06-05 15:26:46 +03:00
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 )
{
2019-08-20 16:15:39 +03:00
struct dw_dma_chip_pdata * data = dev_get_drvdata ( dev ) ;
2019-06-14 14:06:04 +03:00
struct dw_dma_chip * chip = data - > chip ;
2014-03-15 02:02:39 +08:00
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 )
{
2019-08-20 16:15:39 +03:00
struct dw_dma_chip_pdata * data = dev_get_drvdata ( dev ) ;
2019-06-14 14:06:04 +03:00
struct dw_dma_chip * chip = data - > chip ;
2014-03-15 02:02:39 +08:00
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-08-20 16:15:39 +03:00
{ PCI_VDEVICE ( INTEL , 0x0827 ) , ( kernel_ulong_t ) & dw_dma_chip_pdata } ,
2013-06-05 15:26:46 +03:00
/* BayTrail */
2019-08-20 16:15:39 +03:00
{ PCI_VDEVICE ( INTEL , 0x0f06 ) , ( kernel_ulong_t ) & dw_dma_chip_pdata } ,
{ PCI_VDEVICE ( INTEL , 0x0f40 ) , ( kernel_ulong_t ) & dw_dma_chip_pdata } ,
2014-02-06 13:26:55 +02:00
2019-01-07 13:07:38 +02:00
/* Merrifield */
2019-08-20 16:15:39 +03:00
{ PCI_VDEVICE ( INTEL , 0x11a2 ) , ( kernel_ulong_t ) & idma32_chip_pdata } ,
2017-01-17 13:57:32 +02:00
2014-08-19 20:29:18 +03:00
/* Braswell */
2019-08-20 16:15:39 +03:00
{ PCI_VDEVICE ( INTEL , 0x2286 ) , ( kernel_ulong_t ) & dw_dma_chip_pdata } ,
{ PCI_VDEVICE ( INTEL , 0x22c0 ) , ( kernel_ulong_t ) & dw_dma_chip_pdata } ,
2014-08-19 20:29:18 +03:00
2019-08-13 11:06:02 +03:00
/* Elkhart Lake iDMA 32-bit (PSE DMA) */
2019-08-20 16:15:39 +03:00
{ PCI_VDEVICE ( INTEL , 0x4bb4 ) , ( kernel_ulong_t ) & idma32_chip_pdata } ,
{ PCI_VDEVICE ( INTEL , 0x4bb5 ) , ( kernel_ulong_t ) & idma32_chip_pdata } ,
{ PCI_VDEVICE ( INTEL , 0x4bb6 ) , ( kernel_ulong_t ) & idma32_chip_pdata } ,
2019-06-21 16:19:14 +03:00
2014-02-06 13:26:55 +02:00
/* Haswell */
2019-08-20 16:15:39 +03:00
{ PCI_VDEVICE ( INTEL , 0x9c60 ) , ( kernel_ulong_t ) & dw_dma_chip_pdata } ,
2016-01-29 16:27:07 +02:00
/* Broadwell */
2019-08-20 16:15:39 +03:00
{ PCI_VDEVICE ( INTEL , 0x9ce0 ) , ( kernel_ulong_t ) & dw_dma_chip_pdata } ,
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> " ) ;