diff options
Diffstat (limited to 'arch/arm')
68 files changed, 3784 insertions, 173 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2b0d2c9338..5eb1d03cfa 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -800,6 +800,7 @@ config ARCH_UNIPHIER bool "Panasonic UniPhier platform" select CPU_V7 select SUPPORT_SPL + select SPL select OF_CONTROL if !SPL_BUILD endchoice diff --git a/arch/arm/cpu/armv7/bcm281xx/Makefile b/arch/arm/cpu/armv7/bcm281xx/Makefile index bd867a2718..f24aeb3826 100644 --- a/arch/arm/cpu/armv7/bcm281xx/Makefile +++ b/arch/arm/cpu/armv7/bcm281xx/Makefile @@ -10,3 +10,4 @@ obj-y += clk-bcm281xx.o obj-y += clk-sdio.o obj-y += clk-bsc.o obj-$(CONFIG_BCM_SF2_ETH) += clk-eth.o +obj-y += clk-usb-otg.o diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c b/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c index d16b99fc23..7e25255230 100644 --- a/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c +++ b/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c @@ -209,6 +209,10 @@ static struct peri_clk_data sdio4_sleep_data = { .gate = SW_ONLY_GATE(0x0360, 20, 4), }; +static struct bus_clk_data usb_otg_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0348, 16, 0, 1), +}; + static struct bus_clk_data sdio1_ahb_data = { .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1), }; @@ -331,6 +335,17 @@ static struct ccu_clock esub_ccu_clk = { */ /* KPM bus clocks */ +static struct bus_clock usb_otg_ahb_clk = { + .clk = { + .name = "usb_otg_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &usb_otg_ahb_data, +}; + static struct bus_clock sdio1_ahb_clk = { .clk = { .name = "sdio1_ahb_clk", @@ -541,6 +556,7 @@ struct clk_lookup arch_clk_tbl[] = { CLK_LK(bsc2), CLK_LK(bsc3), /* Bus clocks */ + CLK_LK(usb_otg_ahb), CLK_LK(sdio1_ahb), CLK_LK(sdio2_ahb), CLK_LK(sdio3_ahb), diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c b/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c new file mode 100644 index 0000000000..1d7c5af76d --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c @@ -0,0 +1,27 @@ +/* + * Copyright 2014 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/arch/sysmap.h> +#include "clk-core.h" + +/* Enable appropriate clocks for the USB OTG port */ +int clk_usb_otg_enable(void *base) +{ + char *ahbstr; + + switch ((u32) base) { + case HSOTG_BASE_ADDR: + ahbstr = "usb_otg_ahb_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + return clk_get_and_enable(ahbstr); +} diff --git a/arch/arm/cpu/armv7/exynos/Kconfig b/arch/arm/cpu/armv7/exynos/Kconfig index f3eadb4db3..7fcb5d2094 100644 --- a/arch/arm/cpu/armv7/exynos/Kconfig +++ b/arch/arm/cpu/armv7/exynos/Kconfig @@ -24,6 +24,10 @@ config TARGET_TRATS2 config TARGET_ODROID bool "Exynos4412 Odroid board" +config TARGET_ODROID_XU3 + bool "Exynos5422 Odroid board" + select OF_CONTROL + config TARGET_ARNDALE bool "Exynos5250 Arndale board" select CPU_V7_HAS_NONSEC diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 8fab135beb..b31c13b14b 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -848,6 +848,8 @@ static unsigned long exynos5420_get_mmc_clk(int dev_index) if (sel == 0x3) sclk = get_pll_clk(MPLL); + else if (sel == 0x4) + sclk = get_pll_clk(SPLL); else if (sel == 0x6) sclk = get_pll_clk(EPLL); else diff --git a/arch/arm/cpu/armv7/kona-common/clk-stubs.c b/arch/arm/cpu/armv7/kona-common/clk-stubs.c index 338e0e4962..fa10802620 100644 --- a/arch/arm/cpu/armv7/kona-common/clk-stubs.c +++ b/arch/arm/cpu/armv7/kona-common/clk-stubs.c @@ -19,3 +19,8 @@ int __weak clk_bsc_enable(void *base, u32 rate, u32 *actual_ratep) { return 0; } + +int __weak clk_usb_otg_enable(void *base) +{ + return 0; +} diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index a05dca33af..055f44e8e4 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -796,10 +796,11 @@ unsigned int mxc_get_clock(enum mxc_clock clk) case MXC_SATA_CLK: return get_ahb_clk(); default: + printf("Unsupported MXC CLK: %d\n", clk); break; } - return -1; + return 0; } /* diff --git a/arch/arm/cpu/armv7/socfpga/misc.c b/arch/arm/cpu/armv7/socfpga/misc.c index 73cffd3a8d..7873c38e2b 100644 --- a/arch/arm/cpu/armv7/socfpga/misc.c +++ b/arch/arm/cpu/armv7/socfpga/misc.c @@ -9,6 +9,7 @@ #include <altera.h> #include <miiphy.h> #include <netdev.h> +#include <watchdog.h> #include <asm/arch/reset_manager.h> #include <asm/arch/system_manager.h> #include <asm/arch/dwmmc.h> @@ -150,14 +151,23 @@ static inline void socfpga_fpga_add(void) {} int arch_cpu_init(void) { +#ifdef CONFIG_HW_WATCHDOG + /* + * In case the watchdog is enabled, make sure to (re-)configure it + * so that the defined timeout is valid. Otherwise the SPL (Perloader) + * timeout value is still active which might too short for Linux + * booting. + */ + hw_watchdog_init(); +#else /* * If the HW watchdog is NOT enabled, make sure it is not running, * for example because it was enabled in the preloader. This might * trigger a watchdog-triggered reboot of Linux kernel later. */ -#ifndef CONFIG_HW_WATCHDOG socfpga_watchdog_reset(); #endif + return 0; } diff --git a/arch/arm/cpu/armv7/uniphier/Kconfig b/arch/arm/cpu/armv7/uniphier/Kconfig index 97602990aa..0556e4b350 100644 --- a/arch/arm/cpu/armv7/uniphier/Kconfig +++ b/arch/arm/cpu/armv7/uniphier/Kconfig @@ -65,6 +65,13 @@ config DRAM_INIT bool default SPL_BUILD +config CMD_DDRPHY_DUMP + bool "Enable dump command of DDR PHY parameters" + depends on !SPL_BUILD + help + The command "ddrphy" shows the resulting parameters of DDR PHY + training; it is useful for the evaluation of DDR PHY training. + choice prompt "DDR3 Frequency select" depends on DRAM_INIT diff --git a/arch/arm/cpu/armv7/uniphier/Makefile b/arch/arm/cpu/armv7/uniphier/Makefile index 4a7b8a9d08..05462320b5 100644 --- a/arch/arm/cpu/armv7/uniphier/Makefile +++ b/arch/arm/cpu/armv7/uniphier/Makefile @@ -10,11 +10,13 @@ obj-y += reset.o obj-y += cache_uniphier.o obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o obj-y += dram_init.o +obj-$(CONFIG_DRAM_INIT) += ddrphy_training.o obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o obj-$(CONFIG_BOARD_EARLY_INIT_R) += board_early_init_r.o obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o obj-$(CONFIG_UNIPHIER_SMP) += smp.o obj-$(CONFIG_CMD_PINMON) += cmd_pinmon.o +obj-$(CONFIG_CMD_DDRPHY_DUMP) += cmd_ddrphy.o obj-y += board_common.o obj-$(CONFIG_PFC_MICRO_SUPPORT_CARD) += support_card.o diff --git a/arch/arm/cpu/armv7/uniphier/cmd_ddrphy.c b/arch/arm/cpu/armv7/uniphier/cmd_ddrphy.c new file mode 100644 index 0000000000..431d9010f1 --- /dev/null +++ b/arch/arm/cpu/armv7/uniphier/cmd_ddrphy.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2014 Panasonic Corporation + * Author: Masahiro Yamada <yamada.m@jp.panasonic.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/ddrphy-regs.h> + +/* Select either decimal or hexadecimal */ +#if 1 +#define PRINTF_FORMAT "%2d" +#else +#define PRINTF_FORMAT "%02x" +#endif +/* field separator */ +#define FS " " + +static u32 read_bdl(struct ddrphy_datx8 __iomem *dx, int index) +{ + return (readl(&dx->bdlr[index / 5]) >> (index % 5 * 6)) & 0x3f; +} + +static void dump_loop(void (*callback)(struct ddrphy_datx8 __iomem *)) +{ + int ch, p, dx; + struct ddrphy __iomem *phy; + + for (ch = 0; ch < NR_DDRCH; ch++) { + for (p = 0; p < NR_DDRPHY_PER_CH; p++) { + phy = (struct ddrphy __iomem *)DDRPHY_BASE(ch, p); + + for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) { + printf("CH%dP%dDX%d:", ch, p, dx); + (*callback)(&phy->dx[dx]); + printf("\n"); + } + } + } +} + +static void __wbdl_dump(struct ddrphy_datx8 __iomem *dx) +{ + int i; + + for (i = 0; i < 10; i++) + printf(FS PRINTF_FORMAT, read_bdl(dx, i)); + + printf(FS "(+" PRINTF_FORMAT ")", readl(&dx->lcdlr[1]) & 0xff); +} + +void wbdl_dump(void) +{ + printf("\n--- Write Bit Delay Line ---\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n"); + + dump_loop(&__wbdl_dump); +} + +static void __rbdl_dump(struct ddrphy_datx8 __iomem *dx) +{ + int i; + + for (i = 15; i < 24; i++) + printf(FS PRINTF_FORMAT, read_bdl(dx, i)); + + printf(FS "(+" PRINTF_FORMAT ")", (readl(&dx->lcdlr[1]) >> 8) & 0xff); +} + +void rbdl_dump(void) +{ + printf("\n--- Read Bit Delay Line ---\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD)\n"); + + dump_loop(&__rbdl_dump); +} + +static void __wld_dump(struct ddrphy_datx8 __iomem *dx) +{ + int rank; + u32 lcdlr0 = readl(&dx->lcdlr[0]); + u32 gtr = readl(&dx->gtr); + + for (rank = 0; rank < 4; rank++) { + u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */ + u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */ + + printf(FS PRINTF_FORMAT "%sT", wld, + wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1"); + } +} + +void wld_dump(void) +{ + printf("\n--- Write Leveling Delay ---\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); + + dump_loop(&__wld_dump); +} + +static void __dqsgd_dump(struct ddrphy_datx8 __iomem *dx) +{ + int rank; + u32 lcdlr2 = readl(&dx->lcdlr[2]); + u32 gtr = readl(&dx->gtr); + + for (rank = 0; rank < 4; rank++) { + u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */ + u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */ + + printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl); + } +} + +void dqsgd_dump(void) +{ + printf("\n--- DQS Gating Delay ---\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); + + dump_loop(&__dqsgd_dump); +} + +static void __mdl_dump(struct ddrphy_datx8 __iomem *dx) +{ + int i; + u32 mdl = readl(&dx->mdlr); + for (i = 0; i < 3; i++) + printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff); +} + +void mdl_dump(void) +{ + printf("\n--- Master Delay Line ---\n"); + printf(" IPRD TPRD MDLD\n"); + + dump_loop(&__mdl_dump); +} + +#define REG_DUMP(x) \ + { u32 __iomem *p = &phy->x; printf("%3d: %-10s: %p : %08x\n", \ + p - (u32 *)phy, #x, p, readl(p)); } + +void reg_dump(void) +{ + int ch, p; + struct ddrphy __iomem *phy; + + printf("\n--- DDR PHY registers ---\n"); + + for (ch = 0; ch < NR_DDRCH; ch++) { + for (p = 0; p < NR_DDRPHY_PER_CH; p++) { + printf("== Ch%d, PHY%d ==\n", ch, p); + printf(" No: Name : Address : Data\n"); + + phy = (struct ddrphy __iomem *)DDRPHY_BASE(ch, p); + + REG_DUMP(ridr); + REG_DUMP(pir); + REG_DUMP(pgcr[0]); + REG_DUMP(pgcr[1]); + REG_DUMP(pgsr[0]); + REG_DUMP(pgsr[1]); + REG_DUMP(pllcr); + REG_DUMP(ptr[0]); + REG_DUMP(ptr[1]); + REG_DUMP(ptr[2]); + REG_DUMP(ptr[3]); + REG_DUMP(ptr[4]); + REG_DUMP(acmdlr); + REG_DUMP(acbdlr); + REG_DUMP(dxccr); + REG_DUMP(dsgcr); + REG_DUMP(dcr); + REG_DUMP(dtpr[0]); + REG_DUMP(dtpr[1]); + REG_DUMP(dtpr[2]); + REG_DUMP(mr0); + REG_DUMP(mr1); + REG_DUMP(mr2); + REG_DUMP(mr3); + REG_DUMP(dx[0].gcr); + REG_DUMP(dx[0].gtr); + REG_DUMP(dx[1].gcr); + REG_DUMP(dx[1].gtr); + } + } +} + +static int do_ddr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *cmd = argv[1]; + + if (argc == 1) + cmd = "all"; + + if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all")) + wbdl_dump(); + + if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all")) + rbdl_dump(); + + if (!strcmp(cmd, "wld") || !strcmp(cmd, "all")) + wld_dump(); + + if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all")) + dqsgd_dump(); + + if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all")) + mdl_dump(); + + if (!strcmp(cmd, "reg") || !strcmp(cmd, "all")) + reg_dump(); + + return 0; +} + +U_BOOT_CMD( + ddr, 2, 1, do_ddr, + "UniPhier DDR PHY parameters dumper", + "- dump all of the followings\n" + "ddr wbdl - dump Write Bit Delay\n" + "ddr rbdl - dump Read Bit Delay\n" + "ddr wld - dump Write Leveling\n" + "ddr dqsgd - dump DQS Gating Delay\n" + "ddr mdl - dump Master Delay Line\n" + "ddr reg - dump registers\n" +); diff --git a/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c b/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c index eef9f39840..3561b40a33 100644 --- a/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c +++ b/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c @@ -7,6 +7,7 @@ #include <common.h> #include <asm/arch/boot-device.h> +#include <asm/arch/sbc-regs.h> static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -15,6 +16,8 @@ static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) mode_sel = get_boot_mode_sel(); + printf("Boot Swap: %s\n\n", boot_is_swapped() ? "ON" : "OFF"); + puts("Boot Mode Pin:\n"); for (table = boot_device_table; strlen(table->info); table++) { diff --git a/arch/arm/cpu/armv7/uniphier/ddrphy_training.c b/arch/arm/cpu/armv7/uniphier/ddrphy_training.c new file mode 100644 index 0000000000..cc8b8ad648 --- /dev/null +++ b/arch/arm/cpu/armv7/uniphier/ddrphy_training.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Author: Masahiro Yamada <yamada.m@jp.panasonic.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/ddrphy-regs.h> + +void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank) +{ + int dx; + u32 __iomem tmp, *p; + + for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) { + p = &phy->dx[dx].gcr; + + tmp = readl(p); + /* Specify the rank that should be write leveled */ + tmp &= ~DXGCR_WLRKEN_MASK; + tmp |= (1 << (DXGCR_WLRKEN_SHIFT + rank)) & DXGCR_WLRKEN_MASK; + writel(tmp, p); + } + + p = &phy->dtcr; + + tmp = readl(p); + /* Specify the rank used during data bit deskew and eye centering */ + tmp &= ~DTCR_DTRANK_MASK; + tmp |= (rank << DTCR_DTRANK_SHIFT) & DTCR_DTRANK_MASK; + /* Use Multi-Purpose Register for DQS gate training */ + tmp |= DTCR_DTMPR; + /* Specify the rank enabled for data-training */ + tmp &= ~DTCR_RNKEN_MASK; + tmp |= (1 << (DTCR_RNKEN_SHIFT + rank)) & DTCR_RNKEN_MASK; + writel(tmp, p); +} + +struct ddrphy_init_sequence { + char *description; + u32 init_flag; + u32 done_flag; + u32 err_flag; +}; + +static struct ddrphy_init_sequence init_sequence[] = { + { + "DRAM Initialization", + PIR_DRAMRST | PIR_DRAMINIT, + PGSR0_DIDONE, + PGSR0_DIERR + }, + { + "Write Leveling", + PIR_WL, + PGSR0_WLDONE, + PGSR0_WLERR + }, + { + "Read DQS Gate Training", + PIR_QSGATE, + PGSR0_QSGDONE, + PGSR0_QSGERR + }, + { + "Write Leveling Adjustment", + PIR_WLADJ, + PGSR0_WLADONE, + PGSR0_WLAERR + }, + { + "Read Bit Deskew", + PIR_RDDSKW, + PGSR0_RDDONE, + PGSR0_RDERR + }, + { + "Write Bit Deskew", + PIR_WRDSKW, + PGSR0_WDDONE, + PGSR0_WDERR + }, + { + "Read Eye Training", + PIR_RDEYE, + PGSR0_REDONE, + PGSR0_REERR + }, + { + "Write Eye Training", + PIR_WREYE, + PGSR0_WEDONE, + PGSR0_WEERR + } +}; + +int ddrphy_training(struct ddrphy __iomem *phy) +{ + int i; + u32 pgsr0; + u32 init_flag = PIR_INIT; + u32 done_flag = PGSR0_IDONE; + int timeout = 50000; /* 50 msec is long enough */ +#ifdef DISPLAY_ELAPSED_TIME + ulong start = get_timer(0); +#endif + + for (i = 0; i < ARRAY_SIZE(init_sequence); i++) { + init_flag |= init_sequence[i].init_flag; + done_flag |= init_sequence[i].done_flag; + } + + writel(init_flag, &phy->pir); + + do { + if (--timeout < 0) { +#ifndef CONFIG_SPL_BUILD + printf("%s: error: timeout during DDR training\n", + __func__); +#endif + return -1; + } + udelay(1); + pgsr0 = readl(&phy->pgsr[0]); + } while ((pgsr0 & done_flag) != done_flag); + + for (i = 0; i < ARRAY_SIZE(init_sequence); i++) { + if (pgsr0 & init_sequence[i].err_flag) { +#ifndef CONFIG_SPL_BUILD + printf("%s: error: %s failed\n", __func__, + init_sequence[i].description); +#endif + return -1; + } + } + +#ifdef DISPLAY_ELAPSED_TIME + printf("%s: info: elapsed time %ld msec\n", get_timer(start)); +#endif + + return 0; +} diff --git a/arch/arm/cpu/armv7/uniphier/init_page_table.c b/arch/arm/cpu/armv7/uniphier/init_page_table.c index a0d10a995d..febb3c8e4b 100644 --- a/arch/arm/cpu/armv7/uniphier/init_page_table.c +++ b/arch/arm/cpu/armv7/uniphier/init_page_table.c @@ -17,11 +17,7 @@ #define REG DEVICE /* IO Register: Device */ #define DDR DEVICE /* DDR SDRAM: Device */ -#ifdef CONFIG_SPL_BUILD #define IS_SPL_TEXT_AREA(x) ((x) == ((CONFIG_SPL_TEXT_BASE) >> 20)) -#else -#define IS_SPL_TEXT_AREA(x) ((x) == ((CONFIG_SYS_TEXT_BASE) >> 20)) -#endif #define IS_INIT_STACK_AREA(x) ((x) == ((CONFIG_SYS_INIT_SP_ADDR) >> 20)) diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile index 5d682d3ca3..8794629b2a 100644 --- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile +++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile @@ -8,4 +8,4 @@ obj-y += boot-mode.o obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \ clkrst_init.o obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o -obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o +obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/ddrphy_init.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/ddrphy_init.c new file mode 100644 index 0000000000..60fc5ad6ea --- /dev/null +++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/ddrphy_init.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2014 Panasonic Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <linux/types.h> +#include <asm/io.h> +#include <asm/arch/ddrphy-regs.h> + +void ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) +{ + u32 tmp; + + writel(0x0300c473, &phy->pgcr[1]); + if (freq == 1333) { + writel(0x0a806844, &phy->ptr[0]); + writel(0x208e0124, &phy->ptr[1]); + } else { + writel(0x0c807d04, &phy->ptr[0]); + writel(0x2710015E, &phy->ptr[1]); + } + writel(0x00083DEF, &phy->ptr[2]); + if (freq == 1333) { + writel(0x0f051616, &phy->ptr[3]); + writel(0x06ae08d6, &phy->ptr[4]); + } else { + writel(0x12061A80, &phy->ptr[3]); + writel(0x08027100, &phy->ptr[4]); + } + writel(0xF004001A, &phy->dsgcr); + + /* change the value of the on-die pull-up/pull-down registors */ + tmp = readl(&phy->dxccr); + tmp &= ~0x0ee0; + tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM; + writel(tmp, &phy->dxccr); + + writel(0x0000040B, &phy->dcr); + if (freq == 1333) { + writel(0x85589955, &phy->dtpr[0]); + if (size == 1) + writel(0x1a8253c0, &phy->dtpr[1]); + else + writel(0x1a8363c0, &phy->dtpr[1]); + writel(0x5002c200, &phy->dtpr[2]); + writel(0x00000b51, &phy->mr0); + } else { + writel(0x999cbb66, &phy->dtpr[0]); + if (size == 1) + writel(0x1a82dbc0, &phy->dtpr[1]); + else + writel(0x1a878400, &phy->dtpr[1]); + writel(0xa00214f8, &phy->dtpr[2]); + writel(0x00000d71, &phy->mr0); + } + writel(0x00000006, &phy->mr1); + if (freq == 1333) + writel(0x00000290, &phy->mr2); + else + writel(0x00000298, &phy->mr2); + + writel(0x00000800, &phy->mr3); + + while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) + ; + + writel(0x0300C473, &phy->pgcr[1]); + writel(0x0000005D, &phy->zq[0].cr[1]); +} diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c index ebcbaabf65..87889160a7 100644 --- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c +++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c @@ -7,6 +7,7 @@ #include <common.h> #include <asm/io.h> #include <asm/arch/umc-regs.h> +#include <asm/arch/ddrphy-regs.h> static inline void umc_start_ssif(void __iomem *ssif_base) { @@ -125,6 +126,8 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1) void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); + void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); + void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); umc_dram_init_start(dramcont0); umc_dram_init_start(dramcont1); @@ -133,8 +136,18 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1) writel(0x00000101, dramcont0 + UMC_DIOCTLA); + ddrphy_init(phy0_0, freq, size_ch0); + + ddrphy_prepare_training(phy0_0, 0); + ddrphy_training(phy0_0); + writel(0x00000101, dramcont1 + UMC_DIOCTLA); + ddrphy_init(phy1_0, freq, size_ch1); + + ddrphy_prepare_training(phy1_0, 1); + ddrphy_training(phy1_0); + umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile index fd1c432f4f..cee78781f6 100644 --- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile +++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile @@ -7,4 +7,4 @@ obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o obj-y += boot-mode.o obj-$(CONFIG_SOC_INIT) += sbc_init.o sg_init.o pll_init.o clkrst_init.o obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o -obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o +obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/ddrphy_init.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/ddrphy_init.c new file mode 100644 index 0000000000..c5d1f606cf --- /dev/null +++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/ddrphy_init.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2014 Panasonic Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <linux/types.h> +#include <asm/io.h> +#include <asm/arch/ddrphy-regs.h> + +void ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) +{ + u32 tmp; + + writel(0x0300c473, &phy->pgcr[1]); + if (freq == 1333) { + writel(0x0a806844, &phy->ptr[0]); + writel(0x208e0124, &phy->ptr[1]); + } else { + writel(0x0c807d04, &phy->ptr[0]); + writel(0x2710015E, &phy->ptr[1]); + } + writel(0x00083DEF, &phy->ptr[2]); + if (freq == 1333) { + writel(0x0f051616, &phy->ptr[3]); + writel(0x06ae08d6, &phy->ptr[4]); + } else { + writel(0x12061A80, &phy->ptr[3]); + writel(0x08027100, &phy->ptr[4]); + } + writel(0xF004001A, &phy->dsgcr); + + /* change the value of the on-die pull-up/pull-down registors */ + tmp = readl(&phy->dxccr); + tmp &= ~0x0ee0; + tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM; + writel(tmp, &phy->dxccr); + + writel(0x0000040B, &phy->dcr); + if (freq == 1333) { + writel(0x85589955, &phy->dtpr[0]); + if (size == 1) + writel(0x1a8363c0, &phy->dtpr[1]); + else + writel(0x1a8363c0, &phy->dtpr[1]); + writel(0x5002c200, &phy->dtpr[2]); + writel(0x00000b51, &phy->mr0); + } else { + writel(0x999cbb66, &phy->dtpr[0]); + if (size == 1) + writel(0x1a878400, &phy->dtpr[1]); + else + writel(0x1a878400, &phy->dtpr[1]); + writel(0xa00214f8, &phy->dtpr[2]); + writel(0x00000d71, &phy->mr0); + } + writel(0x00000006, &phy->mr1); + if (freq == 1333) + writel(0x00000290, &phy->mr2); + else + writel(0x00000298, &phy->mr2); + + writel(0x00000000, &phy->mr3); + + while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) + ; + + writel(0x0300C473, &phy->pgcr[1]); + writel(0x0000005D, &phy->zq[0].cr[1]); +} diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c index 328b2f4d9a..1973ab04c2 100644 --- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c +++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c @@ -7,6 +7,7 @@ #include <common.h> #include <asm/io.h> #include <asm/arch/umc-regs.h> +#include <asm/arch/ddrphy-regs.h> static inline void umc_start_ssif(void __iomem *ssif_base) { @@ -94,6 +95,10 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1) void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); + void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); + void __iomem *phy0_1 = (void __iomem *)DDRPHY_BASE(0, 1); + void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); + void __iomem *phy1_1 = (void __iomem *)DDRPHY_BASE(1, 1); umc_dram_init_start(dramcont0); umc_dram_init_start(dramcont1); @@ -102,12 +107,32 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1) writel(0x00000101, dramcont0 + UMC_DIOCTLA); + ddrphy_init(phy0_0, freq, size_ch0); + + ddrphy_prepare_training(phy0_0, 0); + ddrphy_training(phy0_0); + writel(0x00000103, dramcont0 + UMC_DIOCTLA); + ddrphy_init(phy0_1, freq, size_ch0); + + ddrphy_prepare_training(phy0_1, 1); + ddrphy_training(phy0_1); + writel(0x00000101, dramcont1 + UMC_DIOCTLA); + ddrphy_init(phy1_0, freq, size_ch1); + + ddrphy_prepare_training(phy1_0, 0); + ddrphy_training(phy1_0); + writel(0x00000103, dramcont1 + UMC_DIOCTLA); + ddrphy_init(phy1_1, freq, size_ch1); + + ddrphy_prepare_training(phy1_1, 1); + ddrphy_training(phy1_1); + umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile index 5d682d3ca3..8794629b2a 100644 --- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile +++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile @@ -8,4 +8,4 @@ obj-y += boot-mode.o obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \ clkrst_init.o obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o -obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o +obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/ddrphy_init.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/ddrphy_init.c new file mode 100644 index 0000000000..a5eafef9a8 --- /dev/null +++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/ddrphy_init.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014 Panasonic Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <linux/types.h> +#include <asm/io.h> +#include <asm/arch/ddrphy-regs.h> + +void ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) +{ + u32 tmp; + + writel(0x0300c473, &phy->pgcr[1]); + if (freq == 1333) { + writel(0x0a806844, &phy->ptr[0]); + writel(0x208e0124, &phy->ptr[1]); + } else { + writel(0x0c807d04, &phy->ptr[0]); + writel(0x2710015E, &phy->ptr[1]); + } + writel(0x00083DEF, &phy->ptr[2]); + if (freq == 1333) { + writel(0x0f051616, &phy->ptr[3]); + writel(0x06ae08d6, &phy->ptr[4]); + } else { + writel(0x12061A80, &phy->ptr[3]); + writel(0x08027100, &phy->ptr[4]); + } + writel(0xF004001A, &phy->dsgcr); + + /* change the value of the on-die pull-up/pull-down registors */ + tmp = readl(&phy->dxccr); + tmp &= ~0x0ee0; + tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM; + writel(tmp, &phy->dxccr); + + writel(0x0000040B, &phy->dcr); + if (freq == 1333) { + writel(0x85589955, &phy->dtpr[0]); + if (size == 1) + writel(0x1a8363c0, &phy->dtpr[1]); + else + writel(0x1a8363c0, &phy->dtpr[1]); + writel(0x5002c200, &phy->dtpr[2]); + writel(0x00000b51, &phy->mr0); + } else { + writel(0x999cbb66, &phy->dtpr[0]); + if (size == 1) + writel(0x1a878400, &phy->dtpr[1]); + else + writel(0x1a878400, &phy->dtpr[1]); + writel(0xa00214f8, &phy->dtpr[2]); + writel(0x00000d71, &phy->mr0); + } + writel(0x00000006, &phy->mr1); + if (freq == 1333) + writel(0x00000290, &phy->mr2); + else + writel(0x00000298, &phy->mr2); + +#ifdef CONFIG_DDR_STANDARD + writel(0x00000000, &phy->mr3); +#else + writel(0x00000800, &phy->mr3); +#endif + + while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) + ; + + writel(0x0300C473, &phy->pgcr[1]); + writel(0x0000005D, &phy->zq[0].cr[1]); +} diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c index a44f999fbf..2e0f9aeaa5 100644 --- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c +++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c @@ -7,6 +7,7 @@ #include <common.h> #include <asm/io.h> #include <asm/arch/umc-regs.h> +#include <asm/arch/ddrphy-regs.h> static inline void umc_start_ssif(void __iomem *ssif_base) { @@ -105,6 +106,8 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1) void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); + void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); + void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); umc_dram_init_start(dramcont0); umc_dram_init_start(dramcont1); @@ -113,8 +116,18 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1) writel(0x00000101, dramcont0 + UMC_DIOCTLA); + ddrphy_init(phy0_0, freq, size_ch0); + + ddrphy_prepare_training(phy0_0, 0); + ddrphy_training(phy0_0); + writel(0x00000101, dramcont1 + UMC_DIOCTLA); + ddrphy_init(phy1_0, freq, size_ch1); + + ddrphy_prepare_training(phy1_0, 1); + ddrphy_training(phy1_0); + umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); diff --git a/arch/arm/cpu/tegra-common/Makefile b/arch/arm/cpu/tegra-common/Makefile index a18c318739..a78869ee23 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 0000000000..439cff36b9 --- /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 0000000000..65f8d2ea96 --- /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 ff77992b33..7b59fb1216 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 739436326e..fc8bd194dd 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 0000000000..43af883f2c --- /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 0c4f5fb288..7b9e10cd93 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 80ba2d8c1c..0eb0f0ade3 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/Makefile b/arch/arm/dts/Makefile index e6a495cb0d..fac16cc384 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -13,7 +13,8 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \ exynos5250-smdk5250.dtb \ exynos5420-smdk5420.dtb \ exynos5420-peach-pit.dtb \ - exynos5800-peach-pi.dtb + exynos5800-peach-pi.dtb \ + exynos5422-odroidxu3.dtb dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \ tegra20-medcom-wide.dtb \ tegra20-paz00.dtb \ diff --git a/arch/arm/dts/exynos5422-odroidxu3.dts b/arch/arm/dts/exynos5422-odroidxu3.dts new file mode 100644 index 0000000000..79a7acd7df --- /dev/null +++ b/arch/arm/dts/exynos5422-odroidxu3.dts @@ -0,0 +1,49 @@ +/* + * Odroid XU3 device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include "exynos54xx.dtsi" + +/ { + model = "Odroid XU3 based on EXYNOS5422"; + compatible = "samsung,odroidxu3", "samsung,exynos5"; + + aliases { + serial0 = "/serial@12C00000"; + console = "/serial@12C20000"; + }; + + memory { + device_type = "memory"; + reg = <0x40000000 0x10000000 + 0x50000000 0x10000000 + 0x60000000 0x10000000 + 0x70000000 0x10000000 + 0x80000000 0x10000000 + 0x90000000 0x10000000 + 0xa0000000 0x10000000 + 0xb0000000 0xea00000>; + }; + + ehci@12110000 { + samsung,vbus-gpio = <&gpio 0x66 0>; /* X26 */ + }; + + serial@12C20000 { + status="okay"; + }; + + mmc@12200000 { + fifoth_val = <0x201f0020>; + }; + + mmc@12220000 { + fifoth_val = <0x201f0020>; + }; +}; diff --git a/arch/arm/dts/exynos5800-peach-pi.dts b/arch/arm/dts/exynos5800-peach-pi.dts index 8aedf8e707..2f9d2dbd54 100644 --- a/arch/arm/dts/exynos5800-peach-pi.dts +++ b/arch/arm/dts/exynos5800-peach-pi.dts @@ -63,11 +63,6 @@ reg = <0x20>; compatible = "maxim,max98090-codec"; }; - - edp-lvds-bridge@48 { - compatible = "parade,ps8625"; - reg = <0x48>; - }; }; sound@3830000 { diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts index f6fe9a050f..51fef54d57 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 6b5c2bea63..9fa141d8fe 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 74e8a16280..1637cbd58e 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 5f927f7e0d..b8c8a92301 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 9acd84d802..5903af6838 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 1b8ed737e0..e13d0fb467 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 572520a00e..37b6abd52f 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 fb92a0fef9..5ea7e347f3 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/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts index 08bbd032c9..6855878c29 100644 --- a/arch/arm/dts/uniphier-ph1-ld4-ref.dts +++ b/arch/arm/dts/uniphier-ph1-ld4-ref.dts @@ -25,10 +25,10 @@ }; aliases { - uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; - uart3 = &uart3; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; diff --git a/arch/arm/dts/uniphier-ph1-pro4-ref.dts b/arch/arm/dts/uniphier-ph1-pro4-ref.dts index 23add7cfd0..1227b628d1 100644 --- a/arch/arm/dts/uniphier-ph1-pro4-ref.dts +++ b/arch/arm/dts/uniphier-ph1-pro4-ref.dts @@ -25,10 +25,10 @@ }; aliases { - uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; - uart3 = &uart3; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; diff --git a/arch/arm/dts/uniphier-ph1-sld3-ref.dts b/arch/arm/dts/uniphier-ph1-sld3-ref.dts index 91b4dbe0b1..fefc592589 100644 --- a/arch/arm/dts/uniphier-ph1-sld3-ref.dts +++ b/arch/arm/dts/uniphier-ph1-sld3-ref.dts @@ -25,9 +25,9 @@ }; aliases { - uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; diff --git a/arch/arm/dts/uniphier-ph1-sld8-ref.dts b/arch/arm/dts/uniphier-ph1-sld8-ref.dts index a8ce049d6c..9b6d95c480 100644 --- a/arch/arm/dts/uniphier-ph1-sld8-ref.dts +++ b/arch/arm/dts/uniphier-ph1-sld8-ref.dts @@ -25,10 +25,10 @@ }; aliases { - uart0 = &uart0; - uart1 = &uart1; - uart2 = &uart2; - uart3 = &uart3; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; diff --git a/arch/arm/imx-common/i2c-mxv7.c b/arch/arm/imx-common/i2c-mxv7.c index 34f53872e8..1a632e7203 100644 --- a/arch/arm/imx-common/i2c-mxv7.c +++ b/arch/arm/imx-common/i2c-mxv7.c @@ -73,26 +73,21 @@ static void * const i2c_bases[] = { int setup_i2c(unsigned i2c_index, int speed, int slave_addr, struct i2c_pads_info *p) { - char *name1, *name2; + char name[9]; int ret; if (i2c_index >= ARRAY_SIZE(i2c_bases)) return -EINVAL; - name1 = malloc(9); - name2 = malloc(9); - if (!name1 || !name2) - return -ENOMEM; - - sprintf(name1, "i2c_sda%d", i2c_index); - sprintf(name2, "i2c_scl%d", i2c_index); - ret = gpio_request(p->sda.gp, name1); + snprintf(name, sizeof(name), "i2c_sda%01d", i2c_index); + ret = gpio_request(p->sda.gp, name); if (ret) - goto err_req1; + return ret; - ret = gpio_request(p->scl.gp, name2); + snprintf(name, sizeof(name), "i2c_scl%01d", i2c_index); + ret = gpio_request(p->scl.gp, name); if (ret) - goto err_req2; + goto err_req; /* Enable i2c clock */ ret = enable_i2c_clk(1, i2c_index); @@ -112,11 +107,8 @@ int setup_i2c(unsigned i2c_index, int speed, int slave_addr, err_idle: err_clk: gpio_free(p->scl.gp); -err_req2: +err_req: gpio_free(p->sda.gp); -err_req1: - free(name1); - free(name2); return ret; } diff --git a/arch/arm/imx-common/spl.c b/arch/arm/imx-common/spl.c index 477c38c1e2..ac6e40e83b 100644 --- a/arch/arm/imx-common/spl.c +++ b/arch/arm/imx-common/spl.c @@ -68,8 +68,10 @@ u32 spl_boot_mode(void) /* for MMC return either RAW or FAT mode */ case BOOT_DEVICE_MMC1: case BOOT_DEVICE_MMC2: -#ifdef CONFIG_SPL_FAT_SUPPORT +#if defined(CONFIG_SPL_FAT_SUPPORT) return MMCSD_MODE_FS; +#elif defined(CONFIG_SUPPORT_EMMC_BOOT) + return MMCSD_MODE_EMMCBOOT; #else return MMCSD_MODE_RAW; #endif diff --git a/arch/arm/include/asm/arch-bcm281xx/sysmap.h b/arch/arm/include/asm/arch-bcm281xx/sysmap.h index 350e7f6b72..93ebf3429a 100644 --- a/arch/arm/include/asm/arch-bcm281xx/sysmap.h +++ b/arch/arm/include/asm/arch-bcm281xx/sysmap.h @@ -13,6 +13,8 @@ #define ESUB_CLK_BASE_ADDR 0x38000000 #define ESW_CONTRL_BASE_ADDR 0x38200000 #define GPIO2_BASE_ADDR 0x35003000 +#define HSOTG_BASE_ADDR 0x3f120000 +#define HSOTG_CTRL_BASE_ADDR 0x3f130000 #define KONA_MST_CLK_BASE_ADDR 0x3f001000 #define KONA_SLV_CLK_BASE_ADDR 0x3e011000 #define PMU_BSC_BASE_ADDR 0x3500d000 diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h b/arch/arm/include/asm/arch-bcm2835/mbox.h index 0289ba6a91..88d2ec11a7 100644 --- a/arch/arm/include/asm/arch-bcm2835/mbox.h +++ b/arch/arm/include/asm/arch-bcm2835/mbox.h @@ -140,6 +140,7 @@ struct bcm2835_mbox_tag_hdr { #define BCM2835_BOARD_REV_B_REV2_f 0xf #define BCM2835_BOARD_REV_B_PLUS 0x10 #define BCM2835_BOARD_REV_CM 0x11 +#define BCM2835_BOARD_REV_A_PLUS 0x12 struct bcm2835_mbox_tag_get_board_rev { struct bcm2835_mbox_tag_hdr tag_hdr; diff --git a/arch/arm/include/asm/arch-exynos/system.h b/arch/arm/include/asm/arch-exynos/system.h index 320763fd8c..4968d3dd2e 100644 --- a/arch/arm/include/asm/arch-exynos/system.h +++ b/arch/arm/include/asm/arch-exynos/system.h @@ -41,7 +41,4 @@ void set_usbhost_mode(unsigned int mode); void set_system_display_ctrl(void); int exynos_lcd_early_init(const void *blob); -/* Initialize the Parade dP<->LVDS bridge if present */ -int parade_init(const void *blob); - #endif /* _EXYNOS4_SYSTEM_H */ 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 0000000000..130b58bef1 --- /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 0000000000..b4b4c8ba4d --- /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 0000000000..260ea801b8 --- /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 8e39d21a7b..8e65086252 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 0000000000..8a0cfbaf96 --- /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 a09cb01978..894be088cd 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 889c65a16f..4df8da96e2 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 0000000000..439d88b702 --- /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 2f24a75cc4..410c352899 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 0000000000..c70e44b621 --- /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/arch-uniphier/ddrphy-regs.h b/arch/arm/include/asm/arch-uniphier/ddrphy-regs.h new file mode 100644 index 0000000000..484559c6cd --- /dev/null +++ b/arch/arm/include/asm/arch-uniphier/ddrphy-regs.h @@ -0,0 +1,172 @@ +/* + * UniPhier DDR PHY registers + * + * Copyright (C) 2014 Panasonic Corporation + * Author: Masahiro Yamada <yamada.m@jp.panasonic.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef ARCH_DDRPHY_REGS_H +#define ARCH_DDRPHY_REGS_H + +#include <linux/compiler.h> + +#ifndef __ASSEMBLY__ + +struct ddrphy { + u32 ridr; /* Revision Identification Register */ + u32 pir; /* PHY Initialixation Register */ + u32 pgcr[2]; /* PHY General Configuration Register */ + u32 pgsr[2]; /* PHY General Status Register */ + u32 pllcr; /* PLL Control Register */ + u32 ptr[5]; /* PHY Timing Register */ + u32 acmdlr; /* AC Master Delay Line Register */ + u32 acbdlr; /* AC Bit Delay Line Register */ + u32 aciocr; /* AC I/O Configuration Register */ + u32 dxccr; /* DATX8 Common Configuration Register */ + u32 dsgcr; /* DDR System General Configuration Register */ + u32 dcr; /* DRAM Configuration Register */ + u32 dtpr[3]; /* DRAM Timing Parameters Register */ + u32 mr0; /* Mode Register 0 */ + u32 mr1; /* Mode Register 1 */ + u32 mr2; /* Mode Register 2 */ + u32 mr3; /* Mode Register 3 */ + u32 odtcr; /* ODT Configuration Register */ + u32 dtcr; /* Data Training Configuration Register */ + u32 dtar[4]; /* Data Training Address Register */ + u32 dtdr[2]; /* Data Training Data Register */ + u32 dtedr[2]; /* Data Training Eye Data Register */ + u32 rsv0[13]; /* Reserved */ + u32 dcuar; /* DCU Address Register */ + u32 dcudr; /* DCU Data Register */ + u32 dcurr; /* DCU Run Register */ + u32 dculr; /* DCU Loop Register */ + u32 dcugcr; /* DCU General Configuration Register */ + u32 dcutpr; /* DCU Timing Parameters Register */ + u32 dcusr[2]; /* DCU Status Register */ + u32 rsv1[8]; /* Reserved */ + u32 bistrr; /* BIST Run Register */ + u32 bistwcr; /* BIST Word Count Register */ + u32 bistmskr[3]; /* BIST Mask Register */ + u32 bistlsr; /* BIST LFSR Sed Register */ + u32 bistar[3]; /* BIST Address Register */ + u32 bistudpr; /* BIST User Data Pattern Register */ + u32 bistgsr; /* BIST General Status Register */ + u32 bistwer; /* BIST Word Error Register */ + u32 bistber[4]; /* BIST Bit Error Register */ + u32 bistwcsr; /* BIST Word Count Status Register */ + u32 bistfwr[3]; /* BIST Fail Word Register */ + u32 rsv2[10]; /* Reserved */ + u32 gpr[2]; /* General Purpose Register */ + struct ddrphy_zq { /* ZQ */ + u32 cr[2]; /* Impedance Control Register */ + u32 sr[2]; /* Impedance Status Register */ + } zq[4]; + struct ddrphy_datx8 { /* DATX8 */ + u32 gcr; /* General Configuration Register */ + u32 gsr[2]; /* General Status Register */ + u32 bdlr[5]; /* Bit Delay Line Register */ + u32 lcdlr[3]; /* Local Calibrated Delay Line Register */ + u32 mdlr; /* Master Delay Line Register */ + u32 gtr; /* General Timing Register */ + u32 rsv[3]; /* Reserved */ + } dx[9]; +} __packed; + +#endif /* __ASSEMBLY__ */ + +#define PIR_INIT (1 << 0) /* Initialization Trigger */ +#define PIR_ZCAL (1 << 1) /* Impedance Calibration */ +#define PIR_PLLINIT (1 << 4) /* PLL Initialization */ +#define PIR_DCAL (1 << 5) /* DDL Calibration */ +#define PIR_PHYRST (1 << 6) /* PHY Reset */ +#define PIR_DRAMRST (1 << 7) /* DRAM Reset */ +#define PIR_DRAMINIT (1 << 8) /* DRAM Initialization */ +#define PIR_WL (1 << 9) /* Write Leveling */ +#define PIR_QSGATE (1 << 10) /* Read DQS Gate Training */ +#define PIR_WLADJ (1 << 11) /* Write Leveling Adjust */ +#define PIR_RDDSKW (1 << 12) /* Read Data Bit Deskew */ +#define PIR_WRDSKW (1 << 13) /* Write Data Bit Deskew */ +#define PIR_RDEYE (1 << 14) /* Read Data Eye Training */ +#define PIR_WREYE (1 << 15) /* Write Data Eye Training */ +#define PIR_LOCKBYP (1 << 28) /* PLL Lock Bypass */ +#define PIR_DCALBYP (1 << 29) /* DDL Calibration Bypass */ +#define PIR_ZCALBYP (1 << 30) /* Impedance Calib Bypass */ +#define PIR_INITBYP (1 << 31) /* Initialization Bypass */ + +#define PGSR0_IDONE (1 << 0) /* Initialization Done */ +#define PGSR0_PLDONE (1 << 1) /* PLL Lock Done */ +#define PGSR0_DCDONE (1 << 2) /* DDL Calibration Done */ +#define PGSR0_ZCDONE (1 << 3) /* Impedance Calibration Done */ +#define PGSR0_DIDONE (1 << 4) /* DRAM Initialization Done */ +#define PGSR0_WLDONE (1 << 5) /* Write Leveling Done */ +#define PGSR0_QSGDONE (1 << 6) /* DQS Gate Training Done */ +#define PGSR0_WLADONE (1 << 7) /* Write Leveling Adjust Done */ +#define PGSR0_RDDONE (1 << 8) /* Read Bit Deskew Done */ +#define PGSR0_WDDONE (1 << 9) /* Write Bit Deskew Done */ +#define PGSR0_REDONE (1 << 10) /* Read Eye Training Done */ +#define PGSR0_WEDONE (1 << 11) /* Write Eye Training Done */ +#define PGSR0_IERR (1 << 16) /* Initialization Error */ +#define PGSR0_PLERR (1 << 17) /* PLL Lock Error */ +#define PGSR0_DCERR (1 << 18) /* DDL Calibration Error */ +#define PGSR0_ZCERR (1 << 19) /* Impedance Calib Error */ +#define PGSR0_DIERR (1 << 20) /* DRAM Initialization Error */ +#define PGSR0_WLERR (1 << 21) /* Write Leveling Error */ +#define PGSR0_QSGERR (1 << 22) /* DQS Gate Training Error */ +#define PGSR0_WLAERR (1 << 23) /* Write Leveling Adj Error */ +#define PGSR0_RDERR (1 << 24) /* Read Bit Deskew Error */ +#define PGSR0_WDERR (1 << 25) /* Write Bit Deskew Error */ +#define PGSR0_REERR (1 << 26) /* Read Eye Training Error */ +#define PGSR0_WEERR (1 << 27) /* Write Eye Training Error */ +#define PGSR0_DTERR_SHIFT 28 /* Data Training Error Status*/ +#define PGSR0_DTERR (7 << (PGSR0_DTERR_SHIFT)) +#define PGSR0_APLOCK (1 << 31) /* AC PLL Lock */ + +#define DXCCR_DQSRES_OPEN (0 << 5) +#define DXCCR_DQSRES_688_OHM (1 << 5) +#define DXCCR_DQSRES_611_OHM (2 << 5) +#define DXCCR_DQSRES_550_OHM (3 << 5) +#define DXCCR_DQSRES_500_OHM (4 << 5) +#define DXCCR_DQSRES_458_OHM (5 << 5) +#define DXCCR_DQSRES_393_OHM (6 << 5) +#define DXCCR_DQSRES_344_OHM (7 << 5) + +#define DXCCR_DQSNRES_OPEN (0 << 9) +#define DXCCR_DQSNRES_688_OHM (1 << 9) +#define DXCCR_DQSNRES_611_OHM (2 << 9) +#define DXCCR_DQSNRES_550_OHM (3 << 9) +#define DXCCR_DQSNRES_500_OHM (4 << 9) +#define DXCCR_DQSNRES_458_OHM (5 << 9) +#define DXCCR_DQSNRES_393_OHM (6 << 9) +#define DXCCR_DQSNRES_344_OHM (7 << 9) + +#define DTCR_DTRANK_SHIFT 4 /* Data Training Rank */ +#define DTCR_DTRANK_MASK (0x3 << (DTCR_DTRANK_SHIFT)) +#define DTCR_DTMPR (1 << 6) /* Data Training using MPR */ +#define DTCR_RNKEN_SHIFT 24 /* Rank Enable */ +#define DTCR_RNKEN_MASK (0xf << (DTCR_RNKEN_SHIFT)) + +#define DXGCR_WLRKEN_SHIFT 26 /* Write Level Rank Enable */ +#define DXGCR_WLRKEN_MASK (0xf << (DXGCR_WLRKEN_SHIFT)) + +/* SoC-specific parameters */ +#define NR_DATX8_PER_DDRPHY 2 + +#if defined(CONFIG_MACH_PH1_LD4) || defined(CONFIG_MACH_PH1_SLD8) +#define NR_DDRPHY_PER_CH 1 +#else +#define NR_DDRPHY_PER_CH 2 +#endif + +#define NR_DDRCH 2 + +#define DDRPHY_BASE(ch, phy) (0x5bc01000 + 0x200000 * (ch) + 0x1000 * (phy)) + +#ifndef __ASSEMBLY__ +void ddrphy_init(struct ddrphy __iomem *phy, int freq, int size); +void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank); +int ddrphy_training(struct ddrphy __iomem *phy); +#endif + +#endif /* ARCH_DDRPHY_REGS_H */ diff --git a/arch/arm/include/asm/kona-common/clk.h b/arch/arm/include/asm/kona-common/clk.h index 2c7e829994..a5e2fd9d6c 100644 --- a/arch/arm/include/asm/kona-common/clk.h +++ b/arch/arm/include/asm/kona-common/clk.h @@ -25,5 +25,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent); struct clk *clk_get_parent(struct clk *clk); int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep); int clk_bsc_enable(void *base); +int clk_usb_otg_enable(void *base); #endif diff --git a/arch/arm/include/asm/semihosting.h b/arch/arm/include/asm/semihosting.h index 74111dc359..835ca7e4b6 100644 --- a/arch/arm/include/asm/semihosting.h +++ b/arch/arm/include/asm/semihosting.h @@ -12,10 +12,6 @@ * code for more information. */ int smh_load(const char *fname, void *memp, int avail, int verbose); -int smh_read(int fd, void *memp, int len); -int smh_open(const char *fname, char *modestr); -int smh_close(int fd); -int smh_len_fd(int fd); -int smh_len(const char *fname); +long smh_len(const char *fname); #endif /* __SEMIHOSTING_H__ */ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 61e2914d44..89f2294689 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 f1c0792ce8..9cedeac6d6 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 */ diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index cb5dc26ac3..fd6d8573f5 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -26,9 +26,9 @@ /* * Call the handler */ -static int smh_trap(unsigned int sysnum, void *addr) +static long smh_trap(unsigned int sysnum, void *addr) { - register int result asm("r0"); + register long result asm("r0"); #if defined(CONFIG_ARM64) asm volatile ("hlt #0xf000" : "=r" (result) : "0"(sysnum), "r"(addr)); #else @@ -39,167 +39,164 @@ static int smh_trap(unsigned int sysnum, void *addr) } /* - * Open, load a file into memory, and close it. Check that the available space - * is sufficient to store the entire file. Return the bytes actually read from - * the file as seen by the read function. The verbose flag enables some extra - * printing of successful read status. + * Open a file on the host. Mode is "r" or "rb" currently. Returns a file + * descriptor or -1 on error. */ -int smh_load(const char *fname, void *memp, int avail, int verbose) +static long smh_open(const char *fname, char *modestr) { - int ret, fd, len; - - ret = -1; - - debug("%s: fname \'%s\', avail %u, memp %p\n", __func__, fname, - avail, memp); - - /* Open the file */ - fd = smh_open(fname, "rb"); - if (fd == -1) - return ret; + long fd; + unsigned long mode; + struct smh_open_s { + const char *fname; + unsigned long mode; + size_t len; + } open; - /* Get the file length */ - ret = smh_len_fd(fd); - if (ret == -1) { - smh_close(fd); - return ret; - } + debug("%s: file \'%s\', mode \'%s\'\n", __func__, fname, modestr); - /* Check that the file will fit in the supplied buffer */ - if (ret > avail) { - printf("%s: ERROR ret %d, avail %u\n", __func__, ret, - avail); - smh_close(fd); - return ret; + /* Check the file mode */ + if (!(strcmp(modestr, "r"))) { + mode = MODE_READ; + } else if (!(strcmp(modestr, "rb"))) { + mode = MODE_READBIN; + } else { + printf("%s: ERROR mode \'%s\' not supported\n", __func__, + modestr); + return -1; } - len = ret; - - /* Read the file into the buffer */ - ret = smh_read(fd, memp, len); - if (ret == 0) { - /* Print successful load information if requested */ - if (verbose) { - printf("\n%s\n", fname); - printf(" 0x%8p dest\n", memp); - printf(" 0x%08x size\n", len); - printf(" 0x%08x avail\n", avail); - } - } + open.fname = fname; + open.len = strlen(fname); + open.mode = mode; - /* Close the file */ - smh_close(fd); + /* Open the file on the host */ + fd = smh_trap(SYSOPEN, &open); + if (fd == -1) + printf("%s: ERROR fd %ld for file \'%s\'\n", __func__, fd, + fname); - return ret; + return fd; } /* * Read 'len' bytes of file into 'memp'. Returns 0 on success, else failure */ -int smh_read(int fd, void *memp, int len) +static long smh_read(long fd, void *memp, size_t len) { - int ret; + long ret; struct smh_read_s { - int fd; + long fd; void *memp; - int len; + size_t len; } read; - debug("%s: fd %d, memp %p, len %d\n", __func__, fd, memp, len); + debug("%s: fd %ld, memp %p, len %lu\n", __func__, fd, memp, len); read.fd = fd; read.memp = memp; read.len = len; ret = smh_trap(SYSREAD, &read); - if (ret == 0) { - return 0; - } else { + if (ret < 0) { /* * The ARM handler allows for returning partial lengths, * but in practice this never happens so rather than create * hard to maintain partial read loops and such, just fail * with an error message. */ - printf("%s: ERROR ret %d, fd %d, len %u memp %p\n", + printf("%s: ERROR ret %ld, fd %ld, len %lu memp %p\n", __func__, ret, fd, len, memp); + return -1; } - return ret; + + return 0; } /* - * Open a file on the host. Mode is "r" or "rb" currently. Returns a file - * descriptor or -1 on error. + * Close the file using the file descriptor */ -int smh_open(const char *fname, char *modestr) +static long smh_close(long fd) { - int ret, fd, mode; - struct smh_open_s { - const char *fname; - unsigned int mode; - unsigned int len; - } open; + long ret; - debug("%s: file \'%s\', mode \'%s\'\n", __func__, fname, modestr); - - ret = -1; + debug("%s: fd %ld\n", __func__, fd); - /* Check the file mode */ - if (!(strcmp(modestr, "r"))) { - mode = MODE_READ; - } else if (!(strcmp(modestr, "rb"))) { - mode = MODE_READBIN; - } else { - printf("%s: ERROR mode \'%s\' not supported\n", __func__, - modestr); - return ret; - } - - open.fname = fname; - open.len = strlen(fname); - open.mode = mode; - - /* Open the file on the host */ - fd = smh_trap(SYSOPEN, &open); - if (fd == -1) - printf("%s: ERROR fd %d for file \'%s\'\n", __func__, fd, - fname); + ret = smh_trap(SYSCLOSE, &fd); + if (ret == -1) + printf("%s: ERROR fd %ld\n", __func__, fd); - return fd; + return ret; } /* - * Close the file using the file descriptor + * Get the file length from the file descriptor */ -int smh_close(int fd) +static long smh_len_fd(long fd) { - int ret; - long fdlong; + long ret; - debug("%s: fd %d\n", __func__, fd); + debug("%s: fd %ld\n", __func__, fd); - fdlong = (long)fd; - ret = smh_trap(SYSCLOSE, &fdlong); + ret = smh_trap(SYSFLEN, &fd); if (ret == -1) - printf("%s: ERROR fd %d\n", __func__, fd); + printf("%s: ERROR ret %ld, fd %ld\n", __func__, ret, fd); return ret; } /* - * Get the file length from the file descriptor + * Open, load a file into memory, and close it. Check that the available space + * is sufficient to store the entire file. Return the bytes actually read from + * the file as seen by the read function. The verbose flag enables some extra + * printing of successful read status. */ -int smh_len_fd(int fd) +int smh_load(const char *fname, void *memp, int avail, int verbose) { - int ret; - long fdlong; + long ret; + long fd; + size_t len; - debug("%s: fd %d\n", __func__, fd); + ret = -1; - fdlong = (long)fd; - ret = smh_trap(SYSFLEN, &fdlong); - if (ret == -1) - printf("%s: ERROR ret %d\n", __func__, ret); + debug("%s: fname \'%s\', avail %u, memp %p\n", __func__, fname, + avail, memp); + + /* Open the file */ + fd = smh_open(fname, "rb"); + if (fd == -1) + return -1; + + /* Get the file length */ + ret = smh_len_fd(fd); + if (ret == -1) { + smh_close(fd); + return -1; + } + + /* Check that the file will fit in the supplied buffer */ + if (ret > avail) { + printf("%s: ERROR ret %ld, avail %u\n", __func__, ret, + avail); + smh_close(fd); + return -1; + } + + len = ret; + + /* Read the file into the buffer */ + ret = smh_read(fd, memp, len); + if (ret == 0) { + /* Print successful load information if requested */ + if (verbose) { + printf("\n%s\n", fname); + printf(" 0x%8p dest\n", memp); + printf(" 0x%08lx size\n", len); + printf(" 0x%08x avail\n", avail); + } + } + + /* Close the file */ + smh_close(fd); return ret; } @@ -207,26 +204,32 @@ int smh_len_fd(int fd) /* * Get the file length from the filename */ -int smh_len(const char *fname) +long smh_len(const char *fname) { - int ret, fd, len; + long ret; + long fd; + long len; debug("%s: file \'%s\'\n", __func__, fname); /* Open the file */ fd = smh_open(fname, "rb"); - if (fd == -1) + if (fd < 0) return fd; /* Get the file length */ len = smh_len_fd(fd); + if (len < 0) { + smh_close(fd); + return len; + } /* Close the file */ ret = smh_close(fd); - if (ret == -1) + if (ret < 0) return ret; - debug("%s: returning len %d\n", __func__, len); + debug("%s: returning len %ld\n", __func__, len); /* Return the file length (or -1 error indication) */ return len; |