in tcic.c [619:690]
static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
u_char reg;
u_short scf1, scf2;
dev_dbg(&sock->dev, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
reg = tcic_getb(TCIC_PWR);
reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
if (state->Vcc == 50) {
switch (state->Vpp) {
case 0: reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
case 50: reg |= TCIC_PWR_VCC(psock); break;
case 120: reg |= TCIC_PWR_VPP(psock); break;
default: return -EINVAL;
}
} else if (state->Vcc != 0)
return -EINVAL;
if (reg != tcic_getb(TCIC_PWR))
tcic_setb(TCIC_PWR, reg);
reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
if (state->flags & SS_OUTPUT_ENA) {
tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
reg |= TCIC_ILOCK_CRESENA;
} else
tcic_setb(TCIC_SCTRL, 0);
if (state->flags & SS_RESET)
reg |= TCIC_ILOCK_CRESET;
tcic_aux_setb(TCIC_AUX_ILOCK, reg);
tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
scf1 = TCIC_SCF1_FINPACK;
scf1 |= TCIC_IRQ(state->io_irq);
if (state->flags & SS_IOCARD) {
scf1 |= TCIC_SCF1_IOSTS;
if (state->flags & SS_SPKR_ENA)
scf1 |= TCIC_SCF1_SPKR;
if (state->flags & SS_DMA_MODE)
scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
}
tcic_setw(TCIC_DATA, scf1);
/* Some general setup stuff, and configure status interrupt */
reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
tcic_aux_setb(TCIC_AUX_WCTL, reg);
tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
TCIC_IRQ(cs_irq));
/* Card status change interrupt mask */
tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
scf2 = TCIC_SCF2_MALL;
if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
if (state->flags & SS_IOCARD) {
if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
} else {
if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
}
tcic_setw(TCIC_DATA, scf2);
/* For the ISA bus, the irq should be active-high totem-pole */
tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
return 0;
} /* tcic_set_socket */