summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/include/mach/pci.h323
-rw-r--r--arch/arm/mach-tegra/include/mach/platform.h1
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-tegra/nvodm/nvodm_services.c21
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_analog.c1909
-rw-r--r--arch/arm/mach-tegra/pci-enum.c637
-rw-r--r--arch/arm/mach-tegra/pci.c561
-rw-r--r--arch/arm/mach-tegra/tegra_sysmap.c2
-rw-r--r--drivers/mtd/devices/tegra_mtd_nand.c20
9 files changed, 1516 insertions, 1959 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 6b8ac3027872..075d18a45193 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -65,4 +65,5 @@ obj-$(CONFIG_TEGRA_NVEC_USER) += nvec_user.o
# PCIe support
obj-$(CONFIG_TEGRA_PCI) += pci.o
+obj-$(CONFIG_TEGRA_PCI) += pci-enum.o
diff --git a/arch/arm/mach-tegra/include/mach/pci.h b/arch/arm/mach-tegra/include/mach/pci.h
new file mode 100644
index 000000000000..e5eac3ad5640
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/pci.h
@@ -0,0 +1,323 @@
+/*
+ * arch/arm/mach-tegra/include/mach/pci.h
+ *
+ * Header file containing constants for the tegra PCIe driver.
+ *
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_TEGRA_PCI_H
+
+#include <linux/pci.h>
+#include <mach/platform.h>
+
+#include "nvrm_drf.h"
+#include "ap20/dev_ap_pcie2_root_port.h"
+#include "ap20/dev_ap_pcie2_pads.h"
+#include "ap20/arafi.h"
+
+extern void __iomem * volatile pci_tegra_regs;
+
+/*
+ * AXI address map for the PCIe aperture. AP20, defines 1GB in the AXI
+ * address map for PCIe.
+ *
+ * That address space is split into different regions, with sizes and
+ * offsets as follows. Exepct for the Register space, SW is free to slice the
+ * regions as it chooces.
+ *
+ * The split below seems to work fine for now.
+ *
+ * 0x8000_0000 to 0x80ff_ffff - Register space 16MB.
+ * 0x8100_0000 to 0x81ff_ffff - Config space 16MB.
+ * 0x8200_0000 to 0x82ff_ffff - Extended config space 16MB.
+ * 0x8300_0000 to 0x83ff_ffff - Downstream IO space
+ * ... Will be filled with other BARS like MSI/upstream IO etc.
+ * 0x9000_0000 to 0x9fff_ffff - non-prefetchable memory aperture
+ * 0xa000_0000 to 0xbfff_ffff - Prefetchable memory aperture
+ *
+ * Config and Extended config sizes are choosen to support
+ * maximum of 256 devices,
+ * which is good enough for all the AP20 use cases.
+ * */
+
+#define PCIE_REGS_SIZE 0x01000000UL
+#define PCIE_CONFIG_OFFSET PCIE_REGS_SIZE
+#define PCIE_CONFIG_SIZE 0x01000000UL
+#define PCIE_EXTENDED_CONFIG_OFFSET (PCIE_CONFIG_SIZE + PCIE_CONFIG_OFFSET)
+#define PCIE_EXTENDED_CONFIG_SIZE 0x01000000UL
+#define PCIE_DOWNSTREAM_IO_OFFSET (PCIE_EXTENDED_CONFIG_SIZE + \
+ PCIE_EXTENDED_CONFIG_OFFSET)
+#define PCIE_DOWNSTREAM_IO_SIZE 0x00100000UL
+
+#define PCIE_NON_PREFETCH_MEMORY_OFFSET 0x10000000UL
+#define PCIE_NON_PREFETCH_MEMORY_SIZE 0x10000000UL
+#define PCIE_PREFETCH_MEMORY_OFFSET (PCIE_NON_PREFETCH_MEMORY_OFFSET + \
+ PCIE_NON_PREFETCH_MEMORY_SIZE)
+#define PCIE_PREFETCH_MEMORY_SIZE 0x20000000UL
+
+/* PCIe registers can be classified into 4 regions.
+ *
+ * 1. AFI registers - AFI is a wrapper between PCIE and ARM AXI bus. These
+ * registers define the address translation registers, interrupt registers and
+ * some configuration (a.k.a CYA) registers.
+ * 2. PAD registers - PAD control registers which are inside the PCIE CORE.
+ * 3. Configuration 0 and Configuration 1 registers - These registers are PCIe
+ * configuration registers of Root port 0 and root port 1.
+ *
+ * Check the PcieRegType enumeration for the list of Registers banks inside the
+ * PCIE aperture.
+ *
+ * */
+#define NV_PCIE_AXI_AFI_REGS_OFSET 0x3800UL
+#define NV_PCIE_AXI_PADS_OFSET 0x3000UL
+#define NV_PCIE_AXI_RP_T0C0_OFFSET 0x0000UL
+#define NV_PCIE_AXI_RP_T0C1_OFFSET 0x1000UL
+
+/* During the boot only registers/config and extended config apertures are
+ * mapped. Rest are mapped on demand by the PCI device drivers.
+ */
+#define PCI_TEGRA_IOMAPPED_REG_APERTURE_SIZE \
+ (PCIE_REGS_SIZE + PCIE_CONFIG_SIZE + PCIE_EXTENDED_CONFIG_SIZE)
+
+/*
+ * PCI address map for memory mapped devices. Still using 32-bit aperture.
+ *
+ * 1GB for the system memory.
+ * Everything mapped as cpu physical = pci
+ *
+ */
+#define FPCI_SYSTEM_MEMORY_OFFSET 0x0UL
+#define FPCI_SYSTEM_MEMORY_SIZE 0x40000000UL
+#define FPCI_NON_PREFETCH_MEMORY_OFFSET 0x90000000UL
+#define FPCI_NON_PREFETCH_MEMORY_SIZE PCIE_NON_PREFETCH_MEMORY_SIZE
+#define FPCI_PREFETCH_MEMORY_OFFSET (FPCI_NON_PREFETCH_MEMORY_OFFSET+ \
+ FPCI_NON_PREFETCH_MEMORY_SIZE)
+#define FPCI_PREFETCH_MEMORY_SIZE 0x40000000UL
+
+
+
+
+/* PCIE DRF macros to read and write PRI registers */
+
+/** NVPCIE_DRF_DEF - define a new register value.
+
+ @param d register domain (hardware block)
+ @param r register name
+ @param f register field
+ @param c defined value for the field
+ */
+#define NVPCIE_DRF_DEF(d,r,f,c) \
+ ((NV_PROJ__PCIE2_##d##_##r##_##f##_##c) \
+ << NV_FIELD_SHIFT(NV_PROJ__PCIE2_##d##_##r##_##f))
+
+/** NVPCIE_DRF_NUM - define a new register value.
+
+ @param d register domain (hardware block)
+ @param r register name
+ @param f register field
+ @param n numeric value for the field
+ */
+#define NVPCIE_DRF_NUM(d,r,f,n) \
+ (((n)& NV_FIELD_MASK(NV_PROJ__PCIE2_##d##_##r##_##f)) << \
+ NV_FIELD_SHIFT(NV_PROJ__PCIE2_##d##_##r##_##f))
+
+/** NVPCIE_DRF_VAL - read a field from a register.
+
+ @param d register domain (hardware block)
+ @param r register name
+ @param f register field
+ @param v register value
+ */
+#define NVPCIE_DRF_VAL(d,r,f,v) \
+ (((v)>> NV_FIELD_SHIFT(NV_PROJ__PCIE2_##d##_##r##_##f)) & \
+ NV_FIELD_MASK(NV_PROJ__PCIE2_##d##_##r##_##f))
+
+/** NVPCIE_FLD_SET_DRF_NUM - modify a register field.
+
+ @param d register domain (hardware block)
+ @param r register name
+ @param f register field
+ @param n numeric field value
+ @param v register value
+ */
+#define NVPCIE_FLD_SET_DRF_NUM(d,r,f,n,v) \
+ ((v & ~NV_FIELD_SHIFTMASK(NV_PROJ__PCIE2_##d##_##r##_##f)) | \
+ NVPCIE_DRF_NUM(d,r,f,n))
+
+/** NVPCIE_FLD_SET_DRF_DEF - modify a register field.
+
+ @param d register domain (hardware block)
+ @param r register name
+ @param f register field
+ @param c defined field value
+ @param v register value
+ */
+#define NVPCIE_FLD_SET_DRF_DEF(d,r,f,c,v) \
+ (((v) & ~NV_FIELD_SHIFTMASK(NV_PROJ__PCIE2_##d##_##r##_##f)) | \
+ NVPCIE_DRF_DEF(d,r,f,c))
+
+/** NVPCIE_RESETVAL - get the reset value for a register.
+
+ @param d register domain (hardware block)
+ @param r register name
+ */
+#define NVPCIE_RESETVAL(d,r) (d##_##r##_0_RESET_VAL)
+
+/* Register access inline functions */
+
+static inline void pci_tegra_afi_writel(u32 value,unsigned long offset)
+{
+ writel(value, offset + NV_PCIE_AXI_AFI_REGS_OFSET + pci_tegra_regs);
+}
+
+static inline void pci_tegra_rp_writel(u32 value, unsigned long offset, int rp)
+{
+ BUG_ON(rp != 0 && rp != 1);
+
+ if (rp == 0) offset += NV_PCIE_AXI_RP_T0C0_OFFSET;
+ if (rp == 1) offset += NV_PCIE_AXI_RP_T0C1_OFFSET;
+
+ writel(value, offset + pci_tegra_regs);
+}
+
+static inline void pci_tegra_rp_writew(u16 value, unsigned long offset, int rp)
+{
+ u32 reg;
+
+ BUG_ON(rp != 0 && rp != 1);
+
+ if (rp == 0) offset += NV_PCIE_AXI_RP_T0C0_OFFSET;
+ if (rp == 1) offset += NV_PCIE_AXI_RP_T0C1_OFFSET;
+
+ reg = readl((offset & ~0x3) + pci_tegra_regs);
+ reg &= ~(0xffff << ((offset & 0x3) * 8));
+ reg |= (u32)value << ((offset & 0x3) * 8);
+ writel(reg, (offset & ~0x3) + pci_tegra_regs);
+}
+
+static inline void pci_tegra_rp_writeb(u8 value, unsigned long offset, int rp)
+{
+ u32 reg;
+
+ BUG_ON(rp != 0 && rp != 1);
+
+ if (rp == 0) offset += NV_PCIE_AXI_RP_T0C0_OFFSET;
+ if (rp == 1) offset += NV_PCIE_AXI_RP_T0C1_OFFSET;
+
+ reg = readl((offset & ~0x3) + pci_tegra_regs);
+ reg &= ~(0xff << ((offset & 0x3) * 8));
+ reg |= (u32)value << ((offset & 0x3) * 8);
+ writel(reg, (offset & ~0x3) + pci_tegra_regs);
+}
+
+static inline void pci_tegra_pads_writel(u32 value, unsigned long offset)
+{
+ writel(value, offset + NV_PCIE_AXI_PADS_OFSET + pci_tegra_regs);
+}
+
+static inline u32 pci_tegra_afi_readl(unsigned long offset)
+{
+ return readl(offset + NV_PCIE_AXI_AFI_REGS_OFSET + pci_tegra_regs);
+}
+
+static inline u32 pci_tegra_rp_readl(unsigned long offset, int rp)
+{
+ BUG_ON(rp != 0 && rp != 1);
+
+ if (rp == 0) offset += NV_PCIE_AXI_RP_T0C0_OFFSET;
+ if (rp == 1) offset += NV_PCIE_AXI_RP_T0C1_OFFSET;
+
+ return readl(offset + pci_tegra_regs);
+}
+
+static inline u16 pci_tegra_rp_readw(unsigned long offset, int rp)
+{
+ u32 val;
+
+ BUG_ON(rp != 0 && rp != 1);
+
+ if (rp == 0) offset += NV_PCIE_AXI_RP_T0C0_OFFSET;
+ if (rp == 1) offset += NV_PCIE_AXI_RP_T0C1_OFFSET;
+
+ val = readl((offset & ~0x3) + pci_tegra_regs);
+ val >>= 8 * (offset & 3);
+ val &= 0xffff;
+
+ return (u16)val;
+}
+
+static inline u8 pci_tegra_rp_readb(unsigned long offset, int rp)
+{
+ u32 val;
+
+ BUG_ON(rp != 0 && rp != 1);
+
+ if (rp == 0) offset += NV_PCIE_AXI_RP_T0C0_OFFSET;
+ if (rp == 1) offset += NV_PCIE_AXI_RP_T0C1_OFFSET;
+
+ val = readl((offset & ~0x3) + pci_tegra_regs);
+ val >>= 8 * (offset & 3);
+ val &= 0xff;
+
+ return (u8)val;
+}
+
+static inline u32 pci_tegra_pads_reedl(unsigned long offset)
+{
+ return readl(offset + NV_PCIE_AXI_PADS_OFSET + pci_tegra_regs);
+}
+
+static inline bool pci_tegra_is_rp(u32 bus_number, int *rp)
+{
+ if (bus_number == pci_tegra_rp_readb(PCI_PRIMARY_BUS, 0)) {
+ *rp = 0;
+ return true;
+ } else if (bus_number == pci_tegra_rp_readb(PCI_PRIMARY_BUS, 1)) {
+ *rp = 1;
+ return true;
+ } else
+ return false;
+}
+
+/*
+ * Given the bus number, devfn and the offset this API returns the mapped
+ * address of the config space.
+ */
+static inline void __iomem *pci_tegra_config_addr(u8 bus_number,
+ u32 devfn, u32 where)
+{
+ void *addr;
+ u32 function;
+ u32 device;
+
+ function = PCI_FUNC(devfn);
+ device = PCI_SLOT(devfn);
+
+ addr = pci_tegra_regs;
+ addr += (where < 256) ? PCIE_CONFIG_OFFSET
+ : PCIE_EXTENDED_CONFIG_OFFSET;
+ addr += bus_number << 16;
+ addr += device << 11;
+ addr += function << 8;
+ addr += where;
+ return addr;
+}
+
+void pci_tegra_enumerate(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/platform.h b/arch/arm/mach-tegra/include/mach/platform.h
index 54cb086e58b3..f80632aff0a8 100644
--- a/arch/arm/mach-tegra/include/mach/platform.h
+++ b/arch/arm/mach-tegra/include/mach/platform.h
@@ -27,6 +27,7 @@ extern unsigned int tegra_get_module_inst_irq(const char *, int, int);
#define TEGRA_PL310_IRQ (tegra_get_module_inst_irq("pl310", 0, 0))
#define TEGRA_SCU_BASE (tegra_get_module_inst_base("scu", 0))
+#define TEGRA_PCIE_BASE (tegra_get_module_inst_base("pcie", 0))
#define TEGRA_SCU0_IRQ NO_IRQ
#define TEGRA_SCU1_IRQ NO_IRQ
diff --git a/arch/arm/mach-tegra/nvodm/nvodm_services.c b/arch/arm/mach-tegra/nvodm/nvodm_services.c
index 76f1bb344760..97e950e59d9b 100644..100755
--- a/arch/arm/mach-tegra/nvodm/nvodm_services.c
+++ b/arch/arm/mach-tegra/nvodm/nvodm_services.c
@@ -937,24 +937,9 @@ NvOdmPwmConfig(NvOdmServicesPwmHandle hOdmPwm,
void NvOdmEnableOtgCircuitry(NvBool Enable)
{
- NvRmDeviceHandle hRmDevice;
- NvRmAnalogUsbConfig UsbConfig;
- NvError e;
-
- // Open RM device handle
- NV_CHECK_ERROR_CLEANUP(NvRmOpen(&hRmDevice, 0));
-
- UsbConfig.InParam = NvRmAnalogUsbInputParam_ConfigureUsbPhy;
- NV_CHECK_ERROR_CLEANUP(
- NvRmAnalogInterfaceControl(hRmDevice, NvRmAnalogInterface_Usb,
- NV_TRUE, &UsbConfig, sizeof(NvRmAnalogUsbConfig))
- );
-
- fail:
- if (hRmDevice)
- {
- NvRmClose(hRmDevice);
- }
+ // Rm analog interface calls related to usb are deleted. This API does nothing.
+ // This API should not be called for usb phy related operations
+ return;
}
NvBool NvOdmUsbIsConnected(void)
diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_analog.c b/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_analog.c
index 3c6bc3e7c523..e0fdb14938b3 100644..100755
--- a/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_analog.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_analog.c
@@ -44,129 +44,6 @@
#include "nvodm_pmu.h"
#include "nvrm_clocks.h"
#include "nvrm_module.h"
-#include "ap20/arusb.h"
-
-/**
- * Structure defining the fields for USB UTMI clocks delay Parameters.
- */
-typedef struct UsbPllDelayParamsRec
-{
- // Pll-U Enable Delay Count
- NvU8 EnableDelayCount;
- //PLL-U Stable count
- NvU8 StableCount;
- //Pll-U Active delay count
- NvU8 ActiveDelayCount;
- //PLL-U Xtal frequency count
- NvU8 XtalFreqCount;
-} UsbPllDelayParams;
-
-/*
- * Set of oscillator frequencies supported
- */
-typedef enum
-{
- NvRmClocksOscFreq_13_MHz = 0x0,
- NvRmClocksOscFreq_19_2_MHz,
- NvRmClocksOscFreq_12_MHz,
- NvRmClocksOscFreq_26_MHz,
- NvRmClocksOscFreq_Num, // dummy to get number of frequencies
- NvRmClocksOscFreq_Force32 = 0x7fffffff
-} NvRmClocksOscFreq;
-
-// Possible Oscillator Frequecies in KHz for mapping the index
-NvRmFreqKHz s_RmOscFrequecy [NvRmClocksOscFreq_Num] =
-{
- 13000, // 13 Mega Hertz
- 19200,// 19.2 Mega Hertz
- 12000,// 12 Mega Hertz
- 26000 // 26 Mega Hertz
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// USB PLL CONFIGURATION & PARAMETERS: refer to the arapb_misc_utmip.spec file.
-///////////////////////////////////////////////////////////////////////////////
-// PLL CONFIGURATION & PARAMETERS for different clock generators:
-//-----------------------------------------------------------------------------
-// Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz
-// ----------------------------------------------------------------------------
-// PLLU_ENABLE_DLY_COUNT 02 (02h) 03 (03h) 02 (02h) 04 (04h)
-// PLLU_STABLE_COUNT 51 (33h) 75 (4Bh) 47 (2Fh) 102 (66h)
-// PLL_ACTIVE_DLY_COUNT 05 (05h) 06 (06h) 04 (04h) 09 (09h)
-// XTAL_FREQ_COUNT 127 (7Fh) 187 (BBh) 118 (76h) 254 (FEh)
-///////////////////////////////////////////////////////////////////////////////
-static const UsbPllDelayParams s_UsbPllDelayParams[NvRmClocksOscFreq_Num] =
-{
- //ENABLE_DLY, STABLE_CNT, ACTIVE_DLY, XTAL_FREQ_CNT
- {0x02, 0x33, 0x05, 0x7F}, // For NvRmClocksOscFreq_13_MHz,
- {0x03, 0x4B, 0x06, 0xBB}, // For NvRmClocksOscFreq_19_2_MHz
- {0x02, 0x2F, 0x04, 0x76}, // For NvRmClocksOscFreq_12_MHz
- {0x04, 0x66, 0x09, 0xFE} // For NvRmClocksOscFreq_26_MHz
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// USB Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and SessEnd.
-// Each of these signals have their own debouncer and for each of those one out
-// of 2 debouncing times can be chosen (BIAS_DEBOUNCE_A or BIAS_DEBOUNCE_B.)
-//
-// The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows:
-// 0xffff -> No debouncing at all
-// <n> ms = <n> *1000 / (1/19.2MHz) / 4
-// So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have:
-// BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0
-// We need to use only DebounceA, We dont need the DebounceB
-// values, so we can keep those to default.
-///////////////////////////////////////////////////////////////////////////////
-static const NvU32 s_UsbBiasDebounceATime[NvRmClocksOscFreq_Num] =
-{
- /* Ten milli second delay for BIAS_DEBOUNCE_A */
- 0x7EF4, // For NvRmClocksOscFreq_13_MHz,
- 0xBB80, // For NvRmClocksOscFreq_19_2_MHz
- 0x7530, // For NvRmClocksOscFreq_12_MHz
- 0xFDE8 // For NvRmClocksOscFreq_26_MHz
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Tracking Length Time: The tracking circuit of the bias cell consumes a
-// measurable portion of the USB idle power To curtail this power consumption
-// the bias pad has added a PD_TDK signal to power down the bias cell. It is
-// estimated that after 20microsec of bias cell operation the PD_TRK signal can
-// be turned high to sve power. This can be automated by programming a timing
-// interval as given in the below structure.
-static const NvU32 s_UsbBiasTrkLengthTime[NvRmClocksOscFreq_Num] =
-{
- /* 20 micro seconds delay after bias cell operation */
- 5, // For NvBootClocksOscFreq_13,
- 7, // For NvBootClocksOscFreq_19_2
- 5, // For NvBootClocksOscFreq_12
- 9 // For NvBootClocksOscFreq_26
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// The following arapb_misc_utmip.spec fields need to be programmed to ensure
-// correct operation of the UTMIP block:
-// Production settings :
-// 'HS_SYNC_START_DLY' : 9,
-// 'IDLE_WAIT' : 17,
-// 'ELASTIC_LIMIT' : 16,
-// All other fields can use the default reset values.
-// Setting the fields above, together with default values of the other fields,
-// results in programming the registers below as follows:
-// UTMIP_HSRX_CFG0 = 0x9168c000
-// UTMIP_HSRX_CFG1 = 0x13
-///////////////////////////////////////////////////////////////////////////////
-//UTMIP Idle Wait Delay
-static const NvU8 s_UtmipIdleWaitDelay = 17;
-//UTMIP Elastic limit
-static const NvU8 s_UtmipElasticLimit = 16;
-//UTMIP High Speed Sync Start Delay
-static const NvU8 s_UtmipHsSyncStartDelay = 9;
-
-// Reset USB host controller
-static NvBool s_IsUSBResetRequired = NV_TRUE;
static NvError
NvRmPrivTvDcControl( NvRmDeviceHandle hDevice, NvBool enable, NvU32 inst,
@@ -270,1788 +147,6 @@ NvRmPrivVideoInputControl( NvRmDeviceHandle hDevice, NvBool enable,
}
-static void
-NvRmPrivUsbfSetUlpiLinkTrimmers(
- NvRmDeviceHandle hDevice,
- NvU32 instance)
-{
- NvU32 RegVal = 0;
-
- // Bypass the Pin Mux on the ULPI outputs and set the trimmer values for inputs to 3
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0);
- RegVal = RegVal & ( ~( (0x1 << 13) | (0xf << 4) | (0xf << 28) ) );
- //bit 13 : data output pinmux bypass enable: set to 1
- //bit 4 : data input trimmer load enable (toggle)
- //bit [7:5] : data input trimmer value: set to 3
- //bit 28 : data input trimmer2 load enable (toggle)
- //bit [31:29] : data input trimmer2 value: set to 3
- RegVal = RegVal | ( (0x1 << 13) | (0x0 << 5) | (0x0 << 4) | (0x0 << 29) | (0x0 << 28) );
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0, RegVal);
-
- // wait 10 us
- NvOsWaitUS(10);
- // toggle bits 4 and 28 to latch the trimmer values
- RegVal = RegVal | ( (0x1 << 4) | (0x1 << 28) );
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0, RegVal);
- // wait 10 us
- NvOsWaitUS(10);
-}
-
-
-static void
-NvRmPrivUsbfSetUlpiNullTrimmers(
- NvRmDeviceHandle hDevice,
- NvU32 instance)
-{
- NvU32 RegVal = 0;
- // Configure 60M clock for USB2 - ULPI controller
-
- // Set up to use PLLU at 60 MHz and keep USB PHY PLL in reset
- // bit 27 : bypass 60 MHz Div5 for PLLU - set to 1
- // bit 9 : nullphy_pll_source - use USB_PHY_PLL output (set to 0) :
- // Workaround: set to 1 to use PLLU Output at 12 MHz
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_SPARE_CFG0_0);
- RegVal &= (~( 0x1 << 27) );
- RegVal |= ((0x1 << 9));
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0,
- RegVal);
-
- // Set the trimmers
- // bit 4 : data input trimmer load enable (toggle)
- // bit [7:5] : data input trimmer value - set to 3
- // bit 28 : data input trimmer2 load enable - (toggle)
- // bit [31:29] : data input trimmer2 value - set to 3
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0);
- RegVal = RegVal | ( (0x7 << 29) | (0x0 << 28) | (0x7 << 5) | (0x0 << 4) );
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0, RegVal);
-
- // wait 10 us
- NvOsWaitUS(10);
- // toggle bits 4 and 28 to latch the trimmer values
- RegVal = RegVal | ( (0x1 << 4) | (0x1 << 28) );
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0, RegVal);
- // wait 10 us
- NvOsWaitUS(10);
-}
-
-
-static void
-NvRmPrivUsbfUlpiClockControl(
- NvRmDeviceHandle hDevice,
- NvU32 instance,
- NvBool Enable)
-{
- NvU32 RegVal = 0;
-
- if (Enable)
- {
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_RST, DISABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_CE, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
- NvOsMutexLock(hDevice->CarMutex);
- // Bring Out of reset
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
-
- NvOsMutexUnlock(hDevice->CarMutex);
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_SPARE_CFG0_0);
- RegVal = RegVal & (0xf);
-
- RegVal = RegVal | ( (0x0 << 29) | (0x0 << 28) | (0x0 << 27) | (0 << 22) |
- (0x0 << 21) | (0x0 << 16) | (0x0 << 15) | (0x1 << 14) |
- (0x1 << 13) | (0x0 << 12) | (0x1 << 11) | (0x1 << 10) |
- (0x1 << 9) | (0x0 << 5) | (0x0 << 4) );
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_SPARE_CFG0_0, RegVal);
-
- // wait 10 us
- NvOsWaitUS(10);
- }
- else
- {
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_RST, ENABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_CE, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
- if (!(NV_DRF_VAL(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB_CE, RegVal)))
- {
- // Enable reset
- NvOsMutexLock(hDevice->CarMutex);
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
- NvOsMutexUnlock(hDevice->CarMutex);
- }
- }
-}
-
-static void
-NvRmPrivUsbfEnableVbusInterrupt(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
-
- //enable VBUS interrupt for cable detection when controller is Off
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_SENSORS_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_SENSORS,
- A_SESS_VLD_INT_EN, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_SENSORS_0, RegVal);
-}
-
-
-static void
-NvRmPrivUsbfDisableVbusInterrupt(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
-
- //disable the VBUS interrupt,
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_SENSORS_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_SENSORS,
- A_SESS_VLD_INT_EN, DISABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_SENSORS,
- A_SESS_VLD_CHG_DET, SET, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_SENSORS_0, RegVal);
-}
-
-
-static NvBool
-NvRmPrivUsbfIsCableConnected(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
- NvBool CableConnected = NV_FALSE;
-
- // Check for cable connection
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_SENSORS_0);
- if (NV_DRF_VAL(APB_MISC, PP_USB_PHY_VBUS_SENSORS, A_SESS_VLD_STS, RegVal))
- {
- CableConnected = NV_TRUE;
- }
- //disable the interrupt, if we detect the cable connection/dis connection
- NvRmPrivUsbfDisableVbusInterrupt(hDevice);
-
- if (!CableConnected)
- {
- NvRmPrivUsbfEnableVbusInterrupt(hDevice);
- }
-
- return CableConnected;
-}
-
-static NvError
-NvRmPrivUsbfWaitForPhyClock(
- NvRmDeviceHandle hDevice,
- NvBool Enable)
-{
- NvU32 TimeOut = 100000; // 100 milli seconds timeout before H/W gives up;
- NvU32 PhyClockValidStatus = APB_MISC_PP_MISC_USB_OTG_0_PCLKVLD_UNSET;
- NvU32 PhyClkValid = 0;
- NvU32 RegVal = 0;
- // If Enable is true, check for PHY Clock Vailid Set
- // Else check for PHY Clock Unset
- if (Enable)
- PhyClockValidStatus = APB_MISC_PP_MISC_USB_OTG_0_PCLKVLD_SET;
- // Wait for the phy clock to become valid or hardware timeout
- do {
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_PP_MISC_USB_OTG_0);
- PhyClkValid = NV_DRF_VAL(APB_MISC_PP, MISC_USB_OTG, PCLKVLD, RegVal);
- if (!TimeOut)
- {
- return NvError_Timeout;
- }
- NvOsWaitUS(1);
- TimeOut--;
- } while (PhyClkValid != PhyClockValidStatus);
-
- return NvSuccess;
-}
-
-static NvBool
-NvRmPrivUsbfIsChargerDetected(
- NvRmDeviceHandle hDevice, NvBool EnableDetection)
-{
- NvU32 RegVal = 0;
- NvBool ChargerConnected = NV_FALSE;
- #define TDP_SRC_ON_MS 100
-
- if (EnableDetection)
- {
- // Enable charger detection logic
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_OP_SRC_EN, 1, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_ON_SINK_EN, 1, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0, RegVal);
- // Source should be on for 100 ms as per USB charging spec
- NvOsSleepMS(TDP_SRC_ON_MS);
- }
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0);
- if (NV_DRF_VAL(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID, VDAT_DET_STS, RegVal))
- {
- //disable the interrupt, if we detect the charger
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID,
- VDAT_DET_INT_EN, DISABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID,
- VDAT_DET_CHG_DET, SET, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0, RegVal);
- ChargerConnected = NV_TRUE;
- // Disable charger detection logic
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_OP_SRC_EN, 0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_ON_SINK_EN, 0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0, RegVal);
-
- }
-
- return ChargerConnected;
-}
-
-static void
-NvRmPrivUsbfChargerDetection(
- NvRmDeviceHandle hDevice,
- NvBool Enable)
-{
- // These values (in milli second) are taken from the battery charging spec.
- #define TDP_SRC_ON_MS 100
- #define TDPSRC_CON_MS 40
- NvU32 RegVal = 0;
-
- if (Enable)
- {
- // Enable charger detection logic
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_OP_SRC_EN, 1, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_ON_SINK_EN, 1, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0, RegVal);
- // Source should be on for 100 ms as per USB charging spec
- NvOsSleepMS(TDP_SRC_ON_MS);
- // Check if charger is connected, enable interrupt to get the event
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0);
- if (NV_DRF_VAL(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID, VDAT_DET_STS, RegVal))
- {
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0,
- NV_DRF_DEF(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID,
- VDAT_DET_INT_EN, ENABLE));
- }
- else
- {
- // If charger is not connected disable the interrupt
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID,
- VDAT_DET_INT_EN, DISABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID,
- VDAT_DET_CHG_DET, SET, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0, RegVal);
- }
- }
- else
- {
- // Disable charger detection logic
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_OP_SRC_EN, 0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_ON_SINK_EN, 0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0, RegVal);
- // Delay of 40 ms before we pull the D+ as per battery charger spec.
- NvOsSleepMS(TDPSRC_CON_MS);
- }
-}
-
-
-static NvError
-NvRmPrivUsb3ConfigureUtmipPhy(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
- NvU32 TimeOut = 100000; // 100 milli seconds timeout before H/W gives up;
- NvU32 PhyClkValid = 0;
- NvRmFreqKHz OscFreqKz = 0;
- NvU32 FreqIndex;
-
- // Get the Oscillator Frequency
- OscFreqKz = NvRmPowerGetPrimaryFrequency(hDevice);
-
- // Get the Oscillator Frequency Index
- for (FreqIndex = 0; FreqIndex < NvRmClocksOscFreq_Num; FreqIndex++)
- {
- if (OscFreqKz == s_RmOscFrequecy[FreqIndex])
- {
- // Bail Out if frequecy matches with the supported frequency
- break;
- }
- }
- // If Index is equal to the maximum supported frequency count
- // There is a mismatch of the frequecy, so returning since the
- // frequency is not supported.
- if (FreqIndex >= NvRmClocksOscFreq_Num)
- {
- return NvError_NotSupported;
- }
-
-
- /**Hold UTMIP3 PHY in reset by writing UTMIP_RESET bit in USB3_IF_USB_SUSP_CTRL
- register to 1. **/
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB3_IF, USB_SUSP_CTRL, UTMIP_RESET, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0, RegVal);
-
-
- /*1. FORCE_PD_POWERDOWN, FORCE_PD2_POWERDOWN, FORCE_PDZI_POWERDOWN fields in
- UTMIP_XCVR_CFG0 register. **/
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_XCVR_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, XCVR_CFG0, UTMIP_FORCE_PD_POWERDOWN,
- 0x0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, XCVR_CFG0, UTMIP_FORCE_PD2_POWERDOWN,
- 0x0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, XCVR_CFG0, UTMIP_FORCE_PDZI_POWERDOWN,
- 0x0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_XCVR_CFG0_0, RegVal);
-
-
- // USB Power Up sequence
- // Power Up OTG and Bias circuitry
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_BIAS_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BIAS_CFG0,
- UTMIP_OTGPD, 0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BIAS_CFG0,
- UTMIP_BIASPD, 0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_BIAS_CFG0_0, RegVal);
-
- /**OTGOD and BIASPD fields in UTMIP_BIAS_CFG0 register. **/
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_BIAS_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, BIAS_CFG0, UTMIP_OTGPD,
- 0x0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, BIAS_CFG0, UTMIP_BIASPD,
- 0x0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_BIAS_CFG0_0, RegVal);
-
- /* FORCE_PDDISC_POWERDOWEN , FORCE_PDCHRP_POWERDOWN, FORCE_PDDR_POWERDOWN
- field in UTMIP_XCVR_CFG1 register. **/
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_XCVR_CFG1_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, XCVR_CFG1, UTMIP_FORCE_PDDISC_POWERDOWN,
- 0x0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, XCVR_CFG1, UTMIP_FORCE_PDCHRP_POWERDOWN,
- 0x0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, XCVR_CFG1, UTMIP_FORCE_PDDR_POWERDOWN,
- 0x0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_XCVR_CFG1_0, RegVal);
-
- /**Enable UTMIP3 interface by setting UTMIP_PHY_ENB in USB3_IF_USB_SUSP_CTRL
- register to 1. **/
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB3_IF, USB_SUSP_CTRL, UTMIP_PHY_ENB, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0, RegVal);
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_MISC_CFG1_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, MISC_CFG1,
- UTMIP_PLLU_STABLE_COUNT,
- s_UsbPllDelayParams[FreqIndex].StableCount, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, MISC_CFG1,
- UTMIP_PLL_ACTIVE_DLY_COUNT,
- s_UsbPllDelayParams[FreqIndex].ActiveDelayCount, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_MISC_CFG1_0, RegVal);
-
-
- // Set PLL enable delay count and Crystal frequency count
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_PLL_CFG1_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, PLL_CFG1,
- UTMIP_PLLU_ENABLE_DLY_COUNT,
- s_UsbPllDelayParams[FreqIndex].EnableDelayCount, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP,
- PLL_CFG1, UTMIP_XTAL_FREQ_COUNT,
- s_UsbPllDelayParams[FreqIndex].XtalFreqCount, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_PLL_CFG1_0, RegVal);
-
- // Program 1ms Debounce time for VBUS to become valid.
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_DEBOUNCE_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, DEBOUNCE_CFG0, UTMIP_BIAS_DEBOUNCE_A,
- s_UsbBiasDebounceATime[FreqIndex], RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_DEBOUNCE_CFG0_0, RegVal);
-
- /** pll_parameters_configured **/
-
- // Configure the UTMIP_HS_SYNC_START_DLY
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_HSRX_CFG1_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, HSRX_CFG1,
- UTMIP_HS_SYNC_START_DLY,
- s_UtmipHsSyncStartDelay, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_HSRX_CFG1_0, RegVal);
-
- /* Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT
- * Setting these fields, together with default values of the other
- * fields, results in programming the registers below as follows:
- * UTMIP_HSRX_CFG0 = 0x9168c000
- * UTMIP_HSRX_CFG1 = 0x13
- */
-
- // Set PLL enable delay count and Crystal frequency count
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_HSRX_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP, HSRX_CFG0,
- UTMIP_IDLE_WAIT,
- s_UtmipIdleWaitDelay, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB3_UTMIP,
- HSRX_CFG0, UTMIP_ELASTIC_LIMIT,
- s_UtmipElasticLimit, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_UTMIP_HSRX_CFG0_0, RegVal);
-
- /**Release reset to UTMIP3 by writing 0 to UTMIP_RESET field in
- USB3_IF_USB_SUSP_CTRL register. ***/
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB3_IF, USB_SUSP_CTRL, UTMIP_RESET, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0, RegVal);
-
-
- /**Wait until PHY clock comes up by checking for USB_PHY_CLK_VALID bit in
- USB3_IF_USB_SUSP_CTRL register **/
- do
- {
- //Wait for the phy clock to become valid
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0);
- PhyClkValid = NV_DRF_VAL(USB3_IF, USB_SUSP_CTRL, USB_PHY_CLK_VALID, RegVal);
-
- if (!TimeOut)
- {
- break;
- }
- NvOsWaitUS(1);
- TimeOut--;
- } while (!PhyClkValid);
-
- /* We can only do this once PHY clock is up. Disable ICUSB interface (it is enabled by default) */
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB2_CONTROLLER_1_USB2D_ICUSB_CTRL_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ICUSB_CTRL, IC_ENB1, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB2_CONTROLLER_1_USB2D_ICUSB_CTRL_0, RegVal);
-
- /**Program the USB3 controller to use UTMIP3 PHY by setting the PTS field in
- USB2_CONTROLLER_USB2D_PORTSC1 register to UTMIP (2'b00). **/
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB2_CONTROLLER_USB2D_PORTSC1_0);
-
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER, USB2D_PORTSC1, PTS, UTMI, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER, USB2D_PORTSC1, STS, PARALLEL_IF, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 2, USB2_CONTROLLER_USB2D_PORTSC1_0, RegVal);
-
- return NvSuccess;
-}
-
-
-static NvError
-NvRmPrivUsbfConfigureUtmipPhy(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
- NvRmFreqKHz OscFreqKz = 0;
- NvU32 FreqIndex;
-
- // Get the Oscillator Frequency
- OscFreqKz = NvRmPowerGetPrimaryFrequency(hDevice);
-
- // Get the Oscillator Frequency Index
- for (FreqIndex = 0; FreqIndex < NvRmClocksOscFreq_Num; FreqIndex++)
- {
- if (OscFreqKz == s_RmOscFrequecy[FreqIndex])
- {
- // Bail Out if frequecy matches with the supported frequency
- break;
- }
- }
- // If Index is equal to the maximum supported frequency count
- // There is a mismatch of the frequecy, so returning since the
- // frequency is not supported.
- if (FreqIndex >= NvRmClocksOscFreq_Num)
- {
- return NvError_NotSupported;
- }
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_TX_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_TX_CFG0, UTMIP_FS_PREAMBLE_J,
- 0x1, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_TX_CFG0_0, RegVal);
-
- // Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT
- // Setting these fields, together with default values of the other
- // fields, results in programming the registers below as follows:
- // UTMIP_HSRX_CFG0 = 0x9168c000
- // UTMIP_HSRX_CFG1 = 0x13
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_HSRX_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_HSRX_CFG0, UTMIP_IDLE_WAIT,
- s_UtmipIdleWaitDelay, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_HSRX_CFG0, UTMIP_ELASTIC_LIMIT,
- s_UtmipElasticLimit, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_HSRX_CFG0_0, RegVal);
-
- // Configure the UTMIP_HS_SYNC_START_DLY
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_HSRX_CFG1_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_HSRX_CFG1,
- UTMIP_HS_SYNC_START_DLY, s_UtmipHsSyncStartDelay, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_HSRX_CFG1_0, RegVal);
-
- // Program 1ms Debounce time for VBUS to become valid.
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_DEBOUNCE_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_DEBOUNCE_CFG0,
- UTMIP_BIAS_DEBOUNCE_A,s_UsbBiasDebounceATime[FreqIndex],
- RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_DEBOUNCE_CFG0_0, RegVal);
-
- // PLL Delay CONFIGURATION settings
- // The following parameters control the bring up of the plls:
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_MISC_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_MISC_CFG0,
- UTMIP_SUSPEND_EXIT_ON_EDGE, 0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_MISC_CFG0_0, RegVal);
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_MISC_CFG1_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_MISC_CFG1,
- UTMIP_PLLU_STABLE_COUNT,
- s_UsbPllDelayParams[FreqIndex].StableCount, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_MISC_CFG1,
- UTMIP_PLL_ACTIVE_DLY_COUNT,
- s_UsbPllDelayParams[FreqIndex].ActiveDelayCount, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_MISC_CFG1_0, RegVal);
-
- // Set PLL enable delay count and Crystal frequency count
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_PLL_CFG1_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_PLL_CFG1,
- UTMIP_PLLU_ENABLE_DLY_COUNT,
- s_UsbPllDelayParams[FreqIndex].EnableDelayCount, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC,
- UTMIP_PLL_CFG1, UTMIP_XTAL_FREQ_COUNT,
- s_UsbPllDelayParams[FreqIndex].XtalFreqCount, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_PLL_CFG1_0, RegVal);
-
- // On AP20 FPGA we do not have VBUS_WAKEUP signal for cable detection.
- // We use A_SESS_VLD that comes from the external UTMIP PHY
- if (NvRmPrivGetExecPlatform(hDevice) == ExecPlatform_Fpga)
- {
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_PP_USB_PHY_PARAM_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC, PP_USB_PHY_PARAM, VS_CTL, A_SESS_VLD, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_PP_USB_PHY_PARAM_0, RegVal);
- }
- return NvSuccess;
-}
-
-static void
-NvRmPrivUsbfPowerControl(
- NvRmDeviceHandle hDevice,
- NvU32 Instance,
- NvBool Enable)
-{
- NvU32 RegVal = 0;
- const NvOdmUsbProperty *pUsbProperty = NULL;
- NvU32 TimeOut = 100000; // 100 milli seconds timeout before H/W gives up;
- static NvU32 s_XcvrSetupValue = 0;
- static NvBool s_ReadFuseValue = NV_FALSE;
-
- if (Enable)
- {
- // USB Power Up sequence
- // Power Up OTG and Bias circuitry
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_BIAS_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BIAS_CFG0,
- UTMIP_OTGPD, 0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BIAS_CFG0,
- UTMIP_BIASPD, 0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_BIAS_CFG0_0, RegVal);
-
- if (!s_ReadFuseValue)
- {
-#if NV_USE_FUSE_CLOCK_ENABLE
- // Enable fuse clock
- NvRmPowerModuleClockControl(hDevice, NvRmModuleID_Fuse, 0, NV_TRUE);
-#endif
- // Enable fuse values to be visible before reading the fuses.
- RegVal = NV_REGR( hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_MISC_CLK_ENB_0 );
- RegVal = NV_FLD_SET_DRF_NUM( CLK_RST_CONTROLLER, MISC_CLK_ENB,
- CFG_ALL_VISIBLE, 1, RegVal );
- NV_REGW( hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_MISC_CLK_ENB_0, RegVal );
-
- // Read the spare register fuses and redundancy fuses for setting up USB
- // UTMIP_XCVR_SETUP value for proper EYE diagram.
- RegVal = NV_REGR( hDevice, NvRmModuleID_Fuse, 0, FUSE_FUSEDATA21_0);
-
- s_XcvrSetupValue = (NV_DRF_VAL(FUSE, FUSEDATA21,FUSEDATA_SPARE_BIT_10__PRI_ALIAS_0, RegVal) |
- NV_DRF_VAL(FUSE, FUSEDATA21, FUSEDATA_SPARE_BIT_13__PRI_ALIAS_0, RegVal)) << 0;
- s_XcvrSetupValue |= (NV_DRF_VAL(FUSE, FUSEDATA21, FUSEDATA_SPARE_BIT_11__PRI_ALIAS_0, RegVal) |
- NV_DRF_VAL(FUSE, FUSEDATA21, FUSEDATA_SPARE_BIT_14__PRI_ALIAS_0, RegVal)) << 1;
- s_XcvrSetupValue |= (NV_DRF_VAL(FUSE, FUSEDATA21, FUSEDATA_SPARE_BIT_12__PRI_ALIAS_0, RegVal) |
- NV_DRF_VAL(FUSE, FUSEDATA21, FUSEDATA_SPARE_BIT_15__PRI_ALIAS_0, RegVal)) << 2;
- // Only UTMIP_XCVR_SETUP[3-1] need to be programmed with the fuse vlaue
- // UTMIP_XCVR_SETUP[0] must be equal to 0
- s_XcvrSetupValue = s_XcvrSetupValue << 1;
-
- // Disable fuse values visibility, we already read the data
- RegVal = NV_REGR( hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_MISC_CLK_ENB_0 );
- RegVal = NV_FLD_SET_DRF_NUM( CLK_RST_CONTROLLER, MISC_CLK_ENB,
- CFG_ALL_VISIBLE, 0, RegVal );
- NV_REGW( hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_MISC_CLK_ENB_0, RegVal );
- s_ReadFuseValue = NV_TRUE;
-#if NV_USE_FUSE_CLOCK_ENABLE
- // Disable fuse clock
- NvRmPowerModuleClockControl(hDevice, NvRmModuleID_Fuse, 0, NV_FALSE);
-#endif
- }
-
- //NvOsDebugPrintf("s_XcvrSetupValue from fuse [0x%x] \n", s_XcvrSetupValue);
-
- // Turn on power in the tranciver
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_XCVR_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_XCVR_CFG0,
- UTMIP_FORCE_PDZI_POWERDOWN, 0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_XCVR_CFG0,
- UTMIP_FORCE_PD2_POWERDOWN, 0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_XCVR_CFG0,
- UTMIP_FORCE_PD_POWERDOWN, 0, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_XCVR_CFG0,
- UTMIP_XCVR_SETUP, s_XcvrSetupValue, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_XCVR_CFG0_0, RegVal);
-
- // Enable Batery charge enabling bit, set to '0' for enable
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_PD_CHRG, 0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0, RegVal);
-
- if (hDevice->ChipId.Id == 0x16)
- {
- if(s_IsUSBResetRequired)
- {
- NvOsMutexLock(hDevice->CarMutex);
- // Put the controller in reset
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
- NvOsMutexUnlock(hDevice->CarMutex);
- s_IsUSBResetRequired = NV_FALSE;
- }
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB_CE, ENABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB_RST, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
- }
- NvOsMutexLock(hDevice->CarMutex);
- // Bring Out of reset
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
- NvOsMutexUnlock(hDevice->CarMutex);
-
- }
- else
- {
- // USB Power down sequence
- // Power down OTG and Bias circuitry
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_BIAS_CFG0_0);
- // Query if Internal Phy is going to wake up the usb controller upon cable insertion.
- pUsbProperty = NvOdmQueryGetUsbProperty(NvOdmIoModule_Usb, Instance);
- if (!pUsbProperty->UseInternalPhyWakeup)
- {
- /// If not internal Phy then Use PMU interrupt for VBUS detection.
- /// Disable the OTG bias circuitry.
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BIAS_CFG0,
- UTMIP_OTGPD, 1, RegVal);
- }
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BIAS_CFG0,
- UTMIP_BIASPD, 1, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_BIAS_CFG0_0, RegVal);
-
- // Disable Batery charge enabling bit set to '1' for disable
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_BAT_CHRG_CFG0,
- UTMIP_PD_CHRG, 1, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_UTMIP_BAT_CHRG_CFG0_0, RegVal);
-
- // Turn off power in the tranciver
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_XCVR_CFG0_0);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_XCVR_CFG0,
- UTMIP_FORCE_PDZI_POWERDOWN, 1, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_XCVR_CFG0,
- UTMIP_FORCE_PD2_POWERDOWN, 1, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(APB_MISC, UTMIP_XCVR_CFG0,
- UTMIP_FORCE_PD_POWERDOWN, 1, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_UTMIP_XCVR_CFG0_0, RegVal);
-
- if (hDevice->ChipId.Id == 0x16)
- {
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB_RST, ENABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB_CE, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
- if (!(NV_DRF_VAL(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB2_CE, RegVal)))
- {
- // Enable reset
- NvOsMutexLock(hDevice->CarMutex);
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
- NvOsMutexUnlock(hDevice->CarMutex);
- }
- }
- else
- {
- // Enable reset
- NvOsMutexLock(hDevice->CarMutex);
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
- NvOsMutexUnlock(hDevice->CarMutex);
- }
- // Wait till B Session end
- do {
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_SENSORS_0,
- NV_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_SENSORS,
- A_SESS_VLD_CHG_DET, SET));
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_SENSORS_0);
- if (NV_DRF_VAL(APB_MISC_PP, USB_PHY_VBUS_SENSORS, B_SESS_END_STS, RegVal))
- {
- // break here once the B Session end apears.
- break;
- }
- NvOsWaitUS(1);
- TimeOut--;
- } while (TimeOut);
- }
-}
-
-#if 0
-static void
-NvRmPrivUsbfDisableChargerInterrupt(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
-
- // disable the charger Interrupt
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID, VDAT_DET_INT_EN, DISABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC, PP_USB_PHY_VBUS_WAKEUP_ID, VDAT_DET_CHG_DET, SET, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0, APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0, RegVal);
-}
-#endif
-
-static void NvRmUsbPrivConfigureUsbPhy(
- NvRmDeviceHandle hDevice,
- NvBool Enable)
- {
- NvU32 RegVal;
- NvU32 TimeOut = 1000;
- NvU32 PhyClkValid = 0;
- NvU32 UlpiRunBit = 1;
- //NvU32 ReadValue = 0;
- //NvU32 i;
-
- if(Enable)
- {
-
- if(s_IsUSBResetRequired)
- {
- // If USB1 is active by this time by KITL, do not do a car reset
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- if (!(NV_DRF_VAL(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB_CE, RegVal)))
- {
- NvOsMutexLock(hDevice->CarMutex);
- // Put the controller in reset
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
- NvOsMutexUnlock(hDevice->CarMutex);
- }
- s_IsUSBResetRequired = NV_FALSE;
- }
- // Bring controller out of reset
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_RST, DISABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_CE, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
- NvOsMutexLock(hDevice->CarMutex);
- // Bring Out of reset
- RegVal = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0);
- RegVal = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
- SWR_USBD_RST, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0,
- CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegVal);
- NvOsMutexUnlock(hDevice->CarMutex);
- // Wake-up ULPI PHY generate a postive pulse
- //set
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_IF_USB_SUSP_CTRL_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_IF, USB_SUSP_CTRL, USB_SUSP_CLR, SET,
- RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_IF_USB_SUSP_CTRL_0, RegVal);
-
- // wait 10 us
- NvOsWaitUS(100);
-
- // clear
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_IF_USB_SUSP_CTRL_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_IF, USB_SUSP_CTRL,
- USB_SUSP_CLR, UNSET, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_IF_USB_SUSP_CTRL_0, RegVal);
-
- // Set the MISC_USB2_CLK_OVR_ON bit and update PP_MISC_USB_CLK_RST_CTL register.
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB2_CLK_OVR_ON,
- ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
-
- // Setting the ULPI register IndicatorPassThru to 1
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x8, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x40, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- // Setting ULPI register UseExternalVbusIndicator to 1.
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0xB, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x80, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- }
- else
- {
- // Programming the ULPI register functuion control
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x4, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x4d, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
- // Resetting the ULPI register IndicatorPassThru
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x7, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x0, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- // Resetting ULPI register UseExternalVbusIndicator
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0xa, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x86, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- // making sure vbus comparator and id are off
- // USB Interrupt Rising
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x0d, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x00, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- // USB Interrupt Falling
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x10, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x00, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x19, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x00, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- // Disabling ID float Rise/Fall (Carkit Enable)
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x1D, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x00, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, WRITE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, 0x39, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_DATA_WR, 0x00, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-#if 0
- // STARTING register
- // taking the register dump for all ULPI 3317 register
- // staring from FCR
- //Read FCR
- for (i = 0x4;i < 0x14;i+=0x3)
- {
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, READ, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, i, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- ReadValue = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_DATA_RD, RegVal);
-
- NvOsDebugPrintf("USB ULPI 3317 reg @ 0x%x value %x",i,ReadValue);
- }
-
- // USB IL
- i = 0x14;
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, READ, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, i, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- ReadValue = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_DATA_RD, RegVal);
-
- NvOsDebugPrintf("USB ULPI 3317 (USB IL)i @ 0x%x value %x",i,ReadValue);
-
-
- // USB CARKit
- i = 0x19;
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, READ, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, i, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- ReadValue = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_DATA_RD, RegVal);
-
- NvOsDebugPrintf("USB ULPI 3317 (USB CARKit)i @ 0x%x value %x",i,ReadValue);
-
- // USB CARKit IE
- i = 0x1D;
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, READ, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, i, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- ReadValue = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_DATA_RD, RegVal);
-
- NvOsDebugPrintf("USB ULPI 3317 (USB CARKit IE)i @ 0x%x value %x",i,ReadValue);
-
- // USB CARKit IS
- i = 0x20;
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, READ, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, i, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- ReadValue = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_DATA_RD, RegVal);
-
- NvOsDebugPrintf("USB ULPI 3317 (USB CARKit IS)i @ 0x%x value %x",i,ReadValue);
-
- // USB CARKit IL
- i = 0x21;
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, READ, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, i, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- ReadValue = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_DATA_RD, RegVal);
-
- NvOsDebugPrintf("USB ULPI 3317 (USB CARKit IL)i @ 0x%x value %x ",i,ReadValue);
-
-
- // USB I/0
- i = 0x39;
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_WAKEUP, CLEAR, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RUN, SET, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_RD_WR, READ, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_PORT, SW_DEFAULT, RegVal);
- RegVal = NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT,
- ULPI_REG_ADDR, i, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0, RegVal);
-
- UlpiRunBit = 1;
- do
- {
- // check for run bit being cleared..
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_ULPI_VIEWPORT_0);
-
- UlpiRunBit = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_RUN, RegVal);
- } while (UlpiRunBit);
-
- ReadValue = NV_DRF_VAL(USB2_CONTROLLER_1, USB2D_ULPI_VIEWPORT, ULPI_DATA_RD, RegVal);
-
- NvOsDebugPrintf("USB ULPI 3317 (USB I/O)i @ 0x%x value %x",i,ReadValue);
-
- //// done with the register dump..
- // ENDING register dump programming..
-#endif
-
- // clear WKCN/WKDS/WKOC wake-on events that can cause the USB Controller to
- // immediately bring the ULPI PHY out of low power mode after setting PHCD
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_PORTSC1_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_USB2D, PORTSC1, WKCN,
- DISBLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_USB2D, PORTSC1, WKDS,
- DISBLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_USB2D, PORTSC1, WKOC,
- DISBLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_PORTSC1_0, RegVal);
-
- // before disabling clock.. put the phy to low power mode..
- // enter low power suspend mode
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_PORTSC1_0);
- RegVal = NV_FLD_SET_DRF_DEF(USB2_CONTROLLER_1, USB2D_PORTSC1, PHCD,
- ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Usb2Otg, 1,
- USB2_CONTROLLER_1_USB2D_PORTSC1_0, RegVal);
-
- // check for the phy in suspend..
- do
- {
- //Wait for the phy clock to stop or invalid
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 1 ,
- USB2_IF_USB_SUSP_CTRL_0);
-
- PhyClkValid = NV_DRF_VAL(USB2_IF, USB_SUSP_CTRL, USB_PHY_CLK_VALID,
- RegVal);
-
- if (!TimeOut)
- {
- break;
- }
- NvOsWaitUS(1);
- TimeOut--;
- } while (PhyClkValid);
-
-
- //NvRmAnalogUsbInputParam_ConfigureUsbPhy
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_CE, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
- s_IsUSBResetRequired = NV_TRUE;
- }
-}
-
-
-static void
-NvRmPrivUsbfEnableIdInterrupt(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
-
- //enable ID interrupt for A cable detection
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_WAKEUP_ID,
- ID_INT_EN, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0, RegVal);
-}
-
-static void
-NvRmPrivUsbfDisableIdInterrupt(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
-
- //disable the ID interrupt,
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_WAKEUP_ID,
- ID_INT_EN, DISABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_WAKEUP_ID,
- ID_CHG_DET, SET, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0, RegVal);
-}
-
-static NvBool
-NvRmPrivUsbfIsIdSetToLow(
- NvRmDeviceHandle hDevice)
-{
- NvU32 RegVal = 0;
- NvBool IdSetToLow = NV_FALSE;
-
- // Check for A cable connection
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0);
- if (!NV_DRF_VAL(APB_MISC_PP, USB_PHY_VBUS_WAKEUP_ID, ID_STS, RegVal))
- {
- IdSetToLow = NV_TRUE;
- }
-
- //Ack the ID interrupt,
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, USB_PHY_VBUS_WAKEUP_ID,
- ID_CHG_DET, SET, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_USB_PHY_VBUS_WAKEUP_ID_0, RegVal);
-
- return IdSetToLow;
-}
-static void NvRmUsbPrivEnableUsb2Clock( NvRmDeviceHandle hDevice )
-{
- NvU32 RegVal;
-
- // fist enable clocks to USB2
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_CE, ENABLE, RegVal);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB_CE, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
- // wait 10 us
- NvOsWaitUS(10);
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_RST, DISABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
- // wait 10 us
- NvOsWaitUS(10);
-
- RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0);
- RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, MISC_USB_CLK_RST_CTL,
- MISC_USB2_RST, ENABLE, RegVal);
- NV_REGW(hDevice, NvRmModuleID_Misc, 0,
- APB_MISC_PP_MISC_USB_CLK_RST_CTL_0, RegVal);
-
- // wait 10 us
- NvOsWaitUS(10);
-}
-
-static NvError
-NvRmPrivUsbfControl(
- NvRmDeviceHandle hDevice,
- NvBool Enable,
- NvU32 inst,
- void *Config,
- NvU32 ConfigLength)
-{
- NvError error = NvSuccess;
- NvRmAnalogUsbConfig *pUsbConf = NULL;
- static NvBool s_IsUsb0PhyConfigured = NV_FALSE;
- static NvBool s_IsUsb2PhyConfigured = NV_FALSE;
- NvU32 TimeOut = 100000; // 100 milli seconds timeout before H/W gives up;
- NvU32 PhyClkValid = 0;
- NvU32 RegVal = 0;
-
-
- const NvOdmUsbProperty *pUsbProperty = NULL;
-
- NV_ASSERT(Config);
-
- pUsbConf = (NvRmAnalogUsbConfig *)Config;
-
- switch (pUsbConf->InParam)
- {
- case NvRmAnalogUsbInputParam_CheckCableStatus:
- if (inst == 0)
- {
- pUsbConf->UsbCableDetected = NvRmPrivUsbfIsCableConnected(hDevice);
- // At this time we don't know charger is connected or not
- pUsbConf->UsbChargerDetected = NV_FALSE;
- }
- break;
- case NvRmAnalogUsbInputParam_WaitForPhyClock:
- if (inst == 0)
- {
- // Wait for PHY clock to settle
- error = NvRmPrivUsbfWaitForPhyClock(hDevice, Enable);
- }
- if( inst == 2)
- {
- // wait for USB3 phy clock is settle
- /**Wait until PHY clock comes up by checking for USB_PHY_CLK_VALID bit in
- USB3_IF_USB_SUSP_CTRL register **/
-
- do {
- //Wait for the phy clock to become valid
- RegVal = NV_REGR(hDevice, NvRmModuleID_Usb2Otg, 2, USB3_IF_USB_SUSP_CTRL_0);
-
- PhyClkValid = NV_DRF_VAL(USB3_IF, USB_SUSP_CTRL, USB_PHY_CLK_VALID, RegVal);
-
- if (!TimeOut)
- {
- break;
- }
- NvOsWaitUS(1);
- TimeOut--;
- } while (!PhyClkValid);
- }
-
- break;
- case NvRmAnalogUsbInputParam_CheckChargerStatus:
- if (inst == 0)
- {
- // Check whether the Dumb charger is detected
- pUsbConf->UsbChargerDetected = NvRmPrivUsbfIsChargerDetected(hDevice, Enable);
- }
- break;
- case NvRmAnalogUsbInputParam_ChargerDetection:
- if (inst == 0)
- {
- // Enable Charger detection logic
- NvRmPrivUsbfChargerDetection(hDevice, Enable);
- }
- break;
- case NvRmAnalogUsbInputParam_ConfigureUsbPhy:
- if (inst == 1) // for ULPI
- {
- NvRmUsbPrivConfigureUsbPhy(hDevice, Enable);
- }
- else
- {
- // UTMIP settings
- if (Enable)
- {
- if ((inst == 0) && (s_IsUsb0PhyConfigured == NV_TRUE))
- {
- // If Usb0 Phy is already configure; nothing to do
- return NvSuccess;
- }
- else if((inst == 2) && (s_IsUsb2PhyConfigured == NV_TRUE))
- {
- // If Usb2 Phy is already configure; nothing to do
- return NvSuccess;
- }
- /** For AP20 instance 2 is utmip and we need to select this
- interface **/
- pUsbProperty = NvOdmQueryGetUsbProperty(NvOdmIoModule_Usb, inst);
- if ((inst == 2) && (pUsbProperty->UsbInterfaceType ==
- NvOdmUsbInterfaceType_Utmi))
- {
- // Select UTMIP3 incase of usb3 and UTMIP
- error = NvRmPrivUsb3ConfigureUtmipPhy(hDevice);
- if (error != NvSuccess)
- {
- return error;
- }
- s_IsUsb2PhyConfigured = NV_TRUE;
- }
- else
- {
- // Configure USB1 UTMIP Phy
- error = NvRmPrivUsbfConfigureUtmipPhy(hDevice);
- if (error != NvSuccess)
- {
- return error;
- }
- // Enable USB circuitry
- NvRmPrivUsbfPowerControl(hDevice, inst, Enable);
- s_IsUsb0PhyConfigured = NV_TRUE;
- }
- }
- else
- {
- if (inst == 0) // for UTMIP1
- {
- // Disable power to the USB phy
- NvRmPrivUsbfPowerControl(hDevice, inst, Enable);
- // Enable VBUS interrupt when USB controller is OFF
- NvRmPrivUsbfEnableVbusInterrupt(hDevice);
- }
- if (inst == 0)
- s_IsUsb0PhyConfigured = NV_FALSE;
- else if (inst == 2)
- s_IsUsb2PhyConfigured = NV_FALSE;
- }
- }
- break;
- case NvRmAnalogUsbInputParam_SetUlpiNullTrimmers:
- if (inst == 1)
- {
- NvRmPrivUsbfSetUlpiNullTrimmers(hDevice, inst);
- }
- break;
- case NvRmAnalogUsbInputParam_SetUlpiLinkTrimmers:
- if (inst == 1)
- {
- NvRmPrivUsbfSetUlpiLinkTrimmers(hDevice, inst);
- }
- break;
- case NvRmAnalogUsbInputParam_VbusInterrupt:
- if (inst == 0)
- {
- if (Enable)
- {
- // enable VBus Interrupt
- NvRmPrivUsbfEnableVbusInterrupt(hDevice);
- }
- else
- {
- // disable VBUS interrupt
- NvRmPrivUsbfDisableVbusInterrupt(hDevice);
- }
- }
- break;
- case NvRmAnalogUsbInputParam_ConfigureUlpiNullClock:
- break;
- case NvRmAnalogUsbInputParam_SetNullUlpiPinMux:
- if(inst == 1)
- {
- NvRmSetModuleTristate(hDevice,
- NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, inst),
- NV_FALSE);
-
- // enb_usb2_clocks
- NvRmUsbPrivEnableUsb2Clock(hDevice);
- NvRmPrivUsbfUlpiClockControl(hDevice, inst, Enable);
- }
- break;
- case NvRmAnalogUsbInputParam_IdInterrupt:
- if (inst == 0)
- {
- if (Enable)
- {
- // enable ID Interrupt
- NvRmPrivUsbfEnableIdInterrupt(hDevice);
- }
- else
- {
- // disable ID interrupt
- NvRmPrivUsbfDisableIdInterrupt(hDevice);
- }
- }
- break;
- case NvRmAnalogUsbInputParam_CheckIdStatus:
- if (inst == 0)
- {
- pUsbConf->UsbIdDetected = NvRmPrivUsbfIsIdSetToLow(hDevice);
- }
- break;
- default:
- NV_ASSERT(NV_FALSE);
- break;
- }
-
- return error;
-}
-
-
NvError
NvRmAnalogInterfaceControl(
NvRmDeviceHandle hDevice,
@@ -2082,10 +177,6 @@ NvRmAnalogInterfaceControl(
break;
case NvRmAnalogInterface_Uart:
break;
- case NvRmAnalogInterface_Usb:
- err = NvRmPrivUsbfControl( hDevice, Enable, inst, Config,
- ConfigLength );
- break;
case NvRmAnalogInterface_Sdio:
break;
case NvRmAnalogInterface_Tv:
diff --git a/arch/arm/mach-tegra/pci-enum.c b/arch/arm/mach-tegra/pci-enum.c
new file mode 100644
index 000000000000..1dab1de0a86d
--- /dev/null
+++ b/arch/arm/mach-tegra/pci-enum.c
@@ -0,0 +1,637 @@
+/*
+ * arch/arm/mach-tegra/pci-enum.c
+ *
+ * Code to enumerate the PCI devices on the PCI bus. Unlike x86 we cannot
+ * rely on BIOS to allocate the PCIe resources for the devices.
+ *
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <mach/pci.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+
+struct pci_tegra_device
+{
+ /* Bus number */
+ u8 bus;
+
+ /* Device + function encoding.
+ * Use macros PCI_DEVFN/PCI_SLOT/PCI_FUNC to encode and decode
+ * */
+ u32 devfn;
+
+ /* Secondary bus nummber. Non-zero only for bridge devices. */
+ u32 sec_bus;
+
+ /* Subordinate bus number. Non-zero only for the bridge devices. */
+ u32 sub_bus;
+
+ /* Device ID/vendor ID of the PCI device/bridge.
+ * Upper 16 bits are device ID and lower 16 bits are vendor ID.
+ */
+ u32 id;
+
+ /* For a bridge device only 3 bars are used.
+ */
+#define PCI_BRIDGE_IO_RES 0
+#define PCI_BRIDGE_MEM_RES 1
+#define PCI_BRIDGE_PREFETCH_RES 2
+
+ /* Here we are limiting to the standard PCI resources */
+ struct resource res[PCI_STD_RESOURCE_END + 1];
+
+ bool disabled;
+
+ struct pci_tegra_device *parent;
+ struct pci_tegra_device *next;
+ struct pci_tegra_device *prev;
+ struct pci_tegra_device *child;
+ bool root_port;
+};
+
+#define TEGRA_MAX_PCI_DEVICES 64
+static struct pci_tegra_device pci_devices[TEGRA_MAX_PCI_DEVICES];
+static int max_devices;
+static struct pci_tegra_device *pci_root;
+
+static u32 pci_tegra_io_base;
+static u32 pci_tegra_mem_base;
+static u32 pci_tegra_prefetech_base;
+
+static u32 pci_tegra_io_limt;
+static u32 pci_tegra_mem_limit;
+static u32 pci_tegra_prefetech_limit;
+
+static void pci_tegra_print_device_tree(struct pci_tegra_device *dev);
+static void pcie_scanbus(struct pci_tegra_device *dev_parent);
+static void pci_tegra_allocate_resources(struct pci_tegra_device *dev);
+
+
+static struct pci_tegra_device *alloc_pci_tegra_device(void)
+{
+ static u32 index = 0;
+ struct pci_tegra_device *dev;
+
+ if (index == 0)
+ memset(pci_devices, 0, sizeof(pci_devices));
+
+ dev = &pci_devices[index];
+ index++;
+ max_devices = index;
+ return dev;
+}
+
+static inline void pci_conf_write8(u8 bus, u32 devfn, u32 where , u8 val)
+{
+ u32 addr;
+ u32 temp;
+
+ addr = (u32)pci_tegra_config_addr(bus, devfn, where);
+ pr_err("Issuing pci_conf_write8 at addr 0x%x with data 0x%x\n",
+ addr, val);
+
+ temp = readl((addr & ~0x3));
+ temp &= ~(0xff << ((addr & 0x3) * 8));
+ temp |= (u32)val << ((addr & 0x3) * 8);
+ writel(temp, (addr & ~0x3));
+}
+
+static inline void pci_conf_write16(u8 bus, u32 devfn, u32 where, u16 val)
+{
+ u32 addr;
+ u32 temp;
+
+ BUG_ON(where & 0x1);
+
+ addr = (u32)pci_tegra_config_addr(bus, devfn, where);
+ pr_err("Issuing pci_conf_write16 at addr 0x%x with data 0x%x\n",
+ addr, val);
+
+ temp = readl((addr & ~0x3));
+ temp &= ~(0xffff << ((addr& 0x3) * 8));
+ temp |= (u32)val << ((addr & 0x3) * 8);
+ writel(temp, (addr & ~0x3));
+}
+
+static inline void pci_conf_write32(u8 bus, u32 devfn, u32 where, u32 val)
+{
+ u32 addr;
+
+ BUG_ON(where & 0x3);
+
+ addr = (u32)pci_tegra_config_addr(bus, devfn, where);
+ pr_err("Issuing pci_conf_write32 at addr 0x%x with data 0x%x\n",
+ addr, val);
+ writel(val, addr);
+}
+
+static inline u8 pci_conf_read8(u8 bus, u32 devfn, u32 where)
+{
+ u32 temp;
+ u32 addr;
+
+ addr = (u32)pci_tegra_config_addr(bus, devfn, where);
+ pr_err("Issuing pci_conf_read8 at 0x%x\n", addr);
+ temp = readl(addr & ~0x3);
+ temp >>= 8 * (addr & 3);
+ temp &= 0xff;
+ pr_err("pci_conf_read8 at 0x%x = %d\n", addr, temp);
+
+ return (u8)temp;
+}
+
+static u16 pci_conf_read16(u8 bus, u32 devfn, u32 where)
+{
+ u32 temp;
+ u32 addr;
+
+ BUG_ON(where & 0x1);
+
+ addr = (u32)pci_tegra_config_addr(bus, devfn, where);
+ pr_err("Issuing pci_conf_read16 at 0x%x\n", addr);
+ temp = readl(addr & ~0x3);
+ temp >>= 8 * (addr & 3);
+ temp &= 0xffff;
+ pr_err("pci_conf_read16 at 0x%x = %d\n", addr, temp);
+
+ return (u16)temp;
+}
+
+static u32 pci_conf_read32(u8 bus, u32 devfn, u32 where)
+{
+ u32 temp;
+
+ BUG_ON(where & 0x3);
+
+ pr_err("Issuing pci_conf_read32 at 0x%x\n",
+ (u32)(pci_tegra_config_addr(bus, devfn, where)));
+
+ temp = readl(pci_tegra_config_addr(bus, devfn, where));
+
+ pr_err("pci_conf_read32 at 0x%x = %d\n", where, temp);
+ return temp;
+}
+
+static void pcie_scanbus(struct pci_tegra_device *dev_parent)
+{
+ u8 subordinate_bus;
+ u8 hdr_type;
+ u8 next_bus_number;
+ u32 device = 0;
+ u32 id;
+ struct pci_tegra_device *dev;
+ u32 retry_count;
+
+ next_bus_number = dev_parent->sec_bus;
+
+next_device:
+ retry_count = 6;
+ if (device == 0x20) {
+ /* Termination condition: Max number of devices reached.
+ * PCIe bus segment can only have 32 devices.
+ * */
+ dev_parent->sub_bus = next_bus_number;
+ if (!dev_parent->root_port) {
+ /* Change the subordinate bus-number to the actual
+ * value of all buses on the hierarcy.
+ *
+ * Do this execpt for the root port.
+ */
+ pci_conf_write8(dev_parent->bus, dev_parent->devfn,
+ PCI_SUBORDINATE_BUS, next_bus_number);
+ }
+ return;
+ }
+
+ if (dev_parent->root_port && device != 0) {
+ /* Sepcial Exit condition for root port.
+ * Root port only connect to one bridge or device.
+ */
+ dev_parent->sub_bus = dev_parent->sec_bus;
+ return;
+ }
+
+ while (--retry_count) {
+ id = pci_conf_read32(dev_parent->sec_bus,
+ PCI_DEVFN(device, 0), 0);
+ if (id != 0xFFFFFFFF)
+ {
+ /* Found a valid device, break. Otherwise, retry a couple of
+ * times. It is possible that the bridges can take some time
+ * to settle and it will take couple of transcations to find
+ * the devcies behind the bridge.
+ * */
+ /* FIXME: What should be the delay? */
+ msleep(100);
+ break;
+ }
+ }
+ if (id == 0xFFFFFFFF) {
+ /* Invalid device. Skip that one and look for next device */
+ device++;
+ goto next_device;
+ }
+
+ dev = alloc_pci_tegra_device();
+
+ /* Fill the device information */
+ dev->parent = dev_parent;
+ dev->id = id;
+ dev->bus = dev_parent->sec_bus;
+ dev->devfn = PCI_DEVFN(device, 0);
+ if (dev_parent->child == NULL) {
+ dev_parent->child = dev;
+ dev->prev = NULL;
+ } else {
+ /* Add dev to the list of devices on the same bus */
+ struct pci_tegra_device *temp;
+
+ temp = dev_parent->child;
+ BUG_ON(temp != NULL);
+ while (temp->next != NULL)
+ temp = temp->next;
+ temp->next = dev;
+ dev->prev = temp;
+ }
+
+ hdr_type = pci_conf_read8(dev->bus, dev->devfn, PCI_HEADER_TYPE);
+ if ((hdr_type & 0x7f) == 0x1) {
+ /* Bridge device */
+
+ /* Temporarily assign 0xff for the subordinate bus number as
+ * we don't * know how many devices are preset behind this
+ * bridge.
+ * */
+ subordinate_bus = 0xff;
+ dev->sec_bus = next_bus_number + 1;
+
+ pci_conf_write8(dev->bus, dev->devfn, PCI_PRIMARY_BUS,
+ dev_parent->sec_bus);
+ pci_conf_write8(dev->bus, dev->devfn, PCI_SECONDARY_BUS,
+ dev->sec_bus);
+ pci_conf_write8(dev->bus, dev->devfn, PCI_SUBORDINATE_BUS,
+ subordinate_bus);
+
+ /* Scan all the buses behind this bridge */
+ pcie_scanbus(dev);
+
+ next_bus_number = dev->sub_bus;
+ } else if ((hdr_type & 0x7f) == 0x0) {
+
+ /* PCI endpoint - Can be single function or multie function */
+ pr_info("PCI endpoint (0x%x) is on bus = %d, device = %d\n",
+ id, dev_parent->sec_bus, device);
+
+ } else if ((hdr_type & 0x7f) == 0x2) {
+ /* PC card device - Not handled */
+ BUG();
+ } else {
+ BUG();
+ }
+ device++;
+ goto next_device;
+}
+
+static void pci_tegra_enumerate_root_port(int rp)
+{
+ struct pci_tegra_device *root;
+ u32 reg;
+
+ root = alloc_pci_tegra_device();
+
+ if (pci_root) {
+ pci_root->next = root;
+ root->bus = pci_root->sub_bus + 1;
+ } else {
+ pci_root = root;
+ root->bus = 0;
+ }
+
+ root->sec_bus = root->bus + 1;
+ root->root_port = true;
+ /* Set the Inital value to the max bus number */
+ root->sub_bus = 0xff;
+ root->id = pci_tegra_rp_readl(0, rp);
+
+ pci_tegra_rp_writeb(root->bus, PCI_PRIMARY_BUS, rp);
+ pci_tegra_rp_writeb(root->sec_bus, PCI_SECONDARY_BUS, rp);
+ pci_tegra_rp_writeb(root->sub_bus, PCI_SUBORDINATE_BUS, rp);
+
+ /* Just assigns the bus numbers and sets up the SW hirerarchy */
+ pcie_scanbus(root);
+
+ /* Write the udpated root port subordinate bus number */
+ pci_tegra_rp_writeb(root->sub_bus, PCI_SUBORDINATE_BUS, rp);
+
+ pci_tegra_allocate_resources(root);
+
+ /* IO base and limits */
+ reg = root->res[PCI_BRIDGE_IO_RES].start;
+ reg = ALIGN(reg, 0x1000);
+ pci_tegra_rp_writeb((((reg & 0xf000) >> 8) | PCI_IO_RANGE_TYPE_32),
+ PCI_IO_BASE, rp);
+ pci_tegra_rp_writew(reg>>16, PCI_IO_BASE_UPPER16, rp);
+
+ reg = root->res[PCI_BRIDGE_IO_RES].end;
+ reg = ALIGN(reg, 0x1000);
+ pci_tegra_rp_writeb((((reg & 0xf000) >> 8) | PCI_IO_RANGE_TYPE_32),
+ PCI_IO_LIMIT, rp);
+ pci_tegra_rp_writew(reg>>16, PCI_IO_LIMIT_UPPER16, rp);
+
+ /* Memory base and limits */
+ reg = root->res[PCI_BRIDGE_MEM_RES].start;
+ reg = ALIGN(reg, 0x100000);
+ pci_tegra_rp_writew(reg >> 16, PCI_MEMORY_BASE, rp);
+ reg = root->res[PCI_BRIDGE_MEM_RES].end;
+ reg = ALIGN(reg, 0x100000);
+ pci_tegra_rp_writew(reg >> 16, PCI_MEMORY_LIMIT, rp);
+
+ /* Prefetch base and limit - 32 bit addressing */
+ reg = root->res[PCI_BRIDGE_PREFETCH_RES].start;
+ reg = ALIGN(reg, 0x100000);
+ pci_tegra_rp_writew(reg >> 16, PCI_PREF_MEMORY_BASE, rp);
+ pci_tegra_rp_writel(0, PCI_PREF_BASE_UPPER32, rp);
+ reg = root->res[PCI_BRIDGE_PREFETCH_RES].end;
+ reg = ALIGN(reg, 0x100000);
+ pci_tegra_rp_writew(reg >> 16, PCI_PREF_MEMORY_LIMIT, rp);
+ pci_tegra_rp_writel(0, PCI_PREF_LIMIT_UPPER32, rp);
+
+ reg = 0;
+ reg |= PCI_COMMAND_IO;
+ reg |= PCI_COMMAND_MEMORY;
+ reg |= PCI_COMMAND_MASTER;
+ reg |= PCI_COMMAND_SERR;
+ pci_tegra_rp_writew(reg, PCI_COMMAND, rp);
+}
+
+static void pci_tegra_setup_pci_bridge(struct pci_tegra_device *dev)
+{
+ u32 reg;
+
+ dev->res[PCI_BRIDGE_IO_RES].end = pci_tegra_io_base;
+ dev->res[PCI_BRIDGE_MEM_RES].end = pci_tegra_mem_base;
+ dev->res[PCI_BRIDGE_PREFETCH_RES].end =
+ pci_tegra_prefetech_base;
+
+ /* Only set here for the non-root port devices */
+ if (dev->root_port)
+ return;
+
+ /* IO base and limits */
+ reg = dev->res[PCI_BRIDGE_IO_RES].start;
+ reg = ALIGN(reg, 0x1000);
+ pci_conf_write8(dev->bus, dev->devfn, PCI_IO_BASE,
+ (((reg & 0xf000) >> 8) | PCI_IO_RANGE_TYPE_32));
+ pci_conf_write16(dev->bus, dev->devfn, PCI_IO_BASE_UPPER16, reg>>16);
+
+ reg = dev->res[PCI_BRIDGE_IO_RES].end;
+ reg = ALIGN(reg, 0x1000);
+ pci_conf_write8(dev->bus, dev->devfn, PCI_IO_LIMIT,
+ (((reg & 0xf000) >> 8) | PCI_IO_RANGE_TYPE_32));
+ pci_conf_write16(dev->bus, dev->devfn, PCI_IO_LIMIT_UPPER16, reg>>16);
+
+ /* Memory base and limits */
+ reg = dev->res[PCI_BRIDGE_MEM_RES].start;
+ reg = ALIGN(reg, 0x100000);
+ pci_conf_write16(dev->bus, dev->devfn, PCI_MEMORY_BASE, reg >> 16);
+
+ reg = dev->res[PCI_BRIDGE_MEM_RES].end;
+ reg = ALIGN(reg, 0x100000);
+ pci_conf_write16(dev->bus, dev->devfn, PCI_MEMORY_LIMIT, reg >> 16);
+
+ /* Prefetch base and limit - 32 bit addressing */
+ reg = dev->res[PCI_BRIDGE_PREFETCH_RES].start;
+ reg = ALIGN(reg, 0x100000);
+ pci_conf_write16(dev->bus, dev->devfn, PCI_PREF_MEMORY_BASE,
+ reg >> 16);
+ pci_conf_write16(dev->bus, dev->devfn, PCI_PREF_BASE_UPPER32, 0);
+
+ reg = dev->res[PCI_BRIDGE_PREFETCH_RES].end;
+ reg = ALIGN(reg, 0x100000);
+ pci_conf_write16(dev->bus, dev->devfn, PCI_PREF_MEMORY_LIMIT,
+ reg >> 16);
+ pci_conf_write16(dev->bus, dev->devfn, PCI_PREF_LIMIT_UPPER32, 0);
+
+ reg = 0;
+ reg |= PCI_COMMAND_IO;
+ reg |= PCI_COMMAND_MEMORY;
+ reg |= PCI_COMMAND_MASTER;
+ reg |= PCI_COMMAND_SERR;
+ pci_conf_write16(dev->bus, dev->devfn, PCI_COMMAND, reg);
+
+ /* FIXME how to handle interrutps */
+ pci_conf_write8(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 0x82);
+ pci_conf_write8(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 0xa);
+}
+
+static void pci_tegra_setup_pci_device(struct pci_tegra_device *dev)
+{
+ u8 flags;
+ u32 bar_index;
+ u32 reg;
+ u32 addr;
+
+ for (bar_index = 0x0; bar_index <= PCI_STD_RESOURCE_END;
+ bar_index ++) {
+ u32 size;
+ pci_conf_write32(dev->bus, dev->devfn, bar_index * 4
+ + PCI_BASE_ADDRESS_0, 0xFFFFFFFFUL);
+
+ size = pci_conf_read32(dev->bus, dev->devfn, bar_index * 4
+ + PCI_BASE_ADDRESS_0);
+
+ if (size == 0xFFFFFFFFUL) continue;
+ if (size == 0) continue; /* A broken device? */
+ flags = (size & 0x000f);
+
+ /* Size align the addr and write that BAR offset */
+ if (flags & 0x1) {
+ size &= ~0xF; /* Ignore the last 4 bits */
+ /* some devices hardwire the high bits of IO bars to 0
+ * So, ignore those bits.
+ */
+ size |= 0xffff0000;
+ size = ~size + 1; /* Do the 1's complement */
+
+ addr = ALIGN(pci_tegra_io_base, size);
+
+ if (addr + size > pci_tegra_io_limt) {
+ pr_err("pci_tegra: "
+ "Cannot asign IO res\n");
+ continue;
+ }
+ dev->res[bar_index].flags = IORESOURCE_IO;
+ dev->res[bar_index].start = addr;
+ dev->res[bar_index].end = addr + size -1;
+
+ pci_tegra_io_base = addr + size;
+ } else {
+ size &= ~0xF; /* Ignore the last 4 bits */
+ size = ~size + 1; /* Do the 1's complement */
+
+ if (flags & 0x08) {
+ addr = ALIGN(pci_tegra_mem_base, size);
+
+ if (addr + size > pci_tegra_mem_limit) {
+ pr_err("pci_tegra: "
+ "Cannot asign mem res\n");
+ continue;
+ }
+
+ dev->res[bar_index].flags = IORESOURCE_MEM;
+ dev->res[bar_index].start = 0;
+ dev->res[bar_index].end =
+ dev->res[bar_index].start + size - 1;
+
+ pci_tegra_mem_base = addr + size;
+ } else {
+ addr = ALIGN(pci_tegra_prefetech_base, size);
+
+ if (addr + size > pci_tegra_prefetech_limit) {
+ pr_err("pci_tegra: "
+ "Cannot asign prefetch res\n");
+ continue;
+ }
+
+ dev->res[bar_index].flags =
+ IORESOURCE_MEM | IORESOURCE_PREFETCH;
+ dev->res[bar_index].start = addr;
+ dev->res[bar_index].end = addr + size - 1;
+
+ pci_tegra_prefetech_base = addr + size;
+ }
+ }
+ pci_conf_write32(dev->bus, dev->devfn, bar_index * 4
+ + PCI_BASE_ADDRESS_0, dev->res[bar_index].start);
+
+ /* Handle 64 bit addresses by forcing to 32 bit addresses */
+ if ((flags == 0x0c) || (flags==0x04)) {
+ bar_index++;
+ BUG_ON(bar_index < 6);
+ pci_conf_write32(dev->bus, dev->devfn, bar_index * 4
+ + PCI_BASE_ADDRESS_0, 0);
+ }
+ }
+
+ reg = 0;
+ reg |= PCI_COMMAND_IO;
+ reg |= PCI_COMMAND_MEMORY;
+ reg |= PCI_COMMAND_MASTER;
+ reg |= PCI_COMMAND_SERR;
+ pci_conf_write16(dev->bus, dev->devfn, PCI_COMMAND, reg);
+
+ /* FIXME how to handle interrutps */
+
+}
+
+static void pci_tegra_print_device_tree(struct pci_tegra_device *dev)
+{
+ u32 i;
+
+ if (!dev)
+ return;
+
+ if (dev->sub_bus)
+ pr_err("PCIe bridge/Root port\n");
+ else
+ pr_err("PCIe device\n");
+
+ pr_err(" Vendor/Device = 0x%x bus = %d sec bus %d sub bus %d\n",
+ dev->id, dev->bus, dev->sec_bus, dev->sub_bus);
+ if (dev->disabled) {
+ pr_err(" Slot disabled\n");
+ } else {
+ for (i=0; i<= PCI_STD_RESOURCE_END; i++) {
+ /* Skip printing the empty ones */
+ if (!dev->res[i].start)
+ continue;
+ pr_err(" bar(%d) \n", i);
+ pr_err(" start = 0x%x\n", dev->res[i].start);
+ pr_err(" end = 0x%x\n", dev->res[i].end);
+ pr_err(" flags = 0x%lx\n", dev->res[i].flags);
+ }
+ }
+
+ if (dev->child != NULL)
+ pci_tegra_print_device_tree(dev->child);
+
+ if (dev->next != NULL)
+ pci_tegra_print_device_tree(dev->next);
+}
+
+static void pci_tegra_allocate_resources(struct pci_tegra_device *dev)
+{
+ /* Employing a depth first search for resource allocation. */
+ if (!dev)
+ return;
+
+ if (dev->sub_bus) {
+
+ dev->res[PCI_BRIDGE_IO_RES].flags = IORESOURCE_IO;
+ dev->res[PCI_BRIDGE_IO_RES].start = pci_tegra_io_base;
+
+ dev->res[PCI_BRIDGE_PREFETCH_RES].flags =
+ IORESOURCE_MEM | IORESOURCE_PREFETCH;
+ dev->res[PCI_BRIDGE_PREFETCH_RES].start =
+ pci_tegra_prefetech_base;
+
+ dev->res[PCI_BRIDGE_MEM_RES].flags = IORESOURCE_MEM;
+ dev->res[PCI_BRIDGE_MEM_RES].start = pci_tegra_mem_base;
+ }
+
+ if (dev->child)
+ pci_tegra_allocate_resources(dev->child);
+ if (dev->next)
+ pci_tegra_allocate_resources(dev->next);
+
+ if (dev->sub_bus)
+ pci_tegra_setup_pci_bridge(dev);
+ else
+ pci_tegra_setup_pci_device(dev);
+}
+
+void pci_tegra_enumerate(void)
+{
+ u32 reg;
+
+ /* Disable all execptions */
+ pci_tegra_afi_writel(0, AFI_FPCI_ERROR_MASKS_0);
+
+ /* Set the base and limits of the resources */
+ pci_tegra_io_base = TEGRA_PCIE_BASE + PCIE_DOWNSTREAM_IO_OFFSET;
+ pci_tegra_io_limt = pci_tegra_io_base + PCIE_DOWNSTREAM_IO_SIZE;
+
+ pci_tegra_mem_base = FPCI_NON_PREFETCH_MEMORY_OFFSET;
+ pci_tegra_mem_limit = FPCI_NON_PREFETCH_MEMORY_OFFSET
+ + PCIE_NON_PREFETCH_MEMORY_SIZE;
+
+ pci_tegra_prefetech_base = FPCI_PREFETCH_MEMORY_OFFSET;
+ pci_tegra_prefetech_limit = FPCI_PREFETCH_MEMORY_OFFSET
+ + PCIE_PREFETCH_MEMORY_SIZE;
+
+ /* Enumerate only if the Link is UP. */
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_VEND_XP, 0);
+ if (NVPCIE_DRF_VAL(RP, VEND_XP, DL_UP, reg) == 1)
+ pci_tegra_enumerate_root_port(0);
+
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_VEND_XP, 1);
+ if (NVPCIE_DRF_VAL(RP, VEND_XP, DL_UP, reg) == 1)
+ pci_tegra_enumerate_root_port(1);
+
+ pci_tegra_print_device_tree(pci_root);
+}
diff --git a/arch/arm/mach-tegra/pci.c b/arch/arm/mach-tegra/pci.c
index dcfdb7981464..2ecba6015229 100644
--- a/arch/arm/mach-tegra/pci.c
+++ b/arch/arm/mach-tegra/pci.c
@@ -20,11 +20,29 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#define DEBUG
+#define VERBOSE_DEBUG
+
+
#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/mach/pci.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <mach/pci.h>
+#include <mach/nvrm_linux.h>
+
+#include "nvrm_pmu.h"
+#include "nvodm_query_discovery.h"
+#include "nvrm_power.h"
+#include "nvrm_interrupt.h"
+
+
+void __iomem * volatile pci_tegra_regs;
+static bool pci_tegra_device_attached = false;
+static unsigned int pci_tegra_powerid;
static int __init pcie_tegra_init(void);
@@ -40,12 +58,20 @@ static int pci_tegra_read_conf(struct pci_bus *bus, u32 devfn,
static int __init pcie_tegra_init(void);
+
+static void pci_tegra_power(int on);
+static void pci_tegra_setup_translations(void);
+static irqreturn_t pci_tegra_isr(int irq, void *arg);
+static bool pci_tegra_check_rp(int rp);
+
unsigned long pci_tegra_get_base(char *aperture)
{
if (!strcmp(aperture, "mem"))
- return 0x90000000;
+ return TEGRA_PCIE_BASE +
+ PCIE_NON_PREFETCH_MEMORY_OFFSET;
else if (!strcmp(aperture, "io"))
- return 0x82000000;
+ return TEGRA_PCIE_BASE +
+ PCIE_DOWNSTREAM_IO_OFFSET;
else
return (unsigned long)-1;
}
@@ -54,32 +80,302 @@ static int pci_tegra_read_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 *val)
{
int i;
+ u32 v;
+ int rp;
+
+ pr_debug("Issuing read conf: bus %d, devfn 0x%x, where 0x%x size %d\n",
+ bus->number, devfn, where, size);
+
+ if (!pci_tegra_device_attached) goto fail;
+ if (where > 4096) goto fail;
+
+ /* Root port config registers are directly mapped in different
+ * aperture - not same as the config registers for devices on the PCI
+ * bus
+ */
+ if (pci_tegra_is_rp(bus->number, &rp)) {
+ /* Root port is just one bridge! */
+ if (devfn != 0) goto fail;
+ v = pci_tegra_rp_readl(where & ~3, rp);
+ } else {
+ void __iomem *addr;
+
+ /* Root is only attached to one device/bridge */
+ if (bus->number == 1 && PCI_SLOT(devfn) != 0) goto fail;
+ addr = pci_tegra_config_addr(bus->number, devfn, where & ~3);
+ v = readl(addr);
+ }
+
+ switch (size) {
+ case 1:
+ if (where & 2) v >>= 16;
+ if (where & 1) v >>= 8;
+ v &= 0xff;
+ break;
+ case 2:
+ if (where & 2) v >>= 16;
+ v &= 0xffff;
+ break;
+ default:
+ break;
+ }
+ *val = v;
+ pr_debug(" Value = 0x%x\n", v);
+
+ return PCIBIOS_SUCCESSFUL;
+fail:
for (i=0; i<size; i++)
((__u8 *)val)[i] = 0xff;
-
return PCIBIOS_SUCCESSFUL;
}
static int pci_tegra_write_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
+ void __iomem *addr;
+ int rp;
+ u32 temp;
+
+ pr_debug("Issuing write conf: bus %d, devfn 0x%x, "
+ "where 0x%x size %d value = 0x%x\n",
+ bus->number, devfn, where, size, val);
+
+ if (!pci_tegra_device_attached) goto fail;
+
+ if (where > 4096) goto fail;
+
+ /* Root port config registers are directly mapped in different
+ * aperture - not same as the config registers for devices on the PCI
+ * bus.
+ */
+ if (pci_tegra_is_rp(bus->number, &rp)) {
+ /* Root port is just one bridge! */
+ if (devfn != 0) goto fail;
+ addr = pci_tegra_regs;
+ if (rp == 0) addr += NV_PCIE_AXI_RP_T0C0_OFFSET;
+ if (rp == 1) addr += NV_PCIE_AXI_RP_T0C1_OFFSET;
+ addr += where;
+ } else {
+ /* Root is only attached to one device/bridge */
+ if (bus->number == 1 && PCI_SLOT(devfn) != 0) goto fail;
+
+ addr = pci_tegra_config_addr(bus->number, devfn, where);
+ }
+
+ switch (size) {
+ case 1:
+ temp = readl((u32)addr & ~0x3);
+ temp &= ~(0xff << ((where & 0x3) * 8));
+ temp |= val << ((where & 0x3) * 8);
+ writel(temp, (u32)addr & ~0x3);
+ break;
+ case 2:
+ temp = readl((u32)addr & ~0x3);
+ temp &= ~(0xffff << ((where & 0x3) * 8));
+ temp |= val << ((where & 0x3) * 8);
+ writel(temp, (u32)addr & ~0x3);
+ break;
+ default:
+ writel(val, addr);
+ break;
+ }
+fail:
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops pci_tegra_ops = {
- .read = pci_tegra_read_conf,
- .write = pci_tegra_write_conf,
+ .read = pci_tegra_read_conf,
+ .write = pci_tegra_write_conf,
};
static void __init pci_tegra_preinit(void)
{
-
+ pcibios_setup("firmware");
}
static int __init pci_tegra_setup(int nr, struct pci_sys_data *data)
{
- return (nr == 0);
+ u32 volatile reg;
+ unsigned int irq;
+
+ if (nr != 0) return 0;
+
+ pci_tegra_power(1);
+ if (NvRmSetModuleTristate(s_hRmGlobal,
+ NVRM_MODULE_ID(NvRmPrivModuleID_Pcie, 0), NV_FALSE)
+ != NvSuccess) {
+ /* No valid Pinmux for PCIe? */
+ return 0;
+ }
+
+ pci_tegra_regs = ioremap_nocache(TEGRA_PCIE_BASE,
+ PCI_TEGRA_IOMAPPED_REG_APERTURE_SIZE);
+ if (pci_tegra_regs == NULL) {
+ pr_err("pci_tegra_setup: Failed to map the PCI/AFI regs\n");
+ return 0;
+ }
+
+ if (NvRmPowerRegister(s_hRmGlobal, 0, &pci_tegra_powerid) != NvSuccess)
+ goto fail;
+ if (NvRmPowerModuleClockControl(s_hRmGlobal, NvRmPrivModuleID_Pcie,
+ pci_tegra_powerid, NV_TRUE) != NvSuccess)
+ goto fail;
+
+ NvRmModuleReset(s_hRmGlobal, NvRmPrivModuleID_Afi);
+ NvRmModuleReset(s_hRmGlobal, NvRmPrivModuleID_Pcie);
+ NvRmModuleResetWithHold(s_hRmGlobal, NvRmPrivModuleID_PcieXclk,
+ NV_TRUE);
+
+ /* Enable slot clock and pulse the reset signals */
+ reg = pci_tegra_afi_readl(AFI_PEX0_CTRL_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX0_CTRL, PEX0_REFCLK_EN, 1, reg);
+ pci_tegra_afi_writel(reg, AFI_PEX0_CTRL_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX0_CTRL, PEX0_RST_L, 0, reg);
+ pci_tegra_afi_writel(reg, AFI_PEX0_CTRL_0);
+
+ reg = pci_tegra_afi_readl(AFI_PEX1_CTRL_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX1_CTRL, PEX1_REFCLK_EN, 1, reg);
+ pci_tegra_afi_writel(reg, AFI_PEX1_CTRL_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX1_CTRL, PEX1_RST_L, 0, reg);
+ pci_tegra_afi_writel(reg, AFI_PEX1_CTRL_0);
+
+ msleep(100);
+
+ reg = pci_tegra_afi_readl(AFI_PEX0_CTRL_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX0_CTRL, PEX0_RST_L, 1, reg);
+ pci_tegra_afi_writel(reg, AFI_PEX0_CTRL_0);
+
+ reg = pci_tegra_afi_readl(AFI_PEX1_CTRL_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX1_CTRL, PEX1_RST_L, 1, reg);
+ pci_tegra_afi_writel(reg, AFI_PEX1_CTRL_0);
+
+ /* Validate by reading the ROOT port IDs that we are infact working on
+ * the TEGRA root port */
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_DEV_ID, 0);
+ BUG_ON((NVPCIE_DRF_VAL(RP, DEV_ID, VENDOR_ID, reg)) !=
+ NV_PROJ__PCIE2_RP_DEV_ID_VENDOR_ID_NVIDIA);
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_DEV_ID, 1);
+ BUG_ON((NVPCIE_DRF_VAL(RP, DEV_ID, VENDOR_ID, reg)) !=
+ NV_PROJ__PCIE2_RP_DEV_ID_VENDOR_ID_NVIDIA);
+
+ /* Enable dual controller and both ports*/
+ reg = pci_tegra_afi_readl(AFI_PCIE_CONFIG_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PCIE_CONFIG, PCIEC0_DISABLE_DEVICE, 0,
+ reg);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PCIE_CONFIG, SM2TMS0_XBAR_CONFIG, 1,
+ reg);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PCIE_CONFIG, PCIEC1_DISABLE_DEVICE, 0,
+ reg);
+ pci_tegra_afi_writel(reg, AFI_PCIE_CONFIG_0);
+
+ reg = pci_tegra_afi_readl(AFI_FUSE_0);
+ reg = NV_FLD_SET_DRF_NUM(AFI, FUSE, FUSE_PCIE_T0_GEN2_DIS, 0, reg);
+ pci_tegra_afi_writel(reg, AFI_FUSE_0);
+
+ /* Initialze AP20 internal PHY */
+ /* ENABLE up to 16 PCIE lanes */
+ pci_tegra_pads_writel(0x0, NV_PROJ__PCIE2_PADS_CTL_SEL_1);
+
+ /* override IDDQ to 1 on all 4 lanes */
+ reg = pci_tegra_pads_reedl(NV_PROJ__PCIE2_PADS_CTL_1);
+ reg = NVPCIE_FLD_SET_DRF_NUM(PADS, CTL_1, IDDQ_1L, 1, reg);
+ pci_tegra_pads_writel(reg, NV_PROJ__PCIE2_PADS_CTL_1);
+
+ /* set up PHY PLL inputs select PLLE output as refclock */
+ reg = pci_tegra_pads_reedl(NV_PROJ__PCIE2_PADS_PLL_CTL1);
+ reg = NVPCIE_FLD_SET_DRF_NUM(PADS, PLL_CTL1, PLL_REFCLK_SEL,
+ NV_PROJ__PCIE2_PADS_PLL_CTL1_PLL_REFCLK_SEL_INTERNAL_CML, reg);
+
+ /* set TX ref sel to div10 (not div5) */
+ reg = NVPCIE_FLD_SET_DRF_NUM(PADS, PLL_CTL1, PLL_TXCLKREF_SEL,
+ NV_PROJ__PCIE2_PADS_PLL_CTL1_PLL_TXCLKREF_SEL_DIV10, reg);
+ pci_tegra_pads_writel(reg, NV_PROJ__PCIE2_PADS_PLL_CTL1);
+
+ /* take PLL out of reset */
+ reg = pci_tegra_pads_reedl(NV_PROJ__PCIE2_PADS_PLL_CTL1);
+ reg = NVPCIE_FLD_SET_DRF_NUM(PADS, PLL_CTL1, PLL_RST_B4SM,
+ NV_PROJ__PCIE2_PADS_PLL_CTL1_PLL_RST_B4SM_DEASSERT, reg);
+ pci_tegra_pads_writel(reg, NV_PROJ__PCIE2_PADS_PLL_CTL1);
+
+ /* Hack, set the clock voltage to the DEFAULT provided by hw folks.
+ * This doesn't exist in the documentation
+ * */
+ reg = 0xFA5CFA5C;
+ pci_tegra_pads_writel(reg, 0xc8);
+
+ /* Wait for the PLL to lock */
+ reg = pci_tegra_pads_reedl(NV_PROJ__PCIE2_PADS_PLL_CTL1);
+ while (NVPCIE_DRF_VAL(PADS, PLL_CTL1, PLL_LOCKDET, reg)
+ != NV_PROJ__PCIE2_PADS_PLL_CTL1_PLL_LOCKDET_LOCKED)
+ {
+ reg = pci_tegra_pads_reedl(NV_PROJ__PCIE2_PADS_PLL_CTL1);
+ }
+
+ /* turn off IDDQ override */
+ reg = pci_tegra_pads_reedl(NV_PROJ__PCIE2_PADS_CTL_1);
+ reg = NVPCIE_FLD_SET_DRF_NUM(PADS, CTL_1, IDDQ_1L, 0, reg);
+ pci_tegra_pads_writel(reg, NV_PROJ__PCIE2_PADS_CTL_1);
+
+ /* ENABLE TX/RX data */
+ reg = pci_tegra_pads_reedl(NV_PROJ__PCIE2_PADS_CTL_1);
+ reg = NVPCIE_FLD_SET_DRF_NUM(PADS, CTL_1, TX_DATA_EN_1L,
+ NV_PROJ__PCIE2_PADS_CTL_1_TX_DATA_EN_1L_ENABLE, reg);
+ reg = NVPCIE_FLD_SET_DRF_NUM(PADS, CTL_1, RX_DATA_EN_1L,
+ NV_PROJ__PCIE2_PADS_CTL_1_RX_DATA_EN_1L_ENABLE, reg);
+ pci_tegra_pads_writel(reg, NV_PROJ__PCIE2_PADS_CTL_1);
+
+ irq = tegra_get_module_inst_irq("pcie", 0, 0);
+ BUG_ON(irq == NO_IRQ);
+ if (request_irq(irq, pci_tegra_isr, IRQF_SHARED, "PCIE", s_hRmGlobal))
+ {
+ pr_err("pci_tegra_setup: Cannot register the IRQ %d\n", irq);
+ }
+ set_irq_flags(irq, IRQF_VALID);
+
+ /* setup the AFI address translations */
+ pci_tegra_setup_translations();
+
+ /* Take the PCIe interface module out of reset to start the PCIe
+ * training sequence */
+ NvRmModuleResetWithHold(s_hRmGlobal, NvRmPrivModuleID_PcieXclk,
+ NV_FALSE);
+
+ /* Finally enable PCIe */
+ reg = pci_tegra_afi_readl(AFI_CONFIGURATION_0);
+ reg = reg | AFI_CONFIGURATION_0_EN_FPCI_DEFAULT_MASK;
+ pci_tegra_afi_writel(reg, AFI_CONFIGURATION_0);
+
+ if (!pci_tegra_check_rp(0) && !pci_tegra_check_rp(1)) {
+ pci_tegra_device_attached = false;
+ return 0;
+ }
+ pci_tegra_device_attached = true;
+
+ /* Enable PCIe interrupts */
+ reg = 0;
+ reg |= NV_DRF_NUM(AFI, AFI_INTR_ENABLE, EN_INI_SLVERR, 1);
+ reg |= NV_DRF_NUM(AFI, AFI_INTR_ENABLE, EN_INI_DECERR, 1);
+ reg |= NV_DRF_NUM(AFI, AFI_INTR_ENABLE, EN_TGT_SLVERR, 1);
+ reg |= NV_DRF_NUM(AFI, AFI_INTR_ENABLE, EN_TGT_DECERR, 1);
+ reg |= NV_DRF_NUM(AFI, AFI_INTR_ENABLE, EN_TGT_WRERR, 1);
+ reg |= NV_DRF_NUM(AFI, AFI_INTR_ENABLE, EN_DFPCI_DECERR, 1);
+ pci_tegra_afi_writel(reg, AFI_AFI_INTR_ENABLE_0);
+ pci_tegra_afi_writel(0xffffffff, AFI_SM_INTR_ENABLE_0);
+
+ reg = 0;
+ reg |= NV_DRF_NUM(AFI, INTR_MASK, INT_MASK, 1);
+ /* FIXME: No MSI for now */
+ reg |= NV_DRF_NUM(AFI, INTR_MASK, MSI_MASK, 0);
+ pci_tegra_afi_writel(reg, AFI_INTR_MASK_0);
+
+ pci_tegra_enumerate();
+
+ pr_err("pci_tegra_setup: Successfull\n");
+ return 1;
+fail:
+ pr_err("pci_tegra_setup: failed\n");
+ return 0;
}
static struct pci_bus __init *pci_tegra_scan_bus(int nr,
@@ -92,11 +388,11 @@ static struct pci_bus __init *pci_tegra_scan_bus(int nr,
}
static struct hw_pci pci_tegra_data __initdata = {
- .nr_controllers = 2,
- .preinit = pci_tegra_preinit,
- .setup = pci_tegra_setup,
- .scan = pci_tegra_scan_bus,
- .swizzle = pci_std_swizzle,
+ .nr_controllers = 2,
+ .preinit = pci_tegra_preinit,
+ .setup = pci_tegra_setup,
+ .scan = pci_tegra_scan_bus,
+ .swizzle = pci_std_swizzle,
};
late_initcall(pcie_tegra_init);
@@ -106,3 +402,244 @@ static int __init pcie_tegra_init(void)
pci_common_init(&pci_tegra_data);
return 0;
}
+
+/*
+ * PCIe support functions
+ */
+
+static void pci_tegra_power(int on)
+{
+ u32 settling_time;
+ const NvOdmPeripheralConnectivity *con = NULL;
+ int i;
+
+ con = NvOdmPeripheralGetGuid(NV_VDD_PEX_CLK_ODM_ID);
+ if (con == NULL)
+ return;
+
+ for (i = 0; i < con->NumAddress; i++) {
+ if (con->AddressList[i].Interface != NvOdmIoModule_Vdd)
+ continue;
+ if (on) {
+ NvRmPmuVddRailCapabilities rail;
+ NvRmPmuGetCapabilities(s_hRmGlobal,
+ con->AddressList[i].Address, &rail);
+ NvRmPmuSetVoltage(s_hRmGlobal,
+ con->AddressList[i].Address,
+ rail.requestMilliVolts, &settling_time);
+ } else
+ NvRmPmuSetVoltage(s_hRmGlobal,
+ con->AddressList[i].Address, NVODM_VOLTAGE_OFF,
+ &settling_time);
+ udelay(settling_time);
+ }
+}
+
+static void pci_tegra_setup_translations(void)
+{
+ u32 fpci_bar;
+ u32 size;
+ u32 axi_address;
+
+ /* Bar 0: Config Bar */
+ fpci_bar = ((u32)0xfdff << 16);
+ size = PCIE_CONFIG_SIZE;
+ axi_address = TEGRA_PCIE_BASE + PCIE_CONFIG_OFFSET;
+ pci_tegra_afi_writel(axi_address, AFI_AXI_BAR0_START_0);
+ pci_tegra_afi_writel(size>>12, AFI_AXI_BAR0_SZ_0);
+ pci_tegra_afi_writel(fpci_bar, AFI_FPCI_BAR0_0);
+
+ /* Bar 1: Extended config Bar */
+ fpci_bar = ((u32)0xfe1 << 20);
+ size = PCIE_EXTENDED_CONFIG_SIZE;
+ axi_address = TEGRA_PCIE_BASE + PCIE_EXTENDED_CONFIG_OFFSET;
+ pci_tegra_afi_writel(axi_address, AFI_AXI_BAR1_START_0);
+ pci_tegra_afi_writel(size >>12, AFI_AXI_BAR1_SZ_0);
+ pci_tegra_afi_writel(fpci_bar, AFI_FPCI_BAR1_0);
+
+ /* Bar 2: Downstream IO bar */
+ fpci_bar = ((__u32)0xfdfc << 16);
+ size = PCIE_DOWNSTREAM_IO_SIZE;
+ axi_address = TEGRA_PCIE_BASE + PCIE_DOWNSTREAM_IO_OFFSET;
+ pci_tegra_afi_writel(axi_address, AFI_AXI_BAR2_START_0);
+ pci_tegra_afi_writel(size>>12, AFI_AXI_BAR2_SZ_0);
+ pci_tegra_afi_writel(fpci_bar, AFI_FPCI_BAR2_0);
+
+ /* Bar 3: Pre-fetchable memory BAR */
+ /* Bits 39:12 of 40 bit FPCI address goes to bits 31:4 */
+ fpci_bar = (((FPCI_PREFETCH_MEMORY_OFFSET >> 12) & 0x0FFFFFFF) << 4);
+ fpci_bar |= 0x1;
+ size = PCIE_PREFETCH_MEMORY_SIZE;
+ axi_address = TEGRA_PCIE_BASE + PCIE_PREFETCH_MEMORY_OFFSET;
+ pci_tegra_afi_writel(axi_address, AFI_AXI_BAR3_START_0);
+ pci_tegra_afi_writel(size >> 12, AFI_AXI_BAR3_SZ_0);
+ pci_tegra_afi_writel(fpci_bar, AFI_FPCI_BAR3_0);
+
+ /* Bar 4: Non pre-fetchable memory BAR */
+ /* Bits 39:12 of 40 bit FPCI address goes to bits 31:4 */
+ fpci_bar = (((FPCI_NON_PREFETCH_MEMORY_OFFSET >> 12)
+ & 0x0FFFFFFF) << 4);
+ fpci_bar |= 0x1;
+ size = PCIE_NON_PREFETCH_MEMORY_SIZE;
+ axi_address = TEGRA_PCIE_BASE
+ + PCIE_NON_PREFETCH_MEMORY_OFFSET;
+ pci_tegra_afi_writel(axi_address, AFI_AXI_BAR4_START_0);
+ pci_tegra_afi_writel(size >> 12, AFI_AXI_BAR4_SZ_0);
+ pci_tegra_afi_writel(fpci_bar, AFI_FPCI_BAR4_0);
+
+ /* Bar 5: NULL out the remaining BAR as it is not used */
+ fpci_bar = 0;
+ size = 0;
+ axi_address = 0;
+ pci_tegra_afi_writel(axi_address, AFI_AXI_BAR5_START_0);
+ pci_tegra_afi_writel(size >> 12, AFI_AXI_BAR5_SZ_0);
+ pci_tegra_afi_writel(fpci_bar, AFI_FPCI_BAR5_0);
+
+ /* map all upstream transactions as uncached */
+ pci_tegra_afi_writel(FPCI_SYSTEM_MEMORY_OFFSET, AFI_CACHE_BAR0_ST_0);
+ pci_tegra_afi_writel(0, AFI_CACHE_BAR0_SZ_0);
+ pci_tegra_afi_writel(0, AFI_CACHE_BAR1_ST_0);
+ pci_tegra_afi_writel(0, AFI_CACHE_BAR1_SZ_0);
+
+ /* Map MSI bar */
+ pci_tegra_afi_writel(0, AFI_MSI_FPCI_BAR_ST_0);
+ pci_tegra_afi_writel(0, AFI_MSI_BAR_SZ_0);
+ pci_tegra_afi_writel(0, AFI_MSI_AXI_BAR_ST_0);
+ pci_tegra_afi_writel(0, AFI_MSI_BAR_SZ_0);
+}
+
+static irqreturn_t pci_tegra_isr(int irq, void *arg)
+{
+ u32 intr_info, intr_extended_info;
+ irqreturn_t ret = IRQ_HANDLED;
+
+ intr_info = pci_tegra_afi_readl(AFI_INTR_CODE_0);
+ intr_info = NV_DRF_VAL(AFI, INTR_CODE, INT_CODE, intr_info);
+ intr_extended_info = pci_tegra_afi_readl(AFI_INTR_SIGNATURE_0);
+
+ /* pr_err("+pci_tegra_isr\n"); */
+
+ switch (intr_info) {
+ case 6: /* legacy */
+ ret = IRQ_NONE;
+ break;
+ case 1: /* SLVERR */
+ pr_err("pci_tegra_isr: AXI slave error\n");
+ break;
+ case 2: /* DECERR */
+ pr_err("pci_tegra_isr: AXI decode error\n");
+ break;
+ case 3: /* PCIE target abort */
+ pr_err("pci_tegra_isr: Target abort\n");
+ break;
+ case 4: /* PCIE master abort */
+ /* Don't print this, as this error is a common error during
+ * enumeration.
+ */
+ /* pr_err("pci_tegra_isr: Master abort\n"); */
+ break;
+ case 5: /* Bufferable write to non-posted write */
+ pr_err("pci_tegra_isr: Invalid write"
+ " - Bufferable write to non-posted region\n");
+ break;
+ case 7: /* Response address mapping error */
+ pr_err("pci_tegra_isr: Response decoding error \n");
+ break;
+ case 8: /* Response address mapping error */
+ pr_err("pci_tegra_isr: AXI response decoding error\n");
+ break;
+ case 9: /* PCIE timeout */
+ pr_err("pci_tegra_isr: Transcation timeout\n");
+ break;
+ default:
+ pr_err("pci_tegra_isr: Unknown interrupt\n");
+ break;
+ }
+
+ /* Clear the interrupt code register to sample the next interrupt */
+ pci_tegra_afi_writel(0, AFI_INTR_CODE_0);
+
+ /* pr_err("-pci_tegra_isr\n"); */
+ return ret;
+}
+
+
+/*
+ * FIXME: If there are no PCIe cards attached, then calling this function
+ * can result in the increase of the bootup time as there are big timeout
+ * loops.
+ */
+static bool pci_tegra_check_rp(int rp)
+{
+#define PCI_TEGRA_LINKUP_TIMEOUT 50 /* i.e .2 seconds */
+ u32 reg;
+ int retry_count = 0;
+ int loop_counter;
+
+ BUG_ON(rp != 0 && rp != 1);
+retry:
+ if (retry_count > 2 ) {
+ pr_err("pci_tegra_check_rp: RP %d Failed\n", rp);
+ return false;
+ }
+
+ if (retry_count != 0) {
+ u32 offset;
+
+ /* Reset before retrying again. */
+ if (rp == 0) offset = AFI_PEX0_CTRL_0;
+ if (rp == 1) offset = AFI_PEX1_CTRL_0;
+
+ BUG_ON(AFI_PEX0_CTRL_0_PEX0_RST_L_SHIFT !=
+ AFI_PEX1_CTRL_0_PEX1_RST_L_SHIFT);
+
+ /* Pulse the PEX reset */
+ reg = pci_tegra_afi_readl(offset);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX0_CTRL, PEX0_RST_L, 1, reg);
+ pci_tegra_afi_writel(reg, offset);
+
+ msleep(100);
+
+ reg = pci_tegra_afi_readl(offset);
+ reg = NV_FLD_SET_DRF_NUM(AFI, PEX0_CTRL, PEX0_RST_L, 0, reg);
+ pci_tegra_afi_writel(reg, offset);
+ }
+
+ loop_counter = PCI_TEGRA_LINKUP_TIMEOUT;
+
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_VEND_XP, rp);
+ while (loop_counter && (NVPCIE_DRF_VAL(RP, VEND_XP, DL_UP, reg)!= 1)) {
+ msleep(1);
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_VEND_XP, rp);
+ loop_counter --;
+ }
+
+ if (!loop_counter) {
+ retry_count++;
+ pr_err("pci_tegra_check_rp: "
+ "RP %d LINK is not up...retrying...\n", rp);
+ goto retry;
+ }
+
+ loop_counter = PCI_TEGRA_LINKUP_TIMEOUT;
+
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_LINK_CONTROL_STATUS, rp);
+ reg = NVPCIE_DRF_VAL(RP, LINK_CONTROL_STATUS, LINKSTAT, reg);
+ while (loop_counter && ((reg & 0x2000) != 0x2000)) {
+ msleep(1);
+ reg = pci_tegra_rp_readl(NV_PROJ__PCIE2_RP_LINK_CONTROL_STATUS,
+ rp);
+ reg = NVPCIE_DRF_VAL(RP, LINK_CONTROL_STATUS, LINKSTAT, reg);
+ pr_err("pci_tegra_check_rp: "
+ "RP %d LINK status 0x%x...retrying...\n", rp, reg);
+ loop_counter --;
+ }
+
+ if (!loop_counter) {
+ retry_count++;
+ goto retry;
+ }
+
+ pr_info("pci_tegra_check_rp: RP %d success\n", rp);
+ return true;
+}
diff --git a/arch/arm/mach-tegra/tegra_sysmap.c b/arch/arm/mach-tegra/tegra_sysmap.c
index 13550ff45322..cb5b88ced984 100644
--- a/arch/arm/mach-tegra/tegra_sysmap.c
+++ b/arch/arm/mach-tegra/tegra_sysmap.c
@@ -34,6 +34,8 @@ static NvRmModuleID tegra_map_name_to_mod(const char *name, int inst)
return NVRM_MODULE_ID(NvRmPrivModuleID_Pl310, inst);
else if (!strcmp(name, "scu"))
return NVRM_MODULE_ID(NvRmPrivModuleID_ArmPerif, inst);
+ else if (!strcmp(name, "pcie"))
+ return NVRM_MODULE_ID(NvRmPrivModuleID_Pcie, inst);
return (NvRmModuleID) 0;
}
diff --git a/drivers/mtd/devices/tegra_mtd_nand.c b/drivers/mtd/devices/tegra_mtd_nand.c
index c6952ea5ef2e..a17b97252733 100644
--- a/drivers/mtd/devices/tegra_mtd_nand.c
+++ b/drivers/mtd/devices/tegra_mtd_nand.c
@@ -55,7 +55,6 @@ static const char *part_probes[] = { "cmdlinepart", NULL, };
#endif
static NvDdkNandHandle s_hNand;
-static struct wake_lock nand_wake_lock;
struct tegra_nand_chip {
spinlock_t lock;
@@ -219,11 +218,9 @@ static int tegra_nand_block_isbad(struct mtd_info *mtd, loff_t offs)
if (offs >= mtd->size)
return -EINVAL;
- wake_lock(&nand_wake_lock);
mutex_lock(&info->lock);
ret = check_block_isbad(mtd, offs, TagArea);
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return ret;
}
@@ -246,7 +243,6 @@ static int tegra_nand_block_markbad(struct mtd_info *mtd, loff_t offs)
pr_info("tegra_nand: setting block %d bad\n", block);
- wake_lock(&nand_wake_lock);
mutex_lock(&info->lock);
offs &= ~(mtd->erasesize - 1);
@@ -272,12 +268,10 @@ static int tegra_nand_block_markbad(struct mtd_info *mtd, loff_t offs)
NvDdkNandSuspendClocks(s_hNand);
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return 0;
fail:
NvDdkNandSuspendClocks(s_hNand);
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return -ENXIO;
}
@@ -383,7 +377,6 @@ static int tegra_nand_read(struct mtd_info *mtd, loff_t from, size_t len,
NvU32 PageNumber = 0, ChipNumber = 0;
NvU64 curAddr = from;
- wake_lock(&nand_wake_lock);
mutex_lock(&info->lock);
for (i=0;i<NDFLASH_CS_MAX;i++)
@@ -423,7 +416,6 @@ static int tegra_nand_read(struct mtd_info *mtd, loff_t from, size_t len,
NvDdkNandSuspendClocks(s_hNand);
*retlen = len;
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return 0;
fail:
@@ -431,7 +423,6 @@ fail:
NvDdkNandSuspendClocks(s_hNand);
*retlen = len - bytesLeft;
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return -EINVAL;
}
@@ -449,7 +440,6 @@ static int do_read_oob(struct mtd_info *mtd, loff_t from,
NvU32 PageNumber = 0, ChipNumber = 0;
NvU64 curAddr = from;
- wake_lock(&nand_wake_lock);
mutex_lock(&info->lock);
if (check_block_isbad(mtd, curAddr, tempSpareBuffer)) {
@@ -490,7 +480,6 @@ static int do_read_oob(struct mtd_info *mtd, loff_t from,
ops->oobretlen = 0;
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return 0;
fail:
@@ -500,7 +489,6 @@ fail:
NvDdkNandSuspendClocks(s_hNand);
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return -EINVAL;
}
@@ -552,7 +540,6 @@ static int tegra_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
pr_info("%s: write: to=0x%llx len=0x%x\n", __func__, to, len);
- wake_lock(&nand_wake_lock);
mutex_lock(&info->lock);
for (i=0;i<NDFLASH_CS_MAX;i++)
@@ -592,7 +579,6 @@ static int tegra_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
*retlen = len;
NvDdkNandSuspendClocks(s_hNand);
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return 0;
fail:
@@ -600,7 +586,6 @@ fail:
pr_info("WriteError: NvDdkNandWrite failed error(0x%x)", e);
*retlen = len - bytesLeft;
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return -EINVAL;
}
@@ -617,7 +602,6 @@ static int do_write_oob(struct mtd_info *mtd, loff_t to,
NvU8 tempSpareBuffer[NAND_SPARE_SIZE];
NvU32 PageNumber = 0, ChipNumber = 0;
- wake_lock(&nand_wake_lock);
mutex_lock(&info->lock);
if (ooblen > info->chip.tagSize)
@@ -652,7 +636,6 @@ static int do_write_oob(struct mtd_info *mtd, loff_t to,
NvDdkNandSuspendClocks(s_hNand);
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return 0;
fail:
@@ -662,7 +645,6 @@ fail:
ops->oobretlen = 0;
mutex_unlock(&info->lock);
- wake_unlock(&nand_wake_lock);
return -EINVAL;
}
@@ -939,13 +921,11 @@ static struct platform_driver tegra_nand_driver = {
static int __init tegra_nand_init(void)
{
- wake_lock_init(&nand_wake_lock, WAKE_LOCK_IDLE, "tegra_nand");
return platform_driver_register(&tegra_nand_driver);
}
static void __exit tegra_nand_exit(void)
{
- wake_lock_destroy(&nand_wake_lock);
platform_driver_unregister(&tegra_nand_driver);
}