Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / arm / mach-k3 / am6_init.c
index 8a3a99f23a7f621837261ccefe90caff3f63019e..516a02e8a899e87ba1ee8b9d6c4c182c6ea8a09a 100644 (file)
@@ -1,17 +1,46 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * K3: Architecture initialization
+ * AM6: SoC specific initialization
  *
  * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
  *     Lokesh Vutla <lokeshvutla@ti.com>
  */
 
 #include <common.h>
+#include <init.h>
 #include <asm/io.h>
 #include <spl.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sysfw-loader.h>
+#include <asm/arch/sys_proto.h>
+#include "common.h"
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <dm/pinctrl.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include <mmc.h>
 
 #ifdef CONFIG_SPL_BUILD
+#ifdef CONFIG_K3_LOAD_SYSFW
+#ifdef CONFIG_TI_SECURE_DEVICE
+struct fwl_data main_cbass_fwls[] = {
+       { "MMCSD1_CFG", 2057, 1 },
+       { "MMCSD0_CFG", 2058, 1 },
+       { "USB3SS0_SLV0", 2176, 2 },
+       { "PCIE0_SLV", 2336, 8 },
+       { "PCIE1_SLV", 2337, 8 },
+       { "PCIE0_CFG", 2688, 1 },
+       { "PCIE1_CFG", 2689, 1 },
+}, mcu_cbass_fwls[] = {
+       { "MCU_ARMSS0_CORE0_SLV", 1024, 1 },
+       { "MCU_ARMSS0_CORE1_SLV", 1028, 1 },
+       { "MCU_FSS0_S1", 1033, 8 },
+       { "MCU_FSS0_S0", 1036, 8 },
+       { "MCU_CPSW0", 1220, 1 },
+};
+#endif
+#endif
+
 static void mmr_unlock(u32 base, u32 partition)
 {
        /* Translate the base address */
@@ -47,15 +76,51 @@ static void ctrl_mmr_unlock(void)
        mmr_unlock(CTRL_MMR0_BASE, 7);
 }
 
+/*
+ * This uninitialized global variable would normal end up in the .bss section,
+ * but the .bss is cleared between writing and reading this variable, so move
+ * it to the .data section.
+ */
+u32 bootindex __attribute__((section(".data")));
+
 static void store_boot_index_from_rom(void)
 {
-       u32 *boot_index = (u32 *)K3_BOOT_PARAM_TABLE_INDEX_VAL;
+       bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
+}
+
+#if defined(CONFIG_K3_LOAD_SYSFW)
+void k3_mmc_stop_clock(void)
+{
+       if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+               struct mmc *mmc = find_mmc_device(0);
+
+               if (!mmc)
+                       return;
+
+               mmc->saved_clock = mmc->clock;
+               mmc_set_clock(mmc, 0, true);
+       }
+}
+
+void k3_mmc_restart_clock(void)
+{
+       if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+               struct mmc *mmc = find_mmc_device(0);
+
+               if (!mmc)
+                       return;
 
-       *boot_index = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
+               mmc_set_clock(mmc, mmc->saved_clock, false);
+       }
 }
+#endif
 
 void board_init_f(ulong dummy)
 {
+#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS)
+       struct udevice *dev;
+       int ret;
+#endif
        /*
         * Cannot delay this further as there is a chance that
         * K3_BOOT_PARAM_TABLE_INDEX can be over written by SPL MALLOC section.
@@ -65,11 +130,97 @@ void board_init_f(ulong dummy)
        /* Make all control module registers accessible */
        ctrl_mmr_unlock();
 
+#ifdef CONFIG_CPU_V7R
+       disable_linefill_optimization();
+       setup_k3_mpu_regions();
+#endif
+
        /* Init DM early in-order to invoke system controller */
        spl_early_init();
 
+#ifdef CONFIG_K3_EARLY_CONS
+       /*
+        * Allow establishing an early console as required for example when
+        * doing a UART-based boot. Note that this console may not "survive"
+        * through a SYSFW PM-init step and will need a re-init in some way
+        * due to changing module clock frequencies.
+        */
+       early_console_init();
+#endif
+
+#ifdef CONFIG_K3_LOAD_SYSFW
+       /*
+        * Process pinctrl for the serial0 a.k.a. WKUP_UART0 module and continue
+        * regardless of the result of pinctrl. Do this without probing the
+        * device, but instead by searching the device that would request the
+        * given sequence number if probed. The UART will be used by the system
+        * firmware (SYSFW) image for various purposes and SYSFW depends on us
+        * to initialize its pin settings.
+        */
+       ret = uclass_find_device_by_seq(UCLASS_SERIAL, 0, true, &dev);
+       if (!ret)
+               pinctrl_select_state(dev, "default");
+
+       /*
+        * Load, start up, and configure system controller firmware while
+        * also populating the SYSFW post-PM configuration callback hook.
+        */
+       k3_sysfw_loader(k3_mmc_stop_clock, k3_mmc_restart_clock);
+
+       /* Prepare console output */
+       preloader_console_init();
+
+       /* Disable ROM configured firewalls right after loading sysfw */
+#ifdef CONFIG_TI_SECURE_DEVICE
+       remove_fwl_configs(main_cbass_fwls, ARRAY_SIZE(main_cbass_fwls));
+       remove_fwl_configs(mcu_cbass_fwls, ARRAY_SIZE(mcu_cbass_fwls));
+#endif
+#else
        /* Prepare console output */
        preloader_console_init();
+#endif
+
+       /* Output System Firmware version info */
+       k3_sysfw_print_ver();
+
+       /* Perform EEPROM-based board detection */
+       do_board_detect();
+
+#if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
+       ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(k3_avs),
+                                         &dev);
+       if (ret)
+               printf("AVS init failed: %d\n", ret);
+#endif
+
+#ifdef CONFIG_K3_AM654_DDRSS
+       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+       if (ret)
+               panic("DRAM init failed: %d\n", ret);
+#endif
+       spl_enable_dcache();
+}
+
+u32 spl_mmc_boot_mode(const u32 boot_device)
+{
+#if defined(CONFIG_SUPPORT_EMMC_BOOT)
+       u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT);
+
+       u32 bootmode = (devstat & CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK) >>
+                       CTRLMMR_MAIN_DEVSTAT_BOOTMODE_SHIFT;
+
+       /* eMMC boot0 mode is only supported for primary boot */
+       if (bootindex == K3_PRIMARY_BOOTMODE &&
+           bootmode == BOOT_DEVICE_MMC1)
+               return MMCSD_MODE_EMMCBOOT;
+#endif
+
+       /* Everything else use filesystem if available */
+#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
+       return MMCSD_MODE_FS;
+#else
+       return MMCSD_MODE_RAW;
+#endif
 }
 
 static u32 __get_backup_bootmedia(u32 devstat)
@@ -85,7 +236,13 @@ static u32 __get_backup_bootmedia(u32 devstat)
        case BACKUP_BOOT_DEVICE_ETHERNET:
                return BOOT_DEVICE_ETHERNET;
        case BACKUP_BOOT_DEVICE_MMC2:
+       {
+               u32 port = (devstat & CTRLMMR_MAIN_DEVSTAT_BKUP_MMC_PORT_MASK) >>
+                           CTRLMMR_MAIN_DEVSTAT_BKUP_MMC_PORT_SHIFT;
+               if (port == 0x0)
+                       return BOOT_DEVICE_MMC1;
                return BOOT_DEVICE_MMC2;
+       }
        case BACKUP_BOOT_DEVICE_SPI:
                return BOOT_DEVICE_SPI;
        case BACKUP_BOOT_DEVICE_HYPERFLASH:
@@ -99,18 +256,30 @@ static u32 __get_backup_bootmedia(u32 devstat)
 
 static u32 __get_primary_bootmedia(u32 devstat)
 {
-       u32 bootmode = devstat & CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK;
+       u32 bootmode = (devstat & CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK) >>
+                       CTRLMMR_MAIN_DEVSTAT_BOOTMODE_SHIFT;
 
        if (bootmode == BOOT_DEVICE_OSPI || bootmode == BOOT_DEVICE_QSPI)
                bootmode = BOOT_DEVICE_SPI;
 
+       if (bootmode == BOOT_DEVICE_MMC2) {
+               u32 port = (devstat & CTRLMMR_MAIN_DEVSTAT_MMC_PORT_MASK) >>
+                           CTRLMMR_MAIN_DEVSTAT_MMC_PORT_SHIFT;
+               if (port == 0x0)
+                       bootmode = BOOT_DEVICE_MMC1;
+       } else if (bootmode == BOOT_DEVICE_MMC1) {
+               u32 port = (devstat & CTRLMMR_MAIN_DEVSTAT_EMMC_PORT_MASK) >>
+                           CTRLMMR_MAIN_DEVSTAT_EMMC_PORT_SHIFT;
+               if (port == 0x1)
+                       bootmode = BOOT_DEVICE_MMC2;
+       }
+
        return bootmode;
 }
 
 u32 spl_boot_device(void)
 {
        u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT);
-       u32 bootindex = readl(K3_BOOT_PARAM_TABLE_INDEX_VAL);
 
        if (bootindex == K3_PRIMARY_BOOTMODE)
                return __get_primary_bootmedia(devstat);
@@ -119,8 +288,53 @@ u32 spl_boot_device(void)
 }
 #endif
 
-#ifndef CONFIG_SYSRESET
-void reset_cpu(ulong ignored)
+#ifdef CONFIG_SYS_K3_SPL_ATF
+
+#define AM6_DEV_MCU_RTI0                       134
+#define AM6_DEV_MCU_RTI1                       135
+#define AM6_DEV_MCU_ARMSS0_CPU0                        159
+#define AM6_DEV_MCU_ARMSS0_CPU1                        245
+
+void release_resources_for_core_shutdown(void)
 {
+       struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+       struct ti_sci_dev_ops *dev_ops = &ti_sci->ops.dev_ops;
+       struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops;
+       int ret;
+       u32 i;
+
+       const u32 put_device_ids[] = {
+               AM6_DEV_MCU_RTI0,
+               AM6_DEV_MCU_RTI1,
+       };
+
+       /* Iterate through list of devices to put (shutdown) */
+       for (i = 0; i < ARRAY_SIZE(put_device_ids); i++) {
+               u32 id = put_device_ids[i];
+
+               ret = dev_ops->put_device(ti_sci, id);
+               if (ret)
+                       panic("Failed to put device %u (%d)\n", id, ret);
+       }
+
+       const u32 put_core_ids[] = {
+               AM6_DEV_MCU_ARMSS0_CPU1,
+               AM6_DEV_MCU_ARMSS0_CPU0,        /* Handle CPU0 after CPU1 */
+       };
+
+       /* Iterate through list of cores to put (shutdown) */
+       for (i = 0; i < ARRAY_SIZE(put_core_ids); i++) {
+               u32 id = put_core_ids[i];
+
+               /*
+                * Queue up the core shutdown request. Note that this call
+                * needs to be followed up by an actual invocation of an WFE
+                * or WFI CPU instruction.
+                */
+               ret = proc_ops->proc_shutdown_no_wait(ti_sci, id);
+               if (ret)
+                       panic("Failed sending core %u shutdown message (%d)\n",
+                             id, ret);
+       }
 }
 #endif