2009-06-13 05:14:28 +04:00
/*
* linux / driver / usb / host / ehci - w90x900 . c
*
* Copyright ( c ) 2008 Nuvoton technology corporation .
*
* Wan ZongShun < mcuos . com @ gmail . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; version 2 of the License .
*
*/
# include <linux/platform_device.h>
/*ebable phy0 and phy1 for w90p910*/
# define ENPHY (0x01<<8)
# define PHY0_CTR (0xA4)
# define PHY1_CTR (0xA8)
static int __devinit usb_w90x900_probe ( const struct hc_driver * driver ,
struct platform_device * pdev )
{
struct usb_hcd * hcd ;
struct ehci_hcd * ehci ;
struct resource * res ;
int retval = 0 , irq ;
unsigned long val ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res ) {
retval = - ENXIO ;
goto err1 ;
}
hcd = usb_create_hcd ( driver , & pdev - > dev , " w90x900 EHCI " ) ;
if ( ! hcd ) {
retval = - ENOMEM ;
goto err1 ;
}
hcd - > rsrc_start = res - > start ;
hcd - > rsrc_len = res - > end - res - > start + 1 ;
if ( ! request_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len , hcd_name ) ) {
retval = - EBUSY ;
goto err2 ;
}
hcd - > regs = ioremap ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
if ( hcd - > regs = = NULL ) {
retval = - EFAULT ;
goto err3 ;
}
ehci = hcd_to_ehci ( hcd ) ;
ehci - > caps = hcd - > regs ;
ehci - > regs = hcd - > regs +
HC_LENGTH ( ehci_readl ( ehci , & ehci - > caps - > hc_capbase ) ) ;
/* enable PHY 0,1,the regs only apply to w90p910
* 0xA4 , 0xA8 were offsets of PHY0 and PHY1 controller of
* w90p910 IC relative to ehci - > regs .
*/
val = __raw_readl ( ehci - > regs + PHY0_CTR ) ;
val | = ENPHY ;
__raw_writel ( val , ehci - > regs + PHY0_CTR ) ;
val = __raw_readl ( ehci - > regs + PHY1_CTR ) ;
val | = ENPHY ;
__raw_writel ( val , ehci - > regs + PHY1_CTR ) ;
ehci - > hcs_params = ehci_readl ( ehci , & ehci - > caps - > hcs_params ) ;
ehci - > sbrn = 0x20 ;
irq = platform_get_irq ( pdev , 0 ) ;
if ( irq < 0 )
goto err4 ;
retval = usb_add_hcd ( hcd , irq , IRQF_SHARED ) ;
if ( retval ! = 0 )
goto err4 ;
ehci_writel ( ehci , 1 , & ehci - > regs - > configured_flag ) ;
return retval ;
err4 :
iounmap ( hcd - > regs ) ;
err3 :
release_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
err2 :
usb_put_hcd ( hcd ) ;
err1 :
return retval ;
}
static
void usb_w90x900_remove ( struct usb_hcd * hcd , struct platform_device * pdev )
{
usb_remove_hcd ( hcd ) ;
iounmap ( hcd - > regs ) ;
release_mem_region ( hcd - > rsrc_start , hcd - > rsrc_len ) ;
usb_put_hcd ( hcd ) ;
}
static const struct hc_driver ehci_w90x900_hc_driver = {
. description = hcd_name ,
. product_desc = " Nuvoton w90x900 EHCI Host Controller " ,
. hcd_priv_size = sizeof ( struct ehci_hcd ) ,
/*
* generic hardware linkage
*/
. irq = ehci_irq ,
. flags = HCD_USB2 | HCD_MEMORY ,
/*
* basic lifecycle operations
*/
. reset = ehci_init ,
. start = ehci_run ,
. stop = ehci_stop ,
. shutdown = ehci_shutdown ,
/*
* managing i / o requests and associated device resources
*/
. urb_enqueue = ehci_urb_enqueue ,
. urb_dequeue = ehci_urb_dequeue ,
. endpoint_disable = ehci_endpoint_disable ,
2010-11-30 11:57:02 +03:00
. endpoint_reset = ehci_endpoint_reset ,
2009-06-13 05:14:28 +04:00
/*
* scheduling support
*/
. get_frame_number = ehci_get_frame ,
/*
* root hub support
*/
. hub_status_data = ehci_hub_status_data ,
. hub_control = ehci_hub_control ,
# ifdef CONFIG_PM
. bus_suspend = ehci_bus_suspend ,
. bus_resume = ehci_bus_resume ,
# endif
. relinquish_port = ehci_relinquish_port ,
. port_handed_over = ehci_port_handed_over ,
2010-11-30 11:57:02 +03:00
. clear_tt_buffer_complete = ehci_clear_tt_buffer_complete ,
2009-06-13 05:14:28 +04:00
} ;
static int __devinit ehci_w90x900_probe ( struct platform_device * pdev )
{
if ( usb_disabled ( ) )
return - ENODEV ;
return usb_w90x900_probe ( & ehci_w90x900_hc_driver , pdev ) ;
}
static int __devexit ehci_w90x900_remove ( struct platform_device * pdev )
{
struct usb_hcd * hcd = platform_get_drvdata ( pdev ) ;
usb_w90x900_remove ( hcd , pdev ) ;
return 0 ;
}
static struct platform_driver ehci_hcd_w90x900_driver = {
. probe = ehci_w90x900_probe ,
. remove = __devexit_p ( ehci_w90x900_remove ) ,
. driver = {
. name = " w90x900-ehci " ,
. owner = THIS_MODULE ,
} ,
} ;
MODULE_AUTHOR ( " Wan ZongShun <mcuos.com@gmail.com> " ) ;
MODULE_DESCRIPTION ( " w90p910 usb ehci driver! " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform:w90p910-ehci " ) ;