Ejemplo n.º 1
0
/*
 * TODO(crbug.com/505480): Setting muxes often involves I2C transcations,
 * which can block. Consider implementing an asynchronous task.
 */
void usb_mux_set(int port, enum typec_mux mux_mode,
		 enum usb_switch usb_mode, int polarity)
{
	const struct usb_mux *mux = &usb_muxes[port];
	int res;
	mux_state_t mux_state;

#ifdef CONFIG_USB_CHARGER
	/* Configure USB2.0 */
	usb_charger_set_switches(port, usb_mode);
#endif

	/* Configure superspeed lanes */
	mux_state = polarity ? mux_mode | MUX_POLARITY_INVERTED : mux_mode;
	res = mux->driver->set(mux->port_addr, mux_state);
	if (res) {
		CPRINTS("Error setting mux port(%d): %d", port, res);
		return;
	}

	if (enable_debug_prints)
		CPRINTS(
		     "usb/dp mux: port(%d) typec_mux(%d) usb2(%d) polarity(%d)",
		     port, mux_mode, usb_mode, polarity);
}
Ejemplo n.º 2
0
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);
}