Commit 643df901 authored by Krishna Kurapati's avatar Krishna Kurapati Committed by Greg Kroah-Hartman
Browse files

usb: dwc3: core: Introduce glue callbacks for flattened implementations



In certain situations like role switching, the glue layers need to be
informed of these events, so that they can take any necessary action.
But in non-flattened implementations, the glue drivers have no data on
when the core driver probe was successful post invoking of_platform_
populate. Now that the core driver supports flattened implementations
as well, introduce vendor callbacks that can be passed on from glue to
core before invoking dwc3_core_probe.

Introduce callbacks to notify glue layer of role_switch and run_stop
changes. These can be used by flattened implementation of Qualcomm
glue layer to generate connect/disconnect events in controller during
cable connect and run stop modifications by udc in device mode.

Acked-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Signed-off-by: default avatarKrishna Kurapati <krishna.kurapati@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250907181412.2174616-2-krishna.kurapati@oss.qualcomm.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5df186e2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2352,6 +2352,7 @@ static int dwc3_probe(struct platform_device *pdev)
		return -ENOMEM;

	dwc->dev = &pdev->dev;
	dwc->glue_ops = NULL;

	probe_data.dwc = dwc;
	probe_data.res = res;
+26 −0
Original line number Diff line number Diff line
@@ -992,6 +992,17 @@ struct dwc3_scratchpad_array {
	__le64	dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
};

/**
 * struct dwc3_glue_ops - The ops indicate the notifications that
 *				need to be passed on to glue layer
 * @pre_set_role: Notify glue of role switch notifications
 * @pre_run_stop: Notify run stop enable/disable information to glue
 */
struct dwc3_glue_ops {
	void	(*pre_set_role)(struct dwc3 *dwc, enum usb_role role);
	void	(*pre_run_stop)(struct dwc3 *dwc, bool is_on);
};

/**
 * struct dwc3 - representation of our controller
 * @drd_work: workqueue used for role swapping
@@ -1012,6 +1023,7 @@ struct dwc3_scratchpad_array {
 * @eps: endpoint array
 * @gadget: device side representation of the peripheral controller
 * @gadget_driver: pointer to the gadget driver
 * @glue_ops: Vendor callbacks for flattened device implementations.
 * @bus_clk: clock for accessing the registers
 * @ref_clk: reference clock
 * @susp_clk: clock used when the SS phy is in low power (S3) state
@@ -1197,6 +1209,8 @@ struct dwc3 {
	struct usb_gadget	*gadget;
	struct usb_gadget_driver *gadget_driver;

	const struct dwc3_glue_ops	*glue_ops;

	struct clk		*bus_clk;
	struct clk		*ref_clk;
	struct clk		*susp_clk;
@@ -1614,6 +1628,18 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
int dwc3_core_soft_reset(struct dwc3 *dwc);
void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);

static inline void dwc3_pre_set_role(struct dwc3 *dwc, enum usb_role role)
{
	if (dwc->glue_ops && dwc->glue_ops->pre_set_role)
		dwc->glue_ops->pre_set_role(dwc, role);
}

static inline void dwc3_pre_run_stop(struct dwc3 *dwc, bool is_on)
{
	if (dwc->glue_ops && dwc->glue_ops->pre_run_stop)
		dwc->glue_ops->pre_run_stop(dwc, is_on);
}

#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc);
void dwc3_host_exit(struct dwc3 *dwc);
+1 −0
Original line number Diff line number Diff line
@@ -464,6 +464,7 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
		break;
	}

	dwc3_pre_set_role(dwc, role);
	dwc3_set_mode(dwc, mode);
	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -2662,6 +2662,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
		dwc->pullups_connected = false;
	}

	dwc3_pre_run_stop(dwc, is_on);
	dwc3_gadget_dctl_write_safe(dwc, reg);

	do {