/*CPU_PER_RST_B low to high*/ void imx_KSZ9021RN_reset(void) { //max7310_set_gpio_output(0, 2, GPIO_LOW_LEVEL); //hal_delay_us(1000000); //max7310_set_gpio_output(0, 2, GPIO_HIGH_LEVEL); #ifdef BOARD_SABRE_LITE // Config gpio3_GPIO[23] to pad EIM_D23(D25) gpio_set_gpio(GPIO_PORT3, 23); HW_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_WR( BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_HYS_V(ENABLED) | BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_PUS_V(100K_OHM_PU) | BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_PUE_V(PULL) | BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_PKE_V(ENABLED) | BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_ODE_V(DISABLED) | BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_SPEED_V(100MHZ) | BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_DSE_V(40_OHM) | BF_IOMUXC_SW_PAD_CTL_PAD_EIM_DATA23_SRE_V(SLOW)); gpio_set_direction(GPIO3, 23, GPIO_GDIR_OUTPUT); gpio_set_level(GPIO3, 23, GPIO_LOW_LEVEL); hal_delay_us(1000000); // hold in reset for a delay gpio_set_level(GPIO3, 23, GPIO_LOW_HIGH); #endif }
/* Initialize board. */ static void board_init(void) { /* Enable PD MCU interrupt */ gpio_enable_interrupt(GPIO_PD_MCU_INT); /* Enable VBUS interrupt */ gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE_L); /* Enable pericom BC1.2 interrupts */ gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); /* Provide AC status to the PCH */ gpio_set_level(GPIO_PCH_ACOK, extpower_is_present()); }
static int svdm_exit_mode(int port, uint32_t *payload) { if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) { gpio_set_level(GPIO_PD_SBU_ENABLE, 0); alt_mode[PD_AMODE_DISPLAYPORT] = 0; pd_log_event(PD_EVENT_VIDEO_DP_MODE, 0, 0, NULL); } else if (PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) { alt_mode[PD_AMODE_GOOGLE] = 0; } else { CPRINTF("Unknown exit mode req:0x%08x\n", payload[0]); } return 1; /* Must return ACK */ }
int pd_set_power_supply_ready(int port) { /* Disable charging */ bd99955_select_input_port(BD99955_CHARGE_PORT_NONE); /* Provide VBUS */ gpio_set_level(port ? GPIO_C1_VOUT_EN_L : GPIO_C0_VOUT_EN_L, 0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); return EC_SUCCESS; /* we are ready */ }
static int test_clear_charge_done(void) { /* Lid is open initially. CHARGE_DONE is set. */ set_lid_open(1); msleep(TEST_CHECK_CHARGE_DELAY); gpio_set_level(GPIO_CHARGE_DONE, 1); TEST_ASSERT(gpio_get_level(GPIO_BASE_CHG_VDD_EN) == 0); TEST_ASSERT(gpio_get_level(GPIO_CHARGE_EN) == 0); /* Close the lid. Charging should start. */ set_lid_open(0); msleep(TEST_CHECK_CHARGE_DELAY); TEST_ASSERT(gpio_get_level(GPIO_BASE_CHG_VDD_EN) == 1); TEST_ASSERT(gpio_get_level(GPIO_CHARGE_EN) == 1); gpio_set_level(GPIO_CHARGE_DONE, 0); /* Charge is done. */ gpio_set_level(GPIO_CHARGE_DONE, 1); TEST_ASSERT(gpio_get_level(GPIO_BASE_CHG_VDD_EN) == 1); TEST_ASSERT(gpio_get_level(GPIO_CHARGE_EN) == 0); return EC_SUCCESS; }
static int svdm_dp_attention(int port, uint32_t *payload) { int cur_lvl; int lvl = PD_VDO_HPD_LVL(payload[1]); int irq = PD_VDO_HPD_IRQ(payload[1]); enum gpio_signal hpd = PORT_TO_HPD(port); cur_lvl = gpio_get_level(hpd); if (irq & cur_lvl) { gpio_set_level(hpd, 0); /* 250 usecs is minimum, 2msec is max */ if (port) hook_call_deferred(hpd1_irq_deferred, 300); else hook_call_deferred(hpd0_irq_deferred, 300); } else if (irq & !cur_lvl) { CPRINTF("PE ERR: IRQ_HPD w/ HPD_LOW\n"); return 0; /* nak */ } else { gpio_set_level(hpd, lvl); } /* ack */ return 1; }
static void keyboard_irq_assert(void) { #ifdef CONFIG_KEYBOARD_IRQ_GPIO /* * Enforce signal-high for long enough for the signal to be pulled high * by the external pullup resistor. This ensures the host will see the * following falling edge, regardless of the line state before this * function call. */ gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); udelay(4); /* Generate a falling edge */ gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 0); udelay(4); /* Set signal high, now that we've generated the edge */ gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); #else /* * SERIRQ is automatically sent by KBC */ #endif }
/** * Set active charge port -- only one port can active at a time. * * @param charge_port Charge port to enable. * * Return EC_SUCCESS if charge port is accepted and made active. * EC_ERROR_* otherwise. */ int board_set_active_charge_port(int charge_port) { /* charge port is a physical port */ int is_real_port = (charge_port >= 0 && charge_port < CONFIG_USB_PD_PORT_COUNT); /* check if we are source VBUS on the port */ int source = gpio_get_level(charge_port == 0 ? GPIO_USB_C0_5V_OUT : GPIO_USB_C1_5V_OUT); if (is_real_port && source) { CPRINTF("Skip enable p%d", charge_port); return EC_ERROR_INVAL; } CPRINTF("New chg p%d", charge_port); if (charge_port == CHARGE_PORT_NONE) { /* * TODO: currently we only get VBUS knowledge when charge * is enabled. so, when not changing, we need to enable * both ports. but, this is dangerous if you have two * chargers plugged in and you set charge override to -1 * then it will enable both sides! */ gpio_set_level(GPIO_USB_C0_CHARGE_L, 0); gpio_set_level(GPIO_USB_C1_CHARGE_L, 0); } else { /* Make sure non-charging port is disabled */ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_L : GPIO_USB_C1_CHARGE_L, 1); /* Enable charging port */ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_L : GPIO_USB_C0_CHARGE_L, 0); } return EC_SUCCESS; }
/* Enable or disable input devices, based upon chipset state and tablet mode */ static void enable_input_devices(void) { int kb_enable = 1; int tp_enable = 1; /* Disable KB & TP if chipset is off */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { kb_enable = 0; tp_enable = 0; } keyboard_scan_enable(kb_enable, KB_SCAN_DISABLE_LID_ANGLE); gpio_set_level(GPIO_EN_P3300_TRACKPAD_ODL, !tp_enable); }
void cts_task(void) { enum cts_rc rc; int i; gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH); for (i = 0; i < CTS_TEST_ID_COUNT; i++) { gpio_set_level(GPIO_OUTPUT_TEST, 1); gpio_set_level(GPIO_CTS_IRQ2, 1); sync(); rc = tests[i].run(); CPRINTF("\n%s %d\n", tests[i].name, rc); cflush(); } CPRINTS("Interrupt test suite finished"); cflush(); while (1) { watchdog_reload(); sleep(1); } }
void chipset_reset(int cold_reset) { CPRINTS("%s(%d)", __func__, cold_reset); if (cold_reset) { /* * Drop and restore PWROK. This causes the PCH to reboot, * regardless of its after-G3 setting. This type of reboot * causes the PCH to assert PLTRST#, SLP_S3#, and SLP_S5#, so * we actually drop power to the rest of the system (hence, a * "cold" reboot). */ /* Ignore if PWROK is already low */ if (gpio_get_level(GPIO_PCH_PWROK) == 0) return; /* PWROK must deassert for at least 3 RTC clocks = 91 us */ gpio_set_level(GPIO_PCH_PWROK, 0); udelay(100); gpio_set_level(GPIO_PCH_PWROK, 1); } else { /* * Send a RCIN# pulse to the PCH. This just causes it to * assert INIT# to the CPU without dropping power or asserting * PLTRST# to reset the rest of the system. */ /* * Pulse must be at least 16 PCI clocks long = 500 ns. */ gpio_set_level(GPIO_PCH_RCIN_L, 0); udelay(10); gpio_set_level(GPIO_PCH_RCIN_L, 1); } }
/* Initialize board. */ static void board_init(void) { timestamp_t now; #ifdef CONFIG_SPI_FLASH board_init_spi2(); #endif now = get_time(); hpd_prev_level = gpio_get_level(GPIO_DP_HPD); hpd_prev_ts = now.val; gpio_enable_interrupt(GPIO_DP_HPD); gpio_set_level(GPIO_STM_READY, 1); /* factory test only */ /* Delay needed to allow HDMI MCU to boot. */ hook_call_deferred(factory_validation_deferred, 200*MSEC); }
/* Enable or disable input devices, based upon chipset state and tablet mode */ static void enable_input_devices(void) { int kb_enable = 1; int tp_enable = 1; /* Disable both TP and KB in tablet mode */ if (!gpio_get_level(GPIO_TABLET_MODE_L)) kb_enable = tp_enable = 0; /* Disable TP if chipset is off */ else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) tp_enable = 0; keyboard_scan_enable(kb_enable, KB_SCAN_DISABLE_LID_ANGLE); gpio_set_level(GPIO_ENABLE_TOUCHPAD, tp_enable); }
void chipset_reset(int cold_reset) { CPRINTS("%s(%d)", __func__, cold_reset); if (cold_reset) { if (gpio_get_level(GPIO_SYS_RESET_L) == 0) return; gpio_set_level(GPIO_SYS_RESET_L, 0); /* Debounce time for SYS_RESET_L is 16 ms */ udelay(20 * MSEC); gpio_set_level(GPIO_SYS_RESET_L, 1); } else { /* * Send a RCIN_PCH_RCIN_L * assert INIT# to the CPU without dropping power or asserting * PLTRST# to reset the rest of the system. */ /* Pulse must be at least 16 PCI clocks long = 500 ns */ gpio_set_level(GPIO_PCH_RCIN_L, 0); udelay(10); gpio_set_level(GPIO_PCH_RCIN_L, 1); } }
/** * Set active charge port -- only one port can be active at a time. * * @param charge_port Charge port to enable. * * Returns EC_SUCCESS if charge port is accepted and made active, * EC_ERROR_* otherwise. */ int board_set_active_charge_port(int charge_port) { /* check if we are source vbus on that port */ int src = gpio_get_level(GPIO_CHGR_OTG); if (charge_port >= 0 && charge_port < CONFIG_USB_PD_PORT_COUNT && src) { CPRINTS("Port %d is not a sink, skipping enable", charge_port); return EC_ERROR_INVAL; } /* Enable/disable charging */ gpio_set_level(GPIO_USBC_CHARGE_EN_L, charge_port == CHARGE_PORT_NONE); return EC_SUCCESS; }
void vbus_wake_interrupt(enum gpio_signal signal) { CPRINTF("VBUS %d\n", !gpio_get_level(signal)); gpio_set_level(GPIO_USB_PD_VBUS_WAKE, !gpio_get_level(GPIO_VBUS_WAKE_L)); /* * TODO(crosbug.com/p/41226): * rev1/rev2 boards don't have vbus input on ec. vbus_wake is a * logical OR of two vbus status. to workaround the power status * issue, wake up both pd tasks on vbus_wake interrupt. a proper * hardware fix will be in rev3. * enable TCPC POWER_STATUS ALERT1 can solve this issue too. */ task_wake(TASK_ID_PD_C0); task_wake(TASK_ID_PD_C1); }
static void board_vbus_update_source_current(int port) { enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); /* * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin, * setting a minimum OCP current of 3186 mA. * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k * resistor on ILIM, setting a minimum OCP current of 1505 mA. */ gpio_set_level(gpio, vbus_en[port]); gpio_set_flags(gpio, flags); }
static void factory_validation_deferred(void) { struct mcdp_info info; mcdp_enable(); /* test mcdp via serial to validate function */ if (!mcdp_get_info(&info) && (MCDP_FAMILY(info.family) == 0x0010) && (MCDP_CHIPID(info.chipid) == 0x2850)) { gpio_set_level(GPIO_MCDP_READY, 1); pd_log_event(PD_EVENT_VIDEO_CODEC, PD_LOG_PORT_SIZE(0, sizeof(info)), 0, &info); } mcdp_disable(); }
/** * Turn off a PD port's DP output. */ void board_typec_dp_off(int port, int *dp_flags) { mutex_lock(&dp_hw_lock); if (dp_hw_port == !port) { mutex_unlock(&dp_hw_lock); return; } dp_hw_port = PD_PORT_NONE; gpio_set_level(GPIO_USB_DP_HPD, 0); mutex_unlock(&dp_hw_lock); /* Enable the other port if its dp flag is on */ if (dp_flags[!port] & DP_FLAGS_DP_ON) board_typec_dp_on(!port); }
static enum ec_error_list set(const char *name, int value) { enum gpio_signal signal = find_signal_by_name(name); if (signal == GPIO_COUNT) return EC_ERROR_INVAL; if (!gpio_is_implemented(signal)) return EC_ERROR_INVAL; if (!(gpio_get_default_flags(signal) & GPIO_OUTPUT)) return EC_ERROR_INVAL; gpio_set_level(signal, value); return EC_SUCCESS; }
/* * Various voltage rails will be enabled / disabled by the PMIC when * GPIO_PMIC_SLP_SUS_L changes. We need to delay the disable of V0.85A * by approximately 25ms in order to allow V1.00A to sufficiently discharge * first. * * Therefore, after GPIO_PMIC_SLP_SUS_L goes high, ignore the state of * the V12_EN pin: Keep V0.85A enabled. * * When GPIO_PMIC_SLP_SUS_L goes low, delay 25ms, and make V12_EN function * as normal - this should result in V0.85A discharging immediately after the * i2c write completes. */ void chipset_set_pmic_slp_sus_l(int level) { static int previous_level; int val; gpio_set_level(GPIO_PMIC_SLP_SUS_L, level); if (previous_level != level) { /* Rising edge: Force V0.85A enable. Falling: Pin control. */ val = level ? 0x80 : 0; if (!level) msleep(25); i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992, 0x43, val); previous_level = level; } }
static void set_pwrbtn_to_pch(int high) { /* * If the battery is discharging and low enough we'd shut down the * system, don't press the power button. Also, don't press the * power button if the battery is charging but the battery level * is too low. */ #ifdef CONFIG_CHARGER if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && !high && (charge_want_shutdown() || charge_prevent_power_on())) { CPRINTS("PB PCH pwrbtn ignored due to battery level"); high = 1; } #endif CPRINTS("PB PCH pwrbtn=%s", high ? "HIGH" : "LOW"); gpio_set_level(GPIO_PCH_PWRBTN_L, high); }
void pd_transition_voltage(int idx) { /* PDO index are starting from 1 */ switch (idx - 1) { case PDO_IDX_20V: gpio_set_level(GPIO_PP20000_EN, 1); gpio_set_level(GPIO_PPVAR_VBUS_EN, 0); break; case PDO_IDX_12V: gpio_set_level(GPIO_PP12000_EN, 1); gpio_set_level(GPIO_PP20000_EN, 0); gpio_set_level(GPIO_PPVAR_VBUS_EN, 1); break; case PDO_IDX_5V: default: gpio_set_level(GPIO_PP12000_EN, 0); gpio_set_level(GPIO_PP20000_EN, 0); gpio_set_level(GPIO_PPVAR_VBUS_EN, 1); } }
void periph_gpio_init() { gpio_config_t cfg; cfg.pin_bit_mask = BIT19; cfg.intr_type = (gpio_int_type_t) 0; cfg.mode = GPIO_MODE_OUTPUT; cfg.pull_down_en = (gpio_pulldown_t) 0; cfg.pull_up_en = (gpio_pullup_t) 0; gpio_config(&cfg); gpio_set_level((gpio_num_t) 19, (uint8_t) 0); cfg.pin_bit_mask = BIT26; cfg.intr_type = (gpio_int_type_t) 0; cfg.mode = GPIO_MODE_INPUT; cfg.pull_down_en = (gpio_pulldown_t) 0; cfg.pull_up_en = (gpio_pullup_t) 0; gpio_config(&cfg); }
static void handle_rsmrst(enum power_state state) { /* * Pass through RSMRST asynchronously, as PCH may not react * immediately to power changes. */ int rsmrst_in = gpio_get_level(GPIO_RSMRST_L_PGOOD); int rsmrst_out = gpio_get_level(GPIO_PCH_RSMRST_L); /* Nothing to do. */ if (rsmrst_in == rsmrst_out) return; /* * Wait at least 10ms between power signals going high * and deasserting RSMRST to PCH. */ if (rsmrst_in) msleep(10); gpio_set_level(GPIO_PCH_RSMRST_L, rsmrst_in); CPRINTS("RSMRST: %d", rsmrst_in); }
/****************************************************************************** * Initialize board. */ static void board_init(void) { /* USB to serial queues */ queue_init(&usart2_to_usb); queue_init(&usb_to_usart2); queue_init(&usart3_to_usb); queue_init(&usb_to_usart3); queue_init(&usart4_to_usb); queue_init(&usb_to_usart4); /* UART init */ usart_init(&usart2); usart_init(&usart3); usart_init(&usart4); /* Enable GPIO expander. */ gpio_set_level(GPIO_TCA6416_RESET_L, 1); /* Structured enpoints */ usb_spi_enable(&usb_spi, 1); }
static int bat_led_set_color(enum led_color color) { switch (color) { case LED_OFF: gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_OFF); gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_OFF); break; case LED_RED: gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_ON); gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_OFF); break; case LED_AMBER: gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_ON); gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_ON); break; case LED_GREEN: gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_OFF); gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_ON); break; default: return EC_ERROR_UNKNOWN; } return EC_SUCCESS; }
static void usb_charge_set_control_mode(int port_id, int mode) { #ifdef CONFIG_USB_PORT_POWER_SMART_SIMPLE /* * One single shared control signal, so the last mode set to either * port wins. Also, only CTL1 can be set; the other pins are * hard-wired. */ gpio_set_level(GPIO_USB_CTL1, mode & 0x4); #else if (port_id == 0) { gpio_set_level(GPIO_USB1_CTL1, mode & 0x4); gpio_set_level(GPIO_USB1_CTL2, mode & 0x2); gpio_set_level(GPIO_USB1_CTL3, mode & 0x1); } else { gpio_set_level(GPIO_USB2_CTL1, mode & 0x4); gpio_set_level(GPIO_USB2_CTL2, mode & 0x2); gpio_set_level(GPIO_USB2_CTL3, mode & 0x1); } #endif }
/** * Update backlight state. */ static void update_backlight(void) { int pch_value; pch_value = gpio_get_level(GPIO_PCH_BKLTEN); /* Immediately disable the backlight when the lid is closed or the PCH * is instructing the backlight to be disabled. */ if (!lid_is_open() || !pch_value) { /* If there was a scheduled callback pending make sure it picks * up the disabled value. */ backlight_deferred_value = 0; gpio_set_level(GPIO_ENABLE_BACKLIGHT, 0); /* Cancel pending hook */ hook_call_deferred(&set_backlight_value, -1); return; } /* Handle a 0->1 transition by calling a deferred hook. */ if (pch_value && !backlight_deferred_value) { backlight_deferred_value = 1; hook_call_deferred(&set_backlight_value, BL_ENABLE_DELAY_US); } }
void lcdvcc_interrupt(enum gpio_signal signal) { int pch_value; pch_value = gpio_get_level(GPIO_PCH_EDP_VDD_EN); /* Immediately disable the LCDVCC when the PCH indicates as such. */ if (!pch_value) { /* If there was a scheduled callback pending make sure it picks * up the disabled value. */ lcdvcc_en_deferred_value = 0; gpio_set_level(GPIO_EC_EDP_VDD_EN, 0); /* Cancel pending hook */ hook_call_deferred(&set_lcdvcc_en_value, -1); return; } /* Handle a 0->1 transition by calling a deferred hook. */ if (pch_value && !lcdvcc_en_deferred_value) { lcdvcc_en_deferred_value = 1; hook_call_deferred(&set_lcdvcc_en_value, LCDVCC_ENABLE_DELAY_US); } }