in i82092.c [443:547]
static int i82092aa_set_socket(struct pcmcia_socket *socket,
socket_state_t *state)
{
struct socket_info *sock_info = container_of(socket, struct socket_info,
socket);
unsigned int sock = sock_info->number;
unsigned char reg;
/* First, set the global controller options */
set_bridge_state(sock);
/* Values for the IGENC register */
reg = 0;
/* The reset bit has "inverse" logic */
if (!(state->flags & SS_RESET))
reg = reg | I365_PC_RESET;
if (state->flags & SS_IOCARD)
reg = reg | I365_PC_IOCARD;
/* IGENC, Interrupt and General Control Register */
indirect_write(sock, I365_INTCTL, reg);
/* Power registers */
reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
if (state->flags & SS_PWR_AUTO) {
dev_info(&sock_info->dev->dev, "Auto power\n");
reg |= I365_PWR_AUTO; /* automatic power mngmnt */
}
if (state->flags & SS_OUTPUT_ENA) {
dev_info(&sock_info->dev->dev, "Power Enabled\n");
reg |= I365_PWR_OUT; /* enable power */
}
switch (state->Vcc) {
case 0:
break;
case 50:
dev_info(&sock_info->dev->dev,
"setting voltage to Vcc to 5V on socket %i\n",
sock);
reg |= I365_VCC_5V;
break;
default:
dev_err(&sock_info->dev->dev,
"%s called with invalid VCC power value: %i",
__func__, state->Vcc);
return -EINVAL;
}
switch (state->Vpp) {
case 0:
dev_info(&sock_info->dev->dev,
"not setting Vpp on socket %i\n", sock);
break;
case 50:
dev_info(&sock_info->dev->dev,
"setting Vpp to 5.0 for socket %i\n", sock);
reg |= I365_VPP1_5V | I365_VPP2_5V;
break;
case 120:
dev_info(&sock_info->dev->dev, "setting Vpp to 12.0\n");
reg |= I365_VPP1_12V | I365_VPP2_12V;
break;
default:
dev_err(&sock_info->dev->dev,
"%s called with invalid VPP power value: %i",
__func__, state->Vcc);
return -EINVAL;
}
if (reg != indirect_read(sock, I365_POWER)) /* only write if changed */
indirect_write(sock, I365_POWER, reg);
/* Enable specific interrupt events */
reg = 0x00;
if (state->csc_mask & SS_DETECT)
reg |= I365_CSC_DETECT;
if (state->flags & SS_IOCARD) {
if (state->csc_mask & SS_STSCHG)
reg |= I365_CSC_STSCHG;
} else {
if (state->csc_mask & SS_BATDEAD)
reg |= I365_CSC_BVD1;
if (state->csc_mask & SS_BATWARN)
reg |= I365_CSC_BVD2;
if (state->csc_mask & SS_READY)
reg |= I365_CSC_READY;
}
/* now write the value and clear the (probably bogus) pending stuff
* by doing a dummy read
*/
indirect_write(sock, I365_CSCINT, reg);
(void)indirect_read(sock, I365_CSC);
return 0;
}