2010-11-24 12:17:14 +03:00
/*
* CE4100 ' s SPI device is more or less the same one as found on PXA
*
*/
# include <linux/pci.h>
# include <linux/platform_device.h>
# include <linux/of_device.h>
2011-07-03 23:44:29 +04:00
# include <linux/module.h>
2010-11-24 12:17:14 +03:00
# include <linux/spi/pxa2xx_spi.h>
2014-07-24 21:10:54 +04:00
# include <linux/clk.h>
# include <linux/clk-provider.h>
2010-11-24 12:17:14 +03:00
2014-08-19 21:29:19 +04:00
# include <linux/dmaengine.h>
# include <linux/platform_data/dma-dw.h>
2014-04-17 20:26:06 +04:00
enum {
PORT_CE4100 ,
PORT_BYT ,
2014-08-19 21:29:21 +04:00
PORT_BSW0 ,
PORT_BSW1 ,
PORT_BSW2 ,
2014-04-17 20:26:06 +04:00
} ;
struct pxa_spi_info {
enum pxa_ssp_type type ;
int port_id ;
int num_chipselect ;
2014-07-24 21:10:54 +04:00
unsigned long max_clk_rate ;
2014-08-19 21:29:19 +04:00
/* DMA channel request parameters */
void * tx_param ;
void * rx_param ;
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 } ;
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 } ;
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 ;
}
2014-04-17 20:26:06 +04:00
static struct pxa_spi_info spi_info_configs [ ] = {
[ PORT_CE4100 ] = {
. type = PXA25x_SSP ,
. port_id = - 1 ,
. num_chipselect = - 1 ,
2014-07-24 21:10:54 +04:00
. max_clk_rate = 3686400 ,
2014-04-17 20:26:06 +04:00
} ,
[ PORT_BYT ] = {
. type = LPSS_SSP ,
. port_id = 0 ,
. num_chipselect = 1 ,
2014-07-24 21:10:54 +04:00
. max_clk_rate = 50000000 ,
2014-08-19 21:29:19 +04:00
. tx_param = & byt_tx_param ,
. rx_param = & byt_rx_param ,
2014-04-17 20:26:06 +04:00
} ,
2014-08-19 21:29:21 +04:00
[ PORT_BSW0 ] = {
. type = LPSS_SSP ,
. port_id = 0 ,
. num_chipselect = 1 ,
. max_clk_rate = 50000000 ,
. tx_param = & bsw0_tx_param ,
. rx_param = & bsw0_rx_param ,
} ,
[ PORT_BSW1 ] = {
. type = LPSS_SSP ,
. port_id = 1 ,
. num_chipselect = 1 ,
. max_clk_rate = 50000000 ,
. tx_param = & bsw1_tx_param ,
. rx_param = & bsw1_rx_param ,
} ,
[ PORT_BSW2 ] = {
. type = LPSS_SSP ,
. port_id = 2 ,
. num_chipselect = 1 ,
. max_clk_rate = 50000000 ,
. tx_param = & bsw2_tx_param ,
. rx_param = & bsw2_rx_param ,
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 )
{
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 ;
2011-02-02 22:01:21 +03:00
struct pxa2xx_spi_master spi_pdata ;
2010-11-24 12:17:14 +03:00
struct ssp_device * ssp ;
2014-04-17 20:26:06 +04:00
struct pxa_spi_info * c ;
2014-07-24 21:10:54 +04:00
char buf [ 40 ] ;
2014-08-19 21:29:19 +04:00
struct pci_dev * dma_dev ;
2010-11-24 12:17:14 +03:00
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 ;
2014-04-17 20:26:06 +04:00
c = & spi_info_configs [ ent - > driver_data ] ;
2011-02-02 22:01:21 +03:00
memset ( & spi_pdata , 0 , sizeof ( spi_pdata ) ) ;
2014-04-17 20:26:06 +04:00
spi_pdata . num_chipselect = ( c - > num_chipselect > 0 ) ?
c - > num_chipselect : dev - > devfn ;
2014-08-19 21:29:19 +04:00
dma_dev = pci_get_slot ( dev - > bus , PCI_DEVFN ( PCI_SLOT ( dev - > devfn ) , 0 ) ) ;
if ( c - > tx_param ) {
struct dw_dma_slave * slave = c - > tx_param ;
slave - > dma_dev = & dma_dev - > dev ;
slave - > src_master = 1 ;
slave - > dst_master = 0 ;
}
if ( c - > rx_param ) {
struct dw_dma_slave * slave = c - > rx_param ;
slave - > dma_dev = & dma_dev - > dev ;
slave - > src_master = 1 ;
slave - > dst_master = 0 ;
}
spi_pdata . dma_filter = lpss_dma_filter ;
spi_pdata . tx_param = c - > tx_param ;
spi_pdata . rx_param = c - > rx_param ;
spi_pdata . enable_dma = c - > rx_param & & c - > tx_param ;
2010-11-24 12:17:14 +03:00
2013-01-07 14:44:33 +04:00
ssp = & spi_pdata . ssp ;
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 ] ;
2010-11-24 12:17:14 +03:00
if ( ! ssp - > mmio_base ) {
2013-01-07 14:44:32 +04:00
dev_err ( & dev - > dev , " failed to ioremap() registers \n " ) ;
return - EIO ;
2010-11-24 12:17:14 +03:00
}
ssp - > irq = dev - > irq ;
2014-04-17 20:26:06 +04:00
ssp - > port_id = ( c - > port_id > = 0 ) ? c - > port_id : dev - > devfn ;
ssp - > type = c - > type ;
2010-11-24 12:17:14 +03:00
2014-07-24 21:10:54 +04:00
snprintf ( buf , sizeof ( buf ) , " pxa2xx-spi.%d " , ssp - > port_id ) ;
ssp - > clk = clk_register_fixed_rate ( & dev - > dev , buf , NULL ,
CLK_IS_ROOT , c - > max_clk_rate ) ;
if ( IS_ERR ( ssp - > clk ) )
return PTR_ERR ( ssp - > clk ) ;
2013-01-07 14:44:32 +04:00
memset ( & pi , 0 , sizeof ( pi ) ) ;
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 ) ;
2014-07-24 21:10:54 +04:00
if ( IS_ERR ( pdev ) ) {
clk_unregister ( ssp - > clk ) ;
2013-02-22 06:52:35 +04:00
return PTR_ERR ( pdev ) ;
2014-07-24 21:10:54 +04:00
}
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 ) ;
2014-07-24 21:10:54 +04:00
struct pxa2xx_spi_master * spi_pdata ;
spi_pdata = dev_get_platdata ( & pdev - > dev ) ;
2010-11-24 12:17:14 +03:00
2013-01-07 14:44:33 +04:00
platform_device_unregister ( pdev ) ;
2014-07-24 21:10:54 +04:00
clk_unregister ( spi_pdata - > ssp . clk ) ;
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 [ ] = {
{ PCI_VDEVICE ( INTEL , 0x2e6a ) , PORT_CE4100 } ,
{ PCI_VDEVICE ( INTEL , 0x0f0e ) , PORT_BYT } ,
2014-08-19 21:29:21 +04:00
{ PCI_VDEVICE ( INTEL , 0x228e ) , PORT_BSW0 } ,
{ PCI_VDEVICE ( INTEL , 0x2290 ) , PORT_BSW1 } ,
{ PCI_VDEVICE ( INTEL , 0x22ac ) , PORT_BSW2 } ,
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> " ) ;