Ver código fonte

usb: cdns3: support separate IRQs for otg/xhci/dev

Some platforms (e.g. TI J721e) have separate interrupt lines
for OTG, XHCI and Device controllers. Provide for that.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Roger Quadros 6 anos atrás
pai
commit
b9d640489b

+ 41 - 7
drivers/usb/cdns3/core.c

@@ -325,30 +325,64 @@ static int cdns3_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, cdns);
 
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "host");
 	if (!res) {
-		dev_err(dev, "missing IRQ\n");
-		return -ENODEV;
+		platform_get_resource_byname(pdev, IORESOURCE_IRQ, 0);
+		if (!res) {
+			dev_err(dev, "missing host IRQ\n");
+			return -ENODEV;
+		}
 	}
-	cdns->irq = res->start;
 
 	cdns->xhci_res[0] = *res;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "xhci");
-	if (!res)
+	if (!res) {
+		dev_err(dev, "couldn't get xhci resource\n");
 		return -ENXIO;
+	}
 
 	cdns->xhci_res[1] = *res;
 
+	cdns->dev_irq = platform_get_irq_byname(pdev, "peripheral");
+	if (cdns->dev_irq == -EPROBE_DEFER)
+		return cdns->dev_irq;
+
+	if (cdns->dev_irq < 0) {
+		cdns->dev_irq = platform_get_irq(pdev, 0);
+		if (cdns->dev_irq < 0) {
+			if (cdns->dev_irq != -EPROBE_DEFER)
+				dev_err(dev, "couldn't get peripheral irq\n");
+			return cdns->dev_irq;
+		}
+	}
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dev");
 	regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(regs))
+	if (IS_ERR(regs)) {
+		dev_err(dev, "couldn't iomap dev resource\n");
 		return PTR_ERR(regs);
+	}
 	cdns->dev_regs	= regs;
 
+	cdns->otg_irq = platform_get_irq_byname(pdev, "otg");
+	if (cdns->otg_irq == -EPROBE_DEFER)
+		return cdns->otg_irq;
+
+	if (cdns->otg_irq < 0) {
+		cdns->otg_irq = platform_get_irq(pdev, 0);
+		if (cdns->otg_irq < 0) {
+			if (cdns->otg_irq != -EPROBE_DEFER)
+				dev_err(dev, "couldn't get otg irq\n");
+			return cdns->otg_irq;
+		}
+	}
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otg");
-	if (!res)
+	if (!res) {
+		dev_err(dev, "couldn't get otg resource\n");
 		return -ENXIO;
+	}
 
 	cdns->otg_res = *res;
 

+ 4 - 2
drivers/usb/cdns3/core.h

@@ -52,7 +52,8 @@ struct cdns3_role_driver {
  * @otg_v0_regs: pointer to base of v0 otg registers
  * @otg_v1_regs: pointer to base of v1 otg registers
  * @otg_regs: pointer to base of otg registers
- * @irq: irq number for controller
+ * @otg_irq: irq number for otg controller
+ * @dev_irq: irq number for device controller
  * @roles: array of supported roles for this controller
  * @role: current role
  * @host_dev: the child host device pointer for cdns3 core
@@ -94,7 +95,8 @@ struct cdns3 {
 #define CDNS3_CONTROLLER_V1	1
 	u32				version;
 
-	int				irq;
+	int				otg_irq;
+	int				dev_irq;
 	struct cdns3_role_driver	*roles[CDNS3_ROLE_END];
 	enum cdns3_roles		role;
 	struct platform_device		*host_dev;

+ 7 - 4
drivers/usb/cdns3/drd.c

@@ -135,7 +135,7 @@ static int cdns3_drd_switch_host(struct cdns3 *cdns, int on)
 	if (on) {
 		writel(OTGCMD_HOST_BUS_REQ | reg, &cdns->otg_regs->cmd);
 
-		dev_dbg(cdns->dev, "Waiting till Host mode is turned on\n");
+		dev_info(cdns->dev, "Waiting till Host mode is turned on\n");
 		ret = cdns3_handshake(&cdns->otg_regs->sts, OTGSTS_XHCI_READY,
 				      OTGSTS_XHCI_READY, 100000);
 
@@ -170,7 +170,7 @@ static int cdns3_drd_switch_gadget(struct cdns3 *cdns, int on)
 	if (on) {
 		writel(OTGCMD_DEV_BUS_REQ | reg, &cdns->otg_regs->cmd);
 
-		dev_dbg(cdns->dev, "Waiting till Device mode is turned on\n");
+		dev_info(cdns->dev, "Waiting till Device mode is turned on\n");
 
 		ret = cdns3_handshake(&cdns->otg_regs->sts, OTGSTS_DEV_READY,
 				      OTGSTS_DEV_READY, 100000);
@@ -347,12 +347,15 @@ int cdns3_drd_init(struct cdns3 *cdns)
 	cdns->desired_dr_mode = cdns->dr_mode;
 	cdns->current_dr_mode = USB_DR_MODE_UNKNOWN;
 
-	ret = devm_request_threaded_irq(cdns->dev, cdns->irq, cdns3_drd_irq,
+	ret = devm_request_threaded_irq(cdns->dev, cdns->otg_irq,
+					cdns3_drd_irq,
 					NULL, IRQF_SHARED,
 					dev_name(cdns->dev), cdns);
 
-	if (ret)
+	if (ret) {
+		dev_err(cdns->dev, "couldn't get otg_irq\n");
 		return ret;
+	}
 
 	state = readl(&cdns->otg_regs->sts);
 	if (OTGSTS_OTG_NRDY(state) != 0) {

+ 2 - 2
drivers/usb/cdns3/gadget.c

@@ -2237,7 +2237,7 @@ void cdns3_gadget_exit(struct cdns3 *cdns)
 
 	cdns3_gadget_disable(cdns);
 
-	devm_free_irq(cdns->dev, cdns->irq, cdns);
+	devm_free_irq(cdns->dev, cdns->dev_irq, cdns);
 
 	pm_runtime_mark_last_busy(cdns->dev);
 	pm_runtime_put_autosuspend(cdns->dev);
@@ -2379,7 +2379,7 @@ static int __cdns3_gadget_init(struct cdns3 *cdns)
 		return ret;
 
 	priv_dev = cdns->gadget_dev;
-	ret = devm_request_threaded_irq(cdns->dev, cdns->irq,
+	ret = devm_request_threaded_irq(cdns->dev, cdns->dev_irq,
 					cdns3_device_irq_handler,
 					cdns3_device_thread_irq_handler,
 					IRQF_SHARED, dev_name(cdns->dev), cdns);