2008-10-10 18:58:12 +04:00
/*
* wm8350 - core . c - - Device access for Wolfson WM8350
*
* Copyright 2007 , 2008 Wolfson Microelectronics PLC .
*
* Author : Liam Girdwood
*
* 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 .
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/mfd/wm8350/core.h>
# include <linux/mfd/wm8350/gpio.h>
# include <linux/mfd/wm8350/pmic.h>
static int gpio_set_dir ( struct wm8350 * wm8350 , int gpio , int dir )
{
int ret ;
wm8350_reg_unlock ( wm8350 ) ;
if ( dir = = WM8350_GPIO_DIR_OUT )
ret = wm8350_clear_bits ( wm8350 ,
WM8350_GPIO_CONFIGURATION_I_O ,
1 < < gpio ) ;
else
ret = wm8350_set_bits ( wm8350 ,
WM8350_GPIO_CONFIGURATION_I_O ,
1 < < gpio ) ;
wm8350_reg_lock ( wm8350 ) ;
return ret ;
}
2011-08-10 12:05:49 +04:00
static int wm8350_gpio_set_debounce ( struct wm8350 * wm8350 , int gpio , int db )
2008-10-10 18:58:12 +04:00
{
if ( db = = WM8350_GPIO_DEBOUNCE_ON )
return wm8350_set_bits ( wm8350 , WM8350_GPIO_DEBOUNCE ,
1 < < gpio ) ;
else
return wm8350_clear_bits ( wm8350 ,
WM8350_GPIO_DEBOUNCE , 1 < < gpio ) ;
}
static int gpio_set_func ( struct wm8350 * wm8350 , int gpio , int func )
{
u16 reg ;
wm8350_reg_unlock ( wm8350 ) ;
switch ( gpio ) {
case 0 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 )
& ~ WM8350_GP0_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 ,
reg | ( ( func & 0xf ) < < 0 ) ) ;
break ;
case 1 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 )
& ~ WM8350_GP1_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 ,
reg | ( ( func & 0xf ) < < 4 ) ) ;
break ;
case 2 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 )
& ~ WM8350_GP2_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 ,
reg | ( ( func & 0xf ) < < 8 ) ) ;
break ;
case 3 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 )
& ~ WM8350_GP3_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_1 ,
reg | ( ( func & 0xf ) < < 12 ) ) ;
break ;
case 4 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 )
& ~ WM8350_GP4_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 ,
reg | ( ( func & 0xf ) < < 0 ) ) ;
break ;
case 5 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 )
& ~ WM8350_GP5_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 ,
reg | ( ( func & 0xf ) < < 4 ) ) ;
break ;
case 6 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 )
& ~ WM8350_GP6_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 ,
reg | ( ( func & 0xf ) < < 8 ) ) ;
break ;
case 7 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 )
& ~ WM8350_GP7_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_2 ,
reg | ( ( func & 0xf ) < < 12 ) ) ;
break ;
case 8 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 )
& ~ WM8350_GP8_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 ,
reg | ( ( func & 0xf ) < < 0 ) ) ;
break ;
case 9 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 )
& ~ WM8350_GP9_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 ,
reg | ( ( func & 0xf ) < < 4 ) ) ;
break ;
case 10 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 )
& ~ WM8350_GP10_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 ,
reg | ( ( func & 0xf ) < < 8 ) ) ;
break ;
case 11 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 )
& ~ WM8350_GP11_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_3 ,
reg | ( ( func & 0xf ) < < 12 ) ) ;
break ;
case 12 :
reg = wm8350_reg_read ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_4 )
& ~ WM8350_GP12_FN_MASK ;
wm8350_reg_write ( wm8350 , WM8350_GPIO_FUNCTION_SELECT_4 ,
reg | ( ( func & 0xf ) < < 0 ) ) ;
break ;
default :
wm8350_reg_lock ( wm8350 ) ;
return - EINVAL ;
}
wm8350_reg_lock ( wm8350 ) ;
return 0 ;
}
static int gpio_set_pull_up ( struct wm8350 * wm8350 , int gpio , int up )
{
if ( up )
return wm8350_set_bits ( wm8350 ,
WM8350_GPIO_PIN_PULL_UP_CONTROL ,
1 < < gpio ) ;
else
return wm8350_clear_bits ( wm8350 ,
WM8350_GPIO_PIN_PULL_UP_CONTROL ,
1 < < gpio ) ;
}
static int gpio_set_pull_down ( struct wm8350 * wm8350 , int gpio , int down )
{
if ( down )
return wm8350_set_bits ( wm8350 ,
WM8350_GPIO_PULL_DOWN_CONTROL ,
1 < < gpio ) ;
else
return wm8350_clear_bits ( wm8350 ,
WM8350_GPIO_PULL_DOWN_CONTROL ,
1 < < gpio ) ;
}
static int gpio_set_polarity ( struct wm8350 * wm8350 , int gpio , int pol )
{
if ( pol = = WM8350_GPIO_ACTIVE_HIGH )
return wm8350_set_bits ( wm8350 ,
WM8350_GPIO_PIN_POLARITY_TYPE ,
1 < < gpio ) ;
else
return wm8350_clear_bits ( wm8350 ,
WM8350_GPIO_PIN_POLARITY_TYPE ,
1 < < gpio ) ;
}
static int gpio_set_invert ( struct wm8350 * wm8350 , int gpio , int invert )
{
if ( invert = = WM8350_GPIO_INVERT_ON )
return wm8350_set_bits ( wm8350 , WM8350_GPIO_INT_MODE , 1 < < gpio ) ;
else
return wm8350_clear_bits ( wm8350 ,
WM8350_GPIO_INT_MODE , 1 < < gpio ) ;
}
int wm8350_gpio_config ( struct wm8350 * wm8350 , int gpio , int dir , int func ,
int pol , int pull , int invert , int debounce )
{
/* make sure we never pull up and down at the same time */
if ( pull = = WM8350_GPIO_PULL_NONE ) {
if ( gpio_set_pull_up ( wm8350 , gpio , 0 ) )
goto err ;
if ( gpio_set_pull_down ( wm8350 , gpio , 0 ) )
goto err ;
} else if ( pull = = WM8350_GPIO_PULL_UP ) {
if ( gpio_set_pull_down ( wm8350 , gpio , 0 ) )
goto err ;
if ( gpio_set_pull_up ( wm8350 , gpio , 1 ) )
goto err ;
} else if ( pull = = WM8350_GPIO_PULL_DOWN ) {
if ( gpio_set_pull_up ( wm8350 , gpio , 0 ) )
goto err ;
if ( gpio_set_pull_down ( wm8350 , gpio , 1 ) )
goto err ;
}
if ( gpio_set_invert ( wm8350 , gpio , invert ) )
goto err ;
if ( gpio_set_polarity ( wm8350 , gpio , pol ) )
goto err ;
2011-08-10 12:05:49 +04:00
if ( wm8350_gpio_set_debounce ( wm8350 , gpio , debounce ) )
2008-10-10 18:58:12 +04:00
goto err ;
if ( gpio_set_dir ( wm8350 , gpio , dir ) )
goto err ;
return gpio_set_func ( wm8350 , gpio , func ) ;
err :
return - EIO ;
}
EXPORT_SYMBOL_GPL ( wm8350_gpio_config ) ;