2005-04-17 02:20:36 +04:00
/*
* linux / drivers / pcmcia / sa1100_neponset . c
*
* Neponset PCMCIA specific routines
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/device.h>
# include <linux/errno.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>
2008-08-05 19:14:15 +04:00
# include <mach/neponset.h>
2005-04-17 02:20:36 +04:00
# include <asm/hardware/sa1111.h>
# include "sa1111_generic.h"
/*
* Neponset uses the Maxim MAX1600 , with the following connections :
*
* MAX1600 Neponset
*
* A0VCC SA - 1111 GPIO A < 1 >
* A1VCC SA - 1111 GPIO A < 0 >
* A0VPP CPLD NCR A0VPP
* A1VPP CPLD NCR A1VPP
* B0VCC SA - 1111 GPIO A < 2 >
* B1VCC SA - 1111 GPIO A < 3 >
* B0VPP ground ( slot B is CF )
* B1VPP ground ( slot B is CF )
*
* VX VCC ( 5 V )
* VY VCC3_3 ( 3.3 V )
* 12 INA 12 V
* 12 INB ground ( slot B is CF )
*
* The MAX1600 CODE pin is tied to ground , placing the device in
* " Standard Intel code " mode . Refer to the Maxim data sheet for
* the corresponding truth table .
*/
static int
neponset_pcmcia_configure_socket ( struct soc_pcmcia_socket * skt , const socket_state_t * state )
{
2009-03-29 22:42:44 +04:00
struct sa1111_pcmcia_socket * s = to_skt ( skt ) ;
2005-04-17 02:20:36 +04:00
unsigned int ncr_mask , ncr_set , pa_dwr_mask , pa_dwr_set ;
int ret ;
switch ( skt - > nr ) {
case 0 :
pa_dwr_mask = GPIO_A0 | GPIO_A1 ;
ncr_mask = NCR_A0VPP | NCR_A1VPP ;
if ( state - > Vpp = = 0 )
ncr_set = 0 ;
else if ( state - > Vpp = = 120 )
ncr_set = NCR_A1VPP ;
else if ( state - > Vpp = = state - > Vcc )
ncr_set = NCR_A0VPP ;
else {
printk ( KERN_ERR " %s(): unrecognized VPP %u \n " ,
2008-05-01 15:34:54 +04:00
__func__ , state - > Vpp ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
break ;
case 1 :
pa_dwr_mask = GPIO_A2 | GPIO_A3 ;
ncr_mask = 0 ;
ncr_set = 0 ;
if ( state - > Vpp ! = state - > Vcc & & state - > Vpp ! = 0 ) {
printk ( KERN_ERR " %s(): CF slot cannot support VPP %u \n " ,
2008-05-01 15:34:54 +04:00
__func__ , state - > Vpp ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
break ;
default :
return - 1 ;
}
/*
* pa_dwr_set is the mask for selecting Vcc on both sockets .
* pa_dwr_mask selects which bits ( and therefore socket ) we change .
*/
switch ( state - > Vcc ) {
default :
case 0 : pa_dwr_set = 0 ; break ;
case 33 : pa_dwr_set = GPIO_A1 | GPIO_A2 ; break ;
case 50 : pa_dwr_set = GPIO_A0 | GPIO_A3 ; break ;
}
ret = sa1111_pcmcia_configure_socket ( skt , state ) ;
if ( ret = = 0 ) {
2012-01-16 13:31:47 +04:00
neponset_ncr_frob ( ncr_mask , ncr_set ) ;
2009-03-29 22:42:44 +04:00
sa1111_set_io ( s - > dev , pa_dwr_mask , pa_dwr_set ) ;
2005-04-17 02:20:36 +04:00
}
2012-01-16 13:27:33 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
static struct pcmcia_low_level neponset_pcmcia_ops = {
. owner = THIS_MODULE ,
. configure_socket = neponset_pcmcia_configure_socket ,
2009-03-29 22:42:44 +04:00
. first = 0 ,
. nr = 2 ,
2005-04-17 02:20:36 +04:00
} ;
2009-09-27 20:30:21 +04:00
int pcmcia_neponset_init ( struct sa1111_dev * sadev )
2005-04-17 02:20:36 +04:00
{
int ret = - ENODEV ;
if ( machine_is_assabet ( ) ) {
/*
* Set GPIO_A < 3 : 0 > to be outputs for the MAX1600 ,
* and switch to standby mode .
*/
sa1111_set_io_dir ( sadev , GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3 , 0 , 0 ) ;
sa1111_set_io ( sadev , GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3 , 0 ) ;
sa1111_set_sleep_io ( sadev , GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3 , 0 ) ;
2009-03-29 22:42:44 +04:00
sa11xx_drv_pcmcia_ops ( & neponset_pcmcia_ops ) ;
ret = sa1111_pcmcia_add ( sadev , & neponset_pcmcia_ops ,
sa11xx_drv_pcmcia_add_one ) ;
2005-04-17 02:20:36 +04:00
}
return ret ;
}