Re: [PATCH v20 7/9] usb: dwc3: qcom: Refactor IRQ handling in glue driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Apr 08, 2024, Krishna Kurapati wrote:
> On multiport supported controllers, each port has its own DP/DM
> and SS (if super speed capable) interrupts. As per the bindings,
> their interrupt names differ from standard ones having "_x" added
> as suffix (x indicates port number). Identify from the interrupt
> names whether the controller is a multiport controller or not.
> Refactor dwc3_qcom_setup_irq() call to parse multiport interrupts
> along with non-multiport ones accordingly..
> 
> Signed-off-by: Krishna Kurapati <quic_kriskura@xxxxxxxxxxx>
> Reviewed-by: Johan Hovold <johan+linaro@xxxxxxxxxx>
> ---
>  drivers/usb/dwc3/dwc3-qcom.c | 137 ++++++++++++++++++++++++++---------
>  1 file changed, 103 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
> index cae5dab8fcfc..35eb338514bc 100644
> --- a/drivers/usb/dwc3/dwc3-qcom.c
> +++ b/drivers/usb/dwc3/dwc3-qcom.c
> @@ -52,6 +52,13 @@
>  #define APPS_USB_AVG_BW 0
>  #define APPS_USB_PEAK_BW MBps_to_icc(40)
>  
> +struct dwc3_qcom_port {
> +	int			qusb2_phy_irq;
> +	int			dp_hs_phy_irq;
> +	int			dm_hs_phy_irq;
> +	int			ss_phy_irq;
> +};
> +
>  struct dwc3_qcom {
>  	struct device		*dev;
>  	void __iomem		*qscratch_base;
> @@ -59,11 +66,8 @@ struct dwc3_qcom {
>  	struct clk		**clks;
>  	int			num_clocks;
>  	struct reset_control	*resets;
> -
> -	int			qusb2_phy_irq;
> -	int			dp_hs_phy_irq;
> -	int			dm_hs_phy_irq;
> -	int			ss_phy_irq;
> +	struct dwc3_qcom_port	ports[DWC3_MAX_PORTS];
> +	u8			num_ports;
>  	enum usb_device_speed	usb2_speed;
>  
>  	struct extcon_dev	*edev;
> @@ -354,24 +358,24 @@ static void dwc3_qcom_disable_wakeup_irq(int irq)
>  
>  static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
>  {
> -	dwc3_qcom_disable_wakeup_irq(qcom->qusb2_phy_irq);
> +	dwc3_qcom_disable_wakeup_irq(qcom->ports[0].qusb2_phy_irq);
>  
>  	if (qcom->usb2_speed == USB_SPEED_LOW) {
> -		dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq);
> +		dwc3_qcom_disable_wakeup_irq(qcom->ports[0].dm_hs_phy_irq);
>  	} else if ((qcom->usb2_speed == USB_SPEED_HIGH) ||
>  			(qcom->usb2_speed == USB_SPEED_FULL)) {
> -		dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq);
> +		dwc3_qcom_disable_wakeup_irq(qcom->ports[0].dp_hs_phy_irq);
>  	} else {
> -		dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq);
> -		dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq);
> +		dwc3_qcom_disable_wakeup_irq(qcom->ports[0].dp_hs_phy_irq);
> +		dwc3_qcom_disable_wakeup_irq(qcom->ports[0].dm_hs_phy_irq);
>  	}
>  
> -	dwc3_qcom_disable_wakeup_irq(qcom->ss_phy_irq);
> +	dwc3_qcom_disable_wakeup_irq(qcom->ports[0].ss_phy_irq);
>  }
>  
>  static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
>  {
> -	dwc3_qcom_enable_wakeup_irq(qcom->qusb2_phy_irq, 0);
> +	dwc3_qcom_enable_wakeup_irq(qcom->ports[0].qusb2_phy_irq, 0);
>  
>  	/*
>  	 * Configure DP/DM line interrupts based on the USB2 device attached to
> @@ -383,20 +387,20 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
>  	 */
>  
>  	if (qcom->usb2_speed == USB_SPEED_LOW) {
> -		dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq,
> -						IRQ_TYPE_EDGE_FALLING);
> +		dwc3_qcom_enable_wakeup_irq(qcom->ports[0].dm_hs_phy_irq,
> +					    IRQ_TYPE_EDGE_FALLING);
>  	} else if ((qcom->usb2_speed == USB_SPEED_HIGH) ||
>  			(qcom->usb2_speed == USB_SPEED_FULL)) {
> -		dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq,
> -						IRQ_TYPE_EDGE_FALLING);
> +		dwc3_qcom_enable_wakeup_irq(qcom->ports[0].dp_hs_phy_irq,
> +					    IRQ_TYPE_EDGE_FALLING);
>  	} else {
> -		dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq,
> -						IRQ_TYPE_EDGE_RISING);
> -		dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq,
> -						IRQ_TYPE_EDGE_RISING);
> +		dwc3_qcom_enable_wakeup_irq(qcom->ports[0].dp_hs_phy_irq,
> +					    IRQ_TYPE_EDGE_RISING);
> +		dwc3_qcom_enable_wakeup_irq(qcom->ports[0].dm_hs_phy_irq,
> +					    IRQ_TYPE_EDGE_RISING);
>  	}
>  
> -	dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq, 0);
> +	dwc3_qcom_enable_wakeup_irq(qcom->ports[0].ss_phy_irq, 0);
>  }
>  
>  static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
> @@ -517,42 +521,107 @@ static int dwc3_qcom_request_irq(struct dwc3_qcom *qcom, int irq,
>  	return ret;
>  }
>  
> -static int dwc3_qcom_setup_irq(struct platform_device *pdev)
> +static int dwc3_qcom_setup_port_irq(struct platform_device *pdev, int port_index, bool is_multiport)
>  {
>  	struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
> +	const char *irq_name;
>  	int irq;
>  	int ret;
>  
> -	irq = platform_get_irq_byname_optional(pdev, "qusb2_phy");
> +	if (is_multiport)
> +		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dp_hs_phy_%d", port_index + 1);
> +	else
> +		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dp_hs_phy_irq");
> +	if (!irq_name)
> +		return -ENOMEM;
> +
> +	irq = platform_get_irq_byname_optional(pdev, irq_name);
>  	if (irq > 0) {
> -		ret = dwc3_qcom_request_irq(qcom, irq, "qusb2_phy");
> +		ret = dwc3_qcom_request_irq(qcom, irq, irq_name);
>  		if (ret)
>  			return ret;
> -		qcom->qusb2_phy_irq = irq;
> +		qcom->ports[port_index].dp_hs_phy_irq = irq;
>  	}
>  
> -	irq = platform_get_irq_byname_optional(pdev, "dp_hs_phy_irq");
> +	if (is_multiport)
> +		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dm_hs_phy_%d", port_index + 1);
> +	else
> +		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dm_hs_phy_irq");
> +	if (!irq_name)
> +		return -ENOMEM;
> +
> +	irq = platform_get_irq_byname_optional(pdev, irq_name);
>  	if (irq > 0) {
> -		ret = dwc3_qcom_request_irq(qcom, irq, "dp_hs_phy_irq");
> +		ret = dwc3_qcom_request_irq(qcom, irq, irq_name);
>  		if (ret)
>  			return ret;
> -		qcom->dp_hs_phy_irq = irq;
> +		qcom->ports[port_index].dm_hs_phy_irq = irq;
>  	}
>  
> -	irq = platform_get_irq_byname_optional(pdev, "dm_hs_phy_irq");
> +	if (is_multiport)
> +		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ss_phy_%d", port_index + 1);
> +	else
> +		irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ss_phy_irq");
> +	if (!irq_name)
> +		return -ENOMEM;
> +
> +	irq = platform_get_irq_byname_optional(pdev, irq_name);
>  	if (irq > 0) {
> -		ret = dwc3_qcom_request_irq(qcom, irq, "dm_hs_phy_irq");
> +		ret = dwc3_qcom_request_irq(qcom, irq, irq_name);
>  		if (ret)
>  			return ret;
> -		qcom->dm_hs_phy_irq = irq;
> +		qcom->ports[port_index].ss_phy_irq = irq;
>  	}
>  
> -	irq = platform_get_irq_byname_optional(pdev, "ss_phy_irq");
> +	if (is_multiport)
> +		return 0;
> +
> +	irq = platform_get_irq_byname_optional(pdev, "qusb2_phy");
>  	if (irq > 0) {
> -		ret = dwc3_qcom_request_irq(qcom, irq, "ss_phy_irq");
> +		ret = dwc3_qcom_request_irq(qcom, irq, "qusb2_phy");
> +		if (ret)
> +			return ret;
> +		qcom->ports[port_index].qusb2_phy_irq = irq;
> +	}
> +
> +	return 0;
> +}
> +
> +static int dwc3_qcom_find_num_ports(struct platform_device *pdev)
> +{
> +	char irq_name[14];
> +	int port_num;
> +	int irq;
> +
> +	irq = platform_get_irq_byname_optional(pdev, "dp_hs_phy_1");
> +	if (irq <= 0)
> +		return 1;
> +
> +	for (port_num = 2; port_num <= DWC3_MAX_PORTS; port_num++) {
> +		sprintf(irq_name, "dp_hs_phy_%d", port_num);
> +
> +		irq = platform_get_irq_byname_optional(pdev, irq_name);
> +		if (irq <= 0)
> +			return port_num - 1;
> +	}
> +
> +	return DWC3_MAX_PORTS;
> +}
> +
> +static int dwc3_qcom_setup_irq(struct platform_device *pdev)
> +{
> +	struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
> +	bool is_multiport;
> +	int ret;
> +	int i;
> +
> +	qcom->num_ports = dwc3_qcom_find_num_ports(pdev);
> +	is_multiport = (qcom->num_ports > 1);
> +
> +	for (i = 0; i < qcom->num_ports; i++) {
> +		ret = dwc3_qcom_setup_port_irq(pdev, i, is_multiport);
>  		if (ret)
>  			return ret;
> -		qcom->ss_phy_irq = irq;
>  	}
>  
>  	return 0;
> -- 
> 2.34.1
> 

Acked-by: Thinh Nguyen <Thinh.Nguyen@xxxxxxxxxxxx>

Thanks,
Thinh




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux