Example #1
0
/**
 * Define one IRQ function to handle all GPIO interrupts. The IRQ determines
 * the interrupt number which was triggered, calls the master handler above,
 * and clears status registers.
 */
static void __gpio_irq(void)
{
	/* Determine interrupt number. */
	int irq = intc_get_ec_int();

#ifdef HAS_TASK_KEYSCAN
	if (irq == IT83XX_IRQ_WKINTC) {
		keyboard_raw_interrupt();
		return;
	}
#endif

	if (irq == IT83XX_IRQ_WKINTAD) {
		IT83XX_WUC_WUESR4 = 0xff;
		task_clear_pending_irq(IT83XX_IRQ_WKINTAD);
		return;
	}

	/*
	 * Clear the WUC status register. Note the external pin first goes
	 * to the WUC module and is always edge triggered.
	 */
	*(wuesr(gpio_irqs[irq].wuc_group)) = gpio_irqs[irq].wuc_mask;

	/*
	 * Clear the interrupt controller  status register. Note the interrupt
	 * controller is level triggered from the WUC status.
	 */
	task_clear_pending_irq(irq);

	/* Run the GPIO master handler above with corresponding port/mask. */
	gpio_interrupt(gpio_irqs[irq].gpio_port, gpio_irqs[irq].gpio_mask);
}
Example #2
0
void pd_adc_interrupt(void)
{
	/* Clear flags */
	STM32_ADC_ISR = 0x8e;

	if (discharge_is_enabled()) {
		if (discharge_volt_idx != volt_idx) {
			/* first step of the discharge completed: now 12V->5V */
			volt_idx = PDO_IDX_5V;
			set_output_voltage(VO_5V);
			discharge_voltage(voltages[PDO_IDX_5V].ovp);
		} else { /* discharge complete */
			discharge_disable();
			/* enable over-current monitoring */
			adc_enable_watchdog(ADC_CH_A_SENSE,
					    MAX_CURRENT_FAST, 0);
		}
	} else {/* Over-current detection */
		/* cut the power output */
		pd_power_supply_reset(0);
		/* record a special fault */
		fault = FAULT_FAST_OCP;
		/* pd_board_checks() will record the timeout later */
	}

	/* clear ADC irq so we don't get a second interrupt */
	task_clear_pending_irq(STM32_IRQ_ADC_COMP);
}
Example #3
0
static void chip_pd_irq(enum usbpd_port port)
{
	task_clear_pending_irq(usbpd_ctrl_regs[port].irq);

	/* check status */
	if (USBPD_IS_HARD_RESET_DETECT(port)) {
		/* clear interrupt */
		IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_HARD_RESET_DETECT;
		task_set_event(PD_PORT_TO_TASK_ID(port),
			PD_EVENT_TCPC_RESET, 0);
	} else {
		if (USBPD_IS_RX_DONE(port)) {
			/* mask RX done interrupt */
			IT83XX_USBPD_IMR(port) |= USBPD_REG_MASK_MSG_RX_DONE;
			/* clear RX done interrupt */
			IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_MSG_RX_DONE;
			task_set_event(PD_PORT_TO_TASK_ID(port),
				PD_EVENT_RX, 0);
		}
		if (USBPD_IS_TX_DONE(port)) {
			/* clear TX done interrupt */
			IT83XX_USBPD_ISR(port) = USBPD_REG_MASK_MSG_TX_DONE;
			task_set_event(PD_PORT_TO_TASK_ID(port),
				TASK_EVENT_PHY_TX_DONE, 0);
		}
	}
}
static void ext_timer_ctrl(enum ext_timer_sel ext_timer,
		enum ext_timer_clock_source ext_timer_clock,
		int start,
		int with_int,
		int32_t count)
{
	uint8_t intc_mask;

	/* rising-edge-triggered */
	intc_mask = et_ctrl_regs[ext_timer].mask;
	*et_ctrl_regs[ext_timer].mode |= intc_mask;
	*et_ctrl_regs[ext_timer].polarity &= ~intc_mask;

	/* clear interrupt status */
	task_clear_pending_irq(et_ctrl_regs[ext_timer].irq);

	/* These bits control the clock input source to the exttimer 3 - 8 */
	IT83XX_ETWD_ETXPSR(ext_timer) = ext_timer_clock;

	/* The count number of external timer n. */
	IT83XX_ETWD_ETXCNTLR(ext_timer) = count;

	ext_timer_stop(ext_timer, 0);
	if (start)
		ext_timer_start(ext_timer, 0);

	if (with_int)
		task_enable_irq(et_ctrl_regs[ext_timer].irq);
	else
		task_disable_irq(et_ctrl_regs[ext_timer].irq);
}
Example #5
0
void lpc_keyboard_put_char(uint8_t chr, int send_irq)
{
	/* Clear programming data bit 7-4 */
	IT83XX_KBC_KBHISR &= 0x0F;

	/* keyboard */
	IT83XX_KBC_KBHISR |= 0x10;

	/*
	 * bit0 = 0, The IRQ1 is controlled by the IRQ1B bit in KBIRQR.
	 * bit1 = 0, The IRQ12 is controlled by the IRQ12B bit in KBIRQR.
	 */
	IT83XX_KBC_KBHICR &= 0xFC;

	/*
	 * Enable the interrupt to keyboard driver in the host processor
	 * via SERIRQ when the output buffer is full.
	 */
	if (send_irq)
		IT83XX_KBC_KBHICR |= 0x01;

	udelay(16);

	task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
	/* The data output to the KBC Data Output Register. */
	IT83XX_KBC_KBHIKDOR = chr;
	task_enable_irq(IT83XX_IRQ_KBC_OUT);
}
Example #6
0
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);
}
Example #7
0
void pm3_ibf_interrupt(void)
{
	if (pm_get_status(LPC_HOST_PORT_80H) & EC_LPC_STATUS_FROM_HOST)
		port_80_write(pm_get_data_in(LPC_HOST_PORT_80H));

	task_clear_pending_irq(IT83XX_IRQ_PMC3_IN);
}
Example #8
0
void pm3_ibf_interrupt(void)
{
	int new_p80_idx, i;
	enum ec2i_message ec2i_r;

	/* set LDN */
	if (ec2i_write(HOST_INDEX_LDN, LDN_RTCT) == EC2I_WRITE_SUCCESS) {
		/* get P80L current index */
		ec2i_r = ec2i_read(HOST_INDEX_DSLDC6);
		/* clear IBF */
		pm_clear_ibf(LPC_HOST_PORT_80H);
		/* read OK */
		if ((ec2i_r & 0xff00) == EC2I_READ_SUCCESS) {
			new_p80_idx = ec2i_r & P80L_BRAM_BANK1_SIZE_MASK;
			for (i = 0; i < (P80L_P80LE - P80L_P80LB + 1); i++) {
				if (++p80l_index > P80L_P80LE)
					p80l_index = P80L_P80LB;
				port_80_write(IT83XX_BRAM_BANK1(p80l_index));
				if (p80l_index == new_p80_idx)
					break;
			}
		}
	} else {
		pm_clear_ibf(LPC_HOST_PORT_80H);
	}

	task_clear_pending_irq(IT83XX_IRQ_PMC3_IN);
}
Example #9
0
/**
 * Define one IRQ function to handle all GPIO interrupts. The IRQ determines
 * the interrupt number which was triggered, calls the master handler above,
 * and clears status registers.
 */
static void __gpio_irq(void)
{
    /* Determine interrupt number. */
    int irq = IT83XX_INTC_IVCT2 - 16;

#if defined(HAS_TASK_KEYSCAN) && defined(CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT)
    if (irq == IT83XX_IRQ_WKINTC) {
        keyboard_raw_interrupt();
        return;
    }
#endif

    /* Run the GPIO master handler above with corresponding port/mask. */
    gpio_interrupt(gpio_irqs[irq].gpio_port, gpio_irqs[irq].gpio_mask);

    /*
     * Clear the WUC status register. Note the external pin first goes
     * to the WUC module and is always edge triggered.
     */
    *(wuesr(gpio_irqs[irq].wuc_group)) = gpio_irqs[irq].wuc_mask;

    /*
     * Clear the interrupt controller  status register. Note the interrupt
     * controller is level triggered from the WUC status.
     */
    task_clear_pending_irq(irq);
}
Example #10
0
void keyboard_raw_enable_interrupt(int enable)
{
	if (enable) {
		task_clear_pending_irq(MEC1322_IRQ_KSC_INT);
		task_enable_irq(MEC1322_IRQ_KSC_INT);
	} else {
		task_disable_irq(MEC1322_IRQ_KSC_INT);
	}
}
void ext_timer_start(enum ext_timer_sel ext_timer, int en_irq)
{
	/* enable external timer n */
	IT83XX_ETWD_ETXCTRL(ext_timer) |= 0x03;

	if (en_irq) {
		task_clear_pending_irq(et_ctrl_regs[ext_timer].irq);
		task_enable_irq(et_ctrl_regs[ext_timer].irq);
	}
}
Example #12
0
int gpio_clear_pending_interrupt(enum gpio_signal signal)
{
	int irq = gpio_to_irq(gpio_list[signal].port, gpio_list[signal].mask);

	if (irq == -1)
		return EC_ERROR_UNKNOWN;

	*(wuesr(gpio_irqs[irq].wuc_group)) = gpio_irqs[irq].wuc_mask;
	task_clear_pending_irq(irq);
	return EC_SUCCESS;
}
Example #13
0
/* KBC and PMC control modules */
void lpc_kbc_ibf_interrupt(void)
{
	if (lpc_keyboard_input_pending()) {
		keyboard_host_write(IT83XX_KBC_KBHIDIR,
			(IT83XX_KBC_KBHISR & 0x08) ? 1 : 0);
	}

	task_clear_pending_irq(IT83XX_IRQ_KBC_IN);

#ifdef HAS_TASK_KEYPROTO
	task_wake(TASK_ID_KEYPROTO);
#endif
}
void tim2_interrupt(void)
{
	uint32_t stat = STM32_TIM_SR(2);

	if (stat & 2) { /* Event match */
		/* disable match interrupt but keep update interrupt */
		STM32_TIM_DIER(2) = 1;
		last_event = TASK_EVENT_TIMER;
	}
	if (stat & 1) /* Counter overflow */
		clksrc_high++;

	STM32_TIM_SR(2) = ~stat & 3; /* clear interrupt flags */
	task_clear_pending_irq(STM32_IRQ_TIM2);
}
Example #15
0
void lpc_kbc_obe_interrupt(void)
{
	task_disable_irq(IT83XX_IRQ_KBC_OUT);

	task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);

	if (!(IT83XX_KBC_KBHICR & 0x01)) {
		IT83XX_KBC_KBIRQR &= ~0x01;

		IT83XX_KBC_KBHICR |= 0x01;
	}

#ifdef HAS_TASK_KEYPROTO
	task_wake(TASK_ID_KEYPROTO);
#endif
}
Example #16
0
void i2c_interrupt(int port)
{
	int id = pdata[port].task_waiting;

	/* Clear the interrupt status */
	task_clear_pending_irq(i2c_ctrl_regs[port].irq);

	/* If no task is waiting, just return */
	if (id == TASK_ID_INVALID)
		return;

	/* If done doing work, wake up the task waiting for the transfer */
	if (!i2c_transaction(port)) {
		task_disable_irq(i2c_ctrl_regs[port].irq);
		task_set_event(id, TASK_EVENT_I2C_IDLE, 0);
	}
}
Example #17
0
void lpc_keyboard_resume_irq(void)
{
	if (lpc_keyboard_has_char()) {
		/* The IRQ1 is controlled by the IRQ1B bit in KBIRQR. */
		IT83XX_KBC_KBHICR &= ~0x01;

		/*
		 * When the OBFKIE bit in KBC Host Interface Control Register
		 * (KBHICR) is 0, the bit directly controls the IRQ1 signal.
		 */
		IT83XX_KBC_KBIRQR |= 0x01;

		task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);

		task_enable_irq(IT83XX_IRQ_KBC_OUT);
	}
}
Example #18
0
void spi_slave_init(void)
{
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;

	/*
	 * MISO: AFIO Push-pull
	 */
	STM32_GPIO_CRL(GPIO_A) = (STM32_GPIO_CRL(GPIO_A) & 0xfff0ffff) |
				 0x000b0000;

	/* Set DFF to 8-bit (default) */

	/* Set CPOL and CPHA (default) */

	/* Configure LSBFIRST (default) */

	/* Set SSM and clear SSI */
	spi->cr1 |= STM32_SPI_CR1_SSM;
	spi->cr1 &= ~STM32_SPI_CR1_SSI;

	/* Enable RXNE interrupt */
	spi->cr2 |= STM32_SPI_CR2_RXNEIE;
	/*task_enable_irq(STM32_IRQ_SPI1);*/

	/* Enable TX and RX DMA */
	spi->cr2 |= STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_RXDMAEN;

	/* Clear MSTR */
	spi->cr1 &= ~STM32_SPI_CR1_MSTR;

	/* Enable CRC */
	spi->cr1 |= STM32_SPI_CR1_CRCEN;

	/* Set SPE */
	spi->cr1 |= STM32_SPI_CR1_SPE;

	/* Dummy byte to clock out when the next packet comes in */
	spi->dr = DUMMY_DATA;

	/* Enable interrupt on PA0 (GPIO_SPI_NSS) */
	STM32_AFIO_EXTICR(0) &= ~0xF;
	STM32_EXTI_IMR |= (1 << 0);
	task_clear_pending_irq(STM32_IRQ_EXTI0);
	task_enable_irq(STM32_IRQ_EXTI0);
}
static void free_run_timer_overflow(void)
{
	/*
	 * If timer 4 (TIMER_H) counter register != 0xffffffff.
	 * This usually happens once after sysjump, force time, and etc.
	 * (when __hw_clock_source_set is called and param 'ts' != 0)
	 */
	if (IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_H) != 0xffffffff) {
		/* set timer counter register */
		IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_H) = 0xffffffff;
		/* bit[1], timer reset */
		IT83XX_ETWD_ETXCTRL(FREE_EXT_TIMER_L) |= (1 << 1);
	}
	/* w/c interrupt status */
	task_clear_pending_irq(et_ctrl_regs[FREE_EXT_TIMER_H].irq);
	/* timer overflow */
	process_timers(1);
	update_exc_start_time();
}
Example #20
0
int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
	     uint8_t *in, int in_size, int flags)
{
	struct i2c_port_data *pd = pdata + port;
	uint32_t events = 0;

	if (out_size == 0 && in_size == 0)
		return EC_SUCCESS;

	if (pd->i2ccs) {
		if ((flags & I2C_XFER_SINGLE) == I2C_XFER_SINGLE)
			flags &= ~I2C_XFER_START;
	}

	/* Copy data to port struct */
	pd->out = out;
	pd->out_size = out_size;
	pd->in = in;
	pd->in_size = in_size;
	pd->flags = flags;
	pd->widx = 0;
	pd->ridx = 0;
	pd->err = 0;
	pd->addr = slave_addr;

	if (port < I2C_STANDARD_PORT_COUNT) {
		/* Make sure we're in a good state to start */
		if ((flags & I2C_XFER_START) && (i2c_is_busy(port)
			|| (IT83XX_SMB_HOSTA(port) & HOSTA_ALL_WC_BIT)
			|| (i2c_get_line_levels(port) != I2C_LINE_IDLE))) {

			/* Attempt to unwedge the port. */
			i2c_unwedge(port);
			/* reset i2c port */
			i2c_reset(port, I2C_RC_NO_IDLE_FOR_START);
		}
	} else {
		/* Make sure we're in a good state to start */
		if ((flags & I2C_XFER_START) && (i2c_is_busy(port)
			|| (i2c_get_line_levels(port) != I2C_LINE_IDLE))) {
			/* Attempt to unwedge the port. */
			i2c_unwedge(port);
			/* reset i2c port */
			i2c_reset(port, I2C_RC_NO_IDLE_FOR_START);
		}
	}

	pd->task_waiting = task_get_current();
	if (pd->flags & I2C_XFER_START) {
		pd->i2ccs = I2C_CH_NORMAL;
		/* enable i2c interrupt */
		task_clear_pending_irq(i2c_ctrl_regs[port].irq);
		task_enable_irq(i2c_ctrl_regs[port].irq);
	}
	/* Start transaction */
	i2c_transaction(port);
	/* Wait for transfer complete or timeout */
	events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, pd->timeout_us);
	/* disable i2c interrupt */
	task_disable_irq(i2c_ctrl_regs[port].irq);
	pd->task_waiting = TASK_ID_INVALID;

	/* Handle timeout */
	if (!(events & TASK_EVENT_I2C_IDLE)) {
		pd->err = EC_ERROR_TIMEOUT;
		/* reset i2c port */
		i2c_reset(port, I2C_RC_TIMEOUT);
	}

	/* reset i2c channel status */
	if (pd->err)
		pd->i2ccs = I2C_CH_NORMAL;

	return pd->err;
}
Example #21
0
static int enhanced_i2c_tran_read(int p)
{
	struct i2c_port_data *pd = pdata + p;
	uint8_t in_data = 0;
	int p_ch;

	/* Shift register */
	p_ch = i2c_ch_reg_shift(p);

	if (pd->flags & I2C_XFER_START) {
		/* clear start flag */
		pd->flags &= ~I2C_XFER_START;

		/* reset channel */
		i2c_reset(p, 0);

		/* Direct read  */
		pd->i2ccs = I2C_CH_WAIT_READ;

		/* Send ID */
		i2c_pio_trans_data(p, RX_DIRECT, (pd->addr + 1), 1);
	} else {
		if (pd->i2ccs) {
			if (pd->i2ccs == I2C_CH_REPEAT_START) {
				pd->i2ccs = I2C_CH_NORMAL;
				/* Receive data */
				i2c_pio_trans_data(p, RX_DIRECT, in_data, 0);
			} else if (pd->i2ccs == I2C_CH_WAIT_READ) {
				pd->i2ccs = I2C_CH_NORMAL;
				/*
				 * If device doesn't response ack, reset
				 * the channel and abort the transaction.
				 */
				if (!(IT83XX_I2C_STR(p_ch) & E_HOSTA_ACK)) {
					pd->err = E_HOSTA_ACK;
					i2c_reset(p, 0);
					/* Disable i2c module */
					IT83XX_I2C_CTR1(p_ch) = 0x00;
					return 0;
				}
				/* Receive data */
				i2c_pio_trans_data(p, RX_DIRECT, in_data, 0);
				/* Direct write with direct read protocol */
				task_clear_pending_irq(i2c_ctrl_regs[p].irq);
				/* Turn on irq before next direct read */
				task_enable_irq(i2c_ctrl_regs[p].irq);
			} else {
				/* Write to read */
				pd->i2ccs = I2C_CH_WAIT_READ;
				/* Send ID */
				i2c_pio_trans_data(p, RX_DIRECT,
					(pd->addr + 1), 1);
				/* Direct write with direct read protocol */
				task_clear_pending_irq(i2c_ctrl_regs[p].irq);
				/* Turn on irq before next direct read */
				task_enable_irq(i2c_ctrl_regs[p].irq);
			}
		} else {
			/* Wait for byte done */
			if (!(IT83XX_I2C_STR(p_ch) & E_HOSTA_BDS))
				return 1;

			if (pd->ridx < pd->in_size) {
				/* read data */
				*(pd->in++) = IT83XX_I2C_DRR(p_ch);
				pd->ridx++;

				/* done */
				if (pd->ridx == pd->in_size) {
					pd->in_size = 0;
					if (pd->flags & I2C_XFER_STOP) {
						pd->i2ccs = I2C_CH_NORMAL;
						/* Stop and finish */
						IT83XX_I2C_CTR(p_ch) =
							(E_STOP | E_HW_RST);
						/* Disable i2c module */
						IT83XX_I2C_CTR1(p_ch) = 0x00;
						return 0;
					}
					/* End the transaction */
					pd->i2ccs = I2C_CH_WAIT_READ;
					return 0;
				}
				/* read next byte */
				i2c_pio_trans_data(p, RX_DIRECT, in_data, 0);
			}
		}
	}
	return 1;
}
Example #22
0
void system_hibernate(uint32_t seconds, uint32_t microseconds)
{
	int i;

#ifdef CONFIG_HOSTCMD_PD
	/* Inform the PD MCU that we are going to hibernate. */
	host_command_pd_request_hibernate();
	/* Wait to ensure exchange with PD before hibernating. */
	msleep(100);
#endif

	cflush();

	if (board_hibernate)
		board_hibernate();

	/* Disable interrupts */
	interrupt_disable();
	for (i = 0; i <= 92; ++i) {
		task_disable_irq(i);
		task_clear_pending_irq(i);
	}

	for (i = 8; i <= 23; ++i)
		MEC1322_INT_DISABLE(i) = 0xffffffff;

	MEC1322_INT_BLK_DIS |= 0xffff00;

	/* Power down ADC VREF */
	MEC1322_EC_ADC_VREF_PD |= 1;

	/* Assert nSIO_RESET */
	MEC1322_PCR_PWR_RST_CTL |= 1;

	/* Disable UART */
	MEC1322_UART_ACT &= ~0x1;
	MEC1322_LPC_ACT &= ~0x1;

	/* Disable JTAG */
	MEC1322_EC_JTAG_EN &= ~1;

	/* Disable 32KHz clock */
	MEC1322_VBAT_CE &= ~0x2;

	/* Stop watchdog */
	MEC1322_WDG_CTL &= ~1;

	/* Stop timers */
	MEC1322_TMR32_CTL(0) &= ~1;
	MEC1322_TMR32_CTL(1) &= ~1;
	MEC1322_TMR16_CTL(0) &= ~1;

	/* Power down ADC */
	MEC1322_ADC_CTRL &= ~1;

	/* Disable blocks */
	MEC1322_PCR_CHIP_SLP_EN |= 0x3;
	MEC1322_PCR_EC_SLP_EN |= MEC1322_PCR_EC_SLP_EN_SLEEP;
	MEC1322_PCR_HOST_SLP_EN |= MEC1322_PCR_HOST_SLP_EN_SLEEP;
	MEC1322_PCR_EC_SLP_EN2 |= MEC1322_PCR_EC_SLP_EN2_SLEEP;
	MEC1322_PCR_SLOW_CLK_CTL &= 0xfffffc00;

	/* Set sleep state */
	MEC1322_PCR_SYS_SLP_CTL = (MEC1322_PCR_SYS_SLP_CTL & ~0x7) | 0x2;
	CPU_SCB_SYSCTRL |= 0x4;

	/* Setup GPIOs for hibernate */
	if (board_hibernate_late)
		board_hibernate_late();

#ifdef CONFIG_USB_PD_PORT_COUNT
	/*
	 * Leave USB-C charging enabled in hibernate, in order to
	 * allow wake-on-plug. 5V enable must be pulled low.
	 */
#if CONFIG_USB_PD_PORT_COUNT > 0
	gpio_set_flags(GPIO_USB_C0_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT);
	gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0);
#endif
#if CONFIG_USB_PD_PORT_COUNT > 1
	gpio_set_flags(GPIO_USB_C1_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT);
	gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 0);
#endif
#endif /* CONFIG_USB_PD_PORT_COUNT */

	if (hibernate_wake_pins_used > 0) {
		for (i = 0; i < hibernate_wake_pins_used; ++i) {
			const enum gpio_signal pin = hibernate_wake_pins[i];

			gpio_reset(pin);
			gpio_enable_interrupt(pin);
		}

		interrupt_enable();
		task_enable_irq(MEC1322_IRQ_GIRQ8);
		task_enable_irq(MEC1322_IRQ_GIRQ9);
		task_enable_irq(MEC1322_IRQ_GIRQ10);
		task_enable_irq(MEC1322_IRQ_GIRQ11);
		task_enable_irq(MEC1322_IRQ_GIRQ20);
	}

	if (seconds || microseconds) {
		MEC1322_INT_BLK_EN |= 1 << 17;
		MEC1322_INT_ENABLE(17) |= 1 << 20;
		interrupt_enable();
		task_enable_irq(MEC1322_IRQ_HTIMER);
		if (seconds > 2) {
			ASSERT(seconds <= 0xffff / 8);
			MEC1322_HTIMER_CONTROL = 1;
			MEC1322_HTIMER_PRELOAD =
				(seconds * 8 + microseconds / 125000);
		} else {
			MEC1322_HTIMER_CONTROL = 0;
			MEC1322_HTIMER_PRELOAD =
				(seconds * 1000000 + microseconds) * 2 / 71;
		}
	}

	asm("wfi");

	/* Use 48MHz clock to speed through wake-up */
	MEC1322_PCR_PROC_CLK_CTL = 1;

	/* Reboot */
	_system_reset(0, 1);

	/* We should never get here. */
	while (1)
		;
}
Example #23
0
static void lpc_init(void)
{
	/*
	 * DLM 52k~56k size select enable.
	 * For mapping LPC I/O cycle 800h ~ 9FFh to DLM 8D800 ~ 8D9FF.
	 */
	IT83XX_GCTRL_MCCR2 |= 0x10;

	IT83XX_GPIO_GCR = 0x06;

	/* 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.
	 */
	IT83XX_KBC_KBHICR |= 0x0C;

	/* 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);

	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);
	task_enable_irq(IT83XX_IRQ_PMC_IN);

	task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
	task_enable_irq(IT83XX_IRQ_PMC2_IN);

	task_clear_pending_irq(IT83XX_IRQ_PMC3_IN);
	task_enable_irq(IT83XX_IRQ_PMC3_IN);

	/* Sufficiently initialized */
	init_done = 1;

	/* Update host events now that we can copy them to memmap */
	update_host_event_status();
}
Example #24
0
void pm5_ibf_interrupt(void)
{
	task_clear_pending_irq(IT83XX_IRQ_PMC5_IN);
}
Example #25
0
void pm5_ibf_interrupt(void)
{
	pm_clear_ibf(LPC_PM5);
	task_clear_pending_irq(IT83XX_IRQ_PMC5_IN);
}
Example #26
0
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);
}
Example #27
0
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();
}
Example #28
0
/**
 * Start a PECI transaction
 *
 * @param  addr       client address
 * @param  w_len      write length (no include [Cmd Code] and [AW FCS])
 * @param  r_len      read length (no include [FCS])
 * @param  cmd_code   command code
 * @param  *w_buf How buffer pointer of write data
 * @param  *r_buf How buffer pointer of read data
 * @param  timeout_us transaction timeout unit:us
 *
 * @return zero if successful, non-zero if error
 */
static enum peci_status peci_transaction(uint8_t addr,
				uint8_t w_len,
				uint8_t r_len,
				enum peci_command_code cmd_code,
				uint8_t *w_buf,
				uint8_t *r_buf,
				int timeout_us)
{
	uint8_t status;
	int index;

	/*
	 * bit5, Both write and read data FIFO pointers will be cleared.
	 *
	 * bit4, This bit enables the PECI host to abort the transaction
	 *       when FCS error occurs.
	 *
	 * bit2, This bit enables the contention mechanism of the PECI bus.
	 *       When this bit is set, the host will abort the transaction
	 *       if the PECI bus is contentious.
	 */
	IT83XX_PECI_HOCTLR |= 0x34;

	/* This register is the target address field of the PECI protocol. */
	IT83XX_PECI_HOTRADDR = addr;

	/* This register is the write length field of the PECI protocol. */
	ASSERT(w_len <= PECI_WRITE_DATA_FIFO_SIZE);

	if (cmd_code == PECI_CMD_PING) {
		/* write length is 0 */
		IT83XX_PECI_HOWRLR = 0x00;
	} else {
		if ((cmd_code == PECI_CMD_WR_PKG_CFG) ||
			(cmd_code == PECI_CMD_WR_IAMSR) ||
			(cmd_code == PECI_CMD_WR_PCI_CFG) ||
			(cmd_code == PECI_CMD_WR_PCI_CFG_LOCAL)) {

			/* write length include Cmd Code + AW FCS */
			IT83XX_PECI_HOWRLR = w_len + 2;

			/* bit1, The bit enables the AW_FCS hardwired mechanism
			 * based on the PECI command. This bit is functional
			 * only when the AW_FCS supported command of
			 * PECI 2.0/3.0/3.1 is issued.
			 * When this bit is set, the hardware will handle the
			 * calculation of AW_FCS.
			 */
			IT83XX_PECI_HOCTLR |= 0x02;
		} else {
			/* write length include Cmd Code */
			IT83XX_PECI_HOWRLR = w_len + 1;

			IT83XX_PECI_HOCTLR &= ~0x02;
		}
	}

	/* This register is the read length field of the PECI protocol. */
	ASSERT(r_len <= PECI_READ_DATA_FIFO_SIZE);
	IT83XX_PECI_HORDLR = r_len;

	/* This register is the command field of the PECI protocol. */
	IT83XX_PECI_HOCMDR = cmd_code;

	/* The write data field of the PECI protocol. */
	for (index = 0x00; index < w_len; index++)
		IT83XX_PECI_HOWRDR = w_buf[index];

	peci_current_task = task_get_current();
#ifdef CONFIG_IT83XX_PECI_WITH_INTERRUPT
	task_clear_pending_irq(IT83XX_IRQ_PECI);
	task_enable_irq(IT83XX_IRQ_PECI);

	/* start */
	IT83XX_PECI_HOCTLR |= 0x01;

	/* pre-set timeout */
	index = timeout_us;
	if (task_wait_event(timeout_us) != TASK_EVENT_TIMER)
		index = 0;

	task_disable_irq(IT83XX_IRQ_PECI);
#else
	/* start */
	IT83XX_PECI_HOCTLR |= 0x01;

	for (index = 0x00; index < timeout_us; index += 16) {
		if (IT83XX_PECI_HOSTAR & PECI_STATUS_ANY_BIT)
			break;

		udelay(15);
	}
#endif
	peci_current_task = TASK_ID_INVALID;

	if (index < timeout_us) {

		status = IT83XX_PECI_HOSTAR;

		/* any error */
		if (IT83XX_PECI_HOSTAR & PECI_STATUS_ANY_ERR) {

			if (IT83XX_PECI_HOSTAR & PECI_STATUS_ERR_NEED_RST)
				peci_reset();

		} else if (IT83XX_PECI_HOSTAR & PECI_STATUS_FINISH) {

			/* The read data field of the PECI protocol. */
			for (index = 0x00; index < r_len; index++)
				r_buf[index] = IT83XX_PECI_HORDDR;

			/* W/C */
			IT83XX_PECI_HOSTAR = PECI_STATUS_FINISH;
			status = IT83XX_PECI_HOSTAR;
		}
	} else {
		/* transaction timeout */
		status = PECI_STATUS_TIMEOUT;
	}

	/* Don't disable PECI host controller if controller already enable. */
	IT83XX_PECI_HOCTLR = 0x08;

	/* W/C */
	IT83XX_PECI_HOSTAR = PECI_STATUS_ANY_BIT;

	return status;
}
static void event_timer_clear_pending_isr(void)
{
	/* w/c interrupt status */
	task_clear_pending_irq(et_ctrl_regs[EVENT_EXT_TIMER].irq);
}
Example #30
0
void system_hibernate(uint32_t seconds, uint32_t microseconds)
{
	int i;

	cflush();

	/* Disable interrupts */
	interrupt_disable();
	for (i = 0; i <= 92; ++i) {
		task_disable_irq(i);
		task_clear_pending_irq(i);
	}

	for (i = 8; i <= 23; ++i)
		MEC1322_INT_DISABLE(i) = 0xffffffff;
	MEC1322_INT_BLK_DIS |= 0xffff00;

	/* Set processor clock to lowest, 1MHz */
	MEC1322_PCR_PROC_CLK_CTL = 48;

	/* Power down ADC VREF */
	MEC1322_EC_ADC_VREF_PD |= 1;

	/* Assert nSIO_RESET */
	MEC1322_PCR_PWR_RST_CTL |= 1;

	/* Disable UART */
	MEC1322_UART_ACT &= ~0x1;
	MEC1322_LPC_ACT &= ~0x1;

	/* Disable JTAG */
	MEC1322_EC_JTAG_EN &= ~1;

	/* Disable 32KHz clock */
	MEC1322_VBAT_CE &= ~0x2;

	/* Stop watchdog */
	MEC1322_WDG_CTL &= ~1;

	/* Stop timers */
	MEC1322_TMR32_CTL(0) &= ~1;
	MEC1322_TMR32_CTL(1) &= ~1;
	MEC1322_TMR16_CTL(0) &= ~1;

	/* Power down ADC */
	MEC1322_ADC_CTRL &= ~1;

	/* Disable blocks */
	MEC1322_PCR_CHIP_SLP_EN |= 0x3;
	MEC1322_PCR_EC_SLP_EN |= 0xe0700ff7;
	MEC1322_PCR_HOST_SLP_EN |= 0x5f003;
	MEC1322_PCR_EC_SLP_EN2 |= 0x1ffffff8;
	MEC1322_PCR_SYS_SLP_CTL = (MEC1322_PCR_SYS_SLP_CTL & ~0x7) | 0x2;
	MEC1322_PCR_SLOW_CLK_CTL &= 0xfffffc00;
	CPU_SCB_SYSCTRL |= 0x4;

	system_unpower_gpio();

#ifdef CONFIG_WAKE_PIN
	gpio_set_flags_by_mask(gpio_list[CONFIG_WAKE_PIN].port,
			       gpio_list[CONFIG_WAKE_PIN].mask,
			       gpio_list[CONFIG_WAKE_PIN].flags);
	gpio_enable_interrupt(CONFIG_WAKE_PIN);
	interrupt_enable();
	task_enable_irq(MEC1322_IRQ_GIRQ8);
	task_enable_irq(MEC1322_IRQ_GIRQ9);
	task_enable_irq(MEC1322_IRQ_GIRQ10);
	task_enable_irq(MEC1322_IRQ_GIRQ11);
	task_enable_irq(MEC1322_IRQ_GIRQ20);
#endif

	if (seconds || microseconds) {
		MEC1322_INT_BLK_EN |= 1 << 17;
		MEC1322_INT_ENABLE(17) |= 1 << 20;
		interrupt_enable();
		task_enable_irq(MEC1322_IRQ_HTIMER);
		if (seconds > 2) {
			ASSERT(seconds <= 0xffff / 8);
			MEC1322_HTIMER_CONTROL = 1;
			MEC1322_HTIMER_PRELOAD =
				(seconds * 8 + microseconds / 125000);
		} else {
			MEC1322_HTIMER_CONTROL = 0;
			MEC1322_HTIMER_PRELOAD =
				(seconds * 1000000 + microseconds) * 2 / 71;
		}
	}

	asm("wfi");

	/* We lost states of most modules, let's just reboot */
	_system_reset(0, 1);
}