in pd6729.c [294:420]
static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct pd6729_socket *socket
= container_of(sock, struct pd6729_socket, socket);
unsigned char reg, data;
/* First, set the global controller options */
indirect_write(socket, I365_GBLCTL, 0x00);
indirect_write(socket, I365_GENCTL, 0x00);
/* Values for the IGENC register */
socket->card_irq = state->io_irq;
reg = 0;
/* The reset bit has "inverse" logic */
if (!(state->flags & SS_RESET))
reg |= I365_PC_RESET;
if (state->flags & SS_IOCARD)
reg |= I365_PC_IOCARD;
/* IGENC, Interrupt and General Control Register */
indirect_write(socket, I365_INTCTL, reg);
/* Power registers */
reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
if (state->flags & SS_PWR_AUTO) {
dev_dbg(&sock->dev, "Auto power\n");
reg |= I365_PWR_AUTO; /* automatic power mngmnt */
}
if (state->flags & SS_OUTPUT_ENA) {
dev_dbg(&sock->dev, "Power Enabled\n");
reg |= I365_PWR_OUT; /* enable power */
}
switch (state->Vcc) {
case 0:
break;
case 33:
dev_dbg(&sock->dev,
"setting voltage to Vcc to 3.3V on socket %i\n",
socket->number);
reg |= I365_VCC_5V;
indirect_setbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
break;
case 50:
dev_dbg(&sock->dev,
"setting voltage to Vcc to 5V on socket %i\n",
socket->number);
reg |= I365_VCC_5V;
indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
break;
default:
dev_dbg(&sock->dev,
"pd6729_set_socket called with invalid VCC power "
"value: %i\n", state->Vcc);
return -EINVAL;
}
switch (state->Vpp) {
case 0:
dev_dbg(&sock->dev, "not setting Vpp on socket %i\n",
socket->number);
break;
case 33:
case 50:
dev_dbg(&sock->dev, "setting Vpp to Vcc for socket %i\n",
socket->number);
reg |= I365_VPP1_5V;
break;
case 120:
dev_dbg(&sock->dev, "setting Vpp to 12.0\n");
reg |= I365_VPP1_12V;
break;
default:
dev_dbg(&sock->dev, "pd6729: pd6729_set_socket called with "
"invalid VPP power value: %i\n", state->Vpp);
return -EINVAL;
}
/* only write if changed */
if (reg != indirect_read(socket, I365_POWER))
indirect_write(socket, I365_POWER, reg);
if (irq_mode == 1) {
/* all interrupts are to be done as PCI interrupts */
data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ;
} else
data = 0;
indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1);
indirect_write(socket, PD67_EXT_DATA, data);
/* 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;
}
if (irq_mode == 1)
reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */
indirect_write(socket, I365_CSCINT, reg);
reg = indirect_read(socket, I365_INTCTL);
if (irq_mode == 1)
reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */
else
reg |= socket->card_irq;
indirect_write(socket, I365_INTCTL, reg);
/* now clear the (probably bogus) pending stuff by doing a dummy read */
(void)indirect_read(socket, I365_CSC);
return 0;
}