2017-11-03 13:28:30 +03:00
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2013-03-12 04:48:01 +04:00
/*
* pci . c - DesignWare HS OTG Controller PCI driver
*
* Copyright ( C ) 2004 - 2013 Synopsys , Inc .
*/
/*
* Provides the initialization and cleanup entry points for the DWC_otg PCI
* driver
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/spinlock.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/slab.h>
# include <linux/pci.h>
# include <linux/usb.h>
# include <linux/usb/hcd.h>
# include <linux/usb/ch11.h>
2015-03-04 04:17:49 +03:00
# include <linux/platform_device.h>
# include <linux/usb/usb_phy_generic.h>
2013-03-12 04:48:01 +04:00
# define PCI_PRODUCT_ID_HAPS_HSOTG 0xabc0
2015-03-04 04:17:49 +03:00
static const char dwc2_driver_name [ ] = " dwc2-pci " ;
struct dwc2_pci_glue {
struct platform_device * dwc2 ;
struct platform_device * phy ;
2013-03-12 04:48:01 +04:00
} ;
2018-05-16 11:04:24 +03:00
/**
2021-05-26 16:00:25 +03:00
* dwc2_pci_remove ( ) - Provides the cleanup entry points for the DWC_otg PCI
2018-05-16 11:04:24 +03:00
* driver
*
* @ pci : The programming view of DWC_otg PCI
*/
2015-03-04 04:17:49 +03:00
static void dwc2_pci_remove ( struct pci_dev * pci )
2013-03-12 04:48:01 +04:00
{
2015-03-04 04:17:49 +03:00
struct dwc2_pci_glue * glue = pci_get_drvdata ( pci ) ;
2013-03-12 04:48:01 +04:00
2015-03-04 04:17:49 +03:00
platform_device_unregister ( glue - > dwc2 ) ;
usb_phy_generic_unregister ( glue - > phy ) ;
pci_set_drvdata ( pci , NULL ) ;
2013-03-12 04:48:01 +04:00
}
2015-03-04 04:17:49 +03:00
static int dwc2_pci_probe ( struct pci_dev * pci ,
2017-01-18 07:30:27 +03:00
const struct pci_device_id * id )
2013-03-12 04:48:01 +04:00
{
2015-03-04 04:17:49 +03:00
struct resource res [ 2 ] ;
struct platform_device * dwc2 ;
struct platform_device * phy ;
int ret ;
struct device * dev = & pci - > dev ;
struct dwc2_pci_glue * glue ;
ret = pcim_enable_device ( pci ) ;
if ( ret ) {
dev_err ( dev , " failed to enable pci device \n " ) ;
return - ENODEV ;
}
pci_set_master ( pci ) ;
2013-03-12 04:48:01 +04:00
2018-01-19 13:45:38 +03:00
phy = usb_phy_generic_register ( ) ;
if ( IS_ERR ( phy ) ) {
dev_err ( dev , " error registering generic PHY (%ld) \n " ,
PTR_ERR ( phy ) ) ;
return PTR_ERR ( phy ) ;
}
2015-03-04 04:17:49 +03:00
dwc2 = platform_device_alloc ( " dwc2 " , PLATFORM_DEVID_AUTO ) ;
if ( ! dwc2 ) {
dev_err ( dev , " couldn't allocate dwc2 device \n " ) ;
2018-10-18 10:36:47 +03:00
ret = - ENOMEM ;
2018-01-19 13:46:30 +03:00
goto err ;
2015-03-04 04:17:49 +03:00
}
2013-03-12 04:48:01 +04:00
2015-03-04 04:17:49 +03:00
memset ( res , 0x00 , sizeof ( struct resource ) * ARRAY_SIZE ( res ) ) ;
2013-03-12 04:48:01 +04:00
2015-03-04 04:17:49 +03:00
res [ 0 ] . start = pci_resource_start ( pci , 0 ) ;
res [ 0 ] . end = pci_resource_end ( pci , 0 ) ;
res [ 0 ] . name = " dwc2 " ;
res [ 0 ] . flags = IORESOURCE_MEM ;
2013-03-12 04:48:01 +04:00
2015-03-04 04:17:49 +03:00
res [ 1 ] . start = pci - > irq ;
res [ 1 ] . name = " dwc2 " ;
res [ 1 ] . flags = IORESOURCE_IRQ ;
2013-03-12 04:48:01 +04:00
2015-03-04 04:17:49 +03:00
ret = platform_device_add_resources ( dwc2 , res , ARRAY_SIZE ( res ) ) ;
if ( ret ) {
dev_err ( dev , " couldn't add resources to dwc2 device \n " ) ;
2018-01-19 13:46:30 +03:00
goto err ;
2015-03-04 04:17:49 +03:00
}
2013-03-12 04:48:01 +04:00
2015-03-04 04:17:49 +03:00
dwc2 - > dev . parent = dev ;
2014-11-11 20:13:37 +03:00
2018-01-19 13:46:04 +03:00
glue = devm_kzalloc ( dev , sizeof ( * glue ) , GFP_KERNEL ) ;
2018-03-28 16:41:13 +03:00
if ( ! glue ) {
ret = - ENOMEM ;
2018-01-19 13:46:30 +03:00
goto err ;
2018-03-28 16:41:13 +03:00
}
2018-01-19 13:46:04 +03:00
2015-03-04 04:17:49 +03:00
ret = platform_device_add ( dwc2 ) ;
if ( ret ) {
dev_err ( dev , " failed to register dwc2 device \n " ) ;
goto err ;
}
glue - > phy = phy ;
glue - > dwc2 = dwc2 ;
pci_set_drvdata ( pci , glue ) ;
2013-03-12 04:48:01 +04:00
2015-03-04 04:17:49 +03:00
return 0 ;
err :
usb_phy_generic_unregister ( phy ) ;
platform_device_put ( dwc2 ) ;
return ret ;
2013-03-12 04:48:01 +04:00
}
2013-12-03 03:26:00 +04:00
static const struct pci_device_id dwc2_pci_ids [ ] = {
2013-03-12 04:48:01 +04:00
{
PCI_DEVICE ( PCI_VENDOR_ID_SYNOPSYS , PCI_PRODUCT_ID_HAPS_HSOTG ) ,
} ,
2013-05-13 21:54:12 +04:00
{
PCI_DEVICE ( PCI_VENDOR_ID_STMICRO ,
PCI_DEVICE_ID_STMICRO_USB_OTG ) ,
} ,
2013-03-12 04:48:01 +04:00
{ /* end: all zeroes */ }
} ;
MODULE_DEVICE_TABLE ( pci , dwc2_pci_ids ) ;
static struct pci_driver dwc2_pci_driver = {
. name = dwc2_driver_name ,
. id_table = dwc2_pci_ids ,
2015-03-04 04:17:49 +03:00
. probe = dwc2_pci_probe ,
. remove = dwc2_pci_remove ,
2013-03-12 04:48:01 +04:00
} ;
module_pci_driver ( dwc2_pci_driver ) ;
MODULE_DESCRIPTION ( " DESIGNWARE HS OTG PCI Bus Glue " ) ;
MODULE_AUTHOR ( " Synopsys, Inc. " ) ;
MODULE_LICENSE ( " Dual BSD/GPL " ) ;