]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-tegra
authorTom Rini <trini@ti.com>
Thu, 1 Jan 2015 20:10:39 +0000 (15:10 -0500)
committerTom Rini <trini@ti.com>
Thu, 1 Jan 2015 20:10:39 +0000 (15:10 -0500)
50 files changed:
README
arch/arm/cpu/tegra-common/Makefile
arch/arm/cpu/tegra-common/powergate.c [new file with mode: 0644]
arch/arm/cpu/tegra-common/xusb-padctl.c [new file with mode: 0644]
arch/arm/cpu/tegra124-common/Makefile
arch/arm/cpu/tegra124-common/clock.c
arch/arm/cpu/tegra124-common/xusb-padctl.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/clock.c
arch/arm/cpu/tegra30-common/clock.c
arch/arm/dts/tegra124-jetson-tk1.dts
arch/arm/dts/tegra124.dtsi
arch/arm/dts/tegra20-trimslice.dts
arch/arm/dts/tegra20.dtsi
arch/arm/dts/tegra30-beaver.dts
arch/arm/dts/tegra30-cardhu.dts
arch/arm/dts/tegra30-colibri.dts
arch/arm/dts/tegra30.dtsi
arch/arm/include/asm/arch-tegra/powergate.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra/xusb-padctl.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/powergate.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra124/clock.h
arch/arm/include/asm/arch-tegra124/powergate.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra20/clock-tables.h
arch/arm/include/asm/arch-tegra20/clock.h
arch/arm/include/asm/arch-tegra20/powergate.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/clock.h
arch/arm/include/asm/arch-tegra30/powergate.h [new file with mode: 0644]
arch/arm/include/asm/system.h
arch/arm/lib/cache.c
board/compulab/trimslice/trimslice.c
board/nvidia/cardhu/cardhu.c
board/nvidia/common/board.c
board/nvidia/jetson-tk1/jetson-tk1.c
common/board_r.c
drivers/net/rtl8169.c
drivers/pci/Makefile
drivers/pci/pci_tegra.c [new file with mode: 0644]
drivers/power/Makefile
drivers/power/as3722.c [new file with mode: 0644]
include/configs/beaver.h
include/configs/cardhu.h
include/configs/jetson-tk1.h
include/configs/tegra-common.h
include/configs/trimslice.h
include/dt-bindings/clock/tegra20-car.h
include/dt-bindings/clock/tegra30-car.h
include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h [new file with mode: 0644]
include/fdtdec.h
include/power/as3722.h [new file with mode: 0644]
lib/fdtdec.c

diff --git a/README b/README
index 42ece994739cd4f56f39e32861d57c78503bc3bc..604f0fa78e5141839e29e8d855a2932f537b3f69 100644 (file)
--- a/README
+++ b/README
@@ -4016,6 +4016,25 @@ Configuration Settings:
                boards which do not use the full malloc in SPL (which is
                enabled with CONFIG_SYS_SPL_MALLOC_START).
 
+- CONFIG_SYS_NONCACHED_MEMORY:
+               Size of non-cached memory area. This area of memory will be
+               typically located right below the malloc() area and mapped
+               uncached in the MMU. This is useful for drivers that would
+               otherwise require a lot of explicit cache maintenance. For
+               some drivers it's also impossible to properly maintain the
+               cache. For example if the regions that need to be flushed
+               are not a multiple of the cache-line size, *and* padding
+               cannot be allocated between the regions to align them (i.e.
+               if the HW requires a contiguous array of regions, and the
+               size of each region is not cache-aligned), then a flush of
+               one region may result in overwriting data that hardware has
+               written to another region in the same cache-line. This can
+               happen for example in network drivers where descriptors for
+               buffers are typically smaller than the CPU cache-line (e.g.
+               16 bytes vs. 32 or 64 bytes).
+
+               Non-cached memory is only supported on 32-bit ARM at present.
+
 - CONFIG_SYS_BOOTM_LEN:
                Normally compressed uImages are limited to an
                uncompressed size of 8 MBytes. If this is not enough,
index a18c318739fa2b6228b182fed24f507dfccfed10..a78869ee2329a6ca5019f91c9168cac83fba61cf 100644 (file)
@@ -13,5 +13,7 @@ obj-y += cache.o
 obj-y += clock.o
 obj-y += lowlevel_init.o
 obj-y += pinmux-common.o
+obj-y += powergate.o
+obj-y += xusb-padctl.o
 obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
 obj-$(CONFIG_TEGRA124) += vpr.o
diff --git a/arch/arm/cpu/tegra-common/powergate.c b/arch/arm/cpu/tegra-common/powergate.c
new file mode 100644 (file)
index 0000000..439cff3
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+
+#include <asm/io.h>
+#include <asm/types.h>
+
+#include <asm/arch/powergate.h>
+#include <asm/arch/tegra.h>
+
+#define PWRGATE_TOGGLE 0x30
+#define  PWRGATE_TOGGLE_START (1 << 8)
+
+#define REMOVE_CLAMPING 0x34
+
+#define PWRGATE_STATUS 0x38
+
+static int tegra_powergate_set(enum tegra_powergate id, bool state)
+{
+       u32 value, mask = state ? (1 << id) : 0, old_mask;
+       unsigned long start, timeout = 25;
+
+       value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+       old_mask = value & (1 << id);
+
+       if (mask == old_mask)
+               return 0;
+
+       writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE);
+
+       start = get_timer(0);
+
+       while (get_timer(start) < timeout) {
+               value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+               if ((value & (1 << id)) == mask)
+                       return 0;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static int tegra_powergate_power_on(enum tegra_powergate id)
+{
+       return tegra_powergate_set(id, true);
+}
+
+int tegra_powergate_power_off(enum tegra_powergate id)
+{
+       return tegra_powergate_set(id, false);
+}
+
+static int tegra_powergate_remove_clamping(enum tegra_powergate id)
+{
+       unsigned long value;
+
+       /*
+        * The REMOVE_CLAMPING register has the bits for the PCIE and VDEC
+        * partitions reversed. This was originally introduced on Tegra20 but
+        * has since been carried forward for backwards-compatibility.
+        */
+       if (id == TEGRA_POWERGATE_VDEC)
+               value = 1 << TEGRA_POWERGATE_PCIE;
+       else if (id == TEGRA_POWERGATE_PCIE)
+               value = 1 << TEGRA_POWERGATE_VDEC;
+       else
+               value = 1 << id;
+
+       writel(value, NV_PA_PMC_BASE + REMOVE_CLAMPING);
+
+       return 0;
+}
+
+int tegra_powergate_sequence_power_up(enum tegra_powergate id,
+                                     enum periph_id periph)
+{
+       int err;
+
+       reset_set_enable(periph, 1);
+
+       err = tegra_powergate_power_on(id);
+       if (err < 0)
+               return err;
+
+       clock_enable(periph);
+
+       udelay(10);
+
+       err = tegra_powergate_remove_clamping(id);
+       if (err < 0)
+               return err;
+
+       udelay(10);
+
+       reset_set_enable(periph, 0);
+
+       return 0;
+}
diff --git a/arch/arm/cpu/tegra-common/xusb-padctl.c b/arch/arm/cpu/tegra-common/xusb-padctl.c
new file mode 100644 (file)
index 0000000..65f8d2e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+
+#include <asm/arch-tegra/xusb-padctl.h>
+
+struct tegra_xusb_phy * __weak tegra_xusb_phy_get(unsigned int type)
+{
+       return NULL;
+}
+
+int __weak tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy)
+{
+       return -ENOSYS;
+}
+
+int __weak tegra_xusb_phy_enable(struct tegra_xusb_phy *phy)
+{
+       return -ENOSYS;
+}
+
+int __weak tegra_xusb_phy_disable(struct tegra_xusb_phy *phy)
+{
+       return -ENOSYS;
+}
+
+int __weak tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy)
+{
+       return -ENOSYS;
+}
+
+void __weak tegra_xusb_padctl_init(const void *fdt)
+{
+}
index ff77992b330cd7d7571be5eff21a89d8519bb67d..7b59fb121614002dd2a48345994a4f8d41754c4a 100644 (file)
@@ -8,3 +8,4 @@
 obj-y  += clock.o
 obj-y  += funcmux.o
 obj-y  += pinmux.o
+obj-y  += xusb-padctl.o
index 739436326ecaf78e1fc39a954ea06611d780ebad..fc8bd194ddc9d7bb29f8c1503939c58f4bf47066 100644 (file)
@@ -824,3 +824,112 @@ void arch_timer_init(void)
        writel(val, &sysctr->cntcr);
        debug("%s: TSC CNTCR = 0x%08X\n", __func__, val);
 }
+
+#define PLLE_SS_CNTL 0x68
+#define  PLLE_SS_CNTL_SSCINCINTR(x) (((x) & 0x3f) << 24)
+#define  PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
+#define  PLLE_SS_CNTL_SSCINVERT (1 << 15)
+#define  PLLE_SS_CNTL_SSCCENTER (1 << 14)
+#define  PLLE_SS_CNTL_SSCBYP (1 << 12)
+#define  PLLE_SS_CNTL_INTERP_RESET (1 << 11)
+#define  PLLE_SS_CNTL_BYPASS_SS (1 << 10)
+#define  PLLE_SS_CNTL_SSCMAX(x) (((x) & 0x1ff) << 0)
+
+#define PLLE_BASE 0x0e8
+#define  PLLE_BASE_ENABLE (1 << 30)
+#define  PLLE_BASE_LOCK_OVERRIDE (1 << 29)
+#define  PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
+#define  PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
+#define  PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
+
+#define PLLE_MISC 0x0ec
+#define  PLLE_MISC_IDDQ_SWCTL (1 << 14)
+#define  PLLE_MISC_IDDQ_OVERRIDE (1 << 13)
+#define  PLLE_MISC_LOCK_ENABLE (1 << 9)
+#define  PLLE_MISC_PTS (1 << 8)
+#define  PLLE_MISC_VREG_BG_CTRL(x) (((x) & 0x3) << 4)
+#define  PLLE_MISC_VREG_CTRL(x) (((x) & 0x3) << 2)
+
+#define PLLE_AUX 0x48c
+#define  PLLE_AUX_SEQ_ENABLE (1 << 24)
+#define  PLLE_AUX_ENABLE_SWCTL (1 << 4)
+
+int tegra_plle_enable(void)
+{
+       unsigned int m = 1, n = 200, cpcon = 13;
+       u32 value;
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+       value &= ~PLLE_BASE_LOCK_OVERRIDE;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_AUX);
+       value |= PLLE_AUX_ENABLE_SWCTL;
+       value &= ~PLLE_AUX_SEQ_ENABLE;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_AUX);
+
+       udelay(1);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+       value |= PLLE_MISC_IDDQ_SWCTL;
+       value &= ~PLLE_MISC_IDDQ_OVERRIDE;
+       value |= PLLE_MISC_LOCK_ENABLE;
+       value |= PLLE_MISC_PTS;
+       value |= PLLE_MISC_VREG_BG_CTRL(3);
+       value |= PLLE_MISC_VREG_CTRL(2);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+       udelay(5);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value |= PLLE_SS_CNTL_SSCBYP | PLLE_SS_CNTL_INTERP_RESET |
+                PLLE_SS_CNTL_BYPASS_SS;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+       value &= ~PLLE_BASE_PLDIV_CML(0xf);
+       value &= ~PLLE_BASE_NDIV(0xff);
+       value &= ~PLLE_BASE_MDIV(0xff);
+       value |= PLLE_BASE_PLDIV_CML(cpcon);
+       value |= PLLE_BASE_NDIV(n);
+       value |= PLLE_BASE_MDIV(m);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       udelay(1);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+       value |= PLLE_BASE_ENABLE;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       /* wait for lock */
+       udelay(300);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value &= ~PLLE_SS_CNTL_SSCINVERT;
+       value &= ~PLLE_SS_CNTL_SSCCENTER;
+
+       value &= ~PLLE_SS_CNTL_SSCINCINTR(0x3f);
+       value &= ~PLLE_SS_CNTL_SSCINC(0xff);
+       value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
+
+       value |= PLLE_SS_CNTL_SSCINCINTR(0x20);
+       value |= PLLE_SS_CNTL_SSCINC(0x01);
+       value |= PLLE_SS_CNTL_SSCMAX(0x25);
+
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value &= ~PLLE_SS_CNTL_SSCBYP;
+       value &= ~PLLE_SS_CNTL_BYPASS_SS;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       udelay(1);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value &= ~PLLE_SS_CNTL_INTERP_RESET;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       udelay(1);
+
+       return 0;
+}
diff --git a/arch/arm/cpu/tegra124-common/xusb-padctl.c b/arch/arm/cpu/tegra124-common/xusb-padctl.c
new file mode 100644 (file)
index 0000000..43af883
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#define pr_fmt(fmt) "tegra-xusb-padctl: " fmt
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/xusb-padctl.h>
+
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
+
+enum tegra124_function {
+       TEGRA124_FUNC_SNPS,
+       TEGRA124_FUNC_XUSB,
+       TEGRA124_FUNC_UART,
+       TEGRA124_FUNC_PCIE,
+       TEGRA124_FUNC_USB3,
+       TEGRA124_FUNC_SATA,
+       TEGRA124_FUNC_RSVD,
+};
+
+static const char *const tegra124_functions[] = {
+       "snps",
+       "xusb",
+       "uart",
+       "pcie",
+       "usb3",
+       "sata",
+       "rsvd",
+};
+
+static const unsigned int tegra124_otg_functions[] = {
+       TEGRA124_FUNC_SNPS,
+       TEGRA124_FUNC_XUSB,
+       TEGRA124_FUNC_UART,
+       TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_usb_functions[] = {
+       TEGRA124_FUNC_SNPS,
+       TEGRA124_FUNC_XUSB,
+};
+
+static const unsigned int tegra124_pci_functions[] = {
+       TEGRA124_FUNC_PCIE,
+       TEGRA124_FUNC_USB3,
+       TEGRA124_FUNC_SATA,
+       TEGRA124_FUNC_RSVD,
+};
+
+struct tegra_xusb_padctl_lane {
+       const char *name;
+
+       unsigned int offset;
+       unsigned int shift;
+       unsigned int mask;
+       unsigned int iddq;
+
+       const unsigned int *funcs;
+       unsigned int num_funcs;
+};
+
+#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)    \
+       {                                                               \
+               .name = _name,                                          \
+               .offset = _offset,                                      \
+               .shift = _shift,                                        \
+               .mask = _mask,                                          \
+               .iddq = _iddq,                                          \
+               .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \
+               .funcs = tegra124_##_funcs##_functions,                 \
+       }
+
+static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
+       TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
+       TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
+       TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
+       TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
+       TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
+       TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
+       TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
+       TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
+       TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
+       TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
+       TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
+       TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
+};
+
+struct tegra_xusb_phy_ops {
+       int (*prepare)(struct tegra_xusb_phy *phy);
+       int (*enable)(struct tegra_xusb_phy *phy);
+       int (*disable)(struct tegra_xusb_phy *phy);
+       int (*unprepare)(struct tegra_xusb_phy *phy);
+};
+
+struct tegra_xusb_phy {
+       const struct tegra_xusb_phy_ops *ops;
+
+       struct tegra_xusb_padctl *padctl;
+};
+
+struct tegra_xusb_padctl_pin {
+       const struct tegra_xusb_padctl_lane *lane;
+
+       unsigned int func;
+       int iddq;
+};
+
+#define MAX_GROUPS 3
+#define MAX_PINS 6
+
+struct tegra_xusb_padctl_group {
+       const char *name;
+
+       const char *pins[MAX_PINS];
+       unsigned int num_pins;
+
+       const char *func;
+       int iddq;
+};
+
+struct tegra_xusb_padctl_config {
+       const char *name;
+
+       struct tegra_xusb_padctl_group groups[MAX_GROUPS];
+       unsigned int num_groups;
+};
+
+struct tegra_xusb_padctl {
+       struct fdt_resource regs;
+
+       unsigned int enable;
+
+       struct tegra_xusb_phy phys[2];
+
+       const struct tegra_xusb_padctl_lane *lanes;
+       unsigned int num_lanes;
+
+       const char *const *functions;
+       unsigned int num_functions;
+
+       struct tegra_xusb_padctl_config config;
+};
+
+static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
+                              unsigned long offset)
+{
+       return readl(padctl->regs.start + offset);
+}
+
+static inline void padctl_writel(struct tegra_xusb_padctl *padctl,
+                                u32 value, unsigned long offset)
+{
+       writel(value, padctl->regs.start + offset);
+}
+
+static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
+{
+       u32 value;
+
+       if (padctl->enable++ > 0)
+               return 0;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       udelay(100);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       udelay(100);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       return 0;
+}
+
+static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
+{
+       u32 value;
+
+       if (padctl->enable == 0) {
+               error("tegra-xusb-padctl: unbalanced enable/disable");
+               return 0;
+       }
+
+       if (--padctl->enable > 0)
+               return 0;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       udelay(100);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       udelay(100);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       return 0;
+}
+
+static int phy_prepare(struct tegra_xusb_phy *phy)
+{
+       return tegra_xusb_padctl_enable(phy->padctl);
+}
+
+static int phy_unprepare(struct tegra_xusb_phy *phy)
+{
+       return tegra_xusb_padctl_disable(phy->padctl);
+}
+
+static int pcie_phy_enable(struct tegra_xusb_phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy->padctl;
+       int err = -ETIMEDOUT;
+       unsigned long start;
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+       value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
+                XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
+                XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+       start = get_timer(0);
+
+       while (get_timer(start) < 50) {
+               value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+               if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
+                       err = 0;
+                       break;
+               }
+       }
+
+       return err;
+}
+
+static int pcie_phy_disable(struct tegra_xusb_phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy->padctl;
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+       return 0;
+}
+
+static int sata_phy_enable(struct tegra_xusb_phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy->padctl;
+       int err = -ETIMEDOUT;
+       unsigned long start;
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+       value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       start = get_timer(0);
+
+       while (get_timer(start) < 50) {
+               value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+               if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
+                       err = 0;
+                       break;
+               }
+       }
+
+       return err;
+}
+
+static int sata_phy_disable(struct tegra_xusb_phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy->padctl;
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+       value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+       value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+       return 0;
+}
+
+static const struct tegra_xusb_phy_ops pcie_phy_ops = {
+       .prepare = phy_prepare,
+       .enable = pcie_phy_enable,
+       .disable = pcie_phy_disable,
+       .unprepare = phy_unprepare,
+};
+
+static const struct tegra_xusb_phy_ops sata_phy_ops = {
+       .prepare = phy_prepare,
+       .enable = sata_phy_enable,
+       .disable = sata_phy_disable,
+       .unprepare = phy_unprepare,
+};
+
+static struct tegra_xusb_padctl *padctl = &(struct tegra_xusb_padctl) {
+       .phys = {
+               [0] = {
+                       .ops = &pcie_phy_ops,
+               },
+               [1] = {
+                       .ops = &sata_phy_ops,
+               },
+       },
+};
+
+static const struct tegra_xusb_padctl_lane *
+tegra_xusb_padctl_find_lane(struct tegra_xusb_padctl *padctl, const char *name)
+{
+       unsigned int i;
+
+       for (i = 0; i < padctl->num_lanes; i++)
+               if (strcmp(name, padctl->lanes[i].name) == 0)
+                       return &padctl->lanes[i];
+
+       return NULL;
+}
+
+static int
+tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
+                                struct tegra_xusb_padctl_group *group,
+                                const void *fdt, int node)
+{
+       unsigned int i;
+       int len, err;
+
+       group->name = fdt_get_name(fdt, node, &len);
+
+       len = fdt_count_strings(fdt, node, "nvidia,lanes");
+       if (len < 0) {
+               error("tegra-xusb-padctl: failed to parse \"nvidia,lanes\" property");
+               return -EINVAL;
+       }
+
+       group->num_pins = len;
+
+       for (i = 0; i < group->num_pins; i++) {
+               err = fdt_get_string_index(fdt, node, "nvidia,lanes", i,
+                                          &group->pins[i]);
+               if (err < 0) {
+                       error("tegra-xusb-padctl: failed to read string from \"nvidia,lanes\" property");
+                       return -EINVAL;
+               }
+       }
+
+       group->num_pins = len;
+
+       err = fdt_get_string(fdt, node, "nvidia,function", &group->func);
+       if (err < 0) {
+               error("tegra-xusb-padctl: failed to parse \"nvidia,func\" property");
+               return -EINVAL;
+       }
+
+       group->iddq = fdtdec_get_int(fdt, node, "nvidia,iddq", -1);
+
+       return 0;
+}
+
+static int tegra_xusb_padctl_find_function(struct tegra_xusb_padctl *padctl,
+                                          const char *name)
+{
+       unsigned int i;
+
+       for (i = 0; i < padctl->num_functions; i++)
+               if (strcmp(name, padctl->functions[i]) == 0)
+                       return i;
+
+       return -ENOENT;
+}
+
+static int
+tegra_xusb_padctl_lane_find_function(struct tegra_xusb_padctl *padctl,
+                                    const struct tegra_xusb_padctl_lane *lane,
+                                    const char *name)
+{
+       unsigned int i;
+       int func;
+
+       func = tegra_xusb_padctl_find_function(padctl, name);
+       if (func < 0)
+               return func;
+
+       for (i = 0; i < lane->num_funcs; i++)
+               if (lane->funcs[i] == func)
+                       return i;
+
+       return -ENOENT;
+}
+
+static int
+tegra_xusb_padctl_group_apply(struct tegra_xusb_padctl *padctl,
+                             const struct tegra_xusb_padctl_group *group)
+{
+       unsigned int i;
+
+       for (i = 0; i < group->num_pins; i++) {
+               const struct tegra_xusb_padctl_lane *lane;
+               unsigned int func;
+               u32 value;
+
+               lane = tegra_xusb_padctl_find_lane(padctl, group->pins[i]);
+               if (!lane) {
+                       error("tegra-xusb-padctl: no lane for pin %s",
+                             group->pins[i]);
+                       continue;
+               }
+
+               func = tegra_xusb_padctl_lane_find_function(padctl, lane,
+                                                           group->func);
+               if (func < 0) {
+                       error("tegra-xusb-padctl: function %s invalid for lane %s: %d",
+                             group->func, lane->name, func);
+                       continue;
+               }
+
+               value = padctl_readl(padctl, lane->offset);
+
+               /* set pin function */
+               value &= ~(lane->mask << lane->shift);
+               value |= func << lane->shift;
+
+               /*
+                * Set IDDQ if supported on the lane and specified in the
+                * configuration.
+                */
+               if (lane->iddq > 0 && group->iddq >= 0) {
+                       if (group->iddq != 0)
+                               value &= ~(1 << lane->iddq);
+                       else
+                               value |= 1 << lane->iddq;
+               }
+
+               padctl_writel(padctl, value, lane->offset);
+       }
+
+       return 0;
+}
+
+static int
+tegra_xusb_padctl_config_apply(struct tegra_xusb_padctl *padctl,
+                              struct tegra_xusb_padctl_config *config)
+{
+       unsigned int i;
+
+       for (i = 0; i < config->num_groups; i++) {
+               const struct tegra_xusb_padctl_group *group;
+               int err;
+
+               group = &config->groups[i];
+
+               err = tegra_xusb_padctl_group_apply(padctl, group);
+               if (err < 0) {
+                       error("tegra-xusb-padctl: failed to apply group %s: %d",
+                             group->name, err);
+                       continue;
+               }
+       }
+
+       return 0;
+}
+
+static int
+tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl,
+                                 struct tegra_xusb_padctl_config *config,
+                                 const void *fdt, int node)
+{
+       int subnode;
+
+       config->name = fdt_get_name(fdt, node, NULL);
+
+       fdt_for_each_subnode(fdt, subnode, node) {
+               struct tegra_xusb_padctl_group *group;
+               int err;
+
+               group = &config->groups[config->num_groups];
+
+               err = tegra_xusb_padctl_group_parse_dt(padctl, group, fdt,
+                                                      subnode);
+               if (err < 0) {
+                       error("tegra-xusb-padctl: failed to parse group %s",
+                             group->name);
+                       return err;
+               }
+
+               config->num_groups++;
+       }
+
+       return 0;
+}
+
+static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl,
+                                     const void *fdt, int node)
+{
+       int subnode, err;
+
+       err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs);
+       if (err < 0) {
+               error("tegra-xusb-padctl: registers not found");
+               return err;
+       }
+
+       fdt_for_each_subnode(fdt, subnode, node) {
+               struct tegra_xusb_padctl_config *config = &padctl->config;
+
+               err = tegra_xusb_padctl_config_parse_dt(padctl, config, fdt,
+                                                       subnode);
+               if (err < 0) {
+                       error("tegra-xusb-padctl: failed to parse entry %s: %d",
+                             config->name, err);
+                       continue;
+               }
+       }
+
+       return 0;
+}
+
+static int process_nodes(const void *fdt, int nodes[], unsigned int count)
+{
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               enum fdt_compat_id id;
+               int err;
+
+               if (!fdtdec_get_is_enabled(fdt, nodes[i]))
+                       continue;
+
+               id = fdtdec_lookup(fdt, nodes[i]);
+               switch (id) {
+               case COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL:
+                       break;
+
+               default:
+                       error("tegra-xusb-padctl: unsupported compatible: %s",
+                             fdtdec_get_compatible(id));
+                       continue;
+               }
+
+               padctl->num_lanes = ARRAY_SIZE(tegra124_lanes);
+               padctl->lanes = tegra124_lanes;
+
+               padctl->num_functions = ARRAY_SIZE(tegra124_functions);
+               padctl->functions = tegra124_functions;
+
+               err = tegra_xusb_padctl_parse_dt(padctl, fdt, nodes[i]);
+               if (err < 0) {
+                       error("tegra-xusb-padctl: failed to parse DT: %d",
+                             err);
+                       continue;
+               }
+
+               /* deassert XUSB padctl reset */
+               reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0);
+
+               err = tegra_xusb_padctl_config_apply(padctl, &padctl->config);
+               if (err < 0) {
+                       error("tegra-xusb-padctl: failed to apply pinmux: %d",
+                             err);
+                       continue;
+               }
+
+               /* only a single instance is supported */
+               break;
+       }
+
+       return 0;
+}
+
+struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type)
+{
+       struct tegra_xusb_phy *phy = NULL;
+
+       switch (type) {
+       case TEGRA_XUSB_PADCTL_PCIE:
+               phy = &padctl->phys[0];
+               phy->padctl = padctl;
+               break;
+
+       case TEGRA_XUSB_PADCTL_SATA:
+               phy = &padctl->phys[1];
+               phy->padctl = padctl;
+               break;
+       }
+
+       return phy;
+}
+
+int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy)
+{
+       if (phy && phy->ops && phy->ops->prepare)
+               return phy->ops->prepare(phy);
+
+       return phy ? -ENOSYS : -EINVAL;
+}
+
+int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy)
+{
+       if (phy && phy->ops && phy->ops->enable)
+               return phy->ops->enable(phy);
+
+       return phy ? -ENOSYS : -EINVAL;
+}
+
+int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy)
+{
+       if (phy && phy->ops && phy->ops->disable)
+               return phy->ops->disable(phy);
+
+       return phy ? -ENOSYS : -EINVAL;
+}
+
+int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy)
+{
+       if (phy && phy->ops && phy->ops->unprepare)
+               return phy->ops->unprepare(phy);
+
+       return phy ? -ENOSYS : -EINVAL;
+}
+
+void tegra_xusb_padctl_init(const void *fdt)
+{
+       int count, nodes[1];
+
+       count = fdtdec_find_aliases_for_id(fdt, "padctl",
+                                          COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
+                                          nodes, ARRAY_SIZE(nodes));
+       if (process_nodes(fdt, nodes, count))
+               return;
+}
index 0c4f5fb288a05d47d5ba97cfaae13d17b9f96668..7b9e10cd93ae37e7b42a4f3763a58029a1696767 100644 (file)
@@ -7,6 +7,7 @@
 /* Tegra20 Clock control functions */
 
 #include <common.h>
+#include <errno.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/tegra.h>
@@ -332,7 +333,7 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
        /* 0x48 */
        NONE(AFI),
        NONE(CORESIGHT),
-       NONE(RESERVED74),
+       NONE(PCIEXCLK),
        NONE(AVPUCQ),
        NONE(RESERVED76),
        NONE(RESERVED77),
@@ -494,7 +495,7 @@ enum periph_id clk_id_to_periph_id(int clk_id)
        case PERIPH_ID_RESERVED30:
        case PERIPH_ID_RESERVED35:
        case PERIPH_ID_RESERVED56:
-       case PERIPH_ID_RESERVED74:
+       case PERIPH_ID_PCIEXCLK:
        case PERIPH_ID_RESERVED76:
        case PERIPH_ID_RESERVED77:
        case PERIPH_ID_RESERVED78:
@@ -548,3 +549,139 @@ void clock_early_init(void)
 void arch_timer_init(void)
 {
 }
+
+#define PMC_SATA_PWRGT 0x1ac
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE (1 << 5)
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1 << 4)
+
+#define PLLE_SS_CNTL 0x68
+#define  PLLE_SS_CNTL_SSCINCINTRV(x) (((x) & 0x3f) << 24)
+#define  PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
+#define  PLLE_SS_CNTL_SSCBYP (1 << 12)
+#define  PLLE_SS_CNTL_INTERP_RESET (1 << 11)
+#define  PLLE_SS_CNTL_BYPASS_SS (1 << 10)
+#define  PLLE_SS_CNTL_SSCMAX(x) (((x) & 0x1ff) << 0)
+
+#define PLLE_BASE 0x0e8
+#define  PLLE_BASE_ENABLE_CML (1 << 31)
+#define  PLLE_BASE_ENABLE (1 << 30)
+#define  PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
+#define  PLLE_BASE_PLDIV(x) (((x) & 0x3f) << 16)
+#define  PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
+#define  PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
+
+#define PLLE_MISC 0x0ec
+#define  PLLE_MISC_SETUP_BASE(x) (((x) & 0xffff) << 16)
+#define  PLLE_MISC_PLL_READY (1 << 15)
+#define  PLLE_MISC_LOCK (1 << 11)
+#define  PLLE_MISC_LOCK_ENABLE (1 << 9)
+#define  PLLE_MISC_SETUP_EXT(x) (((x) & 0x3) << 2)
+
+static int tegra_plle_train(void)
+{
+       unsigned int timeout = 2000;
+       unsigned long value;
+
+       value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+       value |= PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+       writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+       value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+       value |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
+       writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+       value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+       value &= ~PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+       writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+       do {
+               value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+               if (value & PLLE_MISC_PLL_READY)
+                       break;
+
+               udelay(100);
+       } while (--timeout);
+
+       if (timeout == 0) {
+               error("timeout waiting for PLLE to become ready");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+int tegra_plle_enable(void)
+{
+       unsigned int timeout = 1000;
+       u32 value;
+       int err;
+
+       /* disable PLLE clock */
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+       value &= ~PLLE_BASE_ENABLE_CML;
+       value &= ~PLLE_BASE_ENABLE;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       /* clear lock enable and setup field */
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+       value &= ~PLLE_MISC_LOCK_ENABLE;
+       value &= ~PLLE_MISC_SETUP_BASE(0xffff);
+       value &= ~PLLE_MISC_SETUP_EXT(0x3);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+       if ((value & PLLE_MISC_PLL_READY) == 0) {
+               err = tegra_plle_train();
+               if (err < 0) {
+                       error("failed to train PLLE: %d", err);
+                       return err;
+               }
+       }
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+       value |= PLLE_MISC_SETUP_BASE(0x7);
+       value |= PLLE_MISC_LOCK_ENABLE;
+       value |= PLLE_MISC_SETUP_EXT(0);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value |= PLLE_SS_CNTL_SSCBYP | PLLE_SS_CNTL_INTERP_RESET |
+                PLLE_SS_CNTL_BYPASS_SS;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+       value |= PLLE_BASE_ENABLE_CML | PLLE_BASE_ENABLE;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       do {
+               value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+               if (value & PLLE_MISC_LOCK)
+                       break;
+
+               udelay(2);
+       } while (--timeout);
+
+       if (timeout == 0) {
+               error("timeout waiting for PLLE to lock");
+               return -ETIMEDOUT;
+       }
+
+       udelay(50);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value &= ~PLLE_SS_CNTL_SSCINCINTRV(0x3f);
+       value |= PLLE_SS_CNTL_SSCINCINTRV(0x18);
+
+       value &= ~PLLE_SS_CNTL_SSCINC(0xff);
+       value |= PLLE_SS_CNTL_SSCINC(0x01);
+
+       value &= ~PLLE_SS_CNTL_SSCBYP;
+       value &= ~PLLE_SS_CNTL_INTERP_RESET;
+       value &= ~PLLE_SS_CNTL_BYPASS_SS;
+
+       value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
+       value |= PLLE_SS_CNTL_SSCMAX(0x24);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       return 0;
+}
index 80ba2d8c1ca5fa5f315acb3ed593a7aa73b808bd..0eb0f0ade37c518ae27707ba0c433fc4db12da01 100644 (file)
@@ -17,6 +17,7 @@
 /* Tegra30 Clock control functions */
 
 #include <common.h>
+#include <errno.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/tegra.h>
@@ -563,6 +564,7 @@ enum periph_id clk_id_to_periph_id(int clk_id)
        case PERIPH_ID_RESERVED43:
        case PERIPH_ID_RESERVED45:
        case PERIPH_ID_RESERVED56:
+       case PERIPH_ID_PCIEXCLK:
        case PERIPH_ID_RESERVED76:
        case PERIPH_ID_RESERVED77:
        case PERIPH_ID_RESERVED78:
@@ -587,3 +589,156 @@ void clock_early_init(void)
 void arch_timer_init(void)
 {
 }
+
+#define PMC_SATA_PWRGT 0x1ac
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE (1 << 5)
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1 << 4)
+
+#define PLLE_SS_CNTL 0x68
+#define  PLLE_SS_CNTL_SSCINCINTRV(x) (((x) & 0x3f) << 24)
+#define  PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
+#define  PLLE_SS_CNTL_SSCBYP (1 << 12)
+#define  PLLE_SS_CNTL_INTERP_RESET (1 << 11)
+#define  PLLE_SS_CNTL_BYPASS_SS (1 << 10)
+#define  PLLE_SS_CNTL_SSCMAX(x) (((x) & 0x1ff) << 0)
+
+#define PLLE_BASE 0x0e8
+#define  PLLE_BASE_ENABLE_CML (1 << 31)
+#define  PLLE_BASE_ENABLE (1 << 30)
+#define  PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
+#define  PLLE_BASE_PLDIV(x) (((x) & 0x3f) << 16)
+#define  PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
+#define  PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
+
+#define PLLE_MISC 0x0ec
+#define  PLLE_MISC_SETUP_BASE(x) (((x) & 0xffff) << 16)
+#define  PLLE_MISC_PLL_READY (1 << 15)
+#define  PLLE_MISC_LOCK (1 << 11)
+#define  PLLE_MISC_LOCK_ENABLE (1 << 9)
+#define  PLLE_MISC_SETUP_EXT(x) (((x) & 0x3) << 2)
+
+static int tegra_plle_train(void)
+{
+       unsigned int timeout = 2000;
+       unsigned long value;
+
+       value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+       value |= PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+       writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+       value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+       value |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
+       writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+       value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+       value &= ~PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+       writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+       do {
+               value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+               if (value & PLLE_MISC_PLL_READY)
+                       break;
+
+               udelay(100);
+       } while (--timeout);
+
+       if (timeout == 0) {
+               error("timeout waiting for PLLE to become ready");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+int tegra_plle_enable(void)
+{
+       unsigned int cpcon = 11, p = 18, n = 150, m = 1, timeout = 1000;
+       u32 value;
+       int err;
+
+       /* disable PLLE clock */
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+       value &= ~PLLE_BASE_ENABLE_CML;
+       value &= ~PLLE_BASE_ENABLE;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       /* clear lock enable and setup field */
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+       value &= ~PLLE_MISC_LOCK_ENABLE;
+       value &= ~PLLE_MISC_SETUP_BASE(0xffff);
+       value &= ~PLLE_MISC_SETUP_EXT(0x3);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+       if ((value & PLLE_MISC_PLL_READY) == 0) {
+               err = tegra_plle_train();
+               if (err < 0) {
+                       error("failed to train PLLE: %d", err);
+                       return err;
+               }
+       }
+
+       /* configure PLLE */
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       value &= ~PLLE_BASE_PLDIV_CML(0x0f);
+       value |= PLLE_BASE_PLDIV_CML(cpcon);
+
+       value &= ~PLLE_BASE_PLDIV(0x3f);
+       value |= PLLE_BASE_PLDIV(p);
+
+       value &= ~PLLE_BASE_NDIV(0xff);
+       value |= PLLE_BASE_NDIV(n);
+
+       value &= ~PLLE_BASE_MDIV(0xff);
+       value |= PLLE_BASE_MDIV(m);
+
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+       value |= PLLE_MISC_SETUP_BASE(0x7);
+       value |= PLLE_MISC_LOCK_ENABLE;
+       value |= PLLE_MISC_SETUP_EXT(0);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value |= PLLE_SS_CNTL_SSCBYP | PLLE_SS_CNTL_INTERP_RESET |
+                PLLE_SS_CNTL_BYPASS_SS;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+       value |= PLLE_BASE_ENABLE_CML | PLLE_BASE_ENABLE;
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+       do {
+               value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+               if (value & PLLE_MISC_LOCK)
+                       break;
+
+               udelay(2);
+       } while (--timeout);
+
+       if (timeout == 0) {
+               error("timeout waiting for PLLE to lock");
+               return -ETIMEDOUT;
+       }
+
+       udelay(50);
+
+       value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+       value &= ~PLLE_SS_CNTL_SSCINCINTRV(0x3f);
+       value |= PLLE_SS_CNTL_SSCINCINTRV(0x18);
+
+       value &= ~PLLE_SS_CNTL_SSCINC(0xff);
+       value |= PLLE_SS_CNTL_SSCINC(0x01);
+
+       value &= ~PLLE_SS_CNTL_SSCBYP;
+       value &= ~PLLE_SS_CNTL_INTERP_RESET;
+       value &= ~PLLE_SS_CNTL_BYPASS_SS;
+
+       value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
+       value |= PLLE_SS_CNTL_SSCMAX(0x24);
+       writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+       return 0;
+}
index f6fe9a050f511c05b963af7dc7217ff8b01e16f0..51fef54d570e2ebc6fc510cbf86fdab7ed04c3fa 100644 (file)
                reg = <0x80000000 0x80000000>;
        };
 
+       pcie-controller@01003000 {
+               status = "okay";
+
+               avddio-pex-supply = <&vdd_1v05_run>;
+               dvddio-pex-supply = <&vdd_1v05_run>;
+               avdd-pex-pll-supply = <&vdd_1v05_run>;
+               hvdd-pex-supply = <&vdd_3v3_lp0>;
+               hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>;
+               vddio-pex-ctl-supply = <&vdd_3v3_lp0>;
+               avdd-pll-erefe-supply = <&avdd_1v05_run>;
+
+               pci@1,0 {
+                       status = "okay";
+               };
+
+               pci@2,0 {
+                       status = "okay";
+               };
+       };
+
        i2c@7000c000 {
                status = "okay";
                clock-frequency = <100000>;
                clock-frequency = <100000>;
        };
 
+       /* Expansion PWR_I2C_*, on-board components */
        i2c@7000d000 {
                status = "okay";
                clock-frequency = <400000>;
+
+               pmic: pmic@40 {
+                       compatible = "ams,as3722";
+                       reg = <0x40>;
+                       interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+
+                       ams,system-power-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&as3722_default>;
+
+                       as3722_default: pinmux {
+                               gpio0 {
+                                       pins = "gpio0";
+                                       function = "gpio";
+                                       bias-pull-down;
+                               };
+
+                               gpio1_2_4_7 {
+                                       pins = "gpio1", "gpio2", "gpio4", "gpio7";
+                                       function = "gpio";
+                                       bias-pull-up;
+                               };
+
+                               gpio3_5_6 {
+                                       pins = "gpio3", "gpio5", "gpio6";
+                                       bias-high-impedance;
+                               };
+                       };
+
+                       regulators {
+                               vsup-sd2-supply = <&vdd_5v0_sys>;
+                               vsup-sd3-supply = <&vdd_5v0_sys>;
+                               vsup-sd4-supply = <&vdd_5v0_sys>;
+                               vsup-sd5-supply = <&vdd_5v0_sys>;
+                               vin-ldo0-supply = <&vdd_1v35_lp0>;
+                               vin-ldo1-6-supply = <&vdd_3v3_run>;
+                               vin-ldo2-5-7-supply = <&vddio_1v8>;
+                               vin-ldo3-4-supply = <&vdd_3v3_sys>;
+                               vin-ldo9-10-supply = <&vdd_5v0_sys>;
+                               vin-ldo11-supply = <&vdd_3v3_run>;
+
+                               sd0 {
+                                       regulator-name = "+VDD_CPU_AP";
+                                       regulator-min-microvolt = <700000>;
+                                       regulator-max-microvolt = <1400000>;
+                                       regulator-min-microamp = <3500000>;
+                                       regulator-max-microamp = <3500000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       ams,ext-control = <2>;
+                               };
+
+                               sd1 {
+                                       regulator-name = "+VDD_CORE";
+                                       regulator-min-microvolt = <700000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-min-microamp = <2500000>;
+                                       regulator-max-microamp = <2500000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       ams,ext-control = <1>;
+                               };
+
+                               vdd_1v35_lp0: sd2 {
+                                       regulator-name = "+1.35V_LP0(sd2)";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               sd3 {
+                                       regulator-name = "+1.35V_LP0(sd3)";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               vdd_1v05_run: sd4 {
+                                       regulator-name = "+1.05V_RUN";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               vddio_1v8: sd5 {
+                                       regulator-name = "+1.8V_VDDIO";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                               };
+
+                               vdd_gpu: sd6 {
+                                       regulator-name = "+VDD_GPU_AP";
+                                       regulator-min-microvolt = <650000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-min-microamp = <3500000>;
+                                       regulator-max-microamp = <3500000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                               };
+
+                               avdd_1v05_run: ldo0 {
+                                       regulator-name = "+1.05V_RUN_AVDD";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                                       ams,ext-control = <1>;
+                               };
+
+                               ldo1 {
+                                       regulator-name = "+1.8V_RUN_CAM";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                               };
+
+                               ldo2 {
+                                       regulator-name = "+1.2V_GEN_AVDD";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                               };
+
+                               ldo3 {
+                                       regulator-name = "+1.05V_LP0_VDD_RTC";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                                       ams,enable-tracking;
+                               };
+
+                               ldo4 {
+                                       regulator-name = "+2.8V_RUN_CAM";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                               };
+
+                               ldo5 {
+                                       regulator-name = "+1.2V_RUN_CAM_FRONT";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                               };
+
+                               vddio_sdmmc3: ldo6 {
+                                       regulator-name = "+VDDIO_SDMMC3";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <3300000>;
+                               };
+
+                               ldo7 {
+                                       regulator-name = "+1.05V_RUN_CAM_REAR";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               ldo9 {
+                                       regulator-name = "+3.3V_RUN_TOUCH";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                               };
+
+                               ldo10 {
+                                       regulator-name = "+2.8V_RUN_CAM_AF";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                               };
+
+                               ldo11 {
+                                       regulator-name = "+1.8V_RUN_VPP_FUSE";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                               };
+                       };
+               };
        };
 
        i2c@7000d100 {
                spi-max-frequency = <25000000>;
        };
 
+       padctl@7009f000 {
+               pinctrl-0 = <&padctl_default>;
+               pinctrl-names = "default";
+
+               padctl_default: pinmux {
+                       usb3 {
+                               nvidia,lanes = "pcie-0", "pcie-1";
+                               nvidia,function = "usb3";
+                               nvidia,iddq = <0>;
+                       };
+
+                       pcie {
+                               nvidia,lanes = "pcie-2", "pcie-3",
+                                              "pcie-4";
+                               nvidia,function = "pcie";
+                               nvidia,iddq = <0>;
+                       };
+
+                       sata {
+                               nvidia,lanes = "sata-0";
+                               nvidia,function = "sata";
+                               nvidia,iddq = <0>;
+                       };
+               };
+       };
+
        sdhci@700b0400 {
                status = "okay";
                cd-gpios = <&gpio 170 1>; /* gpio PV2 */
                status = "okay";
                nvidia,vbus-gpio = <&gpio 109 0>; /* gpio PN5, USB_VBUS_EN1 */
        };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vdd_mux: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "+VDD_MUX";
+                       regulator-min-microvolt = <12000000>;
+                       regulator-max-microvolt = <12000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               vdd_5v0_sys: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "+5V_SYS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       vin-supply = <&vdd_mux>;
+               };
+
+               vdd_3v3_sys: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "+3.3V_SYS";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       vin-supply = <&vdd_mux>;
+               };
+
+               vdd_3v3_run: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "+3.3V_RUN";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_3v3_sys>;
+               };
+
+               vdd_3v3_hdmi: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "+3.3V_AVDD_HDMI_AP_GATED";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       vin-supply = <&vdd_3v3_run>;
+               };
+
+               vdd_usb1_vbus: regulator@7 {
+                       compatible = "regulator-fixed";
+                       reg = <7>;
+                       regulator-name = "+USB0_VBUS_SW";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_usb3_vbus: regulator@8 {
+                       compatible = "regulator-fixed";
+                       reg = <8>;
+                       regulator-name = "+5V_USB_HS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_3v3_lp0: regulator@10 {
+                       compatible = "regulator-fixed";
+                       reg = <10>;
+                       regulator-name = "+3.3V_LP0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&pmic 2 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_3v3_sys>;
+               };
+
+               vdd_hdmi_pll: regulator@11 {
+                       compatible = "regulator-fixed";
+                       reg = <11>;
+                       regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL";
+                       regulator-min-microvolt = <1050000>;
+                       regulator-max-microvolt = <1050000>;
+                       gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>;
+                       vin-supply = <&vdd_1v05_run>;
+               };
+
+               vdd_5v0_hdmi: regulator@12 {
+                       compatible = "regulator-fixed";
+                       reg = <12>;
+                       regulator-name = "+5V_HDMI_CON";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               /* Molex power connector */
+               vdd_5v0_sata: regulator@13 {
+                       compatible = "regulator-fixed";
+                       reg = <13>;
+                       regulator-name = "+5V_SATA";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio TEGRA_GPIO(EE, 2) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_12v0_sata: regulator@14 {
+                       compatible = "regulator-fixed";
+                       reg = <14>;
+                       regulator-name = "+12V_SATA";
+                       regulator-min-microvolt = <12000000>;
+                       regulator-max-microvolt = <12000000>;
+                       gpio = <&gpio TEGRA_GPIO(EE, 2) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_mux>;
+               };
+       };
 };
index 6b5c2bea63da610c00a655b9cca9d104f1eadb78..9fa141d8fe783fe42eeb538ec1cfb354f346800a 100644 (file)
@@ -2,11 +2,91 @@
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 
 #include "skeleton.dtsi"
 
 / {
        compatible = "nvidia,tegra124";
+       interrupt-parent = <&gic>;
+
+       pcie-controller@01003000 {
+               compatible = "nvidia,tegra124-pcie";
+               device_type = "pci";
+               reg = <0x01003000 0x00000800   /* PADS registers */
+                      0x01003800 0x00000800   /* AFI registers */
+                      0x02000000 0x10000000>; /* configuration space */
+               reg-names = "pads", "afi", "cs";
+               interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
+                            <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+               interrupt-names = "intr", "msi";
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+               bus-range = <0x00 0xff>;
+               #address-cells = <3>;
+               #size-cells = <2>;
+
+               ranges = <0x82000000 0 0x01000000 0x01000000 0 0x00001000   /* port 0 configuration space */
+                         0x82000000 0 0x01001000 0x01001000 0 0x00001000   /* port 1 configuration space */
+                         0x81000000 0 0x0        0x12000000 0 0x00010000   /* downstream I/O (64 KiB) */
+                         0x82000000 0 0x13000000 0x13000000 0 0x0d000000   /* non-prefetchable memory (208 MiB) */
+                         0xc2000000 0 0x20000000 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */
+
+               clocks = <&tegra_car TEGRA124_CLK_PCIE>,
+                        <&tegra_car TEGRA124_CLK_AFI>,
+                        <&tegra_car TEGRA124_CLK_PLL_E>,
+                        <&tegra_car TEGRA124_CLK_CML0>;
+               clock-names = "pex", "afi", "pll_e", "cml";
+               resets = <&tegra_car 70>,
+                        <&tegra_car 72>,
+                        <&tegra_car 74>;
+               reset-names = "pex", "afi", "pcie_x";
+               status = "disabled";
+
+               phys = <&padctl TEGRA_XUSB_PADCTL_PCIE>;
+               phy-names = "pcie";
+
+               pci@1,0 {
+                       device_type = "pci";
+                       assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>;
+                       reg = <0x000800 0 0 0 0>;
+                       status = "disabled";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       nvidia,num-lanes = <2>;
+               };
+
+               pci@2,0 {
+                       device_type = "pci";
+                       assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>;
+                       reg = <0x001000 0 0 0 0>;
+                       status = "disabled";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       nvidia,num-lanes = <1>;
+               };
+       };
+
+       gic: interrupt-controller@50041000 {
+               compatible = "arm,cortex-a15-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x50041000 0x1000>,
+                     <0x50042000 0x2000>,
+                     <0x50044000 0x2000>,
+                     <0x50046000 0x2000>;
+               interrupts = <GIC_PPI 9
+                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
 
        tegra_car: clock@60006000 {
                compatible = "nvidia,tegra124-car";
                clocks = <&tegra_car 105>;
        };
 
+       padctl: padctl@7009f000 {
+               compatible = "nvidia,tegra124-xusb-padctl";
+               reg = <0x7009f000 0x1000>;
+               resets = <&tegra_car 142>;
+               reset-names = "padctl";
+
+               #phy-cells = <1>;
+       };
+
        sdhci@700b0000 {
                compatible = "nvidia,tegra124-sdhci";
                reg = <0x700b0000 0x200>;
index 74e8a16280bd85afa150c77ef52861e734272d46..1637cbd58e32ec4e6f7a4eaf526b348d2fc64f45 100644 (file)
                status = "disabled";
        };
 
+       pcie-controller@80003000 {
+               status = "okay";
+
+               avdd-pex-supply = <&pci_vdd_reg>;
+               vdd-pex-supply = <&pci_vdd_reg>;
+               avdd-pex-pll-supply = <&pci_vdd_reg>;
+               avdd-plle-supply = <&pci_vdd_reg>;
+               vddio-pex-clk-supply = <&pci_clk_reg>;
+
+               pci@1,0 {
+                       status = "okay";
+               };
+       };
+
        usb@c5000000 {
                nvidia,vbus-gpio = <&gpio 170 0>; /* PV2 */
        };
                wp-gpios = <&gpio 122 0>; /* gpio PP2 */
                bus-width = <4>;
        };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               hdmi_vdd_reg: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "avdd_hdmi";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               hdmi_pll_reg: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "avdd_hdmi_pll";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-always-on;
+               };
+
+               vbus_reg: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "usb1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(V, 2) 0>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               pci_clk_reg: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "pci_clk";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               pci_vdd_reg: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "pci_vdd";
+                       regulator-min-microvolt = <1050000>;
+                       regulator-max-microvolt = <1050000>;
+                       regulator-always-on;
+               };
+       };
+
 };
index 5f927f7e0d4e165babc6b0972140f196a025c60b..b8c8a923017e081dc43f5f8ba7c0b9a70088b059 100644 (file)
                reg = <0x7000f400 0x200>;
        };
 
+       pcie-controller@80003000 {
+               compatible = "nvidia,tegra20-pcie";
+               device_type = "pci";
+               reg = <0x80003000 0x00000800   /* PADS registers */
+                      0x80003800 0x00000200   /* AFI registers */
+                      0x90000000 0x10000000>; /* configuration space */
+               reg-names = "pads", "afi", "cs";
+               interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH   /* controller interrupt */
+                             GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+               interrupt-names = "intr", "msi";
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+               bus-range = <0x00 0xff>;
+               #address-cells = <3>;
+               #size-cells = <2>;
+
+               ranges = <0x82000000 0 0x80000000 0x80000000 0 0x00001000   /* port 0 registers */
+                         0x82000000 0 0x80001000 0x80001000 0 0x00001000   /* port 1 registers */
+                         0x81000000 0 0          0x82000000 0 0x00010000   /* downstream I/O */
+                         0x82000000 0 0xa0000000 0xa0000000 0 0x08000000   /* non-prefetchable memory */
+                         0xc2000000 0 0xa8000000 0xa8000000 0 0x18000000>; /* prefetchable memory */
+
+               clocks = <&tegra_car TEGRA20_CLK_PEX>,
+                        <&tegra_car TEGRA20_CLK_AFI>,
+                        <&tegra_car TEGRA20_CLK_PCIE_XCLK>,
+                        <&tegra_car TEGRA20_CLK_PLL_E>;
+               clock-names = "pex", "afi", "pcie_xclk", "pll_e";
+               status = "disabled";
+
+               pci@1,0 {
+                       device_type = "pci";
+                       assigned-addresses = <0x82000800 0 0x80000000 0 0x1000>;
+                       reg = <0x000800 0 0 0 0>;
+                       status = "disabled";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       nvidia,num-lanes = <2>;
+               };
+
+               pci@2,0 {
+                       device_type = "pci";
+                       assigned-addresses = <0x82001000 0 0x80001000 0 0x1000>;
+                       reg = <0x001000 0 0 0 0>;
+                       status = "disabled";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       nvidia,num-lanes = <2>;
+               };
+       };
+
        usb@c5000000 {
                compatible = "nvidia,tegra20-ehci", "usb-ehci";
                reg = <0xc5000000 0x4000>;
index 9acd84d80296fa367f6e1196051cf9f9b200497c..5903af68384b80f6c0f8373a6e3a1b8b420e69fa 100644 (file)
                reg = <0x80000000 0x7ff00000>;
        };
 
+       pcie-controller@00003000 {
+               status = "okay";
+
+               avdd-pexa-supply = <&ldo1_reg>;
+               vdd-pexa-supply = <&ldo1_reg>;
+               avdd-pexb-supply = <&ldo1_reg>;
+               vdd-pexb-supply = <&ldo1_reg>;
+               avdd-pex-pll-supply = <&ldo1_reg>;
+               avdd-plle-supply = <&ldo1_reg>;
+               vddio-pex-ctl-supply = <&sys_3v3_reg>;
+               hvdd-pex-supply = <&sys_3v3_pexs_reg>;
+
+               pci@1,0 {
+                       status = "okay";
+                       nvidia,num-lanes = <2>;
+               };
+
+               pci@2,0 {
+                       nvidia,num-lanes = <2>;
+               };
+
+               pci@3,0 {
+                       status = "okay";
+                       nvidia,num-lanes = <2>;
+               };
+       };
+
        i2c@7000c000 {
                status = "okay";
                clock-frequency = <100000>;
        i2c@7000d000 {
                status = "okay";
                clock-frequency = <100000>;
+
+               pmic: tps65911@2d {
+                       compatible = "ti,tps65911";
+                       reg = <0x2d>;
+
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+
+                       ti,system-power-controller;
+
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       vcc1-supply = <&vdd_5v_in_reg>;
+                       vcc2-supply = <&vdd_5v_in_reg>;
+                       vcc3-supply = <&vio_reg>;
+                       vcc4-supply = <&vdd_5v_in_reg>;
+                       vcc5-supply = <&vdd_5v_in_reg>;
+                       vcc6-supply = <&vdd2_reg>;
+                       vcc7-supply = <&vdd_5v_in_reg>;
+                       vccio-supply = <&vdd_5v_in_reg>;
+
+                       regulators {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               vdd1_reg: vdd1 {
+                                       regulator-name = "vddio_ddr_1v2";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               vdd2_reg: vdd2 {
+                                       regulator-name = "vdd_1v5_gen";
+                                       regulator-min-microvolt = <1500000>;
+                                       regulator-max-microvolt = <1500000>;
+                                       regulator-always-on;
+                               };
+
+                               vddctrl_reg: vddctrl {
+                                       regulator-name = "vdd_cpu,vdd_sys";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+
+                               vio_reg: vio {
+                                       regulator-name = "vdd_1v8_gen";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo1_reg: ldo1 {
+                                       regulator-name = "vdd_pexa,vdd_pexb";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               ldo2_reg: ldo2 {
+                                       regulator-name = "vdd_sata,avdd_plle";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               /* LDO3 is not connected to anything */
+
+                               ldo4_reg: ldo4 {
+                                       regulator-name = "vdd_rtc";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo5_reg: ldo5 {
+                                       regulator-name = "vddio_sdmmc,avdd_vdac";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo6_reg: ldo6 {
+                                       regulator-name = "avdd_dsi_csi,pwrdet_mipi";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                               };
+
+                               ldo7_reg: ldo7 {
+                                       regulator-name = "vdd_pllm,x,u,a_p_c_s";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo8_reg: ldo8 {
+                                       regulator-name = "vdd_ddr_hs";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+                       };
+               };
        };
 
        spi@7000da00 {
                nvidia,vbus-gpio = <&gpio 236 0>; /* PDD4 */
                status = "okay";
        };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vdd_5v_in_reg: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "vdd_5v_in";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               chargepump_5v_reg: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "chargepump_5v";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       enable-active-high;
+                       gpio = <&pmic 0 GPIO_ACTIVE_HIGH>;
+               };
+
+               ddr_reg: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "vdd_ddr";
+                       regulator-min-microvolt = <1500000>;
+                       regulator-max-microvolt = <1500000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&pmic 7 GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&vdd_5v_in_reg>;
+               };
+
+               vdd_5v_sata_reg: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "vdd_5v_sata";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(D, 6) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&vdd_5v_in_reg>;
+               };
+
+               usb1_vbus_reg: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "usb1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(DD, 6) GPIO_ACTIVE_HIGH>;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v_in_reg>;
+               };
+
+               usb3_vbus_reg: regulator@5 {
+                       compatible = "regulator-fixed";
+                       reg = <5>;
+                       regulator-name = "usb3_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v_in_reg>;
+               };
+
+               sys_3v3_reg: regulator@6 {
+                       compatible = "regulator-fixed";
+                       reg = <6>;
+                       regulator-name = "sys_3v3,vdd_3v3_alw";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&pmic 6 GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&vdd_5v_in_reg>;
+               };
+
+               sys_3v3_pexs_reg: regulator@7 {
+                       compatible = "regulator-fixed";
+                       reg = <7>;
+                       regulator-name = "sys_3v3_pexs";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(L, 7) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_5v0_hdmi: regulator@8 {
+                       compatible = "regulator-fixed";
+                       reg = <8>;
+                       regulator-name = "+VDD_5V_HDMI";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+       };
 };
index 1b8ed737e049707f0cec91f491bdb2e84e3099f0..e13d0fb467137766fcfe5677ca1cf64d889a82de 100644 (file)
                reg = <0x80000000 0x40000000>;
        };
 
+       pcie-controller@00003000 {
+               status = "okay";
+
+               /* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
+               avdd-pexb-supply = <&ldo1_reg>;
+               vdd-pexb-supply = <&ldo1_reg>;
+               avdd-pex-pll-supply = <&ldo1_reg>;
+               hvdd-pex-supply = <&pex_hvdd_3v3_reg>;
+               vddio-pex-ctl-supply = <&sys_3v3_reg>;
+               avdd-plle-supply = <&ldo2_reg>;
+
+               pci@1,0 {
+                       nvidia,num-lanes = <4>;
+               };
+
+               pci@2,0 {
+                       nvidia,num-lanes = <1>;
+               };
+
+               pci@3,0 {
+                       status = "okay";
+                       nvidia,num-lanes = <1>;
+               };
+       };
+
        i2c@7000c000 {
                status = "okay";
                clock-frequency = <100000>;
        i2c@7000d000 {
                status = "okay";
                clock-frequency = <100000>;
+
+               pmic: tps65911@2d {
+                       compatible = "ti,tps65911";
+                       reg = <0x2d>;
+
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+
+                       ti,system-power-controller;
+
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       vcc1-supply = <&vdd_ac_bat_reg>;
+                       vcc2-supply = <&vdd_ac_bat_reg>;
+                       vcc3-supply = <&vio_reg>;
+                       vcc4-supply = <&vdd_5v0_reg>;
+                       vcc5-supply = <&vdd_ac_bat_reg>;
+                       vcc6-supply = <&vdd2_reg>;
+                       vcc7-supply = <&vdd_ac_bat_reg>;
+                       vccio-supply = <&vdd_ac_bat_reg>;
+
+                       regulators {
+                               vdd1_reg: vdd1 {
+                                       regulator-name = "vddio_ddr_1v2";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               vdd2_reg: vdd2 {
+                                       regulator-name = "vdd_1v5_gen";
+                                       regulator-min-microvolt = <1500000>;
+                                       regulator-max-microvolt = <1500000>;
+                                       regulator-always-on;
+                               };
+
+                               vddctrl_reg: vddctrl {
+                                       regulator-name = "vdd_cpu,vdd_sys";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+
+                               vio_reg: vio {
+                                       regulator-name = "vdd_1v8_gen";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo1_reg: ldo1 {
+                                       regulator-name = "vdd_pexa,vdd_pexb";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               ldo2_reg: ldo2 {
+                                       regulator-name = "vdd_sata,avdd_plle";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               /* LDO3 is not connected to anything */
+
+                               ldo4_reg: ldo4 {
+                                       regulator-name = "vdd_rtc";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo5_reg: ldo5 {
+                                       regulator-name = "vddio_sdmmc,avdd_vdac";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo6_reg: ldo6 {
+                                       regulator-name = "avdd_dsi_csi,pwrdet_mipi";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                               };
+
+                               ldo7_reg: ldo7 {
+                                       regulator-name = "vdd_pllm,x,u,a_p_c_s";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo8_reg: ldo8 {
+                                       regulator-name = "vdd_ddr_hs";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+                       };
+               };
        };
 
        spi@7000da00 {
                nvidia,vbus-gpio = <&gpio 236 0>;       /* PDD4 */
                status = "okay";
        };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vdd_ac_bat_reg: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "vdd_ac_bat";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               cam_1v8_reg: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "cam_1v8";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(BB, 4) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&vio_reg>;
+               };
+
+               cp_5v_reg: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "cp_5v";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       enable-active-high;
+                       gpio = <&pmic 0 GPIO_ACTIVE_HIGH>;
+               };
+
+               emmc_3v3_reg: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "emmc_3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(D, 1) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               modem_3v3_reg: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "modem_3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(D, 6) GPIO_ACTIVE_HIGH>;
+               };
+
+               pex_hvdd_3v3_reg: regulator@5 {
+                       compatible = "regulator-fixed";
+                       reg = <5>;
+                       regulator-name = "pex_hvdd_3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(L, 7) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_cam1_ldo_reg: regulator@6 {
+                       compatible = "regulator-fixed";
+                       reg = <6>;
+                       regulator-name = "vdd_cam1_ldo";
+                       regulator-min-microvolt = <2800000>;
+                       regulator-max-microvolt = <2800000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(R, 6) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_cam2_ldo_reg: regulator@7 {
+                       compatible = "regulator-fixed";
+                       reg = <7>;
+                       regulator-name = "vdd_cam2_ldo";
+                       regulator-min-microvolt = <2800000>;
+                       regulator-max-microvolt = <2800000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_cam3_ldo_reg: regulator@8 {
+                       compatible = "regulator-fixed";
+                       reg = <8>;
+                       regulator-name = "vdd_cam3_ldo";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(S, 0) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_com_reg: regulator@9 {
+                       compatible = "regulator-fixed";
+                       reg = <9>;
+                       regulator-name = "vdd_com";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_fuse_3v3_reg: regulator@10 {
+                       compatible = "regulator-fixed";
+                       reg = <10>;
+                       regulator-name = "vdd_fuse_3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(L, 6) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_pnl1_reg: regulator@11 {
+                       compatible = "regulator-fixed";
+                       reg = <11>;
+                       regulator-name = "vdd_pnl1";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(L, 4) GPIO_ACTIVE_HIGH>;
+                       vin-supply = <&sys_3v3_reg>;
+               };
+
+               vdd_vid_reg: regulator@12 {
+                       compatible = "regulator-fixed";
+                       reg = <12>;
+                       regulator-name = "vddio_vid";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(T, 0) GPIO_ACTIVE_HIGH>;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v0_reg>;
+               };
+
+               ddr_reg: regulator@100 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "ddr";
+                       reg = <100>;
+                       regulator-min-microvolt = <1500000>;
+                       regulator-max-microvolt = <1500000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&pmic 7 GPIO_ACTIVE_HIGH>;
+               };
+
+               sys_3v3_reg: regulator@101 {
+                       compatible = "regulator-fixed";
+                       reg = <101>;
+                       regulator-name = "sys_3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&pmic 6 GPIO_ACTIVE_HIGH>;
+               };
+
+               usb1_vbus_reg: regulator@102 {
+                       compatible = "regulator-fixed";
+                       reg = <102>;
+                       regulator-name = "usb1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(DD, 6) GPIO_ACTIVE_HIGH>;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v0_reg>;
+               };
+
+               usb3_vbus_reg: regulator@103 {
+                       compatible = "regulator-fixed";
+                       reg = <103>;
+                       regulator-name = "usb3_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v0_reg>;
+               };
+
+               vdd_5v0_reg: regulator@104 {
+                       compatible = "regulator-fixed";
+                       reg = <104>;
+                       regulator-name = "5v0";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       gpio = <&pmic 8 GPIO_ACTIVE_HIGH>;
+               };
+
+               vdd_bl_reg: regulator@105 {
+                       compatible = "regulator-fixed";
+                       reg = <105>;
+                       regulator-name = "vdd_bl";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(DD, 2) GPIO_ACTIVE_HIGH>;
+               };
+
+               vdd_bl2_reg: regulator@106 {
+                       compatible = "regulator-fixed";
+                       reg = <106>;
+                       regulator-name = "vdd_bl2";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       enable-active-high;
+                       gpio = <&gpio TEGRA_GPIO(DD, 0) GPIO_ACTIVE_HIGH>;
+               };
+       };
 };
index 572520a00ec5e330d5bbacd4b187967d45db8ec8..37b6abd52f05480018af45c46458b56aa4fd664f 100644 (file)
                reg = <0x80000000 0x40000000>;
        };
 
-       /* GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier
-          board) */
+       /*
+        * GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier
+        * board)
+        */
        i2c@7000c000 {
                status = "okay";
                clock-frequency = <100000>;
                clock-frequency = <100000>;
        };
 
-       /* PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
-          touch screen controller */
+       /*
+        * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
+        * touch screen controller
+        */
        i2c@7000d000 {
                status = "okay";
                clock-frequency = <100000>;
index fb92a0fef96e0e5c4cfdf5c6f22de68af93ef33c..5ea7e347f3fad4c8acfc6ffc58432659e8093577 100644 (file)
@@ -6,6 +6,89 @@
 
 / {
        compatible = "nvidia,tegra30";
+       interrupt-parent = <&intc>;
+
+       intc: interrupt-controller@50041000 {
+               compatible = "arm,cortex-a9-gic";
+               reg = <0x50041000 0x1000
+                      0x50040100 0x0100>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+       };
+
+       pcie-controller@00003000 {
+               compatible = "nvidia,tegra30-pcie";
+               device_type = "pci";
+               reg = <0x00003000 0x00000800   /* PADS registers */
+                      0x00003800 0x00000200   /* AFI registers */
+                      0x10000000 0x10000000>; /* configuration space */
+               reg-names = "pads", "afi", "cs";
+               interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH   /* controller interrupt */
+                             GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+               interrupt-names = "intr", "msi";
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+               bus-range = <0x00 0xff>;
+               #address-cells = <3>;
+               #size-cells = <2>;
+
+               ranges = <0x82000000 0 0x00000000 0x00000000 0 0x00001000   /* port 0 configuration space */
+                         0x82000000 0 0x00001000 0x00001000 0 0x00001000   /* port 1 configuration space */
+                         0x82000000 0 0x00004000 0x00004000 0 0x00001000   /* port 2 configuration space */
+                         0x81000000 0 0          0x02000000 0 0x00010000   /* downstream I/O */
+                         0x82000000 0 0x20000000 0x20000000 0 0x10000000   /* non-prefetchable memory */
+                         0xc2000000 0 0x30000000 0x30000000 0 0x10000000>; /* prefetchable memory */
+
+               clocks = <&tegra_car TEGRA30_CLK_PCIE>,
+                        <&tegra_car TEGRA30_CLK_AFI>,
+                        <&tegra_car TEGRA30_CLK_PCIEX>,
+                        <&tegra_car TEGRA30_CLK_PLL_E>,
+                        <&tegra_car TEGRA30_CLK_CML0>;
+               clock-names = "pex", "afi", "pcie_xclk", "pll_e", "cml";
+               status = "disabled";
+
+               pci@1,0 {
+                       device_type = "pci";
+                       assigned-addresses = <0x82000800 0 0x00000000 0 0x1000>;
+                       reg = <0x000800 0 0 0 0>;
+                       status = "disabled";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       nvidia,num-lanes = <2>;
+               };
+
+               pci@2,0 {
+                       device_type = "pci";
+                       assigned-addresses = <0x82001000 0 0x00001000 0 0x1000>;
+                       reg = <0x001000 0 0 0 0>;
+                       status = "disabled";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       nvidia,num-lanes = <2>;
+               };
+
+               pci@3,0 {
+                       device_type = "pci";
+                       assigned-addresses = <0x82001800 0 0x00004000 0 0x1000>;
+                       reg = <0x001800 0 0 0 0>;
+                       status = "disabled";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       nvidia,num-lanes = <2>;
+               };
+       };
 
        tegra_car: clock {
                compatible = "nvidia,tegra30-car";
diff --git a/arch/arm/include/asm/arch-tegra/powergate.h b/arch/arm/include/asm/arch-tegra/powergate.h
new file mode 100644 (file)
index 0000000..130b58b
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _TEGRA_POWERGATE_H_
+#define _TEGRA_POWERGATE_H_
+
+#include <asm/arch/clock.h>
+
+enum tegra_powergate {
+       TEGRA_POWERGATE_CPU,
+       TEGRA_POWERGATE_3D,
+       TEGRA_POWERGATE_VENC,
+       TEGRA_POWERGATE_PCIE,
+       TEGRA_POWERGATE_VDEC,
+       TEGRA_POWERGATE_L2,
+       TEGRA_POWERGATE_MPE,
+       TEGRA_POWERGATE_HEG,
+       TEGRA_POWERGATE_SATA,
+       TEGRA_POWERGATE_CPU1,
+       TEGRA_POWERGATE_CPU2,
+       TEGRA_POWERGATE_CPU3,
+       TEGRA_POWERGATE_CELP,
+       TEGRA_POWERGATE_3D1,
+       TEGRA_POWERGATE_CPU0,
+       TEGRA_POWERGATE_C0NC,
+       TEGRA_POWERGATE_C1NC,
+       TEGRA_POWERGATE_SOR,
+       TEGRA_POWERGATE_DIS,
+       TEGRA_POWERGATE_DISB,
+       TEGRA_POWERGATE_XUSBA,
+       TEGRA_POWERGATE_XUSBB,
+       TEGRA_POWERGATE_XUSBC,
+       TEGRA_POWERGATE_VIC,
+       TEGRA_POWERGATE_IRAM,
+};
+
+int tegra_powergate_sequence_power_up(enum tegra_powergate id,
+                                     enum periph_id periph);
+int tegra_powergate_power_off(enum tegra_powergate id);
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra/xusb-padctl.h b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
new file mode 100644 (file)
index 0000000..b4b4c8b
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _TEGRA_XUSB_PADCTL_H_
+#define _TEGRA_XUSB_PADCTL_H_
+
+struct tegra_xusb_phy;
+
+/**
+ * tegra_xusb_phy_get() - obtain a reference to a specified padctl PHY
+ * @type: the type of PHY to obtain
+ *
+ * The type of PHY varies between SoC generations. Typically there are XUSB,
+ * PCIe and SATA PHYs, though not all generations support all of them. The
+ * value of type can usually be directly parsed from a device tree.
+ *
+ * Return: a pointer to the PHY or NULL if no such PHY exists
+ */
+struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type);
+
+void tegra_xusb_padctl_init(const void *fdt);
+int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy);
+int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy);
+int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy);
+int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy);
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra114/powergate.h b/arch/arm/include/asm/arch-tegra114/powergate.h
new file mode 100644 (file)
index 0000000..260ea80
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _TEGRA114_POWERGATE_H_
+#define _TEGRA114_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA114_POWERGATE_H_ */
index 8e39d21a7b5e96390f5c892166452aaf115b0dd6..8e650862529e4046227753c4db3548b5c2fc441c 100644 (file)
@@ -16,4 +16,6 @@
 #define OSC_FREQ_SHIFT          28
 #define OSC_FREQ_MASK           (0xF << OSC_FREQ_SHIFT)
 
+int tegra_plle_enable(void);
+
 #endif /* _TEGRA124_CLOCK_H_ */
diff --git a/arch/arm/include/asm/arch-tegra124/powergate.h b/arch/arm/include/asm/arch-tegra124/powergate.h
new file mode 100644 (file)
index 0000000..8a0cfba
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _TEGRA124_POWERGATE_H_
+#define _TEGRA124_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA124_POWERGATE_H_ */
index a09cb01978637e27b486aeca53673238fe8bf097..894be088cde2dcfae35d7593d864491cfd90b86f 100644 (file)
@@ -131,7 +131,7 @@ enum periph_id {
        /* 72 */
        PERIPH_ID_AFI,
        PERIPH_ID_CORESIGHT,
-       PERIPH_ID_RESERVED74,
+       PERIPH_ID_PCIEXCLK,
        PERIPH_ID_AVPUCQ,
        PERIPH_ID_RESERVED76,
        PERIPH_ID_RESERVED77,
index 889c65a16f1f47446813a933179900a47c3c873c..4df8da96e2a3e6f7899aa5eb5e58be91fc760962 100644 (file)
@@ -15,4 +15,6 @@
 #define OSC_FREQ_SHIFT          30
 #define OSC_FREQ_MASK           (3U << OSC_FREQ_SHIFT)
 
+int tegra_plle_enable(void);
+
 #endif /* _TEGRA20_CLOCK_H */
diff --git a/arch/arm/include/asm/arch-tegra20/powergate.h b/arch/arm/include/asm/arch-tegra20/powergate.h
new file mode 100644 (file)
index 0000000..439d88b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _TEGRA20_POWERGATE_H_
+#define _TEGRA20_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA20_POWERGATE_H_ */
index 2f24a75cc4c324dae76975523b46d8fa1e16f257..410c35289978f28b970745182d832e106bfd752c 100644 (file)
@@ -25,4 +25,6 @@
 #define OSC_FREQ_SHIFT          28
 #define OSC_FREQ_MASK           (0xF << OSC_FREQ_SHIFT)
 
+int tegra_plle_enable(void);
+
 #endif /* _TEGRA30_CLOCK_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/powergate.h b/arch/arm/include/asm/arch-tegra30/powergate.h
new file mode 100644 (file)
index 0000000..c70e44b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _TEGRA30_POWERGATE_H_
+#define _TEGRA30_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA30_POWERGATE_H_ */
index 61e2914d44b44a1d3be2e92b74f52d6a2a765b12..89f22946895301b09a183ead75503ae4dff0f1b2 100644 (file)
@@ -212,6 +212,11 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
  */
 void mmu_page_table_flush(unsigned long start, unsigned long stop);
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+void noncached_init(void);
+phys_addr_t noncached_alloc(size_t size, size_t align);
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
index f1c0792ce8da0afcf1b17b68f6cd9b7547b07822..9cedeac6d641eb7b8548fb8571bcd6a261388fdb 100644 (file)
@@ -8,6 +8,7 @@
 /* for now: just dummy functions to satisfy the linker */
 
 #include <common.h>
+#include <malloc.h>
 
 __weak void flush_cache(unsigned long start, unsigned long size)
 {
@@ -49,3 +50,46 @@ __weak void enable_caches(void)
 {
        puts("WARNING: Caches not enabled\n");
 }
+
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+/*
+ * Reserve one MMU section worth of address space below the malloc() area that
+ * will be mapped uncached.
+ */
+static unsigned long noncached_start;
+static unsigned long noncached_end;
+static unsigned long noncached_next;
+
+void noncached_init(void)
+{
+       phys_addr_t start, end;
+       size_t size;
+
+       end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE;
+       size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
+       start = end - size;
+
+       debug("mapping memory %pa-%pa non-cached\n", &start, &end);
+
+       noncached_start = start;
+       noncached_end = end;
+       noncached_next = start;
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+       mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
+#endif
+}
+
+phys_addr_t noncached_alloc(size_t size, size_t align)
+{
+       phys_addr_t next = ALIGN(noncached_next, align);
+
+       if (next >= noncached_end || (noncached_end - next) < size)
+               return 0;
+
+       debug("allocated %zu bytes of uncached memory @%pa\n", size, &next);
+       noncached_next = next + size;
+
+       return next;
+}
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
index 723293fef35af7aa3f35588a7d54694da732d1ba..c9da80d5eb1c31cd55909cb7cf0da1e11cb7b17f 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/arch/pinmux.h>
 #include <asm/gpio.h>
 #include <i2c.h>
+#include <netdev.h>
 
 void pin_mux_usb(void)
 {
@@ -40,3 +41,10 @@ void pin_mux_mmc(void)
        /* For CD GPIO PP1 */
        pinmux_tristate_disable(PMUX_PINGRP_DAP3);
 }
+
+#ifdef CONFIG_PCI
+int board_eth_init(bd_t *bis)
+{
+       return pci_eth_init(bis);
+}
+#endif
index 026f45c6c686da054603d908989604f2fd78301b..95c4ff25092b7272860d1770c25d239ab27b50b0 100644 (file)
@@ -9,8 +9,11 @@
 #include <dm.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/gp_padctrl.h>
+#include <asm/arch/gpio.h>
+#include <asm/gpio.h>
 #include "pinmux-config-cardhu.h"
 #include <i2c.h>
+#include <netdev.h>
 
 #define PMU_I2C_ADDRESS                0x2D
 #define MAX_I2C_RETRY          3
@@ -83,3 +86,52 @@ void pin_mux_mmc(void)
        board_sdmmc_voltage_init();
 }
 #endif /* MMC */
+
+#ifdef CONFIG_PCI_TEGRA
+int tegra_pcie_board_init(void)
+{
+       struct udevice *dev;
+       u8 addr, data[1];
+       int err;
+
+       err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+       if (err) {
+               debug("failed to find PMU bus\n");
+               return err;
+       }
+
+       /* TPS659110: LDO1_REG = 1.05V, ACTIVE */
+       data[0] = 0x15;
+       addr = 0x30;
+
+       err = i2c_write(dev, addr, data, 1);
+       if (err) {
+               debug("failed to set VDD supply\n");
+               return err;
+       }
+
+       /* GPIO: PEX = 3.3V */
+       err = gpio_request(GPIO_PL7, "PEX");
+       if (err < 0)
+               return err;
+
+       gpio_direction_output(GPIO_PL7, 1);
+
+       /* TPS659110: LDO2_REG = 1.05V, ACTIVE */
+       data[0] = 0x15;
+       addr = 0x31;
+
+       err = i2c_write(dev, addr, data, 1);
+       if (err) {
+               debug("failed to set AVDD supply\n");
+               return err;
+       }
+
+       return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+       return pci_eth_init(bis);
+}
+#endif /* PCI */
index 4bdbf0194ab54f5df0921b3d70613a0fb634e39d..80ef8fdcb23baf885048ac90bded1d023c3328c9 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <asm/arch-tegra/mmc.h>
 #endif
+#include <asm/arch-tegra/xusb-padctl.h>
 #include <i2c.h>
 #include <spi.h>
 #include "emc.h"
@@ -137,6 +138,8 @@ int board_init(void)
        pin_mux_nand();
 #endif
 
+       tegra_xusb_padctl_init(gd->fdt_blob);
+
 #ifdef CONFIG_TEGRA_LP0
        /* save Sdram params to PMC 2, 4, and 24 for WB0 */
        warmboot_save_sdram_params();
index 5d37718f3b89e8b8109f30c8c8876be60179c1fb..daa74a4be02f029949803b6a3a21d435f4bb9e9c 100644 (file)
@@ -6,10 +6,16 @@
  */
 
 #include <common.h>
+#include <netdev.h>
+#include <power/as3722.h>
+
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
+
 #include "pinmux-config-jetson-tk1.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * Routine: pinmux_init
  * Description: Do individual peripheral pinmux configs
@@ -27,3 +33,49 @@ void pinmux_init(void)
        pinmux_config_drvgrp_table(jetson_tk1_drvgrps,
                                   ARRAY_SIZE(jetson_tk1_drvgrps));
 }
+
+#ifdef CONFIG_PCI_TEGRA
+int tegra_pcie_board_init(void)
+{
+       struct udevice *pmic;
+       int err;
+
+       err = as3722_init(&pmic);
+       if (err) {
+               error("failed to initialize AS3722 PMIC: %d\n", err);
+               return err;
+       }
+
+       err = as3722_sd_enable(pmic, 4);
+       if (err < 0) {
+               error("failed to enable SD4: %d\n", err);
+               return err;
+       }
+
+       err = as3722_sd_set_voltage(pmic, 4, 0x24);
+       if (err < 0) {
+               error("failed to set SD4 voltage: %d\n", err);
+               return err;
+       }
+
+       err = as3722_gpio_configure(pmic, 1, AS3722_GPIO_OUTPUT_VDDH |
+                                            AS3722_GPIO_INVERT);
+       if (err < 0) {
+               error("failed to configure GPIO#1 as output: %d\n", err);
+               return err;
+       }
+
+       err = as3722_gpio_direction_output(pmic, 2, 1);
+       if (err < 0) {
+               error("failed to set GPIO#2 high: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+       return pci_eth_init(bis);
+}
+#endif /* PCI */
index 4eb7a023d4eaf5e2c1bdfee9c48bf65b49fb7c9e..a301cc226f1e69fb4f6229382391c80218f12460 100644 (file)
@@ -265,6 +265,14 @@ static int initr_malloc(void)
        return 0;
 }
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+static int initr_noncached(void)
+{
+       noncached_init();
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_DM
 static int initr_dm(void)
 {
@@ -687,6 +695,9 @@ init_fnc_t init_sequence_r[] = {
 #endif
        initr_barrier,
        initr_malloc,
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+       initr_noncached,
+#endif
        bootstage_relocate,
 #ifdef CONFIG_DM
        initr_dm,
index c3ce17516c7407b0f189084bda4cbecb515122ac..cea6701203815e05f37d46040b3fb76d18bed5bf 100644 (file)
@@ -41,6 +41,7 @@
  * Modified to use le32_to_cpu and cpu_to_le32 properly
  */
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <net.h>
 #include <netdev.h>
@@ -79,7 +80,11 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 #define InterFrameGap  0x03    /* 3 means InterFrameGap = the shortest one */
 
 #define NUM_TX_DESC    1       /* Number of Tx descriptor registers */
-#define NUM_RX_DESC    4       /* Number of Rx descriptor registers */
+#ifdef CONFIG_SYS_RX_ETH_BUFFER
+  #define NUM_RX_DESC  CONFIG_SYS_RX_ETH_BUFFER
+#else
+  #define NUM_RX_DESC  4       /* Number of Rx descriptor registers */
+#endif
 #define RX_BUF_SIZE    1536    /* Rx Buffer size */
 #define RX_BUF_LEN     8192
 
@@ -248,6 +253,7 @@ static struct {
        {"RTL-8168b/8111sb",    0x38, 0xff7e1880,},
        {"RTL-8168d/8111d",     0x28, 0xff7e1880,},
        {"RTL-8168evl/8111evl", 0x2e, 0xff7e1880,},
+       {"RTL-8168/8111g",      0x4c, 0xff7e1880,},
        {"RTL-8101e",           0x34, 0xff7e1880,},
        {"RTL-8100e",           0x32, 0xff7e1880,},
 };
@@ -273,23 +279,40 @@ struct RxDesc {
        u32 buf_Haddr;
 };
 
-/* Define the TX Descriptor */
-static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256];
-/*     __attribute__ ((aligned(256))); */
+#define RTL8169_DESC_SIZE 16
 
-/* Create a static buffer of size RX_BUF_SZ for each
-TX Descriptor. All descriptors point to a
-part of this buffer */
-static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE];
+#if ARCH_DMA_MINALIGN > 256
+#  define RTL8169_ALIGN ARCH_DMA_MINALIGN
+#else
+#  define RTL8169_ALIGN 256
+#endif
 
-/* Define the RX Descriptor */
-static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256];
-  /*  __attribute__ ((aligned(256))); */
+/*
+ * Warn if the cache-line size is larger than the descriptor size. In such
+ * cases the driver will likely fail because the CPU needs to flush the cache
+ * when requeuing RX buffers, therefore descriptors written by the hardware
+ * may be discarded.
+ *
+ * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause
+ * the driver to allocate descriptors from a pool of non-cached memory.
+ */
+#if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
+#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && !defined(CONFIG_SYS_DCACHE_OFF)
+#warning cache-line size is larger than descriptor size
+#endif
+#endif
 
-/* Create a static buffer of size RX_BUF_SZ for each
-RX Descriptor  All descriptors point to a
-part of this buffer */
-static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
+/*
+ * Create a static buffer of size RX_BUF_SZ for each TX Descriptor. All
+ * descriptors point to a part of this buffer.
+ */
+DEFINE_ALIGN_BUFFER(u8, txb, NUM_TX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
+
+/*
+ * Create a static buffer of size RX_BUF_SZ for each RX Descriptor. All
+ * descriptors point to a part of this buffer.
+ */
+DEFINE_ALIGN_BUFFER(u8, rxb, NUM_RX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
 
 struct rtl8169_private {
        void *mmio_addr;        /* memory map physical address */
@@ -297,8 +320,6 @@ struct rtl8169_private {
        unsigned long cur_rx;   /* Index into the Rx descriptor buffer of next Rx pkt. */
        unsigned long cur_tx;   /* Index into the Tx descriptor buffer of next Rx pkt. */
        unsigned long dirty_tx;
-       unsigned char *TxDescArrays;    /* Index of Tx Descriptor buffer */
-       unsigned char *RxDescArrays;    /* Index of Rx Descriptor buffer */
        struct TxDesc *TxDescArray;     /* Index of 256-alignment Tx Descriptor buffer */
        struct RxDesc *RxDescArray;     /* Index of 256-alignment Rx Descriptor buffer */
        unsigned char *RxBufferRings;   /* Index of Rx Buffer  */
@@ -397,6 +418,35 @@ match:
        return 0;
 }
 
+/*
+ * TX and RX descriptors are 16 bytes. This causes problems with the cache
+ * maintenance on CPUs where the cache-line size exceeds the size of these
+ * descriptors. What will happen is that when the driver receives a packet
+ * it will be immediately requeued for the hardware to reuse. The CPU will
+ * therefore need to flush the cache-line containing the descriptor, which
+ * will cause all other descriptors in the same cache-line to be flushed
+ * along with it. If one of those descriptors had been written to by the
+ * device those changes (and the associated packet) will be lost.
+ *
+ * To work around this, we make use of non-cached memory if available. If
+ * descriptors are mapped uncached there's no need to manually flush them
+ * or invalidate them.
+ *
+ * Note that this only applies to descriptors. The packet data buffers do
+ * not have the same constraints since they are 1536 bytes large, so they
+ * are unlikely to share cache-lines.
+ */
+static void *rtl_alloc_descs(unsigned int num)
+{
+       size_t size = num * RTL8169_DESC_SIZE;
+
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+       return (void *)noncached_alloc(size, RTL8169_ALIGN);
+#else
+       return memalign(RTL8169_ALIGN, size);
+#endif
+}
+
 /*
  * Cache maintenance functions. These are simple wrappers around the more
  * general purpose flush_cache() and invalidate_dcache_range() functions.
@@ -404,28 +454,36 @@ match:
 
 static void rtl_inval_rx_desc(struct RxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
        unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
        unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
 
        invalidate_dcache_range(start, end);
+#endif
 }
 
 static void rtl_flush_rx_desc(struct RxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
        flush_cache((unsigned long)desc, sizeof(*desc));
+#endif
 }
 
 static void rtl_inval_tx_desc(struct TxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
        unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
        unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
 
        invalidate_dcache_range(start, end);
+#endif
 }
 
 static void rtl_flush_tx_desc(struct TxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
        flush_cache((unsigned long)desc, sizeof(*desc));
+#endif
 }
 
 static void rtl_inval_buffer(void *buf, size_t size)
@@ -707,16 +765,6 @@ static int rtl_reset(struct eth_device *dev, bd_t *bis)
        printf ("%s\n", __FUNCTION__);
 #endif
 
-       tpc->TxDescArrays = tx_ring;
-       /* Tx Desscriptor needs 256 bytes alignment; */
-       tpc->TxDescArray = (struct TxDesc *) ((unsigned long)(tpc->TxDescArrays +
-                                                             255) & ~255);
-
-       tpc->RxDescArrays = rx_ring;
-       /* Rx Desscriptor needs 256 bytes alignment; */
-       tpc->RxDescArray = (struct RxDesc *) ((unsigned long)(tpc->RxDescArrays +
-                                                             255) & ~255);
-
        rtl8169_init_ring(dev);
        rtl8169_hw_start(dev);
        /* Construct a perfect filter frame with the mac address as first match
@@ -758,10 +806,6 @@ static void rtl_halt(struct eth_device *dev)
 
        RTL_W32(RxMissed, 0);
 
-       tpc->TxDescArrays = NULL;
-       tpc->RxDescArrays = NULL;
-       tpc->TxDescArray = NULL;
-       tpc->RxDescArray = NULL;
        for (i = 0; i < NUM_RX_DESC; i++) {
                tpc->RxBufferRing[i] = NULL;
        }
@@ -906,7 +950,16 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 #endif
        }
 
-       return 1;
+
+       tpc->RxDescArray = rtl_alloc_descs(NUM_RX_DESC);
+       if (!tpc->RxDescArray)
+               return -ENOMEM;
+
+       tpc->TxDescArray = rtl_alloc_descs(NUM_TX_DESC);
+       if (!tpc->TxDescArray)
+               return -ENOMEM;
+
+       return 0;
 }
 
 int rtl8169_initialize(bd_t *bis)
@@ -920,6 +973,7 @@ int rtl8169_initialize(bd_t *bis)
        while(1){
                unsigned int region;
                u16 device;
+               int err;
 
                /* Find RTL8169 */
                if ((devno = pci_find_devices(supported, idx++)) < 0)
@@ -958,9 +1012,14 @@ int rtl8169_initialize(bd_t *bis)
                dev->send = rtl_send;
                dev->recv = rtl_recv;
 
-               eth_register (dev);
+               err = rtl_init(dev, bis);
+               if (err < 0) {
+                       printf(pr_fmt("failed to initialize card: %d\n"), err);
+                       free(dev);
+                       continue;
+               }
 
-               rtl_init(dev, bis);
+               eth_register (dev);
 
                card_number++;
        }
index 85e82bdb8c3dd385bb34b61c391e77c311b7775c..50b7be53cae82268bb561d1f8fcbba059d29831a 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_FTPCI100) += pci_ftpci100.o
 obj-$(CONFIG_SH4_PCI) += pci_sh4.o
 obj-$(CONFIG_SH7751_PCI) +=pci_sh7751.o
 obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o
+obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
 obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o
 obj-$(CONFIG_WINBOND_83C553) += w83c553f.o
 obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
new file mode 100644 (file)
index 0000000..a03ad5f
--- /dev/null
@@ -0,0 +1,1143 @@
+/*
+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * Copyright (c) 2013-2014, NVIDIA Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#define DEBUG
+#define pr_fmt(fmt) "tegra-pcie: " fmt
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <pci.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/powergate.h>
+#include <asm/arch-tegra/xusb-padctl.h>
+
+#include <linux/list.h>
+
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define AFI_AXI_BAR0_SZ        0x00
+#define AFI_AXI_BAR1_SZ        0x04
+#define AFI_AXI_BAR2_SZ        0x08
+#define AFI_AXI_BAR3_SZ        0x0c
+#define AFI_AXI_BAR4_SZ        0x10
+#define AFI_AXI_BAR5_SZ        0x14
+
+#define AFI_AXI_BAR0_START     0x18
+#define AFI_AXI_BAR1_START     0x1c
+#define AFI_AXI_BAR2_START     0x20
+#define AFI_AXI_BAR3_START     0x24
+#define AFI_AXI_BAR4_START     0x28
+#define AFI_AXI_BAR5_START     0x2c
+
+#define AFI_FPCI_BAR0  0x30
+#define AFI_FPCI_BAR1  0x34
+#define AFI_FPCI_BAR2  0x38
+#define AFI_FPCI_BAR3  0x3c
+#define AFI_FPCI_BAR4  0x40
+#define AFI_FPCI_BAR5  0x44
+
+#define AFI_CACHE_BAR0_SZ      0x48
+#define AFI_CACHE_BAR0_ST      0x4c
+#define AFI_CACHE_BAR1_SZ      0x50
+#define AFI_CACHE_BAR1_ST      0x54
+
+#define AFI_MSI_BAR_SZ         0x60
+#define AFI_MSI_FPCI_BAR_ST    0x64
+#define AFI_MSI_AXI_BAR_ST     0x68
+
+#define AFI_CONFIGURATION              0xac
+#define  AFI_CONFIGURATION_EN_FPCI     (1 << 0)
+
+#define AFI_FPCI_ERROR_MASKS   0xb0
+
+#define AFI_INTR_MASK          0xb4
+#define  AFI_INTR_MASK_INT_MASK        (1 << 0)
+#define  AFI_INTR_MASK_MSI_MASK        (1 << 8)
+
+#define AFI_SM_INTR_ENABLE     0xc4
+#define  AFI_SM_INTR_INTA_ASSERT       (1 << 0)
+#define  AFI_SM_INTR_INTB_ASSERT       (1 << 1)
+#define  AFI_SM_INTR_INTC_ASSERT       (1 << 2)
+#define  AFI_SM_INTR_INTD_ASSERT       (1 << 3)
+#define  AFI_SM_INTR_INTA_DEASSERT     (1 << 4)
+#define  AFI_SM_INTR_INTB_DEASSERT     (1 << 5)
+#define  AFI_SM_INTR_INTC_DEASSERT     (1 << 6)
+#define  AFI_SM_INTR_INTD_DEASSERT     (1 << 7)
+
+#define AFI_AFI_INTR_ENABLE            0xc8
+#define  AFI_INTR_EN_INI_SLVERR                (1 << 0)
+#define  AFI_INTR_EN_INI_DECERR                (1 << 1)
+#define  AFI_INTR_EN_TGT_SLVERR                (1 << 2)
+#define  AFI_INTR_EN_TGT_DECERR                (1 << 3)
+#define  AFI_INTR_EN_TGT_WRERR         (1 << 4)
+#define  AFI_INTR_EN_DFPCI_DECERR      (1 << 5)
+#define  AFI_INTR_EN_AXI_DECERR                (1 << 6)
+#define  AFI_INTR_EN_FPCI_TIMEOUT      (1 << 7)
+#define  AFI_INTR_EN_PRSNT_SENSE       (1 << 8)
+
+#define AFI_PCIE_CONFIG                                        0x0f8
+#define  AFI_PCIE_CONFIG_PCIE_DISABLE(x)               (1 << ((x) + 1))
+#define  AFI_PCIE_CONFIG_PCIE_DISABLE_ALL              0xe
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK      (0xf << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE    (0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420       (0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1     (0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL      (0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222       (0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1     (0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411       (0x2 << 20)
+
+#define AFI_FUSE                       0x104
+#define  AFI_FUSE_PCIE_T0_GEN2_DIS     (1 << 2)
+
+#define AFI_PEX0_CTRL                  0x110
+#define AFI_PEX1_CTRL                  0x118
+#define AFI_PEX2_CTRL                  0x128
+#define  AFI_PEX_CTRL_RST              (1 << 0)
+#define  AFI_PEX_CTRL_CLKREQ_EN                (1 << 1)
+#define  AFI_PEX_CTRL_REFCLK_EN                (1 << 3)
+#define  AFI_PEX_CTRL_OVERRIDE_EN      (1 << 4)
+
+#define AFI_PLLE_CONTROL               0x160
+#define  AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
+#define  AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
+
+#define AFI_PEXBIAS_CTRL_0             0x168
+
+#define PADS_CTL_SEL           0x0000009C
+
+#define PADS_CTL               0x000000A0
+#define  PADS_CTL_IDDQ_1L      (1 <<  0)
+#define  PADS_CTL_TX_DATA_EN_1L        (1 <<  6)
+#define  PADS_CTL_RX_DATA_EN_1L        (1 << 10)
+
+#define PADS_PLL_CTL_TEGRA20                   0x000000B8
+#define PADS_PLL_CTL_TEGRA30                   0x000000B4
+#define  PADS_PLL_CTL_RST_B4SM                 (0x1 <<  1)
+#define  PADS_PLL_CTL_LOCKDET                  (0x1 <<  8)
+#define  PADS_PLL_CTL_REFCLK_MASK              (0x3 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CML      (0x0 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CMOS     (0x1 << 16)
+#define  PADS_PLL_CTL_REFCLK_EXTERNAL          (0x2 << 16)
+#define  PADS_PLL_CTL_TXCLKREF_MASK            (0x1 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV10           (0x0 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV5            (0x1 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_BUF_EN          (0x1 << 22)
+
+#define PADS_REFCLK_CFG0                       0x000000C8
+#define PADS_REFCLK_CFG1                       0x000000CC
+
+/*
+ * Fields in PADS_REFCLK_CFG*. Those registers form an array of 16-bit
+ * entries, one entry per PCIe port. These field definitions and desired
+ * values aren't in the TRM, but do come from NVIDIA.
+ */
+#define PADS_REFCLK_CFG_TERM_SHIFT             2  /* 6:2 */
+#define PADS_REFCLK_CFG_E_TERM_SHIFT           7
+#define PADS_REFCLK_CFG_PREDI_SHIFT            8  /* 11:8 */
+#define PADS_REFCLK_CFG_DRVI_SHIFT             12 /* 15:12 */
+
+/* Default value provided by HW engineering is 0xfa5c */
+#define PADS_REFCLK_CFG_VALUE \
+       ( \
+               (0x17 << PADS_REFCLK_CFG_TERM_SHIFT)   | \
+               (0    << PADS_REFCLK_CFG_E_TERM_SHIFT) | \
+               (0xa  << PADS_REFCLK_CFG_PREDI_SHIFT)  | \
+               (0xf  << PADS_REFCLK_CFG_DRVI_SHIFT)     \
+       )
+
+#define RP_VEND_XP     0x00000F00
+#define  RP_VEND_XP_DL_UP      (1 << 30)
+
+#define RP_PRIV_MISC   0x00000FE0
+#define  RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0)
+#define  RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0)
+
+#define RP_LINK_CONTROL_STATUS                 0x00000090
+#define  RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
+#define  RP_LINK_CONTROL_STATUS_LINKSTAT_MASK  0x3fff0000
+
+struct tegra_pcie;
+
+struct tegra_pcie_port {
+       struct tegra_pcie *pcie;
+
+       struct fdt_resource regs;
+       unsigned int num_lanes;
+       unsigned int index;
+
+       struct list_head list;
+};
+
+struct tegra_pcie_soc {
+       unsigned int num_ports;
+       unsigned long pads_pll_ctl;
+       unsigned long tx_ref_sel;
+       bool has_pex_clkreq_en;
+       bool has_pex_bias_ctrl;
+       bool has_cml_clk;
+       bool has_gen2;
+};
+
+struct tegra_pcie {
+       struct pci_controller hose;
+
+       struct fdt_resource pads;
+       struct fdt_resource afi;
+       struct fdt_resource cs;
+
+       struct fdt_resource prefetch;
+       struct fdt_resource mem;
+       struct fdt_resource io;
+
+       struct list_head ports;
+       unsigned long xbar;
+
+       const struct tegra_pcie_soc *soc;
+       struct tegra_xusb_phy *phy;
+};
+
+static inline struct tegra_pcie *to_tegra_pcie(struct pci_controller *hose)
+{
+       return container_of(hose, struct tegra_pcie, hose);
+}
+
+static void afi_writel(struct tegra_pcie *pcie, unsigned long value,
+                      unsigned long offset)
+{
+       writel(value, pcie->afi.start + offset);
+}
+
+static unsigned long afi_readl(struct tegra_pcie *pcie, unsigned long offset)
+{
+       return readl(pcie->afi.start + offset);
+}
+
+static void pads_writel(struct tegra_pcie *pcie, unsigned long value,
+                       unsigned long offset)
+{
+       writel(value, pcie->pads.start + offset);
+}
+
+static unsigned long pads_readl(struct tegra_pcie *pcie, unsigned long offset)
+{
+       return readl(pcie->pads.start + offset);
+}
+
+static unsigned long rp_readl(struct tegra_pcie_port *port,
+                             unsigned long offset)
+{
+       return readl(port->regs.start + offset);
+}
+
+static void rp_writel(struct tegra_pcie_port *port, unsigned long value,
+                     unsigned long offset)
+{
+       writel(value, port->regs.start + offset);
+}
+
+static unsigned long tegra_pcie_conf_offset(pci_dev_t bdf, int where)
+{
+       return ((where & 0xf00) << 16) | (PCI_BUS(bdf) << 16) |
+              (PCI_DEV(bdf) << 11) | (PCI_FUNC(bdf) << 8) |
+              (where & 0xfc);
+}
+
+static int tegra_pcie_conf_address(struct tegra_pcie *pcie, pci_dev_t bdf,
+                                  int where, unsigned long *address)
+{
+       unsigned int bus = PCI_BUS(bdf);
+
+       if (bus == 0) {
+               unsigned int dev = PCI_DEV(bdf);
+               struct tegra_pcie_port *port;
+
+               list_for_each_entry(port, &pcie->ports, list) {
+                       if (port->index + 1 == dev) {
+                               *address = port->regs.start + (where & ~3);
+                               return 0;
+                       }
+               }
+       } else {
+               *address = pcie->cs.start + tegra_pcie_conf_offset(bdf, where);
+               return 0;
+       }
+
+       return -1;
+}
+
+static int tegra_pcie_read_conf(struct pci_controller *hose, pci_dev_t bdf,
+                               int where, u32 *value)
+{
+       struct tegra_pcie *pcie = to_tegra_pcie(hose);
+       unsigned long address;
+       int err;
+
+       err = tegra_pcie_conf_address(pcie, bdf, where, &address);
+       if (err < 0) {
+               *value = 0xffffffff;
+               return 1;
+       }
+
+       *value = readl(address);
+
+       /* fixup root port class */
+       if (PCI_BUS(bdf) == 0) {
+               if (where == PCI_CLASS_REVISION) {
+                       *value &= ~0x00ff0000;
+                       *value |= PCI_CLASS_BRIDGE_PCI << 16;
+               }
+       }
+
+       return 0;
+}
+
+static int tegra_pcie_write_conf(struct pci_controller *hose, pci_dev_t bdf,
+                                int where, u32 value)
+{
+       struct tegra_pcie *pcie = to_tegra_pcie(hose);
+       unsigned long address;
+       int err;
+
+       err = tegra_pcie_conf_address(pcie, bdf, where, &address);
+       if (err < 0)
+               return 1;
+
+       writel(value, address);
+
+       return 0;
+}
+
+static int tegra_pcie_port_parse_dt(const void *fdt, int node,
+                                   struct tegra_pcie_port *port)
+{
+       const u32 *addr;
+       int len;
+
+       addr = fdt_getprop(fdt, node, "assigned-addresses", &len);
+       if (!addr) {
+               error("property \"assigned-addresses\" not found");
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       port->regs.start = fdt32_to_cpu(addr[2]);
+       port->regs.end = port->regs.start + fdt32_to_cpu(addr[4]);
+
+       return 0;
+}
+
+static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
+                                     unsigned long *xbar)
+{
+       enum fdt_compat_id id = fdtdec_lookup(fdt, node);
+
+       switch (id) {
+       case COMPAT_NVIDIA_TEGRA20_PCIE:
+               switch (lanes) {
+               case 0x00000004:
+                       debug("single-mode configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE;
+                       return 0;
+
+               case 0x00000202:
+                       debug("dual-mode configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL;
+                       return 0;
+               }
+               break;
+
+       case COMPAT_NVIDIA_TEGRA30_PCIE:
+               switch (lanes) {
+               case 0x00000204:
+                       debug("4x1, 2x1 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420;
+                       return 0;
+
+               case 0x00020202:
+                       debug("2x3 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222;
+                       return 0;
+
+               case 0x00010104:
+                       debug("4x1, 1x2 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411;
+                       return 0;
+               }
+               break;
+
+       case COMPAT_NVIDIA_TEGRA124_PCIE:
+               switch (lanes) {
+               case 0x0000104:
+                       debug("4x1, 1x1 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
+                       return 0;
+
+               case 0x0000102:
+                       debug("2x1, 1x1 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1;
+                       return 0;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+static int tegra_pcie_parse_dt_ranges(const void *fdt, int node,
+                                     struct tegra_pcie *pcie)
+{
+       const u32 *ptr, *end;
+       int len;
+
+       ptr = fdt_getprop(fdt, node, "ranges", &len);
+       if (!ptr) {
+               error("missing \"ranges\" property");
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       end = ptr + len / 4;
+
+       while (ptr < end) {
+               struct fdt_resource *res = NULL;
+               u32 space = fdt32_to_cpu(*ptr);
+
+               switch ((space >> 24) & 0x3) {
+               case 0x01:
+                       res = &pcie->io;
+                       break;
+
+               case 0x02: /* 32 bit */
+               case 0x03: /* 64 bit */
+                       if (space & (1 << 30))
+                               res = &pcie->prefetch;
+                       else
+                               res = &pcie->mem;
+
+                       break;
+               }
+
+               if (res) {
+                       res->start = fdt32_to_cpu(ptr[3]);
+                       res->end = res->start + fdt32_to_cpu(ptr[5]);
+               }
+
+               ptr += 3 + 1 + 2;
+       }
+
+       debug("PCI regions:\n");
+       debug("  I/O: %#x-%#x\n", pcie->io.start, pcie->io.end);
+       debug("  non-prefetchable memory: %#x-%#x\n", pcie->mem.start,
+             pcie->mem.end);
+       debug("  prefetchable memory: %#x-%#x\n", pcie->prefetch.start,
+             pcie->prefetch.end);
+
+       return 0;
+}
+
+static int tegra_pcie_parse_port_info(const void *fdt, int node,
+                                     unsigned int *index,
+                                     unsigned int *lanes)
+{
+       pci_dev_t bdf;
+       int err;
+
+       err = fdtdec_get_int(fdt, node, "nvidia,num-lanes", 0);
+       if (err < 0) {
+               error("failed to parse \"nvidia,num-lanes\" property");
+               return err;
+       }
+
+       *lanes = err;
+
+       err = fdtdec_pci_get_bdf(fdt, node, &bdf);
+       if (err < 0) {
+               error("failed to parse \"reg\" property");
+               return err;
+       }
+
+       *index = PCI_DEV(bdf) - 1;
+
+       return 0;
+}
+
+static int tegra_pcie_parse_dt(const void *fdt, int node,
+                              struct tegra_pcie *pcie)
+{
+       int err, subnode;
+       u32 lanes = 0;
+
+       err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "pads",
+                                    &pcie->pads);
+       if (err < 0) {
+               error("resource \"pads\" not found");
+               return err;
+       }
+
+       err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "afi",
+                                    &pcie->afi);
+       if (err < 0) {
+               error("resource \"afi\" not found");
+               return err;
+       }
+
+       err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "cs",
+                                    &pcie->cs);
+       if (err < 0) {
+               error("resource \"cs\" not found");
+               return err;
+       }
+
+       pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE);
+       if (pcie->phy) {
+               err = tegra_xusb_phy_prepare(pcie->phy);
+               if (err < 0) {
+                       error("failed to prepare PHY: %d", err);
+                       return err;
+               }
+       }
+
+       err = tegra_pcie_parse_dt_ranges(fdt, node, pcie);
+       if (err < 0) {
+               error("failed to parse \"ranges\" property");
+               return err;
+       }
+
+       fdt_for_each_subnode(fdt, subnode, node) {
+               unsigned int index = 0, num_lanes = 0;
+               struct tegra_pcie_port *port;
+
+               err = tegra_pcie_parse_port_info(fdt, subnode, &index,
+                                                &num_lanes);
+               if (err < 0) {
+                       error("failed to obtain root port info");
+                       continue;
+               }
+
+               lanes |= num_lanes << (index << 3);
+
+               if (!fdtdec_get_is_enabled(fdt, subnode))
+                       continue;
+
+               port = malloc(sizeof(*port));
+               if (!port)
+                       continue;
+
+               memset(port, 0, sizeof(*port));
+               port->num_lanes = num_lanes;
+               port->index = index;
+
+               err = tegra_pcie_port_parse_dt(fdt, subnode, port);
+               if (err < 0) {
+                       free(port);
+                       continue;
+               }
+
+               list_add_tail(&port->list, &pcie->ports);
+               port->pcie = pcie;
+       }
+
+       err = tegra_pcie_get_xbar_config(fdt, node, lanes, &pcie->xbar);
+       if (err < 0) {
+               error("invalid lane configuration");
+               return err;
+       }
+
+       return 0;
+}
+
+int __weak tegra_pcie_board_init(void)
+{
+       return 0;
+}
+
+static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+{
+       const struct tegra_pcie_soc *soc = pcie->soc;
+       unsigned long value;
+       int err;
+
+       /* reset PCIEXCLK logic, AFI controller and PCIe controller */
+       reset_set_enable(PERIPH_ID_PCIEXCLK, 1);
+       reset_set_enable(PERIPH_ID_AFI, 1);
+       reset_set_enable(PERIPH_ID_PCIE, 1);
+
+       err = tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+       if (err < 0) {
+               error("failed to power off PCIe partition: %d", err);
+               return err;
+       }
+
+       tegra_pcie_board_init();
+
+       err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
+                                               PERIPH_ID_PCIE);
+       if (err < 0) {
+               error("failed to power up PCIe partition: %d", err);
+               return err;
+       }
+
+       /* take AFI controller out of reset */
+       reset_set_enable(PERIPH_ID_AFI, 0);
+
+       /* enable AFI clock */
+       clock_enable(PERIPH_ID_AFI);
+
+       if (soc->has_cml_clk) {
+               /* enable CML clock */
+               value = readl(NV_PA_CLK_RST_BASE + 0x48c);
+               value |= (1 << 0);
+               value &= ~(1 << 1);
+               writel(value, NV_PA_CLK_RST_BASE + 0x48c);
+       }
+
+       err = tegra_plle_enable();
+       if (err < 0) {
+               error("failed to enable PLLE: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout)
+{
+       const struct tegra_pcie_soc *soc = pcie->soc;
+       unsigned long start = get_timer(0);
+       u32 value;
+
+       while (get_timer(start) < timeout) {
+               value = pads_readl(pcie, soc->pads_pll_ctl);
+               if (value & PADS_PLL_CTL_LOCKDET)
+                       return 0;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
+{
+       const struct tegra_pcie_soc *soc = pcie->soc;
+       u32 value;
+       int err;
+
+       /* initialize internal PHY, enable up to 16 PCIe lanes */
+       pads_writel(pcie, 0, PADS_CTL_SEL);
+
+       /* override IDDQ to 1 on all 4 lanes */
+       value = pads_readl(pcie, PADS_CTL);
+       value |= PADS_CTL_IDDQ_1L;
+       pads_writel(pcie, value, PADS_CTL);
+
+       /*
+        * Set up PHY PLL inputs select PLLE output as refclock, set TX
+        * ref sel to div10 (not div5).
+        */
+       value = pads_readl(pcie, soc->pads_pll_ctl);
+       value &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK);
+       value |= PADS_PLL_CTL_REFCLK_INTERNAL_CML | soc->tx_ref_sel;
+       pads_writel(pcie, value, soc->pads_pll_ctl);
+
+       /* reset PLL */
+       value = pads_readl(pcie, soc->pads_pll_ctl);
+       value &= ~PADS_PLL_CTL_RST_B4SM;
+       pads_writel(pcie, value, soc->pads_pll_ctl);
+
+       udelay(20);
+
+       /* take PLL out of reset */
+       value = pads_readl(pcie, soc->pads_pll_ctl);
+       value |= PADS_PLL_CTL_RST_B4SM;
+       pads_writel(pcie, value, soc->pads_pll_ctl);
+
+       /* configure the reference clock driver */
+       value = PADS_REFCLK_CFG_VALUE | (PADS_REFCLK_CFG_VALUE << 16);
+       pads_writel(pcie, value, PADS_REFCLK_CFG0);
+
+       if (soc->num_ports > 2)
+               pads_writel(pcie, PADS_REFCLK_CFG_VALUE, PADS_REFCLK_CFG1);
+
+       /* wait for the PLL to lock */
+       err = tegra_pcie_pll_wait(pcie, 500);
+       if (err < 0) {
+               error("PLL failed to lock: %d", err);
+               return err;
+       }
+
+       /* turn off IDDQ override */
+       value = pads_readl(pcie, PADS_CTL);
+       value &= ~PADS_CTL_IDDQ_1L;
+       pads_writel(pcie, value, PADS_CTL);
+
+       /* enable TX/RX data */
+       value = pads_readl(pcie, PADS_CTL);
+       value |= PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L;
+       pads_writel(pcie, value, PADS_CTL);
+
+       return 0;
+}
+
+static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
+{
+       const struct tegra_pcie_soc *soc = pcie->soc;
+       struct tegra_pcie_port *port;
+       u32 value;
+       int err;
+
+       if (pcie->phy) {
+               value = afi_readl(pcie, AFI_PLLE_CONTROL);
+               value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
+               value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
+               afi_writel(pcie, value, AFI_PLLE_CONTROL);
+       }
+
+       if (soc->has_pex_bias_ctrl)
+               afi_writel(pcie, 0, AFI_PEXBIAS_CTRL_0);
+
+       value = afi_readl(pcie, AFI_PCIE_CONFIG);
+       value &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK;
+       value |= AFI_PCIE_CONFIG_PCIE_DISABLE_ALL | pcie->xbar;
+
+       list_for_each_entry(port, &pcie->ports, list)
+               value &= ~AFI_PCIE_CONFIG_PCIE_DISABLE(port->index);
+
+       afi_writel(pcie, value, AFI_PCIE_CONFIG);
+
+       value = afi_readl(pcie, AFI_FUSE);
+
+       if (soc->has_gen2)
+               value &= ~AFI_FUSE_PCIE_T0_GEN2_DIS;
+       else
+               value |= AFI_FUSE_PCIE_T0_GEN2_DIS;
+
+       afi_writel(pcie, value, AFI_FUSE);
+
+       if (pcie->phy)
+               err = tegra_xusb_phy_enable(pcie->phy);
+       else
+               err = tegra_pcie_phy_enable(pcie);
+
+       if (err < 0) {
+               error("failed to power on PHY: %d\n", err);
+               return err;
+       }
+
+       /* take the PCIEXCLK logic out of reset */
+       reset_set_enable(PERIPH_ID_PCIEXCLK, 0);
+
+       /* finally enable PCIe */
+       value = afi_readl(pcie, AFI_CONFIGURATION);
+       value |= AFI_CONFIGURATION_EN_FPCI;
+       afi_writel(pcie, value, AFI_CONFIGURATION);
+
+       /* disable all interrupts */
+       afi_writel(pcie, 0, AFI_AFI_INTR_ENABLE);
+       afi_writel(pcie, 0, AFI_SM_INTR_ENABLE);
+       afi_writel(pcie, 0, AFI_INTR_MASK);
+       afi_writel(pcie, 0, AFI_FPCI_ERROR_MASKS);
+
+       return 0;
+}
+
+static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
+{
+       unsigned long fpci, axi, size;
+
+       /* BAR 0: type 1 extended configuration space */
+       fpci = 0xfe100000;
+       size = fdt_resource_size(&pcie->cs);
+       axi = pcie->cs.start;
+
+       afi_writel(pcie, axi, AFI_AXI_BAR0_START);
+       afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ);
+       afi_writel(pcie, fpci, AFI_FPCI_BAR0);
+
+       /* BAR 1: downstream I/O */
+       fpci = 0xfdfc0000;
+       size = fdt_resource_size(&pcie->io);
+       axi = pcie->io.start;
+
+       afi_writel(pcie, axi, AFI_AXI_BAR1_START);
+       afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
+       afi_writel(pcie, fpci, AFI_FPCI_BAR1);
+
+       /* BAR 2: prefetchable memory */
+       fpci = (((pcie->prefetch.start >> 12) & 0x0fffffff) << 4) | 0x1;
+       size = fdt_resource_size(&pcie->prefetch);
+       axi = pcie->prefetch.start;
+
+       afi_writel(pcie, axi, AFI_AXI_BAR2_START);
+       afi_writel(pcie, size >> 12, AFI_AXI_BAR2_SZ);
+       afi_writel(pcie, fpci, AFI_FPCI_BAR2);
+
+       /* BAR 3: non-prefetchable memory */
+       fpci = (((pcie->mem.start >> 12) & 0x0fffffff) << 4) | 0x1;
+       size = fdt_resource_size(&pcie->mem);
+       axi = pcie->mem.start;
+
+       afi_writel(pcie, axi, AFI_AXI_BAR3_START);
+       afi_writel(pcie, size >> 12, AFI_AXI_BAR3_SZ);
+       afi_writel(pcie, fpci, AFI_FPCI_BAR3);
+
+       /* NULL out the remaining BARs as they are not used */
+       afi_writel(pcie, 0, AFI_AXI_BAR4_START);
+       afi_writel(pcie, 0, AFI_AXI_BAR4_SZ);
+       afi_writel(pcie, 0, AFI_FPCI_BAR4);
+
+       afi_writel(pcie, 0, AFI_AXI_BAR5_START);
+       afi_writel(pcie, 0, AFI_AXI_BAR5_SZ);
+       afi_writel(pcie, 0, AFI_FPCI_BAR5);
+
+       /* map all upstream transactions as uncached */
+       afi_writel(pcie, NV_PA_SDRAM_BASE, AFI_CACHE_BAR0_ST);
+       afi_writel(pcie, 0, AFI_CACHE_BAR0_SZ);
+       afi_writel(pcie, 0, AFI_CACHE_BAR1_ST);
+       afi_writel(pcie, 0, AFI_CACHE_BAR1_SZ);
+
+       /* MSI translations are setup only when needed */
+       afi_writel(pcie, 0, AFI_MSI_FPCI_BAR_ST);
+       afi_writel(pcie, 0, AFI_MSI_BAR_SZ);
+       afi_writel(pcie, 0, AFI_MSI_AXI_BAR_ST);
+       afi_writel(pcie, 0, AFI_MSI_BAR_SZ);
+}
+
+static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
+{
+       unsigned long ret = 0;
+
+       switch (port->index) {
+       case 0:
+               ret = AFI_PEX0_CTRL;
+               break;
+
+       case 1:
+               ret = AFI_PEX1_CTRL;
+               break;
+
+       case 2:
+               ret = AFI_PEX2_CTRL;
+               break;
+       }
+
+       return ret;
+}
+
+static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
+{
+       unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
+       unsigned long value;
+
+       /* pulse reset signel */
+       value = afi_readl(port->pcie, ctrl);
+       value &= ~AFI_PEX_CTRL_RST;
+       afi_writel(port->pcie, value, ctrl);
+
+       udelay(2000);
+
+       value = afi_readl(port->pcie, ctrl);
+       value |= AFI_PEX_CTRL_RST;
+       afi_writel(port->pcie, value, ctrl);
+}
+
+static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
+{
+       unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
+       unsigned long value;
+
+       /* enable reference clock */
+       value = afi_readl(port->pcie, ctrl);
+       value |= AFI_PEX_CTRL_REFCLK_EN;
+
+       if (port->pcie->soc->has_pex_clkreq_en)
+               value |= AFI_PEX_CTRL_CLKREQ_EN;
+
+       value |= AFI_PEX_CTRL_OVERRIDE_EN;
+
+       afi_writel(port->pcie, value, ctrl);
+
+       tegra_pcie_port_reset(port);
+}
+
+static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
+{
+       unsigned int retries = 3;
+       unsigned long value;
+
+       value = rp_readl(port, RP_PRIV_MISC);
+       value &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;
+       value |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT;
+       rp_writel(port, value, RP_PRIV_MISC);
+
+       do {
+               unsigned int timeout = 200;
+
+               do {
+                       value = rp_readl(port, RP_VEND_XP);
+                       if (value & RP_VEND_XP_DL_UP)
+                               break;
+
+                       udelay(2000);
+               } while (--timeout);
+
+               if (!timeout) {
+                       debug("link %u down, retrying\n", port->index);
+                       goto retry;
+               }
+
+               timeout = 200;
+
+               do {
+                       value = rp_readl(port, RP_LINK_CONTROL_STATUS);
+                       if (value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE)
+                               return true;
+
+                       udelay(2000);
+               } while (--timeout);
+
+retry:
+               tegra_pcie_port_reset(port);
+       } while (--retries);
+
+       return false;
+}
+
+static void tegra_pcie_port_disable(struct tegra_pcie_port *port)
+{
+       unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
+       unsigned long value;
+
+       /* assert port reset */
+       value = afi_readl(port->pcie, ctrl);
+       value &= ~AFI_PEX_CTRL_RST;
+       afi_writel(port->pcie, value, ctrl);
+
+       /* disable reference clock */
+       value = afi_readl(port->pcie, ctrl);
+       value &= ~AFI_PEX_CTRL_REFCLK_EN;
+       afi_writel(port->pcie, value, ctrl);
+}
+
+static void tegra_pcie_port_free(struct tegra_pcie_port *port)
+{
+       list_del(&port->list);
+       free(port);
+}
+
+static int tegra_pcie_enable(struct tegra_pcie *pcie)
+{
+       struct tegra_pcie_port *port, *tmp;
+
+       list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+               debug("probing port %u, using %u lanes\n", port->index,
+                     port->num_lanes);
+
+               tegra_pcie_port_enable(port);
+
+               if (tegra_pcie_port_check_link(port))
+                       continue;
+
+               debug("link %u down, ignoring\n", port->index);
+
+               tegra_pcie_port_disable(port);
+               tegra_pcie_port_free(port);
+       }
+
+       return 0;
+}
+
+static const struct tegra_pcie_soc tegra20_pcie_soc = {
+       .num_ports = 2,
+       .pads_pll_ctl = PADS_PLL_CTL_TEGRA20,
+       .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10,
+       .has_pex_clkreq_en = false,
+       .has_pex_bias_ctrl = false,
+       .has_cml_clk = false,
+       .has_gen2 = false,
+};
+
+static const struct tegra_pcie_soc tegra30_pcie_soc = {
+       .num_ports = 3,
+       .pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
+       .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+       .has_pex_clkreq_en = true,
+       .has_pex_bias_ctrl = true,
+       .has_cml_clk = true,
+       .has_gen2 = false,
+};
+
+static const struct tegra_pcie_soc tegra124_pcie_soc = {
+       .num_ports = 2,
+       .pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
+       .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+       .has_pex_clkreq_en = true,
+       .has_pex_bias_ctrl = true,
+       .has_cml_clk = true,
+       .has_gen2 = true,
+};
+
+static int process_nodes(const void *fdt, int nodes[], unsigned int count)
+{
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               const struct tegra_pcie_soc *soc;
+               struct tegra_pcie *pcie;
+               enum fdt_compat_id id;
+               int err;
+
+               if (!fdtdec_get_is_enabled(fdt, nodes[i]))
+                       continue;
+
+               id = fdtdec_lookup(fdt, nodes[i]);
+               switch (id) {
+               case COMPAT_NVIDIA_TEGRA20_PCIE:
+                       soc = &tegra20_pcie_soc;
+                       break;
+
+               case COMPAT_NVIDIA_TEGRA30_PCIE:
+                       soc = &tegra30_pcie_soc;
+                       break;
+
+               case COMPAT_NVIDIA_TEGRA124_PCIE:
+                       soc = &tegra124_pcie_soc;
+                       break;
+
+               default:
+                       error("unsupported compatible: %s",
+                             fdtdec_get_compatible(id));
+                       continue;
+               }
+
+               pcie = malloc(sizeof(*pcie));
+               if (!pcie) {
+                       error("failed to allocate controller");
+                       continue;
+               }
+
+               memset(pcie, 0, sizeof(*pcie));
+               pcie->soc = soc;
+
+               INIT_LIST_HEAD(&pcie->ports);
+
+               err = tegra_pcie_parse_dt(fdt, nodes[i], pcie);
+               if (err < 0) {
+                       free(pcie);
+                       continue;
+               }
+
+               err = tegra_pcie_power_on(pcie);
+               if (err < 0) {
+                       error("failed to power on");
+                       continue;
+               }
+
+               err = tegra_pcie_enable_controller(pcie);
+               if (err < 0) {
+                       error("failed to enable controller");
+                       continue;
+               }
+
+               tegra_pcie_setup_translations(pcie);
+
+               err = tegra_pcie_enable(pcie);
+               if (err < 0) {
+                       error("failed to enable PCIe");
+                       continue;
+               }
+
+               pcie->hose.first_busno = 0;
+               pcie->hose.current_busno = 0;
+               pcie->hose.last_busno = 0;
+
+               pci_set_region(&pcie->hose.regions[0], NV_PA_SDRAM_BASE,
+                              NV_PA_SDRAM_BASE, gd->ram_size,
+                              PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+               pci_set_region(&pcie->hose.regions[1], pcie->io.start,
+                              pcie->io.start, fdt_resource_size(&pcie->io),
+                              PCI_REGION_IO);
+
+               pci_set_region(&pcie->hose.regions[2], pcie->mem.start,
+                              pcie->mem.start, fdt_resource_size(&pcie->mem),
+                              PCI_REGION_MEM);
+
+               pci_set_region(&pcie->hose.regions[3], pcie->prefetch.start,
+                              pcie->prefetch.start,
+                              fdt_resource_size(&pcie->prefetch),
+                              PCI_REGION_MEM | PCI_REGION_PREFETCH);
+
+               pcie->hose.region_count = 4;
+
+               pci_set_ops(&pcie->hose,
+                           pci_hose_read_config_byte_via_dword,
+                           pci_hose_read_config_word_via_dword,
+                           tegra_pcie_read_conf,
+                           pci_hose_write_config_byte_via_dword,
+                           pci_hose_write_config_word_via_dword,
+                           tegra_pcie_write_conf);
+
+               pci_register_hose(&pcie->hose);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+               printf("PCI: Enumerating devices...\n");
+               printf("---------------------------------------\n");
+               printf("  Device        ID          Description\n");
+               printf("  ------        --          -----------\n");
+#endif
+
+               pcie->hose.last_busno = pci_hose_scan(&pcie->hose);
+       }
+
+       return 0;
+}
+
+void pci_init_board(void)
+{
+       const void *fdt = gd->fdt_blob;
+       int count, nodes[1];
+
+       count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
+                                          COMPAT_NVIDIA_TEGRA124_PCIE,
+                                          nodes, ARRAY_SIZE(nodes));
+       if (process_nodes(fdt, nodes, count))
+               return;
+
+       count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
+                                          COMPAT_NVIDIA_TEGRA30_PCIE,
+                                          nodes, ARRAY_SIZE(nodes));
+       if (process_nodes(fdt, nodes, count))
+               return;
+
+       count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
+                                          COMPAT_NVIDIA_TEGRA20_PCIE,
+                                          nodes, ARRAY_SIZE(nodes));
+       if (process_nodes(fdt, nodes, count))
+               return;
+}
+
+int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
+{
+       if (PCI_BUS(dev) != 0 && PCI_DEV(dev) > 0)
+               return 1;
+
+       return 0;
+}
index 04bd996cad0dae6db5b23196a55c6ca5cb7e13a2..214565241ed31aa9d185d0a7579f8e2cefee41dd 100644 (file)
@@ -5,6 +5,7 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-$(CONFIG_AS3722_POWER)     += as3722.o
 obj-$(CONFIG_AXP152_POWER)     += axp152.o
 obj-$(CONFIG_AXP209_POWER)     += axp209.o
 obj-$(CONFIG_AXP221_POWER)     += axp221.o
diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
new file mode 100644 (file)
index 0000000..4c6de79
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#define pr_fmt(fmt) "as3722: " fmt
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+
+#include <power/as3722.h>
+
+#define AS3722_SD_VOLTAGE(n) (0x00 + (n))
+#define AS3722_GPIO_CONTROL(n) (0x08 + (n))
+#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0)
+#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0)
+#define  AS3722_GPIO_CONTROL_INVERT (1 << 7)
+#define AS3722_LDO_VOLTAGE(n) (0x10 + (n))
+#define AS3722_GPIO_SIGNAL_OUT 0x20
+#define AS3722_SD_CONTROL 0x4d
+#define AS3722_LDO_CONTROL 0x4e
+#define AS3722_ASIC_ID1 0x90
+#define  AS3722_DEVICE_ID 0x0c
+#define AS3722_ASIC_ID2 0x91
+
+static int as3722_read(struct udevice *pmic, u8 reg, u8 *value)
+{
+       int err;
+
+       err = i2c_read(pmic, reg, value, 1);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int as3722_write(struct udevice *pmic, u8 reg, u8 value)
+{
+       int err;
+
+       err = i2c_write(pmic, reg, &value, 1);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision)
+{
+       int err;
+
+       err = as3722_read(pmic, AS3722_ASIC_ID1, id);
+       if (err) {
+               error("failed to read ID1 register: %d", err);
+               return err;
+       }
+
+       err = as3722_read(pmic, AS3722_ASIC_ID2, revision);
+       if (err) {
+               error("failed to read ID2 register: %d", err);
+               return err;
+       }
+
+       return 0;
+}
+
+int as3722_sd_enable(struct udevice *pmic, unsigned int sd)
+{
+       u8 value;
+       int err;
+
+       if (sd > 6)
+               return -EINVAL;
+
+       err = as3722_read(pmic, AS3722_SD_CONTROL, &value);
+       if (err) {
+               error("failed to read SD control register: %d", err);
+               return err;
+       }
+
+       value |= 1 << sd;
+
+       err = as3722_write(pmic, AS3722_SD_CONTROL, value);
+       if (err < 0) {
+               error("failed to write SD control register: %d", err);
+               return err;
+       }
+
+       return 0;
+}
+
+int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value)
+{
+       int err;
+
+       if (sd > 6)
+               return -EINVAL;
+
+       err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value);
+       if (err < 0) {
+               error("failed to write SD%u voltage register: %d", sd, err);
+               return err;
+       }
+
+       return 0;
+}
+
+int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo)
+{
+       u8 value;
+       int err;
+
+       if (ldo > 11)
+               return -EINVAL;
+
+       err = as3722_read(pmic, AS3722_LDO_CONTROL, &value);
+       if (err) {
+               error("failed to read LDO control register: %d", err);
+               return err;
+       }
+
+       value |= 1 << ldo;
+
+       err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
+       if (err < 0) {
+               error("failed to write LDO control register: %d", err);
+               return err;
+       }
+
+       return 0;
+}
+
+int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value)
+{
+       int err;
+
+       if (ldo > 11)
+               return -EINVAL;
+
+       err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
+       if (err < 0) {
+               error("failed to write LDO%u voltage register: %d", ldo,
+                     err);
+               return err;
+       }
+
+       return 0;
+}
+
+int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
+                         unsigned long flags)
+{
+       u8 value = 0;
+       int err;
+
+       if (flags & AS3722_GPIO_OUTPUT_VDDH)
+               value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+       if (flags & AS3722_GPIO_INVERT)
+               value |= AS3722_GPIO_CONTROL_INVERT;
+
+       err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+       if (err) {
+               error("failed to configure GPIO#%u: %d", gpio, err);
+               return err;
+       }
+
+       return 0;
+}
+
+static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio,
+                          unsigned int level)
+{
+       const char *l;
+       u8 value;
+       int err;
+
+       if (gpio > 7)
+               return -EINVAL;
+
+       err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value);
+       if (err < 0) {
+               error("failed to read GPIO signal out register: %d", err);
+               return err;
+       }
+
+       if (level == 0) {
+               value &= ~(1 << gpio);
+               l = "low";
+       } else {
+               value |= 1 << gpio;
+               l = "high";
+       }
+
+       err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
+       if (err) {
+               error("failed to set GPIO#%u %s: %d", gpio, l, err);
+               return err;
+       }
+
+       return 0;
+}
+
+int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
+                                unsigned int level)
+{
+       u8 value;
+       int err;
+
+       if (gpio > 7)
+               return -EINVAL;
+
+       if (level == 0)
+               value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+       else
+               value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+       err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+       if (err) {
+               error("failed to configure GPIO#%u as output: %d", gpio, err);
+               return err;
+       }
+
+       err = as3722_gpio_set(pmic, gpio, level);
+       if (err < 0) {
+               error("failed to set GPIO#%u high: %d", gpio, err);
+               return err;
+       }
+
+       return 0;
+}
+
+int as3722_init(struct udevice **devp)
+{
+       struct udevice *pmic;
+       u8 id, revision;
+       const unsigned int bus = 0;
+       const unsigned int address = 0x40;
+       int err;
+
+       err = i2c_get_chip_for_busnum(bus, address, &pmic);
+       if (err)
+               return err;
+       err = as3722_read_id(pmic, &id, &revision);
+       if (err < 0) {
+               error("failed to read ID: %d", err);
+               return err;
+       }
+
+       if (id != AS3722_DEVICE_ID) {
+               error("unknown device");
+               return -ENOENT;
+       }
+
+       debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
+             revision, bus, address);
+       *devp = pmic;
+
+       return 0;
+}
index 5d765f3d36fa10ada3d5c86151e0dfe7de7f9e5e..5df460c96b1d0072b36e06c1e8c74b8b58f5f891 100644 (file)
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
index 758b7ad392dc9f7f13e68f12e0ffe7c11fb5b01f..5e13b655c28788b9cfdf65a699c8e65929fb78ee 100644 (file)
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
index a7d76650ce6e0d26098eefb50a8187d332947678..0a79c7cfc361ead7f91ae7b5d1d9d226d1593dbb 100644 (file)
@@ -10,6 +10,9 @@
 
 #include <linux/sizes.h>
 
+/* enable PMIC */
+#define CONFIG_AS3722_POWER
+
 #include "tegra124-common.h"
 
 /* High-level configuration options */
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
index 06853285a25d70648d6b9f989d1706987773158b..8f1e3709155f476e47f51860369b130df1c67a5a 100644 (file)
@@ -47,7 +47,9 @@
  * Size of malloc() pool
  */
 #define CONFIG_SYS_MALLOC_LEN          (4 << 20)       /* 4MB  */
-#define CONFIG_SYS_MALLOC_F_LEN        (1 << 10)
+#define CONFIG_SYS_MALLOC_F_LEN                (1 << 10)
+
+#define CONFIG_SYS_NONCACHED_MEMORY    (1 << 20)       /* 1 MiB */
 
 /*
  * NS16550 Configuration
index a254f864097f7c2dffd8118c4cdc78183c1750ae..59f4f6767b76a62cf100f15b1c207b5c303f96b6 100644 (file)
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
index 9406207cfac8715b2545a8e77ae8bc7866e838fb..a1ae9a8fdd6c5bbb5bd0472d65791b650b660a6c 100644 (file)
@@ -92,7 +92,7 @@
 #define TEGRA20_CLK_OWR 71
 #define TEGRA20_CLK_AFI 72
 #define TEGRA20_CLK_CSITE 73
-/* 74 */
+#define TEGRA20_CLK_PCIE_XCLK 74
 #define TEGRA20_CLK_AVPUCQ 75
 #define TEGRA20_CLK_LA 76
 /* 77 */
index 889e49ba0aa3de3f3b83ad27b1d0f4b12521a05a..22445820a92925ec1776cf83f8fe3ab9f5a23fa9 100644 (file)
@@ -92,7 +92,7 @@
 #define TEGRA30_CLK_OWR 71
 #define TEGRA30_CLK_AFI 72
 #define TEGRA30_CLK_CSITE 73
-/* 74 */
+#define TEGRA30_CLK_PCIEX 74
 #define TEGRA30_CLK_AVPUCQ 75
 #define TEGRA30_CLK_LA 76
 /* 77 */
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
new file mode 100644 (file)
index 0000000..914d56d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H
+#define _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H 1
+
+#define TEGRA_XUSB_PADCTL_PCIE 0
+#define TEGRA_XUSB_PADCTL_SATA 1
+
+#endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
index d2b665ca119a71348cafe67b0441c0a75f70de1a..5effa240afef3e8a84a2c166b51ee3427bc58c4e 100644 (file)
@@ -86,6 +86,11 @@ enum fdt_compat_id {
        COMPAT_NVIDIA_TEGRA20_SFLASH,   /* Tegra 2 SPI flash controller */
        COMPAT_NVIDIA_TEGRA20_SLINK,    /* Tegra 2 SPI SLINK controller */
        COMPAT_NVIDIA_TEGRA114_SPI,     /* Tegra 114 SPI controller */
+       COMPAT_NVIDIA_TEGRA124_PCIE,    /* Tegra 124 PCIe controller */
+       COMPAT_NVIDIA_TEGRA30_PCIE,     /* Tegra 30 PCIe controller */
+       COMPAT_NVIDIA_TEGRA20_PCIE,     /* Tegra 20 PCIe controller */
+       COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
+                                       /* Tegra124 XUSB pad controller */
        COMPAT_SMSC_LAN9215,            /* SMSC 10/100 Ethernet LAN9215 */
        COMPAT_SAMSUNG_EXYNOS5_SROMC,   /* Exynos5 SROMC */
        COMPAT_SAMSUNG_S3C2440_I2C,     /* Exynos I2C Controller */
@@ -123,6 +128,7 @@ enum fdt_compat_id {
        COMPAT_INTEL_PANTHERPOINT_AHCI, /* Intel Pantherpoint AHCI */
        COMPAT_INTEL_MODEL_206AX,       /* Intel Model 206AX CPU */
        COMPAT_INTEL_GMA,               /* Intel Graphics Media Accelerator */
+       COMPAT_AMS_AS3722,              /* AMS AS3722 PMIC */
 
        COMPAT_COUNT,
 };
diff --git a/include/power/as3722.h b/include/power/as3722.h
new file mode 100644 (file)
index 0000000..aa966d2
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __POWER_AS3722_H__
+#define __POWER_AS3722_H__
+
+#include <asm/types.h>
+
+#define AS3722_GPIO_OUTPUT_VDDH (1 << 0)
+#define AS3722_GPIO_INVERT (1 << 1)
+
+struct udevice;
+
+int as3722_init(struct udevice **devp);
+int as3722_sd_enable(struct udevice *pmic, unsigned int sd);
+int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value);
+int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo);
+int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value);
+int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
+                         unsigned long flags);
+int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
+                                unsigned int level);
+
+#endif /* __POWER_AS3722_H__ */
index 9d86dba32944ccdca97d35cfa02305f1de2508c3..745b39083672f47497d68f4fd95a63c33b385419 100644 (file)
@@ -41,6 +41,10 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
        COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
        COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
+       COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"),
+       COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"),
+       COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"),
+       COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
        COMPAT(SMSC_LAN9215, "smsc,lan9215"),
        COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
        COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
@@ -78,6 +82,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"),
        COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"),
        COMPAT(INTEL_GMA, "intel,gma"),
+       COMPAT(AMS_AS3722, "ams,as3722"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)