2005-04-17 02:20:36 +04:00
/*
* drivers / pcmcia / sa1100_simpad . c
*
* PCMCIA implementation routines for simpad
*
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/device.h>
# include <linux/init.h>
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-04-17 02:20:36 +04:00
# include <asm/mach-types.h>
# include <asm/irq.h>
2008-08-05 19:14:15 +04:00
# include <mach/simpad.h>
2005-04-17 02:20:36 +04:00
# include "sa1100_generic.h"
static int simpad_pcmcia_hw_init ( struct soc_pcmcia_socket * skt )
{
2011-08-19 00:50:31 +04:00
simpad_clear_cs3_bit ( VCC_3V_EN | VCC_5V_EN | EN0 | EN1 ) ;
2005-04-17 02:20:36 +04:00
2012-01-14 03:06:48 +04:00
skt - > stat [ SOC_STAT_CD ] . gpio = GPIO_CF_CD ;
skt - > stat [ SOC_STAT_CD ] . name = " CF_CD " ;
skt - > stat [ SOC_STAT_RDY ] . gpio = GPIO_CF_IRQ ;
skt - > stat [ SOC_STAT_RDY ] . name = " CF_RDY " ;
2005-04-17 02:20:36 +04:00
2012-01-14 03:06:48 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
static void simpad_pcmcia_hw_shutdown ( struct soc_pcmcia_socket * skt )
{
/* Disable CF bus: */
2011-08-19 00:50:31 +04:00
/*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/
simpad_clear_cs3_bit ( PCMCIA_RESET ) ;
2005-04-17 02:20:36 +04:00
}
static void
simpad_pcmcia_socket_state ( struct soc_pcmcia_socket * skt ,
struct pcmcia_state * state )
{
2011-08-19 00:50:31 +04:00
long cs3reg = simpad_get_cs3_ro ( ) ;
2005-04-17 02:20:36 +04:00
2012-01-14 03:06:48 +04:00
/* the detect signal is inverted - fix that up here */
state - > detect = ! state - > detect ;
2011-08-19 00:50:31 +04:00
state - > bvd1 = 1 ; /* Might be cs3reg & PCMCIA_BVD1 */
state - > bvd2 = 1 ; /* Might be cs3reg & PCMCIA_BVD2 */
if ( ( cs3reg & ( PCMCIA_VS1 | PCMCIA_VS2 ) ) = =
( PCMCIA_VS1 | PCMCIA_VS2 ) ) {
2005-04-17 02:20:36 +04:00
state - > vs_3v = 0 ;
state - > vs_Xv = 0 ;
} else {
state - > vs_3v = 1 ;
state - > vs_Xv = 0 ;
}
}
static int
simpad_pcmcia_configure_socket ( struct soc_pcmcia_socket * skt ,
const socket_state_t * state )
{
unsigned long flags ;
local_irq_save ( flags ) ;
/* Murphy: see table of MIC2562a-1 */
switch ( state - > Vcc ) {
case 0 :
2011-08-19 00:50:31 +04:00
simpad_clear_cs3_bit ( VCC_3V_EN | VCC_5V_EN | EN0 | EN1 ) ;
2005-04-17 02:20:36 +04:00
break ;
case 33 :
2011-08-19 00:50:31 +04:00
simpad_clear_cs3_bit ( VCC_3V_EN | EN1 ) ;
simpad_set_cs3_bit ( VCC_5V_EN | EN0 ) ;
2005-04-17 02:20:36 +04:00
break ;
case 50 :
2011-08-19 00:50:31 +04:00
simpad_clear_cs3_bit ( VCC_5V_EN | EN1 ) ;
simpad_set_cs3_bit ( VCC_3V_EN | EN0 ) ;
2005-04-17 02:20:36 +04:00
break ;
default :
printk ( KERN_ERR " %s(): unrecognized Vcc %u \n " ,
2008-05-01 15:34:54 +04:00
__func__ , state - > Vcc ) ;
2011-08-19 00:50:31 +04:00
simpad_clear_cs3_bit ( VCC_3V_EN | VCC_5V_EN | EN0 | EN1 ) ;
2005-04-17 02:20:36 +04:00
local_irq_restore ( flags ) ;
return - 1 ;
}
local_irq_restore ( flags ) ;
return 0 ;
}
static void simpad_pcmcia_socket_suspend ( struct soc_pcmcia_socket * skt )
{
2011-08-19 00:50:31 +04:00
simpad_set_cs3_bit ( PCMCIA_RESET ) ;
2005-04-17 02:20:36 +04:00
}
static struct pcmcia_low_level simpad_pcmcia_ops = {
. owner = THIS_MODULE ,
. hw_init = simpad_pcmcia_hw_init ,
. hw_shutdown = simpad_pcmcia_hw_shutdown ,
. socket_state = simpad_pcmcia_socket_state ,
. configure_socket = simpad_pcmcia_configure_socket ,
. socket_suspend = simpad_pcmcia_socket_suspend ,
} ;
2012-11-19 22:23:12 +04:00
int pcmcia_simpad_init ( struct device * dev )
2005-04-17 02:20:36 +04:00
{
int ret = - ENODEV ;
if ( machine_is_simpad ( ) )
ret = sa11xx_drv_pcmcia_probe ( dev , & simpad_pcmcia_ops , 1 , 1 ) ;
return ret ;
}