2009-01-31 06:44:20 +03:00
/*
* arch / arm / mach - kirkwood / mpp . c
*
* MPP functions for Marvell Kirkwood SoCs
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/mbus.h>
# include <linux/io.h>
# include <asm/gpio.h>
# include <mach/hardware.h>
# include "common.h"
# include "mpp.h"
static unsigned int __init kirkwood_variant ( void )
{
u32 dev , rev ;
kirkwood_pcie_id ( & dev , & rev ) ;
if ( dev = = MV88F6281_DEV_ID & & rev > = MV88F6281_REV_A0 )
return MPP_F6281_MASK ;
if ( dev = = MV88F6192_DEV_ID & & rev > = MV88F6192_REV_A0 )
return MPP_F6192_MASK ;
if ( dev = = MV88F6180_DEV_ID )
return MPP_F6180_MASK ;
printk ( KERN_ERR " MPP setup: unknown kirkwood variant "
" (dev %#x rev %#x) \n " , dev , rev ) ;
return 0 ;
}
# define MPP_CTRL(i) (DEV_BUS_VIRT_BASE + (i) * 4)
# define MPP_NR_REGS (1 + MPP_MAX / 8)
void __init kirkwood_mpp_conf ( unsigned int * mpp_list )
{
u32 mpp_ctrl [ MPP_NR_REGS ] ;
unsigned int variant_mask ;
int i ;
variant_mask = kirkwood_variant ( ) ;
if ( ! variant_mask )
return ;
2009-05-29 04:08:55 +04:00
/* Initialize gpiolib. */
orion_gpio_init ( ) ;
2009-01-31 06:44:20 +03:00
printk ( KERN_DEBUG " initial MPP regs: " ) ;
for ( i = 0 ; i < MPP_NR_REGS ; i + + ) {
mpp_ctrl [ i ] = readl ( MPP_CTRL ( i ) ) ;
printk ( " %08x " , mpp_ctrl [ i ] ) ;
}
printk ( " \n " ) ;
while ( * mpp_list ) {
unsigned int num = MPP_NUM ( * mpp_list ) ;
unsigned int sel = MPP_SEL ( * mpp_list ) ;
int shift , gpio_mode ;
if ( num > MPP_MAX ) {
printk ( KERN_ERR " kirkwood_mpp_conf: invalid MPP "
" number (%u) \n " , num ) ;
continue ;
}
if ( ! ( * mpp_list & variant_mask ) ) {
printk ( KERN_WARNING
" kirkwood_mpp_conf: requested MPP%u config "
" unavailable on this hardware \n " , num ) ;
continue ;
}
shift = ( num & 7 ) < < 2 ;
mpp_ctrl [ num / 8 ] & = ~ ( 0xf < < shift ) ;
mpp_ctrl [ num / 8 ] | = sel < < shift ;
gpio_mode = 0 ;
if ( * mpp_list & MPP_INPUT_MASK )
gpio_mode | = GPIO_INPUT_OK ;
if ( * mpp_list & MPP_OUTPUT_MASK )
gpio_mode | = GPIO_OUTPUT_OK ;
if ( sel ! = 0 )
gpio_mode = 0 ;
orion_gpio_set_valid ( num , gpio_mode ) ;
mpp_list + + ;
}
printk ( KERN_DEBUG " final MPP regs: " ) ;
for ( i = 0 ; i < MPP_NR_REGS ; i + + ) {
writel ( mpp_ctrl [ i ] , MPP_CTRL ( i ) ) ;
printk ( " %08x " , mpp_ctrl [ i ] ) ;
}
printk ( " \n " ) ;
}