2007-07-10 16:10:04 +04:00
/*
2009-04-14 18:50:37 +04:00
* Utility to set the DAVINCI MUX register from a table in mux . h
2007-07-10 16:10:04 +04:00
*
* Author : Vladimir Barinov , MontaVista Software , Inc . < source @ mvista . com >
*
2009-04-14 18:50:37 +04:00
* Based on linux / arch / arm / plat - omap / mux . c :
* Copyright ( C ) 2003 - 2005 Nokia Corporation
*
* Written by Tony Lindgren
*
2007-07-10 16:10:04 +04:00
* 2007 ( c ) MontaVista Software , Inc . 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 .
2009-04-14 18:50:37 +04:00
*
* Copyright ( C ) 2008 Texas Instruments .
2007-07-10 16:10:04 +04:00
*/
# include <linux/io.h>
2009-04-14 18:50:37 +04:00
# include <linux/module.h>
2007-07-10 16:10:04 +04:00
# include <linux/spinlock.h>
2008-08-05 19:14:15 +04:00
# include <mach/mux.h>
2009-04-15 23:39:48 +04:00
# include <mach/common.h>
2007-07-10 16:10:04 +04:00
2010-05-08 01:06:38 +04:00
static void __iomem * pinmux_base ;
2009-04-14 18:50:37 +04:00
/*
* Sets the DAVINCI MUX register based on the table
*/
int __init_or_module davinci_cfg_reg ( const unsigned long index )
2007-07-10 16:10:04 +04:00
{
2009-04-14 18:50:37 +04:00
static DEFINE_SPINLOCK ( mux_spin_lock ) ;
2009-04-15 23:39:48 +04:00
struct davinci_soc_info * soc_info = & davinci_soc_info ;
2009-04-14 18:50:37 +04:00
unsigned long flags ;
const struct mux_config * cfg ;
unsigned int reg_orig = 0 , reg = 0 ;
unsigned int mask , warn = 0 ;
2010-05-08 01:06:38 +04:00
if ( WARN_ON ( ! soc_info - > pinmux_pins ) )
return - ENODEV ;
if ( ! pinmux_base ) {
pinmux_base = ioremap ( soc_info - > pinmux_base , SZ_4K ) ;
if ( WARN_ON ( ! pinmux_base ) )
return - ENOMEM ;
}
2009-04-14 18:50:37 +04:00
2009-04-15 23:39:48 +04:00
if ( index > = soc_info - > pinmux_pins_num ) {
2009-04-14 18:50:37 +04:00
printk ( KERN_ERR " Invalid pin mux index: %lu (%lu) \n " ,
2009-04-15 23:39:48 +04:00
index , soc_info - > pinmux_pins_num ) ;
2009-04-14 18:50:37 +04:00
dump_stack ( ) ;
return - ENODEV ;
}
2009-04-15 23:39:48 +04:00
cfg = & soc_info - > pinmux_pins [ index ] ;
2009-04-14 18:50:37 +04:00
if ( cfg - > name = = NULL ) {
printk ( KERN_ERR " No entry for the specified index \n " ) ;
return - ENODEV ;
}
/* Update the mux register in question */
if ( cfg - > mask ) {
unsigned tmp1 , tmp2 ;
spin_lock_irqsave ( & mux_spin_lock , flags ) ;
2010-05-08 01:06:38 +04:00
reg_orig = __raw_readl ( pinmux_base + cfg - > mux_reg ) ;
2009-04-14 18:50:37 +04:00
mask = ( cfg - > mask < < cfg - > mask_offset ) ;
tmp1 = reg_orig & mask ;
reg = reg_orig & ~ mask ;
tmp2 = ( cfg - > mode < < cfg - > mask_offset ) ;
reg | = tmp2 ;
if ( tmp1 ! = tmp2 )
warn = 1 ;
2010-05-08 01:06:38 +04:00
__raw_writel ( reg , pinmux_base + cfg - > mux_reg ) ;
2009-04-14 18:50:37 +04:00
spin_unlock_irqrestore ( & mux_spin_lock , flags ) ;
}
if ( warn ) {
# ifdef CONFIG_DAVINCI_MUX_WARNINGS
printk ( KERN_WARNING " MUX: initialized %s \n " , cfg - > name ) ;
# endif
}
2007-07-10 16:10:04 +04:00
2009-04-14 18:50:37 +04:00
# ifdef CONFIG_DAVINCI_MUX_DEBUG
if ( cfg - > debug | | warn ) {
printk ( KERN_WARNING " MUX: Setting register %s \n " , cfg - > name ) ;
printk ( KERN_WARNING " %s (0x%08x) = 0x%08x -> 0x%08x \n " ,
cfg - > mux_reg_name , cfg - > mux_reg , reg_orig , reg ) ;
2007-07-10 16:10:04 +04:00
}
2009-04-14 18:50:37 +04:00
# endif
2007-07-10 16:10:04 +04:00
2009-04-14 18:50:37 +04:00
return 0 ;
2007-07-10 16:10:04 +04:00
}
2009-04-14 18:50:37 +04:00
EXPORT_SYMBOL ( davinci_cfg_reg ) ;
2009-07-16 13:45:32 +04:00
2010-03-26 00:43:48 +03:00
int __init_or_module davinci_cfg_reg_list ( const short pins [ ] )
2009-07-16 13:45:32 +04:00
{
int i , error = - EINVAL ;
if ( pins )
for ( i = 0 ; pins [ i ] > = 0 ; i + + ) {
error = davinci_cfg_reg ( pins [ i ] ) ;
if ( error )
break ;
}
return error ;
}