2009-10-28 01:14:59 +01:00
/*
* Copyright ( c ) 2009 Daniel Mack < daniel @ caiaq . de >
*
* 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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/platform_device.h>
# include <linux/io.h>
# include <mach/hardware.h>
# include <mach/mxc_ehci.h>
# define USBCTRL_OTGBASE_OFFSET 0x600
# define MX31_OTG_SIC_SHIFT 29
2010-02-04 14:45:11 +01:00
# define MX31_OTG_SIC_MASK (0x3 << MX31_OTG_SIC_SHIFT)
2009-10-28 01:14:59 +01:00
# define MX31_OTG_PM_BIT (1 << 24)
# define MX31_H2_SIC_SHIFT 21
2010-02-04 14:45:11 +01:00
# define MX31_H2_SIC_MASK (0x3 << MX31_H2_SIC_SHIFT)
2009-10-28 01:14:59 +01:00
# define MX31_H2_PM_BIT (1 << 16)
# define MX31_H2_DT_BIT (1 << 5)
# define MX31_H1_SIC_SHIFT 13
2010-02-04 14:45:11 +01:00
# define MX31_H1_SIC_MASK (0x3 << MX31_H1_SIC_SHIFT)
2009-10-28 01:14:59 +01:00
# define MX31_H1_PM_BIT (1 << 8)
# define MX31_H1_DT_BIT (1 << 4)
2010-02-04 14:34:48 +01:00
# define MX35_OTG_SIC_SHIFT 29
# define MX35_OTG_SIC_MASK (0x3 << MX35_OTG_SIC_SHIFT)
# define MX35_OTG_PM_BIT (1 << 24)
# define MX35_H1_SIC_SHIFT 21
# define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT)
# define MX35_H1_PM_BIT (1 << 8)
# define MX35_H1_IPPUE_UP_BIT (1 << 7)
# define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
# define MX35_H1_TLL_BIT (1 << 5)
# define MX35_H1_USBTE_BIT (1 << 4)
2009-10-28 01:14:59 +01:00
int mxc_set_usbcontrol ( int port , unsigned int flags )
{
unsigned int v ;
2010-02-04 14:45:41 +01:00
# ifdef CONFIG_ARCH_MX3
2009-10-28 01:14:59 +01:00
if ( cpu_is_mx31 ( ) ) {
2009-12-16 19:06:12 +01:00
v = readl ( MX31_IO_ADDRESS ( MX31_OTG_BASE_ADDR +
2009-10-28 01:14:59 +01:00
USBCTRL_OTGBASE_OFFSET ) ) ;
switch ( port ) {
case 0 : /* OTG port */
v & = ~ ( MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT ) ;
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX31_OTG_SIC_SHIFT ;
2010-02-04 14:45:11 +01:00
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
2009-10-28 01:14:59 +01:00
v | = MX31_OTG_PM_BIT ;
break ;
case 1 : /* H1 port */
2010-02-04 14:45:11 +01:00
v & = ~ ( MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT ) ;
2009-10-28 01:14:59 +01:00
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX31_H1_SIC_SHIFT ;
2010-02-04 14:45:11 +01:00
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
2009-10-28 01:14:59 +01:00
v | = MX31_H1_PM_BIT ;
if ( ! ( flags & MXC_EHCI_TTL_ENABLED ) )
v | = MX31_H1_DT_BIT ;
break ;
case 2 : /* H2 port */
2010-02-04 14:45:11 +01:00
v & = ~ ( MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT ) ;
2009-10-28 01:14:59 +01:00
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX31_H2_SIC_SHIFT ;
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
v | = MX31_H2_PM_BIT ;
if ( ! ( flags & MXC_EHCI_TTL_ENABLED ) )
v | = MX31_H2_DT_BIT ;
break ;
2010-02-04 14:45:11 +01:00
default :
return - EINVAL ;
2009-10-28 01:14:59 +01:00
}
2009-12-16 19:06:12 +01:00
writel ( v , MX31_IO_ADDRESS ( MX31_OTG_BASE_ADDR +
2009-10-28 01:14:59 +01:00
USBCTRL_OTGBASE_OFFSET ) ) ;
return 0 ;
}
2010-02-04 14:34:48 +01:00
if ( cpu_is_mx35 ( ) ) {
v = readl ( MX35_IO_ADDRESS ( MX35_OTG_BASE_ADDR +
USBCTRL_OTGBASE_OFFSET ) ) ;
switch ( port ) {
case 0 : /* OTG port */
v & = ~ ( MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT ) ;
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX35_OTG_SIC_SHIFT ;
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
v | = MX35_OTG_PM_BIT ;
break ;
case 1 : /* H1 port */
v & = ~ ( MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT ) ;
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX35_H1_SIC_SHIFT ;
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
v | = MX35_H1_PM_BIT ;
if ( ! ( flags & MXC_EHCI_TTL_ENABLED ) )
v | = MX35_H1_TLL_BIT ;
if ( flags & MXC_EHCI_INTERNAL_PHY )
v | = MX35_H1_USBTE_BIT ;
if ( flags & MXC_EHCI_IPPUE_DOWN )
v | = MX35_H1_IPPUE_DOWN_BIT ;
if ( flags & MXC_EHCI_IPPUE_UP )
v | = MX35_H1_IPPUE_UP_BIT ;
break ;
default :
return - EINVAL ;
}
writel ( v , MX35_IO_ADDRESS ( MX35_OTG_BASE_ADDR +
USBCTRL_OTGBASE_OFFSET ) ) ;
return 0 ;
}
2010-02-04 14:45:41 +01:00
# endif /* CONFIG_ARCH_MX3 */
# ifdef CONFIG_MACH_MX27
if ( cpu_is_mx27 ( ) ) {
/* On i.MX27 we can use the i.MX31 USBCTRL bits, they
* are identical
*/
v = readl ( MX27_IO_ADDRESS ( MX27_OTG_BASE_ADDR +
USBCTRL_OTGBASE_OFFSET ) ) ;
switch ( port ) {
case 0 : /* OTG port */
v & = ~ ( MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT ) ;
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX31_OTG_SIC_SHIFT ;
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
v | = MX31_OTG_PM_BIT ;
break ;
case 1 : /* H1 port */
v & = ~ ( MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT ) ;
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX31_H1_SIC_SHIFT ;
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
v | = MX31_H1_PM_BIT ;
if ( ! ( flags & MXC_EHCI_TTL_ENABLED ) )
v | = MX31_H1_DT_BIT ;
2009-10-28 01:14:59 +01:00
2010-02-04 14:45:41 +01:00
break ;
case 2 : /* H2 port */
v & = ~ ( MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT ) ;
v | = ( flags & MXC_EHCI_INTERFACE_MASK )
< < MX31_H2_SIC_SHIFT ;
if ( ! ( flags & MXC_EHCI_POWER_PINS_ENABLED ) )
v | = MX31_H2_PM_BIT ;
if ( ! ( flags & MXC_EHCI_TTL_ENABLED ) )
v | = MX31_H2_DT_BIT ;
break ;
default :
return - EINVAL ;
}
writel ( v , MX27_IO_ADDRESS ( MX27_OTG_BASE_ADDR +
USBCTRL_OTGBASE_OFFSET ) ) ;
return 0 ;
}
# endif /* CONFIG_MACH_MX27 */
2009-10-28 01:14:59 +01:00
printk ( KERN_WARNING
" %s() unable to setup USBCONTROL for this CPU \n " , __func__ ) ;
return - EINVAL ;
}
EXPORT_SYMBOL ( mxc_set_usbcontrol ) ;