2019-05-19 15:08:20 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-11-24 12:17:14 +03:00
/*
2021-05-17 17:03:49 +03:00
* PCI glue driver for SPI PXA2xx compatible controllers .
* CE4100 ' s SPI device is more or less the same one as found on PXA .
2010-11-24 12:17:14 +03:00
*
2021-05-17 17:03:49 +03:00
* Copyright ( C ) 2016 , 2021 Intel Corporation
2010-11-24 12:17:14 +03:00
*/
2016-07-04 12:44:27 +03:00
# include <linux/clk-provider.h>
# include <linux/module.h>
2010-11-24 12:17:14 +03:00
# include <linux/pci.h>
# include <linux/platform_device.h>
2021-04-23 21:24:31 +03:00
2010-11-24 12:17:14 +03:00
# include <linux/spi/pxa2xx_spi.h>
2014-08-19 21:29:19 +04:00
# include <linux/dmaengine.h>
# include <linux/platform_data/dma-dw.h>
2022-02-25 20:23:46 +03:00
# define PCI_DEVICE_ID_INTEL_QUARK_X1000 0x0935
# define PCI_DEVICE_ID_INTEL_BYT 0x0f0e
# define PCI_DEVICE_ID_INTEL_MRFLD 0x1194
# define PCI_DEVICE_ID_INTEL_BSW0 0x228e
# define PCI_DEVICE_ID_INTEL_BSW1 0x2290
# define PCI_DEVICE_ID_INTEL_BSW2 0x22ac
# define PCI_DEVICE_ID_INTEL_CE4100 0x2e6a
# define PCI_DEVICE_ID_INTEL_LPT0_0 0x9c65
# define PCI_DEVICE_ID_INTEL_LPT0_1 0x9c66
# define PCI_DEVICE_ID_INTEL_LPT1_0 0x9ce5
# define PCI_DEVICE_ID_INTEL_LPT1_1 0x9ce6
2014-04-17 20:26:06 +04:00
struct pxa_spi_info {
2022-02-25 20:23:49 +03:00
int ( * setup ) ( struct pci_dev * pdev , struct pxa2xx_spi_controller * c ) ;
2014-04-17 20:26:06 +04:00
} ;
2014-08-19 21:29:19 +04:00
static struct dw_dma_slave byt_tx_param = { . dst_id = 0 } ;
static struct dw_dma_slave byt_rx_param = { . src_id = 1 } ;
2017-01-02 14:47:31 +03:00
static struct dw_dma_slave mrfld3_tx_param = { . dst_id = 15 } ;
static struct dw_dma_slave mrfld3_rx_param = { . src_id = 14 } ;
static struct dw_dma_slave mrfld5_tx_param = { . dst_id = 13 } ;
static struct dw_dma_slave mrfld5_rx_param = { . src_id = 12 } ;
static struct dw_dma_slave mrfld6_tx_param = { . dst_id = 11 } ;
static struct dw_dma_slave mrfld6_rx_param = { . src_id = 10 } ;
2014-08-19 21:29:21 +04:00
static struct dw_dma_slave bsw0_tx_param = { . dst_id = 0 } ;
static struct dw_dma_slave bsw0_rx_param = { . src_id = 1 } ;
static struct dw_dma_slave bsw1_tx_param = { . dst_id = 6 } ;
static struct dw_dma_slave bsw1_rx_param = { . src_id = 7 } ;
static struct dw_dma_slave bsw2_tx_param = { . dst_id = 8 } ;
static struct dw_dma_slave bsw2_rx_param = { . src_id = 9 } ;
2021-02-08 19:38:15 +03:00
static struct dw_dma_slave lpt1_tx_param = { . dst_id = 0 } ;
static struct dw_dma_slave lpt1_rx_param = { . src_id = 1 } ;
static struct dw_dma_slave lpt0_tx_param = { . dst_id = 2 } ;
static struct dw_dma_slave lpt0_rx_param = { . src_id = 3 } ;
2016-02-20 22:20:22 +03:00
2022-02-25 20:23:48 +03:00
static void pxa2xx_spi_pci_clk_unregister ( void * clk )
{
clk_unregister ( clk ) ;
}
static int pxa2xx_spi_pci_clk_register ( struct pci_dev * dev , struct ssp_device * ssp ,
unsigned long rate )
{
char buf [ 40 ] ;
snprintf ( buf , sizeof ( buf ) , " pxa2xx-spi.%d " , ssp - > port_id ) ;
ssp - > clk = clk_register_fixed_rate ( & dev - > dev , buf , NULL , 0 , rate ) ;
if ( IS_ERR ( ssp - > clk ) )
return PTR_ERR ( ssp - > clk ) ;
return devm_add_action_or_reset ( & dev - > dev , pxa2xx_spi_pci_clk_unregister , ssp - > clk ) ;
}
2014-08-19 21:29:19 +04:00
static bool lpss_dma_filter ( struct dma_chan * chan , void * param )
{
struct dw_dma_slave * dws = param ;
if ( dws - > dma_dev ! = chan - > device - > dev )
return false ;
chan - > private = dws ;
return true ;
}
2022-02-23 22:16:37 +03:00
static void lpss_dma_put_device ( void * dma_dev )
{
pci_dev_put ( dma_dev ) ;
}
2022-02-25 20:23:49 +03:00
static int lpss_spi_setup ( struct pci_dev * dev , struct pxa2xx_spi_controller * c )
2016-07-04 12:44:24 +03:00
{
2022-02-25 20:23:49 +03:00
struct ssp_device * ssp = & c - > ssp ;
2022-02-25 20:23:47 +03:00
struct dw_dma_slave * tx , * rx ;
2016-07-04 12:44:24 +03:00
struct pci_dev * dma_dev ;
2022-02-23 22:16:37 +03:00
int ret ;
2016-07-04 12:44:24 +03:00
2022-02-25 20:23:46 +03:00
switch ( dev - > device ) {
case PCI_DEVICE_ID_INTEL_BYT :
2022-02-25 20:23:49 +03:00
ssp - > type = LPSS_BYT_SSP ;
ssp - > port_id = 0 ;
2022-02-25 20:23:46 +03:00
c - > tx_param = & byt_tx_param ;
c - > rx_param = & byt_rx_param ;
break ;
case PCI_DEVICE_ID_INTEL_BSW0 :
2022-02-25 20:23:49 +03:00
ssp - > type = LPSS_BSW_SSP ;
ssp - > port_id = 0 ;
2022-02-25 20:23:46 +03:00
c - > tx_param = & bsw0_tx_param ;
c - > rx_param = & bsw0_rx_param ;
break ;
case PCI_DEVICE_ID_INTEL_BSW1 :
2022-02-25 20:23:49 +03:00
ssp - > type = LPSS_BSW_SSP ;
ssp - > port_id = 1 ;
2022-02-25 20:23:46 +03:00
c - > tx_param = & bsw1_tx_param ;
c - > rx_param = & bsw1_rx_param ;
break ;
case PCI_DEVICE_ID_INTEL_BSW2 :
2022-02-25 20:23:49 +03:00
ssp - > type = LPSS_BSW_SSP ;
ssp - > port_id = 2 ;
2022-02-25 20:23:46 +03:00
c - > tx_param = & bsw2_tx_param ;
c - > rx_param = & bsw2_rx_param ;
break ;
case PCI_DEVICE_ID_INTEL_LPT0_0 :
case PCI_DEVICE_ID_INTEL_LPT1_0 :
2022-02-25 20:23:49 +03:00
ssp - > type = LPSS_LPT_SSP ;
ssp - > port_id = 0 ;
2022-02-25 20:23:46 +03:00
c - > tx_param = & lpt0_tx_param ;
c - > rx_param = & lpt0_rx_param ;
break ;
case PCI_DEVICE_ID_INTEL_LPT0_1 :
case PCI_DEVICE_ID_INTEL_LPT1_1 :
2022-02-25 20:23:49 +03:00
ssp - > type = LPSS_LPT_SSP ;
ssp - > port_id = 1 ;
2022-02-25 20:23:46 +03:00
c - > tx_param = & lpt1_tx_param ;
c - > rx_param = & lpt1_rx_param ;
break ;
default :
return - ENODEV ;
}
2016-07-04 12:44:24 +03:00
c - > num_chipselect = 1 ;
2022-02-25 20:23:49 +03:00
ret = pxa2xx_spi_pci_clk_register ( dev , ssp , 50000000 ) ;
if ( ret )
return ret ;
2016-07-04 12:44:24 +03:00
dma_dev = pci_get_slot ( dev - > bus , PCI_DEVFN ( PCI_SLOT ( dev - > devfn ) , 0 ) ) ;
2022-02-23 22:16:37 +03:00
ret = devm_add_action_or_reset ( & dev - > dev , lpss_dma_put_device , dma_dev ) ;
if ( ret )
return ret ;
2016-07-04 12:44:24 +03:00
2022-02-25 20:23:47 +03:00
tx = c - > tx_param ;
tx - > dma_dev = & dma_dev - > dev ;
tx - > m_master = 0 ;
tx - > p_master = 1 ;
2016-07-04 12:44:24 +03:00
2022-02-25 20:23:47 +03:00
rx = c - > rx_param ;
rx - > dma_dev = & dma_dev - > dev ;
rx - > m_master = 0 ;
rx - > p_master = 1 ;
2016-07-04 12:44:24 +03:00
c - > dma_filter = lpss_dma_filter ;
2022-02-25 20:23:44 +03:00
c - > dma_burst_size = 1 ;
2022-02-25 20:23:49 +03:00
c - > enable_dma = 1 ;
2016-07-04 12:44:24 +03:00
return 0 ;
}
2022-02-25 20:23:50 +03:00
static const struct pxa_spi_info lpss_info_config = {
2022-02-25 20:23:46 +03:00
. setup = lpss_spi_setup ,
} ;
2022-02-25 20:23:49 +03:00
static int ce4100_spi_setup ( struct pci_dev * dev , struct pxa2xx_spi_controller * c )
2022-02-25 20:23:40 +03:00
{
2022-02-25 20:23:49 +03:00
struct ssp_device * ssp = & c - > ssp ;
ssp - > type = PXA25x_SSP ;
ssp - > port_id = dev - > devfn ;
2022-02-25 20:23:40 +03:00
c - > num_chipselect = dev - > devfn ;
2022-02-25 20:23:49 +03:00
return pxa2xx_spi_pci_clk_register ( dev , ssp , 3686400 ) ;
2022-02-25 20:23:40 +03:00
}
2022-02-25 20:23:50 +03:00
static const struct pxa_spi_info ce4100_info_config = {
2022-02-25 20:23:46 +03:00
. setup = ce4100_spi_setup ,
} ;
2022-02-25 20:23:49 +03:00
static int mrfld_spi_setup ( struct pci_dev * dev , struct pxa2xx_spi_controller * c )
2016-07-04 12:44:25 +03:00
{
2022-02-25 20:23:49 +03:00
struct ssp_device * ssp = & c - > ssp ;
2017-01-02 14:47:31 +03:00
struct dw_dma_slave * tx , * rx ;
2022-02-23 22:16:37 +03:00
struct pci_dev * dma_dev ;
int ret ;
2017-01-02 14:47:31 +03:00
2022-02-25 20:23:49 +03:00
ssp - > type = MRFLD_SSP ;
2016-07-04 12:44:25 +03:00
switch ( PCI_FUNC ( dev - > devfn ) ) {
case 0 :
2022-02-25 20:23:49 +03:00
ssp - > port_id = 3 ;
2016-07-04 12:44:25 +03:00
c - > num_chipselect = 1 ;
2017-01-02 14:47:31 +03:00
c - > tx_param = & mrfld3_tx_param ;
c - > rx_param = & mrfld3_rx_param ;
2016-07-04 12:44:25 +03:00
break ;
case 1 :
2022-02-25 20:23:49 +03:00
ssp - > port_id = 5 ;
2016-07-04 12:44:25 +03:00
c - > num_chipselect = 4 ;
2017-01-02 14:47:31 +03:00
c - > tx_param = & mrfld5_tx_param ;
c - > rx_param = & mrfld5_rx_param ;
2016-07-04 12:44:25 +03:00
break ;
case 2 :
2022-02-25 20:23:49 +03:00
ssp - > port_id = 6 ;
2016-07-04 12:44:25 +03:00
c - > num_chipselect = 1 ;
2017-01-02 14:47:31 +03:00
c - > tx_param = & mrfld6_tx_param ;
c - > rx_param = & mrfld6_rx_param ;
2016-07-04 12:44:25 +03:00
break ;
default :
return - ENODEV ;
}
2017-01-02 14:47:31 +03:00
2022-02-25 20:23:49 +03:00
ret = pxa2xx_spi_pci_clk_register ( dev , ssp , 25000000 ) ;
if ( ret )
return ret ;
2022-02-25 20:23:45 +03:00
2022-02-23 22:16:37 +03:00
dma_dev = pci_get_slot ( dev - > bus , PCI_DEVFN ( 21 , 0 ) ) ;
ret = devm_add_action_or_reset ( & dev - > dev , lpss_dma_put_device , dma_dev ) ;
if ( ret )
return ret ;
2017-01-02 14:47:31 +03:00
tx = c - > tx_param ;
tx - > dma_dev = & dma_dev - > dev ;
rx = c - > rx_param ;
rx - > dma_dev = & dma_dev - > dev ;
c - > dma_filter = lpss_dma_filter ;
2019-03-19 18:48:42 +03:00
c - > dma_burst_size = 8 ;
2022-02-25 20:23:49 +03:00
c - > enable_dma = 1 ;
2016-07-04 12:44:25 +03:00
return 0 ;
}
2022-02-25 20:23:50 +03:00
static const struct pxa_spi_info mrfld_info_config = {
2022-02-25 20:23:46 +03:00
. setup = mrfld_spi_setup ,
} ;
2022-02-25 20:23:49 +03:00
static int qrk_spi_setup ( struct pci_dev * dev , struct pxa2xx_spi_controller * c )
2022-02-25 20:23:41 +03:00
{
2022-02-25 20:23:49 +03:00
struct ssp_device * ssp = & c - > ssp ;
ssp - > type = QUARK_X1000_SSP ;
ssp - > port_id = dev - > devfn ;
2022-02-25 20:23:41 +03:00
c - > num_chipselect = 1 ;
2022-02-25 20:23:49 +03:00
return pxa2xx_spi_pci_clk_register ( dev , ssp , 50000000 ) ;
2022-02-25 20:23:41 +03:00
}
2022-02-25 20:23:50 +03:00
static const struct pxa_spi_info qrk_info_config = {
2022-02-25 20:23:46 +03:00
. setup = qrk_spi_setup ,
2014-04-17 20:26:06 +04:00
} ;
static int pxa2xx_spi_pci_probe ( struct pci_dev * dev ,
2010-11-24 12:17:14 +03:00
const struct pci_device_id * ent )
{
2022-02-25 20:23:50 +03:00
const struct pxa_spi_info * info ;
2013-01-07 14:44:32 +04:00
struct platform_device_info pi ;
2010-11-24 12:17:14 +03:00
int ret ;
struct platform_device * pdev ;
2019-01-16 18:13:31 +03:00
struct pxa2xx_spi_controller spi_pdata ;
2010-11-24 12:17:14 +03:00
struct ssp_device * ssp ;
2013-01-07 14:44:32 +04:00
ret = pcim_enable_device ( dev ) ;
2010-11-24 12:17:14 +03:00
if ( ret )
return ret ;
2013-01-07 14:44:32 +04:00
ret = pcim_iomap_regions ( dev , 1 < < 0 , " PXA2xx SPI " ) ;
2013-03-05 14:05:16 +04:00
if ( ret )
2010-11-24 12:17:14 +03:00
return ret ;
2016-07-04 12:44:24 +03:00
memset ( & spi_pdata , 0 , sizeof ( spi_pdata ) ) ;
2010-11-24 12:17:14 +03:00
2013-01-07 14:44:33 +04:00
ssp = & spi_pdata . ssp ;
2021-04-23 21:24:30 +03:00
ssp - > dev = & dev - > dev ;
2010-11-24 12:17:14 +03:00
ssp - > phys_base = pci_resource_start ( dev , 0 ) ;
2013-01-07 14:44:32 +04:00
ssp - > mmio_base = pcim_iomap_table ( dev ) [ 0 ] ;
2022-02-25 20:23:49 +03:00
info = ( struct pxa_spi_info * ) ent - > driver_data ;
ret = info - > setup ( dev , & spi_pdata ) ;
if ( ret )
return ret ;
2010-11-24 12:17:14 +03:00
2017-01-21 12:06:39 +03:00
pci_set_master ( dev ) ;
ret = pci_alloc_irq_vectors ( dev , 1 , 1 , PCI_IRQ_ALL_TYPES ) ;
if ( ret < 0 )
return ret ;
ssp - > irq = pci_irq_vector ( dev , 0 ) ;
2013-01-07 14:44:32 +04:00
memset ( & pi , 0 , sizeof ( pi ) ) ;
2022-02-23 22:19:48 +03:00
pi . fwnode = dev_fwnode ( & dev - > dev ) ;
2013-01-07 14:44:32 +04:00
pi . parent = & dev - > dev ;
pi . name = " pxa2xx-spi " ;
pi . id = ssp - > port_id ;
pi . data = & spi_pdata ;
pi . size_data = sizeof ( spi_pdata ) ;
2010-11-24 12:17:14 +03:00
2013-01-07 14:44:32 +04:00
pdev = platform_device_register_full ( & pi ) ;
2022-02-25 20:23:48 +03:00
if ( IS_ERR ( pdev ) )
2013-02-22 06:52:35 +04:00
return PTR_ERR ( pdev ) ;
2010-11-24 12:17:14 +03:00
2013-01-07 14:44:33 +04:00
pci_set_drvdata ( dev , pdev ) ;
2010-11-24 12:17:14 +03:00
2013-01-07 14:44:32 +04:00
return 0 ;
2010-11-24 12:17:14 +03:00
}
2014-04-17 20:26:06 +04:00
static void pxa2xx_spi_pci_remove ( struct pci_dev * dev )
2010-11-24 12:17:14 +03:00
{
2013-01-07 14:44:33 +04:00
struct platform_device * pdev = pci_get_drvdata ( dev ) ;
2010-11-24 12:17:14 +03:00
2013-01-07 14:44:33 +04:00
platform_device_unregister ( pdev ) ;
2010-11-24 12:17:14 +03:00
}
2014-04-17 20:26:06 +04:00
static const struct pci_device_id pxa2xx_spi_pci_devices [ ] = {
2022-02-25 20:23:46 +03:00
{ PCI_DEVICE_DATA ( INTEL , QUARK_X1000 , & qrk_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , BYT , & lpss_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , MRFLD , & mrfld_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , BSW0 , & lpss_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , BSW1 , & lpss_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , BSW2 , & lpss_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , CE4100 , & ce4100_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , LPT0_0 , & lpss_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , LPT0_1 , & lpss_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , LPT1_0 , & lpss_info_config ) } ,
{ PCI_DEVICE_DATA ( INTEL , LPT1_1 , & lpss_info_config ) } ,
2021-02-08 19:38:15 +03:00
{ }
2010-11-24 12:17:14 +03:00
} ;
2014-04-17 20:26:06 +04:00
MODULE_DEVICE_TABLE ( pci , pxa2xx_spi_pci_devices ) ;
2010-11-24 12:17:14 +03:00
2014-04-17 20:26:06 +04:00
static struct pci_driver pxa2xx_spi_pci_driver = {
. name = " pxa2xx_spi_pci " ,
. id_table = pxa2xx_spi_pci_devices ,
. probe = pxa2xx_spi_pci_probe ,
. remove = pxa2xx_spi_pci_remove ,
2010-11-24 12:17:14 +03:00
} ;
2014-04-17 20:26:06 +04:00
module_pci_driver ( pxa2xx_spi_pci_driver ) ;
2010-11-24 12:17:14 +03:00
2014-04-17 20:26:06 +04:00
MODULE_DESCRIPTION ( " CE4100/LPSS PCI-SPI glue code for PXA's driver " ) ;
2010-11-24 12:17:14 +03:00
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_AUTHOR ( " Sebastian Andrzej Siewior <bigeasy@linutronix.de> " ) ;