static void update_vbus_supplier(int port, int vbus_level) { struct charge_port_info charge; /* * If VBUS is low, or VBUS is high and we are not outputting VBUS * ourselves, then update the VBUS supplier. */ if (!vbus_level || !usb_charger_port_is_sourcing_vbus(port)) { charge.voltage = USB_CHARGER_VOLTAGE_MV; charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0; charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, port, &charge); } }
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); }