2007-02-02 16:38:41 +09:00
/*
* SCC ( Super Companion Chip ) UHC setup
*
* ( C ) Copyright 2006 - 2007 TOSHIBA CORPORATION
*
* 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 ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
# include <linux/kernel.h>
# include <linux/pci.h>
# include <asm/delay.h>
# include <asm/io.h>
# include <asm/machdep.h>
2008-04-24 19:26:28 +10:00
# include "celleb_scc.h"
2007-02-02 16:38:41 +09:00
# define UHC_RESET_WAIT_MAX 10000
static inline int uhc_clkctrl_ready ( u32 val )
{
const u32 mask = SCC_UHC_USBCEN | SCC_UHC_USBCEN ;
return ( ( val & mask ) = = mask ) ;
}
/*
2007-10-19 23:10:43 +02:00
* UHC ( usb host controller ) enable function .
2007-02-02 16:38:41 +09:00
* affect to both of OHCI and EHCI core module .
*/
static void enable_scc_uhc ( struct pci_dev * dev )
{
void __iomem * uhc_base ;
u32 __iomem * uhc_clkctrl ;
u32 __iomem * uhc_ecmode ;
u32 val = 0 ;
int i ;
2007-12-13 21:13:14 +11:00
if ( ! machine_is ( celleb_beat ) & &
! machine_is ( celleb_native ) )
2007-02-02 16:38:41 +09:00
return ;
uhc_base = ioremap ( pci_resource_start ( dev , 0 ) ,
pci_resource_len ( dev , 0 ) ) ;
if ( ! uhc_base ) {
printk ( KERN_ERR " failed to map UHC register base. \n " ) ;
return ;
}
uhc_clkctrl = uhc_base + SCC_UHC_CKRCTRL ;
uhc_ecmode = uhc_base + SCC_UHC_ECMODE ;
/* setup for normal mode */
val | = SCC_UHC_F48MCKLEN ;
out_be32 ( uhc_clkctrl , val ) ;
val | = SCC_UHC_PHY_SUSPEND_SEL ;
out_be32 ( uhc_clkctrl , val ) ;
udelay ( 10 ) ;
val | = SCC_UHC_PHYEN ;
out_be32 ( uhc_clkctrl , val ) ;
udelay ( 50 ) ;
/* disable reset */
val | = SCC_UHC_HCLKEN ;
out_be32 ( uhc_clkctrl , val ) ;
val | = ( SCC_UHC_USBCEN | SCC_UHC_USBEN ) ;
out_be32 ( uhc_clkctrl , val ) ;
i = 0 ;
while ( ! uhc_clkctrl_ready ( in_be32 ( uhc_clkctrl ) ) ) {
udelay ( 10 ) ;
if ( i + + > UHC_RESET_WAIT_MAX ) {
printk ( KERN_ERR " Failed to disable UHC reset %x \n " ,
in_be32 ( uhc_clkctrl ) ) ;
break ;
}
}
/* Endian Conversion Mode for Master ALL area */
out_be32 ( uhc_ecmode , SCC_UHC_ECMODE_BY_BYTE ) ;
iounmap ( uhc_base ) ;
}
DECLARE_PCI_FIXUP_HEADER ( PCI_VENDOR_ID_TOSHIBA_2 ,
PCI_DEVICE_ID_TOSHIBA_SCC_USB , enable_scc_uhc ) ;