/** * 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); }
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); }
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); }
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); }
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); }
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); }
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); }
/** * 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); }
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); } }
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; }
/* 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); }
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 }
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); } }
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); } }
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(); }
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; }
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; }
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) ; }
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(); }
void pm5_ibf_interrupt(void) { task_clear_pending_irq(IT83XX_IRQ_PMC5_IN); }
void pm5_ibf_interrupt(void) { pm_clear_ibf(LPC_PM5); task_clear_pending_irq(IT83XX_IRQ_PMC5_IN); }
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); }
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(); }
/** * 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); }
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); }