diff options
Diffstat (limited to 'arch/arm')
28 files changed, 2693 insertions, 7 deletions
diff --git a/arch/arm/cpu/tegra-common/Makefile b/arch/arm/cpu/tegra-common/Makefile index a18c318..a78869e 100644 --- a/arch/arm/cpu/tegra-common/Makefile +++ b/arch/arm/cpu/tegra-common/Makefile @@ -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 index 0000000..439cff3 --- /dev/null +++ b/arch/arm/cpu/tegra-common/powergate.c @@ -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 index 0000000..65f8d2e --- /dev/null +++ b/arch/arm/cpu/tegra-common/xusb-padctl.c @@ -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) +{ +} diff --git a/arch/arm/cpu/tegra124-common/Makefile b/arch/arm/cpu/tegra124-common/Makefile index ff77992..7b59fb1 100644 --- a/arch/arm/cpu/tegra124-common/Makefile +++ b/arch/arm/cpu/tegra124-common/Makefile @@ -8,3 +8,4 @@ obj-y += clock.o obj-y += funcmux.o obj-y += pinmux.o +obj-y += xusb-padctl.o diff --git a/arch/arm/cpu/tegra124-common/clock.c b/arch/arm/cpu/tegra124-common/clock.c index 7394363..fc8bd19 100644 --- a/arch/arm/cpu/tegra124-common/clock.c +++ b/arch/arm/cpu/tegra124-common/clock.c @@ -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 index 0000000..43af883 --- /dev/null +++ b/arch/arm/cpu/tegra124-common/xusb-padctl.c @@ -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; +} diff --git a/arch/arm/cpu/tegra20-common/clock.c b/arch/arm/cpu/tegra20-common/clock.c index 0c4f5fb..7b9e10c 100644 --- a/arch/arm/cpu/tegra20-common/clock.c +++ b/arch/arm/cpu/tegra20-common/clock.c @@ -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; +} diff --git a/arch/arm/cpu/tegra30-common/clock.c b/arch/arm/cpu/tegra30-common/clock.c index 80ba2d8..0eb0f0a 100644 --- a/arch/arm/cpu/tegra30-common/clock.c +++ b/arch/arm/cpu/tegra30-common/clock.c @@ -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; +} diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts index f6fe9a0..51fef54 100644 --- a/arch/arm/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/dts/tegra124-jetson-tk1.dts @@ -29,6 +29,26 @@ 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>; @@ -49,9 +69,195 @@ 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 { @@ -69,6 +275,32 @@ 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 */ @@ -91,4 +323,145 @@ 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>; + }; + }; }; diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi index 6b5c2be..9fa141d 100644 --- a/arch/arm/dts/tegra124.dtsi +++ b/arch/arm/dts/tegra124.dtsi @@ -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"; @@ -269,6 +349,15 @@ 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>; diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts index 74e8a16..1637cbd 100644 --- a/arch/arm/dts/tegra20-trimslice.dts +++ b/arch/arm/dts/tegra20-trimslice.dts @@ -47,6 +47,20 @@ 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 */ }; @@ -66,4 +80,59 @@ 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; + }; + }; + }; diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi index 5f927f7..b8c8a92 100644 --- a/arch/arm/dts/tegra20.dtsi +++ b/arch/arm/dts/tegra20.dtsi @@ -332,6 +332,65 @@ 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>; diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts index 9acd84d..5903af6 100644 --- a/arch/arm/dts/tegra30-beaver.dts +++ b/arch/arm/dts/tegra30-beaver.dts @@ -28,6 +28,33 @@ 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>; @@ -51,6 +78,110 @@ 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 { @@ -86,4 +217,118 @@ 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>; + }; + }; }; diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts index 1b8ed73..e13d0fb 100644 --- a/arch/arm/dts/tegra30-cardhu.dts +++ b/arch/arm/dts/tegra30-cardhu.dts @@ -27,6 +27,31 @@ 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>; @@ -50,6 +75,107 @@ 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 { @@ -74,4 +200,240 @@ 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>; + }; + }; }; diff --git a/arch/arm/dts/tegra30-colibri.dts b/arch/arm/dts/tegra30-colibri.dts index 572520a..37b6abd 100644 --- a/arch/arm/dts/tegra30-colibri.dts +++ b/arch/arm/dts/tegra30-colibri.dts @@ -27,8 +27,10 @@ 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>; @@ -44,8 +46,10 @@ 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>; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index fb92a0f..5ea7e34 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -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 index 0000000..130b58b --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/powergate.h @@ -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 index 0000000..b4b4c8b --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/xusb-padctl.h @@ -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 index 0000000..260ea80 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra114/powergate.h @@ -0,0 +1,6 @@ +#ifndef _TEGRA114_POWERGATE_H_ +#define _TEGRA114_POWERGATE_H_ + +#include <asm/arch-tegra/powergate.h> + +#endif /* _TEGRA114_POWERGATE_H_ */ diff --git a/arch/arm/include/asm/arch-tegra124/clock.h b/arch/arm/include/asm/arch-tegra124/clock.h index 8e39d21..8e65086 100644 --- a/arch/arm/include/asm/arch-tegra124/clock.h +++ b/arch/arm/include/asm/arch-tegra124/clock.h @@ -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 index 0000000..8a0cfba --- /dev/null +++ b/arch/arm/include/asm/arch-tegra124/powergate.h @@ -0,0 +1,6 @@ +#ifndef _TEGRA124_POWERGATE_H_ +#define _TEGRA124_POWERGATE_H_ + +#include <asm/arch-tegra/powergate.h> + +#endif /* _TEGRA124_POWERGATE_H_ */ diff --git a/arch/arm/include/asm/arch-tegra20/clock-tables.h b/arch/arm/include/asm/arch-tegra20/clock-tables.h index a09cb01..894be08 100644 --- a/arch/arm/include/asm/arch-tegra20/clock-tables.h +++ b/arch/arm/include/asm/arch-tegra20/clock-tables.h @@ -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, diff --git a/arch/arm/include/asm/arch-tegra20/clock.h b/arch/arm/include/asm/arch-tegra20/clock.h index 889c65a..4df8da9 100644 --- a/arch/arm/include/asm/arch-tegra20/clock.h +++ b/arch/arm/include/asm/arch-tegra20/clock.h @@ -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 index 0000000..439d88b --- /dev/null +++ b/arch/arm/include/asm/arch-tegra20/powergate.h @@ -0,0 +1,6 @@ +#ifndef _TEGRA20_POWERGATE_H_ +#define _TEGRA20_POWERGATE_H_ + +#include <asm/arch-tegra/powergate.h> + +#endif /* _TEGRA20_POWERGATE_H_ */ diff --git a/arch/arm/include/asm/arch-tegra30/clock.h b/arch/arm/include/asm/arch-tegra30/clock.h index 2f24a75..410c352 100644 --- a/arch/arm/include/asm/arch-tegra30/clock.h +++ b/arch/arm/include/asm/arch-tegra30/clock.h @@ -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 index 0000000..c70e44b --- /dev/null +++ b/arch/arm/include/asm/arch-tegra30/powergate.h @@ -0,0 +1,6 @@ +#ifndef _TEGRA30_POWERGATE_H_ +#define _TEGRA30_POWERGATE_H_ + +#include <asm/arch-tegra/powergate.h> + +#endif /* _TEGRA30_POWERGATE_H_ */ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 61e2914..89f2294 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -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) diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index f1c0792..9cedeac 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -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 */ |