/* Called by APL power state machine when transitioning from G3 to S5 */ static void chipset_pre_init(void) { /* * No need to re-init PMIC since settings are sticky across sysjump. * However, be sure to check that PMIC is already enabled. If it is * then there's no need to re-sequence the PMIC. */ if (system_jumped_to_this_image() && gpio_get_level(GPIO_PMIC_EN)) return; /* Enable PP5000 before PP3300 due to NFC: chrome-os-partner:50807 */ gpio_set_level(GPIO_EN_PP5000, 1); while (!gpio_get_level(GPIO_PP5000_PG)) ; /* * To prevent SLP glitches, PMIC_EN (V5A_EN) should be enabled * at the same time as PP3300 (chrome-os-partner:51323). */ /* Enable 3.3V rail */ gpio_set_level(GPIO_EN_PP3300, 1); while (!gpio_get_level(GPIO_PP3300_PG)) ; /* Enable PMIC */ gpio_set_level(GPIO_PMIC_EN, 1); }
static int command_gpio_get(int argc, char **argv) { int changed, v, i; /* If a signal is specified, print only that one */ if (argc == 2) { i = find_signal_by_name(argv[1]); if (i == GPIO_COUNT) return EC_ERROR_PARAM1; v = gpio_get_level(i); changed = last_val_changed(i, v); ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '), gpio_get_name(i)); return EC_SUCCESS; } /* Otherwise print them all */ for (i = 0; i < GPIO_COUNT; i++) { if (!gpio_is_implemented(i)) continue; /* Skip unsupported signals */ v = gpio_get_level(i); changed = last_val_changed(i, v); ccprintf(" %d%c %s\n", v, (changed ? '*' : ' '), gpio_get_name(i)); /* Flush console to avoid truncating output */ cflush(); } return EC_SUCCESS; }
int board_get_version(void) { static int ver; if (!ver) { /* * read the board EC ID on the tristate strappings * using ternary encoding: 0 = 0, 1 = 1, Hi-Z = 2 */ uint8_t id0 = 0, id1 = 0; gpio_set_flags(GPIO_BOARD_ID0, GPIO_PULL_DOWN | GPIO_INPUT); gpio_set_flags(GPIO_BOARD_ID1, GPIO_PULL_DOWN | GPIO_INPUT); usleep(100); id0 = gpio_get_level(GPIO_BOARD_ID0); id1 = gpio_get_level(GPIO_BOARD_ID1); gpio_set_flags(GPIO_BOARD_ID0, GPIO_PULL_UP | GPIO_INPUT); gpio_set_flags(GPIO_BOARD_ID1, GPIO_PULL_UP | GPIO_INPUT); usleep(100); id0 = gpio_get_level(GPIO_BOARD_ID0) && !id0 ? 2 : id0; id1 = gpio_get_level(GPIO_BOARD_ID1) && !id1 ? 2 : id1; gpio_set_flags(GPIO_BOARD_ID0, GPIO_INPUT); gpio_set_flags(GPIO_BOARD_ID1, GPIO_INPUT); ver = id1 * 3 + id0; CPRINTS("Board ID = %d", ver); } return ver; }
static void anx74xx_cable_det_handler(void) { /* confirm if cable_det is asserted */ if (!gpio_get_level(GPIO_USB_C0_CABLE_DET) || gpio_get_level(GPIO_USB_C0_PD_RST_L)) return; task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); }
int usb_charger_port_is_sourcing_vbus(int port) { if (port == 0) return gpio_get_level(GPIO_USB_C0_5V_EN); #if CONFIG_USB_PD_PORT_COUNT >= 2 else if (port == 1) return gpio_get_level(GPIO_USB_C1_5V_EN); #endif /* Not a valid port */ return 0; }
int usb_charge_ports_enabled(void) { int mask = 0; if (gpio_get_level(GPIO_USB1_ENABLE)) mask |= (1 << 0); if (gpio_get_level(GPIO_USB2_ENABLE)) mask |= (1 << 1); return mask; }
static int board_get_usb_mux(int port, mux_state_t *mux_state) { int oe_disabled = gpio_get_level(GPIO_SS_MUX_OE_L); int dp_4lanes = gpio_get_level(GPIO_SS_MUX_SEL); if (oe_disabled) *mux_state = 0; else if (dp_4lanes) *mux_state = MUX_DP_ENABLED; else *mux_state = MUX_USB_ENABLED | MUX_DP_ENABLED; return EC_SUCCESS; }
static int gpio_command_get(struct host_cmd_handler_args *args) { const struct ec_params_gpio_get_v1 *p_v1 = args->params; struct ec_response_gpio_get_v1 *r_v1 = args->response; int i, len; if (args->version == 0) { const struct ec_params_gpio_get *p = args->params; struct ec_response_gpio_get *r = args->response; i = find_signal_by_name(p->name); if (i == GPIO_COUNT) return EC_RES_ERROR; r->val = gpio_get_level(i); args->response_size = sizeof(struct ec_response_gpio_get); return EC_RES_SUCCESS; } switch (p_v1->subcmd) { case EC_GPIO_GET_BY_NAME: i = find_signal_by_name(p_v1->get_value_by_name.name); if (i == GPIO_COUNT) return EC_RES_ERROR; r_v1->get_value_by_name.val = gpio_get_level(i); args->response_size = sizeof(r_v1->get_value_by_name); break; case EC_GPIO_GET_COUNT: r_v1->get_count.val = GPIO_COUNT; args->response_size = sizeof(r_v1->get_count); break; case EC_GPIO_GET_INFO: if (p_v1->get_info.index >= GPIO_COUNT) return EC_RES_ERROR; i = p_v1->get_info.index; len = strlen(gpio_get_name(i)); memcpy(r_v1->get_info.name, gpio_get_name(i), len+1); r_v1->get_info.val = gpio_get_level(i); r_v1->get_info.flags = gpio_get_default_flags(i); args->response_size = sizeof(r_v1->get_info); break; default: return EC_RES_INVALID_PARAM; } return EC_RES_SUCCESS; }
static int test_lid_open_during_charging(void) { /* Close the lid. Start charging. */ set_lid_open(0); msleep(TEST_CHECK_CHARGE_DELAY); gpio_set_level(GPIO_CHARGE_DONE, 0); TEST_ASSERT(gpio_get_level(GPIO_BASE_CHG_VDD_EN) == 1); TEST_ASSERT(gpio_get_level(GPIO_CHARGE_EN) == 1); /* Open the lid. Transmitter should be turned off. */ set_lid_open(1); msleep(TEST_CHECK_CHARGE_DELAY); TEST_ASSERT(gpio_get_level(GPIO_BASE_CHG_VDD_EN) == 0); TEST_ASSERT(gpio_get_level(GPIO_CHARGE_EN) == 0); /* Toggle charge done signal. Charging should not start. */ 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); gpio_set_level(GPIO_CHARGE_DONE, 0); TEST_ASSERT(gpio_get_level(GPIO_BASE_CHG_VDD_EN) == 0); TEST_ASSERT(gpio_get_level(GPIO_CHARGE_EN) == 0); return EC_SUCCESS; }
int system_get_board_version(void) { int v = 0; #ifdef CONFIG_BOARD_VERSION if (gpio_get_level(GPIO_BOARD_VERSION1)) v |= 0x01; if (gpio_get_level(GPIO_BOARD_VERSION2)) v |= 0x02; if (gpio_get_level(GPIO_BOARD_VERSION3)) v |= 0x04; #endif return v; }
/* * FIXME(dhendrix): Weak symbol hack until we can get a better solution for * both Amenia and Reef. */ void chipset_do_shutdown(void) { /* Disable PMIC */ gpio_set_level(GPIO_PMIC_EN, 0); /*Disable 3.3V rail */ gpio_set_level(GPIO_EN_PP3300, 0); while (gpio_get_level(GPIO_PP3300_PG)) ; /*Disable 5V rail */ gpio_set_level(GPIO_EN_PP5000, 0); while (gpio_get_level(GPIO_PP5000_PG)) ; }
static void tcpc_alert_event(enum gpio_signal signal) { if ((signal == GPIO_USB_C0_PD_INT_ODL) && !gpio_get_level(GPIO_USB_C0_PD_RST_L)) return; if ((signal == GPIO_USB_C1_PD_INT_ODL) && !gpio_get_level(GPIO_USB_C1_PD_RST_ODL)) return; #ifdef HAS_TASK_PDCMD /* Exchange status with TCPCs */ host_command_pd_send_status(PD_CHARGE_NO_CHANGE); #endif }
static int cmd_btn_press(int argc, char **argv) { enum gpio_signal gpio; char *e; int v; if (argc < 2) return EC_ERROR_PARAM_COUNT; if (!strcasecmp(argv[1], "volup")) gpio = GPIO_BTN_VOLU_L; else if (!strcasecmp(argv[1], "voldown")) gpio = GPIO_BTN_VOLD_L; else return EC_ERROR_PARAM1; if (argc < 3) { /* Just reading */ ccprintf("Button %s pressed = %d\n", argv[1], !gpio_get_level(gpio)); return EC_SUCCESS; } v = strtoi(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; if (v) gpio_set_flags(gpio, GPIO_OUT_LOW); else gpio_set_flags(gpio, GPIO_INPUT | GPIO_PULL_UP); return EC_SUCCESS; }
int IRAM_ATTR sdcard_read_detect_pin(void) { if (g_gpio >= 0) { return gpio_get_level(g_gpio); } return 0; }
/** * Initialize panel module. */ static void panel_init(void) { /* Set initial deferred value and signal to the current PCH signal. */ backlight_deferred_value = gpio_get_level(GPIO_PCH_BKLTEN); set_backlight_value(); update_backlight(); gpio_enable_interrupt(GPIO_PCH_BKLTEN); /* The interrupt is enabled for the GPIO_PCH_EDP_VDD_EN in the * chipset_haswell.c compilation unit. Initially set the value * to whatever it current is reading. */ lcdvcc_en_deferred_value = gpio_get_level(GPIO_PCH_EDP_VDD_EN); set_lcdvcc_en_value(); }
/** * 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 source = gpio_get_level(GPIO_USB_C0_5V_EN); /* charge port is a realy physical port */ if ((charge_port == 0) && source) { CPRINTS("Skip enable p%d", charge_port); return EC_ERROR_INVAL; } CPRINTS("New chg p%d", charge_port); if (charge_port == CHARGE_PORT_NONE) { /* Disable charge ports */ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1); } else { /* We have only one port, no need to make sure non-charging port is disabled */ /* Enable charging port */ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0); } 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); }
bool sdcard_is_exist() { if (g_gpio >= 0) { return (gpio_get_level(g_gpio) == 0x00); } return false; }
/** * Set active charge port -- Enable or Disable charging * * @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) { /* charge port is a realy physical port */ int is_real_port = (charge_port >= 0 && charge_port < CONFIG_USB_PD_PORT_COUNT); /* check if we are source vbus on that port */ int source = gpio_get_level(GPIO_USB_C0_5V_EN); if (is_real_port && source) { CPRINTS("Skip enable p%d", charge_port); return EC_ERROR_INVAL; } CPRINTS("New chg p%d", charge_port); if (charge_port == CHARGE_PORT_NONE) { /* Disable charging port */ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1); gpio_set_level(GPIO_EC_ACDET_CTRL, 1); } else { /* Enable charging port */ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0); gpio_set_level(GPIO_EC_ACDET_CTRL, 0); } return EC_SUCCESS; }
static int svdm_dp_attention(int port, uint32_t *payload) { int cur_lvl; int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); cur_lvl = gpio_get_level(GPIO_USBC_DP_HPD); dp_status = payload[1]; /* Its initial DP status message prior to config */ if (!(dp_flags & DP_FLAGS_DP_ON)) { if (lvl) dp_flags |= DP_FLAGS_HPD_HI_PENDING; return 1; } if (irq & cur_lvl) { gpio_set_level(GPIO_USBC_DP_HPD, 0); hook_call_deferred(&hpd_irq_deferred_data, HPD_DSTREAM_DEBOUNCE_IRQ); } else if (irq & !cur_lvl) { CPRINTF("ERR:HPD:IRQ&LOW\n"); return 0; /* nak */ } else { gpio_set_level(GPIO_USBC_DP_HPD, lvl); } /* ack */ return 1; }
uint16_t tcpc_get_alert_status(void) { uint16_t status = 0; if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) { if (gpio_get_level(GPIO_USB_C0_PD_RST_L)) status |= PD_STATUS_TCPC_ALERT_0; } if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) { if (gpio_get_level(GPIO_USB_C1_PD_RST_ODL)) status |= PD_STATUS_TCPC_ALERT_1; } return status; }
static int svdm_dp_attention(int port, uint32_t *payload) { int cur_lvl; int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); enum gpio_signal hpd = PORT_TO_HPD(port); cur_lvl = gpio_get_level(hpd); dp_status[port] = payload[1]; /* Its initial DP status message prior to config */ if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { if (lvl) dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; return 1; } if (irq & cur_lvl) { gpio_set_level(hpd, 0); hook_call_deferred(PORT_TO_HPD_IRQ_DEFERRED(port), HPD_DSTREAM_DEBOUNCE_IRQ); } else if (irq & !cur_lvl) { CPRINTF("ERR:HPD:IRQ&LOW\n"); return 0; /* nak */ } else { gpio_set_level(hpd, lvl); } /* ack */ return 1; }
static void siglog_deferred(void) { const struct gpio_info *g = gpio_list; unsigned int i; timestamp_t tdiff = {.val = 0}; /* Disable interrupts for input signals while we print stuff.*/ for (i = 0; i < POWER_SIGNAL_COUNT; i++) gpio_disable_interrupt(power_signal_list[i].gpio); CPRINTF("%d signal changes:\n", siglog_entries); for (i = 0; i < siglog_entries; i++) { if (i) tdiff.val = siglog[i].time.val - siglog[i-1].time.val; CPRINTF(" %.6ld +%.6ld %s => %d\n", siglog[i].time.val, tdiff.val, g[siglog[i].signal].name, siglog[i].level); } if (siglog_truncated) CPRINTF(" SIGNAL LOG TRUNCATED...\n"); siglog_entries = siglog_truncated = 0; /* Okay, turn 'em on again. */ for (i = 0; i < POWER_SIGNAL_COUNT; i++) gpio_enable_interrupt(power_signal_list[i].gpio); } DECLARE_DEFERRED(siglog_deferred); static void siglog_add(enum gpio_signal signal) { if (siglog_entries >= MAX_SIGLOG_ENTRIES) { siglog_truncated = 1; return; } siglog[siglog_entries].time = get_time(); siglog[siglog_entries].signal = signal; siglog[siglog_entries].level = gpio_get_level(signal); siglog_entries++; hook_call_deferred(siglog_deferred, SECOND); } #define SIGLOG(S) siglog_add(S) #else #define SIGLOG(S) #endif /* CONFIG_BRINGUP */ void power_signal_interrupt(enum gpio_signal signal) { SIGLOG(signal); /* Shadow signals and compare with our desired signal state. */ power_update_signals(); /* Wake up the task */ task_wake(TASK_ID_CHIPSET); }
static void print_gpio_info(int gpio) { int changed, v, flags; if (!gpio_is_implemented(gpio)) return; /* Skip unsupported signals */ v = gpio_get_level(gpio); #ifdef CONFIG_CMD_GPIO_EXTENDED flags = gpio_get_flags(gpio); #else flags = 0; #endif changed = last_val_changed(gpio, v); ccprintf(" %d%c %s%s%s%s%s%s%s%s%s%s\n", v, (changed ? '*' : ' '), (flags & GPIO_INPUT ? "I " : ""), (flags & GPIO_OUTPUT ? "O " : ""), (flags & GPIO_LOW ? "L " : ""), (flags & GPIO_HIGH ? "H " : ""), (flags & GPIO_ANALOG ? "A " : ""), (flags & GPIO_OPEN_DRAIN ? "ODR " : ""), (flags & GPIO_PULL_UP ? "PU " : ""), (flags & GPIO_PULL_DOWN ? "PD " : ""), (flags & GPIO_ALTERNATE ? "ALT " : ""), gpio_get_name(gpio)); /* Flush console to avoid truncating output */ cflush(); }
/** * Update status of non-debounced switches. * * Note that deferred functions are called in the same context as lid and * power button changes, so we don't need a mutex. */ static void switch_update(void) { static uint8_t prev; /* Make sure this is safe to call before power_button_init() */ if (!memmap_switches) return; prev = *memmap_switches; if (power_button_is_pressed()) *memmap_switches |= EC_SWITCH_POWER_BUTTON_PRESSED; else *memmap_switches &= ~EC_SWITCH_POWER_BUTTON_PRESSED; if (lid_is_open()) *memmap_switches |= EC_SWITCH_LID_OPEN; else *memmap_switches &= ~EC_SWITCH_LID_OPEN; if ((flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) == 0) *memmap_switches |= EC_SWITCH_WRITE_PROTECT_DISABLED; else *memmap_switches &= ~EC_SWITCH_WRITE_PROTECT_DISABLED; #ifdef CONFIG_SWITCH_DEDICATED_RECOVERY if (gpio_get_level(GPIO_RECOVERY_L) == 0) *memmap_switches |= EC_SWITCH_DEDICATED_RECOVERY; else *memmap_switches &= ~EC_SWITCH_DEDICATED_RECOVERY; #endif if (prev != *memmap_switches) CPRINTS("SW 0x%02x", *memmap_switches); }
static int svdm_dp_attention(int port, uint32_t *payload) { int cur_lvl; int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); dp_status[port] = payload[1]; cur_lvl = gpio_get_level(GPIO_USB_DP_HPD); /* Its initial DP status message prior to config */ if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { if (lvl) dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; return 1; } if (irq & cur_lvl) { board_typec_dp_on(port); } else if (irq & !cur_lvl) { CPRINTF("ERR:HPD:IRQ&LOW\n"); return 0; /* nak */ } else { board_typec_dp_set(port, lvl); } /* ack */ return 1; }
void hpd_event(enum gpio_signal signal) { timestamp_t now = get_time(); int level = gpio_get_level(signal); uint64_t cur_delta = now.val - hpd_prev_ts; /* store current time */ hpd_prev_ts = now.val; /* All previous hpd level events need to be re-triggered */ hook_call_deferred(hpd_lvl_deferred, -1); /* It's a glitch. Previous time moves but level is the same. */ if (cur_delta < HPD_USTREAM_DEBOUNCE_IRQ) return; if ((!hpd_prev_level && level) && (cur_delta < HPD_USTREAM_DEBOUNCE_LVL)) /* It's an irq */ hook_call_deferred(hpd_irq_deferred, 0); else if (cur_delta >= HPD_USTREAM_DEBOUNCE_LVL) hook_call_deferred(hpd_lvl_deferred, HPD_USTREAM_DEBOUNCE_LVL); hpd_prev_level = level; }
void usb_spi_board_enable(struct usb_spi_config const *config) { hook_call_deferred(&update_finished_data, -1); update_in_progress = 1; disable_ec_ap_spi(); if (config->state->enabled_host == USB_SPI_EC) enable_ec_spi(); else if (config->state->enabled_host == USB_SPI_AP) enable_ap_spi(); else { CPRINTS("DEVICE NOT SUPPORTED"); return; } /* Connect DIO A4, A8, and A14 to the SPI peripheral */ GWRITE(PINMUX, DIOA4_SEL, 0); /* SPI_MOSI */ GWRITE(PINMUX, DIOA8_SEL, 0); /* SPI_CS_L */ GWRITE(PINMUX, DIOA14_SEL, 0); /* SPI_CLK */ /* Set SPI_CS to be an internal pull up */ GWRITE_FIELD(PINMUX, DIOA14_CTL, PU, 1); CPRINTS("usb_spi enable %s", gpio_get_level(GPIO_AP_FLASH_SELECT) ? "AP" : "EC"); spi_enable(CONFIG_SPI_FLASH_PORT, 1); }
static int dp_status(int port, uint32_t *payload) { int opos = PD_VDO_OPOS(payload[0]); int hpd = gpio_get_level(GPIO_DP_HPD); if (opos != OPOS_DP) return 0; /* nak */ payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ (hpd == 1), /* HPD_HI|LOW */ 0, /* request exit DP */ 0, /* request exit USB */ 0, /* MF pref */ gpio_get_level(GPIO_PD_SBU_ENABLE), 0, /* power low */ 0x2); return 2; }
void Tubes::run_sensing() { while (1) { for (int i = 0; i < NUM_TUBES; i++){ tube_state[i] = gpio_get_level((gpio_num_t)sense_list[i]); } vTaskDelay(500 / portTICK_PERIOD_MS); } }