Source-Changes-HG archive

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

[src/trunk]: src/sys/external/bsd/dwc2/dist Import dwc2 2013-09-05



details:   https://anonhg.NetBSD.org/src/rev/47ee108ee6b9
branches:  trunk
changeset: 789727:47ee108ee6b9
user:      skrll <skrll%NetBSD.org@localhost>
date:      Thu Sep 05 07:53:10 2013 +0000

description:
Import dwc2 2013-09-05

diffstat:

 sys/external/bsd/dwc2/dist/dwc2_core.c     |  2731 ++++++++++++++++++++++++
 sys/external/bsd/dwc2/dist/dwc2_core.h     |   674 ++++++
 sys/external/bsd/dwc2/dist/dwc2_coreintr.c |   500 ++++
 sys/external/bsd/dwc2/dist/dwc2_hcd.c      |  3063 ++++++++++++++++++++++++++++
 sys/external/bsd/dwc2/dist/dwc2_hcd.h      |   772 +++++++
 sys/external/bsd/dwc2/dist/dwc2_hcdddma.c  |  1212 +++++++++++
 sys/external/bsd/dwc2/dist/dwc2_hcdintr.c  |  2147 +++++++++++++++++++
 sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c |   875 +++++++
 sys/external/bsd/dwc2/dist/dwc2_hw.h       |   817 +++++++
 9 files changed, 12791 insertions(+), 0 deletions(-)

diffs (truncated from 12827 to 300 lines):

diff -r 5f1db9320db2 -r 47ee108ee6b9 sys/external/bsd/dwc2/dist/dwc2_core.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/external/bsd/dwc2/dist/dwc2_core.c    Thu Sep 05 07:53:10 2013 +0000
@@ -0,0 +1,2731 @@
+/*     $NetBSD: dwc2_core.c,v 1.1.1.1 2013/09/05 07:53:10 skrll Exp $  */
+
+/*
+ * core.c - DesignWare HS OTG Controller common routines
+ *
+ * Copyright (C) 2004-2013 Synopsys, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the above-listed copyright holders may not be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The Core code provides basic services for accessing and managing the
+ * DWC_otg hardware. These services are used by both the Host Controller
+ * Driver and the Peripheral Controller Driver.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch11.h>
+
+#include "core.h"
+#include "hcd.h"
+
+/**
+ * dwc2_enable_common_interrupts() - Initializes the commmon interrupts,
+ * used in both device and host modes
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
+{
+       u32 intmsk;
+
+       /* Clear any pending OTG Interrupts */
+       writel(0xffffffff, hsotg->regs + GOTGINT);
+
+       /* Clear any pending interrupts */
+       writel(0xffffffff, hsotg->regs + GINTSTS);
+
+       /* Enable the interrupts in the GINTMSK */
+       intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT;
+
+       if (hsotg->core_params->dma_enable <= 0)
+               intmsk |= GINTSTS_RXFLVL;
+
+       intmsk |= GINTSTS_CONIDSTSCHNG | GINTSTS_WKUPINT | GINTSTS_USBSUSP |
+                 GINTSTS_SESSREQINT;
+
+       writel(intmsk, hsotg->regs + GINTMSK);
+}
+
+/*
+ * Initializes the FSLSPClkSel field of the HCFG register depending on the
+ * PHY type
+ */
+static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
+{
+       u32 hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK;
+       u32 fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK;
+       u32 hcfg, val;
+
+       if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
+            fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
+            hsotg->core_params->ulpi_fs_ls > 0) ||
+           hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
+               /* Full speed PHY */
+               val = HCFG_FSLSPCLKSEL_48_MHZ;
+       } else {
+               /* High speed PHY running at full speed or high speed */
+               val = HCFG_FSLSPCLKSEL_30_60_MHZ;
+       }
+
+       dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val);
+       hcfg = readl(hsotg->regs + HCFG);
+       hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
+       hcfg |= val;
+       writel(hcfg, hsotg->regs + HCFG);
+}
+
+/*
+ * Do core a soft reset of the core.  Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
+{
+       u32 greset;
+       int count = 0;
+
+       dev_vdbg(hsotg->dev, "%s()\n", __func__);
+
+       /* Wait for AHB master IDLE state */
+       do {
+               usleep_range(20000, 40000);
+               greset = readl(hsotg->regs + GRSTCTL);
+               if (++count > 50) {
+                       dev_warn(hsotg->dev,
+                                "%s() HANG! AHB Idle GRSTCTL=%0x\n",
+                                __func__, greset);
+                       return;
+               }
+       } while (!(greset & GRSTCTL_AHBIDLE));
+
+       /* Core Soft Reset */
+       count = 0;
+       greset |= GRSTCTL_CSFTRST;
+       writel(greset, hsotg->regs + GRSTCTL);
+       do {
+               usleep_range(20000, 40000);
+               greset = readl(hsotg->regs + GRSTCTL);
+               if (++count > 50) {
+                       dev_warn(hsotg->dev,
+                                "%s() HANG! Soft Reset GRSTCTL=%0x\n",
+                                __func__, greset);
+                       break;
+               }
+       } while (greset & GRSTCTL_CSFTRST);
+
+       /*
+        * NOTE: This long sleep is _very_ important, otherwise the core will
+        * not stay in host mode after a connector ID change!
+        */
+       usleep_range(150000, 200000);
+}
+
+static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+{
+       u32 usbcfg, i2cctl;
+
+       /*
+        * core_init() is now called on every switch so only call the
+        * following for the first time through
+        */
+       if (select_phy) {
+               dev_dbg(hsotg->dev, "FS PHY selected\n");
+               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg |= GUSBCFG_PHYSEL;
+               writel(usbcfg, hsotg->regs + GUSBCFG);
+
+               /* Reset after a PHY select */
+               dwc2_core_reset(hsotg);
+       }
+
+       /*
+        * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
+        * do this on HNP Dev/Host mode switches (done in dev_init and
+        * host_init).
+        */
+       if (dwc2_is_host_mode(hsotg))
+               dwc2_init_fs_ls_pclk_sel(hsotg);
+
+       if (hsotg->core_params->i2c_enable > 0) {
+               dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
+
+               /* Program GUSBCFG.OtgUtmiFsSel to I2C */
+               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL;
+               writel(usbcfg, hsotg->regs + GUSBCFG);
+
+               /* Program GI2CCTL.I2CEn */
+               i2cctl = readl(hsotg->regs + GI2CCTL);
+               i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK;
+               i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT;
+               i2cctl &= ~GI2CCTL_I2CEN;
+               writel(i2cctl, hsotg->regs + GI2CCTL);
+               i2cctl |= GI2CCTL_I2CEN;
+               writel(i2cctl, hsotg->regs + GI2CCTL);
+       }
+}
+
+static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+{
+       u32 usbcfg;
+
+       if (!select_phy)
+               return;
+
+       usbcfg = readl(hsotg->regs + GUSBCFG);
+
+       /*
+        * HS PHY parameters. These parameters are preserved during soft reset
+        * so only program the first time. Do a soft reset immediately after
+        * setting phyif.
+        */
+       switch (hsotg->core_params->phy_type) {
+       case DWC2_PHY_TYPE_PARAM_ULPI:
+               /* ULPI interface */
+               dev_dbg(hsotg->dev, "HS ULPI PHY selected\n");
+               usbcfg |= GUSBCFG_ULPI_UTMI_SEL;
+               usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
+               if (hsotg->core_params->phy_ulpi_ddr > 0)
+                       usbcfg |= GUSBCFG_DDRSEL;
+               break;
+       case DWC2_PHY_TYPE_PARAM_UTMI:
+               /* UTMI+ interface */
+               dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n");
+               usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
+               if (hsotg->core_params->phy_utmi_width == 16)
+                       usbcfg |= GUSBCFG_PHYIF16;
+               break;
+       default:
+               dev_err(hsotg->dev, "FS PHY selected at HS!\n");
+               break;
+       }
+
+       writel(usbcfg, hsotg->regs + GUSBCFG);
+
+       /* Reset after setting the PHY parameters */
+       dwc2_core_reset(hsotg);
+}
+
+static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+{
+       u32 usbcfg, hs_phy_type, fs_phy_type;
+
+       if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL &&
+           hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
+               /* If FS mode with FS PHY */
+               dwc2_fs_phy_init(hsotg, select_phy);
+       } else {
+               /* High speed PHY */
+               dwc2_hs_phy_init(hsotg, select_phy);
+       }
+
+       hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK;
+       fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK;
+
+       if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
+           fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
+           hsotg->core_params->ulpi_fs_ls > 0) {
+               dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
+               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg |= GUSBCFG_ULPI_FS_LS;
+               usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M;
+               writel(usbcfg, hsotg->regs + GUSBCFG);
+       } else {
+               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg &= ~GUSBCFG_ULPI_FS_LS;
+               usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
+               writel(usbcfg, hsotg->regs + GUSBCFG);
+       }
+}
+
+static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
+{
+       u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+
+       switch (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) {
+       case GHWCFG2_EXT_DMA_ARCH:
+               dev_err(hsotg->dev, "External DMA Mode not supported\n");
+               return -EINVAL;
+
+       case GHWCFG2_INT_DMA_ARCH:
+               dev_dbg(hsotg->dev, "Internal DMA Mode\n");
+               if (hsotg->core_params->ahbcfg != -1) {
+                       ahbcfg &= GAHBCFG_CTRL_MASK;
+                       ahbcfg |= hsotg->core_params->ahbcfg &
+                                 ~GAHBCFG_CTRL_MASK;
+               }
+               break;



Home | Main Index | Thread Index | Old Index