コード例 #1
0
ファイル: lpc.c プロジェクト: fourier49/BIZ_EC
void pm1_ibf_interrupt(void)
{
	int is_cmd;
	uint8_t value, result;

	if (pm_get_status(LPC_ACPI_CMD) & EC_LPC_STATUS_FROM_HOST) {
		/* Set the busy bit */
		pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_PROCESSING, 1);

		/* data from command port or data port */
		is_cmd = pm_get_status(LPC_ACPI_CMD) & EC_LPC_STATUS_LAST_CMD;

		/* Get command or data */
		value = pm_get_data_in(LPC_ACPI_CMD);

		/* Handle whatever this was. */
		if (acpi_ap_to_ec(is_cmd, value, &result))
			pm_put_data_out(LPC_ACPI_CMD, result);

		/* Clear the busy bit */
		pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_PROCESSING, 0);

		/*
		 * ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty
		 * Output Buffer Full condition on the kernel channel.
		 */
		lpc_generate_sci();
	}

	task_clear_pending_irq(IT83XX_IRQ_PMC_IN);
}
コード例 #2
0
ファイル: lpc.c プロジェクト: fourier49/BIZ_EC
static void update_host_event_status(void)
{
	int need_sci = 0;
	int need_smi = 0;

	if (!init_done)
		return;

	/* Disable PMC1 interrupt while updating status register */
	task_disable_irq(IT83XX_IRQ_PMC_IN);

	if (host_events & event_mask[LPC_HOST_EVENT_SMI]) {
		/* Only generate SMI for first event */
		if (!(pm_get_status(LPC_ACPI_CMD) & EC_LPC_STATUS_SMI_PENDING))
			need_smi = 1;
		pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SMI_PENDING, 1);
	} else {
		pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SMI_PENDING, 0);
	}

	if (host_events & event_mask[LPC_HOST_EVENT_SCI]) {
		/* Generate SCI for every event */
		need_sci = 1;
		pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SCI_PENDING, 1);
	} else {
		pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SCI_PENDING, 0);
	}

	/* Copy host events to mapped memory */
	*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = host_events;

	task_enable_irq(IT83XX_IRQ_PMC_IN);

	/* Process the wake events. */
	lpc_update_wake(host_events & event_mask[LPC_HOST_EVENT_WAKE]);

	/* Send pulse on SMI signal if needed */
	if (need_smi)
		lpc_generate_smi();

	/* ACPI 5.0-12.6.1: Generate SCI for SCI_EVT=1. */
	if (need_sci)
		lpc_generate_sci();
}
コード例 #3
0
ファイル: lpc.c プロジェクト: fourier49/BIZ_EC
static void lpc_send_response_packet(struct host_packet *pkt)
{
	/* Ignore in-progress on LPC since interface is synchronous anyway */
	if (pkt->driver_result == EC_RES_IN_PROGRESS)
		return;

	/* Write result to the data byte. */
	pm_put_data_out(LPC_HOST_CMD, pkt->driver_result);

	/* Clear the busy bit, so the host knows the EC is done. */
	pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 0);
}
コード例 #4
0
ファイル: lpc.c プロジェクト: fourier49/BIZ_EC
static void lpc_send_response(struct host_cmd_handler_args *args)
{
	uint8_t *out;
	int size = args->response_size;
	int csum;
	int i;

	/* Ignore in-progress on LPC since interface is synchronous anyway */
	if (args->result == EC_RES_IN_PROGRESS)
		return;

	/* Handle negative size */
	if (size < 0) {
		args->result = EC_RES_INVALID_RESPONSE;
		size = 0;
	}

	/* New-style response */
	lpc_host_args->flags =
		(host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) |
		EC_HOST_ARGS_FLAG_TO_HOST;

	lpc_host_args->data_size = size;

	csum = args->command + lpc_host_args->flags +
		lpc_host_args->command_version +
		lpc_host_args->data_size;

	for (i = 0, out = (uint8_t *)args->response; i < size; i++, out++)
		csum += *out;

	lpc_host_args->checksum = (uint8_t)csum;

	/* Fail if response doesn't fit in the param buffer */
	if (size > EC_PROTO2_MAX_PARAM_SIZE)
		args->result = EC_RES_INVALID_RESPONSE;

	/* Write result to the data byte.  This sets the OBF status bit. */
	pm_put_data_out(LPC_HOST_CMD, args->result);

	/* Clear the busy bit, so the host knows the EC is done. */
	pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 0);
}
コード例 #5
0
ファイル: lpc.c プロジェクト: fourier49/BIZ_EC
void pm2_ibf_interrupt(void)
{
	uint8_t value __attribute__((unused)) = 0;
	uint8_t status;

	status = pm_get_status(LPC_HOST_CMD);
	/* IBE */
	if (!(status & EC_LPC_STATUS_FROM_HOST)) {
		task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
		return;
	}

	/* IBF and data port */
	if (!(status & EC_LPC_STATUS_LAST_CMD)) {
		/* R/C IBF*/
		value = pm_get_data_in(LPC_HOST_CMD);
		task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
		return;
	}

	/* Set the busy bit */
	pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 1);

	/*
	 * Read the command byte.  This clears the FRMH bit in
	 * the status byte.
	 */
	host_cmd_args.command = pm_get_data_in(LPC_HOST_CMD);

	host_cmd_args.result = EC_RES_SUCCESS;
	if (host_cmd_args.command != EC_COMMAND_PROTOCOL_3)
		host_cmd_args.send_response = lpc_send_response;
	host_cmd_flags = lpc_host_args->flags;

	/* We only support new style command (v3) now */
	if (host_cmd_args.command == EC_COMMAND_PROTOCOL_3) {
		lpc_packet.send_response = lpc_send_response_packet;

		lpc_packet.request = (const void *)host_cmd_memmap;
		lpc_packet.request_temp = params_copy;
		lpc_packet.request_max = sizeof(params_copy);
		/* Don't know the request size so pass in the entire buffer */
		lpc_packet.request_size = EC_LPC_HOST_PACKET_SIZE;

		lpc_packet.response = (void *)host_cmd_memmap;
		lpc_packet.response_max = EC_LPC_HOST_PACKET_SIZE;
		lpc_packet.response_size = 0;

		lpc_packet.driver_result = EC_RES_SUCCESS;
		host_packet_receive(&lpc_packet);

		task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
		return;
	} else {
		/* Old style command, now unsupported */
		host_cmd_args.result = EC_RES_INVALID_COMMAND;
	}

	/* Hand off to host command handler */
	host_command_received(&host_cmd_args);

	task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
}
コード例 #6
0
ファイル: lpc.c プロジェクト: fourier49/BIZ_EC
void lpc_clear_acpi_status_mask(uint8_t mask)
{
	pm_set_status(LPC_ACPI_CMD, mask, 0);
}
コード例 #7
0
ファイル: lpc.c プロジェクト: fourier49/BIZ_EC
void lpc_set_acpi_status_mask(uint8_t mask)
{
	pm_set_status(LPC_ACPI_CMD, mask, 1);
}
コード例 #8
0
ファイル: lpc.c プロジェクト: coreboot/chrome-ec
static void lpc_init(void)
{
	enum ec2i_message ec2i_r;

	/* SPI slave interface is disabled */
	IT83XX_GCTRL_SSCR = 0;
	/*
	 * DLM 52k~56k size select enable.
	 * For mapping LPC I/O cycle 800h ~ 9FFh to DLM 8D800 ~ 8D9FF.
	 */
	IT83XX_GCTRL_MCCR2 |= 0x10;

	/* The register pair to access PNPCFG is 004Eh and 004Fh */
	IT83XX_GCTRL_BADRSEL = 0x01;

	/* Disable KBC IRQ */
	IT83XX_KBC_KBIRQR = 0x00;

	/*
	 * bit2, Output Buffer Empty CPU Interrupt Enable.
	 * bit3, Input Buffer Full CPU Interrupt Enable.
	 * bit5, IBF/OBF EC clear mode.
	 *   0b: IBF cleared if EC read data register, EC reset, or host reset.
	 *       OBF cleared if host read data register, or EC reset.
	 *   1b: IBF cleared if EC write-1 to bit7 at related registers,
	 *       EC reset, or host reset.
	 *       OBF cleared if host read data register, EC write-1 to bit6 at
	 *       related registers, or EC reset.
	 */
	IT83XX_KBC_KBHICR |= 0x2C;

	/* PM1 Input Buffer Full Interrupt Enable for 62h/66 port */
	pm_set_ctrl(LPC_ACPI_CMD, PM_CTRL_IBFIE, 1);

	/* PM2 Input Buffer Full Interrupt Enable for 200h/204 port */
	pm_set_ctrl(LPC_HOST_CMD, PM_CTRL_IBFIE, 1);

	memset(lpc_get_memmap_range(), 0, EC_MEMMAP_SIZE);
	memset(lpc_host_args, 0, sizeof(*lpc_host_args));

	/* Host LPC I/O cycle mapping to RAM */
	/*
	 * bit[4], H2RAM through LPC IO cycle.
	 * bit[1], H2RAM window 1 enabled.
	 * bit[0], H2RAM window 0 enabled.
	 */
	IT83XX_SMFI_HRAMWC |= 0x13;

	/*
	 * bit[7:6]
	 * Host RAM Window[x] Read Protect Enable
	 * 00b: Disabled
	 * 01b: Lower half of RAM window protected
	 * 10b: Upper half of RAM window protected
	 * 11b: All protected
	 *
	 * bit[5:4]
	 * Host RAM Window[x] Write Protect Enable
	 * 00b: Disabled
	 * 01b: Lower half of RAM window protected
	 * 10b: Upper half of RAM window protected
	 * 11b: All protected
	 *
	 * bit[2:0]
	 * Host RAM Window 1 Size (HRAMW1S)
	 * 0h: 16 bytes
	 * 1h: 32 bytes
	 * 2h: 64 bytes
	 * 3h: 128 bytes
	 * 4h: 256 bytes
	 * 5h: 512 bytes
	 * 6h: 1024 bytes
	 * 7h: 2048 bytes
	 */

	/* H2RAM Win 0 Base Address 800h allow r/w for host_cmd_memmap */
	IT83XX_SMFI_HRAMW0BA = 0x80;
	IT83XX_SMFI_HRAMW0AAS = 0x04;

	/* H2RAM Win 1 Base Address 900h allow r for acpi_ec_memmap */
	IT83XX_SMFI_HRAMW1BA = 0x90;
	IT83XX_SMFI_HRAMW1AAS = 0x34;

	/* We support LPC args and version 3 protocol */
	*(lpc_get_memmap_range() + EC_MEMMAP_HOST_CMD_FLAGS) =
		EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED |
		EC_HOST_CMD_FLAG_VERSION_3;

	/*
	 * bit[5], Dedicated interrupt
	 * INT3: PMC1 Output Buffer Empty Int
	 * INT25: PMC1 Input Buffer Full Int
	 * INT26: PMC2 Output Buffer Empty Int
	 * INT27: PMC2 Input Buffer Full Int
	 */
	IT83XX_PMC_MBXCTRL |= 0x20;

	/* PM3 Input Buffer Full Interrupt Enable for 80h port */
	pm_set_ctrl(LPC_HOST_PORT_80H, PM_CTRL_IBFIE, 1);

	p80l_index = P80L_P80LC;
	if (ec2i_write(HOST_INDEX_LDN, LDN_RTCT) == EC2I_WRITE_SUCCESS) {
		/* get P80L current index */
		ec2i_r = ec2i_read(HOST_INDEX_DSLDC6);
		/* read OK */
		if ((ec2i_r & 0xff00) == EC2I_READ_SUCCESS)
			p80l_index = ec2i_r & P80L_BRAM_BANK1_SIZE_MASK;
	}

	/*
	 * bit[7], enable P80L function.
	 * bit[6], accept port 80h cycle.
	 * bit[1-0], 10b: I2EC is read-only.
	 */
	IT83XX_GCTRL_SPCTRL1 |= 0xC2;

	gpio_enable_interrupt(GPIO_PCH_PLTRST_L);

	task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
	task_disable_irq(IT83XX_IRQ_KBC_OUT);

	task_clear_pending_irq(IT83XX_IRQ_KBC_IN);
	task_enable_irq(IT83XX_IRQ_KBC_IN);

	task_clear_pending_irq(IT83XX_IRQ_PMC_IN);
	pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_PROCESSING, 0);
	task_enable_irq(IT83XX_IRQ_PMC_IN);

	task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
	pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 0);
	task_enable_irq(IT83XX_IRQ_PMC2_IN);

	task_clear_pending_irq(IT83XX_IRQ_PMC3_IN);
	task_enable_irq(IT83XX_IRQ_PMC3_IN);

	/* Restore event masks if needed */
	lpc_post_sysjump();

	/* Sufficiently initialized */
	init_done = 1;

	/* Update host events now that we can copy them to memmap */
	update_host_event_status();
}