diff options
author | Tom Rini | 2018-07-13 09:05:05 -0400 |
---|---|---|
committer | Tom Rini | 2018-07-13 14:47:04 -0400 |
commit | 914bb7ea2f9373fa59285ff77a95df73848c8f66 (patch) | |
tree | f27ecab47f71990f91fbe0daad932ab0c5fce726 /arch | |
parent | f2df46e5d9388987c2084a39f05f2ad32801b3b0 (diff) | |
parent | aa529663368e97663d7ec16d6997cb69a2dd8afb (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-socfpga
- Update SPDX tag in arch/arm/mach-socfpga/spl_a10.c
Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'arch')
20 files changed, 1470 insertions, 84 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4fbb424037b..5b3746c80bf 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -759,10 +759,10 @@ config ARCH_SOCFPGA bool "Altera SOCFPGA family" select ARCH_EARLY_INIT_R select ARCH_MISC_INIT - select CPU_V7A + select CPU_V7A if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 select DM select DM_SERIAL - select ENABLE_ARM_SOC_BOOT0_HOOK + select ENABLE_ARM_SOC_BOOT0_HOOK if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 select OF_CONTROL select SPL_LIBCOMMON_SUPPORT select SPL_LIBDISK_SUPPORT @@ -772,20 +772,22 @@ config ARCH_SOCFPGA select SPL_OF_CONTROL select SPL_SERIAL_SUPPORT select SPL_DM_SERIAL + select SPL_RESET_SUPPORT select SPL_SPI_FLASH_SUPPORT if SPL_SPI_SUPPORT select SPL_SPI_SUPPORT if DM_SPI select SPL_WATCHDOG_SUPPORT select SUPPORT_SPL select SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE select SYS_NS16550 - select SYS_THUMB_BUILD + select SYS_THUMB_BUILD if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 + select ARM64 if TARGET_SOCFPGA_STRATIX10 imply CMD_MTDPARTS imply CRC32_VERIFY imply DM_SPI imply DM_SPI_FLASH imply FAT_WRITE - imply HW_WATCHDOG imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + select SPL_SEPARATE_BSS if TARGET_SOCFPGA_STRATIX10 config ARCH_SUNXI bool "Support sunxi (Allwinner) SoCs" diff --git a/arch/arm/dts/socfpga_arria10_socdk.dtsi b/arch/arm/dts/socfpga_arria10_socdk.dtsi index d7616dd1c51..3f59f025775 100644 --- a/arch/arm/dts/socfpga_arria10_socdk.dtsi +++ b/arch/arm/dts/socfpga_arria10_socdk.dtsi @@ -34,6 +34,7 @@ name = "memory"; device_type = "memory"; reg = <0x0 0x40000000>; /* 1GB */ + u-boot,dm-pre-reloc; }; a10leds { diff --git a/arch/arm/dts/socfpga_stratix10_socdk.dts b/arch/arm/dts/socfpga_stratix10_socdk.dts index c6ab0ae9923..6e8ddcd9f4c 100644 --- a/arch/arm/dts/socfpga_stratix10_socdk.dts +++ b/arch/arm/dts/socfpga_stratix10_socdk.dts @@ -36,8 +36,8 @@ memory { device_type = "memory"; - /* We expect the bootloader to fill in the reg */ - reg = <0 0 0 0>; + reg = <0 0 0 0x80000000>; /* 2GB */ + u-boot,dm-pre-reloc; }; }; diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 30b475254c4..91ea742f3b1 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -20,6 +20,12 @@ config TARGET_SOCFPGA_GEN5 bool select ALTERA_SDRAM +config TARGET_SOCFPGA_STRATIX10 + bool + select ARMV8_MULTIENTRY + select ARMV8_SPIN_TABLE + select ARMV8_SET_SMPEN + choice prompt "Altera SOCFPGA board select" optional @@ -57,6 +63,10 @@ config TARGET_SOCFPGA_SR1500 bool "SR1500 (Cyclone V)" select TARGET_SOCFPGA_CYCLONE5 +config TARGET_SOCFPGA_STRATIX10_SOCDK + bool "Intel SOCFPGA SoCDK (Stratix 10)" + select TARGET_SOCFPGA_STRATIX10 + config TARGET_SOCFPGA_TERASIC_DE0_NANO bool "Terasic DE0-Nano-Atlas (Cyclone V)" select TARGET_SOCFPGA_CYCLONE5 @@ -87,12 +97,14 @@ config SYS_BOARD default "sockit" if TARGET_SOCFPGA_TERASIC_SOCKIT default "socrates" if TARGET_SOCFPGA_EBV_SOCRATES default "sr1500" if TARGET_SOCFPGA_SR1500 + default "stratix10-socdk" if TARGET_SOCFPGA_STRATIX10_SOCDK default "vining_fpga" if TARGET_SOCFPGA_SAMTEC_VINING_FPGA config SYS_VENDOR default "altera" if TARGET_SOCFPGA_ARRIA5_SOCDK default "altera" if TARGET_SOCFPGA_ARRIA10_SOCDK default "altera" if TARGET_SOCFPGA_CYCLONE5_SOCDK + default "altera" if TARGET_SOCFPGA_STRATIX10_SOCDK default "devboards" if TARGET_SOCFPGA_DEVBOARDS_DBM_SOC1 default "ebv" if TARGET_SOCFPGA_EBV_SOCRATES default "samtec" if TARGET_SOCFPGA_SAMTEC_VINING_FPGA @@ -116,6 +128,7 @@ config SYS_CONFIG_NAME default "socfpga_sockit" if TARGET_SOCFPGA_TERASIC_SOCKIT default "socfpga_socrates" if TARGET_SOCFPGA_EBV_SOCRATES default "socfpga_sr1500" if TARGET_SOCFPGA_SR1500 + default "socfpga_stratix10_socdk" if TARGET_SOCFPGA_STRATIX10_SOCDK default "socfpga_vining_fpga" if TARGET_SOCFPGA_SAMTEC_VINING_FPGA endif diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index 61f5778de57..654999cdf68 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -9,7 +9,6 @@ obj-y += board.o obj-y += clock_manager.o obj-y += misc.o obj-y += reset_manager.o -obj-y += timer.o ifdef CONFIG_TARGET_SOCFPGA_GEN5 obj-y += clock_manager_gen5.o @@ -17,6 +16,7 @@ obj-y += misc_gen5.o obj-y += reset_manager_gen5.o obj-y += scan_manager.o obj-y += system_manager_gen5.o +obj-y += timer.o obj-y += wrap_pll_config.o obj-y += fpga_manager.o endif @@ -26,23 +26,35 @@ obj-y += clock_manager_arria10.o obj-y += misc_arria10.o obj-y += pinmux_arria10.o obj-y += reset_manager_arria10.o +obj-y += timer.o endif ifdef CONFIG_TARGET_SOCFPGA_STRATIX10 obj-y += clock_manager_s10.o +obj-y += mailbox_s10.o +obj-y += misc_s10.o +obj-y += mmu-arm64_s10.o obj-y += reset_manager_s10.o obj-y += system_manager_s10.o +obj-y += timer_s10.o obj-y += wrap_pinmux_config_s10.o obj-y += wrap_pll_config_s10.o endif + ifdef CONFIG_SPL_BUILD -obj-y += spl.o ifdef CONFIG_TARGET_SOCFPGA_GEN5 +obj-y += spl_gen5.o obj-y += freeze_controller.o obj-y += wrap_iocsr_config.o obj-y += wrap_pinmux_config.o obj-y += wrap_sdram_config.o endif +ifdef CONFIG_TARGET_SOCFPGA_ARRIA10 +obj-y += spl_a10.o +endif +ifdef CONFIG_TARGET_SOCFPGA_STRATIX10 +obj-y += spl_s10.o +endif endif ifdef CONFIG_TARGET_SOCFPGA_GEN5 diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c index 189e12a6683..26d84be6e96 100644 --- a/arch/arm/mach-socfpga/board.c +++ b/arch/arm/mach-socfpga/board.c @@ -18,7 +18,20 @@ DECLARE_GLOBAL_DATA_PTR; -void s_init(void) {} +void s_init(void) { +#ifndef CONFIG_ARM64 + /* + * Preconfigure ACTLR, make sure Write Full Line of Zeroes is disabled. + * This is optional on CycloneV / ArriaV. + * This is mandatory on Arria10, otherwise Linux refuses to boot. + */ + asm volatile( + "mcr p15, 0, %0, c1, c0, 1\n" + "isb\n" + "dsb\n" + ::"r"(0x0)); +#endif +} /* * Miscellaneous platform dependent initialisations diff --git a/arch/arm/mach-socfpga/include/mach/firewall_s10.h b/arch/arm/mach-socfpga/include/mach/firewall_s10.h new file mode 100644 index 00000000000..b96f779f148 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/firewall_s10.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Intel Corporation <www.intel.com> + * + */ + +#ifndef _FIREWALL_S10_ +#define _FIREWALL_S10_ + +struct socfpga_firwall_l4_per { + u32 nand; /* 0x00 */ + u32 nand_data; + u32 _pad_0x8; + u32 usb0; + u32 usb1; /* 0x10 */ + u32 _pad_0x14; + u32 _pad_0x18; + u32 spim0; + u32 spim1; /* 0x20 */ + u32 spis0; + u32 spis1; + u32 emac0; + u32 emac1; /* 0x30 */ + u32 emac2; + u32 _pad_0x38; + u32 _pad_0x3c; + u32 sdmmc; /* 0x40 */ + u32 gpio0; + u32 gpio1; + u32 _pad_0x4c; + u32 i2c0; /* 0x50 */ + u32 i2c1; + u32 i2c2; + u32 i2c3; + u32 i2c4; /* 0x60 */ + u32 timer0; + u32 timer1; + u32 uart0; + u32 uart1; /* 0x70 */ +}; + +struct socfpga_firwall_l4_sys { + u32 _pad_0x00; /* 0x00 */ + u32 _pad_0x04; + u32 dma_ecc; + u32 emac0rx_ecc; + u32 emac0tx_ecc; /* 0x10 */ + u32 emac1rx_ecc; + u32 emac1tx_ecc; + u32 emac2rx_ecc; + u32 emac2tx_ecc; /* 0x20 */ + u32 _pad_0x24; + u32 _pad_0x28; + u32 nand_ecc; + u32 nand_read_ecc; /* 0x30 */ + u32 nand_write_ecc; + u32 ocram_ecc; + u32 _pad_0x3c; + u32 sdmmc_ecc; /* 0x40 */ + u32 usb0_ecc; + u32 usb1_ecc; + u32 clock_manager; + u32 _pad_0x50; /* 0x50 */ + u32 io_manager; + u32 reset_manager; + u32 system_manager; + u32 osc0_timer; /* 0x60 */ + u32 osc1_timer; + u32 watchdog0; + u32 watchdog1; + u32 watchdog2; /* 0x70 */ + u32 watchdog3; +}; + +#define FIREWALL_L4_DISABLE_ALL (BIT(0) | BIT(24) | BIT(16)) +#define FIREWALL_BRIDGE_DISABLE_ALL (~0) + +/* Cache coherency unit (CCU) registers */ +#define CCU_CPU0_MPRT_ADBASE_DDRREG 0x4400 +#define CCU_CPU0_MPRT_ADBASE_MEMSPACE0 0x45c0 +#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1A 0x45e0 +#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1B 0x4600 +#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1C 0x4620 +#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1D 0x4640 +#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1E 0x4660 + +#define CCU_CPU0_MPRT_ADMASK_MEM_RAM0 0x4688 + +#define CCU_IOM_MPRT_ADBASE_MEMSPACE0 0x18560 +#define CCU_IOM_MPRT_ADBASE_MEMSPACE1A 0x18580 +#define CCU_IOM_MPRT_ADBASE_MEMSPACE1B 0x185a0 +#define CCU_IOM_MPRT_ADBASE_MEMSPACE1C 0x185c0 +#define CCU_IOM_MPRT_ADBASE_MEMSPACE1D 0x185e0 +#define CCU_IOM_MPRT_ADBASE_MEMSPACE1E 0x18600 + +#define CCU_IOM_MPRT_ADMASK_MEM_RAM0 0x18628 + +#define CCU_ADMASK_P_MASK BIT(0) +#define CCU_ADMASK_NS_MASK BIT(1) + +#define CCU_ADBASE_DI_MASK BIT(4) + +#define CCU_REG_ADDR(reg) \ + (SOCFPGA_CCU_ADDRESS + (reg)) + +/* Firewall MPU DDR SCR registers */ +#define FW_MPU_DDR_SCR_EN 0x00 +#define FW_MPU_DDR_SCR_EN_SET 0x04 +#define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT 0x18 +#define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT 0x1c +#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT 0x98 +#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT 0x9c + +#define MPUREGION0_ENABLE BIT(0) +#define NONMPUREGION0_ENABLE BIT(8) + +#define FW_MPU_DDR_SCR_WRITEL(data, reg) \ + writel(data, SOCFPGA_FW_MPU_DDR_SCR_ADDRESS + (reg)) + +#endif /* _FIREWALL_S10_ */ diff --git a/arch/arm/mach-socfpga/include/mach/mailbox_s10.h b/arch/arm/mach-socfpga/include/mach/mailbox_s10.h new file mode 100644 index 00000000000..81a609d2f82 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/mailbox_s10.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Intel Corporation <www.intel.com> + * + */ + +#ifndef _MAILBOX_S10_H_ +#define _MAILBOX_S10_H_ + +/* user define Uboot ID */ +#define MBOX_CLIENT_ID_UBOOT 0xB +#define MBOX_ID_UBOOT 0x1 + +#define MBOX_CMD_DIRECT 0 +#define MBOX_CMD_INDIRECT 1 + +#define MBOX_MAX_CMD_INDEX 2047 +#define MBOX_CMD_BUFFER_SIZE 32 +#define MBOX_RESP_BUFFER_SIZE 16 + +#define MBOX_HDR_CMD_LSB 0 +#define MBOX_HDR_CMD_MSK (BIT(11) - 1) +#define MBOX_HDR_I_LSB 11 +#define MBOX_HDR_I_MSK BIT(11) +#define MBOX_HDR_LEN_LSB 12 +#define MBOX_HDR_LEN_MSK 0x007FF000 +#define MBOX_HDR_ID_LSB 24 +#define MBOX_HDR_ID_MSK 0x0F000000 +#define MBOX_HDR_CLIENT_LSB 28 +#define MBOX_HDR_CLIENT_MSK 0xF0000000 + +/* Interrupt flags */ +#define MBOX_FLAGS_INT_COE BIT(0) /* COUT update interrupt enable */ +#define MBOX_FLAGS_INT_RIE BIT(1) /* RIN update interrupt enable */ +#define MBOX_FLAGS_INT_UAE BIT(8) /* Urgent ACK interrupt enable */ +#define MBOX_ALL_INTRS (MBOX_FLAGS_INT_COE | \ + MBOX_FLAGS_INT_RIE | \ + MBOX_FLAGS_INT_UAE) + +/* Status */ +#define MBOX_STATUS_UA_MSK BIT(8) + +#define MBOX_CMD_HEADER(client, id, len, indirect, cmd) \ + ((((cmd) << MBOX_HDR_CMD_LSB) & MBOX_HDR_CMD_MSK) | \ + (((indirect) << MBOX_HDR_I_LSB) & MBOX_HDR_I_MSK) | \ + (((len) << MBOX_HDR_LEN_LSB) & MBOX_HDR_LEN_MSK) | \ + (((id) << MBOX_HDR_ID_LSB) & MBOX_HDR_ID_MSK) | \ + (((client) << MBOX_HDR_CLIENT_LSB) & MBOX_HDR_CLIENT_MSK)) + +#define MBOX_RESP_ERR_GET(resp) \ + (((resp) & MBOX_HDR_CMD_MSK) >> MBOX_HDR_CMD_LSB) +#define MBOX_RESP_LEN_GET(resp) \ + (((resp) & MBOX_HDR_LEN_MSK) >> MBOX_HDR_LEN_LSB) +#define MBOX_RESP_ID_GET(resp) \ + (((resp) & MBOX_HDR_ID_MSK) >> MBOX_HDR_ID_LSB) +#define MBOX_RESP_CLIENT_GET(resp) \ + (((resp) & MBOX_HDR_CLIENT_MSK) >> MBOX_HDR_CLIENT_LSB) + +/* Response error list */ +enum ALT_SDM_MBOX_RESP_CODE { + /* CMD completed successfully, but check resp ARGS for any errors */ + MBOX_RESP_STATOK = 0, + /* CMD is incorrectly formatted in some way */ + MBOX_RESP_INVALID_COMMAND = 1, + /* BootROM Command code not undesrtood */ + MBOX_RESP_UNKNOWN_BR = 2, + /* CMD code not recognized by firmware */ + MBOX_RESP_UNKNOWN = 3, + /* Indicates that the device is not configured */ + MBOX_RESP_NOT_CONFIGURED = 256, + /* Indicates that the device is busy */ + MBOX_RESP_DEVICE_BUSY = 0x1FF, + /* Indicates that there is no valid response available */ + MBOX_RESP_NO_VALID_RESP_AVAILABLE = 0x2FF, + /* General Error */ + MBOX_RESP_ERROR = 0x3FF, +}; + +/* Mailbox command list */ +#define MBOX_RESTART 2 +#define MBOX_CONFIG_STATUS 4 +#define MBOX_RECONFIG 6 +#define MBOX_RECONFIG_MSEL 7 +#define MBOX_RECONFIG_DATA 8 +#define MBOX_RECONFIG_STATUS 9 +#define MBOX_QSPI_OPEN 50 +#define MBOX_QSPI_CLOSE 51 +#define MBOX_QSPI_DIRECT 59 +#define MBOX_REBOOT_HPS 71 + +/* Mailbox registers */ +#define MBOX_CIN 0 /* command valid offset */ +#define MBOX_ROUT 4 /* response output offset */ +#define MBOX_URG 8 /* urgent command */ +#define MBOX_FLAGS 0x0c /* interrupt enables */ +#define MBOX_COUT 0x20 /* command free offset */ +#define MBOX_RIN 0x24 /* respond valid offset */ +#define MBOX_STATUS 0x2c /* mailbox status */ +#define MBOX_CMD_BUF 0x40 /* circular command buffer */ +#define MBOX_RESP_BUF 0xc0 /* circular response buffer */ +#define MBOX_DOORBELL_TO_SDM 0x400 /* Doorbell to SDM */ +#define MBOX_DOORBELL_FROM_SDM 0x480 /* Doorbell from SDM */ + +/* Status and bit information returned by RECONFIG_STATUS */ +#define RECONFIG_STATUS_RESPONSE_LEN 6 +#define RECONFIG_STATUS_STATE 0 +#define RECONFIG_STATUS_PIN_STATUS 2 +#define RECONFIG_STATUS_SOFTFUNC_STATUS 3 + +#define MBOX_CFGSTAT_STATE_IDLE 0x00000000 +#define MBOX_CFGSTAT_STATE_CONFIG 0x10000000 +#define MBOX_CFGSTAT_STATE_FAILACK 0x08000000 +#define MBOX_CFGSTAT_STATE_ERROR_INVALID 0xf0000001 +#define MBOX_CFGSTAT_STATE_ERROR_CORRUPT 0xf0000002 +#define MBOX_CFGSTAT_STATE_ERROR_AUTH 0xf0000003 +#define MBOX_CFGSTAT_STATE_ERROR_CORE_IO 0xf0000004 +#define MBOX_CFGSTAT_STATE_ERROR_HARDWARE 0xf0000005 +#define MBOX_CFGSTAT_STATE_ERROR_FAKE 0xf0000006 +#define MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO 0xf0000007 +#define MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR 0xf0000008 + +#define RCF_SOFTFUNC_STATUS_CONF_DONE BIT(0) +#define RCF_SOFTFUNC_STATUS_INIT_DONE BIT(1) +#define RCF_SOFTFUNC_STATUS_SEU_ERROR BIT(3) +#define RCF_PIN_STATUS_NSTATUS BIT(31) + +int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, u8 urgent, + u32 *resp_buf_len, u32 *resp_buf); +int mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, + u8 urgent, u32 *resp_buf_len, u32 *resp_buf); +int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg); +int mbox_send_cmd_only_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg); +int mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len); +int mbox_rcv_resp_psci(u32 *resp_buf, u32 resp_buf_max_len); +int mbox_init(void); + +#ifdef CONFIG_CADENCE_QSPI +int mbox_qspi_close(void); +int mbox_qspi_open(void); +#endif + +int mbox_reset_cold(void); + +#endif /* _MAILBOX_S10_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/misc.h b/arch/arm/mach-socfpga/include/mach/misc.h index 197f09a57cb..7fe77ac8d81 100644 --- a/arch/arm/mach-socfpga/include/mach/misc.h +++ b/arch/arm/mach-socfpga/include/mach/misc.h @@ -27,4 +27,6 @@ unsigned int shared_uart_com_port(const void *blob); unsigned int uart_com_port(const void *blob); #endif +void do_bridge_reset(int enable); + #endif /* _MISC_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/sdram_s10.h b/arch/arm/mach-socfpga/include/mach/sdram_s10.h new file mode 100644 index 00000000000..91bfc0e5ec8 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/sdram_s10.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Intel Corporation <www.intel.com> + * + */ + +#ifndef _SDRAM_S10_H_ +#define _SDRAM_S10_H_ + +unsigned long sdram_calculate_size(void); +int sdram_mmr_init_full(unsigned int sdr_phy_reg); +int sdram_calibration_full(void); + +#define DDR_TWR 15 +#define DDR_READ_LATENCY_DELAY 40 +#define DDR_ACTIVATE_FAWBANK 0x1 + +/* ECC HMC registers */ +#define DDRIOCTRL 0x8 +#define DDRCALSTAT 0xc +#define DRAMADDRWIDTH 0xe0 +#define ECCCTRL1 0x100 +#define ECCCTRL2 0x104 +#define ERRINTEN 0x110 +#define INTMODE 0x11c +#define INTSTAT 0x120 +#define AUTOWB_CORRADDR 0x138 +#define ECC_REG2WRECCDATABUS 0x144 +#define ECC_DIAGON 0x150 +#define ECC_DECSTAT 0x154 +#define HPSINTFCSEL 0x210 +#define RSTHANDSHAKECTRL 0x214 +#define RSTHANDSHAKESTAT 0x218 + +#define DDR_HMC_DDRIOCTRL_IOSIZE_MSK 0x00000003 +#define DDR_HMC_DDRCALSTAT_CAL_MSK BIT(0) +#define DDR_HMC_ECCCTL_AWB_CNT_RST_SET_MSK BIT(16) +#define DDR_HMC_ECCCTL_CNT_RST_SET_MSK BIT(8) +#define DDR_HMC_ECCCTL_ECC_EN_SET_MSK BIT(0) +#define DDR_HMC_ECCCTL2_RMW_EN_SET_MSK BIT(8) +#define DDR_HMC_ECCCTL2_AWB_EN_SET_MSK BIT(0) +#define DDR_HMC_ECC_DIAGON_ECCDIAGON_EN_SET_MSK BIT(16) +#define DDR_HMC_ECC_DIAGON_WRDIAGON_EN_SET_MSK BIT(0) +#define DDR_HMC_ERRINTEN_SERRINTEN_EN_SET_MSK BIT(0) +#define DDR_HMC_ERRINTEN_DERRINTEN_EN_SET_MSK BIT(1) +#define DDR_HMC_INTSTAT_SERRPENA_SET_MSK BIT(0) +#define DDR_HMC_INTSTAT_DERRPENA_SET_MSK BIT(1) +#define DDR_HMC_INTSTAT_ADDRMTCFLG_SET_MSK BIT(16) +#define DDR_HMC_INTMODE_INTMODE_SET_MSK BIT(0) +#define DDR_HMC_RSTHANDSHAKE_MASK 0x000000ff +#define DDR_HMC_CORE2SEQ_INT_REQ 0xF +#define DDR_HMC_SEQ2CORE_INT_RESP_MASK BIT(3) +#define DDR_HMC_HPSINTFCSEL_ENABLE_MASK 0x001f1f1f + +/* NOC DDR scheduler */ +#define DDR_SCH_ID_COREID 0 +#define DDR_SCH_ID_REVID 0x4 +#define DDR_SCH_DDRCONF 0x8 +#define DDR_SCH_DDRTIMING 0xc +#define DDR_SCH_DDRMODE 0x10 +#define DDR_SCH_READ_LATENCY 0x14 +#define DDR_SCH_ACTIVATE 0x38 +#define DDR_SCH_DEVTODEV 0x3c +#define DDR_SCH_DDR4TIMING 0x40 + +#define DDR_SCH_DDRTIMING_ACTTOACT_OFF 0 +#define DDR_SCH_DDRTIMING_RDTOMISS_OFF 6 +#define DDR_SCH_DDRTIMING_WRTOMISS_OFF 12 +#define DDR_SCH_DDRTIMING_BURSTLEN_OFF 18 +#define DDR_SCH_DDRTIMING_RDTOWR_OFF 21 +#define DDR_SCH_DDRTIMING_WRTORD_OFF 26 +#define DDR_SCH_DDRTIMING_BWRATIO_OFF 31 +#define DDR_SCH_DDRMOD_BWRATIOEXTENDED_OFF 1 +#define DDR_SCH_ACTIVATE_RRD_OFF 0 +#define DDR_SCH_ACTIVATE_FAW_OFF 4 +#define DDR_SCH_ACTIVATE_FAWBANK_OFF 10 +#define DDR_SCH_DEVTODEV_BUSRDTORD_OFF 0 +#define DDR_SCH_DEVTODEV_BUSRDTOWR_OFF 2 +#define DDR_SCH_DEVTODEV_BUSWRTORD_OFF 4 + +/* HMC MMR IO48 registers */ +#define CTRLCFG0 0x28 +#define CTRLCFG1 0x2c +#define DRAMTIMING0 0x50 +#define CALTIMING0 0x7c +#define CALTIMING1 0x80 +#define CALTIMING2 0x84 +#define CALTIMING3 0x88 +#define CALTIMING4 0x8c +#define CALTIMING9 0xa0 +#define DRAMADDRW 0xa8 +#define DRAMSTS 0xec +#define NIOSRESERVED0 0x110 +#define NIOSRESERVED1 0x114 +#define NIOSRESERVED2 0x118 + +#define DRAMADDRW_CFG_COL_ADDR_WIDTH(x) \ + (((x) >> 0) & 0x1F) +#define DRAMADDRW_CFG_ROW_ADDR_WIDTH(x) \ + (((x) >> 5) & 0x1F) +#define DRAMADDRW_CFG_BANK_ADDR_WIDTH(x) \ + (((x) >> 10) & 0xF) +#define DRAMADDRW_CFG_BANK_GRP_ADDR_WIDTH(x) \ + (((x) >> 14) & 0x3) +#define DRAMADDRW_CFG_CS_ADDR_WIDTH(x) \ + (((x) >> 16) & 0x7) + +#define CTRLCFG0_CFG_MEMTYPE(x) \ + (((x) >> 0) & 0xF) +#define CTRLCFG0_CFG_DIMM_TYPE(x) \ + (((x) >> 4) & 0x7) +#define CTRLCFG0_CFG_AC_POS(x) \ + (((x) >> 7) & 0x3) +#define CTRLCFG0_CFG_CTRL_BURST_LEN(x) \ + (((x) >> 9) & 0x1F) + +#define CTRLCFG1_CFG_DBC3_BURST_LEN(x) \ + (((x) >> 0) & 0x1F) +#define CTRLCFG1_CFG_ADDR_ORDER(x) \ + (((x) >> 5) & 0x3) +#define CTRLCFG1_CFG_CTRL_EN_ECC(x) \ + (((x) >> 7) & 0x1) + +#define DRAMTIMING0_CFG_TCL(x) \ + (((x) >> 0) & 0x7F) + +#define CALTIMING0_CFG_ACT_TO_RDWR(x) \ + (((x) >> 0) & 0x3F) +#define CALTIMING0_CFG_ACT_TO_PCH(x) \ + (((x) >> 6) & 0x3F) +#define CALTIMING0_CFG_ACT_TO_ACT(x) \ + (((x) >> 12) & 0x3F) +#define CALTIMING0_CFG_ACT_TO_ACT_DB(x) \ + (((x) >> 18) & 0x3F) + +#define CALTIMING1_CFG_RD_TO_RD(x) \ + (((x) >> 0) & 0x3F) +#define CALTIMING1_CFG_RD_TO_RD_DC(x) \ + (((x) >> 6) & 0x3F) +#define CALTIMING1_CFG_RD_TO_RD_DB(x) \ + (((x) >> 12) & 0x3F) +#define CALTIMING1_CFG_RD_TO_WR(x) \ + (((x) >> 18) & 0x3F) +#define CALTIMING1_CFG_RD_TO_WR_DC(x) \ + (((x) >> 24) & 0x3F) + +#define CALTIMING2_CFG_RD_TO_WR_DB(x) \ + (((x) >> 0) & 0x3F) +#define CALTIMING2_CFG_RD_TO_WR_PCH(x) \ + (((x) >> 6) & 0x3F) +#define CALTIMING2_CFG_RD_AP_TO_VALID(x) \ + (((x) >> 12) & 0x3F) +#define CALTIMING2_CFG_WR_TO_WR(x) \ + (((x) >> 18) & 0x3F) +#define CALTIMING2_CFG_WR_TO_WR_DC(x) \ + (((x) >> 24) & 0x3F) + +#define CALTIMING3_CFG_WR_TO_WR_DB(x) \ + (((x) >> 0) & 0x3F) +#define CALTIMING3_CFG_WR_TO_RD(x) \ + (((x) >> 6) & 0x3F) +#define CALTIMING3_CFG_WR_TO_RD_DC(x) \ + (((x) >> 12) & 0x3F) +#define CALTIMING3_CFG_WR_TO_RD_DB(x) \ + (((x) >> 18) & 0x3F) +#define CALTIMING3_CFG_WR_TO_PCH(x) \ + (((x) >> 24) & 0x3F) + +#define CALTIMING4_CFG_WR_AP_TO_VALID(x) \ + (((x) >> 0) & 0x3F) +#define CALTIMING4_CFG_PCH_TO_VALID(x) \ + (((x) >> 6) & 0x3F) +#define CALTIMING4_CFG_PCH_ALL_TO_VALID(x) \ + (((x) >> 12) & 0x3F) +#define CALTIMING4_CFG_ARF_TO_VALID(x) \ + (((x) >> 18) & 0xFF) +#define CALTIMING4_CFG_PDN_TO_VALID(x) \ + (((x) >> 26) & 0x3F) + +#define CALTIMING9_CFG_4_ACT_TO_ACT(x) \ + (((x) >> 0) & 0xFF) + +#endif /* _SDRAM_S10_H_ */ diff --git a/arch/arm/mach-socfpga/mailbox_s10.c b/arch/arm/mach-socfpga/mailbox_s10.c new file mode 100644 index 00000000000..cccd1a4404a --- /dev/null +++ b/arch/arm/mach-socfpga/mailbox_s10.c @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017-2018 Intel Corporation <www.intel.com> + * + */ + +#include <common.h> +#include <wait_bit.h> +#include <asm/io.h> +#include <asm/arch/mailbox_s10.h> +#include <asm/arch/system_manager.h> +#include <asm/secure.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define MBOX_READL(reg) \ + readl(SOCFPGA_MAILBOX_ADDRESS + (reg)) + +#define MBOX_WRITEL(data, reg) \ + writel(data, SOCFPGA_MAILBOX_ADDRESS + (reg)) + +#define MBOX_READ_RESP_BUF(rout) \ + MBOX_READL(MBOX_RESP_BUF + ((rout) * sizeof(u32))) + +#define MBOX_WRITE_CMD_BUF(data, cin) \ + MBOX_WRITEL(data, MBOX_CMD_BUF + ((cin) * sizeof(u32))) + +static __always_inline int mbox_polling_resp(u32 rout) +{ + u32 rin; + unsigned long i = ~0; + + while (i) { + rin = MBOX_READL(MBOX_RIN); + if (rout != rin) + return 0; + + i--; + } + + return -ETIMEDOUT; +} + +/* Check for available slot and write to circular buffer. + * It also update command valid offset (cin) register. + */ +static __always_inline int mbox_fill_cmd_circular_buff(u32 header, u32 len, + u32 *arg) +{ + u32 cin; + u32 cout; + u32 i; + + cin = MBOX_READL(MBOX_CIN) % MBOX_CMD_BUFFER_SIZE; + cout = MBOX_READL(MBOX_COUT) % MBOX_CMD_BUFFER_SIZE; + + /* if command buffer is full or not enough free space + * to fit the data + */ + if (((cin + 1) % MBOX_CMD_BUFFER_SIZE) == cout || + ((MBOX_CMD_BUFFER_SIZE - cin + cout - 1) % + MBOX_CMD_BUFFER_SIZE) < len) + return -ENOMEM; + + /* write header to circular buffer */ + MBOX_WRITE_CMD_BUF(header, cin++); + /* wrapping around when it reach the buffer size */ + cin %= MBOX_CMD_BUFFER_SIZE; + + /* write arguments */ + for (i = 0; i < len; i++) { + MBOX_WRITE_CMD_BUF(arg[i], cin++); + /* wrapping around when it reach the buffer size */ + cin %= MBOX_CMD_BUFFER_SIZE; + } + + /* write command valid offset */ + MBOX_WRITEL(cin, MBOX_CIN); + + return 0; +} + +/* Check the command and fill it into circular buffer */ +static __always_inline int mbox_prepare_cmd_only(u8 id, u32 cmd, + u8 is_indirect, u32 len, + u32 *arg) +{ + u32 header; + int ret; + + /* Total length is command + argument length */ + if ((len + 1) > MBOX_CMD_BUFFER_SIZE) + return -EINVAL; + + if (cmd > MBOX_MAX_CMD_INDEX) + return -EINVAL; + + header = MBOX_CMD_HEADER(MBOX_CLIENT_ID_UBOOT, id, len, + (is_indirect) ? 1 : 0, cmd); + + ret = mbox_fill_cmd_circular_buff(header, len, arg); + + return ret; +} + +/* Send command only without waiting for responses from SDM */ +static __always_inline int mbox_send_cmd_only_common(u8 id, u32 cmd, + u8 is_indirect, u32 len, + u32 *arg) +{ + int ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg); + /* write doorbell */ + MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM); + + return ret; +} + +/* Return number of responses received in buffer */ +static __always_inline int __mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len) +{ + u32 rin; + u32 rout; + u32 resp_len = 0; + + /* clear doorbell from SDM if it was SET */ + if (MBOX_READL(MBOX_DOORBELL_FROM_SDM) & 1) + MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM); + + /* read current response offset */ + rout = MBOX_READL(MBOX_ROUT); + /* read response valid offset */ + rin = MBOX_READL(MBOX_RIN); + + while (rin != rout && (resp_len < resp_buf_max_len)) { + /* Response received */ + if (resp_buf) + resp_buf[resp_len++] = MBOX_READ_RESP_BUF(rout); + + rout++; + /* wrapping around when it reach the buffer size */ + rout %= MBOX_RESP_BUFFER_SIZE; + /* update next ROUT */ + MBOX_WRITEL(rout, MBOX_ROUT); + } + + return resp_len; +} + +/* Support one command and up to 31 words argument length only */ +static __always_inline int mbox_send_cmd_common(u8 id, u32 cmd, u8 is_indirect, + u32 len, u32 *arg, u8 urgent, + u32 *resp_buf_len, + u32 *resp_buf) +{ + u32 rin; + u32 resp; + u32 rout; + u32 status; + u32 resp_len; + u32 buf_len; + int ret; + + ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg); + if (ret) + return ret; + + if (urgent) { + /* Read status because it is toggled */ + status = MBOX_READL(MBOX_STATUS) & MBOX_STATUS_UA_MSK; + /* Send command as urgent command */ + MBOX_WRITEL(1, MBOX_URG); + } + + /* write doorbell */ + MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM); + + while (1) { + ret = ~0; + + /* Wait for doorbell from SDM */ + while (!MBOX_READL(MBOX_DOORBELL_FROM_SDM) && ret--) + ; + if (!ret) + return -ETIMEDOUT; + + /* clear interrupt */ + MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM); + + if (urgent) { + u32 new_status = MBOX_READL(MBOX_STATUS); + /* urgent command doesn't have response */ + MBOX_WRITEL(0, MBOX_URG); + /* Urgent ACK is toggled */ + if ((new_status & MBOX_STATUS_UA_MSK) ^ status) + return 0; + + return -ECOMM; + } + + /* read current response offset */ + rout = MBOX_READL(MBOX_ROUT); + + /* read response valid offset */ + rin = MBOX_READL(MBOX_RIN); + + if (rout != rin) { + /* Response received */ + resp = MBOX_READ_RESP_BUF(rout); + rout++; + /* wrapping around when it reach the buffer size */ + rout %= MBOX_RESP_BUFFER_SIZE; + /* update next ROUT */ + MBOX_WRITEL(rout, MBOX_ROUT); + + /* check client ID and ID */ + if ((MBOX_RESP_CLIENT_GET(resp) == + MBOX_CLIENT_ID_UBOOT) && + (MBOX_RESP_ID_GET(resp) == id)) { + ret = MBOX_RESP_ERR_GET(resp); + if (ret) + return ret; + + if (resp_buf_len) { + buf_len = *resp_buf_len; + *resp_buf_len = 0; + } else { + buf_len = 0; + } + + resp_len = MBOX_RESP_LEN_GET(resp); + while (resp_len) { + ret = mbox_polling_resp(rout); + if (ret) + return ret; + /* we need to process response buffer + * even caller doesn't need it + */ + resp = MBOX_READ_RESP_BUF(rout); + rout++; + resp_len--; + rout %= MBOX_RESP_BUFFER_SIZE; + MBOX_WRITEL(rout, MBOX_ROUT); + if (buf_len) { + /* copy response to buffer */ + resp_buf[*resp_buf_len] = resp; + (*resp_buf_len)++; + buf_len--; + } + } + return ret; + } + } + }; + + return -EIO; +} + +int mbox_init(void) +{ + int ret; + + /* enable mailbox interrupts */ + MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS); + + /* Ensure urgent request is cleared */ + MBOX_WRITEL(0, MBOX_URG); + + /* Ensure the Doorbell Interrupt is cleared */ + MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM); + + ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RESTART, MBOX_CMD_DIRECT, 0, + NULL, 1, 0, NULL); + if (ret) + return ret; + + /* Renable mailbox interrupts after MBOX_RESTART */ + MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS); + + return 0; +} + +#ifdef CONFIG_CADENCE_QSPI +int mbox_qspi_close(void) +{ + return mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_CLOSE, MBOX_CMD_DIRECT, + 0, NULL, 0, 0, NULL); +} + +int mbox_qspi_open(void) +{ + static const struct socfpga_system_manager *sysmgr_regs = + (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; + + int ret; + u32 resp_buf[1]; + u32 resp_buf_len; + + ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, MBOX_CMD_DIRECT, + 0, NULL, 0, 0, NULL); + if (ret) { + /* retry again by closing and reopen the QSPI again */ + ret = mbox_qspi_close(); + if (ret) + return ret; + + ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, + MBOX_CMD_DIRECT, 0, NULL, 0, 0, NULL); + if (ret) + return ret; + } + + /* HPS will directly control the QSPI controller, no longer mailbox */ + resp_buf_len = 1; + ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_DIRECT, MBOX_CMD_DIRECT, + 0, NULL, 0, (u32 *)&resp_buf_len, + (u32 *)&resp_buf); + if (ret) + goto error; + + /* We are getting QSPI ref clock and set into sysmgr boot register */ + printf("QSPI: Reference clock at %d Hz\n", resp_buf[0]); + writel(resp_buf[0], &sysmgr_regs->boot_scratch_cold0); + + return 0; + +error: + mbox_qspi_close(); + + return ret; +} +#endif /* CONFIG_CADENCE_QSPI */ + +int mbox_reset_cold(void) +{ + int ret; + + ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_REBOOT_HPS, MBOX_CMD_DIRECT, + 0, NULL, 0, 0, NULL); + if (ret) { + /* mailbox sent failure, wait for watchdog to kick in */ + hang(); + } + return 0; +} + +int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, + u8 urgent, u32 *resp_buf_len, u32 *resp_buf) +{ + return mbox_send_cmd_common(id, cmd, is_indirect, len, arg, urgent, + resp_buf_len, resp_buf); +} + +int __secure mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, + u32 *arg, u8 urgent, u32 *resp_buf_len, + u32 *resp_buf) +{ + return mbox_send_cmd_common(id, cmd, is_indirect, len, arg, urgent, + resp_buf_len, resp_buf); +} + +int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg) +{ + return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg); +} + +int __secure mbox_send_cmd_only_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, + u32 *arg) +{ + return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg); +} + +int mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len) +{ + return __mbox_rcv_resp(resp_buf, resp_buf_max_len); +} + +int __secure mbox_rcv_resp_psci(u32 *resp_buf, u32 resp_buf_max_len) +{ + return __mbox_rcv_resp(resp_buf, resp_buf_max_len); +} diff --git a/arch/arm/mach-socfpga/misc.c b/arch/arm/mach-socfpga/misc.c index fca86507f18..77628e11818 100644 --- a/arch/arm/mach-socfpga/misc.c +++ b/arch/arm/mach-socfpga/misc.c @@ -40,7 +40,9 @@ struct bsel bsel_str[] = { int dram_init(void) { - gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); + if (fdtdec_setup_memory_size() != 0) + return -EINVAL; + return 0; } @@ -204,3 +206,34 @@ int socfpga_eth_reset_common(void (*resetfn)(const u8 of_reset_id, return 0; } #endif + +#ifndef CONFIG_SPL_BUILD +static int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc != 2) + return CMD_RET_USAGE; + + argv++; + + switch (*argv[0]) { + case 'e': /* Enable */ + do_bridge_reset(1); + break; + case 'd': /* Disable */ + do_bridge_reset(0); + break; + default: + return CMD_RET_USAGE; + } + + return 0; +} + +U_BOOT_CMD(bridge, 2, 1, do_bridge, + "SoCFPGA HPS FPGA bridge control", + "enable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" + "bridge disable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" + "" +); + +#endif diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index 47a9d50ef13..a75cbc4ce6c 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -14,6 +14,7 @@ #include <asm/arch/misc.h> #include <asm/arch/pinmux.h> #include <asm/arch/reset_manager.h> +#include <asm/arch/reset_manager_arria10.h> #include <asm/arch/sdram_arria10.h> #include <asm/arch/system_manager.h> #include <asm/arch/nic301.h> @@ -262,3 +263,11 @@ int arch_misc_init(void) return socfpga_eth_reset(); } #endif + +void do_bridge_reset(int enable) +{ + if (enable) + socfpga_reset_deassert_bridges_handoff(); + else + socfpga_bridges_reset(); +} diff --git a/arch/arm/mach-socfpga/misc_gen5.c b/arch/arm/mach-socfpga/misc_gen5.c index 434373404e3..848551c73f8 100644 --- a/arch/arm/mach-socfpga/misc_gen5.c +++ b/arch/arm/mach-socfpga/misc_gen5.c @@ -259,40 +259,20 @@ static void socfpga_sdram_apply_static_cfg(void) : : "r"(val), "r"(&sdr_ctrl->static_cfg) : "memory", "cc"); } -static int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +void do_bridge_reset(int enable) { - if (argc != 2) - return CMD_RET_USAGE; - - argv++; - - switch (*argv[0]) { - case 'e': /* Enable */ + if (enable) { writel(iswgrp_handoff[2], &sysmgr_regs->fpgaintfgrp_module); socfpga_sdram_apply_static_cfg(); writel(iswgrp_handoff[3], &sdr_ctrl->fpgaport_rst); writel(iswgrp_handoff[0], &reset_manager_base->brg_mod_reset); writel(iswgrp_handoff[1], &nic301_regs->remap); - break; - case 'd': /* Disable */ + } else { writel(0, &sysmgr_regs->fpgaintfgrp_module); writel(0, &sdr_ctrl->fpgaport_rst); socfpga_sdram_apply_static_cfg(); writel(0, &reset_manager_base->brg_mod_reset); writel(1, &nic301_regs->remap); - break; - default: - return CMD_RET_USAGE; } - - return 0; } - -U_BOOT_CMD( - bridge, 2, 1, do_bridge, - "SoCFPGA HPS FPGA bridge control", - "enable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" - "bridge disable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" - "" -); #endif diff --git a/arch/arm/mach-socfpga/misc_s10.c b/arch/arm/mach-socfpga/misc_s10.c new file mode 100644 index 00000000000..918baac5025 --- /dev/null +++ b/arch/arm/mach-socfpga/misc_s10.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Intel Corporation <www.intel.com> + * + */ + +#include <altera.h> +#include <common.h> +#include <errno.h> +#include <fdtdec.h> +#include <miiphy.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/reset_manager.h> +#include <asm/arch/system_manager.h> +#include <asm/arch/misc.h> +#include <asm/pl310.h> +#include <linux/libfdt.h> + +#include <dt-bindings/reset/altr,rst-mgr-s10.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct socfpga_system_manager *sysmgr_regs = + (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; + +/* + * DesignWare Ethernet initialization + */ +#ifdef CONFIG_ETH_DESIGNWARE + +static u32 socfpga_phymode_setup(u32 gmac_index, const char *phymode) +{ + u32 modereg; + + if (!phymode) + return -EINVAL; + + if (!strcmp(phymode, "mii") || !strcmp(phymode, "gmii")) + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; + else if (!strcmp(phymode, "rgmii")) + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; + else if (!strcmp(phymode, "rmii")) + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; + else + return -EINVAL; + + clrsetbits_le32(&sysmgr_regs->emac0 + gmac_index, + SYSMGR_EMACGRP_CTRL_PHYSEL_MASK, + modereg); + + return 0; +} + +static int socfpga_set_phymode(void) +{ + const void *fdt = gd->fdt_blob; + struct fdtdec_phandle_args args; + const char *phy_mode; + u32 gmac_index; + int nodes[2]; /* Max. 3 GMACs */ + int ret, count; + int i, node; + + count = fdtdec_find_aliases_for_id(fdt, "ethernet", + COMPAT_ALTERA_SOCFPGA_DWMAC, + nodes, ARRAY_SIZE(nodes)); + for (i = 0; i < count; i++) { + node = nodes[i]; + if (node <= 0) + continue; + + ret = fdtdec_parse_phandle_with_args(fdt, node, "resets", + "#reset-cells", 1, 0, + &args); + if (ret || args.args_count != 1) { + debug("GMAC%i: Failed to parse DT 'resets'!\n", i); + continue; + } + + gmac_index = args.args[0] - EMAC0_RESET; + + phy_mode = fdt_getprop(fdt, node, "phy-mode", NULL); + ret = socfpga_phymode_setup(gmac_index, phy_mode); + if (ret) { + debug("GMAC%i: Failed to parse DT 'phy-mode'!\n", i); + continue; + } + } + + return 0; +} +#else +static int socfpga_set_phymode(void) +{ + return 0; +}; +#endif + +/* + * Print CPU information + */ +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + puts("CPU: Intel FPGA SoCFPGA Platform (ARMv8 64bit Cortex-A53)\n"); + + return 0; +} +#endif + +#ifdef CONFIG_ARCH_MISC_INIT +int arch_misc_init(void) +{ + char qspi_string[13]; + + sprintf(qspi_string, "<0x%08x>", cm_get_qspi_controller_clk_hz()); + env_set("qspi_clock", qspi_string); + + socfpga_set_phymode(); + return 0; +} +#endif + +int arch_early_init_r(void) +{ + return 0; +} + +void do_bridge_reset(int enable) +{ + socfpga_bridges_reset(enable); +} diff --git a/arch/arm/mach-socfpga/mmu-arm64_s10.c b/arch/arm/mach-socfpga/mmu-arm64_s10.c new file mode 100644 index 00000000000..670ceb92ae3 --- /dev/null +++ b/arch/arm/mach-socfpga/mmu-arm64_s10.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Intel Corporation <www.intel.com> + * + */ + +#include <common.h> +#include <asm/armv8/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct mm_region socfpga_stratix10_mem_map[] = { + { + /* MEM 2GB*/ + .virt = 0x0UL, + .phys = 0x0UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* FPGA 1.5GB */ + .virt = 0x80000000UL, + .phys = 0x80000000UL, + .size = 0x60000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, { + /* DEVICE 142MB */ + .virt = 0xF7000000UL, + .phys = 0xF7000000UL, + .size = 0x08E00000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, { + /* OCRAM 1MB but available 256KB */ + .virt = 0xFFE00000UL, + .phys = 0xFFE00000UL, + .size = 0x00100000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* DEVICE 32KB */ + .virt = 0xFFFC0000UL, + .phys = 0xFFFC0000UL, + .size = 0x00008000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, { + /* MEM 124GB */ + .virt = 0x0100000000UL, + .phys = 0x0100000000UL, + .size = 0x1F00000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* DEVICE 4GB */ + .virt = 0x2000000000UL, + .phys = 0x2000000000UL, + .size = 0x0100000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, { + /* List terminator */ + }, +}; + +struct mm_region *mem_map = socfpga_stratix10_mem_map; diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c new file mode 100644 index 00000000000..fe4782c9cb6 --- /dev/null +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 Altera Corporation <www.altera.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/pl310.h> +#include <asm/u-boot.h> +#include <asm/utils.h> +#include <image.h> +#include <asm/arch/reset_manager.h> +#include <spl.h> +#include <asm/arch/system_manager.h> +#include <asm/arch/freeze_controller.h> +#include <asm/arch/clock_manager.h> +#include <asm/arch/scan_manager.h> +#include <asm/arch/sdram.h> +#include <asm/arch/scu.h> +#include <asm/arch/nic301.h> +#include <asm/sections.h> +#include <fdtdec.h> +#include <watchdog.h> +#include <asm/arch/pinmux.h> + +DECLARE_GLOBAL_DATA_PTR; + +static const struct socfpga_system_manager *sysmgr_regs = + (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; + +u32 spl_boot_device(void) +{ + const u32 bsel = readl(&sysmgr_regs->bootinfo); + + switch (SYSMGR_GET_BOOTINFO_BSEL(bsel)) { + case 0x1: /* FPGA (HPS2FPGA Bridge) */ + return BOOT_DEVICE_RAM; + case 0x2: /* NAND Flash (1.8V) */ + case 0x3: /* NAND Flash (3.0V) */ + socfpga_per_reset(SOCFPGA_RESET(NAND), 0); + return BOOT_DEVICE_NAND; + case 0x4: /* SD/MMC External Transceiver (1.8V) */ + case 0x5: /* SD/MMC Internal Transceiver (3.0V) */ + socfpga_per_reset(SOCFPGA_RESET(SDMMC), 0); + socfpga_per_reset(SOCFPGA_RESET(DMA), 0); + return BOOT_DEVICE_MMC1; + case 0x6: /* QSPI Flash (1.8V) */ + case 0x7: /* QSPI Flash (3.0V) */ + socfpga_per_reset(SOCFPGA_RESET(QSPI), 0); + return BOOT_DEVICE_SPI; + default: + printf("Invalid boot device (bsel=%08x)!\n", bsel); + hang(); + } +} + +#ifdef CONFIG_SPL_MMC_SUPPORT +u32 spl_boot_mode(const u32 boot_device) +{ +#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) + return MMCSD_MODE_FS; +#else + return MMCSD_MODE_RAW; +#endif +} +#endif + +void spl_board_init(void) +{ + /* configuring the clock based on handoff */ + cm_basic_init(gd->fdt_blob); + WATCHDOG_RESET(); + + config_dedicated_pins(gd->fdt_blob); + WATCHDOG_RESET(); + + /* Release UART from reset */ + socfpga_reset_uart(0); + + /* enable console uart printing */ + preloader_console_init(); +} + +void board_init_f(ulong dummy) +{ + /* + * Configure Clock Manager to use intosc clock instead external osc to + * ensure success watchdog operation. We do it as early as possible. + */ + cm_use_intosc(); + + socfpga_watchdog_disable(); + + arch_early_init_r(); + +#ifdef CONFIG_HW_WATCHDOG + /* release osc1 watchdog timer 0 from reset */ + socfpga_reset_deassert_osc1wd0(); + + /* reconfigure and enable the watchdog */ + hw_watchdog_init(); + WATCHDOG_RESET(); +#endif /* CONFIG_HW_WATCHDOG */ +} diff --git a/arch/arm/mach-socfpga/spl.c b/arch/arm/mach-socfpga/spl_gen5.c index 0c9d7388e68..d6fe7d35af1 100644 --- a/arch/arm/mach-socfpga/spl.c +++ b/arch/arm/mach-socfpga/spl_gen5.c @@ -22,21 +22,15 @@ #include <asm/sections.h> #include <fdtdec.h> #include <watchdog.h> -#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10) -#include <asm/arch/pinmux.h> -#endif DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_TARGET_SOCFPGA_GEN5) static struct pl310_regs *const pl310 = (struct pl310_regs *)CONFIG_SYS_PL310_BASE; static struct scu_registers *scu_regs = (struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS; static struct nic301_registers *nic301_regs = (struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS; -#endif - static const struct socfpga_system_manager *sysmgr_regs = (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; @@ -66,7 +60,17 @@ u32 spl_boot_device(void) } } -#if defined(CONFIG_TARGET_SOCFPGA_GEN5) +#ifdef CONFIG_SPL_MMC_SUPPORT +u32 spl_boot_mode(const u32 boot_device) +{ +#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) + return MMCSD_MODE_FS; +#else + return MMCSD_MODE_RAW; +#endif +} +#endif + static void socfpga_nic301_slave_ns(void) { writel(0x1, &nic301_regs->lwhps2fpgaregs); @@ -177,47 +181,3 @@ void board_init_f(ulong dummy) /* Configure simple malloc base pointer into RAM. */ gd->malloc_base = CONFIG_SYS_TEXT_BASE + (1024 * 1024); } -#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) -void spl_board_init(void) -{ - /* configuring the clock based on handoff */ - cm_basic_init(gd->fdt_blob); - WATCHDOG_RESET(); - - config_dedicated_pins(gd->fdt_blob); - WATCHDOG_RESET(); - - /* Release UART from reset */ - socfpga_reset_uart(0); - - /* enable console uart printing */ - preloader_console_init(); - - WATCHDOG_RESET(); - - /* Add device descriptor to FPGA device table */ - socfpga_fpga_add(); -} - -void board_init_f(ulong dummy) -{ - /* - * Configure Clock Manager to use intosc clock instead external osc to - * ensure success watchdog operation. We do it as early as possible. - */ - cm_use_intosc(); - - socfpga_watchdog_disable(); - - arch_early_init_r(); - -#ifdef CONFIG_HW_WATCHDOG - /* release osc1 watchdog timer 0 from reset */ - socfpga_reset_deassert_osc1wd0(); - - /* reconfigure and enable the watchdog */ - hw_watchdog_init(); - WATCHDOG_RESET(); -#endif /* CONFIG_HW_WATCHDOG */ -} -#endif diff --git a/arch/arm/mach-socfpga/spl_s10.c b/arch/arm/mach-socfpga/spl_s10.c new file mode 100644 index 00000000000..69d6e919aa0 --- /dev/null +++ b/arch/arm/mach-socfpga/spl_s10.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Intel Corporation <www.intel.com> + * + */ + +#include <asm/io.h> +#include <asm/u-boot.h> +#include <asm/utils.h> +#include <common.h> +#include <debug_uart.h> +#include <image.h> +#include <spl.h> +#include <asm/arch/clock_manager.h> +#include <asm/arch/firewall_s10.h> +#include <asm/arch/mailbox_s10.h> +#include <asm/arch/reset_manager.h> +#include <asm/arch/sdram_s10.h> +#include <asm/arch/system_manager.h> +#include <watchdog.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct socfpga_system_manager *sysmgr_regs = + (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; + +u32 spl_boot_device(void) +{ + /* TODO: Get from SDM or handoff */ + return BOOT_DEVICE_MMC1; +} + +#ifdef CONFIG_SPL_MMC_SUPPORT +u32 spl_boot_mode(const u32 boot_device) +{ +#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) + return MMCSD_MODE_FS; +#else + return MMCSD_MODE_RAW; +#endif +} +#endif + +void spl_disable_firewall_l4_per(void) +{ + const struct socfpga_firwall_l4_per *firwall_l4_per_base = + (struct socfpga_firwall_l4_per *)SOCFPGA_FIREWALL_L4_PER; + u32 i; + const u32 *addr[] = { + &firwall_l4_per_base->nand, + &firwall_l4_per_base->nand_data, + &firwall_l4_per_base->usb0, + &firwall_l4_per_base->usb1, + &firwall_l4_per_base->spim0, + &firwall_l4_per_base->spim1, + &firwall_l4_per_base->emac0, + &firwall_l4_per_base->emac1, + &firwall_l4_per_base->emac2, + &firwall_l4_per_base->sdmmc, + &firwall_l4_per_base->gpio0, + &firwall_l4_per_base->gpio1, + &firwall_l4_per_base->i2c0, + &firwall_l4_per_base->i2c1, + &firwall_l4_per_base->i2c2, + &firwall_l4_per_base->i2c3, + &firwall_l4_per_base->i2c4, + &firwall_l4_per_base->timer0, + &firwall_l4_per_base->timer1, + &firwall_l4_per_base->uart0, + &firwall_l4_per_base->uart1 + }; + + /* + * The following lines of code will enable non-secure access + * to nand, usb, spi, emac, sdmmc, gpio, i2c, timers and uart. This + * is needed as most OS run in non-secure mode. Thus we need to + * enable non-secure access to these peripherals in order for the + * OS to use these peripherals. + */ + for (i = 0; i < ARRAY_SIZE(addr); i++) + writel(FIREWALL_L4_DISABLE_ALL, addr[i]); +} + +void spl_disable_firewall_l4_sys(void) +{ + const struct socfpga_firwall_l4_sys *firwall_l4_sys_base = + (struct socfpga_firwall_l4_sys *)SOCFPGA_FIREWALL_L4_SYS; + u32 i; + const u32 *addr[] = { + &firwall_l4_sys_base->dma_ecc, + &firwall_l4_sys_base->emac0rx_ecc, + &firwall_l4_sys_base->emac0tx_ecc, + &firwall_l4_sys_base->emac1rx_ecc, + &firwall_l4_sys_base->emac1tx_ecc, + &firwall_l4_sys_base->emac2rx_ecc, + &firwall_l4_sys_base->emac2tx_ecc, + &firwall_l4_sys_base->nand_ecc, + &firwall_l4_sys_base->nand_read_ecc, + &firwall_l4_sys_base->nand_write_ecc, + &firwall_l4_sys_base->ocram_ecc, + &firwall_l4_sys_base->sdmmc_ecc, + &firwall_l4_sys_base->usb0_ecc, + &firwall_l4_sys_base->usb1_ecc, + &firwall_l4_sys_base->clock_manager, + &firwall_l4_sys_base->io_manager, + &firwall_l4_sys_base->reset_manager, + &firwall_l4_sys_base->system_manager, + &firwall_l4_sys_base->watchdog0, + &firwall_l4_sys_base->watchdog1, + &firwall_l4_sys_base->watchdog2, + &firwall_l4_sys_base->watchdog3 + }; + + for (i = 0; i < ARRAY_SIZE(addr); i++) + writel(FIREWALL_L4_DISABLE_ALL, addr[i]); +} + +void board_init_f(ulong dummy) +{ + const struct cm_config *cm_default_cfg = cm_get_default_config(); + int ret; + +#ifdef CONFIG_HW_WATCHDOG + /* Ensure watchdog is paused when debugging is happening */ + writel(SYSMGR_WDDBG_PAUSE_ALL_CPU, &sysmgr_regs->wddbg); + + /* Enable watchdog before initializing the HW */ + socfpga_per_reset(SOCFPGA_RESET(L4WD0), 1); + socfpga_per_reset(SOCFPGA_RESET(L4WD0), 0); + hw_watchdog_init(); +#endif + + /* ensure all processors are not released prior Linux boot */ + writeq(0, CPU_RELEASE_ADDR); + + socfpga_per_reset(SOCFPGA_RESET(OSC1TIMER0), 0); + timer_init(); + + populate_sysmgr_pinmux(); + + /* configuring the HPS clocks */ + cm_basic_init(cm_default_cfg); + +#ifdef CONFIG_DEBUG_UART + socfpga_per_reset(SOCFPGA_RESET(UART0), 0); + debug_uart_init(); +#endif + ret = spl_early_init(); + if (ret) { + debug("spl_early_init() failed: %d\n", ret); + hang(); + } + + preloader_console_init(); + cm_print_clock_quick_summary(); + + /* enable non-secure interface to DMA330 DMA and peripherals */ + writel(SYSMGR_DMA_IRQ_NS | SYSMGR_DMA_MGR_NS, &sysmgr_regs->dma); + writel(SYSMGR_DMAPERIPH_ALL_NS, &sysmgr_regs->dma_periph); + + spl_disable_firewall_l4_per(); + + spl_disable_firewall_l4_sys(); + + /* disable lwsocf2fpga and soc2fpga bridge security */ + writel(FIREWALL_BRIDGE_DISABLE_ALL, SOCFPGA_FIREWALL_SOC2FPGA); + writel(FIREWALL_BRIDGE_DISABLE_ALL, SOCFPGA_FIREWALL_LWSOC2FPGA); + + /* disable SMMU security */ + writel(FIREWALL_L4_DISABLE_ALL, SOCFPGA_FIREWALL_TCU); + + /* disable ocram security at CCU for non secure access */ + clrbits_le32(CCU_REG_ADDR(CCU_CPU0_MPRT_ADMASK_MEM_RAM0), + CCU_ADMASK_P_MASK | CCU_ADMASK_NS_MASK); + clrbits_le32(CCU_REG_ADDR(CCU_IOM_MPRT_ADMASK_MEM_RAM0), + CCU_ADMASK_P_MASK | CCU_ADMASK_NS_MASK); + + debug("DDR: Initializing Hard Memory Controller\n"); + if (sdram_mmr_init_full(0)) { + puts("DDR: Initialization failed.\n"); + hang(); + } + + gd->ram_size = sdram_calculate_size(); + printf("DDR: %d MiB\n", (int)(gd->ram_size >> 20)); + + /* Sanity check ensure correct SDRAM size specified */ + debug("DDR: Running SDRAM size sanity check\n"); + if (get_ram_size(0, gd->ram_size) != gd->ram_size) { + puts("DDR: SDRAM size check failed!\n"); + hang(); + } + debug("DDR: SDRAM size check passed!\n"); + + mbox_init(); + +#ifdef CONFIG_CADENCE_QSPI + mbox_qspi_open(); +#endif +} diff --git a/arch/arm/mach-socfpga/timer_s10.c b/arch/arm/mach-socfpga/timer_s10.c new file mode 100644 index 00000000000..57237892c34 --- /dev/null +++ b/arch/arm/mach-socfpga/timer_s10.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017-2018 Intel Corporation <www.intel.com> + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/timer.h> + +/* + * Timer initialization + */ +int timer_init(void) +{ + int enable = 0x3; /* timer enable + output signal masked */ + int loadval = ~0; + + /* enable system counter */ + writel(enable, SOCFPGA_GTIMER_SEC_ADDRESS); + /* enable processor pysical counter */ + asm volatile("msr cntp_ctl_el0, %0" : : "r" (enable)); + asm volatile("msr cntp_tval_el0, %0" : : "r" (loadval)); + + return 0; +} |