static int i82092aa_set_socket()

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;
}