void pd_power_supply_reset(int port) { /* Kill VBUS */ gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }
void pd_power_supply_reset(int port) { /* Kill VBUS */ charger_enable_otg_power(0); gpio_set_level(GPIO_CHGR_OTG, 0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }
void pd_power_supply_reset(int port) { /* Disable VBUS */ gpio_set_level(port ? GPIO_C1_VOUT_EN_L : GPIO_C0_VOUT_EN_L, 1); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }
int pd_set_power_supply_ready(int port) { /* provide VBUS */ gpio_set_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN, 1); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); return EC_SUCCESS; /* we are ready */ }
void typec_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) { struct charge_port_info charge; charge.current = max_ma; charge.voltage = supply_voltage; charge_manager_update(CHARGE_SUPPLIER_TYPEC, port, &charge); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }
int pd_set_power_supply_ready(int port) { /* provide VBUS */ gpio_set_level(GPIO_CHGR_OTG, 1); charger_enable_otg_power(1); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); return EC_SUCCESS; /* we are ready */ }
void pd_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) { #ifdef CONFIG_CHARGE_MANAGER struct charge_port_info charge; charge.current = max_ma; charge.voltage = supply_voltage; charge_manager_update_charge(CHARGE_SUPPLIER_PD, port, &charge); #endif /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }
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 */ }
void pd_power_supply_reset(int port) { int prev_en; prev_en = vbus_en[port]; /* Disable VBUS */ vbus_en[port] = 0; board_vbus_update_source_current(port); /* Enable discharge if we were previously sourcing 5V */ if (prev_en) pd_set_vbus_discharge(port, 1); /* Give back the current quota we are no longer using */ charge_manager_source_port(port, 0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }
int pd_set_power_supply_ready(int port) { /* Ensure we're not charging from this port */ bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0); /* Ensure we advertise the proper available current quota */ charge_manager_source_port(port, 1); pd_set_vbus_discharge(port, 0); /* Provide VBUS */ vbus_en[port] = 1; board_vbus_update_source_current(port); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); return EC_SUCCESS; /* we are ready */ }
static int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { int cmd = PD_VDO_CMD(payload[0]); uint16_t dev_id = 0; CPRINTF("VDM/%d [%d] %08x\n", cnt, cmd, payload[0]); /* make sure we have some payload */ if (cnt == 0) return 0; switch (cmd) { case VDO_CMD_VERSION: /* guarantee last byte of payload is null character */ *(payload + cnt - 1) = 0; CPRINTF("version: %s\n", (char *)(payload+1)); break; case VDO_CMD_READ_INFO: case VDO_CMD_SEND_INFO: /* copy hash */ if (cnt == 7) { dev_id = VDO_INFO_HW_DEV_ID(payload[6]); pd_dev_store_rw_hash(port, dev_id, payload + 1); pd_send_host_event(PD_EVENT_UPDATE_DEVICE); CPRINTF("Dev:0x%04x SW:%d RW:%d\n", dev_id, VDO_INFO_SW_DBG_VER(payload[6]), VDO_INFO_IS_RW(payload[6])); } else if (cnt == 6) { /* really old devices don't have last byte */ pd_dev_store_rw_hash(port, dev_id, payload + 1); } break; case VDO_CMD_CURRENT: CPRINTF("Current: %dmA\n", payload[1]); break; case VDO_CMD_FLIP: board_flip_usb_mux(port); break; } return 0; }
static void usb_charger_bc12_detect(void) { int type; struct charge_port_info charge; type = charger_detect_get_device_type(); if (gpio_get_level(GPIO_AC_PRESENT) && type) { charge.voltage = USB_CHARGER_VOLTAGE_MV; if (type == CHARGE_SUPPLIER_BC12_CDP) charge.current = 1500; else charge.current = 500; charge_manager_update_charge(type, 0, &charge); } else reset_charge(0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }
/** * Called when charge override times out waiting for power swap. */ static void charge_override_timeout(void) { delayed_override_port = OVERRIDE_OFF; pd_send_host_event(PD_EVENT_POWER_CHANGE); }
/** * Called when charge override times out waiting for power swap. */ static void charge_override_timeout(void) { pd_send_host_event(PD_EVENT_POWER_CHANGE); }
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { int cmd = PD_VDO_CMD(payload[0]); uint16_t dev_id = 0; int is_rw, is_latest; /* make sure we have some payload */ if (cnt == 0) return 0; switch (cmd) { case VDO_CMD_VERSION: /* guarantee last byte of payload is null character */ *(payload + cnt - 1) = 0; CPRINTF("version: %s\n", (char *)(payload+1)); break; case VDO_CMD_READ_INFO: case VDO_CMD_SEND_INFO: /* copy hash */ if (cnt == 7) { dev_id = VDO_INFO_HW_DEV_ID(payload[6]); is_rw = VDO_INFO_IS_RW(payload[6]); is_latest = pd_dev_store_rw_hash(port, dev_id, payload + 1, is_rw ? SYSTEM_IMAGE_RW : SYSTEM_IMAGE_RO); /* * Send update host event unless our RW hash is * already known to be the latest update RW. */ if (!is_rw || !is_latest) pd_send_host_event(PD_EVENT_UPDATE_DEVICE); CPRINTF("DevId:%d.%d SW:%d RW:%d\n", HW_DEV_ID_MAJ(dev_id), HW_DEV_ID_MIN(dev_id), VDO_INFO_SW_DBG_VER(payload[6]), is_rw); } else if (cnt == 6) { /* really old devices don't have last byte */ pd_dev_store_rw_hash(port, dev_id, payload + 1, SYSTEM_IMAGE_UNKNOWN); } break; case VDO_CMD_CURRENT: CPRINTF("Current: %dmA\n", payload[1]); break; case VDO_CMD_FLIP: usb_mux_flip(port); break; #ifdef CONFIG_USB_PD_LOGGING case VDO_CMD_GET_LOG: pd_log_recv_vdm(port, cnt, payload); break; #endif /* CONFIG_USB_PD_LOGGING */ } return 0; }
void pd_execute_data_swap(int port, int data_role) { /* inform the host controller to change role */ pd_send_host_event(PD_EVENT_DATA_SWAP); }
void chg_ramp_task(void) { int task_wait_time = -1; int i, lim; uint64_t detect_end_time_us = 0, time_us; int last_active_port = CHARGE_PORT_NONE; /* * Static initializer so that we don't clobber early calls to this * module. */ static enum chg_ramp_state ramp_st_prev = CHG_RAMP_DISCONNECTED, ramp_st_new = CHG_RAMP_DISCONNECTED; int active_icl_new; /* Clear last OCP supplier to guarantee we ramp on first connect */ for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) oc_info[i][0].sup = CHARGE_SUPPLIER_NONE; while (1) { ramp_st_new = ramp_st; active_icl_new = active_icl; switch (ramp_st) { case CHG_RAMP_DISCONNECTED: /* Do nothing */ task_wait_time = -1; break; case CHG_RAMP_CHARGE_DETECT_DELAY: /* Delay for charge_manager to determine supplier */ /* * On entry to state, or if port changes, store the * OC recovery time, and calculate the detect end * time to exit this state. */ if (ramp_st_prev != ramp_st || active_port != last_active_port) { last_active_port = active_port; ACTIVE_OC_INFO.recover = reg_time.val - ACTIVE_OC_INFO.ts.val; detect_end_time_us = get_time().val + CHARGE_DETECT_DELAY; task_wait_time = CHARGE_DETECT_DELAY; break; } /* If detect delay has not passed, set wait time */ time_us = get_time().val; if (time_us < detect_end_time_us) { task_wait_time = detect_end_time_us - time_us; break; } /* Detect delay is over, fall through to next state */ ramp_st_new = CHG_RAMP_OVERCURRENT_DETECT; /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); case CHG_RAMP_OVERCURRENT_DETECT: /* Check if we should ramp or go straight to stable */ task_wait_time = SECOND; /* Skip ramp for specific suppliers */ if (!board_is_ramp_allowed(active_sup)) { active_icl_new = min_icl; ramp_st_new = CHG_RAMP_STABLE; break; } /* * If we are not drawing full charge, then don't ramp, * just wait in this state, until we are. */ if (!board_is_consuming_full_charge()) { task_wait_time = CURRENT_DRAW_DELAY; break; } /* * Compare recent OCP events, if all info matches, * then we don't need to ramp anymore. */ for (i = 0; i < RAMP_COUNT; i++) { if (oc_info[active_port][i].sup != active_sup || oc_info[active_port][i].recover > OC_RECOVER_MAX_TIME) break; } if (i == RAMP_COUNT) { /* Found OC threshold! */ active_icl_new = ACTIVE_OC_INFO.icl - RAMP_ICL_BACKOFF; ramp_st_new = CHG_RAMP_STABLE; } else { /* * Need to ramp to find OC threshold, start * at the minimum input current limit. */ active_icl_new = min_icl; ramp_st_new = CHG_RAMP_RAMP; } break; case CHG_RAMP_RAMP: /* Keep ramping until we find the limit */ task_wait_time = RAMP_CURR_DELAY; /* Pause ramping if we are not drawing full current */ if (!board_is_consuming_full_charge()) { task_wait_time = CURRENT_DRAW_DELAY; break; } /* If VBUS is sagging a lot, then stop ramping */ if (board_is_vbus_too_low(CHG_RAMP_VBUS_RAMPING)) { CPRINTS("VBUS low"); active_icl_new = MAX(min_icl, active_icl - RAMP_ICL_BACKOFF); ramp_st_new = CHG_RAMP_STABILIZE; task_wait_time = STABLIZE_DELAY; stablize_port = active_port; stablize_sup = active_sup; break; } /* Ramp the current limit if we haven't reached max */ if (active_icl == max_icl) ramp_st_new = CHG_RAMP_STABLE; else if (active_icl + RAMP_CURR_INCR_MA > max_icl) active_icl_new = max_icl; else active_icl_new = active_icl + RAMP_CURR_INCR_MA; break; case CHG_RAMP_STABILIZE: /* Wait for current to stabilize after ramp is done */ /* Use default delay for exiting this state */ task_wait_time = SECOND; if (active_port == stablize_port && active_sup == stablize_sup) { ramp_st_new = CHG_RAMP_STABLE; break; } ramp_st_new = active_port == CHARGE_PORT_NONE ? CHG_RAMP_DISCONNECTED : CHG_RAMP_CHARGE_DETECT_DELAY; break; case CHG_RAMP_STABLE: /* Maintain input current limit */ /* On entry log charging stats */ if (ramp_st_prev != ramp_st) { #ifdef CONFIG_USB_PD_LOGGING charge_manager_save_log(active_port); #endif /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } /* Keep an eye on VBUS and restart ramping if it dips */ if (board_is_ramp_allowed(active_sup) && board_is_vbus_too_low(CHG_RAMP_VBUS_STABLE)) { CPRINTS("VBUS low; Re-ramp"); active_icl_new = min_icl; ramp_st_new = CHG_RAMP_RAMP; } task_wait_time = STABLE_VBUS_MONITOR_INTERVAL; break; } if (ramp_st != ramp_st_new || active_icl != active_icl_new) CPRINTS("Ramp p%d st%d %dmA %dmA", active_port, ramp_st_new, min_icl, active_icl_new); ramp_st_prev = ramp_st; ramp_st = ramp_st_new; active_icl = active_icl_new; /* Set the input current limit */ lim = chg_ramp_get_current_limit(); board_set_charge_limit(active_port, active_sup, lim, lim); if (ramp_st == CHG_RAMP_STABILIZE) /* * When in stabilize state, supplier/port may change * and we don't want to wake up task until we have * slept this amount of time. */ usleep(task_wait_time); else task_wait_event(task_wait_time); } }
static void usb_charger_bc12_detect(int port) { int device_type, charger_status; struct charge_port_info charge; int type; charge.voltage = USB_CHARGER_VOLTAGE_MV; /* Read interrupt register to clear on chip */ pi3usb9281_get_interrupts(port); if (usb_charger_port_is_sourcing_vbus(port)) { /* If we're sourcing VBUS then we're not charging */ device_type = charger_status = 0; } else { /* Set device type */ device_type = pi3usb9281_get_device_type(port); charger_status = pi3usb9281_get_charger_status(port); } /* Debounce pin plug order if we detect a charger */ if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) { msleep(USB_CHG_DEBOUNCE_DELAY_MS); /* next operation might trigger a detach interrupt */ pi3usb9281_disable_interrupts(port); /* Ensure D+/D- are open before resetting */ pi3usb9281_set_switch_manual(port, 1); pi3usb9281_set_pins(port, 0); /* Let D+/D- relax to their idle state */ msleep(40); /* * Trigger chip reset to refresh detection registers. * WARNING: This reset is acceptable for samus_pd, * but may not be acceptable for devices that have * an OTG / device mode, as we may be interrupting * the connection. */ pi3usb9281_reset(port); /* * Restore data switch settings - switches return to * closed on reset until restored. */ usb_charger_set_switches(port, USB_SWITCH_RESTORE); /* Clear possible disconnect interrupt */ pi3usb9281_get_interrupts(port); /* Mask attach interrupt */ pi3usb9281_set_interrupt_mask(port, 0xff & ~PI3USB9281_INT_ATTACH); /* Re-enable interrupts */ pi3usb9281_enable_interrupts(port); msleep(USB_CHG_RESET_DELAY_MS); /* Clear possible attach interrupt */ pi3usb9281_get_interrupts(port); /* Re-enable attach interrupt */ pi3usb9281_set_interrupt_mask(port, 0xff); /* Re-read ID registers */ device_type = pi3usb9281_get_device_type(port); charger_status = pi3usb9281_get_charger_status(port); } /* Attachment: decode + update available charge */ if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) { if (PI3USB9281_CHG_STATUS_ANY(charger_status)) type = CHARGE_SUPPLIER_PROPRIETARY; else if (device_type & PI3USB9281_TYPE_CDP) type = CHARGE_SUPPLIER_BC12_CDP; else if (device_type & PI3USB9281_TYPE_DCP) type = CHARGE_SUPPLIER_BC12_DCP; else if (device_type & PI3USB9281_TYPE_SDP) type = CHARGE_SUPPLIER_BC12_SDP; else type = CHARGE_SUPPLIER_OTHER; charge.current = pi3usb9281_get_ilim(device_type, charger_status); charge_manager_update_charge(type, port, &charge); } else { /* Detachment: update available charge to 0 */ charge.current = 0; charge_manager_update_charge( CHARGE_SUPPLIER_PROPRIETARY, port, &charge); charge_manager_update_charge( CHARGE_SUPPLIER_BC12_CDP, port, &charge); charge_manager_update_charge( CHARGE_SUPPLIER_BC12_DCP, port, &charge); charge_manager_update_charge( CHARGE_SUPPLIER_BC12_SDP, port, &charge); charge_manager_update_charge( CHARGE_SUPPLIER_OTHER, port, &charge); } /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); }