2005-04-17 02:20:36 +04:00
/*
* linux / drivers / pcmcia / pxa2xx_lubbock . c
*
* Author : George Davis
* Created : Jan 10 , 2002
* Copyright : MontaVista Software Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* Originally based upon linux / drivers / pcmcia / sa1100_neponset . c
*
* Lubbock PCMCIA specific routines .
*
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/device.h>
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/delay.h>
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-04-17 02:20:36 +04:00
# include <asm/hardware/sa1111.h>
# include <asm/mach-types.h>
2008-08-05 19:14:15 +04:00
# include <mach/lubbock.h>
2005-04-17 02:20:36 +04:00
# include "sa1111_generic.h"
static int
lubbock_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 pa_dwr_mask , pa_dwr_set , misc_mask , misc_set ;
int ret = 0 ;
pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0 ;
/* Lubbock uses the Maxim MAX1602, with the following connections:
*
* Socket 0 ( PCMCIA ) :
* MAX1602 Lubbock Register
* Pin Signal
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* A0VPP S0_PWR0 SA - 1111 GPIO A < 0 >
* A1VPP S0_PWR1 SA - 1111 GPIO A < 1 >
* A0VCC S0_PWR2 SA - 1111 GPIO A < 2 >
* A1VCC S0_PWR3 SA - 1111 GPIO A < 3 >
* VX VCC
* VY + 3.3 V
* 12 IN + 12 V
* CODE + 3.3 V Cirrus Code , CODE = High ( VY )
*
* Socket 1 ( CF ) :
* MAX1602 Lubbock Register
* Pin Signal
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* A0VPP GND VPP is not connected
* A1VPP GND VPP is not connected
* A0VCC S1_PWR0 MISC_WR < 14 >
* A1VCC S1_PWR1 MISC_WR < 15 >
* VX VCC
* VY + 3.3 V
* 12 IN GND VPP is not connected
* CODE + 3.3 V Cirrus Code , CODE = High ( VY )
*
*/
again :
switch ( skt - > nr ) {
case 0 :
pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3 ;
switch ( state - > Vcc ) {
case 0 : /* Hi-Z */
break ;
case 33 : /* VY */
pa_dwr_set | = GPIO_A3 ;
break ;
case 50 : /* VX */
pa_dwr_set | = GPIO_A2 ;
break ;
default :
printk ( KERN_ERR " %s(): unrecognized Vcc %u \n " ,
2008-05-01 15:34:54 +04:00
__func__ , state - > Vcc ) ;
2005-04-17 02:20:36 +04:00
ret = - 1 ;
}
switch ( state - > Vpp ) {
case 0 : /* Hi-Z */
break ;
case 120 : /* 12IN */
pa_dwr_set | = GPIO_A1 ;
break ;
default : /* VCC */
if ( state - > Vpp = = state - > Vcc )
pa_dwr_set | = GPIO_A0 ;
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
ret = - 1 ;
break ;
}
}
break ;
case 1 :
misc_mask = ( 1 < < 15 ) | ( 1 < < 14 ) ;
switch ( state - > Vcc ) {
case 0 : /* Hi-Z */
break ;
case 33 : /* VY */
misc_set | = 1 < < 15 ;
break ;
case 50 : /* VX */
misc_set | = 1 < < 14 ;
break ;
default :
printk ( KERN_ERR " %s(): unrecognized Vcc %u \n " ,
2008-05-01 15:34:54 +04:00
__func__ , state - > Vcc ) ;
2005-04-17 02:20:36 +04:00
ret = - 1 ;
break ;
}
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
ret = - 1 ;
break ;
}
break ;
default :
ret = - 1 ;
}
if ( ret = = 0 )
ret = sa1111_pcmcia_configure_socket ( skt , state ) ;
if ( ret = = 0 ) {
lubbock_set_misc_wr ( misc_mask , misc_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
}
# if 1
if ( ret = = 0 & & state - > Vcc = = 33 ) {
struct pcmcia_state new_state ;
/*
* HACK ALERT :
* We can ' t sense the voltage properly on Lubbock before
* actually applying some power to the socket ( catch 22 ) .
* Resense the socket Voltage Sense pins after applying
* socket power .
*
* Note : It takes about 2.5 ms for the MAX1602 VCC output
* to rise .
*/
mdelay ( 3 ) ;
sa1111_pcmcia_socket_state ( skt , & new_state ) ;
if ( ! new_state . vs_3v & & ! new_state . vs_Xv ) {
/*
* Switch to 5 V , Configure socket with 5 V voltage
*/
lubbock_set_misc_wr ( misc_mask , 0 ) ;
2009-03-29 22:42:44 +04:00
sa1111_set_io ( s - > dev , pa_dwr_mask , 0 ) ;
2005-04-17 02:20:36 +04:00
/*
* It takes about 100 ms to turn off Vcc .
*/
mdelay ( 100 ) ;
/*
* We need to hack around the const qualifier as
* well to keep this ugly workaround localized and
* not force it to the rest of the code . Barf bags
2011-03-31 05:57:33 +04:00
* available in the seat pocket in front of you !
2005-04-17 02:20:36 +04:00
*/
( ( socket_state_t * ) state ) - > Vcc = 50 ;
( ( socket_state_t * ) state ) - > Vpp = 50 ;
goto again ;
}
}
# endif
return ret ;
}
static struct pcmcia_low_level lubbock_pcmcia_ops = {
. owner = THIS_MODULE ,
. configure_socket = lubbock_pcmcia_configure_socket ,
. first = 0 ,
. nr = 2 ,
} ;
# include "pxa2xx_base.h"
2007-12-23 01:03:29 +03:00
int pcmcia_lubbock_init ( struct sa1111_dev * sadev )
2005-04-17 02:20:36 +04:00
{
int ret = - ENODEV ;
if ( machine_is_lubbock ( ) ) {
/*
* 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 ) ;
/* Set CF Socket 1 power to standby mode. */
lubbock_set_misc_wr ( ( 1 < < 15 ) | ( 1 < < 14 ) , 0 ) ;
2009-03-29 22:42:44 +04:00
pxa2xx_drv_pcmcia_ops ( & lubbock_pcmcia_ops ) ;
2011-02-04 11:03:43 +03:00
pxa2xx_configure_sockets ( & sadev - > dev ) ;
2009-03-29 22:42:44 +04:00
ret = sa1111_pcmcia_add ( sadev , & lubbock_pcmcia_ops ,
pxa2xx_drv_pcmcia_add_one ) ;
2005-04-17 02:20:36 +04:00
}
return ret ;
}
MODULE_LICENSE ( " GPL " ) ;