From patchwork Fri Oct 7 16:42:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Axel Haslam X-Patchwork-Id: 9367063 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2CB5C60752 for ; Fri, 7 Oct 2016 16:50:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1BBDC297A6 for ; Fri, 7 Oct 2016 16:50:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0EB44297A8; Fri, 7 Oct 2016 16:50:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A78BE297A6 for ; Fri, 7 Oct 2016 16:50:05 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bsYIO-0001bm-Tg; Fri, 07 Oct 2016 16:46:52 +0000 Received: from mail-wm0-x22c.google.com ([2a00:1450:400c:c09::22c]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bsYF7-0006WO-2S for linux-arm-kernel@lists.infradead.org; Fri, 07 Oct 2016 16:43:33 +0000 Received: by mail-wm0-x22c.google.com with SMTP id f193so43175213wmg.0 for ; Fri, 07 Oct 2016 09:43:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=p1sNG6S8WmQnt/i3IP6mJrToeGpOjNEcHDSWgdn3l5E=; b=2DXBzx40on5k+S8EYyP87ffYoZRufvdfYxL16R1kxPSMHcRZDzn/UqzePsEl2KmbL9 yUDksHkjJXbwXqXQQT8DL100i0YWxcBVXZjdz1ryBz+8PhTm125yxvQySQ1LPYWFIOMh NeJ7lVvAfnow7QtGYT1GCeX2rP0L0mWqFoGuWyKndXrA55M+C764ObBJVALic12s6b2H MPEctsfZ7phDN3Q/yDzgolgOvqtcHqM2z484cUXcC6/hptk7lwx5izW1A7UGxTzYzim6 K0owoXkBTYxot56SFFEio8VZu0PzCiEDEBM85zlThwD0/is3lJYph+S3v9f5Tp3K9jzN 5fFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=p1sNG6S8WmQnt/i3IP6mJrToeGpOjNEcHDSWgdn3l5E=; b=gY2JgCCUf5TsJ/YZ7BLs0daNVt+emiF90Ev2uILZDXA/3S2v+xlzWwIttVO3eFd6t3 Aw4MJnXOhB4s1X4LxOLD4g9J1rfldgyyoJ6qRfKddpoKDumvMTYLO/uHwOmMQ13HZCZO tsskX2+owWtHYGFOyh3OOiHeh31Gwyrm7VB32OW/iWMsCj0XLZUoP0up9pplI0GjQTwn +7jhZ9p/twqu7hEctg4yjjhg2Dc+BkG1EVFUuTPnBzNjKnVl2j8Yqr2i2nyV01SUSnro RzXlwL34A/EhKIVo1c3GZfAZaszhmPj4ncrshrYBo9ybHiO/moMlXUHjY7vQ/5QZhV5L G0xQ== X-Gm-Message-State: AA6/9Rmmx2+6FNSLEx94sJN+Lz2sm6WXzs3VmlF6LB/XImSu9RcoPSwQ0VxAiKtGG5DGBw8H X-Received: by 10.28.26.1 with SMTP id a1mr20162985wma.68.1475858587177; Fri, 07 Oct 2016 09:43:07 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id n5sm20353566wjv.35.2016.10.07.09.43.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 07 Oct 2016 09:43:06 -0700 (PDT) From: ahaslam@baylibre.com To: gregkh@linuxfoundation.org, robh+dt@kernel.org, nsekhar@ti.com, stern@rowland.harvard.edu, khilman@baylibre.com, sshtylyov@ru.mvista.com, david@lechnology.com Subject: [PATCH/RFT 07/12] USB: ohci-da8xx: Request gpios and handle interrupt in the driver Date: Fri, 7 Oct 2016 18:42:52 +0200 Message-Id: <1475858577-10366-8-git-send-email-ahaslam@baylibre.com> X-Mailer: git-send-email 2.7.1 In-Reply-To: <1475858577-10366-1-git-send-email-ahaslam@baylibre.com> References: <1475858577-10366-1-git-send-email-ahaslam@baylibre.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161007_094329_730513_6737F963 X-CRM114-Status: GOOD ( 22.24 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, Axel Haslam , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Axel Haslam Currently requesting the vbus and overcurrent gpio is handled on the board specific file. But this does not play well moving to device tree. In preparation to migrate to a device tree boot, handle requesting gpios and overcurrent interrupt on the usb driver itself, thus avoiding callbacks to arch/mach* Signed-off-by: Axel Haslam --- arch/arm/mach-davinci/board-da830-evm.c | 71 ++--------------------- arch/arm/mach-davinci/board-omapl138-hawk.c | 11 ---- drivers/usb/host/ohci-da8xx.c | 90 +++++++++++++++++++++++------ include/linux/platform_data/usb-davinci.h | 16 +++-- 4 files changed, 82 insertions(+), 106 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 8d126e4..cfba9fa 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -47,62 +47,15 @@ static const short da830_evm_usb11_pins[] = { -1 }; -static da8xx_ocic_handler_t da830_evm_usb_ocic_handler; - -static int da830_evm_usb_set_power(unsigned port, int on) -{ - gpio_set_value(ON_BD_USB_DRV, on); - return 0; -} - -static int da830_evm_usb_get_power(unsigned port) -{ - return gpio_get_value(ON_BD_USB_DRV); -} - -static int da830_evm_usb_get_oci(unsigned port) -{ - return !gpio_get_value(ON_BD_USB_OVC); -} - -static irqreturn_t da830_evm_usb_ocic_irq(int, void *); - -static int da830_evm_usb_ocic_notify(da8xx_ocic_handler_t handler) -{ - int irq = gpio_to_irq(ON_BD_USB_OVC); - int error = 0; - - if (handler != NULL) { - da830_evm_usb_ocic_handler = handler; - - error = request_irq(irq, da830_evm_usb_ocic_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "OHCI over-current indicator", NULL); - if (error) - pr_err("%s: could not request IRQ to watch over-current indicator changes\n", - __func__); - } else - free_irq(irq, NULL); - - return error; -} - static struct da8xx_ohci_platform_data da830_evm_usb11_pdata = { - .set_power = da830_evm_usb_set_power, - .get_power = da830_evm_usb_get_power, - .get_oci = da830_evm_usb_get_oci, - .ocic_notify = da830_evm_usb_ocic_notify, - + .gpio_vbus = ON_BD_USB_DRV, + .gpio_overcurrent = ON_BD_USB_OVC, + .flags = (DA8XX_OHCI_FLAG_GPIO_VBUS + | DA8XX_OHCI_FLAG_GPIO_OCI), /* TPS2065 switch @ 5V */ .potpgt = 3, /* 3 ms max */ }; -static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id) -{ - da830_evm_usb_ocic_handler(&da830_evm_usb11_pdata, 1); - return IRQ_HANDLED; -} - static __init void da830_evm_usb_init(void) { int ret; @@ -143,22 +96,6 @@ static __init void da830_evm_usb_init(void) return; } - ret = gpio_request(ON_BD_USB_DRV, "ON_BD_USB_DRV"); - if (ret) { - pr_err("%s: failed to request GPIO for USB 1.1 port power control: %d\n", - __func__, ret); - return; - } - gpio_direction_output(ON_BD_USB_DRV, 0); - - ret = gpio_request(ON_BD_USB_OVC, "ON_BD_USB_OVC"); - if (ret) { - pr_err("%s: failed to request GPIO for USB 1.1 port over-current indicator: %d\n", - __func__, ret); - return; - } - gpio_direction_input(ON_BD_USB_OVC); - ret = da8xx_register_usb11(&da830_evm_usb11_pdata); if (ret) pr_warn("%s: USB 1.1 registration failed: %d\n", __func__, ret); diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index 075be1b..8d72bc1 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -178,11 +178,6 @@ static __init void omapl138_hawk_mmc_init(void) gpio_free(DA850_HAWK_MMCSD_CD_PIN); } -static const short da850_hawk_usb11_pins[] = { - DA850_GPIO2_4, DA850_GPIO6_13, - -1 -}; - static struct da8xx_ohci_platform_data omapl138_hawk_usb11_pdata = { /* TPS2087 switch @ 5V */ .potpgt = 3 /* 3 ms max */ @@ -192,12 +187,6 @@ static __init void omapl138_hawk_usb_init(void) { int ret; - ret = davinci_cfg_reg_list(da850_hawk_usb11_pins); - if (ret) { - pr_warn("%s: USB 1.1 PinMux setup failed: %d\n", __func__, ret); - return; - } - /* USB_REFCLKIN is not used. */ ret = da8xx_register_usb20_phy_clk(false); if (ret) diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 9d9f8e3..d7a0f11 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef CONFIG_ARCH_DAVINCI_DA8XX #error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX." @@ -61,6 +62,24 @@ static void ohci_da8xx_disable(void) clk_disable_unprepare(usb11_clk); } + +static int ohci_da8xx_set_power(struct da8xx_ohci_platform_data *pdata, + int on) +{ + gpio_set_value(pdata->gpio_vbus, on); + return 0; +} + +static int ohci_da8xx_get_power(struct da8xx_ohci_platform_data *pdata) +{ + return gpio_get_value(pdata->gpio_vbus); +} + +static int ohci_da8xx_get_oci(struct da8xx_ohci_platform_data *pdata) +{ + return !gpio_get_value(pdata->gpio_overcurrent); +} + /* * Handle the port over-current indicator change. */ @@ -70,8 +89,18 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_platform_data *pdata, ocic_mask |= 1 << port; /* Once over-current is detected, the port needs to be powered down */ - if (pdata->get_oci(port) > 0) - pdata->set_power(port, 0); + if (ohci_da8xx_get_oci(pdata) > 0) + ohci_da8xx_set_power(pdata, 0); +} + +static irqreturn_t ohci_da8xx_ocic_irq(int irq, void *data) +{ + struct platform_device *pdev = (struct platform_device *) data; + struct da8xx_ohci_platform_data *pdata = dev_get_platdata(&pdev->dev); + + ohci_da8xx_ocic_handler(pdata, 1); + + return IRQ_HANDLED; } static int ohci_da8xx_init(struct usb_hcd *hcd) @@ -107,11 +136,11 @@ static int ohci_da8xx_init(struct usb_hcd *hcd) * the correct hub descriptor... */ rh_a = ohci_readl(ohci, &ohci->regs->roothub.a); - if (pdata->set_power) { + if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS) { rh_a &= ~RH_A_NPS; rh_a |= RH_A_PSM; } - if (pdata->get_oci) { + if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_OCI) { rh_a &= ~RH_A_NOCP; rh_a |= RH_A_OCPM; } @@ -185,11 +214,13 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1); /* The port power status (PPS) bit defaults to 1 */ - if (pdata->get_power && pdata->get_power(wIndex) == 0) + if ((pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS) + && ohci_da8xx_get_power(pdata) == 0) temp &= ~RH_PS_PPS; /* The port over-current indicator (POCI) bit is always 0 */ - if (pdata->get_oci && pdata->get_oci(wIndex) > 0) + if ((pdata->flags & DA8XX_OHCI_FLAG_GPIO_OCI) + && ohci_da8xx_get_oci(pdata) > 0) temp |= RH_PS_POCI; /* The over-current indicator change (OCIC) bit is 0 too */ @@ -214,10 +245,10 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dev_dbg(dev, "%sPortFeature(%u): %s\n", temp ? "Set" : "Clear", wIndex, "POWER"); - if (!pdata->set_power) + if (!(pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS)) return 0; - return pdata->set_power(wIndex, temp) ? -EPIPE : 0; + return ohci_da8xx_set_power(pdata, temp) ? -EPIPE : 0; case USB_PORT_FEAT_C_OVER_CURRENT: dev_dbg(dev, "%sPortFeature(%u): %s\n", temp ? "Set" : "Clear", wIndex, @@ -314,6 +345,38 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, return PTR_ERR(usb11_phy); } + + if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS) { + error = devm_gpio_request_one(&pdev->dev, + pdata->gpio_vbus, + GPIOF_DIR_OUT, "usb11 vbus"); + if (error) { + pr_err("could not request vbus gpio: %d\n", error); + return error; + } + } + + if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_OCI) { + error = devm_gpio_request_one(&pdev->dev, + pdata->gpio_overcurrent, + GPIOF_DIR_IN, "usb11 oci"); + if (error) { + pr_err("could not request oci gpio: %d\n", error); + return error; + } + + error = devm_request_irq(&pdev->dev, + gpio_to_irq(pdata->gpio_overcurrent), + ohci_da8xx_ocic_irq, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "ohci overcurrent indicator", pdev); + if (error) { + pr_err("could not request oci irq: %d\n", error); + return error; + } + } + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; @@ -341,15 +404,7 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, device_wakeup_enable(hcd->self.controller); - if (pdata->ocic_notify) { - error = pdata->ocic_notify(ohci_da8xx_ocic_handler); - if (error) - goto err_notify; - } - return 0; -err_notify: - usb_remove_hcd(hcd); err: usb_put_hcd(hcd); return error; @@ -367,9 +422,6 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, static inline void usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) { - struct da8xx_ohci_platform_data *pdata = dev_get_platdata(&pdev->dev); - - pdata->ocic_notify(NULL); usb_remove_hcd(hcd); usb_put_hcd(hcd); } diff --git a/include/linux/platform_data/usb-davinci.h b/include/linux/platform_data/usb-davinci.h index dffe3bf..b72f703 100644 --- a/include/linux/platform_data/usb-davinci.h +++ b/include/linux/platform_data/usb-davinci.h @@ -41,17 +41,15 @@ typedef void (*da8xx_ocic_handler_t)(struct da8xx_ohci_platform_data *pdata, /* Passed as the platform data to the OHCI driver */ struct da8xx_ohci_platform_data { - /* Switch the port power on/off */ - int (*set_power)(unsigned port, int on); - /* Read the port power status */ - int (*get_power)(unsigned port); - /* Read the port over-current indicator */ - int (*get_oci)(unsigned port); - /* Over-current indicator change notification (pass NULL to disable) */ - int (*ocic_notify)(da8xx_ocic_handler_t handler); - /* Time from power on to power good (in 2 ms units) */ u8 potpgt; + + u32 flags; +#define DA8XX_OHCI_FLAG_GPIO_VBUS (1 << 0) +#define DA8XX_OHCI_FLAG_GPIO_OCI (1 << 1) + + int gpio_vbus; + int gpio_overcurrent; }; void davinci_setup_usb(unsigned mA, unsigned potpgt_ms);