2010-12-07 17:53:59 +05:30
/*
* ci13xxx_pci . c - MIPS USB IP core family device controller
*
* Copyright ( C ) 2008 Chipidea - MIPS Technologies , Inc . All rights reserved .
*
* Author : David Lopo
*
* 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 .
*/
2012-05-08 23:29:01 +03:00
# include <linux/platform_device.h>
2010-12-07 17:53:59 +05:30
# include <linux/module.h>
# include <linux/pci.h>
2012-05-08 23:29:01 +03:00
# include <linux/interrupt.h>
# include <linux/usb/gadget.h>
2012-05-11 17:25:46 +03:00
# include <linux/usb/chipidea.h>
2010-12-07 17:53:59 +05:30
/* driver name */
# define UDC_DRIVER_NAME "ci13xxx_pci"
/******************************************************************************
* PCI block
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-03-30 12:54:02 +02:00
static struct ci13xxx_platform_data pci_platdata = {
2012-05-08 23:29:01 +03:00
. name = UDC_DRIVER_NAME ,
. capoffset = DEF_CAPOFFSET ,
} ;
2010-12-07 17:53:59 +05:30
2013-03-30 12:54:02 +02:00
static struct ci13xxx_platform_data langwell_pci_platdata = {
2010-12-07 17:54:02 +05:30
. name = UDC_DRIVER_NAME ,
2012-05-08 23:29:01 +03:00
. capoffset = 0 ,
2010-12-07 17:54:02 +05:30
} ;
2013-03-30 12:54:02 +02:00
static struct ci13xxx_platform_data penwell_pci_platdata = {
2012-05-11 17:25:55 +03:00
. name = UDC_DRIVER_NAME ,
. capoffset = 0 ,
. power_budget = 200 ,
} ;
2010-12-07 17:53:59 +05:30
/**
* ci13xxx_pci_probe : PCI probe
* @ pdev : USB device controller being probed
* @ id : PCI hotplug ID connecting controller to UDC framework
*
* This function returns an error code
* Allocates basic PCI resources for this USB device controller , and then
* invokes the udc_probe ( ) method to start the UDC associated with it
*/
2012-11-19 13:21:48 -05:00
static int ci13xxx_pci_probe ( struct pci_dev * pdev ,
2010-12-07 17:53:59 +05:30
const struct pci_device_id * id )
{
2012-06-29 17:48:53 +08:00
struct ci13xxx_platform_data * platdata = ( void * ) id - > driver_data ;
2012-05-08 23:29:01 +03:00
struct platform_device * plat_ci ;
struct resource res [ 3 ] ;
int retval = 0 , nres = 2 ;
2010-12-07 17:53:59 +05:30
2012-06-29 17:48:53 +08:00
if ( ! platdata ) {
2012-05-11 17:25:40 +03:00
dev_err ( & pdev - > dev , " device doesn't provide driver data \n " ) ;
return - ENODEV ;
}
2010-12-07 17:53:59 +05:30
retval = pci_enable_device ( pdev ) ;
if ( retval )
goto done ;
if ( ! pdev - > irq ) {
dev_err ( & pdev - > dev , " No IRQ, check BIOS/PCI setup! " ) ;
retval = - ENODEV ;
goto disable_device ;
}
2012-05-08 23:29:01 +03:00
pci_set_power_state ( pdev , PCI_D0 ) ;
2010-12-07 17:53:59 +05:30
pci_set_master ( pdev ) ;
pci_try_set_mwi ( pdev ) ;
2012-05-08 23:29:01 +03:00
memset ( res , 0 , sizeof ( res ) ) ;
res [ 0 ] . start = pci_resource_start ( pdev , 0 ) ;
res [ 0 ] . end = pci_resource_end ( pdev , 0 ) ;
res [ 0 ] . flags = IORESOURCE_MEM ;
res [ 1 ] . start = pdev - > irq ;
res [ 1 ] . flags = IORESOURCE_IRQ ;
2012-07-07 22:56:41 +08:00
plat_ci = ci13xxx_add_device ( & pdev - > dev , res , nres , platdata ) ;
if ( IS_ERR ( plat_ci ) ) {
dev_err ( & pdev - > dev , " ci13xxx_add_device failed! \n " ) ;
retval = PTR_ERR ( plat_ci ) ;
goto disable_device ;
2012-05-08 23:29:01 +03:00
}
pci_set_drvdata ( pdev , plat_ci ) ;
2010-12-07 17:53:59 +05:30
return 0 ;
disable_device :
pci_disable_device ( pdev ) ;
done :
return retval ;
}
/**
* ci13xxx_pci_remove : PCI remove
* @ pdev : USB Device Controller being removed
*
* Reverses the effect of ci13xxx_pci_probe ( ) ,
* first invoking the udc_remove ( ) and then releases
* all PCI resources allocated for this USB device controller
*/
2012-11-19 13:26:20 -05:00
static void ci13xxx_pci_remove ( struct pci_dev * pdev )
2010-12-07 17:53:59 +05:30
{
2012-05-08 23:29:01 +03:00
struct platform_device * plat_ci = pci_get_drvdata ( pdev ) ;
2012-07-07 22:56:41 +08:00
ci13xxx_remove_device ( plat_ci ) ;
2012-05-08 23:29:01 +03:00
pci_set_drvdata ( pdev , NULL ) ;
2010-12-07 17:53:59 +05:30
pci_disable_device ( pdev ) ;
}
/**
* PCI device table
* PCI device structure
*
* Check " pci.h " for details
*/
static DEFINE_PCI_DEVICE_TABLE ( ci13xxx_pci_id_table ) = {
2012-05-08 23:29:01 +03:00
{
PCI_DEVICE ( 0x153F , 0x1004 ) ,
2012-06-29 17:48:53 +08:00
. driver_data = ( kernel_ulong_t ) & pci_platdata ,
2012-05-08 23:29:01 +03:00
} ,
{
PCI_DEVICE ( 0x153F , 0x1006 ) ,
2012-06-29 17:48:53 +08:00
. driver_data = ( kernel_ulong_t ) & pci_platdata ,
2012-05-08 23:29:01 +03:00
} ,
{
PCI_DEVICE ( PCI_VENDOR_ID_INTEL , 0x0811 ) ,
2012-06-29 17:48:53 +08:00
. driver_data = ( kernel_ulong_t ) & langwell_pci_platdata ,
2012-05-08 23:29:01 +03:00
} ,
{
PCI_DEVICE ( PCI_VENDOR_ID_INTEL , 0x0829 ) ,
2012-06-29 17:48:53 +08:00
. driver_data = ( kernel_ulong_t ) & penwell_pci_platdata ,
2012-05-08 23:29:01 +03:00
} ,
2010-12-07 17:53:59 +05:30
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 /* end: all zeroes */ }
} ;
MODULE_DEVICE_TABLE ( pci , ci13xxx_pci_id_table ) ;
static struct pci_driver ci13xxx_pci_driver = {
. name = UDC_DRIVER_NAME ,
. id_table = ci13xxx_pci_id_table ,
. probe = ci13xxx_pci_probe ,
2012-11-19 13:21:08 -05:00
. remove = ci13xxx_pci_remove ,
2010-12-07 17:53:59 +05:30
} ;
2012-04-04 22:14:58 +08:00
module_pci_driver ( ci13xxx_pci_driver ) ;
2010-12-07 17:53:59 +05:30
MODULE_AUTHOR ( " MIPS - David Lopo <dlopo@chipidea.mips.com> " ) ;
MODULE_DESCRIPTION ( " MIPS CI13XXX USB Peripheral Controller " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_VERSION ( " June 2008 " ) ;