2010-11-15 12:48:33 +03:00
/*
* arch / arm / mach - dove / mpp . c
*
* MPP functions for Marvell Dove 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/gpio.h>
# include <linux/io.h>
2011-05-15 15:32:54 +04:00
# include <plat/mpp.h>
2010-11-15 12:48:33 +03:00
# include <mach/dove.h>
2012-08-29 19:16:55 +04:00
# include <plat/orion-gpio.h>
2010-11-15 12:48:33 +03:00
# include "mpp.h"
struct dove_mpp_grp {
int start ;
int end ;
} ;
2011-05-15 15:32:54 +04:00
/* Map a group to a range of GPIO pins in that group */
static const struct dove_mpp_grp dove_mpp_grp [ ] = {
2010-11-15 12:48:33 +03:00
[ MPP_24_39 ] = {
. start = 24 ,
. end = 39 ,
} ,
[ MPP_40_45 ] = {
. start = 40 ,
. end = 45 ,
} ,
[ MPP_46_51 ] = {
2011-05-15 15:32:54 +04:00
. start = 46 ,
. end = 51 ,
2010-11-15 12:48:33 +03:00
} ,
[ MPP_58_61 ] = {
. start = 58 ,
. end = 61 ,
} ,
[ MPP_62_63 ] = {
. start = 62 ,
. end = 63 ,
} ,
} ;
2011-05-15 15:32:54 +04:00
/* Enable gpio for a range of pins. mode should be a combination of
GPIO_OUTPUT_OK | GPIO_INPUT_OK */
2013-07-01 18:56:12 +04:00
static void __init dove_mpp_gpio_mode ( int start , int end , int gpio_mode )
2010-11-15 12:48:33 +03:00
{
int i ;
for ( i = start ; i < = end ; i + + )
orion_gpio_set_valid ( i , gpio_mode ) ;
}
2011-05-15 15:32:54 +04:00
/* Dump all the extra MPP registers. The platform code will dump the
registers for pins 0 - 23. */
2012-05-14 13:28:43 +04:00
static void __init dove_mpp_dump_regs ( void )
2010-11-15 12:48:33 +03:00
{
2011-05-15 15:32:54 +04:00
pr_debug ( " PMU_CTRL4_CTRL: %08x \n " ,
readl ( DOVE_MPP_CTRL4_VIRT_BASE ) ) ;
2010-11-15 12:48:33 +03:00
2011-05-15 15:32:54 +04:00
pr_debug ( " PMU_MPP_GENERAL_CTRL: %08x \n " ,
readl ( DOVE_PMU_MPP_GENERAL_CTRL ) ) ;
2010-11-15 12:48:33 +03:00
pr_debug ( " MPP_GENERAL: %08x \n " , readl ( DOVE_MPP_GENERAL_VIRT_BASE ) ) ;
}
2012-05-14 13:28:43 +04:00
static void __init dove_mpp_cfg_nfc ( int sel )
2010-11-15 12:48:33 +03:00
{
u32 mpp_gen_cfg = readl ( DOVE_MPP_GENERAL_VIRT_BASE ) ;
mpp_gen_cfg & = ~ 0x1 ;
mpp_gen_cfg | = sel ;
writel ( mpp_gen_cfg , DOVE_MPP_GENERAL_VIRT_BASE ) ;
dove_mpp_gpio_mode ( 64 , 71 , GPIO_OUTPUT_OK ) ;
}
2012-05-14 13:28:43 +04:00
static void __init dove_mpp_cfg_au1 ( int sel )
2010-11-15 12:48:33 +03:00
{
2011-05-15 15:32:54 +04:00
u32 mpp_ctrl4 = readl ( DOVE_MPP_CTRL4_VIRT_BASE ) ;
2010-11-15 12:48:33 +03:00
u32 ssp_ctrl1 = readl ( DOVE_SSP_CTRL_STATUS_1 ) ;
u32 mpp_gen_ctrl = readl ( DOVE_MPP_GENERAL_VIRT_BASE ) ;
u32 global_cfg_2 = readl ( DOVE_GLOBAL_CONFIG_2 ) ;
mpp_ctrl4 & = ~ ( DOVE_AU1_GPIO_SEL ) ;
ssp_ctrl1 & = ~ ( DOVE_SSP_ON_AU1 ) ;
mpp_gen_ctrl & = ~ ( DOVE_AU1_SPDIFO_GPIO_EN ) ;
global_cfg_2 & = ~ ( DOVE_TWSI_OPTION3_GPIO ) ;
if ( ! sel | | sel = = 0x2 )
dove_mpp_gpio_mode ( 52 , 57 , 0 ) ;
else
dove_mpp_gpio_mode ( 52 , 57 , GPIO_OUTPUT_OK | GPIO_INPUT_OK ) ;
if ( sel & 0x1 ) {
global_cfg_2 | = DOVE_TWSI_OPTION3_GPIO ;
dove_mpp_gpio_mode ( 56 , 57 , 0 ) ;
}
if ( sel & 0x2 ) {
mpp_gen_ctrl | = DOVE_AU1_SPDIFO_GPIO_EN ;
dove_mpp_gpio_mode ( 57 , 57 , GPIO_OUTPUT_OK | GPIO_INPUT_OK ) ;
}
if ( sel & 0x4 ) {
ssp_ctrl1 | = DOVE_SSP_ON_AU1 ;
dove_mpp_gpio_mode ( 52 , 55 , 0 ) ;
}
if ( sel & 0x8 )
mpp_ctrl4 | = DOVE_AU1_GPIO_SEL ;
writel ( mpp_ctrl4 , DOVE_MPP_CTRL4_VIRT_BASE ) ;
writel ( ssp_ctrl1 , DOVE_SSP_CTRL_STATUS_1 ) ;
writel ( mpp_gen_ctrl , DOVE_MPP_GENERAL_VIRT_BASE ) ;
writel ( global_cfg_2 , DOVE_GLOBAL_CONFIG_2 ) ;
}
2011-05-15 15:32:54 +04:00
/* Configure the group registers, enabling GPIO if sel indicates the
pin is to be used for GPIO */
2012-05-14 13:28:43 +04:00
static void __init dove_mpp_conf_grp ( unsigned int * mpp_grp_list )
2010-11-15 12:48:33 +03:00
{
2011-05-15 15:32:54 +04:00
u32 mpp_ctrl4 = readl ( DOVE_MPP_CTRL4_VIRT_BASE ) ;
int gpio_mode ;
2010-11-15 12:48:33 +03:00
2011-05-15 15:32:54 +04:00
for ( ; * mpp_grp_list ; mpp_grp_list + + ) {
unsigned int num = MPP_NUM ( * mpp_grp_list ) ;
unsigned int sel = MPP_SEL ( * mpp_grp_list ) ;
2010-11-15 12:48:33 +03:00
2011-05-15 15:32:54 +04:00
if ( num > MPP_GRP_MAX ) {
pr_err ( " dove: invalid MPP GRP number (%u) \n " , num ) ;
2010-11-15 12:48:33 +03:00
continue ;
}
2011-05-15 15:32:54 +04:00
mpp_ctrl4 & = ~ ( 0x1 < < num ) ;
mpp_ctrl4 | = sel < < num ;
2010-11-15 12:48:33 +03:00
2011-05-15 15:32:54 +04:00
gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0 ;
dove_mpp_gpio_mode ( dove_mpp_grp [ num ] . start ,
dove_mpp_grp [ num ] . end , gpio_mode ) ;
2010-11-15 12:48:33 +03:00
}
2011-05-15 15:32:54 +04:00
writel ( mpp_ctrl4 , DOVE_MPP_CTRL4_VIRT_BASE ) ;
}
2010-11-15 12:48:33 +03:00
2011-05-15 15:32:54 +04:00
/* Configure the various MPP pins on Dove */
void __init dove_mpp_conf ( unsigned int * mpp_list ,
unsigned int * mpp_grp_list ,
unsigned int grp_au1_52_57 ,
unsigned int grp_nfc_64_71 )
{
dove_mpp_dump_regs ( ) ;
2010-11-15 12:48:33 +03:00
2011-05-15 15:32:54 +04:00
/* Use platform code for pins 0-23 */
orion_mpp_conf ( mpp_list , 0 , MPP_MAX , DOVE_MPP_VIRT_BASE ) ;
2010-11-15 12:48:33 +03:00
2011-05-15 15:32:54 +04:00
dove_mpp_conf_grp ( mpp_grp_list ) ;
dove_mpp_cfg_au1 ( grp_au1_52_57 ) ;
dove_mpp_cfg_nfc ( grp_nfc_64_71 ) ;
2010-11-15 12:48:33 +03:00
dove_mpp_dump_regs ( ) ;
}