From 591d110c72b3ffeb660ba82eaebb79cbd0336f0c Mon Sep 17 00:00:00 2001 From: Masahisa Kojima Date: Mon, 17 Jun 2019 12:05:05 +0900 Subject: [PATCH] synquacer: add SynQuacer support Signed-off-by: Masahisa Kojima Change-Id: Ib2430bc06be3c17531dc7d36315444b0756480a5 --- product/synquacer/include/fmw_cmsis.h | 30 + product/synquacer/include/low_level_access.h | 53 + product/synquacer/include/mmu500.h | 265 ++++ product/synquacer/include/pik_cpu.h | 70 + product/synquacer/include/pik_scp.h | 75 + product/synquacer/include/pik_system.h | 63 + .../synquacer/include/scp_system_mmap_scp.h | 24 + product/synquacer/include/synquacer_common.h | 30 + product/synquacer/include/synquacer_config.h | 101 ++ product/synquacer/include/synquacer_core.h | 27 + product/synquacer/include/synquacer_debug.h | 53 + product/synquacer/include/synquacer_irq.h | 91 ++ product/synquacer/include/synquacer_mmap.h | 298 ++++ product/synquacer/include/synquacer_pik.h | 61 + product/synquacer/include/system_clock.h | 39 + .../module/ccn512/include/internal/ccn512.h | 265 ++++ .../module/ccn512/include/mod_ccn512.h | 128 ++ product/synquacer/module/ccn512/src/Makefile | 11 + .../synquacer/module/ccn512/src/mod_ccn512.c | 242 +++ .../synquacer/module/f_i2c/include/i2c_api.h | 31 + .../f_i2c/include/internal/i2c_depend.h | 26 + .../f_i2c/include/internal/i2c_driver.h | 131 ++ .../module/f_i2c/include/internal/i2c_reg.h | 283 ++++ .../f_i2c/include/internal/i2c_reg_access.h | 149 ++ .../module/f_i2c/include/mod_f_i2c.h | 106 ++ product/synquacer/module/f_i2c/src/Makefile | 11 + product/synquacer/module/f_i2c/src/i2c_api.c | 182 +++ .../synquacer/module/f_i2c/src/i2c_depend.c | 97 ++ .../synquacer/module/f_i2c/src/i2c_driver.c | 703 +++++++++ .../module/f_i2c/src/i2c_reg_access.c | 341 +++++ .../synquacer/module/f_i2c/src/mod_f_i2c.c | 68 + .../module/f_uart3/include/mod_f_uart3.h | 57 + product/synquacer/module/f_uart3/src/Makefile | 11 + .../synquacer/module/f_uart3/src/f_uart3.h | 154 ++ .../module/f_uart3/src/mod_f_uart3.c | 226 +++ .../module/hsspi/include/internal/hsspi_api.h | 31 + .../hsspi/include/internal/hsspi_driver.h | 90 ++ .../module/hsspi/include/internal/reg_HSSPI.h | 428 ++++++ .../module/hsspi/include/mod_hsspi.h | 66 + product/synquacer/module/hsspi/src/Makefile | 11 + .../synquacer/module/hsspi/src/hsspi_api.c | 83 + .../synquacer/module/hsspi/src/hsspi_driver.c | 683 +++++++++ .../synquacer/module/hsspi/src/mod_hsspi.c | 70 + .../ppu_v0_synquacer/include/mod_ppu_v0.h | 72 + .../module/ppu_v0_synquacer/include/ppu_v0.h | 147 ++ .../module/ppu_v0_synquacer/src/Makefile | 11 + .../module/ppu_v0_synquacer/src/mod_ppu_v0.c | 387 +++++ .../module/ppu_v0_synquacer/src/ppu_v0.c | 64 + .../include/internal/scmi_vendor_ext.h | 105 ++ .../module/scmi_vendor_ext/src/Makefile | 11 + .../scmi_vendor_ext/src/mod_scmi_vendor_ext.c | 342 +++++ .../module/synquacer_memc/include/ddr_init.h | 58 + .../include/internal/reg_DDRPHY_CONFIG.h | 1040 +++++++++++++ .../include/internal/reg_DMA330.h | 202 +++ .../include/internal/reg_DMC520.h | 427 ++++++ .../include/mod_synquacer_memc.h | 38 + .../synquacer_memc/include/synquacer_ddr.h | 73 + .../module/synquacer_memc/src/Makefile | 11 + .../module/synquacer_memc/src/ddr_init.c | 1340 +++++++++++++++++ .../synquacer_memc/src/mod_synquacer_memc.c | 88 ++ .../module/synquacer_memc/src/synquacer_ddr.c | 896 +++++++++++ .../include/mod_synquacer_pik_clock.h | 287 ++++ .../module/synquacer_pik_clock/src/Makefile | 11 + .../src/mod_synquacer_pik_clock.c | 802 ++++++++++ .../synquacer_rom/include/mod_synquacer_rom.h | 50 + .../module/synquacer_rom/src/Makefile | 11 + .../synquacer_rom/src/mod_synquacer_rom.c | 125 ++ .../module/synquacer_rom/src/synquacer_init.c | 228 +++ .../synquacer_system/include/boot_ctl.h | 16 + .../synquacer_system/include/internal/crg11.h | 36 + .../synquacer_system/include/internal/gpio.h | 26 + .../include/internal/nic400.h | 16 + .../synquacer_system/include/internal/pmu.h | 34 + .../include/internal/reg_PPU.h | 69 + .../synquacer_system/include/internal/reset.h | 113 ++ .../include/internal/smmu_wrapper.h | 33 + .../include/internal/synquacer_pd.h | 284 ++++ .../include/internal/synquacer_ppu_driver.h | 42 + .../synquacer_system/include/internal/sysoc.h | 25 + .../include/internal/thermal_sensor.h | 69 + .../include/internal/transaction_sw.h | 17 + .../include/mod_synquacer_system.h | 91 ++ .../synquacer_system/include/sysdef_option.h | 47 + .../module/synquacer_system/src/Makefile | 24 + .../module/synquacer_system/src/boot_ctl.c | 33 + .../module/synquacer_system/src/gpio.c | 134 ++ .../synquacer_system/src/load_secure_fw.c | 155 ++ .../module/synquacer_system/src/mmu500.c | 145 ++ .../src/mod_synquacer_system.c | 185 +++ .../module/synquacer_system/src/nic400.c | 61 + .../module/synquacer_system/src/pmu_driver.c | 267 ++++ .../module/synquacer_system/src/smmu_config.c | 494 ++++++ .../synquacer_system/src/synquacer_main.c | 368 +++++ .../src/synquacer_pd_manage.c | 370 +++++ .../synquacer_system/src/sysdef_option.c | 95 ++ .../module/synquacer_system/src/sysoc.c | 380 +++++ .../synquacer_system/src/thermal_sensor.c | 58 + .../synquacer_system/src/transaction_sw.c | 68 + product/synquacer/product.mk | 11 + product/synquacer/scp_ramfw/RTX_Config.h | 56 + .../synquacer/scp_ramfw/config_armv7m_mpu.c | 62 + product/synquacer/scp_ramfw/config_ccn512.c | 22 + product/synquacer/scp_ramfw/config_clock.c | 10 + product/synquacer/scp_ramfw/config_clock.h | 118 ++ .../synquacer/scp_ramfw/config_css_clock.c | 28 + product/synquacer/scp_ramfw/config_f_i2c.c | 17 + product/synquacer/scp_ramfw/config_hsspi.c | 17 + .../synquacer/scp_ramfw/config_log_f_uart3.c | 57 + .../synquacer/scp_ramfw/config_log_pl011.c | 56 + product/synquacer/scp_ramfw/config_mhu.c | 43 + product/synquacer/scp_ramfw/config_mhu.h | 17 + .../synquacer/scp_ramfw/config_pik_clock.c | 1148 ++++++++++++++ .../synquacer/scp_ramfw/config_power_domain.c | 238 +++ .../synquacer/scp_ramfw/config_power_domain.h | 30 + product/synquacer/scp_ramfw/config_ppu_v0.h | 59 + .../scp_ramfw/config_ppu_v0_synquacer.c | 159 ++ product/synquacer/scp_ramfw/config_scmi.c | 58 + product/synquacer/scp_ramfw/config_scmi.h | 23 + .../synquacer/scp_ramfw/config_scmi_apcore.c | 29 + .../scp_ramfw/config_scmi_system_power.c | 16 + product/synquacer/scp_ramfw/config_smt.c | 55 + .../scp_ramfw/config_synquacer_memc.c | 16 + .../synquacer/scp_ramfw/config_system_power.c | 92 ++ product/synquacer/scp_ramfw/config_timer.c | 66 + product/synquacer/scp_ramfw/firmware.mk | 74 + product/synquacer/scp_ramfw/fmw_memory.ld.S | 32 + product/synquacer/scp_ramfw/rtx_config.c | 84 ++ .../synquacer/scp_romfw/config_armv7m_mpu.c | 62 + product/synquacer/scp_romfw/config_clock.c | 10 + product/synquacer/scp_romfw/config_clock.h | 29 + .../synquacer/scp_romfw/config_log_f_uart3.c | 57 + .../scp_romfw/config_synquacer_pik_clock.c | 243 +++ .../scp_romfw/config_synquacer_rom.c | 18 + product/synquacer/scp_romfw/config_timer.c | 66 + product/synquacer/scp_romfw/firmware.mk | 37 + product/synquacer/scp_romfw/fmw_memory.ld.S | 32 + product/synquacer/src/synquacer_core.c | 23 + tools/ci.py | 34 + 138 files changed, 19849 insertions(+) create mode 100644 product/synquacer/include/fmw_cmsis.h create mode 100644 product/synquacer/include/low_level_access.h create mode 100644 product/synquacer/include/mmu500.h create mode 100644 product/synquacer/include/pik_cpu.h create mode 100644 product/synquacer/include/pik_scp.h create mode 100644 product/synquacer/include/pik_system.h create mode 100644 product/synquacer/include/scp_system_mmap_scp.h create mode 100644 product/synquacer/include/synquacer_common.h create mode 100644 product/synquacer/include/synquacer_config.h create mode 100644 product/synquacer/include/synquacer_core.h create mode 100644 product/synquacer/include/synquacer_debug.h create mode 100644 product/synquacer/include/synquacer_irq.h create mode 100644 product/synquacer/include/synquacer_mmap.h create mode 100644 product/synquacer/include/synquacer_pik.h create mode 100644 product/synquacer/include/system_clock.h create mode 100644 product/synquacer/module/ccn512/include/internal/ccn512.h create mode 100644 product/synquacer/module/ccn512/include/mod_ccn512.h create mode 100644 product/synquacer/module/ccn512/src/Makefile create mode 100644 product/synquacer/module/ccn512/src/mod_ccn512.c create mode 100644 product/synquacer/module/f_i2c/include/i2c_api.h create mode 100644 product/synquacer/module/f_i2c/include/internal/i2c_depend.h create mode 100644 product/synquacer/module/f_i2c/include/internal/i2c_driver.h create mode 100644 product/synquacer/module/f_i2c/include/internal/i2c_reg.h create mode 100644 product/synquacer/module/f_i2c/include/internal/i2c_reg_access.h create mode 100644 product/synquacer/module/f_i2c/include/mod_f_i2c.h create mode 100644 product/synquacer/module/f_i2c/src/Makefile create mode 100644 product/synquacer/module/f_i2c/src/i2c_api.c create mode 100644 product/synquacer/module/f_i2c/src/i2c_depend.c create mode 100644 product/synquacer/module/f_i2c/src/i2c_driver.c create mode 100644 product/synquacer/module/f_i2c/src/i2c_reg_access.c create mode 100644 product/synquacer/module/f_i2c/src/mod_f_i2c.c create mode 100644 product/synquacer/module/f_uart3/include/mod_f_uart3.h create mode 100644 product/synquacer/module/f_uart3/src/Makefile create mode 100644 product/synquacer/module/f_uart3/src/f_uart3.h create mode 100644 product/synquacer/module/f_uart3/src/mod_f_uart3.c create mode 100644 product/synquacer/module/hsspi/include/internal/hsspi_api.h create mode 100644 product/synquacer/module/hsspi/include/internal/hsspi_driver.h create mode 100644 product/synquacer/module/hsspi/include/internal/reg_HSSPI.h create mode 100644 product/synquacer/module/hsspi/include/mod_hsspi.h create mode 100644 product/synquacer/module/hsspi/src/Makefile create mode 100644 product/synquacer/module/hsspi/src/hsspi_api.c create mode 100644 product/synquacer/module/hsspi/src/hsspi_driver.c create mode 100644 product/synquacer/module/hsspi/src/mod_hsspi.c create mode 100644 product/synquacer/module/ppu_v0_synquacer/include/mod_ppu_v0.h create mode 100644 product/synquacer/module/ppu_v0_synquacer/include/ppu_v0.h create mode 100644 product/synquacer/module/ppu_v0_synquacer/src/Makefile create mode 100644 product/synquacer/module/ppu_v0_synquacer/src/mod_ppu_v0.c create mode 100644 product/synquacer/module/ppu_v0_synquacer/src/ppu_v0.c create mode 100644 product/synquacer/module/scmi_vendor_ext/include/internal/scmi_vendor_ext.h create mode 100644 product/synquacer/module/scmi_vendor_ext/src/Makefile create mode 100644 product/synquacer/module/scmi_vendor_ext/src/mod_scmi_vendor_ext.c create mode 100644 product/synquacer/module/synquacer_memc/include/ddr_init.h create mode 100644 product/synquacer/module/synquacer_memc/include/internal/reg_DDRPHY_CONFIG.h create mode 100644 product/synquacer/module/synquacer_memc/include/internal/reg_DMA330.h create mode 100644 product/synquacer/module/synquacer_memc/include/internal/reg_DMC520.h create mode 100644 product/synquacer/module/synquacer_memc/include/mod_synquacer_memc.h create mode 100644 product/synquacer/module/synquacer_memc/include/synquacer_ddr.h create mode 100644 product/synquacer/module/synquacer_memc/src/Makefile create mode 100644 product/synquacer/module/synquacer_memc/src/ddr_init.c create mode 100644 product/synquacer/module/synquacer_memc/src/mod_synquacer_memc.c create mode 100644 product/synquacer/module/synquacer_memc/src/synquacer_ddr.c create mode 100644 product/synquacer/module/synquacer_pik_clock/include/mod_synquacer_pik_clock.h create mode 100644 product/synquacer/module/synquacer_pik_clock/src/Makefile create mode 100644 product/synquacer/module/synquacer_pik_clock/src/mod_synquacer_pik_clock.c create mode 100644 product/synquacer/module/synquacer_rom/include/mod_synquacer_rom.h create mode 100644 product/synquacer/module/synquacer_rom/src/Makefile create mode 100644 product/synquacer/module/synquacer_rom/src/mod_synquacer_rom.c create mode 100644 product/synquacer/module/synquacer_rom/src/synquacer_init.c create mode 100644 product/synquacer/module/synquacer_system/include/boot_ctl.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/crg11.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/gpio.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/nic400.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/pmu.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/reg_PPU.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/reset.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/smmu_wrapper.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/synquacer_pd.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/synquacer_ppu_driver.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/sysoc.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/thermal_sensor.h create mode 100644 product/synquacer/module/synquacer_system/include/internal/transaction_sw.h create mode 100644 product/synquacer/module/synquacer_system/include/mod_synquacer_system.h create mode 100644 product/synquacer/module/synquacer_system/include/sysdef_option.h create mode 100644 product/synquacer/module/synquacer_system/src/Makefile create mode 100644 product/synquacer/module/synquacer_system/src/boot_ctl.c create mode 100644 product/synquacer/module/synquacer_system/src/gpio.c create mode 100644 product/synquacer/module/synquacer_system/src/load_secure_fw.c create mode 100644 product/synquacer/module/synquacer_system/src/mmu500.c create mode 100644 product/synquacer/module/synquacer_system/src/mod_synquacer_system.c create mode 100644 product/synquacer/module/synquacer_system/src/nic400.c create mode 100644 product/synquacer/module/synquacer_system/src/pmu_driver.c create mode 100644 product/synquacer/module/synquacer_system/src/smmu_config.c create mode 100644 product/synquacer/module/synquacer_system/src/synquacer_main.c create mode 100644 product/synquacer/module/synquacer_system/src/synquacer_pd_manage.c create mode 100644 product/synquacer/module/synquacer_system/src/sysdef_option.c create mode 100644 product/synquacer/module/synquacer_system/src/sysoc.c create mode 100644 product/synquacer/module/synquacer_system/src/thermal_sensor.c create mode 100644 product/synquacer/module/synquacer_system/src/transaction_sw.c create mode 100644 product/synquacer/product.mk create mode 100644 product/synquacer/scp_ramfw/RTX_Config.h create mode 100644 product/synquacer/scp_ramfw/config_armv7m_mpu.c create mode 100644 product/synquacer/scp_ramfw/config_ccn512.c create mode 100644 product/synquacer/scp_ramfw/config_clock.c create mode 100644 product/synquacer/scp_ramfw/config_clock.h create mode 100644 product/synquacer/scp_ramfw/config_css_clock.c create mode 100644 product/synquacer/scp_ramfw/config_f_i2c.c create mode 100644 product/synquacer/scp_ramfw/config_hsspi.c create mode 100644 product/synquacer/scp_ramfw/config_log_f_uart3.c create mode 100644 product/synquacer/scp_ramfw/config_log_pl011.c create mode 100644 product/synquacer/scp_ramfw/config_mhu.c create mode 100644 product/synquacer/scp_ramfw/config_mhu.h create mode 100644 product/synquacer/scp_ramfw/config_pik_clock.c create mode 100644 product/synquacer/scp_ramfw/config_power_domain.c create mode 100644 product/synquacer/scp_ramfw/config_power_domain.h create mode 100644 product/synquacer/scp_ramfw/config_ppu_v0.h create mode 100644 product/synquacer/scp_ramfw/config_ppu_v0_synquacer.c create mode 100644 product/synquacer/scp_ramfw/config_scmi.c create mode 100644 product/synquacer/scp_ramfw/config_scmi.h create mode 100644 product/synquacer/scp_ramfw/config_scmi_apcore.c create mode 100644 product/synquacer/scp_ramfw/config_scmi_system_power.c create mode 100644 product/synquacer/scp_ramfw/config_smt.c create mode 100644 product/synquacer/scp_ramfw/config_synquacer_memc.c create mode 100644 product/synquacer/scp_ramfw/config_system_power.c create mode 100644 product/synquacer/scp_ramfw/config_timer.c create mode 100644 product/synquacer/scp_ramfw/firmware.mk create mode 100644 product/synquacer/scp_ramfw/fmw_memory.ld.S create mode 100644 product/synquacer/scp_ramfw/rtx_config.c create mode 100644 product/synquacer/scp_romfw/config_armv7m_mpu.c create mode 100644 product/synquacer/scp_romfw/config_clock.c create mode 100644 product/synquacer/scp_romfw/config_clock.h create mode 100644 product/synquacer/scp_romfw/config_log_f_uart3.c create mode 100644 product/synquacer/scp_romfw/config_synquacer_pik_clock.c create mode 100644 product/synquacer/scp_romfw/config_synquacer_rom.c create mode 100644 product/synquacer/scp_romfw/config_timer.c create mode 100644 product/synquacer/scp_romfw/firmware.mk create mode 100644 product/synquacer/scp_romfw/fmw_memory.ld.S create mode 100644 product/synquacer/src/synquacer_core.c diff --git a/product/synquacer/include/fmw_cmsis.h b/product/synquacer/include/fmw_cmsis.h new file mode 100644 index 000000000..12414c428 --- /dev/null +++ b/product/synquacer/include/fmw_cmsis.h @@ -0,0 +1,30 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FMW_CMSIS_H +#define FMW_CMSIS_H + +#define __CHECK_DEVICE_DEFINES +#define __CM3_REV 0x0201 +#define __MPU_PRESENT 1 +#define __NVIC_PRIO_BITS 3 +#define __Vendor_SysTickConfig 0 + +typedef enum IRQn { + NonMaskableInt_IRQn = -14, + MemoryManagement_IRQn = -12, + BusFault_IRQn = -11, + UsageFault_IRQn = -10, + SVCall_IRQn = -5, + DebugMonitor_IRQn = -4, + PendSV_IRQn = -2, + SysTick_IRQn = -1, +} IRQn_Type; + +#include + +#endif /* FMW_CMSIS_H */ diff --git a/product/synquacer/include/low_level_access.h b/product/synquacer/include/low_level_access.h new file mode 100644 index 000000000..66fb98c37 --- /dev/null +++ b/product/synquacer/include/low_level_access.h @@ -0,0 +1,53 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef LOW_LEVEL_ACCESS_H +#define LOW_LEVEL_ACCESS_H + +#include + +static inline void writeb(uint32_t ads, uint8_t data) +{ + *((volatile uint8_t *)ads) = data; +} + +static inline void writew(uint32_t ads, uint16_t data) +{ + *((volatile uint16_t *)ads) = data; +} + +static inline void writel(uint32_t ads, uint32_t data) +{ + *((volatile uint32_t *)ads) = data; +} + +static inline void writeq(uint32_t ads, uint64_t data) +{ + *((volatile uint64_t *)ads) = data; +} + +static inline uint8_t readb(uint32_t ads) +{ + return *((volatile uint8_t *)ads); +} + +static inline uint16_t readw(uint32_t ads) +{ + return *((volatile uint16_t *)ads); +} + +static inline uint32_t readl(uint32_t ads) +{ + return *((volatile uint32_t *)ads); +} + +static inline uint64_t readq(uint32_t ads) +{ + return *((volatile uint64_t *)ads); +} + +#endif /* LOW_LEVEL_ACCESS_H */ diff --git a/product/synquacer/include/mmu500.h b/product/synquacer/include/mmu500.h new file mode 100644 index 000000000..9704cce07 --- /dev/null +++ b/product/synquacer/include/mmu500.h @@ -0,0 +1,265 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MMU500_H +#define MMU500_H + +#include +#include + +#define SMMU_NUMSMRG 16 +#define SMMU_NUMCB 8 + +typedef struct { + FWK_RW uint32_t CR0; + FWK_RW uint32_t SCR1; + uint32_t reserved0[(0x010 - 0x008) / 4]; + FWK_RW uint32_t ACR; + uint32_t reserved1[(0x020 - 0x014) / 4]; + FWK_R uint32_t IDR0; + FWK_R uint32_t IDR1; + FWK_R uint32_t IDR2; + uint32_t reserved2[(0x03C - 0x02C) / 4]; + FWK_R uint32_t IDR7; + FWK_RW uint32_t GFAR_L; + FWK_RW uint32_t GFAR_U; + FWK_RW uint32_t GFSR; + FWK_W uint32_t GFSRRESTORE; + FWK_RW uint32_t GFSYNR0; + FWK_RW uint32_t GFSYNR1; + uint32_t reserved3[(0x060 - 0x058) / 4]; + FWK_W uint32_t STLBIALL; + FWK_W uint32_t TLBIVMID; + FWK_W uint32_t TLBIALLNSNH; + uint32_t reserved5; + FWK_W uint32_t TLBGSYNC; + FWK_R uint32_t TLBGSTATUS; + uint32_t reserved6[(0x080 - 0x078) / 4]; + FWK_RW uint32_t DBGRPTR; + FWK_R uint32_t DBGRDATA; + uint32_t reserved7[(0x800 - 0x088) / 4]; + FWK_RW uint32_t SMR[SMMU_NUMSMRG]; + uint32_t reserved8[(0xC00 - (0x800 + SMMU_NUMSMRG * 4)) / 4]; + FWK_RW uint32_t S2CR[SMMU_NUMSMRG]; + uint32_t reserved9[(0x1000 - (0xC00 + SMMU_NUMSMRG * 4)) / 4]; +} GSPACE0_Type_t; + +typedef struct { + FWK_RW uint32_t CBAR[SMMU_NUMCB]; + uint32_t reserved0[(0x400 - (0x000 + SMMU_NUMCB * 4)) / 4]; + FWK_RW uint32_t CBFRSYNRA[SMMU_NUMCB]; + uint32_t reserved1[(0x800 - (0x400 + SMMU_NUMCB * 4)) / 4]; + FWK_RW uint32_t CBA2R[SMMU_NUMCB]; + uint32_t reserved2[(0x1000 - (0x800 + SMMU_NUMCB * 4)) / 4]; +} GSPACE1_Type_t; + +typedef struct { + FWK_RW uint32_t CB_SCTLR; + FWK_RW uint32_t CB_ACTLR; + FWK_W uint32_t CB_RESUME; + uint32_t reserved0; + FWK_RW uint32_t CB_TCR2; + uint32_t reserved1[(0x20 - 0x14) / 4]; + FWK_RW uint64_t CB_TTBR0; + FWK_RW uint64_t CB_TTBR1; + FWK_RW uint32_t CB_TCR; + FWK_RW uint32_t CB_CONTEXTIDR; + FWK_RW uint32_t CB_MAIR0; + FWK_RW uint32_t CB_MAIR1; + uint32_t reserved2[(0x50 - 0x40) / 4]; + FWK_RW uint64_t CB_PAR; + FWK_RW uint32_t CB_FSR; + FWK_W uint32_t CB_FSRRESTORE; + FWK_RW uint64_t CB_FAR; + FWK_RW uint32_t CB_FSYNC0; + FWK_RW uint32_t CB_FSYNC1; + uint32_t reserved3[(0x1000 - 0x70) / 4]; +} TCB_Type_t; + +typedef struct { + GSPACE0_Type_t GR0; + GSPACE1_Type_t GR1; + uint32_t reserved2[(0x3000 - 0x2000) / 4]; + uint32_t reserved3[(0x4000 - 0x3000) / 4]; + FWK_RW uint32_t SSDR[256]; + uint32_t reserved4[(0x8000 - 0x4400) / 4]; + TCB_Type_t TCB[SMMU_NUMCB]; +} MMU500_Type_t; + +typedef struct { + unsigned stream_match_mask : 15; + unsigned stream_match_id : 15; + uint64_t base_addr; +} MMU500_ContextInfo_t; + +//#define SMMU_BASE 0x50240000 //mmu_a2p +//#define SMMU_BASE 0x50250000 //mmu_p2a +//#define SMMU_BASE 0xd1e00000 //mmu_scb +//#define SMMU ((MMU500_Type_t *) SMMU_BASE) + +/* --------------------------------- */ +/* ---- Global Space Register 0 ---- */ + +#define SMMU_ACR_PAGESIZE_64K ((uint32_t)0x1 << 16) +#define SMMU_ACR_S2CRB_TLBEN ((uint32_t)0x1 << 10) +#define SMMU_ACR_MMUDISB_TLBEN ((uint32_t)0x1 << 9) +#define SMMU_ACR_SMTNMB_TLBEN ((uint32_t)0x1 << 8) + +#define SMMU_IDR0_NUMSMRG ((uint32_t)0xff << 0) + +#define SMMU_IDR1_NUMCB ((uint32_t)0xff << 0) +#define SMMU_IDR1_PAGESIZE ((uint32_t)1U << 31) + +#define SMMU_CR0_SMCFCFG ((uint32_t)1 << 21) +#define SMMU_CR0_USFCFG ((uint32_t)1 << 10) +#define SMMU_CR0_GSE ((uint32_t)1 << 9) +#define SMMU_CR0_STALLD ((uint32_t)1 << 8) +#define SMMU_CR0_GCFGFIE ((uint32_t)1 << 5) +#define SMMU_CR0_GCFGFRE ((uint32_t)1 << 4) +// +#define SMMU_CR0_GFIE ((uint32_t)1 << 2) +#define SMMU_CR0_GFRE ((uint32_t)1 << 1) +#define SMMU_CR0_CLIENTPD ((uint32_t)1 << 0) + +#define SMMU_SCR1_NSNUMCBO ((uint32_t)0xff << 0) +#define SMMU_SCR1_NSNUMSMRGO ((uint32_t)0xff << 8) +#define SMMU_SCR1_NSNUMCBO_OFFSET ((uint32_t)0) +#define SMMU_SCR1_NSNUMSMRGO_OFFSET ((uint32_t)8) +#define SMMU_SCR1_SPMEN ((uint32_t)1 << 27) + +#define SMMU_TLBGSTATUS_GACTIVE ((uint32_t)1) + +#define SMMU_SMRn_VALID ((uint32_t)1 << 31) +#define SMMU_SMRn_ID_OFFSET 0 + +#define SMMU_S2CRn_TYPE_CONTEXT ((uint32_t)0 << 16) +#define SMMU_S2CRn_TYPE_BYPASS ((uint32_t)1 << 16) +#define SMMU_S2CRn_TYPE_FAULT ((uint32_t)2 << 16) + +#define SMMU_S2CRn_SH_DEF ((uint32_t)0 << 8) +#define SMMU_S2CRn_SH_OUTER ((uint32_t)1 << 8) +#define SMMU_S2CRn_SH_INNER ((uint32_t)2 << 8) +#define SMMU_S2CRn_SH_NON ((uint32_t)3 << 8) + +#define SMMU_S2CRn_CBNDX_OFFSET 0 + +/* ---- Global Space Register 1 ---- */ +/* --------------------------------- */ +#define SMMU_CBAR_TYPE_STAGE2 ((uint32_t)0 << 16) +#define SMMU_CBAR_TYPE_STAGE1 ((uint32_t)1 << 16) +#define SMMU_CBAR_TYPE_STAGE1_2 ((uint32_t)3 << 16) +#define SMMU_CBAR_MEM_NORMAL ((uint32_t)0xf << 12) + +#define SMMU_CBAR_HYPC ((uint32_t)1 << 10) + +/* ------------------------------ */ +#define SMMU_CBA2R_MONC ((uint32_t)1 << 1) +#define SMMU_CBA2R_VA64 ((uint32_t)1 << 0) + +/* ---- Translation Context Bank --- */ +/* ---- SCTLR ---------------------- */ +#define SMMU_SCTLR_SH_OUTER ((uint32_t)0x1 << 22) +#define SMMU_SCTLR_MEM_NORMAL ((uint32_t)0xf << 16) +#define SMMU_SCTLR_UWXN ((uint32_t)1 << 10) +#define SMMU_SCTLR_WXN ((uint32_t)1 << 9) +#define SMMU_SCTLR_HUPCF ((uint32_t)1 << 8) // Hit Under Previous Context Faut +#define SMMU_SCTLR_CFCFG ((uint32_t)1 << 7) // Context fault Configuration +#define SMMU_SCTLR_CFIE ((uint32_t)1 << 6) // Context Fault Interrupt Enable +#define SMMU_SCTLR_CFRE ((uint32_t)1 << 5) // Context Fault Report Enable +#define SMMU_SCTLR_E ((uint32_t)1 << 4) +#define SMMU_SCTLR_A ((uint32_t)1 << 3) +#define SMMU_SCTLR_AFE ((uint32_t)1 << 2) +#define SMMU_SCTLR_TRE ((uint32_t)1 << 1) +#define SMMU_SCTLR_M ((uint32_t)1 << 0) + +/* ------- TCR ----------------- */ +#define SMMU_TCR_EPD1 ((uint32_t)1 << 23) +#define SMMU_TCR_A1 ((uint32_t)1 << 22) + +#define SMMU_TCR_TG0_4KB ((uint32_t)0 << 14) +#define SMMU_TCR_TG0_16KB ((uint32_t)2 << 14) +#define SMMU_TCR_TG0_64KB ((uint32_t)1 << 14) + +#define SMMU_TCR_SH0_NON ((uint32_t)0 << 12) +#define SMMU_TCR_SH0_RESERVED ((uint32_t)1 << 12) +#define SMMU_TCR_SH0_OUTER ((uint32_t)2 << 12) +#define SMMU_TCR_SH0_INNERN ((uint32_t)3 << 12) + +#define SMMU_TCR_ORGN0_WBWA ((uint32_t)1 << 10) +#define SMMU_TCR_IRGN0_WBWA ((uint32_t)1 << 8) + +#define SMMU_TCR_EPD0 ((uint32_t)1 << 7) + +#define SMMU_TCR_T0SZ_4GB ((uint32_t)32 << 0) +#define SMMU_TCR_T0SZ_8GB ((uint32_t)31 << 0) +#define SMMU_TCR_T0SZ_16GB ((uint32_t)30 << 0) +#define SMMU_TCR_T0SZ_32GB ((uint32_t)29 << 0) +#define SMMU_TCR_T0SZ_64GB ((uint32_t)28 << 0) +#define SMMU_TCR_T0SZ_128GB ((uint32_t)27 << 0) +#define SMMU_TCR_T0SZ_256GB ((uint32_t)26 << 0) +#define SMMU_TCR_T0SZ_512GB ((uint32_t)25 << 0) +#define SMMU_TCR_T0SZ_1TB ((uint32_t)24 << 0) +#define SMMU_TCR_T0SZ_256TB ((uint32_t)16 << 0) + +/* for stage2 */ +#define SMMU_TCR_PASIZE_4GB ((uint32_t)0 << 16) +#define SMMU_TCR_PASIZE_64GB ((uint32_t)1 << 16) +#define SMMU_TCR_PASIZE_1TB ((uint32_t)2 << 16) + +#define SMMU_TCR_SL0_LV3 ((uint32_t)0 << 6) +#define SMMU_TCR_SL0_LV2 ((uint32_t)1 << 6) +#define SMMU_TCR_SL0_LV1 ((uint32_t)2 << 6) + +/* ------- TCR2 ----------------- */ +#define SMMU_TCR2_SEP_41 ((uint32_t)3 << 15) +#define SMMU_TCR2_SEP_47 ((uint32_t)5 << 15) +#define SMMU_TCR2_PASIZE_32 ((uint32_t)0 << 0) +#define SMMU_TCR2_PASIZE_36 ((uint32_t)1 << 0) +#define SMMU_TCR2_PASIZE_40 ((uint32_t)2 << 0) +#define SMMU_TCR2_PASIZE_48 ((uint32_t)5 << 0) + +/* ------------------------------ */ + +#define SMMU_TTBRn_ADDR_MASK_1TB_64KB ((uint64_t)0x0000ffffe0000000) +#define SMMU_TTBRn_ASID_OFFSET 48 + +#define SMMU_TBUID_GPU ((uint32_t)0 << 10) +#define SMMU_TBUID_ETR ((uint32_t)1 << 10) +#define SMMU_TBUID_SCP ((uint32_t)2 << 10) + +#ifdef __cplusplus +extern "C" { +#endif +/** + * MMU500 page table manipulators + */ +enum mmu500_granule { + MMU500_GRANULE_4KB = 0, + MMU500_GRANULE_16KB = 1, + MMU500_GRANULE_64KB = 2 +}; + +int32_t SMMU_s_init( + MMU500_Type_t *SMMU, + uint32_t num_context, + const MMU500_ContextInfo_t *context_info, + enum mmu500_granule granule); +int32_t SMMU_ns_init(MMU500_Type_t *SMMU, uint64_t addr); +void SMMU_ns_cb0_stage2_init(MMU500_Type_t *SMMU, uint64_t addr); +void SMMU_ns_cb0_stage1_init(MMU500_Type_t *SMMU, uint64_t addr); +void SMMU_ns_cb_stage1_init( + MMU500_Type_t *SMMU, + uint32_t cb, + uint64_t addr, + enum mmu500_granule granule); +void SMMU_s_disable(MMU500_Type_t *SMMU, uint32_t num_context); + +#ifdef __cplusplus +} +#endif + +#endif /* MMU500_H */ diff --git a/product/synquacer/include/pik_cpu.h b/product/synquacer/include/pik_cpu.h new file mode 100644 index 000000000..526366f96 --- /dev/null +++ b/product/synquacer/include/pik_cpu.h @@ -0,0 +1,70 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PIK_CPU_H +#define PIK_CPU_H + +#include +#include + +/*! + * \brief CPU PIK register definitions + */ +typedef struct { + FWK_RW uint32_t STATIC_CONFIG; + FWK_R uint32_t RESERVED0[3]; + FWK_RW uint32_t RVBARADDR0_LW; + FWK_RW uint32_t RVBARADDR0_UP; + FWK_RW uint32_t RVBARADDR1_LW; + FWK_RW uint32_t RVBARADDR1_UP; + FWK_RW uint32_t RVBARADDR2_LW; + FWK_RW uint32_t RVBARADDR2_UP; + FWK_RW uint32_t RVBARADDR3_LW; + FWK_RW uint32_t RVBARADDR3_UP; + FWK_RW uint32_t CLUSTER_CONFIG; + FWK_R uint8_t RESERVED1[0x200 - 0x34]; + FWK_R uint32_t DBG_RST_STATUS; + FWK_RW uint32_t DBG_RST_SET; + FWK_RW uint32_t DBG_RST_CLR; + FWK_R uint8_t RESERVED2[0x400 - 0x20c]; + FWK_RW uint32_t CPUACTIVE_CTRL; + FWK_R uint8_t RESERVED3[0x800 - 0x404]; + FWK_RW uint32_t PPUCLK_CTRL; + FWK_RW uint32_t PPUCLK_DIV1; + FWK_RW uint32_t PPUCLK_DIV2; + FWK_R uint32_t RESERVED4; + FWK_RW uint32_t CPUCLK_CTRL; + FWK_RW uint32_t CPUCLK_DIV1; + FWK_RW uint32_t CPUCLK_DIV2; + FWK_R uint32_t RESERVED5; + FWK_RW uint32_t PCLKDBG_CTRL; + FWK_R uint32_t RESERVED6[3]; + FWK_RW uint32_t ATCLKDBG_CTRL; + FWK_R uint32_t RESERVED7[3]; + FWK_RW uint32_t ACLKCPU_CTRL; + FWK_R uint8_t RESERVED8[0xA00 - 0x844]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_RW uint32_t CLKFORCE_SET; + FWK_RW uint32_t CLKFORCE_CLR; + FWK_R uint8_t RESERVED9[0xFC0 - 0xA0C]; + FWK_R uint32_t CONFIG; + FWK_R uint32_t RESERVED10[3]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +} pik_cpu_reg_t; + +#endif /* PIK_CPU_H */ diff --git a/product/synquacer/include/pik_scp.h b/product/synquacer/include/pik_scp.h new file mode 100644 index 000000000..6b2108fe9 --- /dev/null +++ b/product/synquacer/include/pik_scp.h @@ -0,0 +1,75 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PIK_SCP_H +#define PIK_SCP_H + +#include +#include + +/*! + * \brief SCP PIK register definitions + */ +typedef struct { + FWK_R uint32_t RESERVED0[4]; + FWK_RW uint32_t RESET_SYNDROME; + FWK_R uint32_t RESERVED1[3]; + FWK_RW uint32_t SURVIVAL; + FWK_R uint32_t RESERVED2[4]; + FWK_RW uint32_t ADDR_TRANS; + FWK_R uint32_t RESERVED3[2]; + FWK_RW uint32_t WS1_TIMER_MATCH; + FWK_RW uint32_t WS1_TIMER_EN; + FWK_R uint32_t RESERVED4[110]; + FWK_R uint32_t SS_RESET_STATUS; + FWK_W uint32_t SS_RESET_SET; + FWK_W uint32_t SS_RESET_CLR; + FWK_R uint32_t RESERVED5[385]; + FWK_RW uint32_t CORECLK_CNTRL; + FWK_RW uint32_t CORECLK_DIV1; + FWK_R uint32_t RESERVED6[2]; + FWK_RW uint32_t ACLK_CNTRL; + FWK_RW uint32_t ACLK_DIV1; + FWK_R uint32_t RESERVED7[118]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_R uint32_t CLKFORCE_SET; + FWK_R uint32_t CLKFORCE_CLEAR; + FWK_R uint32_t RESERVED8[1]; + FWK_R uint32_t PLL_STATUS[17]; + FWK_R uint32_t RESERVED9[43]; + FWK_R uint32_t MHU_NS_INT_STATUS; + FWK_R uint32_t MHU_S_INT_STATUS; + FWK_R uint32_t RESERVED10[6]; + FWK_R uint32_t CPU_PPU_INT_STATUS[8]; + FWK_R uint32_t CLUS_INT_STATUS; + FWK_R uint32_t RESERVED11[7]; + FWK_R uint32_t TIMER_INT_STATUS[8]; + FWK_R uint32_t CPU_PLLA_LOCK_STATUS[8]; + FWK_R uint32_t CPU_PLLB_LOCK_STATUS[8]; + FWK_R uint32_t CPU_PLLA_UNLOCK_STATUS[8]; + FWK_R uint32_t CPU_PLLB_UNLOCK_STATUS[8]; + FWK_R uint32_t RESERVED12[240]; + FWK_R uint32_t PWR_CTRL_CFG; + FWK_R uint32_t RESERVED13[3]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +} pik_scp_reg_t; + +#define PLL_STATUS_0_REFCLK UINT32_C(0x00000001) +#define PLL_STATUS_0_SYSPLLLOCK UINT32_C(0x00000002) + +#endif /* PIK_SCP_H */ diff --git a/product/synquacer/include/pik_system.h b/product/synquacer/include/pik_system.h new file mode 100644 index 000000000..93186c999 --- /dev/null +++ b/product/synquacer/include/pik_system.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PIK_SYSTEM_H +#define PIK_SYSTEM_H + +#include +#include + +typedef struct { + FWK_R uint32_t RESERVED0[512]; + FWK_RW uint32_t PPUCLK_CTRL; + FWK_RW uint32_t PPUCLK_DIV1; + FWK_R uint32_t RESERVED1[6]; + FWK_RW uint32_t CCNCLK_CTRL; + FWK_RW uint32_t CCNCLK_DIV1; + FWK_R uint32_t RESERVED2[10]; + FWK_RW uint32_t GICCLK_CTRL; + FWK_RW uint32_t GICCLK_DIV1; + FWK_R uint32_t RESERVED3[2]; + FWK_RW uint32_t PCLKSCP_CTRL; + FWK_RW uint32_t PCLKSCP_DIV1; + FWK_R uint32_t RESERVED4[2]; + FWK_RW uint32_t SYSPERCLK_CTRL; + FWK_RW uint32_t SYSPERCLK_DIV1; + FWK_R uint32_t RESERVED5[2]; + FWK_RW uint32_t DMCCLK_CTRL; + FWK_RW uint32_t DMCCLK_DIV1; + FWK_R uint32_t RESERVED6[2]; + FWK_RW uint32_t SYSPCLKDBG_CTRL; + FWK_RW uint32_t SYSPCLKDBG_DIV1; + FWK_R uint32_t RESERVED7[2]; + FWK_RW uint32_t UARTCLK_CTRL; + FWK_RW uint32_t UARTCLK_DIV1; + FWK_R uint32_t RESERVED8[86]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_RW uint32_t CLKFORCE_SET; + FWK_RW uint32_t CLKFORCE_CLR; + FWK_R uint32_t RESERVED9[63]; + FWK_RW uint32_t DMC_CONTROL; + FWK_RW uint32_t SYSTOP_RST_DLY; + FWK_R uint32_t RESERVED10[300]; + FWK_R uint32_t PIK_CONFIG; + FWK_R uint32_t RESERVED11[3]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +} pik_system_reg_t; + +#endif /* PIK_SYSTEM_H */ diff --git a/product/synquacer/include/scp_system_mmap_scp.h b/product/synquacer/include/scp_system_mmap_scp.h new file mode 100644 index 000000000..95e5415ff --- /dev/null +++ b/product/synquacer/include/scp_system_mmap_scp.h @@ -0,0 +1,24 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCP_SYSTEM_MMAP_SCP_H +#define SCP_SYSTEM_MMAP_SCP_H + +#define SCP_ROM_SIZE (512 * 1024) +#define SCP_RAM0_SIZE (128 * 1024) +#define SCP_RAM1_SIZE (64 * 1024) +#define SCP_RAM2_SIZE (128 * 1024) + +#define SCP_ROM_BASE (0x08100000) +#define SCP_RAM0_BASE (0x00800000) +#define SCP_RAM1_BASE (0x00900000) +#define SCP_RAM2_BASE (0x1C020000) + +#define SCP_RAMFW_ROM_BASE (0x08110000) +#define SCP_RAMFW_IMAGE_SIZE (128 * 1024) + +#endif /* SCP_SYSTEM_MMAP_SCP_H */ diff --git a/product/synquacer/include/synquacer_common.h b/product/synquacer/include/synquacer_common.h new file mode 100644 index 000000000..fc98deef8 --- /dev/null +++ b/product/synquacer/include/synquacer_common.h @@ -0,0 +1,30 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_COMMON_H +#define SYNQUACER_COMMON_H + +#ifdef HAS_RTOS +#include +#endif +#include +#include + +#define DI(intsts) \ + do { \ + intsts = __get_FAULTMASK(); \ + __disable_fault_irq(); \ + } while (0) + +#define EI(intsts) \ + do { \ + if ((intsts & 0x1) == 0) { \ + __enable_fault_irq(); \ + } \ + } while (0) + +#endif /* SYNQUACER_COMMON_H */ diff --git a/product/synquacer/include/synquacer_config.h b/product/synquacer/include/synquacer_config.h new file mode 100644 index 000000000..75356a90e --- /dev/null +++ b/product/synquacer/include/synquacer_config.h @@ -0,0 +1,101 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_CONFIG_H +#define SYNQUACER_CONFIG_H + +#include +#include +#include + +#define THRESHOLD_TYPE_UNR (0) +#define THRESHOLD_TYPE_UCR (1) +#define THRESHOLD_TYPE_UNC (2) +#define THRESHOLD_TYPE_NUM_MAX (3) + +#define SENSOR_NUM_MAX (256) + +#define PARTITION_NUM_MAX (8 * 8) + +#define check_valid_bit(bitmap, pos) (((bitmap) & (1 << (pos))) != 0) +#define dram_ecc_is_enabled() (eeprom_config.pec_ecc_status != 0) + +struct unused_eeprom_config_head_part_t { + uint8_t mac_addr[8]; + uint32_t hm_me_addr_high; + uint32_t hm_me_addr_low; + uint32_t hm_me_size; + uint32_t mh_me_addr_high; + uint32_t mh_me_addr_low; + uint32_t mh_me_size; + uint32_t packet_me_addr_low; + uint32_t packet_me_size; + uint32_t magic_word; + uint8_t reserved_212[212]; + uint32_t reserved_1; + uint32_t reserved_2; +}; + +#define EEPROM_CONFIG_T_START_OFFSET \ + sizeof(struct unused_eeprom_config_head_part_t) + +struct nat_config { + uint8_t valid; + uint8_t reserved[3]; + uint8_t ext_ipaddr[4]; +}; + +typedef struct { + uint32_t system_composition; + + uint8_t reverved_1; + uint8_t reserved_valid_sbb_after[3]; + uint8_t reserved_8[8]; + uint8_t reverved_1_1; + uint8_t reverved_1_2; + + uint8_t reserved_2[2]; + + uint8_t reverved_1_3; + uint8_t reverved_1_4; + uint8_t reverved_1_5; + + uint8_t reserved_1[1]; + + uint64_t reserved_8_2; + uint64_t reserved_8_3; + uint8_t pcie_cache_snoop_valid[2]; + uint8_t reverved_1_6; + + uint8_t reserved_205[205]; + + uint8_t reverved_1_7[8][8]; + + uint8_t reserved_192[192]; + + uint8_t reverved_1_8[8][8][8]; + + uint8_t reverved_1_9; + uint8_t reverved_1_10[7]; + uint8_t reverved_1_11[8]; + uint8_t reverved_1_12[8][8]; + + uint8_t reserved_176[176]; + + uint8_t reverved_1_13[PARTITION_NUM_MAX][8]; + + uint8_t sbb_ecc_status; + uint8_t pec_ecc_status; + + uint8_t reserved_before_sensor_threshold[0x1300 - 0x802]; + + uint8_t sensor_thresh[THRESHOLD_TYPE_NUM_MAX][SENSOR_NUM_MAX]; +} eeprom_config_t; + +extern eeprom_config_t eeprom_config; + +#endif /* SYNQUACER_CONFIG_H */ diff --git a/product/synquacer/include/synquacer_core.h b/product/synquacer/include/synquacer_core.h new file mode 100644 index 000000000..51938e4e3 --- /dev/null +++ b/product/synquacer/include/synquacer_core.h @@ -0,0 +1,27 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_CORE_H +#define SYNQUACER_CORE_H + +#include + +/* Maximum number of clusters */ +#define SYNQUACER_CSS_CPUS_CLUSTER_MAX UINT32_C(12) + +/* Maximum number of CPUs per cluster */ +#define SYNQUACER_CSS_CPUS_PER_CLUSTER_MAX UINT32_C(2) + +/* Maximum number of CPUs */ +#define SYNQUACER_CSS_CPUS_MAX \ + (SYNQUACER_CSS_CPUS_CLUSTER_MAX * SYNQUACER_CSS_CPUS_PER_CLUSTER_MAX) + +uint32_t synquacer_core_get_core_count(void); +uint32_t synquacer_core_get_cluster_count(void); +uint32_t synquacer_core_get_core_per_cluster_count(void); + +#endif /* SYNQUACER_CORE_H */ diff --git a/product/synquacer/include/synquacer_debug.h b/product/synquacer/include/synquacer_debug.h new file mode 100644 index 000000000..86f2bd1d7 --- /dev/null +++ b/product/synquacer/include/synquacer_debug.h @@ -0,0 +1,53 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_DEBUG_H +#define SYNQUACER_DEBUG_H + +#include +#include +#include +#include +#include + +#ifdef SYNQUACER_LOG_GROUP_ERROR +#define SYNQUACER_DEV_LOG_ERROR(...) \ + synquacer_system_ctx.log_api->log(MOD_LOG_GROUP_ERROR, __VA_ARGS__) +#else +#define SYNQUACER_DEV_LOG_ERROR(...) \ + do { \ + } while (0) +#endif + +#ifdef SYNQUACER_LOG_GROUP_WARNING +#define SYNQUACER_DEV_LOG_WARNING(...) \ + synquacer_system_ctx.log_api->log(MOD_LOG_GROUP_WARNING, __VA_ARGS__) +#else +#define SYNQUACER_DEV_LOG_WARNING(...) \ + do { \ + } while (0) +#endif + +#ifdef SYNQUACER_LOG_GROUP_INFO +#define SYNQUACER_DEV_LOG_INFO(...) \ + synquacer_system_ctx.log_api->log(MOD_LOG_GROUP_INFO, __VA_ARGS__) +#else +#define SYNQUACER_DEV_LOG_INFO(...) \ + do { \ + } while (0) +#endif + +#ifdef SYNQUACER_LOG_GROUP_DEBUG +#define SYNQUACER_DEV_LOG_DEBUG(...) \ + synquacer_system_ctx.log_api->log(MOD_LOG_GROUP_DEBUG, __VA_ARGS__) +#else +#define SYNQUACER_DEV_LOG_DEBUG(...) \ + do { \ + } while (0) +#endif + +#endif /* SYNQUACER_DEBUG_H */ diff --git a/product/synquacer/include/synquacer_irq.h b/product/synquacer/include/synquacer_irq.h new file mode 100644 index 000000000..fce5b9c91 --- /dev/null +++ b/product/synquacer/include/synquacer_irq.h @@ -0,0 +1,91 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_IRQ_H +#define SYNQUACER_IRQ_H + +enum scp_interrupt { + WDOG_IRQn = -14, /*!< SCP Watchdog (SP805) - NMI */ + + CDBG_PWR_UP_REQ_IRQn = 1, /*!< Coresight Debug Power Request */ + CSYS_PWR_UP_REQ_IRQn = 2, /*!< Coresight System Power Request */ + CDBG_RST_REQ_IRQn = 3, /*!< Coresight Debug Reset Request */ + GIC_EXT_WAKEUP = 4, /*!< External GIC Wakeup Request */ + + TIMREFCLK_IRQn = 33, /*!< REFCLK Physical Timer */ + + CTI_TRIGGER0_IRQn = 37, /*!< SCP CTI Trigger */ + CTI_TRIGGER1_IRQn = 38, /*!< SCP CTI Trigger */ + GIC_ERROR_ECC_IRQn = 39, /*!< GIC Error (ECC Fatal) */ + GIC_ERROR_AXIM_IRQn = 40, /*!< GIC Error (AXIM) */ + + AON_UART_IRQn = 42, /*!< Always on UART */ + + GEN_WD_WS0_IRQn = 44, /*!< Generic Watchdog timer WS0 */ + GEN_WD_WS1_IRQn = 45, /*!< Generic Watchdog timer WS1 */ + TRUSTED_WD_WS0_IRQn = 46, /*!< Trusted Watchdog timer WS0 */ + TRUSTED_WD_WS1_IRQn = 47, /*!< Trusted Watchdog timer WS1 */ + APPS_UART_IRQn = 48, /*!< Application UART */ + CCN_IRQn = 49, /*!< CCN */ + PPU_A72_1_32_IRQn = 50, /*!< A72 CPU1 - 32 Power Policy Unit */ + PPU_A72_33_64_IRQn = 51, /*!< A72 CPU33 - 64 Power Policy Unit */ + PPU_A72_65_96_IRQn = 52, /*!< A72 CPU65 - 96 Power Policy Unit */ + PPU_A72_97_128_IRQn = 53, /*!< A72 CPU97 - 128 Power Policy Unit */ + PPU_A72_SSTOP_CLUSTER_1_32_IRQn = 54, /*!< A72 SSTOP Power Policy Unit */ + PLL_CLUSTER_1_16_LOCK_IRQn = 55, /*!< CPU 1 ~ 16 PLL Lock */ + PLL_CLUSTER_17_32_LOCK_IRQn = 56, /*!< CPU 17~32 PLL Lock */ + PLL_CLUSTER_1_16_UNLOCK_IRQn = 57, /*!< CPU 1 ~ 16 PLL Unlock */ + PLL_CLUSTER_17_32_UNLOCK_IRQn = 58, /*!< CPU 17 ~ 32 PLL Unlock */ + + MHU_NON_SEC_SCP_AP_IRQn = 82, /*!< MHU non-secure irq bewteen SCP and AP */ + MHU_SEC_SCP_AP_IRQn = 83, /*!< MHU secure irq bewteen SCP and AP */ + MHU_NON_SEC_SCP_MCP_IRQn = + 84, /*!< MHU non-secure irq between SCP and MCP */ + MHU_SEC_SCP_MCP_IRQn = 85, /*!< MHU secure irq bewteen SCP and MCP */ + + P1_32_REFCLK_GEN_TIM_IRQn = 90, /*!< P0 Reference Clock Timer */ + P33_64_REFCLK_GEN_TIM_IRQn = 91, /*!< P1 Reference Clock Timer */ + P65_96_REFCLK_GEN_TIM_IRQn = 92, /*!< P2 Reference Clock Timer */ + P97_128_REFCLK_GEN_TIM_IRQn = 93, /*!< P3 Reference Clock Timer */ + + DEBUG_PIK_IRQn = 130, /*!< DEBUG PIK */ + PPU_LOGIC_IRQn = 131, /*!< PPU LOGIC */ + PPU_L3RAM0_IRQn = 132, /*!< PPU L3 RAM 0 */ + PPU_L3RAM1_IRQn = 133, /*!< PPU L3 RAM 1 */ + PPU_SFRAM_IRQn = 134, /*!< PPU SF RAM */ + PPU_SRAM_IRQn = 135, /*!< PPU S RAM */ + + MCP_WS1_IRQn = 139, /*!< MCP watchdog reset */ + PLL_SYS_LOCK_IRQn = 140, /*!< System PLL Lock */ + PLL_SYS_UNLOCK_IRQn = 141, /*!< System PLL Unlock */ + + PLL_DMC_LOCK_IRQn = 174, /*!< DMC PLL LOCK */ + PLL_DMC_UNLOCK_IRQn = 175, /*!< DMC PLL LOCK */ + + DMC1_COMBINED_OFLOW_IRQn = 187, /*!< DMC 1 Combined Overflow */ + DMC1_COMBINED_ERR_OVLOW_IRQn = 188, /*!< DMC 1 Combined err Ovlow */ + DMC1_COMBINED_ECC_ERR_IRQn = 189, /*!< DMC 1 ECC Error */ + DMC1_COMBINED_MISC_ACCESS_IRQn = + 190, /*!< DMC 1 Combined Miscellaneous access */ + DMC1_TEMPERATURE_EVENT_IRQn = 191, /*!< DMC 1 Temperature event */ + DMC1_SCRUB_IRQn = 192, /*!< DMC 1 Scrub */ + DMC1_CC_FREQ_IRQn = 193, /*!< DMC 1 clock frequency */ + + DMC3_COMBINED_OFLOW_IRQn = 201, /*!< DMC 3 Combined Overflow */ + DMC3_COMBINED_ERR_OVLOW_IRQn = 202, /*!< DMC 3 Combined err Ovlow */ + DMC3_COMBINED_ECC_ERR_IRQn = 203, /*!< DMC 3 ECC Error */ + DMC3_COMBINED_MISC_ACCESS_IRQn = + 204, /*!< DMC 3 Combined Miscellaneous access */ + DMC3_TEMPERATURE_EVENT_IRQn = 205, /*!< DMC 3 Temperature event */ + DMC3_SCRUB_IRQn = 206, /*!< DMC 3 Scrub */ + DMC3_CC_FREQ_IRQn = 207, /*!< DMC 3 clock frequency */ + + NETSEC0_IRQn = 212, /*!< NETSEC0 INTA */ + NETSEC1_IRQn = 214, /*!< NETSEC1 INTA */ +}; + +#endif /* SYNQUACER_IRQ_H */ diff --git a/product/synquacer/include/synquacer_mmap.h b/product/synquacer/include/synquacer_mmap.h new file mode 100644 index 000000000..1001c5095 --- /dev/null +++ b/product/synquacer/include/synquacer_mmap.h @@ -0,0 +1,298 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_MMAP_H +#define SYNQUACER_MMAP_H + +#include +#include + +#define PERIPH_BASE UINT32_C(0x44000000) +#define POWER_PERIPH_BASE UINT32_C(0x50000000) +#define EXTERNAL_DEV_BASE UINT32_C(0xA0000000) + +#define TRUSTED_RAM_BASE (EXTERNAL_DEV_BASE + 0x04000000) +#define NIC_BASE (EXTERNAL_DEV_BASE + 0x2A100000) +#define REFCLK_CNTCONTROL_BASE (EXTERNAL_DEV_BASE + 0x2A430000) +#define REFCLK_CNTREAD_BASE (EXTERNAL_DEV_BASE + 0x2A800000) +#define DDR_WINDOW_BASE (EXTERNAL_DEV_BASE + 0x2B000000) +#define NONTRUSTED_RAM_BASE (EXTERNAL_DEV_BASE + 0x2E000000) + +#define DDR_WINDOW_SIZE UINT32_C(0x100000) + +#define REFCLK_CNTCTL_BASE (PERIPH_BASE + 0x0000) +#define REFCLK_CNTBASE0_BASE (PERIPH_BASE + 0x1000) +#ifdef CONFIG_SCB_USE_AP_PL011 +#define SCP_UART_BASE UINT32_C(0xCA400000) +#else +#define SCP_UART_BASE (PERIPH_BASE + 0x2000) +#endif +#define WDOG_BASE (PERIPH_BASE + 0x6000) +#define MHU_AP_BASE (PERIPH_BASE + 0x1000000) + +#define REFCLK_CNTCONTROL ((cntcontrol_reg_t *)REFCLK_CNTCONTROL_BASE) +#define REFCLK_CNTCTL ((cntctl_reg_t *)REFCLK_CNTCTL_BASE) +#define REFCLK_CNTBASE0 ((cntbase_reg_t *)REFCLK_CNTBASE0_BASE) +#define WDOG ((sp805_reg_t *)WDOG_BASE) + +#define MHU_SCP_TO_AP_NS(cluster) \ + ((uintptr_t)(MHU_AP_BASE + 0x00010000 * cluster + 0x00000020)) +#define MHU_AP_TO_SCP_NS(cluster) \ + ((uintptr_t)(MHU_AP_BASE + 0x00010000 * cluster + 0x00000120)) +#define MHU_SCP_TO_AP_S(cluster) \ + ((uintptr_t)(MHU_AP_BASE + 0x00010000 * cluster + 0x00000200)) +#define MHU_AP_TO_SCP_S(cluster) \ + ((uintptr_t)(MHU_AP_BASE + 0x00010000 * cluster + 0x00000300)) + +/* + * MHU secure/non-secure SRAM + */ +#define MHU_CLUSTER_PAYLOAD_INTERVAL (64 * 1024) +#define MHU_PAYLOAD_SIZE (256) +#define MHU_PAYLOAD_NS_BASE (PERIPH_BASE + 0x01200000) +#define MHU_PAYLOAD_S_BASE (PERIPH_BASE + 0x01400000) + +#define MHU_PAYLOAD_S_CLUSTER_BASE(cluster) \ + (MHU_PAYLOAD_S_BASE + MHU_CLUSTER_PAYLOAD_INTERVAL * cluster) +/* + * Context area used by trusted firmware. Should be zeroed by SCP. + */ +#define AP_CONTEXT_BASE (TRUSTED_RAM_BASE + 0x0003F000) +#define AP_CONTEXT_SIZE 8 + +#define CCN512_BASE (EXTERNAL_DEV_BASE + 0x32000000) + +#define CONFIG_SOC_CORE_CLOCK UINT32_C(125000000) +#define CONFIG_SCB_TICK_US 500 + +/* SynQuacer peripheral address */ +#define HSSPI_REG_BASE UINT32_C(0x48800000) +#define HSSPI_MEM_BASE UINT32_C(0xA8000000) + +#define CONFIG_SOC_REG_ADDR_PBC_TOP UINT32_C(0x48900000) +#define CONFIG_SOC_REG_ADDR_PMU_TOP UINT32_C(0x48130000) + +#define CONFIG_SOC_HSSPI_EEPROM_BASE_ADDR UINT32_C(0x48810000) +#define CONFIG_SOC_BOOT_HSSPI_REG_ADDR UINT32_C(0x48100008) + +#define CONFIG_SCP_CONFIG_TABLE_ADDR UINT32_C(0xA8080000) + +/* EEPROM CONFIG */ +#define CONFIG_SCB_EEPROM_SIZE UINT32_C(65536) +#define CONFIG_SCP_CONFIG_TABLE_MAX_SIZE UINT32_C(65536) + +#define CONFIG_SOC_REG_ADDR_SYSOC_TOP UINT32_C(0x48300000) +#define CONFIG_SOC_REG_ADDR_BOOT_CTL_TOP UINT32_C(0x48100000) +#define CONFIG_SOC_REG_ADDR_CFG_CTL_TOP UINT32_C(0x48110000) +#define CONFIG_SOC_REG_ADDR_XCPB_TOP UINT32_C(0x48160000) + +#define AP_SCP_NIC UINT32_C(0x70100000) +#define DDRPHYREG0_NIC UINT32_C(0x7f000000) +#define DDRPHYREG1_NIC UINT32_C(0x7f400000) +#define DMABREG_NIC UINT32_C(0x7f800000) +#define FE_NIC UINT32_C(0x75000000) +#define SCBM_MV_NIC UINT32_C(0x72600000) + +#define CONFIG_SOC_NIC_ADDR_INFO \ + { \ + NIC_BASE, AP_SCP_NIC, DDRPHYREG0_NIC, DDRPHYREG1_NIC, DMABREG_NIC, \ + FE_NIC, \ + } + +#define CONFIG_SCB_NIC_INFO \ + { \ + { /* NIC_BASE */ \ + NIC_SETUP_SKIP, NIC_SETUP_SKIP, NIC_SETUP_SKIP, \ + NIC_SETUP_SKIP, NIC_SETUP_SKIP, 1, \ + END_OF_NIC_LIST \ + }, \ + { /* AP_SCP_NIC */ \ + 1, \ + END_OF_NIC_LIST \ + }, \ + { /* DDRPHYREG0_NIC */ \ + 3, \ + END_OF_NIC_LIST \ + }, \ + { /* DDRPHYREG1_NIC */ \ + 3, \ + END_OF_NIC_LIST \ + }, \ + { /* DMABREG_NIC */ \ + NIC_SETUP_SKIP, \ + 1, \ + END_OF_NIC_LIST \ + }, \ + { /* FE_NIC */ \ + NIC_SETUP_SKIP, \ + NIC_SETUP_SKIP, \ + 1, \ + 1, \ + END_OF_NIC_LIST \ + }, \ + } + +/* CRG config */ +#define CONFIG_SOC_CRG11_NUM 2 +#define CONFIG_SCB_CRG11_ID_PERI 0 +#define CONFIG_SCB_CRG11_ID_EMMC 1 + +#define CONFIG_SOC_REG_ADDR_CRG_PERI_TOP UINT32_C(0x48310000) +#define CONFIG_SOC_REG_ADDR_CRG_EMMC_TOP UINT32_C(0x48320000) + +#define F_UART3_BASE_ADDR UINT32_C(0x71040000) +#define CONFIG_SCB_UART_BAUD_RATE UART_SYSPARAM_BAUD_RATE_115200 + +#define CONFIG_SOC_REG_ADDR_SYSOC_TOP UINT32_C(0x48300000) +#define CONFIG_SOC_REG_ADDR_SYSOC_BUS_TOP CONFIG_SOC_REG_ADDR_SYSOC_TOP +#define CONFIG_SOC_REG_ADDR_SYSOC_SCP_TOP (CONFIG_SOC_REG_ADDR_SYSOC_TOP + 0x10) +#define CONFIG_SOC_REG_ADDR_SYSOC_DMA_TOP (CONFIG_SOC_REG_ADDR_SYSOC_TOP + 0x40) +#define CONFIG_SOC_REG_ADDR_SYSOC_PCIE_TOP \ + (CONFIG_SOC_REG_ADDR_SYSOC_TOP + 0x50) +#define CONFIG_SOC_REG_ADDR_SYSOC_DDR_TOP (CONFIG_SOC_REG_ADDR_SYSOC_TOP + 0x60) + +#define CONFIG_SOC_INIT_SYSOC_ADDR_INFOS \ + { \ + CONFIG_SOC_REG_ADDR_SYSOC_BUS_TOP, CONFIG_SOC_REG_ADDR_SYSOC_SCP_TOP, \ + } + +#define CONFIG_SOC_INIT_SYSOC_RESET_INFOS \ + { \ + /* BUS */ UINT32_C(0xf), /* SCP */ UINT32_C(0x1f), \ + } + +#define CONFIG_SCB_ARM_TF_BASE_ADDR UINT32_C(0xA8180000) +#define CONFIG_SCB_UEFI_BASE_ADDR UINT32_C(0xA8200000) + +#define CONFIG_SCB_ARM_TB_BL1_BASE_ADDR UINT32_C(0xA4000000) +#define CONFIG_SCB_ARM_TB_BL2_BASE_ADDR UINT32_C(0xA4013000) +#define CONFIG_SCB_ARM_TB_BL3_BASE_ADDR UINT32_C(0xA401F000) +#define CONFIG_SCB_ARM_TB_BL32_BASE_ADDR UINT32_C(0xFC000000) + +#define CONFIG_SCB_UART_RECV_BUF_BASE_ADDR UINT32_C(0xA4050000) + +/* 125MHz / 4 = 31.25MHz */ +#define CONFIG_SOC_HSSPI_CLK_CONFIG \ + { \ + .clk_sel = HSSPI_EN_MCTRL_CDSS_iHCLK, .clk_div = 4, \ + .syncon = HSSPI_EN_MCTRL_SYNCON_SYNC \ + } + +#define CONFIG_SOC_LPCM_SCB_TOP_ADDR UINT32_C(0x48318000) +#define CONFIG_SOC_LPCM_PCIE_TOP_ADDR UINT32_C(0x48319000) +#define CONFIG_SOC_LPCM_DMAB_TOP_ADDR UINT32_C(0x4831A000) +#define CONFIG_SOC_LPCM_EMMC_TOP_ADDR UINT32_C(0x48328000) + +#define CONFIG_SOC_LPCM_SCB_RESET_FLAG UINT32_C(0x1) +#define CONFIG_SOC_LPCM_PCIE_RESET_FLAG UINT32_C(0x73) +#define CONFIG_SOC_LPCM_DMAB_RESET_FLAG UINT32_C(0x3) + +#define CONFIG_SOC_REG_ADDR_SYS_OVER_REG_TOP UINT32_C(0x7FFF0000) +#define CONFIG_SOC_SYS_OVER_OFFSET_SEC_OVERRIDE UINT32_C(0x100) + +#define CONFIG_SCB_DDR_FREQ DDR_FREQ_2133 + +#define CONFIG_SCB_USE_4BYTE_MODE + +#define CONFIG_SCB_SMMU_PAGE_TABLE_BASE_ADDR UINT32_C(0xA4040000) + +#define CONFIG_SOC_NORTH_SMMU_REG_BASE UINT32_C(0x78280000) +#define CONFIG_SOC_SOUTH_SMMU_REG_BASE UINT32_C(0x782C0000) +#define CONFIG_SOC_DMAB_SMMU_REG_BASE UINT32_C(0x7fb00000) + +#define CONFIG_SOC_SD_CTL_REG_BASE UINT32_C(0x722E0000) + +#define CONFIG_SOC_DMA330_REG_BASE UINT32_C(0x7fa00000) +#define CONFIG_SOC_DMAB_WRAPPER_REG UINT32_C(0x7fb80000) + +#define CONFIG_SCB_ALL_OFF_LOG_GROUP UINT32_C(0x00) + +/** Number of PCIe instances */ +#define CONFIG_SOC_PCIE_NUM 2 + +/* cpl timeout range value 6: 65msec ~ 210msec */ +#define CONFIG_SCB_PCIE_CPL_TIMEOUT_RANVE_VALUE 0x6U + +/* Overriding BE[7:1] in PCIe TLP */ +#define CONFIG_SCB_TWEAK_PCIE_TLP_BE_OVERRIDE 0x7U + +#define CONFIG_SOC_PCIE_BAR0_MASK_DEFAULT 0x0000000FFFFFFFFFLLU + +#define CONFIG_SOC_PCIE_PME_SUPPORT (0x1BU) +#define CONFIG_SOC_PCIE_D2_SUPPORT (1U) +#define CONFIG_SOC_PCIE_D1_SUPPORT (1U) +#define CONFIG_SOC_PCIE_AUX_CURRENT (7U) +#define CONFIG_SOC_PCIE_DSI (0) +#define CONFIG_SOC_PCIE_ASPM_SUPPORT (0x3U) + +#define CONFIG_SOC_PRMUX_BASE_ADDR UINT32_C(0x74600000) +#define CONFIG_SOC_AP_GPIO_BASE (0x71000000) + +/** + * PRMUX settings + * 1:GPIO_NS + */ +#define CONFIG_SCB_PRMUX_PINGRP \ + { \ + 1, 1, 1, 1, 1, 1 \ + } + +/** + * GPIO direction settings + * 1: out + * 0: in + */ +#ifndef CONFIG_SCB_GPIO_DIRECTION +#define CONFIG_SCB_GPIO_DIRECTION \ + { \ + 0, 0, 0, 0 \ + } +#endif /* CONFIG_SCB_GPIO_DIRECTION */ + +/** + * GPIO function settings + * 0: GPIO + */ +#ifndef CONFIG_SCB_GPIO_FUNCTION +#define CONFIG_SCB_GPIO_FUNCTION \ + { \ + 0, 0, 0, 0 \ + } +#endif /* CONFIG_SCB_GPIO_FUNCTION */ + +#define CONFIG_SOC_I2C_ENABLE_BITMAP (1 << 0) +#define CONFIG_SOC_I2C_BASE_ADDRS \ + { \ + 0x4A000000 \ + } +#define CONFIG_SOC_I2C_TYPES \ + { \ + I2C_TYPE_F_I2C \ + } +#define CONFIG_SOC_I2C_CHANNELS \ + { \ + I2C_EN_CH0 \ + } + +#define CONFIG_SCB_I2C_PARAMS \ + { \ + { .I2C_PARAM_F_I2C = { .FSR_FS = 0x02, \ + .CSR_CS = 0x03, \ + .CCR_CS = 0x07, \ + .CCR_FM = 0x01 } }, \ + } + +/* SRAM for one way CM3->AP mailbox for BMC bootflag */ +#define CONFIG_SCB_BMC_BOOTFLAG_ADDR UINT32_C(0xCE00FFF8) + +#ifdef CONFIG_SCB_DIST_FIRM +#define CONFIG_SCB_MANUAL_THERMAL_READ +#endif /* CONFIG_SCB_DIST_FIRM */ + +#define CONFIG_SOC_PRMUX_MAX_IDX 7 + +#endif /* SYNQUACER_MMAP_H */ diff --git a/product/synquacer/include/synquacer_pik.h b/product/synquacer/include/synquacer_pik.h new file mode 100644 index 000000000..3217a8157 --- /dev/null +++ b/product/synquacer/include/synquacer_pik.h @@ -0,0 +1,61 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_PIK_H +#define SYNQUACER_PIK_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PIK_SCP_BASE (POWER_PERIPH_BASE + 0x00000) +#define PIK_DEBUG_BASE (POWER_PERIPH_BASE + 0x20000) +#define PIK_SYSTEM_BASE (POWER_PERIPH_BASE + 0x40000) +#define PIK_CLUSTER_BASE (POWER_PERIPH_BASE + 0x60000) + +#define PIK_AP_CLUSTER0_BASE (POWER_PERIPH_BASE + 0x60000) +#define PIK_AP_CLUSTER_INTERVAL (0x20000) +#define PIK_AP_CLUSTER_BASE(n) \ + (PIK_AP_CLUSTER0_BASE + (PIK_AP_CLUSTER_INTERVAL * (n))) + +#define PPU_SCP_BASE (PIK_SCP_BASE + 0x1000) +#define PPU_SYS0_BASE (PIK_SYSTEM_BASE + 0x1000) +#define PPU_SYS1_BASE (PIK_SYSTEM_BASE + 0x2000) +#define PPU_SYS2_BASE (PIK_SYSTEM_BASE + 0x3000) +#define PPU_SYS3_BASE (PIK_SYSTEM_BASE + 0x4000) +#define PPU_SYS4_BASE (PIK_SYSTEM_BASE + 0x5000) +#define PPU_DEBUG_BASE (PIK_DEBUG_BASE + 0x1000) +#define PPU_AP_CLUSTER_BASE(n) (PIK_AP_CLUSTER_BASE((n)) + 0x1000) + +#define PPU_CLUSTER_AP_CORE_INTERVAL (0x1000) +#define PPU_CPU_BASE(cluster, core) \ + (PPU_AP_CLUSTER_BASE((cluster)) + 0x1000 + \ + (PPU_CLUSTER_AP_CORE_INTERVAL * (core))) + +#define PIK_SCP ((pik_scp_reg_t *)PIK_SCP_BASE) +#define PIK_DEBUG ((pik_debug_reg_t *)PIK_DEBUG_BASE) +#define PIK_SYSTEM ((pik_system_reg_t *)PIK_SYSTEM_BASE) +#define PIK_CLUSTER(n) ((pik_cpu_reg_t *)PIK_AP_CLUSTER_BASE(n)) + +#define PPU_SCP ((struct ppu_v0_reg *)PPU_SCP_BASE) +#define PPU_SYS0 ((struct ppu_v0_reg *)PPU_SYS0_BASE) +#define PPU_SYS1 ((struct ppu_v0_reg *)PPU_SYS1_BASE) +#define PPU_SYS2 ((struct ppu_v0_reg *)PPU_SYS2_BASE) +#define PPU_SYS3 ((struct ppu_v0_reg *)PPU_SYS3_BASE) +#define PPU_SYS4 ((struct ppu_v0_reg *)PPU_SYS4_BASE) +#define PPU_DEBUG ((struct ppu_v0_reg *)PPU_DEBUG_BASE) +#define PPU_CLUSTER(n) ((struct ppu_v0_reg *)PPU_AP_CLUSTER_BASE(n)) +#define PPU_CPU(cluster, core) \ + ((struct ppu_v0_reg *)PPU_CPU_BASE(cluster, core)) + +#endif /* SYNQUACER_PIK_H */ diff --git a/product/synquacer/include/system_clock.h b/product/synquacer/include/system_clock.h new file mode 100644 index 000000000..04b2aaaaf --- /dev/null +++ b/product/synquacer/include/system_clock.h @@ -0,0 +1,39 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYSTEM_CLOCK_H +#define SYSTEM_CLOCK_H + +#include + +/*! + * \brief Calculates the necessary divider for obtaining a target frequency + * from a given clock. + * + * \param CLOCK_RATE The tick rate of the clock to be divided. + * + * \param TARGET_FREQ The target frequency to be obtained by the division. + * + * \return The divider needed to obtain TARGET_FREQ from CLOCK_RATE. + */ +#define DIV_FROM_CLOCK(CLOCK_RATE, TARGET_FREQ) (CLOCK_RATE / (TARGET_FREQ)) + +/* + * Clock references + */ +#define CLOCK_RATE_SYSINCLK (1000UL * FWK_MHZ) +#define CLOCK_RATE_REFCLK (100UL * FWK_MHZ) +#define CLOCK_RATE_DDRPLLCLK (1066UL * FWK_MHZ) +#define CLOCK_RATE_AP_PL011CLK (62500 * FWK_KHZ) + +#ifdef CONFIG_SCB_USE_AP_PL011 +#define CLOCK_RATE_PL011CLK CLOCK_RATE_AP_PL011CLK +#else +#define CLOCK_RATE_PL011CLK (100000 * FWK_KHZ) +#endif + +#endif /* SYSTEM_CLOCK_H */ diff --git a/product/synquacer/module/ccn512/include/internal/ccn512.h b/product/synquacer/module/ccn512/include/internal/ccn512.h new file mode 100644 index 000000000..f1636469d --- /dev/null +++ b/product/synquacer/module/ccn512/include/internal/ccn512.h @@ -0,0 +1,265 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCN512_H +#define CCN512_H + +#include +#include + +/* + * CCN5xx miscellaneous node (MN) registers + */ +typedef struct { + FWK_RW uint64_t SECURE_ACCESS; + FWK_RW uint64_t ERRINT_STATUS; + uint8_t RESERVED0[0x170]; + FWK_R uint64_t OLY_RNF_NODEID_LIST; + uint8_t RESERVED1[0x8]; + FWK_R uint64_t OLY_RNI_NODEID_LIST; + uint8_t RESERVED2[0x8]; + FWK_R uint64_t OLY_RNIDVM_NODEID_LIST; + uint8_t RESERVED3[0x8]; + FWK_R uint64_t OLY_HNF_NODEID_LIST; + uint8_t RESERVED4[0x8]; + FWK_R uint64_t OLY_HNI_NODEID_LIST; + uint8_t RESERVED5[0x8]; + FWK_R uint64_t OLY_SN_NODEID_LIST; + uint8_t RESERVED6[0x8]; + FWK_R uint64_t OLY_COMP_LIST_63_0; + FWK_R uint64_t OLY_COMP_LIST_127_64; + FWK_R uint64_t OLY_COMP_LIST_191_128; + FWK_R uint64_t OLY_COMP_LIST_255_192; + FWK_R uint64_t DVM_DOMAIN_CTL; + uint8_t RESERVED7[0x8]; + FWK_W uint64_t DVM_DOMAIN_CTL_SET; + uint8_t RESERVED8[0x8]; + FWK_W uint64_t DVM_DOMAIN_CTL_CLR; + uint8_t RESERVED9[0xD8]; + FWK_R uint64_t ERR_SIG_VAL_63_0; + FWK_R uint64_t ERR_SIG_VAL_127_64; + FWK_R uint64_t ERR_SIG_VAL_191_128; + uint8_t RESERVED10[0x8]; + FWK_R uint64_t ERR_TYPE_31_0; + FWK_R uint64_t ERR_TYPE_63_32; + FWK_R uint64_t ERR_TYPE_95_64; + uint8_t RESERVED11[0x8]; + FWK_R uint64_t ERR_TYPE_159_128; + uint8_t RESERVED12[0xC88]; + FWK_R uint64_t PERIPH_ID_4_PERIPH_ID_5; + FWK_R uint64_t PERIPH_ID_6_PERIPH_ID_7; + FWK_R uint64_t PERIPH_ID_0_PERIPH_ID_1; + FWK_R uint64_t PERIPH_ID_2_PERIPH_ID_3; + FWK_R uint64_t COMPONENT_ID_0_COMPONENT_ID_1; + FWK_R uint64_t COMPONENT_ID_2_COMPONENT_ID_3; + uint8_t RESERVED13[0xEF00]; + FWK_R uint64_t OLY_MN_OLY_ID; + uint8_t RESERVED14[0xF8]; +} ccn5xx_mn_reg_t; + +/* + * CCN5xx crosspoint (XP) registers + */ +typedef struct { + FWK_RW uint64_t XP_ROUTING_CONTROL; + FWK_RW uint64_t DEV0_NSM_ROUTING_VECTOR; + FWK_RW uint64_t DEV1_NSM_ROUTING_VECTOR; + uint8_t RESERVED0[0xF8]; + FWK_RW uint64_t DEV0_QOS_CONTROL; + FWK_RW uint64_t DEV0_QOS_LAT_TGT; + FWK_RW uint64_t DEV0_QOS_LAT_SCALE; + FWK_RW uint64_t DEV0_QOS_LAT_RANGE; + uint8_t RESERVED1[0xE0]; + FWK_RW uint64_t DEV1_QOS_CONTROL; + FWK_RW uint64_t DEV1_QOS_LAT_TGT; + FWK_RW uint64_t DEV1_QOS_LAT_SCALE; + FWK_RW uint64_t DEV1_QOS_LAT_RANGE; + uint8_t RESERVED2[0xD0]; + FWK_RW uint64_t DT_CONFIG; + FWK_RW uint64_t DT_INTERFACE_SEL; + FWK_RW uint64_t DT_CMP_VAL0_L; + FWK_RW uint64_t DT_CMP_VAL0_H; + FWK_RW uint64_t DT_CMP_MASK0_L; + FWK_RW uint64_t DT_CMP_MASK0_H; + uint8_t RESERVED3[0x20]; + FWK_RW uint64_t DT_CMP_VAL1_L; + FWK_RW uint64_t DT_CMP_VAL1_H; + FWK_RW uint64_t DT_CMP_MASK1_L; + FWK_RW uint64_t DT_CMP_MASK1_H; + FWK_RW uint64_t DT_CONTROL; + FWK_RW uint64_t DT_STATUS; + FWK_W uint64_t DT_STATUS_CLR; + uint8_t RESERVED4[0x78]; + FWK_R uint64_t ERR_SYNDROME_REG0; + uint8_t RESERVED5[0x78]; + FWK_W uint64_t ERR_SYNDROME_CLR; + uint8_t RESERVED6[0x78]; + FWK_RW uint64_t AUX_CTL; + uint8_t RESERVED7[0xF8]; + FWK_RW uint64_t PMU_EVENT_SEL; + uint8_t RESERVED8[0xF8F8]; + FWK_R uint64_t OLY_XP_OLY_ID; + uint8_t RESERVED9[0xF8]; +} ccn5xx_xp_reg_t; + +/* + * CCN5xx fully coherent home node (HN-F) registers + */ +typedef struct { + FWK_RW uint64_t HNF_CFG_CTRL; + FWK_RW uint64_t HNF_SAM_CONTROL; + FWK_W uint64_t HN_CFG_PSTATE_REQ; + FWK_R uint64_t HN_CFG_PSTATE_STATUS; + FWK_R uint64_t QOS_BAND; + FWK_RW uint64_t QOS_RESERVATION; + FWK_RW uint64_t RN_STARVATION; + FWK_RW uint64_t HNF_ERR_INJ; + FWK_RW uint64_t HNF_L3_LOCK_WAYS; + FWK_RW uint64_t HNF_L3_LOCK_BASE0; + FWK_RW uint64_t HNF_L3_LOCK_BASE1; + FWK_RW uint64_t HNF_L3_LOCK_BASE2; + FWK_RW uint64_t HNF_L3_LOCK_BASE3; + uint8_t RESERVED0[0xA0]; + FWK_RW uint64_t HN_CFG_RNI_VEC; + uint8_t RESERVED1[0xF0]; + FWK_R uint64_t SNOOP_DOMAIN_CTL; + uint8_t RESERVED2[0x8]; + FWK_W uint64_t SNOOP_DOMAIN_CTL_SET; + uint8_t RESERVED3[0x8]; + FWK_W uint64_t SNOOP_DOMAIN_CTL_CLR; + uint8_t RESERVED4[0xD8]; + FWK_W uint64_t HN_CFG_L3SF_DBGRD; + FWK_R uint64_t L3_CACHE_ACCESS_L3_TAG; + FWK_R uint64_t L3_CACHE_ACCESS_L3_DATA; + FWK_R uint64_t L3_CACHE_ACCESS_SF_TAG; + uint8_t RESERVED5[0xE0]; + FWK_R uint64_t ERR_SYNDROME_REG0; + FWK_R uint64_t ERR_SYNDROME_REG1; + uint8_t RESERVED6[0x70]; + FWK_W uint64_t ERR_SYNDROME_CLR; + uint8_t RESERVED7[0x78]; + FWK_RW uint64_t HNF_AUX_CTL; + uint8_t RESERVED8[0xF8]; + FWK_RW uint64_t PMU_EVENT_SEL; + uint8_t RESERVED9[0xF8F8]; + FWK_R uint64_t OLY_HNF_MISC_OLY_ID; + uint8_t RESERVED10[0xF8]; +} ccn5xx_hnf_reg_t; + +/* + * CCN5xx I/O home node (HN-I) registers + */ +typedef struct { + FWK_RW uint64_t POS_CONTROL; + FWK_RW uint64_t PCIERC_RNI_NODEID_LIST; + uint8_t RESERVED0[0x3F0]; + FWK_R uint64_t ERR_SYNDROME_REG0; + FWK_R uint64_t ERR_SYNDROME_REG1; + uint8_t RESERVED1[0x70]; + FWK_W uint64_t ERR_SYNDROME_CLR; + uint8_t RESERVED2[0x78]; + FWK_RW uint64_t SA_AUX_CTL; + uint8_t RESERVED3[0xF9F8]; + FWK_R uint64_t OLY_HNI_OLY_ID; + uint8_t RESERVED4[0xF8]; +} ccn5xx_hni_reg_t; + +/* + * CCN5xx debug event module registers + */ +typedef struct { + FWK_RW uint64_t ACTIVE_DSM; + FWK_RW uint64_t TRIGGER_CTL; + FWK_RW uint64_t TRIGGER_STATUS; + FWK_W uint64_t TRIGGER_STATUS_CLR; + FWK_RW uint64_t TIMER_VAL; + FWK_RW int64_t DT_CTL; + uint8_t RESERVED0[0x50]; + FWK_RW uint64_t DBG_ID; + uint8_t RESERVED1[0x78]; + FWK_RW uint64_t PMEVCNT0; + FWK_RW uint64_t PMEVCNT1; + FWK_RW uint64_t PMEVCNT2; + FWK_RW uint64_t PMEVCNT3; + FWK_RW uint64_t PMEVCNT4; + FWK_RW uint64_t PMEVCNT5; + FWK_RW uint64_t PMEVCNT6; + FWK_RW uint64_t PMEVCNT7; + FWK_RW uint64_t PMCCNTR; + uint8_t RESERVED2[0x8]; + FWK_RW uint64_t PMEVCNTSR0; + FWK_RW uint64_t PMEVCNTSR1; + FWK_RW uint64_t PMEVCNTSR2; + FWK_RW uint64_t PMEVCNTSR3; + FWK_RW uint64_t PMEVCNTSR4; + FWK_RW uint64_t PMEVCNTSR5; + FWK_RW uint64_t PMEVCNTSR6; + FWK_RW uint64_t PMEVCNTSR7; + FWK_RW uint64_t PMCCNTRSR; + FWK_R uint64_t PMOVSR; + FWK_RW uint64_t PMOVSR_CLR; + FWK_RW uint64_t PMCR; + FWK_R uint64_t PMSR; + FWK_W uint64_t PMSR_REQ; + FWK_W uint64_t PMSR_CLR; + uint8_t RESERVED3[0xFD38]; + FWK_R uint64_t OLY_MN_DT_OLY_ID; + uint8_t RESERVED4[0xF8]; +} ccn5xx_dbg_reg_t; + +/* + * CCN5xx I/O coherent requesting node bridge (RN-I) registers + */ +typedef struct { + uint8_t RESERVED0[0x8]; + FWK_RW uint64_t S0_PORT_CONTROL; + FWK_RW uint64_t S0_QOS_CONTROL; + FWK_RW uint64_t S0_QOS_LAT_TGT; + FWK_RW uint64_t S0_QOS_LAT_SCALE; + FWK_RW uint64_t S0_QOS_LAT_RANGE; + uint8_t RESERVED1[0xD8]; + FWK_RW uint64_t S1_PORT_CONTROL; + FWK_RW uint64_t S1_QOS_CONTROL; + FWK_RW uint64_t S1_QOS_LAT_TGT; + FWK_RW uint64_t S1_QOS_LAT_SCALE; + FWK_RW uint64_t S1_QOS_LAT_RANGE; + uint8_t RESERVED2[0xD8]; + FWK_RW uint64_t S2_PORT_CONTROL; + FWK_RW uint64_t S2_QOS_CONTROL; + FWK_RW uint64_t S2_QOS_LAT_TGT; + FWK_RW uint64_t S2_QOS_LAT_SCALE; + FWK_RW uint64_t S2_QOS_LAT_RANGE; + uint8_t RESERVED3[0x2D0]; + FWK_RW uint64_t AUX_CTL; + uint8_t RESERVED4[0xF8]; + FWK_RW uint64_t PMU_EVENT_SEL; + uint8_t RESERVED5[0xF8F8]; + FWK_R uint64_t OLY_RNI_OLY_ID; + uint8_t RESERVED6[0xF8]; +} ccn5xx_rni_reg_t; + +/* + * CCN5xx CHI to AXI bridge (SBSX) registers + */ +typedef struct { + uint8_t RESERVED0[0x500]; + FWK_RW uint64_t SA_AUX_CTL; + uint8_t RESERVED1[0xF9F8]; + FWK_R uint64_t OLY_SBSX_OLY_ID; + uint8_t RESERVED2[0xF8]; +} ccn5xx_sbsx_reg_t; + +/* + * CCN5xx unused region structure, used as a placeholder + */ +typedef struct { + uint8_t RESERVED0[0xFF00]; + FWK_R uint64_t OLY_REGION_OLY_ID; + uint8_t RESERVED1[0xF8]; +} ccn5xx_region_t; + +#endif /* CCN512_H */ diff --git a/product/synquacer/module/ccn512/include/mod_ccn512.h b/product/synquacer/module/ccn512/include/mod_ccn512.h new file mode 100644 index 000000000..94dfa9a13 --- /dev/null +++ b/product/synquacer/module/ccn512/include/mod_ccn512.h @@ -0,0 +1,128 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_CCN512_H +#define MOD_CCN512_H + +#include +#include +#include +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupCCN512 CCN512 Driver + * + * \brief CCN512 device driver. + * + * \details This module implements a device driver for the CCN512 + * + * @{ + */ + +/* + * \brief CCN512 memory map + */ +typedef struct { + /*! + * \cond + * @{ + */ + ccn5xx_mn_reg_t MN_ID_34; + ccn5xx_dbg_reg_t DEBUG_ID_34; + ccn5xx_region_t RESERVED0[6]; + ccn5xx_hni_reg_t HNI_ID_13; + ccn5xx_hni_reg_t HNI_ID_34; + ccn5xx_region_t RESERVED1[6]; + ccn5xx_sbsx_reg_t SBSX_ID_3; + ccn5xx_sbsx_reg_t SBSX_ID_8; + ccn5xx_sbsx_reg_t SBSX_ID_21; + ccn5xx_sbsx_reg_t SBSX_ID_26; + ccn5xx_region_t RESERVED2[12]; + ccn5xx_hnf_reg_t HNF_ID_2; + ccn5xx_hnf_reg_t HNF_ID_5; + ccn5xx_hnf_reg_t HNF_ID_6; + ccn5xx_hnf_reg_t HNF_ID_9; + ccn5xx_hnf_reg_t HNF_ID_20; + ccn5xx_hnf_reg_t HNF_ID_23; + ccn5xx_hnf_reg_t HNF_ID_24; + ccn5xx_hnf_reg_t HNF_ID_27; + ccn5xx_region_t RESERVED3[24]; + ccn5xx_xp_reg_t XP_ID_0; + ccn5xx_xp_reg_t XP_ID_1; + ccn5xx_xp_reg_t XP_ID_2; + ccn5xx_xp_reg_t XP_ID_3; + ccn5xx_xp_reg_t XP_ID_4; + ccn5xx_xp_reg_t XP_ID_5; + ccn5xx_xp_reg_t XP_ID_6; + ccn5xx_xp_reg_t XP_ID_7; + ccn5xx_xp_reg_t XP_ID_8; + ccn5xx_xp_reg_t XP_ID_9; + ccn5xx_xp_reg_t XP_ID_10; + ccn5xx_xp_reg_t XP_ID_11; + ccn5xx_xp_reg_t XP_ID_12; + ccn5xx_xp_reg_t XP_ID_13; + ccn5xx_xp_reg_t XP_ID_14; + ccn5xx_xp_reg_t XP_ID_15; + ccn5xx_xp_reg_t XP_ID_16; + ccn5xx_xp_reg_t XP_ID_17; + ccn5xx_region_t RESERVED4[47]; + ccn5xx_rni_reg_t RNI_ID_1; + ccn5xx_region_t RESERVED5[2]; + ccn5xx_rni_reg_t RNI_ID_4; + ccn5xx_region_t RESERVED6[2]; + ccn5xx_rni_reg_t RNI_ID_7; + ccn5xx_region_t RESERVED7[2]; + ccn5xx_rni_reg_t RNI_ID_10; + ccn5xx_region_t RESERVED8[8]; + ccn5xx_rni_reg_t RNI_ID_19; + ccn5xx_region_t RESERVED9[2]; + ccn5xx_rni_reg_t RNI_ID_22; + ccn5xx_region_t RESERVED10[2]; + ccn5xx_rni_reg_t RNI_ID_25; + ccn5xx_region_t RESERVED11[2]; + ccn5xx_rni_reg_t RNI_ID_28; + /*! + * \endcond + * @} + */ +} ccn512_reg_t; + +/*! + * \brief APIs to configure ccn512. + */ +struct mod_ccn512_api { + /*! + * \brief APIs to configure ccn512 + * + * \param none + * + */ + void (*ccn512_exit)(void); +}; + +/*! + * \brief CCN512 device configuration data. + */ +struct mod_ccn512_module_config { + /*! Base address of the device registers */ + ccn512_reg_t *reg_base; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_CCN512_H */ diff --git a/product/synquacer/module/ccn512/src/Makefile b/product/synquacer/module/ccn512/src/Makefile new file mode 100644 index 000000000..19623cf91 --- /dev/null +++ b/product/synquacer/module/ccn512/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := "ccn512" +BS_LIB_SOURCES = mod_ccn512.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/ccn512/src/mod_ccn512.c b/product/synquacer/module/ccn512/src/mod_ccn512.c new file mode 100644 index 000000000..7e13e8072 --- /dev/null +++ b/product/synquacer/module/ccn512/src/mod_ccn512.c @@ -0,0 +1,242 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mod_log_api *log_api; + +#define HNF_COUNT 8 +#define SNF_ID_DMC1 0x8ULL +#define SNF_ID_DMC3 0x1AULL + +#define SNF_MP_ID_DMC0 0x8ULL +#define SNF_MP_ID_DMC1 0x1AULL + +static void ccn512_qos_init(ccn512_reg_t *ccn512) +{ + /* + * Setting QOS priority for each CPU cluster to 0xE and setting the + * enable bit so the new setting takes effect. This function must be + * called when there are no ongoing transactions on the ports being + * configured, so it must be called after powering on SYSTOP and before + * the applications cores/clusters are released from reset. + * + * See "Device 0 Port QoS Control register" in the Corelink CCN512 Cache + * Coherent Network technical reference manual. + */ + ccn512->XP_ID_0.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 0 */ + ccn512->XP_ID_1.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_2.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_3.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_4.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_5.DEV0_QOS_CONTROL = 0xE0004; /* PCIE1 */ + ccn512->XP_ID_6.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 6 */ + ccn512->XP_ID_7.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 8 */ + ccn512->XP_ID_8.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_9.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 1 */ + ccn512->XP_ID_10.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_11.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_12.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_13.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_14.DEV0_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_15.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 7 */ + ccn512->XP_ID_16.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 9 */ + ccn512->XP_ID_17.DEV0_QOS_CONTROL = 0; + + ccn512->XP_ID_0.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_1.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_2.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_3.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_4.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_5.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 2 */ + ccn512->XP_ID_6.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_7.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 10 */ + ccn512->XP_ID_8.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 5 */ + ccn512->XP_ID_9.DEV1_QOS_CONTROL = 0xE0004; /* PCIE0 */ + ccn512->XP_ID_10.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_11.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_12.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_13.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_14.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 3 */ + ccn512->XP_ID_15.DEV1_QOS_CONTROL = 0; /* not Cluster */ + ccn512->XP_ID_16.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 11 */ + ccn512->XP_ID_17.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 4 */ +} + +static void ccn512_dmc_init(ccn512_reg_t *ccn512) +{ + unsigned int i; + ccn5xx_hnf_reg_t *hnf = &ccn512->HNF_ID_2; + uint64_t ddr_ch0_id, ddr_ch1_id; + + uint8_t ddr_memory_used_ch; + ddr_memory_used_ch = fw_get_used_memory_ch(); + + ddr_ch0_id = SNF_MP_ID_DMC0; + ddr_ch1_id = SNF_MP_ID_DMC1; + + /* + * On SynQuacer, there are only 2 DMCs (IDs 1 and 3). + * All traffic from the first half of the HN-Fs must go to DMC1 and the + * second half to DMC3. + * If this setup is not done, the traffic for the DMCs that do not + * exist will lock-up the system. + */ + for (i = 0; i < HNF_COUNT; i++) { + if (ddr_memory_used_ch == DDR_USE_CH0) { + hnf[i].HNF_SAM_CONTROL = ddr_ch0_id; + } else if (ddr_memory_used_ch == DDR_USE_CH1) { + hnf[i].HNF_SAM_CONTROL = ddr_ch1_id; + } else { + hnf[i].HNF_SAM_CONTROL = + (i < (HNF_COUNT / 2) ? ddr_ch0_id : ddr_ch1_id); + } + } +} + +static void ccn512_secure_init(ccn512_reg_t *ccn512) +{ + /* set Non-secure access enable */ + ccn512->MN_ID_34.SECURE_ACCESS |= 0x1; +} + +void fw_ccn512_init(ccn512_reg_t *ccn512) +{ + ccn512_secure_init(ccn512); + ccn512_qos_init(ccn512); + ccn512_dmc_init(ccn512); + + /* Wait for write operations to finish. */ + __DMB(); +} + +void fw_ccn512_exit(void) +{ + const struct mod_ccn512_module_config *module_config; + ccn512_reg_t *ccn512; + unsigned int i; + + module_config = fwk_module_get_data(fwk_module_id_ccn512); + assert(module_config != NULL); + + ccn512 = module_config->reg_base; + + ccn5xx_hnf_reg_t *hnf = &ccn512->HNF_ID_2; + + log_api->log(MOD_LOG_GROUP_DEBUG, "[CCN512] CCN512 exit.\n"); + + /* exit ALL CA53 CPU SNOOP */ + for (i = 0; i < HNF_COUNT; i++) + hnf[i].SNOOP_DOMAIN_CTL_CLR = hnf[i].SNOOP_DOMAIN_CTL; + + /* Wait for write operations to finish. */ + __DMB(); + + log_api->log(MOD_LOG_GROUP_DEBUG, "[CCN512] CCN512 exit end.\n"); +} + +static int ccn512_config(ccn512_reg_t *ccn512) +{ + log_api->log( + MOD_LOG_GROUP_DEBUG, + "[CCN512] Initialising ccn512 at 0x%x\n", + (uintptr_t)ccn512); + + fw_ccn512_init(ccn512); + + log_api->log(MOD_LOG_GROUP_DEBUG, "[CCN512] CCN512 init done.\n"); + + return FWK_SUCCESS; +} + +static struct mod_ccn512_api module_api = { + .ccn512_exit = fw_ccn512_exit, +}; + +/* Framework API */ +static int mod_ccn512_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + return FWK_SUCCESS; +} + +static int mod_ccn512_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + assert(data != NULL); + + return FWK_SUCCESS; +} + +static int mod_ccn512_bind(fwk_id_t id, unsigned int round) +{ + int status; + + /* Nothing to do in the second round of calls. */ + if (round == 1) + return FWK_SUCCESS; + + /* Nothing to do in case of elements. */ + if (fwk_module_is_valid_element_id(id)) + return FWK_SUCCESS; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_LOG), MOD_LOG_API_ID, &log_api); + if (status != FWK_SUCCESS) + return status; + + return FWK_SUCCESS; +} + +static int mod_ccn512_start(fwk_id_t id) +{ + const struct mod_ccn512_module_config *module_config; + ccn512_reg_t *ccn512; + + module_config = fwk_module_get_data(fwk_module_id_ccn512); + assert(module_config != NULL); + + ccn512 = module_config->reg_base; + + return ccn512_config(ccn512); +} + +static int mod_ccn512_process_bind_request( + fwk_id_t requester_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + *api = &module_api; + + return FWK_SUCCESS; +} + +const struct fwk_module module_ccn512 = { + .name = "ccn512", + .type = FWK_MODULE_TYPE_DRIVER, + .init = mod_ccn512_init, + .element_init = mod_ccn512_element_init, + .bind = mod_ccn512_bind, + .start = mod_ccn512_start, + .process_bind_request = mod_ccn512_process_bind_request, + .api_count = 1, + .event_count = 0, +}; diff --git a/product/synquacer/module/f_i2c/include/i2c_api.h b/product/synquacer/module/f_i2c/include/i2c_api.h new file mode 100644 index 000000000..c0445772b --- /dev/null +++ b/product/synquacer/module/f_i2c/include/i2c_api.h @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_API_H +#define I2C_API_H + +#include +#include +#include + +#define I2C_MP_START_ADDR 0x50 + +I2C_ERR_t f_i2c_api_recv_data( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + uint8_t *data, + int length); + +I2C_ERR_t f_i2c_api_send_data( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + const uint8_t *data, + int length); + +#endif /* I2C_API_H */ diff --git a/product/synquacer/module/f_i2c/include/internal/i2c_depend.h b/product/synquacer/module/f_i2c/include/internal/i2c_depend.h new file mode 100644 index 000000000..d91aa3ea4 --- /dev/null +++ b/product/synquacer/module/f_i2c/include/internal/i2c_depend.h @@ -0,0 +1,26 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_DEPEND_H +#define I2C_DEPEND_H + +#include +#include + +typedef enum { I2C_EN_CH0, I2C_EN_CH1, I2C_EN_CH2 } I2C_EN_CH_t; + +I2C_ST_PACKET_INFO_t *i2c_get_channel_structure(I2C_EN_CH_t ch); + +void i2c_construction(void); +void i2c_destruction(void); +I2C_ERR_t f_i2c_api_initialize( + I2C_ST_PACKET_INFO_t *packet_info, + uint32_t reg_base, + I2C_TYPE type, + const I2C_PARAM_t *param); + +#endif /* I2C_DEPEND_H */ diff --git a/product/synquacer/module/f_i2c/include/internal/i2c_driver.h b/product/synquacer/module/f_i2c/include/internal/i2c_driver.h new file mode 100644 index 000000000..fb06dc97c --- /dev/null +++ b/product/synquacer/module/f_i2c/include/internal/i2c_driver.h @@ -0,0 +1,131 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_DRIVER_H +#define I2C_DRIVER_H + +#include +#include + +#define I2C_POLLING_LIMIT (0x00100000U) + +typedef enum { + I2C_ERR_OK = 0, + I2C_ERR_PARAM, + I2C_ERR_BUSY, + I2C_ERR_BER, + I2C_ERR_BER_MC, + I2C_ERR_POLLING, + I2C_ERR_UNAVAILABLE +} I2C_ERR_t; + +typedef enum { + I2C_EN_EVF_NONE = 0, + I2C_EN_EVF_FINISH, + I2C_EN_EVF_BUSERROR, + I2C_EN_EVF_MC_BUSERROR, + I2C_EN_EVF_TIMEOUT, + I2C_EN_EVF_NAK +} I2C_EN_EVF_t; + +typedef enum { I2C_TYPE_F_I2C = 0, I2C_TYPE_F_I2C_SP1 } I2C_TYPE; + +typedef union { + uint8_t DATA; + struct { + /** B[0] READ/WRITE */ + uint32_t BITFIELD_READ : 1; + /** B[7:1] SLAVE ADDRESS */ + uint32_t BITFIELD_ADDR : 7; + } bit; +} I2C_UN_SLVADDR_t; + +typedef union { + struct { + uint8_t FSR_FS; + uint8_t CSR_CS; + uint8_t CCR_CS; + uint8_t CCR_FM; + } I2C_PARAM_F_I2C; + struct { + uint8_t NFR_NF; + uint8_t NFR_NFH; + uint8_t TLWR_TLW; + uint8_t TLW2R_TLW; + uint8_t THWR_THW; + uint8_t THW2R_THW; + uint8_t TBFR_TBF; + uint8_t TBF2R_TBF; + uint8_t TRSR_TRS; + uint8_t TRS2R_TRS; + uint8_t TSHR_TSH; + uint8_t TSH2R_TSH; + uint8_t TPSR_TPS; + uint8_t TPS2R_TPS; + uint8_t TLWRH_TLWH; + uint8_t THWRH_THWH; + uint8_t TRSRH_TRSH; + uint8_t TSHRH_TSHH; + uint8_t TPSRH_TPSH; + } I2C_PARAM_F_I2C_SP1; +} I2C_PARAM_t; + +typedef struct { + char *BUFF; + bool *ATTR; + int SIZE; + int LIMIT; + int INDEX; +} I2C_ST_FIFO_t; + +typedef struct { + I2C_ST_FIFO_t CTRL; + I2C_ST_FIFO_t DATA; +} I2C_ST_PACKET_t; + +typedef struct { + I2C_TYPE TYPE; + uint32_t I2C_BASE_ADDR; + bool USE_HS_MODE; + bool MASTER_CODE_FLAG; + I2C_ST_PACKET_t PACKET; + char CTRL_BUFF[0x08]; + bool CTRL_ATTR[0x08]; +} I2C_ST_PACKET_INFO_t; + +I2C_ST_PACKET_t *i2c_packet_initialize(I2C_ST_PACKET_t *packet); + +I2C_ST_PACKET_t *i2c_packet_set_payload( + I2C_ST_PACKET_t *packet, + char *buffer, + int size); + +I2C_ST_PACKET_t *i2c_packet_set_control( + I2C_ST_PACKET_t *packet, + uint32_t address, + bool read); + +I2C_ST_PACKET_t *i2c_packet_set_address( + I2C_ST_PACKET_t *packet, + int address, + int size); + +I2C_ERR_t i2c_handler_polling(I2C_ST_PACKET_INFO_t *packet_info); + +I2C_ERR_t i2c_initialize( + I2C_ST_PACKET_INFO_t *packet_info, + uint32_t reg_base, + I2C_TYPE type, + const I2C_PARAM_t *param); + +I2C_ERR_t i2c_exec_transfer(I2C_ST_PACKET_INFO_t *packet_info); + +void i2c_disable(I2C_ST_PACKET_INFO_t *packet); + +void i2c_enable(I2C_ST_PACKET_INFO_t *packet_info); + +#endif /* I2C_DRIVER_H */ diff --git a/product/synquacer/module/f_i2c/include/internal/i2c_reg.h b/product/synquacer/module/f_i2c/include/internal/i2c_reg.h new file mode 100644 index 000000000..8ae84cc9d --- /dev/null +++ b/product/synquacer/module/f_i2c/include/internal/i2c_reg.h @@ -0,0 +1,283 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_REG_H +#define I2C_REG_H + +#include + +typedef union { + uint8_t DATA; + struct { + uint32_t FBT : 1; /* B00 First Byte Transfer */ + uint32_t reserved1 : 2; /* B01-02 Reserved */ + uint32_t TRX : 1; /* B03 Transfer/Receive */ + uint32_t LRB : 1; /* B04 LAST Received Bit */ + uint32_t reserved2 : 1; /* B05 Reserved */ + uint32_t RSC : 1; /* B06 Repeated Start Condition */ + uint32_t BB : 1; /* B07 Bus busy */ + } bit_COMMON; + struct { + uint32_t reserved1 : 1; /* B00 Reserved */ + uint32_t GCA : 1; /* B01 General Call Address */ + uint32_t AAS : 1; /* B02 Address As Slave */ + uint32_t reserved2 : 2; /* B03-04 Reserved */ + uint32_t AL : 1; /* B05 Arbitration Lost */ + uint32_t reserved3 : 2; /* B06-07 Reserved */ + } bit_F_I2C; +} I2C_UN_BSR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t reserved1 : 6; /* B00-05 Reserved */ + uint32_t HS : 1; /* B06 Hi Speed Mode */ + uint32_t MAS : 1; /* B07 Master Code */ + } bit_F_I2C_SP1; +} I2C_UN_BS2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t INT : 1; /* B00 INTerrupt */ + uint32_t INTE : 1; /* B01 INTerrupt Enable */ + uint32_t reserved1 : 1; /* B02 Reserved */ + uint32_t ACK : 1; /* B03 Acknowledge Enable */ + uint32_t MSS : 1; /* B04 Master Slave Select 1:Master */ + uint32_t SCC : 1; /* B05 Start Condition Continue */ + uint32_t BEIE : 1; /* B06 Bus Error Interrupt Enable */ + uint32_t BER : 1; /* B07 Bus Error */ + } bit_COMMON; + struct { + uint32_t reserved1 : 2; /* B00-01 Reserved */ + uint32_t GCAA : 1; /* B02 General Call Address Acknowledge */ + uint32_t reserved2 : 5; /* B03-07 Reserved */ + } bit_F_I2C; +} I2C_UN_BCR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t SCLL : 1; /* B00 SCL Low drive */ + uint32_t SDAL : 1; /* B01 SDA Low drive */ + uint32_t reserved1 : 2; /* B02-B03 Reserved */ + uint32_t SCLS : 1; /* B04 SCL Status(Read Only) */ + uint32_t SDAS : 1; /* B05 SDA Status(Read Only) */ + uint32_t reserved2 : 2; /* B06-B07 Reserved */ + } bit_COMMON; + struct { + uint32_t reserved1 : 7; /* B00-07 Reserved */ + uint32_t EN : 1; /* B07 Enable */ + } bit_F_I2C_SP1; +} I2C_UN_BC2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t A : 7; /* B00-B06 Address */ + uint32_t reserved1 : 1; /* B07 Reserved */ + } bit_COMMON; +} I2C_UN_ADR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t D : 8; /* B00-B07 Serial Data */ + } bit_COMMON; +} I2C_UN_DAR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t NF : 5; /* B00-04 Noise Filter Select for Sm/FM/FM+ */ + uint32_t NFH : 3; /* B05-07 Noise Filter Select for Hs */ + } bit_F_I2C_SP1; +} I2C_UN_NFR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TLW : 8; + } bit_F_I2C_SP1; +} I2C_UN_TLWR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TLW : 8; + } bit_F_I2C_SP1; +} I2C_UN_TLW2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t THW : 8; + } bit_F_I2C_SP1; +} I2C_UN_THWR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t THW : 8; + } bit_F_I2C_SP1; +} I2C_UN_THW2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TBF : 8; + } bit_F_I2C_SP1; +} I2C_UN_TBFR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TBF : 8; + } bit_F_I2C_SP1; +} I2C_UN_TBF2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TRS : 8; + } bit_F_I2C_SP1; +} I2C_UN_TRSR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TRS : 8; + } bit_F_I2C_SP1; +} I2C_UN_TRS2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TSH : 8; + } bit_F_I2C_SP1; +} I2C_UN_TSHR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TSH : 8; + } bit_F_I2C_SP1; +} I2C_UN_TSH2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TPS : 8; + } bit_F_I2C_SP1; +} I2C_UN_TPSR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TPS : 8; + } bit_F_I2C_SP1; +} I2C_UN_TPS2R_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TLWH : 8; + } bit_F_I2C_SP1; +} I2C_UN_TLWRH_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t THWH : 8; + } bit_F_I2C_SP1; +} I2C_UN_THWRH_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TRSH : 8; + } bit_F_I2C_SP1; +} I2C_UN_TRSRH_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TSHH : 8; + } bit_F_I2C_SP1; +} I2C_UN_TSHRH_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t TPSH : 8; + } bit_F_I2C_SP1; +} I2C_UN_TPSRH_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t CS : 5; /* B00-B04 Clock Period Select 4-0 */ + uint32_t EN : 1; /* B05 Enable */ + uint32_t FM : 1; /* B06 High Speed Mode */ + uint32_t reserved1 : 1; /* B07 Reserved */ + } bit_F_I2C; +} I2C_UN_CCR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t CS : 6; /* B00-B05 Clock Period Select 10-5 */ + uint32_t TST : 2; /* B06-B07 TST1, TST0 */ + } bit_F_I2C; +} I2C_UN_CSR_t; + +typedef union { + uint8_t DATA; + struct { + uint32_t FS : 4; /* B00-B03 Bus Clock Frequency Select 3-0 */ + uint32_t reserved1 : 4; /* B04-B07 Reserved */ + } bit_F_I2C; +} I2C_UN_FSR_t; + +/*! + * \brief SYNQUACER I2C register address definitions + */ +#define I2C_REG_ADDR_BSR (0x00U) +#define I2C_REG_ADDR_BCR (0x04U) +#define I2C_REG_ADDR_CCR (0x08U) +#define I2C_REG_ADDR_ADR (0x0CU) +#define I2C_REG_ADDR_DAR (0x10U) +#define I2C_REG_ADDR_CSR (0x14U) +#define I2C_REG_ADDR_FSR (0x18U) +#define I2C_REG_ADDR_BC2R (0x1CU) + +#define I2C_SP1_REG_ADDR_BSR ((0x00U) << 2) +#define I2C_SP1_REG_ADDR_BS2R ((0x01U) << 2) +#define I2C_SP1_REG_ADDR_BCR ((0x02U) << 2) +#define I2C_SP1_REG_ADDR_BC2R ((0x03U) << 2) +#define I2C_SP1_REG_ADDR_ADR ((0x04U) << 2) +#define I2C_SP1_REG_ADDR_DAR ((0x05U) << 2) +#define I2C_SP1_REG_ADDR_NFR ((0x06U) << 2) +#define I2C_SP1_REG_ADDR_TLWR ((0x07U) << 2) +#define I2C_SP1_REG_ADDR_TLW2R ((0x08U) << 2) +#define I2C_SP1_REG_ADDR_THWR ((0x09U) << 2) +#define I2C_SP1_REG_ADDR_THW2R ((0x0AU) << 2) +#define I2C_SP1_REG_ADDR_TBFR ((0x0BU) << 2) +#define I2C_SP1_REG_ADDR_TBF2R ((0x0CU) << 2) +#define I2C_SP1_REG_ADDR_TRSR ((0x0DU) << 2) +#define I2C_SP1_REG_ADDR_TRS2R ((0x0EU) << 2) +#define I2C_SP1_REG_ADDR_TSHR ((0x0FU) << 2) +#define I2C_SP1_REG_ADDR_TSH2R ((0x10U) << 2) +#define I2C_SP1_REG_ADDR_TPSR ((0x11U) << 2) +#define I2C_SP1_REG_ADDR_TPS2R ((0x12U) << 2) +#define I2C_SP1_REG_ADDR_TLWRH ((0x13U) << 2) +#define I2C_SP1_REG_ADDR_THWRH ((0x14U) << 2) +#define I2C_SP1_REG_ADDR_TRSRH ((0x15U) << 2) +#define I2C_SP1_REG_ADDR_TSHRH ((0x16U) << 2) +#define I2C_SP1_REG_ADDR_TPSRH ((0x17U) << 2) + +#endif /* I2C_REG_H */ diff --git a/product/synquacer/module/f_i2c/include/internal/i2c_reg_access.h b/product/synquacer/module/f_i2c/include/internal/i2c_reg_access.h new file mode 100644 index 000000000..9df914fe4 --- /dev/null +++ b/product/synquacer/module/f_i2c/include/internal/i2c_reg_access.h @@ -0,0 +1,149 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_REG_ACCESS_H +#define I2C_REG_ACCESS_H + +#include +#include + +/* F_I2C Register Write */ +void f_i2c_write_BSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_BCR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_CCR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_ADR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_DAR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_CSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_FSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_BC2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_write_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + +/* F_I2C Register Read */ +uint8_t f_i2c_read_BSR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_BCR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_CCR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_ADR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_DAR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_CSR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_FSR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_BC2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_read_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info); + +/* F_I2C_SP1 Register Write */ +void f_i2c_sp1_write_BSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_BS2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_BCR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_BC2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_ADR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_DAR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_NFR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TLWR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TLW2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_THWR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_THW2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TBFR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TBF2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TRSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TRS2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TSHR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TSH2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TPSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TPS2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TLWRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_THWRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TRSRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TSHRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_TPSRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); +void f_i2c_sp1_write_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info, + uint8_t value); + +/* F_I2C_SP1 Register Read */ +uint8_t f_i2c_sp1_read_BSR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_BS2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_BCR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_BC2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_ADR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_DAR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_NFR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TLWR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TLW2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_THWR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_THW2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TBFR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TBF2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TRSR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TRS2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TSHR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TSH2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TPSR(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TPS2R(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TLWRH(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_THWRH(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TRSRH(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TSHRH(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_TPSRH(I2C_ST_PACKET_INFO_t *packet_info); +uint8_t f_i2c_sp1_read_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info); + +struct I2C_REG_FUNC_TABLE { + void (*set_BSR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_BS2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_BCR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_BC2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_ADR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_DAR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_NFR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TLWR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TLW2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_THWR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_THW2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TBFR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TBF2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TRSR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TRS2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TSHR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TSH2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TPSR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TPS2R)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TLWRH)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_THWRH)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TRSRH)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TSHRH)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_TPSRH)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_CCR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_CSR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + void (*set_FSR)(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value); + + uint8_t (*get_BSR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_BS2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_BCR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_BC2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_ADR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_DAR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_NFR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TLWR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TLW2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_THWR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_THW2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TBFR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TBF2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TRSR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TRS2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TSHR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TSH2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TPSR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TPS2R)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TLWRH)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_THWRH)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TRSRH)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TSHRH)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_TPSRH)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_CCR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_CSR)(I2C_ST_PACKET_INFO_t *packet_info); + uint8_t (*get_FSR)(I2C_ST_PACKET_INFO_t *packet_info); +}; + +#endif /* I2C_REG_ACCESS_H */ diff --git a/product/synquacer/module/f_i2c/include/mod_f_i2c.h b/product/synquacer/module/f_i2c/include/mod_f_i2c.h new file mode 100644 index 000000000..e70c6b64c --- /dev/null +++ b/product/synquacer/module/f_i2c/include/mod_f_i2c.h @@ -0,0 +1,106 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_F_I2C_H +#define MOD_F_I2C_H + +#include +#include +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupF_I2C F_I2C Driver + * + * \brief SynQuacer F_I2C device driver. + * + * \details This module implements a device driver for the F_I2C + * + * @{ + */ + +/*! + * \brief APIs to access the i2c device. + */ +struct mod_f_i2c_api { + /*! + * \brief APIs to access the i2c device. + * + * \param id Module identifier. + * \param count Pointer to storage for the descriptor table. + * + * \retval I2C_ERR_OK Operation succeeded. + * \return One of the I2C_ERR_t codes described by f_i2c module. + */ + void (*init)(void); + + /*! + * \brief receive data from i2c device + * + * \param ch channel + * \param slave_address slave address + * \param address target address + * \param data buffer to receive the data + * \param length length to read + * + * \retval I2C_ERR_OK Operation succeeded. + * \retval I2C_ERR_PARAM Invalid parameter. + * \retval I2C_ERR_BUSY I2C controller is busy. + * \retval I2C_ERR_BER Bus error. + * \return One of the other specific error codes. + */ + I2C_ERR_t (*recv_data) + (I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + uint8_t *data, + int length); + + /*! + * \brief send data to i2c device + * + * \param ch channel + * \param slave_address slave address + * \param address target address + * \param data buffer to be sent + * \param length length to be sent + * + * \retval I2C_ERR_OK Operation succeeded. + * \retval I2C_ERR_PARAM Invalid parameter. + * \retval I2C_ERR_BUSY I2C controller is busy. + * \retval I2C_ERR_BER Bus error. + * \return One of the other specific error codes. + */ + I2C_ERR_t (*send_data) + (I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + const uint8_t *data, + int length); +}; + +/*! + * \brief F_I2C device configuration data. + */ +struct mod_f_i2c_config { + /*! Base address of the device registers */ + uintptr_t reg_base; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_F_I2C_H */ diff --git a/product/synquacer/module/f_i2c/src/Makefile b/product/synquacer/module/f_i2c/src/Makefile new file mode 100644 index 000000000..39db66699 --- /dev/null +++ b/product/synquacer/module/f_i2c/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := "f_i2c" +BS_LIB_SOURCES = mod_f_i2c.c i2c_api.c i2c_depend.c i2c_driver.c i2c_reg_access.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/f_i2c/src/i2c_api.c b/product/synquacer/module/f_i2c/src/i2c_api.c new file mode 100644 index 000000000..b3ab35f9c --- /dev/null +++ b/product/synquacer/module/f_i2c/src/i2c_api.c @@ -0,0 +1,182 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define FILE_GRP_ID DBG_DRV_I2C +#define MASTER_CODE_VAL 0x04 + +static I2C_ERR_t i2c_api_recv_data_i( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + uint8_t *data, + int length, + int flgid); + +static I2C_ERR_t i2c_api_send_data_i( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + const uint8_t *data, + int length, + int flgid); + +I2C_ERR_t f_i2c_api_initialize( + I2C_ST_PACKET_INFO_t *packet_info, + uint32_t reg_base, + I2C_TYPE type, + const I2C_PARAM_t *param) +{ + I2C_ERR_t ercd = I2C_ERR_OK; + ercd = i2c_initialize(packet_info, reg_base, type, param); + return ercd; +} + +I2C_ERR_t i2c_api_use_hs_mode(I2C_EN_CH_t ch, bool use_hsmode_flag) +{ + I2C_ST_PACKET_INFO_t *packet_info = i2c_get_channel_structure(ch); + + if (packet_info == NULL) + return I2C_ERR_PARAM; + + if (packet_info->TYPE != I2C_TYPE_F_I2C_SP1) + return I2C_ERR_UNAVAILABLE; + + packet_info->USE_HS_MODE = use_hsmode_flag; + return I2C_ERR_OK; +} + +static I2C_ERR_t i2c_api_recv_data_i( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + uint8_t *data, + int length, + int flgid) +{ + I2C_ERR_t ercd = I2C_ERR_OK; + I2C_ST_PACKET_INFO_t *packet_info = i2c_get_channel_structure(ch); + + if (packet_info == NULL) + return I2C_ERR_PARAM; + + i2c_enable(packet_info); + + i2c_packet_initialize(&packet_info->PACKET); + + /* Send master code, only for F_I2C_SP1 */ + if (packet_info->TYPE == I2C_TYPE_F_I2C_SP1) { + if (packet_info->USE_HS_MODE) { + packet_info->MASTER_CODE_FLAG = true; + i2c_packet_set_control( + &packet_info->PACKET, MASTER_CODE_VAL, false); + } + } + + i2c_packet_set_control(&packet_info->PACKET, slave_address, false); + i2c_packet_set_address(&packet_info->PACKET, address, 1); + i2c_packet_set_control(&packet_info->PACKET, slave_address, true); + i2c_packet_set_payload(&packet_info->PACKET, (char *)data, length); + + ercd = i2c_exec_transfer(packet_info); + if ((flgid == 0) && (ercd == I2C_ERR_OK)) + ercd = i2c_handler_polling(packet_info); + + i2c_disable(packet_info); + + return ercd; +} + +I2C_ERR_t f_i2c_api_recv_data( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + uint8_t *data, + int length) +{ + I2C_ERR_t ercd = I2C_ERR_OK; + + if ((slave_address <= 0x03) || (slave_address >= 0x78)) + return I2C_ERR_PARAM; + + if (data == NULL) + return I2C_ERR_PARAM; + + if (length <= 0) + return I2C_ERR_PARAM; + + ercd = i2c_api_recv_data_i( + ch, slave_address, address, data, length, 0x00000000); + + return ercd; +} + +static I2C_ERR_t i2c_api_send_data_i( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + const uint8_t *data, + int length, + int flgid) +{ + I2C_ERR_t ercd = I2C_ERR_OK; + I2C_ST_PACKET_INFO_t *packet_info = i2c_get_channel_structure(ch); + + if (packet_info == NULL) + return I2C_ERR_PARAM; + + i2c_enable(packet_info); + + i2c_packet_initialize(&packet_info->PACKET); + + /* Send master code, only for F_I2C_SP1 */ + if (packet_info->TYPE == I2C_TYPE_F_I2C_SP1) { + if (packet_info->USE_HS_MODE) { + packet_info->MASTER_CODE_FLAG = true; + i2c_packet_set_control( + &packet_info->PACKET, MASTER_CODE_VAL, false); + } + } + + i2c_packet_set_control(&packet_info->PACKET, slave_address, false); + i2c_packet_set_address(&packet_info->PACKET, address, 1); + i2c_packet_set_payload(&packet_info->PACKET, (char *)data, length); + + ercd = i2c_exec_transfer(packet_info); + if ((flgid == 0) && (ercd == I2C_ERR_OK)) + ercd = i2c_handler_polling(packet_info); + + i2c_disable(packet_info); + + return ercd; +} + +I2C_ERR_t f_i2c_api_send_data( + I2C_EN_CH_t ch, + uint32_t slave_address, + uint32_t address, + const uint8_t *data, + int length) +{ + I2C_ERR_t ercd = I2C_ERR_OK; + + if ((slave_address == 0x01) || (slave_address == 0x02) || + (slave_address == 0x03) || (slave_address >= 0x78)) { + return I2C_ERR_PARAM; + } + + if (length < 0) + return I2C_ERR_PARAM; + + ercd = i2c_api_send_data_i( + ch, slave_address, address, data, length, 0x00000000); + + return ercd; +} diff --git a/product/synquacer/module/f_i2c/src/i2c_depend.c b/product/synquacer/module/f_i2c/src/i2c_depend.c new file mode 100644 index 000000000..fe19e57b9 --- /dev/null +++ b/product/synquacer/module/f_i2c/src/i2c_depend.c @@ -0,0 +1,97 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +typedef unsigned int ADDR_T; + +#define SCB_BUILDTIME_ASSERT(x) +#define FILE_GRP_ID DBG_DRV_I2C +#define SCB_Error(x) + +#if CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 0) +static I2C_ST_PACKET_INFO_t m_stI2C0; +#endif /* CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 0) */ + +#if CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 1) +static I2C_ST_PACKET_INFO_t m_stI2C1; +#endif /* CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 1) */ + +#if CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 2) +static I2C_ST_PACKET_INFO_t m_stI2C2; +#endif /* CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 2) */ + +static const ADDR_T i2c_base_addrs[] = CONFIG_SOC_I2C_BASE_ADDRS; +static const I2C_TYPE i2c_types[] = CONFIG_SOC_I2C_TYPES; +static const I2C_EN_CH_t i2c_channels[] = CONFIG_SOC_I2C_CHANNELS; +static const I2C_PARAM_t i2c_params[] = CONFIG_SCB_I2C_PARAMS; + +I2C_ST_PACKET_INFO_t *i2c_get_channel_structure(I2C_EN_CH_t ch) +{ + I2C_ST_PACKET_INFO_t *result = NULL; + + switch (ch) { +#if CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 0) + case I2C_EN_CH0: + result = &m_stI2C0; + break; +#endif /* CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 0) */ + +#if CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 1) + case I2C_EN_CH1: + result = &m_stI2C1; + break; +#endif /* CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 1) */ + +#if CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 2) + case I2C_EN_CH2: + result = &m_stI2C2; + break; +#endif /* CONFIG_SOC_I2C_ENABLE_BITMAP & (1 << 2) */ + + default: + result = NULL; + break; + } + + return result; +} + +void i2c_construction(void) +{ + I2C_ERR_t i2c_err; + size_t i; + + /* Check config consistency */ + SCB_BUILDTIME_ASSERT( + FWK_ARRAY_SIZE(i2c_types) == FWK_ARRAY_SIZE(i2c_base_addrs)); + SCB_BUILDTIME_ASSERT( + FWK_ARRAY_SIZE(i2c_channels) == FWK_ARRAY_SIZE(i2c_base_addrs)); + SCB_BUILDTIME_ASSERT( + FWK_ARRAY_SIZE(i2c_params) == FWK_ARRAY_SIZE(i2c_base_addrs)); + + for (i = 0; i < FWK_ARRAY_SIZE(i2c_params); i++) { + i2c_err = f_i2c_api_initialize( + i2c_get_channel_structure(i2c_channels[i]), + i2c_base_addrs[i], + i2c_types[i], + &i2c_params[i]); + if (i2c_err != I2C_ERR_OK) { + SCB_Error(i2c_err); + SYNQUACER_DEV_LOG_ERROR("[I2C] I2C ch#%d initialize error.\n", i); + } + } +} + +void i2c_destruction(void) +{ +} diff --git a/product/synquacer/module/f_i2c/src/i2c_driver.c b/product/synquacer/module/f_i2c/src/i2c_driver.c new file mode 100644 index 000000000..19c6bc4aa --- /dev/null +++ b/product/synquacer/module/f_i2c/src/i2c_driver.c @@ -0,0 +1,703 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#define FILE_GRP_ID DBG_DRV_I2C + +#define DEBUG_PrintError(...) + +struct I2C_REG_FUNC_TABLE tables[2] = { + { f_i2c_write_BSR, f_i2c_write_UNDEFINED, f_i2c_write_BCR, + f_i2c_write_BC2R, f_i2c_write_ADR, f_i2c_write_DAR, + f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, + f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, + f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, + f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, + f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, + f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, f_i2c_write_UNDEFINED, + f_i2c_write_CCR, f_i2c_write_CSR, f_i2c_write_FSR, + + f_i2c_read_BSR, f_i2c_read_UNDEFINED, f_i2c_read_BCR, + f_i2c_read_BC2R, f_i2c_read_ADR, f_i2c_read_DAR, + f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, + f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, + f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, + f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, + f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, + f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, f_i2c_read_UNDEFINED, + f_i2c_read_CCR, f_i2c_read_CSR, f_i2c_read_FSR }, + + { f_i2c_sp1_write_BSR, f_i2c_sp1_write_BS2R, + f_i2c_sp1_write_BCR, f_i2c_sp1_write_BC2R, + f_i2c_sp1_write_ADR, f_i2c_sp1_write_DAR, + f_i2c_sp1_write_NFR, f_i2c_sp1_write_TLWR, + f_i2c_sp1_write_TLW2R, f_i2c_sp1_write_THWR, + f_i2c_sp1_write_THW2R, f_i2c_sp1_write_TBFR, + f_i2c_sp1_write_TBF2R, f_i2c_sp1_write_TRSR, + f_i2c_sp1_write_TRS2R, f_i2c_sp1_write_TSHR, + f_i2c_sp1_write_TSH2R, f_i2c_sp1_write_TPSR, + f_i2c_sp1_write_TPS2R, f_i2c_sp1_write_TLWRH, + f_i2c_sp1_write_THWRH, f_i2c_sp1_write_TRSRH, + f_i2c_sp1_write_TSHRH, f_i2c_sp1_write_TPSRH, + f_i2c_sp1_write_UNDEFINED, f_i2c_sp1_write_UNDEFINED, + f_i2c_sp1_write_UNDEFINED, + + f_i2c_sp1_read_BSR, f_i2c_sp1_read_BS2R, + f_i2c_sp1_read_BCR, f_i2c_sp1_read_BC2R, + f_i2c_sp1_read_ADR, f_i2c_sp1_read_DAR, + f_i2c_sp1_read_NFR, f_i2c_sp1_read_TLWR, + f_i2c_sp1_read_TLW2R, f_i2c_sp1_read_THWR, + f_i2c_sp1_read_THW2R, f_i2c_sp1_read_TBFR, + f_i2c_sp1_read_TBF2R, f_i2c_sp1_read_TRSR, + f_i2c_sp1_read_TRS2R, f_i2c_sp1_read_TSHR, + f_i2c_sp1_read_TSH2R, f_i2c_sp1_read_TPSR, + f_i2c_sp1_read_TPS2R, f_i2c_sp1_read_TLWRH, + f_i2c_sp1_read_THWRH, f_i2c_sp1_read_TRSRH, + f_i2c_sp1_read_TSHRH, f_i2c_sp1_read_TPSRH, + f_i2c_sp1_read_UNDEFINED, f_i2c_sp1_read_UNDEFINED, + f_i2c_sp1_read_UNDEFINED } +}; + +#define SET_BSR(VAL) i2c_reg->set_BSR(packet_info, (VAL)) +#define SET_BS2R(VAL) i2c_reg->set_BS2R(packet_info, (VAL)) +#define SET_BCR(VAL) i2c_reg->set_BCR(packet_info, (VAL)) +#define SET_BC2R(VAL) i2c_reg->set_BC2R(packet_info, (VAL)) +#define SET_ADR(VAL) i2c_reg->set_ADR(packet_info, (VAL)) +#define SET_DAR(VAL) i2c_reg->set_DAR(packet_info, (VAL)) +#define SET_NFR(VAL) i2c_reg->set_NFR(packet_info, (VAL)) +#define SET_TLWR(VAL) i2c_reg->set_TLWR(packet_info, (VAL)) +#define SET_TLW2R(VAL) i2c_reg->set_TLW2R(packet_info, (VAL)) +#define SET_THWR(VAL) i2c_reg->set_THWR(packet_info, (VAL)) +#define SET_THW2R(VAL) i2c_reg->set_THW2R(packet_info, (VAL)) +#define SET_TBFR(VAL) i2c_reg->set_TBFR(packet_info, (VAL)) +#define SET_TBF2R(VAL) i2c_reg->set_TBF2R(packet_info, (VAL)) +#define SET_TRSR(VAL) i2c_reg->set_TRSR(packet_info, (VAL)) +#define SET_TRS2R(VAL) i2c_reg->set_TRS2R(packet_info, (VAL)) +#define SET_TSHR(VAL) i2c_reg->set_TSHR(packet_info, (VAL)) +#define SET_TSH2R(VAL) i2c_reg->set_TSH2R(packet_info, (VAL)) +#define SET_TPSR(VAL) i2c_reg->set_TPSR(packet_info, (VAL)) +#define SET_TPS2R(VAL) i2c_reg->set_TPS2R(packet_info, (VAL)) +#define SET_TLWRH(VAL) i2c_reg->set_TLWRH(packet_info, (VAL)) +#define SET_THWRH(VAL) i2c_reg->set_THWRH(packet_info, (VAL)) +#define SET_TRSRH(VAL) i2c_reg->set_TRSRH(packet_info, (VAL)) +#define SET_TSHRH(VAL) i2c_reg->set_TSHRH(packet_info, (VAL)) +#define SET_TPSRH(VAL) i2c_reg->set_TPSRH(packet_info, (VAL)) +#define SET_CCR(VAL) i2c_reg->set_CCR(packet_info, (VAL)) +#define SET_CSR(VAL) i2c_reg->set_CSR(packet_info, (VAL)) +#define SET_FSR(VAL) i2c_reg->set_FSR(packet_info, (VAL)) + +#define GET_BSR() i2c_reg->get_BSR(packet_info) +#define GET_BS2R() i2c_reg->get_BSR(packet_info) +#define GET_BCR() i2c_reg->get_BCR(packet_info) +#define GET_BC2R() i2c_reg->get_BC2R(packet_info) +#define GET_ADR() i2c_reg->get_ADR(packet_info) +#define GET_DAR() i2c_reg->get_DAR(packet_info) +#define GET_NFR() i2c_reg->get_NFR(packet_info) +#define GET_TLWR() i2c_reg->get_TLWR(packet_info) +#define GET_TLW2R() i2c_reg->get_TLW2R(packet_info) +#define GET_THWR() i2c_reg->get_THWR(packet_info) +#define GET_THW2R() i2c_reg->get_THW2R(packet_info) +#define GET_TBFR() i2c_reg->get_TBFR(packet_info) +#define GET_TBF2R() i2c_reg->get_TBF2R(packet_info) +#define GET_TRSR() i2c_reg->get_TRSR(packet_info) +#define GET_TRS2R() i2c_reg->get_TRS2R(packet_info) +#define GET_TSHR() i2c_reg->get_TSHR(packet_info) +#define GET_TSH2R() i2c_reg->get_TSH2R(packet_info) +#define GET_TPSR() i2c_reg->get_TPSR(packet_info) +#define GET_TPS2R() i2c_reg->get_TPS2R(packet_info) +#define GET_TLWRH() i2c_reg->get_TLWRH(packet_info) +#define GET_THWRH() i2c_reg->get_THWRH(packet_info) +#define GET_TRSRH() i2c_reg->get_TRSRH(packet_info) +#define GET_TSHRH() i2c_reg->get_TSHRH(packet_info) +#define GET_TPSRH() i2c_reg->get_TPSRH(packet_info) +#define GET_CCR() i2c_reg->get_CCR(packet_info) +#define GET_CSR() i2c_reg->get_CSR(packet_info) +#define GET_FSR() i2c_reg->get_FSR(packet_info) + +static inline bool i2c_fifo_isfull(I2C_ST_FIFO_t *instance) +{ + return (instance->LIMIT == instance->SIZE); +} + +static inline bool i2c_fifo_islimit(I2C_ST_FIFO_t *instance) +{ + return (instance->INDEX == instance->LIMIT); +} + +static inline bool i2c_fifo_isnextlimit(I2C_ST_FIFO_t *instance) +{ + return ((instance->INDEX + 1) >= instance->LIMIT); +} + +static inline void i2c_fifo_initialize(I2C_ST_FIFO_t *instance) +{ + instance->LIMIT = instance->INDEX = 0; +} + +static I2C_ST_FIFO_t *i2c_fifo_registry( + I2C_ST_FIFO_t *instance, + char *buf, + bool *attribute, + int size) +{ + instance->BUFF = buf; + instance->ATTR = attribute; + instance->SIZE = size; + i2c_fifo_initialize(instance); + + return instance; +} + +static bool i2c_fifo_push_data(I2C_ST_FIFO_t *instance, char data, bool attr) +{ + bool bFull = i2c_fifo_isfull(instance); + + if (!bFull) { + if (instance->BUFF) + instance->BUFF[instance->LIMIT] = data; + if (instance->ATTR) + instance->ATTR[instance->LIMIT] = attr; + ++instance->LIMIT; + } + + return !bFull; +} + +static bool i2c_fifo_get_send_data( + I2C_ST_FIFO_t *instance, + char *data, + bool *attr) +{ + bool limit = i2c_fifo_islimit(instance); + + if (!limit) { + *data = (instance->BUFF) ? instance->BUFF[instance->INDEX] : 0x00; + *attr = (instance->ATTR) ? instance->ATTR[instance->INDEX] : false; + ++instance->INDEX; + } + + return !limit; +} + +static bool i2c_fifo_put_recv_data( + I2C_ST_FIFO_t *instance, + char data, bool attr) +{ + bool limit = i2c_fifo_islimit(instance); + + if (!limit) { + if (instance->BUFF) + instance->BUFF[instance->INDEX] = data; + if (instance->ATTR) + instance->ATTR[instance->INDEX] = attr; + ++instance->INDEX; + } + + return !limit; +} + +I2C_ST_PACKET_t *i2c_packet_initialize(I2C_ST_PACKET_t *packet) +{ + i2c_fifo_initialize(&packet->CTRL); + i2c_fifo_initialize(&packet->DATA); + + return packet; +} + +I2C_ST_PACKET_t *i2c_packet_set_payload( + I2C_ST_PACKET_t *packet, + char *buf, + int size) +{ + i2c_fifo_registry(&packet->DATA, buf, NULL, size); + packet->DATA.LIMIT = size; + + return packet; +} + +I2C_ST_PACKET_t *i2c_packet_set_control( + I2C_ST_PACKET_t *packet, + uint32_t address, + bool read) +{ + I2C_UN_SLVADDR_t addr = { 0 }; + + addr.DATA = 0; + + addr.bit.BITFIELD_READ = read; + addr.bit.BITFIELD_ADDR = (uint8_t)address; + i2c_fifo_push_data(&packet->CTRL, (char)addr.DATA, true); + + return packet; +} + +I2C_ST_PACKET_t *i2c_packet_set_address( + I2C_ST_PACKET_t *packet, + int address, + int size) +{ + switch (size) { + case 4: + i2c_fifo_push_data(&packet->CTRL, (char)(address >> 24), false); + /* fallthrough */ + case 3: + i2c_fifo_push_data(&packet->CTRL, (char)(address >> 16), false); + /* fallthrough */ + case 2: + i2c_fifo_push_data(&packet->CTRL, (char)(address >> 8), false); + /* fallthrough */ + case 1: + i2c_fifo_push_data(&packet->CTRL, (char)(address >> 0), false); + break; + default: + packet = NULL; + break; + } + + return packet; +} + +static bool i2c_packet_get_send_data( + I2C_ST_PACKET_t *packet, + char *data, + bool *attr) +{ + bool result; + + if (i2c_fifo_islimit(&packet->CTRL)) + result = i2c_fifo_get_send_data(&packet->DATA, data, attr); + else + result = i2c_fifo_get_send_data(&packet->CTRL, data, attr); + + return result; +} + +static bool i2c_packet_put_recv_data(I2C_ST_PACKET_t *packet, char data) +{ + bool result = i2c_fifo_put_recv_data(&packet->DATA, data, false); + + return result; +} + +static bool i2c_handler_buserror( + I2C_ST_PACKET_INFO_t *packet_info, + const I2C_UN_BSR_t *bsr_reg, + I2C_UN_BCR_t *bcr_reg) +{ + bool result = false; + + if (packet_info->MASTER_CODE_FLAG) { + packet_info->MASTER_CODE_FLAG = false; + if (!(bsr_reg->bit_COMMON.LRB)) + result = true; + } + + return result; +} + +static bool i2c_handler_normal( + I2C_ST_PACKET_INFO_t *packet_info, + const I2C_UN_BSR_t *bsr_reg, + I2C_UN_BCR_t *bcr_reg, + bool *timeout, + bool *nak_detect) +{ + bool result = false; + char data; + bool attr; + uint32_t count = 0; + + *timeout = false; + *nak_detect = false; + + struct I2C_REG_FUNC_TABLE *i2c_reg = &tables[packet_info->TYPE]; + + if (bcr_reg->bit_COMMON.MSS) { + if (packet_info->MASTER_CODE_FLAG) { + I2C_UN_BS2R_t unBS2R = { 0 }; + packet_info->MASTER_CODE_FLAG = 0; + unBS2R.DATA = GET_BS2R(); + if (!(unBS2R.bit_F_I2C_SP1.MAS)) { + bcr_reg->bit_COMMON.MSS = 0; + } else if ( + i2c_packet_get_send_data(&packet_info->PACKET, &data, &attr) == + false) { + bcr_reg->bit_COMMON.MSS = 0; + } else { + do { + unBS2R.DATA = GET_BS2R(); + __DSB(); + count++; + if (count > I2C_POLLING_LIMIT) { + DEBUG_PrintError( + "Error in %s. polling timeout " + "occurred. BS2R=0x%02x", + __func__, + unBS2R.DATA); + *timeout = true; + return false; + } + } while (!(unBS2R.bit_F_I2C_SP1.HS)); + + bcr_reg->bit_COMMON.SCC = attr ? 1 : 0; + SET_DAR(data); + __DSB(); + } + } else if (bsr_reg->bit_COMMON.TRX) { + if (bsr_reg->bit_COMMON.LRB) { + bcr_reg->bit_COMMON.MSS = 0; + *nak_detect = true; + } else if ( + i2c_packet_get_send_data(&packet_info->PACKET, &data, &attr) == + false) { + bcr_reg->bit_COMMON.MSS = 0; + } else { + bcr_reg->bit_COMMON.SCC = attr ? 1 : 0; + SET_DAR(data); + __DSB(); + } + } else { + if (bsr_reg->bit_COMMON.FBT) { + bcr_reg->bit_COMMON.ACK = + i2c_fifo_isnextlimit(&packet_info->PACKET.DATA) ? + 0 /*NAK*/ : + 1 /*ACK*/; + } else if ( + i2c_packet_put_recv_data( + &packet_info->PACKET, (char)GET_DAR()) == false) { + /* Buffer Full */ + bcr_reg->bit_COMMON.MSS = 0; /* issue STOP CONDITION */ + } else { + bcr_reg->bit_COMMON.MSS = + i2c_fifo_islimit(&packet_info->PACKET.DATA) ? 0 /*SC*/ : + 1 /*---*/; + bcr_reg->bit_COMMON.ACK = + i2c_fifo_isnextlimit(&packet_info->PACKET.DATA) ? + 0 /*NAK*/ : + 1 /*ACK*/; + } + } + + if (bcr_reg->bit_COMMON.MSS == 0) + result = true; + + } else { + /* %MN0 SLAVE MODE is not supported */ + } + + return result; +} + +void i2c_enable(I2C_ST_PACKET_INFO_t *packet_info) +{ + struct I2C_REG_FUNC_TABLE *i2c_reg = &tables[packet_info->TYPE]; + + I2C_UN_BCR_t bcr_reg = { 0 }; + bcr_reg.DATA = GET_BCR(); + + bcr_reg.bit_COMMON.BER = 0; /* Clear bus error status */ + SET_BCR(bcr_reg.DATA); + __DSB(); + + if (packet_info->TYPE == I2C_TYPE_F_I2C_SP1) { + I2C_UN_BC2R_t unBC2R = { 0 }; + unBC2R.DATA = GET_BC2R(); + unBC2R.bit_F_I2C_SP1.EN = 1; + SET_BC2R(unBC2R.DATA); + } else { + I2C_UN_CCR_t unCCR = { 0 }; + unCCR.DATA = GET_CCR(); + unCCR.bit_F_I2C.EN = 1; + SET_CCR(unCCR.DATA); + } + __DSB(); + + return; +} + +static uint32_t i2c_handler_common( + I2C_ST_PACKET_INFO_t *packet_info, + const I2C_UN_BSR_t *bsr_reg, + I2C_UN_BCR_t *bcr_reg) +{ + uint32_t result = 0; + volatile uint8_t tmp; + bool tmp_BER = false; + bool timeout = false; + bool nak_detect = false; + + struct I2C_REG_FUNC_TABLE *i2c_reg = &tables[packet_info->TYPE]; + + if (bcr_reg->bit_COMMON.BER) { /* Bus Error */ + tmp_BER = true; + + if (i2c_handler_buserror(packet_info, bsr_reg, bcr_reg)) + result = I2C_EN_EVF_MC_BUSERROR; + else + result = I2C_EN_EVF_BUSERROR; + + } else if (bcr_reg->bit_COMMON.INT) { /* Normal Interrupt */ + if (i2c_handler_normal( + packet_info, bsr_reg, bcr_reg, &timeout, &nak_detect)) { + result = I2C_EN_EVF_FINISH; + } + + if (timeout) + result = I2C_EN_EVF_TIMEOUT; + if (nak_detect) + result = I2C_EN_EVF_NAK; + } + + /* clear interrupt cause */ + bcr_reg->bit_COMMON.BER = 0; + bcr_reg->bit_COMMON.INT = 0; + SET_BCR(bcr_reg->DATA); + __DSB(); + + if (tmp_BER) + i2c_enable(packet_info); + + /*===== [Important] T_PLINTR : INTR delays 3PCLK CYCLE =====*/ + tmp = GET_BSR(); /* read interrupt status */ + tmp = GET_BSR(); /* read interrupt status */ + tmp = GET_BSR(); /* read interrupt status */ + (void)tmp; + + return result; +} + +I2C_ERR_t i2c_handler_polling(I2C_ST_PACKET_INFO_t *packet_info) +{ + I2C_UN_BSR_t bsr_reg = { 0 }; /* +00H BSR BUS STATUS REGISTER */ + I2C_UN_BCR_t bcr_reg = { 0 }; /* +04H BCR BUS CONTROL REGISTER */ + uint32_t result; + I2C_ERR_t ercd = I2C_ERR_OK; + uint32_t count = 0; + + struct I2C_REG_FUNC_TABLE *i2c_reg = &tables[packet_info->TYPE]; + + for (result = 0; result == 0; /*nop*/) { + do { + bcr_reg.DATA = GET_BCR(); + __DSB(); + count++; + if (count > I2C_POLLING_LIMIT) { + DEBUG_PrintError( + "Error in %s. polling timeout occurred. " + "BCR=0x%02x", + __func__, + bcr_reg.DATA); + return I2C_ERR_POLLING; + } + } while (!(bcr_reg.bit_COMMON.BER || bcr_reg.bit_COMMON.INT)); + bsr_reg.DATA = GET_BSR(); + result = i2c_handler_common(packet_info, &bsr_reg, &bcr_reg); + } + + switch (result) { + case I2C_EN_EVF_BUSERROR: + ercd = I2C_ERR_BER; + break; + case I2C_EN_EVF_MC_BUSERROR: + ercd = I2C_ERR_BER_MC; + break; + case I2C_EN_EVF_TIMEOUT: + ercd = I2C_ERR_POLLING; + break; + case I2C_EN_EVF_NAK: + ercd = I2C_ERR_UNAVAILABLE; + break; + default: + break; + } + + return ercd; +} + +I2C_ERR_t i2c_initialize( + I2C_ST_PACKET_INFO_t *packet_info, + uint32_t reg_base, + I2C_TYPE enType, + const I2C_PARAM_t *param) +{ + I2C_UN_BCR_t bcr_reg = { 0 }; /* +04H BCR BUS CONTROL REGISTER */ + struct I2C_REG_FUNC_TABLE *i2c_reg; + + if (packet_info == NULL) + return I2C_ERR_PARAM; + + if (reg_base == 0) + return I2C_ERR_PARAM; + + if ((enType != I2C_TYPE_F_I2C) && (enType != I2C_TYPE_F_I2C_SP1)) + return I2C_ERR_PARAM; + + if (param == NULL) + return I2C_ERR_PARAM; + + packet_info->I2C_BASE_ADDR = reg_base; + packet_info->TYPE = enType; + i2c_reg = &tables[enType]; + + i2c_fifo_registry( + &packet_info->PACKET.CTRL, + packet_info->CTRL_BUFF, + packet_info->CTRL_ATTR, + sizeof(packet_info->CTRL_BUFF)); + + if (enType == I2C_TYPE_F_I2C) { + I2C_UN_FSR_t unFSR = { 0 }; + I2C_UN_CSR_t unCSR = { 0 }; + I2C_UN_CCR_t unCCR = { 0 }; + + unFSR.DATA = GET_FSR(); + unFSR.bit_F_I2C.FS = param->I2C_PARAM_F_I2C.FSR_FS; + SET_FSR(unFSR.DATA); + + unCSR.DATA = GET_CSR(); + unCSR.bit_F_I2C.CS = param->I2C_PARAM_F_I2C.CSR_CS; + SET_CSR(unCSR.DATA); + + unCCR.DATA = GET_CCR(); + unCCR.bit_F_I2C.CS = param->I2C_PARAM_F_I2C.CCR_CS; + unCCR.bit_F_I2C.FM = param->I2C_PARAM_F_I2C.CCR_FM; + SET_CCR(unCCR.DATA); + } else { + I2C_UN_NFR_t unNFR = { 0 }; + uint8_t tmp = 0; + + unNFR.bit_F_I2C_SP1.NF = param->I2C_PARAM_F_I2C_SP1.NFR_NF; + unNFR.bit_F_I2C_SP1.NFH = param->I2C_PARAM_F_I2C_SP1.NFR_NFH; + SET_NFR(unNFR.DATA); + + tmp = param->I2C_PARAM_F_I2C_SP1.TLWR_TLW; + SET_TLWR(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TLW2R_TLW; + SET_TLW2R(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.THWR_THW; + SET_THWR(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.THW2R_THW; + SET_THW2R(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TBFR_TBF; + SET_TBFR(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TBF2R_TBF; + SET_TBF2R(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TRSR_TRS; + SET_TRSR(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TRS2R_TRS; + SET_TRS2R(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TSHR_TSH; + SET_TSHR(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TSH2R_TSH; + SET_TSH2R(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TPSR_TPS; + SET_TPSR(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TPS2R_TPS; + SET_TPS2R(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TLWRH_TLWH; + SET_TLWRH(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.THWRH_THWH; + SET_THWRH(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TRSRH_TRSH; + SET_TRSRH(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TSHRH_TSHH; + SET_TSHRH(tmp); + + tmp = param->I2C_PARAM_F_I2C_SP1.TPSRH_TPSH; + SET_TPSRH(tmp); + } + __DSB(); + + /* + * i2c_enable() is moved to each i2c access function + */ + + bcr_reg.DATA = GET_BCR(); + bcr_reg.bit_COMMON.INTE = 0; + bcr_reg.bit_COMMON.BEIE = 0; + SET_BCR(bcr_reg.DATA); + __DSB(); + + return I2C_ERR_OK; +} + +I2C_ERR_t i2c_exec_transfer(I2C_ST_PACKET_INFO_t *packet_info) +{ + I2C_UN_BCR_t bcr_reg = { 0 }; /* +04H BCR BUS CONTROL REGISTER */ + char data; + bool attr; + uint32_t count = 0; + + struct I2C_REG_FUNC_TABLE *i2c_reg = &tables[packet_info->TYPE]; + + if (i2c_packet_get_send_data(&packet_info->PACKET, &data, &attr)) { + I2C_UN_BSR_t bsr_reg = { 0 }; /* +00H BSR BUS STATUS REGISTER */ + do { + bsr_reg.DATA = GET_BSR(); + __DSB(); + count++; + if (count > I2C_POLLING_LIMIT) { + DEBUG_PrintError( + "Error in %s. polling timeout occurred. " + "BSR=0x%02x", + __func__, + bsr_reg.DATA); + return I2C_ERR_POLLING; + } + } while (bsr_reg.bit_COMMON.BB); + SET_DAR(data); + __DSB(); + bcr_reg.DATA = GET_BCR(); + bcr_reg.bit_COMMON.MSS = 1; /* I2C=MASTER MODE */ + SET_BCR(bcr_reg.DATA); + __DSB(); + } + + return I2C_ERR_OK; +} + +void i2c_disable(I2C_ST_PACKET_INFO_t *packet_info) +{ + struct I2C_REG_FUNC_TABLE *i2c_reg = &tables[packet_info->TYPE]; + + if (packet_info->TYPE == I2C_TYPE_F_I2C_SP1) { + I2C_UN_BC2R_t unBC2R = { 0 }; + unBC2R.DATA = GET_BC2R(); + unBC2R.bit_F_I2C_SP1.EN = 0; + SET_BC2R(unBC2R.DATA); + } else { + I2C_UN_CCR_t unCCR = { 0 }; + unCCR.DATA = GET_BC2R(); + unCCR.bit_F_I2C.EN = 0; + SET_CCR(unCCR.DATA); + } + __DSB(); + + return; +} diff --git a/product/synquacer/module/f_i2c/src/i2c_reg_access.c b/product/synquacer/module/f_i2c/src/i2c_reg_access.c new file mode 100644 index 000000000..eb087e21b --- /dev/null +++ b/product/synquacer/module/f_i2c/src/i2c_reg_access.c @@ -0,0 +1,341 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static inline void i2c_write_reg( + uint32_t base_addr, + uint32_t reg_addr, + uint8_t value) +{ + *((volatile uint8_t *)(base_addr + reg_addr)) = value; +} + +static inline uint8_t i2c_read_reg(uint32_t base_addr, uint32_t reg_addr) +{ + return *((volatile uint8_t *)(base_addr + reg_addr)); +} + +/* F_I2C Register Write */ +void f_i2c_write_BSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_BSR, value); + return; +} +void f_i2c_write_BCR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_BCR, value); + return; +} +void f_i2c_write_CCR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_CCR, value); + return; +} +void f_i2c_write_ADR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_ADR, value); + return; +} +void f_i2c_write_DAR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_DAR, value); + return; +} +void f_i2c_write_CSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_CSR, value); + return; +} +void f_i2c_write_FSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_FSR, value); + return; +} +void f_i2c_write_BC2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_BC2R, value); + return; +} +void f_i2c_write_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + while (1) + ; +} + +/* F_I2C Register Read */ +uint8_t f_i2c_read_BSR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_BSR); +} +uint8_t f_i2c_read_BCR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_BCR); +} +uint8_t f_i2c_read_CCR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_CCR); +} +uint8_t f_i2c_read_ADR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_ADR); +} +uint8_t f_i2c_read_DAR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_DAR); +} +uint8_t f_i2c_read_CSR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_CSR); +} +uint8_t f_i2c_read_FSR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_FSR); +} +uint8_t f_i2c_read_BC2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_REG_ADDR_BC2R); +} +uint8_t f_i2c_read_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info) +{ + while (1) + ; +} + +/* F_I2C_SP1 Register Write */ +void f_i2c_sp1_write_BSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BSR, value); + return; +} +void f_i2c_sp1_write_BS2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BS2R, value); + return; +} +void f_i2c_sp1_write_BCR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BCR, value); + return; +} +void f_i2c_sp1_write_BC2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BC2R, value); + return; +} +void f_i2c_sp1_write_ADR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_ADR, value); + return; +} +void f_i2c_sp1_write_DAR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_DAR, value); + return; +} +void f_i2c_sp1_write_NFR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_NFR, value); + return; +} +void f_i2c_sp1_write_TLWR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TLWR, value); + return; +} +void f_i2c_sp1_write_TLW2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TLW2R, value); + return; +} +void f_i2c_sp1_write_THWR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_THWR, value); + return; +} +void f_i2c_sp1_write_THW2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_THW2R, value); + return; +} +void f_i2c_sp1_write_TBFR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TBFR, value); + return; +} +void f_i2c_sp1_write_TBF2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TBF2R, value); + return; +} +void f_i2c_sp1_write_TRSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TRSR, value); + return; +} +void f_i2c_sp1_write_TRS2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TRS2R, value); + return; +} +void f_i2c_sp1_write_TSHR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TSHR, value); + return; +} +void f_i2c_sp1_write_TSH2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TSH2R, value); + return; +} +void f_i2c_sp1_write_TPSR(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TPSR, value); + return; +} +void f_i2c_sp1_write_TPS2R(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TPS2R, value); + return; +} +void f_i2c_sp1_write_TLWRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TLWRH, value); + return; +} +void f_i2c_sp1_write_THWRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_THWRH, value); + return; +} +void f_i2c_sp1_write_TRSRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TRSRH, value); + return; +} +void f_i2c_sp1_write_TSHRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TSHRH, value); + return; +} +void f_i2c_sp1_write_TPSRH(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + i2c_write_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TPSRH, value); + return; +} +void f_i2c_sp1_write_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info, uint8_t value) +{ + while (1) + ; +} + +/* F_I2C_SP1 Register Read */ +uint8_t f_i2c_sp1_read_BSR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BSR); +} +uint8_t f_i2c_sp1_read_BS2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BS2R); +} +uint8_t f_i2c_sp1_read_BCR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BCR); +} +uint8_t f_i2c_sp1_read_BC2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_BC2R); +} +uint8_t f_i2c_sp1_read_ADR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_ADR); +} +uint8_t f_i2c_sp1_read_DAR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_DAR); +} +uint8_t f_i2c_sp1_read_NFR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_NFR); +} +uint8_t f_i2c_sp1_read_TLWR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TLWR); +} +uint8_t f_i2c_sp1_read_TLW2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TLW2R); +} +uint8_t f_i2c_sp1_read_THWR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_THWR); +} +uint8_t f_i2c_sp1_read_THW2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_THW2R); +} +uint8_t f_i2c_sp1_read_TBFR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TBFR); +} +uint8_t f_i2c_sp1_read_TBF2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TBF2R); +} +uint8_t f_i2c_sp1_read_TRSR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TRSR); +} +uint8_t f_i2c_sp1_read_TRS2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TRS2R); +} +uint8_t f_i2c_sp1_read_TSHR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TSHR); +} +uint8_t f_i2c_sp1_read_TSH2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TSH2R); +} +uint8_t f_i2c_sp1_read_TPSR(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TPSR); +} +uint8_t f_i2c_sp1_read_TPS2R(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TPS2R); +} +uint8_t f_i2c_sp1_read_TLWRH(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TLWRH); +} +uint8_t f_i2c_sp1_read_THWRH(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_THWRH); +} +uint8_t f_i2c_sp1_read_TRSRH(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TRSRH); +} +uint8_t f_i2c_sp1_read_TSHRH(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TSHRH); +} +uint8_t f_i2c_sp1_read_TPSRH(I2C_ST_PACKET_INFO_t *packet_info) +{ + return i2c_read_reg(packet_info->I2C_BASE_ADDR, I2C_SP1_REG_ADDR_TPSRH); +} +uint8_t f_i2c_sp1_read_UNDEFINED(I2C_ST_PACKET_INFO_t *packet_info) +{ + while (1) + ; +} diff --git a/product/synquacer/module/f_i2c/src/mod_f_i2c.c b/product/synquacer/module/f_i2c/src/mod_f_i2c.c new file mode 100644 index 000000000..a49c58bc8 --- /dev/null +++ b/product/synquacer/module/f_i2c/src/mod_f_i2c.c @@ -0,0 +1,68 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mod_f_i2c_api module_api = { + .init = i2c_construction, + .recv_data = f_i2c_api_recv_data, + .send_data = f_i2c_api_send_data, +}; + +/* + * Framework handlers + */ + +static int f_i2c_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + return FWK_SUCCESS; +} + +static int f_i2c_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + +static int f_i2c_process_bind_request( + fwk_id_t requester_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + *api = &module_api; + + return FWK_SUCCESS; +} + +static int f_i2c_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +const struct fwk_module module_f_i2c = { + .name = "f_i2c", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = f_i2c_init, + .element_init = f_i2c_element_init, + .start = f_i2c_start, + .process_bind_request = f_i2c_process_bind_request, +}; diff --git a/product/synquacer/module/f_uart3/include/mod_f_uart3.h b/product/synquacer/module/f_uart3/include/mod_f_uart3.h new file mode 100644 index 000000000..190eb00c6 --- /dev/null +++ b/product/synquacer/module/f_uart3/include/mod_f_uart3.h @@ -0,0 +1,57 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_F_UART3_H +#define MOD_F_UART3_H + +#include +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupF_UART3 F_UART3 Driver + * + * \brief SynQuacer F_UART3 device driver. + * + * \details This module implements a device driver for the F_UART3 + * + * @{ + */ + +/*! + * \brief F_UART3 device configuration data. + */ +struct mod_f_uart3_device_config { + /*! Base address of the device registers */ + uintptr_t reg_base; + + /*! Base address of the DivLatch access device registers */ + uintptr_t dla_reg_base; + + /*! Baud rate (bits per second) */ + unsigned int baud_rate_bps; + + /*! Reference clock (Hertz) */ + uint64_t clock_rate_hz; + + /*! Identifier of the clock that this device depends on */ + fwk_id_t clock_id; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_F_UART3_H */ diff --git a/product/synquacer/module/f_uart3/src/Makefile b/product/synquacer/module/f_uart3/src/Makefile new file mode 100644 index 000000000..32f0861be --- /dev/null +++ b/product/synquacer/module/f_uart3/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := "f_uart3" +BS_LIB_SOURCES = mod_f_uart3.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/f_uart3/src/f_uart3.h b/product/synquacer/module/f_uart3/src/f_uart3.h new file mode 100644 index 000000000..ffefa6801 --- /dev/null +++ b/product/synquacer/module/f_uart3/src/f_uart3.h @@ -0,0 +1,154 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef F_UART3_H +#define F_UART3_H + +#include +#include + +/* Normal mode registers */ +struct f_uart3_reg { + FWK_RW uint32_t RFR_TFR; /* R->RFR, W->TFR */ + FWK_RW uint32_t IER; + FWK_RW uint32_t IIR_FCR; /* R->IIR, W->FCR */ + FWK_RW uint32_t LCR; + FWK_RW uint32_t MCR; + FWK_R uint32_t LSR; + FWK_R uint32_t MSR; + FWK_RW uint32_t SCR; +}; + +/* DivLatch access registers */ +struct f_uart3_dla_reg { + FWK_RW uint32_t DLL; + FWK_RW uint32_t DLM; + FWK_RW uint32_t IIR_FCR; /* R->IIR, W->FCR */ + FWK_RW uint32_t LCR; + FWK_RW uint32_t MCR; + FWK_R uint32_t LSR; + FWK_R uint32_t MSR; + FWK_W uint32_t TST; +}; + +/* Bit definition */ +/* Interrupt Enable Register */ +#define F_UART3_IER_ERBFI ((uint32_t)(0x1 << 0)) +#define F_UART3_IER_ETBEI ((uint32_t)(0x1 << 1)) +#define F_UART3_IER_ELSI ((uint32_t)(0x1 << 2)) +#define F_UART3_IER_EDSSI ((uint32_t)(0x1 << 3)) + +/* Interrupt Identification Register */ +#define F_UART3_IIR_ID ((uint32_t)(0xF << 0)) +#define F_UART3_IIR_FIFO ((uint32_t)(0x3 << 6)) +#define F_UART3_IIR_ID_NOINTR (uint32_t(0x1)) +#define F_UART3_IIR_ID_RLINE (uint32_t(0x6)) +#define F_UART3_IIR_ID_RDATA (uint32_t(0x4)) +#define F_UART3_IIR_ID_TIMEOUT (uint32_t(0xC)) +#define F_UART3_IIR_ID_TFEMPTY (uint32_t(0x2)) +#define F_UART3_IIR_ID_MODEM (uint32_t(0x0)) + +/* FIFO Control Register */ +#define F_UART3_FCR_RXFRST ((uint32_t)(0x1 << 1)) +#define F_UART3_FCR_TXFRST ((uint32_t)(0x1 << 2)) +#define F_UART3_FCR_DMA ((uint32_t)(0x1 << 3)) +#define F_UART3_FCR_RCVR ((uint32_t)(0x3 << 6)) + +/* Rx FIFO trigger level */ +#define F_UART3_FCR_RCVR_1B ((uint32_t)(0x0 << 6)) +#define F_UART3_FCR_RCVR_4B ((uint32_t)(0x1 << 6)) +#define F_UART3_FCR_RCVR_8B ((uint32_t)(0x2 << 6)) +#define F_UART3_FCR_RCVR_14B ((uint32_t)(0x3 << 6)) + +/* Line Control Register */ +#define F_UART3_LCR_WLS ((uint32_t)(0x3 << 0)) +#define F_UART3_LCR_STB ((uint32_t)(0x3 << 2)) +#define F_UART3_LCR_PEN ((uint32_t)(0x1 << 3)) +#define F_UART3_LCR_EPS ((uint32_t)(0x1 << 4)) +#define F_UART3_LCR_SP ((uint32_t)(0x1 << 5)) +#define F_UART3_LCR_SB ((uint32_t)(0x1 << 6)) +#define F_UART3_LCR_DLAB ((uint32_t)(0x1 << 7)) +/* Word length */ +#define F_UART3_LCR_WLS_5 ((uint32_t)(0x0)) +#define F_UART3_LCR_WLS_6 ((uint32_t)(0x1)) +#define F_UART3_LCR_WLS_7 ((uint32_t)(0x2)) +#define F_UART3_LCR_WLS_8 ((uint32_t)(0x3)) + +/* Modem Control Register */ +#define F_UART3_MCR_DTR ((uint32_t)(0x1 << 0)) +#define F_UART3_MCR_RTS ((uint32_t)(0x1 << 1)) +#define F_UART3_MCR_OUT1 ((uint32_t)(0x1 << 2)) +#define F_UART3_MCR_OUT2 ((uint32_t)(0x1 << 3)) +#define F_UART3_MCR_LOOP ((uint32_t)(0x1 << 4)) + +/* Line Status Register */ +#define F_UART3_LSR_DR ((uint32_t)(0x1 << 0)) +#define F_UART3_LSR_OE ((uint32_t)(0x1 << 1)) +#define F_UART3_LSR_PE ((uint32_t)(0x1 << 2)) +#define F_UART3_LSR_FE ((uint32_t)(0x1 << 3)) +#define F_UART3_LSR_BI ((uint32_t)(0x1 << 4)) +#define F_UART3_LSR_THRE ((uint32_t)(0x1 << 5)) +#define F_UART3_LSR_TEMT ((uint32_t)(0x1 << 6)) +#define F_UART3_LSR_ERRF ((uint32_t)(0x1 << 7)) + +/* Modem Status Register */ +#define F_UART3_MSR_DCTS ((uint32_t)(0x1 << 0)) +#define F_UART3_MSR_DDSR ((uint32_t)(0x1 << 1)) +#define F_UART3_MSR_TERI ((uint32_t)(0x1 << 2)) +#define F_UART3_MSR_DDCD ((uint32_t)(0x1 << 3)) +#define F_UART3_MSR_CTS ((uint32_t)(0x1 << 4)) +#define F_UART3_MSR_DSR ((uint32_t)(0x1 << 5)) +#define F_UART3_MSR_RI ((uint32_t)(0x1 << 6)) +#define F_UART3_MSR_DCD ((uint32_t)(0x1 << 7)) + +/* + * Baud rate + * F_UART3 Clock domain: MAIN_CRG11.CLK6 + * freq : 500MHz/8 = 62.5MHz + * + * DivRatio = Freq(Hz) / (16 * BaudRate(bps)) + */ + +/* 230.4 kbps (DivRatio: 16.95) */ +#define F_UART3_DLL_230400 ((uint32_t)(0x11)) +#define F_UART3_DLM_230400 ((uint32_t)(0x00)) + +/* 115.2 kbps (DivRatio: 33.91) */ +#define F_UART3_DLL_115200 ((uint32_t)(0x22)) +#define F_UART3_DLM_115200 ((uint32_t)(0x00)) + +/* 57.6 kbps (DivRatio: 67.82) */ +#define F_UART3_DLL_57600 ((uint32_t)(0x44)) +#define F_UART3_DLM_57600 ((uint32_t)(0x00)) + +/* 38.4 kbps (DivRatio: 101.73) */ +#define F_UART3_DLL_38400 ((uint32_t)(0x66)) +#define F_UART3_DLM_38400 ((uint32_t)(0x00)) + +/* 19.2 kbps (DivRatio: 203.45) */ +#define F_UART3_DLL_19200 ((uint32_t)(0xCC)) +#define F_UART3_DLM_19200 ((uint32_t)(0x00)) + +/* 9.6 kbps (DivRatio: 409.9) */ +#define F_UART3_DLL_9600 ((uint32_t)(0x9A)) +#define F_UART3_DLM_9600 ((uint32_t)(0x01)) + +#define F_UART3_SYSPARAM_BAUD_RATE_9600 (0) +#define F_UART3_SYSPARAM_BAUD_RATE_19200 (1) +#define F_UART3_SYSPARAM_BAUD_RATE_38400 (2) +#define F_UART3_SYSPARAM_BAUD_RATE_57600 (3) +#define F_UART3_SYSPARAM_BAUD_RATE_115200 (4) +#define F_UART3_SYSPARAM_BAUD_RATE_230400 (5) +#define F_UART3_SYSPARAM_BAUD_RATE_MAX (5) + +typedef enum { + F_UART3_NEWLINE_CODE_CRLF = 0, + F_UART3_NEWLINE_CODE_CR = 1, + F_UART3_NEWLINE_CODE_LF = 2 +} F_UART3_newline_code_t; + +#endif /* F_UART3_H */ diff --git a/product/synquacer/module/f_uart3/src/mod_f_uart3.c b/product/synquacer/module/f_uart3/src/mod_f_uart3.c new file mode 100644 index 000000000..881c95b21 --- /dev/null +++ b/product/synquacer/module/f_uart3/src/mod_f_uart3.c @@ -0,0 +1,226 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct mod_f_uart3_device_config **device_config_table; + +static struct { + unsigned stdio_output_ch : 2; + unsigned parity_enable_flag : 1; + unsigned even_parity_flag : 1; + unsigned newline_code : 2; + uint8_t divider_latch_table_index; +} uart_config = { .stdio_output_ch = 0, + .parity_enable_flag = false, + .even_parity_flag = false, + .newline_code = F_UART3_NEWLINE_CODE_CRLF, + .divider_latch_table_index = + F_UART3_SYSPARAM_BAUD_RATE_115200 }; + +static const struct { + uint8_t DLM; + uint8_t DLL; +} uart_divider_latch_table[] = { + [F_UART3_SYSPARAM_BAUD_RATE_9600] = { + .DLM = F_UART3_DLM_9600, + .DLL = F_UART3_DLL_9600, + }, + [F_UART3_SYSPARAM_BAUD_RATE_19200] = { + .DLM = F_UART3_DLM_19200, + .DLL = F_UART3_DLL_19200, + }, + [F_UART3_SYSPARAM_BAUD_RATE_38400] = { + .DLM = F_UART3_DLM_38400, + .DLL = F_UART3_DLL_38400, + }, + [F_UART3_SYSPARAM_BAUD_RATE_57600] = { + .DLM = F_UART3_DLM_57600, + .DLL = F_UART3_DLL_57600, + }, + [F_UART3_SYSPARAM_BAUD_RATE_115200] = { + .DLM = F_UART3_DLM_115200, + .DLL = F_UART3_DLL_115200, + }, + [F_UART3_SYSPARAM_BAUD_RATE_230400] = { + .DLM = F_UART3_DLM_230400, + .DLL = F_UART3_DLL_230400, + } +}; + +void get_device_reg( + fwk_id_t device_id, + struct f_uart3_reg **reg, + struct f_uart3_dla_reg **dla_reg) +{ + unsigned int device_idx; + + device_idx = fwk_id_get_element_idx(device_id); + *reg = (struct f_uart3_reg *)device_config_table[device_idx]->reg_base; + *dla_reg = + (struct f_uart3_dla_reg *)device_config_table[device_idx]->dla_reg_base; +} + +/* + * Module log driver API + */ + +static int do_putchar(fwk_id_t device_id, char c) +{ + int status; + struct f_uart3_reg *reg; + struct f_uart3_dla_reg *dla_reg; + + status = fwk_module_check_call(device_id); + if (status != FWK_SUCCESS) + return status; + + get_device_reg(device_id, ®, &dla_reg); + if (reg != NULL) { + while ((reg->LSR & F_UART3_LSR_THRE) == 0x0) { + /* wait for TxFIFO to empty. */ + continue; + } + reg->RFR_TFR = (uint32_t)c; + __DSB(); + } + + return FWK_SUCCESS; +} + +static int do_flush(fwk_id_t device_id) +{ + int status; + struct f_uart3_reg *reg; + struct f_uart3_dla_reg *dla_reg; + + status = fwk_module_check_call(device_id); + if (status != FWK_SUCCESS) + return status; + + get_device_reg(device_id, ®, &dla_reg); + if (reg != NULL) { + while ((reg->LSR & F_UART3_LSR_TEMT) == 0x0) { + /* wait for TxFIFO to empty. */ + continue; + } + } + + return FWK_SUCCESS; +} + +static const struct mod_log_driver_api driver_api = { + .flush = do_flush, + .putchar = do_putchar, +}; + +/* + * Framework handlers + */ +static int f_uart3_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + if (element_count == 0) + return FWK_E_DATA; + + /* + * Create an array of pointers used to store the configuration data pointer + * of each element. + */ + device_config_table = + fwk_mm_calloc(element_count, sizeof(*device_config_table)); + if (device_config_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int f_uart3_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + struct f_uart3_reg *reg; + struct f_uart3_dla_reg *dla_reg; + const struct mod_f_uart3_device_config *config = data; + + reg = (struct f_uart3_reg *)config->reg_base; + dla_reg = (struct f_uart3_dla_reg *)config->dla_reg_base; + if ((reg == NULL) || (dla_reg == NULL)) + return FWK_E_DATA; + + /* Set DLAB */ + reg->LCR |= F_UART3_LCR_DLAB; + __DSB(); + + dla_reg->DLL = + uart_divider_latch_table[uart_config.divider_latch_table_index].DLL; + dla_reg->DLM = + uart_divider_latch_table[uart_config.divider_latch_table_index].DLM; + __DSB(); + + /* Clear DLAB */ + reg->LCR &= ~F_UART3_LCR_DLAB; + __DSB(); + + reg->LCR = F_UART3_LCR_WLS_8; + if (uart_config.parity_enable_flag) { + reg->LCR |= F_UART3_LCR_PEN; + if (uart_config.even_parity_flag) + reg->LCR |= F_UART3_LCR_EPS; + } + __DSB(); + + /* Disable interrupt */ + reg->IER = 0x0; + __DSB(); + + /* FIFO Reset */ + reg->IIR_FCR = (F_UART3_FCR_RXFRST | F_UART3_FCR_TXFRST); + __DSB(); + + device_config_table[fwk_id_get_element_idx(element_id)] = config; + + return FWK_SUCCESS; +} + +static int f_uart3_process_bind_request( + fwk_id_t requester_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + *api = &driver_api; + + return FWK_SUCCESS; +} + +static int f_uart3_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +const struct fwk_module module_f_uart3 = { + .name = "F_UART3", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = f_uart3_init, + .element_init = f_uart3_element_init, + .start = f_uart3_start, + .process_bind_request = f_uart3_process_bind_request, +}; diff --git a/product/synquacer/module/hsspi/include/internal/hsspi_api.h b/product/synquacer/module/hsspi/include/internal/hsspi_api.h new file mode 100644 index 000000000..e5727e831 --- /dev/null +++ b/product/synquacer/module/hsspi/include/internal/hsspi_api.h @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HSSPI_API_H +#define HSSPI_API_H + +#include +#include +#include +#include + +struct HSSPI_clk_config { + HSSPI_EN_MCTRL_CDSS_t clk_sel; + int clk_div; + int syncon; +}; + +/** + * Initialize HS-SPI controller and external serial flash memory + */ +void HSSPI_init(void); +/** + * Finalize HS-SPI controller and external serial flash memory + */ +void HSSPI_exit(void); + +#endif /* HSSPI_API_H */ diff --git a/product/synquacer/module/hsspi/include/internal/hsspi_driver.h b/product/synquacer/module/hsspi/include/internal/hsspi_driver.h new file mode 100644 index 000000000..daafc32b2 --- /dev/null +++ b/product/synquacer/module/hsspi/include/internal/hsspi_driver.h @@ -0,0 +1,90 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HSSPI_DRIVER_H +#define HSSPI_DRIVER_H + +#include +#include +#include +#include + +#define MEM_HSSPI_BYTE(var) ((volatile uint8_t *)(var)) +#define MEM_HSSPI_HALF(var) ((volatile uint16_t *)(var)) +#define MEM_HSSPI_WORD(var) ((volatile uint32_t *)(var)) + +typedef enum { + HSSPI_EN_STARTUP_COMMAND_READ_ID = 0x9F, /* READ ID */ + HSSPI_EN_STARTUP_COMMAND_READ = 0x03, /* READ */ + HSSPI_EN_STARTUP_COMMAND_DOFR = 0x3B, /* DUAL OUTPUT FAST READ */ + HSSPI_EN_STARTUP_COMMAND_QOFR = 0x6B, /* QUAD OUTPUT FAST READ */ + HSSPI_EN_STARTUP_COMMAND_READ_4B = 0x13, /* 4-BYTE READ */ + HSSPI_EN_STARTUP_COMMAND_DOFR_4B = 0x3C, /* 4-BYTE DUAL OUTPUT FAST READ */ + HSSPI_EN_STARTUP_COMMAND_QOFR_4B = 0x6C, /* 4-BYTE QUAD OUTPUT FAST READ */ + HSSPI_EN_STARTUP_COMMAND_WEN = 0x06, /* WRITE ENABLE */ + HSSPI_EN_STARTUP_COMMAND_ENTER_4B = 0xB7, /* ENTER 4-BYTE MODE */ +} HSSPI_EN_STARTUP_COMMAND_t; + +typedef enum { + HSSPI_EN_JEDEC_MID_UNKNOWN = -1, + HSSPI_EN_JEDEC_MID_SPANSION = 0x01, + HSSPI_EN_JEDEC_MID_MICRON = 0x20, + HSSPI_EN_JEDEC_MID_MACRONIX = 0xC2, + HSSPI_EN_JEDEC_MID_WINBOND = 0xEF +} HSSPI_EN_JEDEC_MID_t; + +typedef void (*HSSPI_FUNC_INIT)(volatile REG_ST_HSSPI_t *, volatile void *); + +typedef struct { + HSSPI_EN_JEDEC_MID_t MID; + HSSPI_FUNC_INIT FUNC; +} HSSPI_ST_INIT_t; + +void hsspi_command_switch( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + volatile void *reg_boot_ctl, + HSSPI_EN_MCTRL_CDSS_t clk_sel, + int clk_div, + int syncon, + int use_hsspi_cs1_flag, + HSSPI_EN_CSCFG_MSEL_t msel); + +void hsspi_exit( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + volatile void *reg_boot_ctl, + HSSPI_EN_MCTRL_CDSS_t clk_sel, + int clk_div, + int syncon, + int use_hsspi_cs1_flag, + HSSPI_EN_CSCFG_MSEL_t msel); + +void hsspi_write_command_direct( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + int command); +unsigned char hsspi_read_command_direct( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + int command); + +void hsspi_write_command_sequence_addr2( + volatile REG_ST_HSSPI_t *reg_hsspi, + int command); +void hsspi_read_command_sequence_addr2( + volatile REG_ST_HSSPI_t *reg_hsspi, + int command); + +void hsspi_set_window_size( + volatile REG_ST_HSSPI_t *reg_hsspi, + int use_hsspi_cs1_flag, + HSSPI_EN_CSCFG_MSEL_t msel); + +void hsspi_init(volatile REG_ST_HSSPI_t *reg_hsspi); + +#endif /* HSSPI_DRIVER_H */ diff --git a/product/synquacer/module/hsspi/include/internal/reg_HSSPI.h b/product/synquacer/module/hsspi/include/internal/reg_HSSPI.h new file mode 100644 index 000000000..27d148c67 --- /dev/null +++ b/product/synquacer/module/hsspi/include/internal/reg_HSSPI.h @@ -0,0 +1,428 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REG_HSSPI_H +#define REG_HSSPI_H + +#ifdef RESERVED_AREA_BYTE +#undef RESERVED_AREA_BYTE +#endif +#define RESERVED_AREA_BYTE(var1, var2) \ + unsigned char reserved_##var1_##var2 \ + [(((var2) + 1) - (var1)) / sizeof(unsigned char)] + +#ifdef RESERVED_AREA_HALF +#undef RESERVED_AREA_HALF +#endif +#define RESERVED_AREA_HALF(var1, var2) \ + unsigned short reserved_##var1_##var2 \ + [(((var2) + 1) - (var1)) / sizeof(unsigned short)] + +#ifdef RESERVED_AREA_WORD +#undef RESERVED_AREA_WORD +#endif +#define RESERVED_AREA_WORD(var1, var2) \ + unsigned long reserved_##var1_##var2 \ + [(((var2) + 1) - (var1)) / sizeof(unsigned long)] + +typedef enum { + HSSPI_EN_TRP_MBM = 0, + HSSPI_EN_TRP_DUAL = 1, + HSSPI_EN_TRP_QUAD = 2, + HSSPI_EN_TRP_SINGLE = 3 +} HSSPI_EN_TRP_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int MEN : 1; + unsigned int CSEN : 1; + unsigned int reserved1 : 1; + unsigned int CDSS : 1; + unsigned int MES : 1; + unsigned int SYNCON : 1; + unsigned int reserved2 : 2; + unsigned int reserved3 : 24; + } bit; +} HSSPI_UN_MCTRL_t; + +typedef enum { + HSSPI_EN_MCTRL_MEM_DISABLE = 0, + HSSPI_EN_MCTRL_MEM_ENABLE = 1 +} HSSPI_EN_MCTRL_MEM_t; + +typedef enum { + HSSPI_EN_MCTRL_CSEN_DIRECT = 0, + HSSPI_EN_MCTRL_CSEN_CMDSEQ = 1 +} HSSPI_EN_MCTRL_CSEN_t; + +typedef enum { + HSSPI_EN_MCTRL_CDSS_iHCLK = 0, + HSSPI_EN_MCTRL_CDSS_iPCLK = 1 +} HSSPI_EN_MCTRL_CDSS_t; + +typedef enum { + HSSPI_EN_MCTRL_SYNCON_ASYNC = 0, + HSSPI_EN_MCTRL_SYNCON_SYNC = 1 +} HSSPI_EN_MCTRL_SYNCON_t; + +#define HSSPI_MAKE_MCTRL(SYNCON, CDSS, CSEN, MEM) \ + (((SYNCON) << 5) | ((CDSS) << 3) | ((CSEN) << 1) | ((MEM) << 0)) + +typedef union { + unsigned int DATA; + struct { + unsigned int CPHA : 1; + unsigned int CPOL : 1; + unsigned int ACES : 1; + unsigned int RTM : 1; + unsigned int SSPOL : 1; + unsigned int SS2CD : 2; + unsigned int SDIR : 1; + unsigned int SENDIAN : 1; + unsigned int CDRS : 7; + unsigned int SAFESYNC : 1; + unsigned int WRDSEL : 4; + unsigned int RDDSEL : 2; + unsigned int reserved1 : 1; + unsigned int reserved2 : 8; + } bit; +} HSSPI_UN_PCC_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int UMAFS : 1; + unsigned int WAFS : 1; + unsigned int PVFS : 1; + unsigned int DWCBSFS : 1; + unsigned int DRCBSFS : 1; + unsigned int reserved1 : 3; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_FAULTF_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int UMAFC : 1; + unsigned int WAFC : 1; + unsigned int PVFC : 1; + unsigned int DWCBSFC : 1; + unsigned int DRCBSFC : 1; + unsigned int reserved1 : 3; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_FAULTC_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int RXFTH : 4; + unsigned int TXFTH : 4; + unsigned int FWIDTH : 2; + unsigned int TXCTRL : 1; + unsigned int RXFLSH : 1; + unsigned int TXFLSH : 1; + unsigned int reserved1 : 3; + unsigned int reserved2 : 16; + } bit; +} HSSPI_UN_FIFOCFG_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int TFFS : 1; + unsigned int TFES : 1; + unsigned int TFOS : 1; + unsigned int TFUS : 1; + unsigned int TFLETS : 1; + unsigned int TFMTS : 1; + unsigned int TSSRS : 1; + unsigned int reserved1 : 1; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_TXF_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int TFFE : 1; + unsigned int TFEE : 1; + unsigned int TFOE : 1; + unsigned int TFUE : 1; + unsigned int TFLETE : 1; + unsigned int TFMTE : 1; + unsigned int TSSRE : 1; + unsigned int reserved1 : 1; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_TXE_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int TFFC : 1; + unsigned int TFEC : 1; + unsigned int TFOC : 1; + unsigned int TFUC : 1; + unsigned int TFLETC : 1; + unsigned int TFMTC : 1; + unsigned int TSSRC : 1; + unsigned int reserved1 : 1; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_TXC_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int RFFS : 1; + unsigned int RFES : 1; + unsigned int RFOS : 1; + unsigned int RFUS : 1; + unsigned int RFLETS : 1; + unsigned int RFMTS : 1; + unsigned int RSSRS : 1; + unsigned int reserved1 : 1; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_RXF; + +typedef union { + unsigned int DATA; + struct { + unsigned int RFFE : 1; + unsigned int RFEE : 1; + unsigned int RFOE : 1; + unsigned int RFUE : 1; + unsigned int RFLETE : 1; + unsigned int RFMTE : 1; + unsigned int RSSRE : 1; + unsigned int reserved1 : 1; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_RXE_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int RFFC : 1; + unsigned int RFEC : 1; + unsigned int RFOC : 1; + unsigned int RFUC : 1; + unsigned int RFLETC : 1; + unsigned int RFMTC : 1; + unsigned int RSSRC : 1; + unsigned int reserved1 : 1; + unsigned int reserved2 : 24; + } bit; +} HSSPI_UN_RXC_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int RXDMAEN : 1; + unsigned int TXDMAEN : 1; + unsigned int reserved1 : 6; + unsigned int MUSTBE1 : 1; + unsigned int SSDC : 1; + unsigned int MSTARTEN : 1; + unsigned int reserved2 : 5; + unsigned int reserved3 : 16; + } bit; +} HSSPI_UN_DMDMAENCFG_t; + +typedef enum { + HSSPI_EN_DMTRP_TRPW_SINGLE = 0, + HSSPI_EN_DMTRP_TRPW_DUAL = 1, + HSSPI_EN_DMTRP_TRPW_QUAD = 2 +} HSSPI_EN_DMTRP_TRPW_t; + +typedef enum { + HSSPI_EN_DMTRP_TRPM_TXandRX = 0, + HSSPI_EN_DMTRP_TRPM_RXonly = 1, + HSSPI_EN_DMTRP_TRPM_TXonly = 2 +} HSSPI_EN_DMTRP_TRPM_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int START : 1; + unsigned int reserved1: 7; + unsigned int STOP : 1; + unsigned int reserved2 : 7; + unsigned int PSEL : 2; + unsigned int reserved3 : 6; + unsigned int TRPW : 2; + unsigned int TRPM : 2; + unsigned int reserved4 : 4; + } bit; +} HSSPI_UN_DMx_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int BCC : 16; + unsigned int BCS : 16; + } bit; +} HSSPI_UN_DMBCx_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int RXACTIVE : 1; + unsigned int TXACTIVE : 1; + unsigned int reserved1 : 6; + unsigned int RXFLEVEL : 5; + unsigned int reserved2 : 3; + unsigned int TXFLEVEL : 5; + unsigned int reserved3 : 3; + unsigned int reserved4 : 8; + } bit; +} HSSPI_UN_DMSTATUS_t; + +typedef enum { + HSSPI_EN_CSCFG_MSEL_8K = 0x0, + HSSPI_EN_CSCFG_MSEL_16K = 0x1, + HSSPI_EN_CSCFG_MSEL_32K = 0x2, + HSSPI_EN_CSCFG_MSEL_64K = 0x3, + HSSPI_EN_CSCFG_MSEL_128K = 0x4, + HSSPI_EN_CSCFG_MSEL_256K = 0x5, + HSSPI_EN_CSCFG_MSEL_512K = 0x6, + HSSPI_EN_CSCFG_MSEL_1M = 0x7, + HSSPI_EN_CSCFG_MSEL_2M = 0x8, + HSSPI_EN_CSCFG_MSEL_4M = 0x9, + HSSPI_EN_CSCFG_MSEL_8M = 0xA, + HSSPI_EN_CSCFG_MSEL_16M = 0xB, + HSSPI_EN_CSCFG_MSEL_32M = 0xC, + HSSPI_EN_CSCFG_MSEL_64M = 0xD, + HSSPI_EN_CSCFG_MSEL_128M = 0xE, + HSSPI_EN_CSCFG_MSEL_256M = 0xF +} HSSPI_EN_CSCFG_MSEL_t; + +typedef enum { + HSSPI_EN_CSCFG_SRAM_RO = 0, + HSSPI_EN_CSCFG_SRAM_RW = 1 +} HSSPI_EN_CSCFG_SRAM_t; + +#define HSSPI_SHIFT_CSCFG_SRAM (0) + +typedef enum { + HSSPI_EN_CSCFG_MBM_SINGLE = 0, + HSSPI_EN_CSCFG_MBM_DUAL = 1, + HSSPI_EN_CSCFG_MBM_QUAD = 2 +} HSSPI_EN_CSCFG_MBM_t; + +#define HSSPI_SHIFT_CSCFG_MBM (1) + +typedef union { + unsigned int DATA; + struct { + unsigned int SRAM : 1; /* B[00] */ + unsigned int MBM : 2; /* B[02:01] */ + unsigned int SPICHNG : 1; /* B[03] */ + unsigned int BOOTEN : 1; /* B[04] */ + unsigned int BSEL : 1; /* B[05] */ + unsigned int reserved1 : 2; /* B[07:06] */ + unsigned int SSEL0EN : 1; /* B[08] */ + unsigned int SSEL1EN : 1; /* B[09] */ + unsigned int SSEL2EN : 1; /* B[10] */ + unsigned int SSEL3EN : 1; /* B[11] */ + unsigned int reserved2 : 4; /* B[15:12] */ + unsigned int MSEL : 4; /* B[19:16] */ + unsigned int reserved3 : 4; /* B[23:20] */ + unsigned int reserved4 : 8; /* B[31:24] */ + } bit; +} HSSPI_UN_CSCFG_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int ITIME : 16; /* B[15:00] */ + unsigned int reserved1 : 16; /* B[31:16] */ + } bit; +} HSSPI_UN_CSITIME_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int reserved1 : 13; /* B[12:00] */ + unsigned int AEXT : 19; /* B[31:13] */ + } bit; +} HSSPI_UN_CSAEXT_t; + +#define MAKE_CSDC(DATA, CONT, TRP, DEC) \ + (((DATA) << 8) | ((CONT) << 3) | ((TRP) << 1) | ((DEC) << 0)) + +typedef union { + unsigned int DATA; + struct { + unsigned int DEC : 1; /* B[00] */ + unsigned int TRP : 2; /* B[02:01] */ + unsigned int CONT : 1; /* B[03] */ + unsigned int reserved1 : 4; /* B[07:04] */ + unsigned int DATA : 8; /* B[15:08] */ + unsigned int reserved2 : 16; /* B[31:16] */ + } bit; +} HSSPI_UN_CSDC_LO_t; + +typedef union { + unsigned int DATA; + struct { + unsigned int reserved1 : 16; /* B[15:00] */ + unsigned int DEC : 1; /* B[16] */ + unsigned int TRP : 2; /* B[18:17] */ + unsigned int CONT : 1; /* B[19] */ + unsigned int reserved2 : 4; /* B[23:20] */ + unsigned int DATA : 8; /* B[31:24] */ + } bit; +} HSSPI_UN_CSDC_HI_t; + +typedef union { + unsigned int DATA; + HSSPI_UN_CSDC_LO_t CSDC_LO; + HSSPI_UN_CSDC_HI_t CSDC_HI; + struct { + unsigned int BIT1500 : 16; + unsigned int BIT3116 : 16; + } half; +} HSSPI_UN_CSDC_ITEM_t; + +typedef union { + unsigned short HALF[8]; + HSSPI_UN_CSDC_ITEM_t CSDC[4]; +} HSSPI_UN_CSDC_t; + +typedef struct { + HSSPI_UN_MCTRL_t MCTRL; + HSSPI_UN_PCC_t PCC[4]; + HSSPI_UN_TXF_t TXF; + HSSPI_UN_TXE_t TXE; + HSSPI_UN_TXC_t TXC; + HSSPI_UN_RXF RXF; + HSSPI_UN_RXE_t RXE; + HSSPI_UN_RXC_t RXC; + HSSPI_UN_FAULTF_t FAULTF; + HSSPI_UN_FAULTC_t FAULTC; + HSSPI_UN_DMDMAENCFG_t DMDMAEN_DMCFG; + HSSPI_UN_DMx_t DMx; + HSSPI_UN_DMBCx_t DMBCx; + HSSPI_UN_DMSTATUS_t DMSTATUS; + RESERVED_AREA_WORD(0x044, 0x04B); + HSSPI_UN_FIFOCFG_t FIFOCFG; + unsigned int TXFIFO[16]; + unsigned int RXFIFO[16]; + HSSPI_UN_CSCFG_t CSCFG; + HSSPI_UN_CSITIME_t CSITIME; + HSSPI_UN_CSAEXT_t CSAEXT; + HSSPI_UN_CSDC_t RDCSDC; + HSSPI_UN_CSDC_t WRCSDC; + unsigned int MID; +} REG_ST_HSSPI_t; + +#endif /* REG_HSSPI_H */ diff --git a/product/synquacer/module/hsspi/include/mod_hsspi.h b/product/synquacer/module/hsspi/include/mod_hsspi.h new file mode 100644 index 000000000..19c01a73a --- /dev/null +++ b/product/synquacer/module/hsspi/include/mod_hsspi.h @@ -0,0 +1,66 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_HSSPI_H +#define MOD_HSSPI_H + +#include +#include +#include +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupSYNQUACER_HSSPI HSSPI Driver + * + * \brief SynQuacer High Speed SPI device driver. + * + * \details This module implements a device driver for the HSSPI + * + * @{ + */ + +/*! + * \brief APIs to access the descriptors in the flash memory. + */ +struct mod_hsspi_api { + /*! + * \brief initialize the high speed spi controller + * + * \param void + * \return void + */ + void (*hsspi_init)(void); + + /*! + * \brief uninitialize the high speed spi controller + * + * \param void + * \return void + */ + void (*hsspi_exit)(void); +}; + +/*! + * \brief HSSPI device configuration data. + */ +struct mod_hsspi_config { + /*! Base address of the device registers */ + uintptr_t reg_base; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_HSSPI_H */ diff --git a/product/synquacer/module/hsspi/src/Makefile b/product/synquacer/module/hsspi/src/Makefile new file mode 100644 index 000000000..02755b18a --- /dev/null +++ b/product/synquacer/module/hsspi/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := "hsspi" +BS_LIB_SOURCES = mod_hsspi.c hsspi_api.c hsspi_driver.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/hsspi/src/hsspi_api.c b/product/synquacer/module/hsspi/src/hsspi_api.c new file mode 100644 index 000000000..7ef2a9701 --- /dev/null +++ b/product/synquacer/module/hsspi/src/hsspi_api.c @@ -0,0 +1,83 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define FILE_GRP_ID DBG_DRV_HSSPI +#define xcpb_bridge_mode_set(enable) + +static const struct HSSPI_clk_config clk_config = CONFIG_SOC_HSSPI_CLK_CONFIG; + +#define HSSPI_WINDOW_SIZE_INDEX_256MB (0xF) +#define HSSPI_WINDOW_SIZE_INDEX_128MB (0xE) +#define HSSPI_WINDOW_SIZE_INDEX_64MB (0xD) +#define HSSPI_WINDOW_SIZE_INDEX_32MB (0xC) +#define HSSPI_WINDOW_SIZE_INDEX_16MB (0xB) +#define HSSPI_WINDOW_SIZE_INDEX_8MB (0xA) +#define HSSPI_WINDOW_SIZE_INDEX_4MB (0x9) +#define HSSPI_WINDOW_SIZE_INDEX_2MB (0x8) + +#define CONFIG_SCB_FORCE_HSSPI_RESOURCE_ALLOCATION_MODEL \ + HSSPI_WINDOW_SIZE_INDEX_256MB + +void HSSPI_init(void) +{ + int model_index; + + xcpb_bridge_mode_set(true); + + model_index = CONFIG_SCB_FORCE_HSSPI_RESOURCE_ALLOCATION_MODEL; + + SYNQUACER_DEV_LOG_INFO( + "[HS-SPI] Configuring HS-SPI controller with " + "clk_sel=%d clk_div=%d syncon=%d use_hsspi_cs1_flag=%d msel=%d\n", + clk_config.clk_sel, + clk_config.clk_div, + clk_config.syncon, + false, + model_index); + + /* Initialize HS-SPI controller and external serial flash memory */ + hsspi_command_switch( + (volatile REG_ST_HSSPI_t *)HSSPI_REG_BASE, + (volatile void *)HSSPI_MEM_BASE, + (volatile void *)CONFIG_SOC_REG_ADDR_BOOT_CTL_TOP, + clk_config.clk_sel, + clk_config.clk_div, + clk_config.syncon, + 0, /* use_hsspi_cs1_flag disable*/ + (HSSPI_EN_CSCFG_MSEL_t)model_index); + + xcpb_bridge_mode_set(false); +} + +void HSSPI_exit(void) +{ + int model_index; + + xcpb_bridge_mode_set(true); + + model_index = CONFIG_SCB_FORCE_HSSPI_RESOURCE_ALLOCATION_MODEL; + + /* Initialize HS-SPI controller and external serial flash memory */ + hsspi_exit( + (volatile REG_ST_HSSPI_t *)HSSPI_REG_BASE, + (volatile void *)HSSPI_MEM_BASE, + (volatile void *)CONFIG_SOC_REG_ADDR_BOOT_CTL_TOP, + clk_config.clk_sel, + clk_config.clk_div, + clk_config.syncon, + 0, /* use_hsspi_cs1_flag disable*/ + (HSSPI_EN_CSCFG_MSEL_t)model_index); +} diff --git a/product/synquacer/module/hsspi/src/hsspi_driver.c b/product/synquacer/module/hsspi/src/hsspi_driver.c new file mode 100644 index 000000000..dfd2cc2be --- /dev/null +++ b/product/synquacer/module/hsspi/src/hsspi_driver.c @@ -0,0 +1,683 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#include +#include + +static const uint16_t m_awcCommandList_NULL[] = { + /* DATA[15:8] CONT[3] TRP[2:1] DEC[0] */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1) /* EndOfList */ +}; + +static const uint16_t m_awcCommandList_CMD_S[] = { + /* DATA[15:8] CONT[3] TRP[2:1] DEC[0] */ + MAKE_CSDC(0x00, 0, HSSPI_EN_TRP_SINGLE, 0), /* COMMAND */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1) /* EndOfList */ +}; + +#ifdef CONFIG_SCB_USE_4BYTE_MODE +static const uint16_t m_awcCommandList_CMD_S_ADDR4_S_D8_S[] = { + /* DATA[15:8] CONT[3] TRP[2:1] DEC[0] */ + MAKE_CSDC(0x00, 0, HSSPI_EN_TRP_SINGLE, 0), /* COMMAND */ + MAKE_CSDC(0x03, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[31:24] */ + MAKE_CSDC(0x02, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[23:16] */ + MAKE_CSDC(0x01, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[15:08] */ + MAKE_CSDC(0x00, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[07:00] */ + MAKE_CSDC(0x04, 0, HSSPI_EN_TRP_SINGLE, 1), /* DUMMY CYCLE x8 */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ +}; +#else /* CONFIG_SCB_USE_4BYTE_MODE */ +static const uint16_t m_awcCommandList_CMD_S_ADDR3_S_D8_S[] = { + /* DATA[15:8] CONT[3] TRP[2:1] DEC[0] */ + MAKE_CSDC(0x00, 0, HSSPI_EN_TRP_SINGLE, 0), /* COMMAND */ + MAKE_CSDC(0x02, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[23:16] */ + MAKE_CSDC(0x01, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[15:08] */ + MAKE_CSDC(0x00, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[07:00] */ + MAKE_CSDC(0x04, 0, HSSPI_EN_TRP_SINGLE, 1), /* DUMMY CYCLE x8 */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1) /* EndOfList */ +}; +#endif /* CONFIG_SCB_USE_4BYTE_MODE */ + +static const uint16_t m_awcCommandList_SingleCMD[] = { + /* DATA[15:8] CONT[3] TRP[2:1] DEC[0] */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 0), + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1) /* EndOfList */ +}; + +static const uint16_t m_awcCommandList_CMD_S_ADDR2_S[] = { + /* DATA[15:8] CONT[3] TRP[2:1] DEC[0] */ + MAKE_CSDC(0x00, 0, HSSPI_EN_TRP_SINGLE, 0), /* COMMAND */ + MAKE_CSDC(0x01, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[15:08] */ + MAKE_CSDC(0x00, 0, HSSPI_EN_TRP_SINGLE, 1), /* ADDR[07:00] */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1), /* EndOfList */ + MAKE_CSDC(0x07, 0, HSSPI_EN_TRP_MBM, 1) /* EndOfList */ +}; + +static void hsspi_stop( + volatile REG_ST_HSSPI_t *reg_hsspi, + HSSPI_EN_MCTRL_CDSS_t clk_sel, + int syncon) +{ + (*reg_hsspi).MCTRL.DATA = HSSPI_MAKE_MCTRL( + syncon, + clk_sel, + HSSPI_EN_MCTRL_CSEN_CMDSEQ, + HSSPI_EN_MCTRL_MEM_DISABLE); + do { + __DSB(); + } while ((*reg_hsspi).MCTRL.bit.MES != 0); +} + +static void hsspi_csen( + volatile REG_ST_HSSPI_t *reg_hsspi, + HSSPI_EN_MCTRL_CDSS_t clk_sel, + int syncon) +{ + (*reg_hsspi).MCTRL.DATA = HSSPI_MAKE_MCTRL( + syncon, clk_sel, HSSPI_EN_MCTRL_CSEN_CMDSEQ, HSSPI_EN_MCTRL_MEM_ENABLE); + do { + __DSB(); + } while ((*reg_hsspi).MCTRL.bit.MES == 0); +} + +static void hsspi_raw_set_csdc( + volatile HSSPI_UN_CSDC_t *csdc, + const uint16_t *command_list, + int command) +{ + int nIndex; + + for (nIndex = 0; nIndex < 8; + csdc->HALF[nIndex] = command_list[nIndex], ++nIndex) + continue; + + if (!(command < 0)) + csdc->CSDC[0].CSDC_LO.bit.DATA = command; +} + +static void hsspi_read_command_sequence( + volatile REG_ST_HSSPI_t *reg_hsspi, + const uint16_t *command_list, + int command) +{ + hsspi_raw_set_csdc(®_hsspi->RDCSDC, command_list, command); +} + +void hsspi_read_command_sequence_addr2( + volatile REG_ST_HSSPI_t *reg_hsspi, + int command) +{ + hsspi_read_command_sequence( + reg_hsspi, m_awcCommandList_CMD_S_ADDR2_S, command); +} + +static void hsspi_write_command_sequence( + volatile REG_ST_HSSPI_t *reg_hsspi, + const uint16_t *command_list, + int command) +{ + hsspi_raw_set_csdc(®_hsspi->WRCSDC, command_list, command); +} + +void hsspi_write_command_sequence_addr2( + volatile REG_ST_HSSPI_t *reg_hsspi, + int command) +{ + hsspi_write_command_sequence( + reg_hsspi, m_awcCommandList_CMD_S_ADDR2_S, command); +} + +void hsspi_write_command_direct( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + int command) +{ + hsspi_raw_set_csdc(®_hsspi->WRCSDC, m_awcCommandList_NULL, -1); + if (!(command < 0)) + MEM_HSSPI_BYTE(mem_hsspi)[0] = command; +} + +uint8_t m_abyJEDEC_ID[3]; + +static void hsspi_read_jedec_id( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi) +{ + hsspi_read_command_sequence( + reg_hsspi, m_awcCommandList_CMD_S, HSSPI_EN_STARTUP_COMMAND_READ_ID); + + /* +00h Manufacturer ID */ + m_abyJEDEC_ID[0] = MEM_HSSPI_BYTE(mem_hsspi)[0]; + /* +01h Device ID Most Significant Byte - Memory Interface Type */ + m_abyJEDEC_ID[1] = MEM_HSSPI_BYTE(mem_hsspi)[1]; + /* +02h Device ID Least Significant Byte - Density */ + m_abyJEDEC_ID[2] = MEM_HSSPI_BYTE(mem_hsspi)[2]; +} + +static void hsspi_dual_output_fast_read(volatile REG_ST_HSSPI_t *reg_hsspi) +{ +#ifdef CONFIG_SCB_USE_4BYTE_MODE + hsspi_read_command_sequence( + reg_hsspi, + m_awcCommandList_CMD_S_ADDR4_S_D8_S, + HSSPI_EN_STARTUP_COMMAND_DOFR_4B); +#else /* CONFIG_SCB_USE_4BYTE_MODE */ + hsspi_read_command_sequence( + reg_hsspi, + m_awcCommandList_CMD_S_ADDR3_S_D8_S, + HSSPI_EN_STARTUP_COMMAND_DOFR); +#endif /* CONFIG_SCB_USE_4BYTE_MODE */ +} + +static void hsspi_quad_output_fast_read(volatile REG_ST_HSSPI_t *reg_hsspi) +{ +#ifdef CONFIG_SCB_USE_4BYTE_MODE + hsspi_read_command_sequence( + reg_hsspi, + m_awcCommandList_CMD_S_ADDR4_S_D8_S, + HSSPI_EN_STARTUP_COMMAND_QOFR_4B); +#else /* CONFIG_SCB_USE_4BYTE_MODE */ + hsspi_read_command_sequence( + reg_hsspi, + m_awcCommandList_CMD_S_ADDR3_S_D8_S, + HSSPI_EN_STARTUP_COMMAND_QOFR); +#endif /* CONFIG_SCB_USE_4BYTE_MODE */ +} + +static void hsspi_wait_status_register_for_wip( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi) +{ + /* Status Register */ + union general_status_register { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t WIP : 1; /* B[0] Write in progress */ + uint32_t WEL : 1; /* B[1] Write enable latch */ + uint32_t BP : 3; /* B[4:2] */ + uint32_t E_ERR : 1; /* B[5] */ + uint32_t P_ERR : 1; /* B[6] */ + uint32_t SRWD : 1; /* B[7] */ + uint32_t reserved1 : 24; /* reserved */ + } bit; + } unRDSR; + + /* 05h : RDSR Read Status Register */ + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x05); + do { + unRDSR.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + } while (unRDSR.bit.WIP); +} + +unsigned char hsspi_read_command_direct( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + int command) +{ + hsspi_raw_set_csdc(®_hsspi->RDCSDC, m_awcCommandList_SingleCMD, command); + + return MEM_HSSPI_BYTE(mem_hsspi)[0]; +} + +static void hsspi_enter_to_quad_for_spansion( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi) +{ + /* Status Register 1 (SR1) */ + union spansion_status_register_1 { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t WIP : 1; /* B[0] */ + uint32_t WEL : 1; /* B[1] */ + uint32_t BP : 3; /* B[4:2] */ + uint32_t E_ERR : 1; /* B[5] */ + uint32_t P_ERR : 1; /* B[6] */ + uint32_t SRWD : 1; /* B[7] */ + uint32_t reserved1 : 24; /* reserved */ + } bit; + } unSR1; + + /* Configuration Register 1 (CR1) */ + union spansion_configuration_register_1 { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t FREEZE : 1; /* B[0] */ + uint32_t QUAD : 1; /* B[1] (0=Dual or Serial, 1=Quad) */ + uint32_t reserved1 : 1; /* B[2] Reserved for Future Use */ + uint32_t BPNV : 1; /* B[3] (0=Non-Volatile, 1=Volatile) */ + uint32_t reserved2 : 1; /* B[4] Reserved for Future Use */ + uint32_t TBPROT : 1; /* B[5] */ + uint32_t LC : 2; /* B[7:6] */ + uint32_t reserved3 : 24; /* reserved */ + } bit; + } unCR1; + + /* 05h : RDSR1 Read Status Register-1 */ + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x05); + unSR1.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + /* 35h : RDCR Read Configuration Register-1 */ + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x35); + unCR1.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + unCR1.bit.QUAD = 1; /* QUAD MODE ENTRY */ + /* 06h : WRITE ENABLE */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0x06); + /* 01h : WRR Write Register (Status-1, Configuration-1) */ + hsspi_write_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x01); + MEM_HSSPI_BYTE(mem_hsspi)[0] = unSR1.BYTE[0]; + MEM_HSSPI_BYTE(mem_hsspi)[1] = unCR1.BYTE[0]; + /* 05h : READ STATUS REGISTER */ + hsspi_wait_status_register_for_wip(reg_hsspi, mem_hsspi); +} + +static void hsspi_enter_to_quad_for_micron( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi) +{ + /* Enhanced Volatile Configuration Register */ + union micron_enhanced_volatile_configuration_register { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t OUTPUT_DRIVER_STRENGTH : 3; /* B[2:0] */ + uint32_t VPP_ACCELERATOR : 1; /* B[3] */ + uint32_t RESET_HOLD : 1; /* B[4] Reset/hold */ + uint32_t reserved1 : 1; /* B[5] reserved */ + uint32_t DUAL_IO_PROTOCOL : 1; /* B[6] */ + uint32_t QUAD_IO_PROTOCOL : 1; /* B[7] */ + uint32_t reserved2 : 24; /* reserved */ + } bit; + } unEVCR; + + /* 65h : READ ENHANCED VOLATILE CONFIGURATION REGISTER */ + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x65); + unEVCR.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + unEVCR.bit.RESET_HOLD = 0; /* QUAD MODE ENTRY */ + /* 06h : WRITE ENABLE */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0x06); + /* E9h : EXIT 4-BYTE ADDRESS MODE */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0xE9); + /* 06h : WRITE ENABLE */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0x06); + /* 61h : WRITE ENHANCED VOLATILE CONFIGURATION REGISTER */ + hsspi_write_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x61); + MEM_HSSPI_BYTE(mem_hsspi)[0] = unEVCR.BYTE[0]; + /* 05h : READ STATUS REGISTER */ + hsspi_wait_status_register_for_wip(reg_hsspi, mem_hsspi); +} + +static void hsspi_enter_to_quad_for_winbond( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi) +{ + /* Status Register-1 */ + union winbond_status_register_1 { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t BUSY : 1; /* B[0] */ + uint32_t WEL : 1; /* B[1] */ + uint32_t BP : 3; /* B[4:2] */ + uint32_t TB : 1; /* B[5] */ + uint32_t SEC : 1; /* B[6] */ + uint32_t SRP0 : 1; /* B[7] */ + uint32_t reserved1 : 24; /* reserved */ + } bit; + } unSR1; + + /* Status Register-2 */ + union winbond_status_register_2 { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t SRP1 : 1; /* B[0] */ + uint32_t QE : 1; /* B[1] Quad Enable (0=Disable, 1=Enable) */ + uint32_t reserved1 : 1; /* B[2] */ + uint32_t LB : 3; /* B[5:3] */ + uint32_t CMP : 1; /* B[6] */ + uint32_t SUS : 1; /* B[7] */ + uint32_t reserved2 : 24; /* reserved */ + } bit; + } unSR2; + + /* 05h : Read Status Register-1 (S7-A0) */ + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x05); + unSR1.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + /* 35h : Read Status Register-2 (S15-A8) */ + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x35); + unSR2.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + unSR2.bit.QE = 1; /* QUAD MODE ENTRY */ + /* 06h : WRITE ENABLE */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0x06); + /* 01h : Write Status Register-2 (S7-A0, S15-A8) */ + hsspi_write_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x01); + MEM_HSSPI_BYTE(mem_hsspi)[0] = unSR1.BYTE[0]; + MEM_HSSPI_BYTE(mem_hsspi)[1] = unSR2.BYTE[0]; + /* 05h : READ STATUS REGISTER */ + hsspi_wait_status_register_for_wip(reg_hsspi, mem_hsspi); +} + +static void hsspi_enter_to_quad_for_macronix( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi) +{ + /* Status Register */ + union macronix_status_register { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t WIP : 1; /* B[0] */ + uint32_t WEL : 1; /* B[1] */ + uint32_t BP : 4; /* B[5:2] */ + uint32_t QE : 1; /* B[6] Quad Enable (0=Disable, 1=Enable) */ + uint32_t SRWD : 1; /* B[7] */ + uint32_t reserved1: 24; /* reserved */ + } bit; + } unSR; + + /* 05h : Read Status Register (RDSR) */ + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x05); + unSR.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + unSR.bit.QE = 1; /* QUAD MODE ENTRY */ + /* 06h : WRITE ENABLE */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0x06); + /* 01h : Write Status Register (WRSR) */ + hsspi_write_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x01); + MEM_HSSPI_BYTE(mem_hsspi)[0] = unSR.BYTE[0]; + /* 05h : READ STATUS REGISTER */ + hsspi_wait_status_register_for_wip(reg_hsspi, mem_hsspi); +} + +static int hsspi_enter_to_quad_by_jedec_id( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + int nJedecMID) +{ + static const HSSPI_ST_INIT_t m_astcHsspiInitTable[] = { + { HSSPI_EN_JEDEC_MID_SPANSION, hsspi_enter_to_quad_for_spansion }, + { HSSPI_EN_JEDEC_MID_MICRON, hsspi_enter_to_quad_for_micron }, + { HSSPI_EN_JEDEC_MID_MACRONIX, hsspi_enter_to_quad_for_macronix }, + { HSSPI_EN_JEDEC_MID_WINBOND, hsspi_enter_to_quad_for_winbond }, + { HSSPI_EN_JEDEC_MID_UNKNOWN, NULL } + }; + const HSSPI_ST_INIT_t *pstcIndex; + + for (pstcIndex = m_astcHsspiInitTable; + pstcIndex->MID != HSSPI_EN_JEDEC_MID_UNKNOWN; + ++pstcIndex) { + if (pstcIndex->MID == nJedecMID) { + if (pstcIndex->FUNC) + (*pstcIndex->FUNC)(reg_hsspi, mem_hsspi); + break; + } + } + + return pstcIndex->MID; +} + +static void hsspi_software_reset( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi) +{ + HSSPI_UN_CSCFG_t unCSCFG; + + /* Status Register */ + union general_status_register { + uint32_t WORD; + uint8_t BYTE[4]; + struct { + uint32_t WIP : 1; /* B[0] Write in progress */ + uint32_t WEL : 1; /* B[1] Write enable latch */ + uint32_t BP : 3; /* B[4:2] */ + uint32_t E_ERR : 1; /* B[5] */ + uint32_t P_ERR : 1; /* B[6] */ + uint32_t SRWD : 1; /* B[7] */ + uint32_t reserved1 : 24; /* reserved */ + } bit; + } unRDSR; + + unCSCFG.DATA = (*reg_hsspi).CSCFG.DATA; + + unCSCFG.bit.SRAM = HSSPI_EN_CSCFG_SRAM_RW; /* allow rea/write access */ + unCSCFG.bit.MBM = HSSPI_EN_CSCFG_MBM_SINGLE; + + (*reg_hsspi).CSCFG.DATA = unCSCFG.DATA; + + hsspi_read_command_sequence(reg_hsspi, m_awcCommandList_CMD_S, 0x05); + + do { + /* Reset Enable */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0x66); + + /* Wait for SPI device ready */ + osDelay(1); + + /* Reset */ + hsspi_write_command_direct(reg_hsspi, mem_hsspi, 0x99); + + /* Wait for SPI device ready */ + osDelay(1); + + /* 05h : RDSR Read Status Register */ + unRDSR.WORD = MEM_HSSPI_BYTE(mem_hsspi)[0]; + } while (unRDSR.bit.WIP); + + return; +} + +void hsspi_command_switch( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + volatile void *reg_boot_ctl, + HSSPI_EN_MCTRL_CDSS_t clk_sel, + int clk_div, + int syncon, + int use_hsspi_cs1_flag, + HSSPI_EN_CSCFG_MSEL_t msel) +{ + HSSPI_UN_PCC_t unPCC; + HSSPI_UN_CSCFG_t unCSCFG; + + int known_jedec_id; + + hsspi_stop(reg_hsspi, clk_sel, syncon); + + unCSCFG.DATA = (*reg_hsspi).CSCFG.DATA; + unCSCFG.bit.MSEL = msel; + unCSCFG.bit.SSEL0EN = 1; + unCSCFG.bit.SSEL1EN = use_hsspi_cs1_flag; + unCSCFG.bit.BOOTEN = 0; + unCSCFG.bit.SRAM = HSSPI_EN_CSCFG_SRAM_RW; /* allow read/write access */ + unCSCFG.bit.MBM = HSSPI_EN_CSCFG_MBM_SINGLE; + (*reg_hsspi).CSCFG.DATA = unCSCFG.DATA; + (*reg_hsspi).CSITIME.DATA = 0x100; /* IDLE TIMER=0x100cycle */ + + MEM_HSSPI_WORD(reg_boot_ctl)[0x008 >> 2] |= (1 << 0); + hsspi_csen(reg_hsspi, clk_sel, syncon); /* HS-SPI IP start(CS MODE) */ + + hsspi_software_reset(reg_hsspi, mem_hsspi); + + hsspi_read_jedec_id(reg_hsspi, mem_hsspi); + + SYNQUACER_DEV_LOG_INFO( + "[HS-SPI] CS#0: Manufacturer ID:%02x, DeviceID:%02x%02x\n", + m_abyJEDEC_ID[0], + m_abyJEDEC_ID[1], + m_abyJEDEC_ID[2]); + + known_jedec_id = + hsspi_enter_to_quad_by_jedec_id(reg_hsspi, mem_hsspi, m_abyJEDEC_ID[0]); + + if (known_jedec_id < 0) { + SYNQUACER_DEV_LOG_INFO( + "[HS-SPI] Unknown manufacturer ID:%02x," + " default to Dual-Output-Fast-Read mode\n", + m_abyJEDEC_ID[0]); + + hsspi_dual_output_fast_read(reg_hsspi); + unCSCFG.DATA = (*reg_hsspi).CSCFG.DATA; + unCSCFG.bit.SRAM = HSSPI_EN_CSCFG_SRAM_RO; + unCSCFG.bit.MBM = HSSPI_EN_CSCFG_MBM_DUAL; + (*reg_hsspi).CSCFG.DATA = unCSCFG.DATA; + } else { + SYNQUACER_DEV_LOG_INFO( + "[HS-SPI] Configuring Quad-Output-Fast-Read mode\n"); + + hsspi_quad_output_fast_read(reg_hsspi); + unCSCFG.DATA = (*reg_hsspi).CSCFG.DATA; + unCSCFG.bit.SRAM = HSSPI_EN_CSCFG_SRAM_RO; + unCSCFG.bit.MBM = HSSPI_EN_CSCFG_MBM_QUAD; + (*reg_hsspi).CSCFG.DATA = unCSCFG.DATA; + } + +#ifdef CONFIG_SCB_USE_4BYTE_MODE + /* Enter 4-byte mode */ + hsspi_write_command_direct( + reg_hsspi, mem_hsspi, HSSPI_EN_STARTUP_COMMAND_WEN); + hsspi_write_command_direct( + reg_hsspi, mem_hsspi, HSSPI_EN_STARTUP_COMMAND_ENTER_4B); +#endif /* CONFIG_SCB_USE_4BYTE_MODE */ + + hsspi_stop(reg_hsspi, clk_sel, syncon); + + unPCC.DATA = (*reg_hsspi).PCC[0].DATA; /* Read original Value*/ + if (clk_div == 1) + unPCC.bit.CDRS = (clk_div - 1); + else + unPCC.bit.CDRS = (clk_div >> 1); + + (*reg_hsspi).PCC[0].DATA = unPCC.DATA; + + hsspi_csen(reg_hsspi, clk_sel, syncon); +} + +void hsspi_set_window_size( + volatile REG_ST_HSSPI_t *reg_hsspi, + int use_hsspi_cs1_flag, + HSSPI_EN_CSCFG_MSEL_t msel) +{ + HSSPI_UN_CSCFG_t unCSCFG; + + unCSCFG.DATA = (*reg_hsspi).CSCFG.DATA; + + unCSCFG.bit.SRAM = 1; + + unCSCFG.bit.MSEL = msel; + unCSCFG.bit.SSEL0EN = 1; + unCSCFG.bit.SSEL1EN = use_hsspi_cs1_flag; + (*reg_hsspi).CSCFG.DATA = unCSCFG.DATA; +} + +void hsspi_init(volatile REG_ST_HSSPI_t *reg_hsspi) +{ + HSSPI_UN_CSCFG_t unCSCFG; + + /* Stop HSSPI */ + (*reg_hsspi).MCTRL.bit.MEN = 0; + do { + __DSB(); + } while ((*reg_hsspi).MCTRL.bit.MES); + + (*reg_hsspi).MCTRL.bit.CSEN = 1; + + unCSCFG.DATA = (*reg_hsspi).CSCFG.DATA; + unCSCFG.bit.SRAM = 1; + unCSCFG.bit.MBM = 0; + unCSCFG.bit.BOOTEN = 0; + unCSCFG.bit.SSEL0EN = 1; + unCSCFG.bit.SSEL1EN = 0; + unCSCFG.bit.SSEL2EN = 0; + unCSCFG.bit.SSEL3EN = 0; + unCSCFG.bit.MSEL = HSSPI_EN_CSCFG_MSEL_256M; + + (*reg_hsspi).CSCFG.DATA = unCSCFG.DATA; + + (*reg_hsspi).MCTRL.bit.MEN = 1; +} + +void hsspi_exit( + volatile REG_ST_HSSPI_t *reg_hsspi, + volatile void *mem_hsspi, + volatile void *reg_boot_ctl, + HSSPI_EN_MCTRL_CDSS_t clk_sel, + int clk_div, + int syncon, + int use_hsspi_cs1_flag, + HSSPI_EN_CSCFG_MSEL_t msel) +{ + HSSPI_UN_PCC_t unPCC; + HSSPI_UN_CSCFG_t unCSCFG; + + hsspi_stop(reg_hsspi, clk_sel, syncon); + + unCSCFG.DATA = (*reg_hsspi).CSCFG.DATA; + unCSCFG.bit.MSEL = msel; + unCSCFG.bit.SSEL0EN = 1; + unCSCFG.bit.SSEL1EN = use_hsspi_cs1_flag; + unCSCFG.bit.BOOTEN = 0; + unCSCFG.bit.SRAM = HSSPI_EN_CSCFG_SRAM_RW; + unCSCFG.bit.MBM = HSSPI_EN_CSCFG_MBM_SINGLE; + (*reg_hsspi).CSCFG.DATA = unCSCFG.DATA; + (*reg_hsspi).CSITIME.DATA = 0x100; + + MEM_HSSPI_WORD(reg_boot_ctl)[0x008 >> 2] |= (1 << 0); + hsspi_csen(reg_hsspi, clk_sel, syncon); + + hsspi_software_reset(reg_hsspi, mem_hsspi); + + hsspi_stop(reg_hsspi, clk_sel, syncon); + + unPCC.DATA = (*reg_hsspi).PCC[0].DATA; /* Read original Value*/ + + if (clk_div == 1) + unPCC.bit.CDRS = (clk_div - 1); + else + unPCC.bit.CDRS = (clk_div >> 1); + + (*reg_hsspi).PCC[0].DATA = unPCC.DATA; + + hsspi_csen(reg_hsspi, clk_sel, syncon); + + /* set FAST_READ mode bit to run in FAST_READ after reboot */ + MEM_HSSPI_WORD(reg_boot_ctl)[0x008 >> 2] |= (0x1U << 1); + + MEM_HSSPI_WORD(reg_boot_ctl)[0x008 >> 2] &= ~(0x1U << 0); +} diff --git a/product/synquacer/module/hsspi/src/mod_hsspi.c b/product/synquacer/module/hsspi/src/mod_hsspi.c new file mode 100644 index 000000000..f4a49b294 --- /dev/null +++ b/product/synquacer/module/hsspi/src/mod_hsspi.c @@ -0,0 +1,70 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mod_hsspi_api module_api = { + .hsspi_init = HSSPI_init, + .hsspi_exit = HSSPI_exit, +}; + +/* + * Framework handlers + */ + +static int hsspi_controller_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + return FWK_SUCCESS; +} + +static int hsspi_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + +static int hsspi_process_bind_request( + fwk_id_t requester_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + *api = &module_api; + + return FWK_SUCCESS; +} + +static int hsspi_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +const struct fwk_module module_hsspi = { + .name = "hsspi", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = hsspi_controller_init, + .element_init = hsspi_element_init, + .start = hsspi_start, + .process_bind_request = hsspi_process_bind_request, +}; diff --git a/product/synquacer/module/ppu_v0_synquacer/include/mod_ppu_v0.h b/product/synquacer/module/ppu_v0_synquacer/include/mod_ppu_v0.h new file mode 100644 index 000000000..58bc9edc7 --- /dev/null +++ b/product/synquacer/module/ppu_v0_synquacer/include/mod_ppu_v0.h @@ -0,0 +1,72 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * PPU v0 driver module + */ + +#ifndef MOD_PPU_V0_H +#define MOD_PPU_V0_H + +#include +#include +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupSYNQUACER_PPUv0 PPUv0 Driver + * + * \brief PPUv0 device driver. + * + * \details This module implements a device driver for the PPUv0. + * Threre are 3 reasons why SynQuacer has custom PPUv0 driver. + * 1) Existing ppu_v0 does not support CLUSTER/CORE power management. + * 2) Synquacer needs special handling when PPU is set to OFF. + * 3) need special handling for setting MOD_PD_TYPE_SYSTEM to OFF. + * + * @{ + */ + +/*! + * \brief Power domain PPU descriptor. + */ +struct mod_ppu_v0 { + /*! Base address of the PPU registers */ + uintptr_t reg_base; + + /*! PPU's IRQ number */ + unsigned int irq; +}; + +/*! + * \brief Configuration data of a power domain of the PPU_V0 driver module. + */ +struct mod_ppu_v0_pd_config { + /*! Power domain type */ + enum mod_pd_type pd_type; + + /*! PPU descriptor */ + struct mod_ppu_v0 ppu; + + /*! + * Flag indicating if this domain should be powered on during element init. + */ + bool default_power_on; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_PPU_V0_H */ diff --git a/product/synquacer/module/ppu_v0_synquacer/include/ppu_v0.h b/product/synquacer/module/ppu_v0_synquacer/include/ppu_v0.h new file mode 100644 index 000000000..25e3fc08a --- /dev/null +++ b/product/synquacer/module/ppu_v0_synquacer/include/ppu_v0.h @@ -0,0 +1,147 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PPU_V0_H +#define PPU_V0_H + +/*! + * \cond + * @{ + */ + +#include +#include +#include + +struct ppu_v0_reg { + FWK_RW uint32_t POWER_POLICY; + FWK_R uint32_t POWER_STATUS; + FWK_R uint32_t STATIC_CFG_STATUS; + FWK_R uint32_t DEV_IF_IP_CUR_STATUS; + FWK_R uint32_t MISC_IP_CUR_STATUS; + FWK_R uint32_t STORED_STATUS; + FWK_W uint32_t OFF_MEM_RET_UNLOCK; + uint32_t RESERVED0; + FWK_RW uint32_t POWER_CFG; + uint32_t RESERVED1[3]; + FWK_RW uint32_t IMR; + FWK_RW uint32_t ISR; + FWK_RW uint32_t IESR; + uint32_t RESERVED2[5]; + FWK_RW uint32_t FUNC_RET_RAM_CFG; + FWK_RW uint32_t FULL_RET_RAM_CFG; + FWK_RW uint32_t MEM_RET_RAM_CFG; + uint32_t RESERVED3; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_0; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_1; + uint32_t RESERVED4[2]; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_0; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_1; + uint8_t RESERVED5[0xFC8 - 0x78]; + FWK_R uint32_t IMPLEMENTATION_ID; + FWK_R uint32_t ARCHITECTURE_ID; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t CID0; + FWK_R uint32_t CID1; + FWK_R uint32_t CID2; + FWK_R uint32_t CID3; +}; + +enum ppu_v0_mode { + PPU_V0_MODE_OFF = 0, + PPU_V0_MODE_MEM_RET = 1, + PPU_V0_MODE_LOGIC_RET = 2, + PPU_V0_MODE_FULL_RET = 3, + PPU_V0_MODE_MEM_OFF = 4, + PPU_V0_MODE_FUNC_RET = 5, + PPU_V0_MODE_ON = 6, + PPU_V0_MODE_WARM_RESET = 7, + PPU_V0_MODE_COUNT, +}; + +/* + * Bit definitions for PPR + */ +#define PPU_V0_PPR_POLICY UINT32_C(0x00000007) +#define PPU_V0_PPR_DYNAMIC_EN UINT32_C(0x00000100) +#define PPU_V0_PPR_EMULATED_EN UINT32_C(0x00000200) +#define PPU_V0_PPR_OFF_LOCK_EN UINT32_C(0x00001000) + +/* + * Bit definitions for PSR + */ +#define PPU_V0_PSR_EMULATED UINT32_C(0x00000200) +#define PPU_V0_PSR_DYNAMIC UINT32_C(0x00000100) +#define PPU_V0_PSR_POWSTAT UINT32_C(0x00000007) + +/* + * Bit definitions for IMR + */ +#define PPU_V0_IMR_MASK UINT32_C(0x010000FF) +#define PPU_V0_IMR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_IMR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_IMR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_IMR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_IMR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_IMR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_IMR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_IMR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_IMR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ISR + */ +#define PPU_V0_ISR_MASK UINT32_C(0x01FF01FF) +#define PPU_V0_ISR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_ISR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_ISR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_ISR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_ISR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_ISR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_ISR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_ISR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_ISR_DBGEMUPWRDWN_EDGE UINT32_C(0x00000100) +#define PPU_V0_ISR_ACTIVE_EDGE UINT32_C(0x00FF0000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE0 UINT32_C(0x00010000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE1 UINT32_C(0x00020000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE2 UINT32_C(0x00040000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE3 UINT32_C(0x00080000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE4 UINT32_C(0x00100000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE5 UINT32_C(0x00200000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE6 UINT32_C(0x00400000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE7 UINT32_C(0x00800000) +#define PPU_V0_ISR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ARCHITECTURE_ID + */ +#define PPU_V0_ARCHITECTURE_ID UINT32_C(0x00000000) + +#define PPU_PCR_DEV_ACTIVE_EN UINT32_C(0x0000FF00) +#define PPU_PCR_DEV_REQ_EN UINT32_C(0x000000FF) + +/* + * Interface + */ +void ppu_v0_init(struct ppu_v0_reg *ppu); +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode); + +/*! + * \endcond + * @} + */ + +#endif /* PPU_V0_H */ diff --git a/product/synquacer/module/ppu_v0_synquacer/src/Makefile b/product/synquacer/module/ppu_v0_synquacer/src/Makefile new file mode 100644 index 000000000..f4b54f2cc --- /dev/null +++ b/product/synquacer/module/ppu_v0_synquacer/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := PPU_V0 +BS_LIB_SOURCES = ppu_v0.c mod_ppu_v0.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/ppu_v0_synquacer/src/mod_ppu_v0.c b/product/synquacer/module/ppu_v0_synquacer/src/mod_ppu_v0.c new file mode 100644 index 000000000..223147b8b --- /dev/null +++ b/product/synquacer/module/ppu_v0_synquacer/src/mod_ppu_v0.c @@ -0,0 +1,387 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Power State Management PPU v0 driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if BUILD_HAS_MOD_SYSTEM_POWER +#include +#endif +#include + +/* Power domain context */ +struct ppu_v0_pd_ctx { + /* Power domain configuration data */ + const struct mod_ppu_v0_pd_config *config; + + /* PPU registers */ + struct ppu_v0_reg *ppu; + + /* Identifier of the entity bound to the power domain driver API */ + fwk_id_t bound_id; + + /* Power module driver input API */ + struct mod_pd_driver_input_api *pd_driver_input_api; +}; + +/* Module context */ +struct ppu_v0_ctx { + /* Table of the power domain contexts */ + struct ppu_v0_pd_ctx *pd_ctx_table; + + /* Log API */ + struct mod_log_api *log_api; +}; + +/* + * Internal variables + */ + +static struct ppu_v0_ctx ppu_v0_ctx; + +#define MODE_UNSUPPORTED ~0U +static const uint8_t ppu_mode_to_power_state[] = { + [PPU_V0_MODE_ON] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_FUNC_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_MEM_OFF] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_FULL_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_LOGIC_RET] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_MEM_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_OFF] = (uint8_t)MOD_PD_STATE_OFF, + [PPU_V0_MODE_WARM_RESET] = (uint8_t)MODE_UNSUPPORTED, +}; + +/* + * Power domain driver interface + */ + +/* Driver functions not specific to any type of power domain. */ +static int get_state(struct ppu_v0_reg *ppu, unsigned int *state) +{ + enum ppu_v0_mode ppu_mode; + + /* Ensure ppu_mode_to_power_state has an entry for each PPU state */ + static_assert( + FWK_ARRAY_SIZE(ppu_mode_to_power_state) == PPU_V0_MODE_COUNT, + "[MOD_PPU_V0] ppu_mode_to_power_state size error"); + + ppu_v0_get_power_mode(ppu, &ppu_mode); + assert(ppu_mode < PPU_V0_MODE_COUNT); + + *state = ppu_mode_to_power_state[ppu_mode]; + if (*state == MODE_UNSUPPORTED) { + ppu_v0_ctx.log_api->log( + MOD_LOG_GROUP_ERROR, + "[PPUV0] Unexpected PPU mode (%i).\n", + ppu_mode); + return FWK_E_DEVICE; + } + + ppu_v0_ctx.log_api->log( + MOD_LOG_GROUP_INFO, "[PPUV0] get state reg=0x%x (0x%x)\n", ppu, *state); + + return FWK_SUCCESS; +} + +static int pd_init(struct ppu_v0_pd_ctx *pd_ctx) +{ + ppu_v0_init(pd_ctx->ppu); + + return FWK_SUCCESS; +} + +static int pd_set_state(fwk_id_t pd_id, unsigned int state) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + status = fwk_module_check_call(pd_id); + if (status != FWK_SUCCESS) + return status; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + ppu_v0_ctx.log_api->log( + MOD_LOG_GROUP_INFO, + "[PPUV0] set_state start. reg=(0x%x) state=(0x%x)\n", + pd_ctx->ppu, + state); + + switch (state) { + case MOD_PD_STATE_ON: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_ON); + + ppu_v0_ctx.log_api->log( + MOD_LOG_GROUP_INFO, + "[PPUV0] set_state end. reg=(0x%x) state=(0x%x)\n", + pd_ctx->ppu, + state); + + assert(status == FWK_SUCCESS); + break; + + case MOD_PD_STATE_OFF: + if (pd_ctx->config->pd_type == MOD_PD_TYPE_SYSTEM) { + ppu_v0_ctx.log_api->log( + MOD_LOG_GROUP_INFO, + "[PPUV0] SYNQUACER SYSTEM module will shutdown the system\n"); + break; + } + + /* + * As it is not guaranteed that the PACTIVE signals of the core are low + * as the core may not be in WFI for example, deactivate the check of + * the PACTIVE signals by the PPU logic and the handshake with the core + * P-channel before to ask for the core to be powered off. + */ + pd_ctx->ppu->POWER_CFG &= ~PPU_PCR_DEV_ACTIVE_EN; + pd_ctx->ppu->POWER_CFG &= ~PPU_PCR_DEV_REQ_EN; + + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_OFF); + + ppu_v0_ctx.log_api->log( + MOD_LOG_GROUP_INFO, + "[PPUV0] set_state end. reg=(0x%x) state=(0x%x)\n", + pd_ctx->ppu, + state); + + assert(status == FWK_SUCCESS); + break; + + default: + ppu_v0_ctx.log_api->log( + MOD_LOG_GROUP_ERROR, + "[PPUV0] Requested power state (%i) is not supported.\n", + state); + return FWK_E_PARAM; + } + + return FWK_SUCCESS; +} + +static int pd_get_state(fwk_id_t pd_id, unsigned int *state) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + status = fwk_module_check_call(pd_id); + if (status != FWK_SUCCESS) + return status; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + return get_state(pd_ctx->ppu, state); +} + +static int pd_reset(fwk_id_t pd_id) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + status = fwk_module_check_call(pd_id); + if (status != FWK_SUCCESS) + return status; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + /* Model does not support warm reset at the moment. Using OFF instead. */ + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + if (status == FWK_SUCCESS) + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return status; +} + +static int ppu_v0_prepare_core_for_system_suspend(fwk_id_t core_pd_id) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + status = fwk_module_check_call(core_pd_id); + if (status != FWK_SUCCESS) + return status; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(core_pd_id); + ppu_v0_request_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + + return FWK_SUCCESS; +} + +static const struct mod_pd_driver_api pd_driver = { + .set_state = pd_set_state, + .get_state = pd_get_state, + .reset = pd_reset, + .prepare_core_for_system_suspend = ppu_v0_prepare_core_for_system_suspend, +}; + +/* + * Framework handlers + */ + +static int ppu_v0_mod_init( + fwk_id_t module_id, + unsigned int pd_count, + const void *unused) +{ + ppu_v0_ctx.pd_ctx_table = + fwk_mm_calloc(pd_count, sizeof(struct ppu_v0_pd_ctx)); + if (ppu_v0_ctx.pd_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int ppu_v0_pd_init(fwk_id_t pd_id, unsigned int unused, const void *data) +{ + const struct mod_ppu_v0_pd_config *config = data; + struct ppu_v0_pd_ctx *pd_ctx; + int status; + + if (config->pd_type >= MOD_PD_TYPE_COUNT) + return FWK_E_DATA; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + pd_ctx->config = config; + pd_ctx->ppu = (struct ppu_v0_reg *)(config->ppu.reg_base); + pd_ctx->bound_id = FWK_ID_NONE; + + switch (config->pd_type) { + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + case MOD_PD_TYPE_SYSTEM: + case MOD_PD_TYPE_CORE: + case MOD_PD_TYPE_CLUSTER: + status = pd_init(pd_ctx); + if (status != FWK_SUCCESS) + return status; + + if (config->default_power_on) + return ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return FWK_SUCCESS; + + default: + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_bind(fwk_id_t id, unsigned int round) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + /* Nothing to do during the first round of calls where the power module + will bind to the power domains of this module. */ + if (round == 0) + return FWK_SUCCESS; + + /* In the case of the module, bind to the log component */ + if (fwk_module_is_valid_module_id(id)) { + return fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_LOG), + FWK_ID_API(FWK_MODULE_IDX_LOG, 0), + &ppu_v0_ctx.log_api); + } + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(id); + + if (fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) + return FWK_SUCCESS; + + switch (fwk_id_get_module_idx(pd_ctx->bound_id)) { +#if BUILD_HAS_MOD_POWER_DOMAIN + case FWK_MODULE_IDX_POWER_DOMAIN: + return fwk_module_bind( + pd_ctx->bound_id, + mod_pd_api_id_driver_input, + &pd_ctx->pd_driver_input_api); + break; +#endif + +#if BUILD_HAS_MOD_SYSTEM_POWER + case FWK_MODULE_IDX_SYSTEM_POWER: + return fwk_module_bind( + pd_ctx->bound_id, + mod_system_power_api_id_pd_driver_input, + &pd_ctx->pd_driver_input_api); + break; +#endif + + default: + assert(false); + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t not_used, + const void **api) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(target_id); + + switch (pd_ctx->config->pd_type) { + case MOD_PD_TYPE_SYSTEM: + if (!fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) { + assert(false); + return FWK_E_ACCESS; + } + /* Fallthrough */ + + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + case MOD_PD_TYPE_CLUSTER: + case MOD_PD_TYPE_CORE: +#if BUILD_HAS_MOD_POWER_DOMAIN + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_POWER_DOMAIN) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } +#endif +#if BUILD_HAS_MOD_SYSTEM_POWER + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_SYSTEM_POWER) { + *api = &pd_driver; + break; + } +#endif + assert(false); + return FWK_E_ACCESS; + + default: + (void)pd_driver; + return FWK_E_SUPPORT; + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_ppu_v0_synquacer = { + .name = "PPU_V0_SYNQUACER", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = ppu_v0_mod_init, + .element_init = ppu_v0_pd_init, + .bind = ppu_v0_bind, + .process_bind_request = ppu_v0_process_bind_request, +}; diff --git a/product/synquacer/module/ppu_v0_synquacer/src/ppu_v0.c b/product/synquacer/module/ppu_v0_synquacer/src/ppu_v0.c new file mode 100644 index 000000000..4bb8498ec --- /dev/null +++ b/product/synquacer/module/ppu_v0_synquacer/src/ppu_v0.c @@ -0,0 +1,64 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +void ppu_v0_init(struct ppu_v0_reg *ppu) +{ + assert(ppu != NULL); + + /* Set mode as masked to all input edge interrupts */ + ppu->IESR = 0; + + /* Mask all interrupts */ + ppu->IMR = PPU_V0_IMR_MASK; + + /* Acknowledge any interrupt left pending */ + ppu->ISR = PPU_V0_ISR_MASK; +} + +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + uint32_t power_policy; + assert(ppu != NULL); + assert(mode < PPU_V0_MODE_COUNT); + + power_policy = + ppu->POWER_POLICY & ~(PPU_V0_PPR_POLICY | PPU_V0_PPR_DYNAMIC_EN); + ppu->POWER_POLICY = power_policy | mode; + + return FWK_SUCCESS; +} + +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + int status; + assert(ppu != NULL); + + status = ppu_v0_request_power_mode(ppu, mode); + if (status != FWK_SUCCESS) + return status; + + while ((ppu->POWER_STATUS & (PPU_V0_PSR_POWSTAT | PPU_V0_PSR_DYNAMIC)) != + mode) + continue; + + return FWK_SUCCESS; +} + +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode) +{ + assert(ppu != NULL); + assert(mode != NULL); + + *mode = (enum ppu_v0_mode)(ppu->POWER_STATUS & PPU_V0_PSR_POWSTAT); + + return FWK_SUCCESS; +} diff --git a/product/synquacer/module/scmi_vendor_ext/include/internal/scmi_vendor_ext.h b/product/synquacer/module/scmi_vendor_ext/include/internal/scmi_vendor_ext.h new file mode 100644 index 000000000..2f61d9d73 --- /dev/null +++ b/product/synquacer/module/scmi_vendor_ext/include/internal/scmi_vendor_ext.h @@ -0,0 +1,105 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * System Control and Management Interface (SCMI) support. + */ + +#ifndef SCMI_VENDOR_EXT_H +#define SCMI_VENDOR_EXT_H + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupSCMI_VendorEXT SCMI vendor extension protocol + * + * \brief SCMI vendor extension protocol. + * + * \details This module implements a SCMI vendor extension protocol. + * + * @{ + */ + +/*! SCMI protocol id for vendor extension message. */ +#define SCMI_PROTOCOL_ID_VENDOR_EXT UINT32_C(0x80) +/*! SCMI version. */ +#define SCMI_PROTOCOL_VERSION_VENDOR_EXT UINT32_C(0x10000) + +/*! + * \brief Identifiers of the SCMI Vendor extension Protocol commands. + */ +enum scmi_vendor_ext_command_id { + /*! Retrieve DRAM mapping information */ + SCMI_VENDOR_EXT_MEMORY_INFO_GET = 0x003, +}; + +/*! + * \brief PROTOCOL_ATTRIBUTES + */ +struct __attribute((packed)) scmi_vendor_ext_protocol_attributes_p2a { + /*! SCMI status. */ + int32_t status; + /*! attributes. */ + uint32_t attributes; +}; + +/* + * Memory Info get structure + */ + +/*! array size of memory information array. */ +#define SCMI_MEMORY_INFO_ARRAY_NUM_MAX (3) + +/*! + * \brief detailed memory mapping information. + */ +struct memory_info_array { + /*! dram region start address of lower 32-bits. */ + uint32_t start_offset_low; + /*! dram region start address of upper 32-bits. */ + uint32_t start_offset_high; + /*! dram size of lower 32-bits. */ + uint32_t size_low; + /*! dram size of upper 32-bits. */ + uint32_t size_high; +}; + +/*! + * \brief memory mapping information structure. + */ +struct __attribute((packed)) synquacer_memory_info { + /*! number of memory regions. */ + uint32_t array_num; + /*! reserved. */ + uint32_t reserved; + /*! array of memory regions. */ + struct memory_info_array memory_info_array[SCMI_MEMORY_INFO_ARRAY_NUM_MAX]; +}; + +/*! + * \brief memory mapping information response. + */ +struct scmi_vendor_ext_memory_info_get_resp { + /*! SCMI status. */ + int status; + /*! reserved. */ + int reserved; + /*! pointer to the momory information array. */ + struct synquacer_memory_info meminfo; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* SCMI_VENDOR_EXT_H */ diff --git a/product/synquacer/module/scmi_vendor_ext/src/Makefile b/product/synquacer/module/scmi_vendor_ext/src/Makefile new file mode 100644 index 000000000..df48f0733 --- /dev/null +++ b/product/synquacer/module/scmi_vendor_ext/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := SCMI Vendor extension Protocol +BS_LIB_SOURCES := mod_scmi_vendor_ext.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/scmi_vendor_ext/src/mod_scmi_vendor_ext.c b/product/synquacer/module/scmi_vendor_ext/src/mod_scmi_vendor_ext.c new file mode 100644 index 000000000..7adfae2cb --- /dev/null +++ b/product/synquacer/module/scmi_vendor_ext/src/mod_scmi_vendor_ext.c @@ -0,0 +1,342 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct scmi_vendor_ext_ctx { + const struct mod_scmi_from_protocol_api *scmi_api; + const struct mod_vendor_ext_api *vendor_ext_api; + const struct mod_log_api *log_api; + uint32_t vendor_ext_count; +}; + +static int scmi_vendor_ext_protocol_version_handler( + fwk_id_t service_id, + const uint32_t *payload); +static int scmi_vendor_ext_protocol_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload); +static int scmi_vendor_ext_protocol_msg_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload); +static int scmi_vendor_ext_protocol_memory_info_get_handler( + fwk_id_t service_id, + const uint32_t *payload); + +/* + * Internal variables. + */ +static struct scmi_vendor_ext_ctx scmi_vendor_ext_ctx; + +static int (*handler_table[])(fwk_id_t, const uint32_t *) = { + [SCMI_PROTOCOL_VERSION] = scmi_vendor_ext_protocol_version_handler, + [SCMI_PROTOCOL_ATTRIBUTES] = scmi_vendor_ext_protocol_attributes_handler, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = + scmi_vendor_ext_protocol_msg_attributes_handler, + [SCMI_VENDOR_EXT_MEMORY_INFO_GET] = + scmi_vendor_ext_protocol_memory_info_get_handler, +}; + +static unsigned int payload_size_table[] = { + [SCMI_PROTOCOL_VERSION] = 0, + [SCMI_PROTOCOL_ATTRIBUTES] = 0, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = + sizeof(struct scmi_protocol_message_attributes_a2p), + [SCMI_VENDOR_EXT_MEMORY_INFO_GET] = 0, +}; + +/* + * vendor_ext management protocol implementation + */ +static int scmi_vendor_ext_protocol_version_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_VENDOR_EXT, + }; + + scmi_vendor_ext_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + + return FWK_SUCCESS; +} + +static int scmi_vendor_ext_protocol_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + struct scmi_vendor_ext_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = scmi_vendor_ext_ctx.vendor_ext_count, + }; + + scmi_vendor_ext_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + + return FWK_SUCCESS; +} + +static int scmi_vendor_ext_protocol_msg_attributes_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + const struct scmi_protocol_message_attributes_a2p *parameters; + struct scmi_protocol_message_attributes_p2a return_values; + + parameters = (const struct scmi_protocol_message_attributes_a2p *)payload; + + if ((parameters->message_id < FWK_ARRAY_SIZE(handler_table)) && + (handler_table[parameters->message_id] != NULL)) { + return_values = (struct scmi_protocol_message_attributes_p2a) { + .status = SCMI_SUCCESS, + /* All commands have an attributes value of 0 */ + .attributes = 0, + }; + } else + return_values.status = SCMI_NOT_FOUND; + + scmi_vendor_ext_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + return FWK_SUCCESS; +} + +static const uint64_t ddr_memorymap_start_addr[] = { DRAM_AREA_1_START_ADDR, + DRAM_AREA_2_START_ADDR, + DRAM_AREA_3_START_ADDR }; + +static const uint64_t ddr_memorymap_size[] = { DRAM_AREA_1_SIZE, + DRAM_AREA_2_SIZE, + DRAM_AREA_3_SIZE }; + +static void fill_available_dram_region( + uint32_t *memory_array_count_num, + uint64_t *area_start, + uint64_t *area_size) +{ + uint32_t i; + uint64_t dram_size; + uint64_t allocated_size; + + dram_size = (uint64_t)fw_get_ddr4_sdram_total_size() * 1024 * 1024; + + for (i = 0; (i < SCMI_MEMORY_INFO_ARRAY_NUM_MAX) && (dram_size > 0); i++) { + area_start[i] = ddr_memorymap_start_addr[i]; + allocated_size = dram_size > ddr_memorymap_size[i] ? + ddr_memorymap_size[i] : + dram_size; + area_size[i] = allocated_size; + + dram_size -= allocated_size; + } + + *memory_array_count_num = i; +} + +static int get_memory_info(struct synquacer_memory_info *meminfo) +{ + uint32_t i; + uint32_t memory_array_count_num = 0; + uint64_t area_start[SCMI_MEMORY_INFO_ARRAY_NUM_MAX] = { 0 }; + uint64_t area_size[SCMI_MEMORY_INFO_ARRAY_NUM_MAX] = { 0 }; + + fill_available_dram_region(&memory_array_count_num, area_start, area_size); + + if (ddr_is_secure_dram_enabled()) + area_size[0] -= DRAM_RESERVED_FOR_SECURE_APP_SIZE; + + for (i = 0, meminfo->array_num = 0; i < memory_array_count_num; i++) { + meminfo->memory_info_array[i].start_offset_low = + (uint32_t)(area_start[i] & 0xFFFFFFFFU); + + meminfo->memory_info_array[i].start_offset_high = + (uint32_t)(area_start[i] >> 32); + + meminfo->memory_info_array[i].size_low = + (uint32_t)(area_size[i] & 0xFFFFFFFFU); + + meminfo->memory_info_array[i].size_high = + (uint32_t)(area_size[i] >> 32); + + meminfo->array_num++; + } + + return FWK_SUCCESS; +} + +static struct scmi_vendor_ext_memory_info_get_resp resp; + +static int scmi_vendor_ext_protocol_memory_info_get_handler( + fwk_id_t service_id, + const uint32_t *payload) +{ + memset(&resp, 0, sizeof(struct scmi_vendor_ext_memory_info_get_resp)); + + scmi_vendor_ext_ctx.log_api->log( + MOD_LOG_GROUP_DEBUG, "[scmi_vendor_ext] memory info get handler.\n"); + + get_memory_info(&resp.meminfo); + + scmi_vendor_ext_ctx.scmi_api->respond(service_id, &resp, sizeof(resp)); + + return FWK_SUCCESS; +} + +/* + * SCMI module -> SCMI vendor_ext module interface + */ +static int scmi_vendor_ext_get_scmi_protocol_id( + fwk_id_t protocol_id, + uint8_t *scmi_protocol_id) +{ + int status; + + status = fwk_module_check_call(protocol_id); + if (status != FWK_SUCCESS) + return status; + + *scmi_protocol_id = SCMI_PROTOCOL_ID_VENDOR_EXT; + + return FWK_SUCCESS; +} + +static int scmi_vendor_ext_message_handler( + fwk_id_t protocol_id, + fwk_id_t service_id, + const uint32_t *payload, + size_t payload_size, + unsigned int message_id) +{ + int status; + int32_t return_value; + + scmi_vendor_ext_ctx.log_api->log( + MOD_LOG_GROUP_DEBUG, "[scmi_vendor_ext] message handler.\n"); + + status = fwk_module_check_call(protocol_id); + if (status != FWK_SUCCESS) + return status; + + static_assert( + FWK_ARRAY_SIZE(handler_table) == FWK_ARRAY_SIZE(payload_size_table), + "[SCMI] vendor_ext management protocol table sizes not consistent"); + assert(payload != NULL); + + if (message_id >= FWK_ARRAY_SIZE(handler_table)) { + return_value = SCMI_NOT_SUPPORTED; + goto error; + } + + if (payload_size != payload_size_table[message_id]) { + return_value = SCMI_PROTOCOL_ERROR; + goto error; + } + + return handler_table[message_id](service_id, payload); + +error: + scmi_vendor_ext_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); + return FWK_SUCCESS; +} + +static struct mod_scmi_to_protocol_api + scmi_vendor_ext_mod_scmi_to_protocol_api = { + .get_scmi_protocol_id = scmi_vendor_ext_get_scmi_protocol_id, + .message_handler = scmi_vendor_ext_message_handler + }; + +/* + * Framework interface + */ +static int scmi_vendor_ext_init( + fwk_id_t module_id, + unsigned int element_count, + const void *unused) +{ + if (element_count != 0) { + /* This module should not have any elements */ + assert(false); + return FWK_E_SUPPORT; + } + + return FWK_SUCCESS; +} + +static int scmi_vendor_ext_bind(fwk_id_t id, unsigned int round) +{ + int status; + + if (round == 1) + return FWK_SUCCESS; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_LOG), + FWK_ID_API(FWK_MODULE_IDX_LOG, 0), + &scmi_vendor_ext_ctx.log_api); + if (status != FWK_SUCCESS) + return status; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_SCMI), + FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_PROTOCOL), + &scmi_vendor_ext_ctx.scmi_api); + if (status != FWK_SUCCESS) { + /* Failed to bind to SCMI module */ + assert(false); + return status; + } + + return FWK_SUCCESS; +} + +static int scmi_vendor_ext_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + if (!fwk_id_is_equal(source_id, FWK_ID_MODULE(FWK_MODULE_IDX_SCMI))) + return FWK_E_ACCESS; + + scmi_vendor_ext_ctx.log_api->log( + MOD_LOG_GROUP_DEBUG, "[scmi_vendor_ext] process bind request.\n"); + + *api = &scmi_vendor_ext_mod_scmi_to_protocol_api; + + return FWK_SUCCESS; +} + +const struct fwk_module module_scmi_vendor_ext = { + .name = "SCMI vendor_ext management", + .api_count = 1, + .type = FWK_MODULE_TYPE_PROTOCOL, + .init = scmi_vendor_ext_init, + .bind = scmi_vendor_ext_bind, + .process_bind_request = scmi_vendor_ext_process_bind_request, +}; + +/* No elements, no module configuration data */ +struct fwk_module_config config_scmi_vendor_ext = { 0 }; diff --git a/product/synquacer/module/synquacer_memc/include/ddr_init.h b/product/synquacer/module/synquacer_memc/include/ddr_init.h new file mode 100644 index 000000000..9b56cee54 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/include/ddr_init.h @@ -0,0 +1,58 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DDR_INIT_H +#define DDR_INIT_H + +#include +#include +#include +#include + +#include +#include + +#define printf(...) SYNQUACER_DEV_LOG_INFO("[DDR] " __VA_ARGS__) +#define pr_err(...) SYNQUACER_DEV_LOG_ERROR("[DDR] " __VA_ARGS__) + +#define dmb __DMB +#define usleep(usec) osDelay((usec / 1000) + 2) + +#define REG_DDRPHY_CONFIG_0_BA UINT32_C(0x7F210000) +#define REG_DDRPHY_CONFIG_1_BA UINT32_C(0x7F610000) + +#define REG_DMC520_0_BA UINT32_C(0x4E000000) +#define REG_DMC520_1_BA UINT32_C(0x4E100000) +#define REG_DMC520_3_BA UINT32_C(0x4E300000) + +#define DDR_TRAINING_ON +#define DDR_WAIT_TIMEOUT_US UINT32_C(1000000) + +/** + * Wait until BUSY_COND becomes false or timeouts. + * Return from the caller function with ERR_CODE if timeout occurs. + * Continue execution otherwise. + * + * The expression BUSY_COND is evaluated in each repetition. + */ +#define ddr_wait(BUSY_COND, TIMEOUT_US, ERR_CODE) \ + do { \ + uint32_t tick = osKernelSysTick(); \ + while (BUSY_COND) { \ + if (osKernelSysTick() - tick >= \ + osKernelSysTickMicroSec(TIMEOUT_US)) { \ + return ERR_CODE; \ + } \ + } \ + } while (false) + +extern int ddr_dual_ch_init_mp(void); +extern int ddr_ch0_init_mp(void); +extern int ddr_ch1_init_mp(void); +extern uint8_t ddr_is_secure_dram_enabled(void); + +#endif /*DDR_INIT_H */ diff --git a/product/synquacer/module/synquacer_memc/include/internal/reg_DDRPHY_CONFIG.h b/product/synquacer/module/synquacer_memc/include/internal/reg_DDRPHY_CONFIG.h new file mode 100644 index 000000000..8a20b6519 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/include/internal/reg_DDRPHY_CONFIG.h @@ -0,0 +1,1040 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REG_DDRPHY_CONFIG_H +#define REG_DDRPHY_CONFIG_H + +#include + +typedef volatile struct { + uint32_t RIDR; // 0x000 + uint32_t PIR; // 0x001 + uint32_t CGCR; // 0x002 + uint32_t CGCR1; // 0x003 + uint32_t PGCR0; // 0x004 + uint32_t PGCR1; // 0x005 + uint32_t PGCR2; // 0x006 + uint32_t PGCR3; // 0x007 + uint32_t PGCR4; // 0x008 + uint32_t PGCR5; // 0x009 + uint32_t PGCR6; // 0x00A + uint32_t PGCR7; // 0x00B + uint32_t PGCR8; // 0x00C + uint32_t PGSR0; // 0x00D + uint32_t PGSR1; // 0x00E + uint32_t __Reserved_00F__; // 0x00F + uint32_t PTR0; // 0x010 + uint32_t PTR1; // 0x011 + uint32_t PTR2; // 0x012 + uint32_t PTR3; // 0x013 + uint32_t PTR4; // 0x014 + uint32_t PTR5; // 0x015 + uint32_t PTR6; // 0x016 + uint32_t __Reserved_017__; // 0x017 + uint32_t __Reserved_018__; // 0x018 + uint32_t __Reserved_019__; // 0x019 + uint32_t PLLCR0; // 0x01A + uint32_t PLLCR1; // 0x01B + uint32_t PLLCR2; // 0x01C + uint32_t PLLCR3; // 0x01D + uint32_t PLLCR4; // 0x01E + uint32_t PLLCR5; // 0x01F + uint32_t PLLCR; // 0x020 + uint32_t __Reserved_021__; // 0x021 + uint32_t DXCCR; // 0x022 + uint32_t __Reserved_023__; // 0x023 + uint32_t DSGCR; // 0x024 + uint32_t __Reserved_025__; // 0x025 + uint32_t ODTCR; // 0x026 + uint32_t __Reserved_027__; // 0x027 + uint32_t AACR; // 0x028 + uint32_t __Reserved_029__; // 0x029 + uint32_t __Reserved_02A__; // 0x02A + uint32_t __Reserved_02B__; // 0x02B + uint32_t __Reserved_02C__; // 0x02C + uint32_t __Reserved_02D__; // 0x02D + uint32_t __Reserved_02E__; // 0x02E + uint32_t __Reserved_02F__; // 0x02F + uint32_t GPR0; // 0x030 + uint32_t GPR1; // 0x031 + uint32_t __Reserved_032__; // 0x032 + uint32_t __Reserved_033__; // 0x033 + uint32_t __Reserved_034__; // 0x034 + uint32_t __Reserved_035__; // 0x035 + uint32_t __Reserved_036__; // 0x036 + uint32_t __Reserved_037__; // 0x037 + uint32_t __Reserved_038__; // 0x038 + uint32_t __Reserved_039__; // 0x039 + uint32_t __Reserved_03A__; // 0x03A + uint32_t __Reserved_03B__; // 0x03B + uint32_t __Reserved_03C__; // 0x03C + uint32_t __Reserved_03D__; // 0x03D + uint32_t __Reserved_03E__; // 0x03E + uint32_t __Reserved_03F__; // 0x03F + uint32_t DCR; // 0x040 + uint32_t __Reserved_041__; // 0x041 + uint32_t __Reserved_042__; // 0x042 + uint32_t __Reserved_043__; // 0x043 + uint32_t DTPR0; // 0x044 + uint32_t DTPR1; // 0x045 + uint32_t DTPR2; // 0x046 + uint32_t DTPR3; // 0x047 + uint32_t DTPR4; // 0x048 + uint32_t DTPR5; // 0x049 + uint32_t DTPR6; // 0x04A + uint32_t __Reserved_04B__; // 0x04B + uint32_t __Reserved_04C__; // 0x04C + uint32_t __Reserved_04D__; // 0x04D + uint32_t __Reserved_04E__; // 0x04E + uint32_t __Reserved_04F__; // 0x04F + uint32_t RDIMMGCR0; // 0x050 + uint32_t RDIMMGCR1; // 0x051 + uint32_t RDIMMGCR2; // 0x052 + uint32_t __Reserved_053__; // 0x053 + uint32_t RDIMMCR0; // 0x054 + uint32_t RDIMMCR1; // 0x055 + uint32_t RDIMMCR2; // 0x056 + uint32_t RDIMMCR3; // 0x057 + uint32_t RDIMMCR4; // 0x058 + uint32_t __Reserved_059__; // 0x059 + uint32_t SCHCR0; // 0x05A + uint32_t SCHCR1; // 0x05B + uint32_t __Reserved_05C__; // 0x05C + uint32_t __Reserved_05D__; // 0x05D + uint32_t __Reserved_05E__; // 0x05E + uint32_t __Reserved_05F__; // 0x05F + uint32_t MR0; // 0x060 + uint32_t MR1; // 0x061 + uint32_t MR2; // 0x062 + uint32_t MR3; // 0x063 + uint32_t MR4; // 0x064 + uint32_t MR5; // 0x065 + uint32_t MR6; // 0x066 + uint32_t MR7; // 0x067 + uint32_t __Reserved_068__; // 0x068 + uint32_t __Reserved_069__; // 0x069 + uint32_t __Reserved_06A__; // 0x06A + uint32_t MR11; // 0x06B + uint32_t __Reserved_06C__; // 0x06C + uint32_t __Reserved_06D__; // 0x06D + uint32_t __Reserved_06E__; // 0x06E + uint32_t __Reserved_06F__; // 0x06F + uint32_t __Reserved_070__; // 0x070 + uint32_t __Reserved_071__; // 0x071 + uint32_t __Reserved_072__; // 0x072 + uint32_t __Reserved_073__; // 0x073 + uint32_t __Reserved_074__; // 0x074 + uint32_t __Reserved_075__; // 0x075 + uint32_t __Reserved_076__; // 0x076 + uint32_t __Reserved_077__; // 0x077 + uint32_t __Reserved_078__; // 0x078 + uint32_t __Reserved_079__; // 0x079 + uint32_t __Reserved_07A__; // 0x07A + uint32_t __Reserved_07B__; // 0x07B + uint32_t __Reserved_07C__; // 0x07C + uint32_t __Reserved_07D__; // 0x07D + uint32_t __Reserved_07E__; // 0x07E + uint32_t __Reserved_07F__; // 0x07F + uint32_t DTCR0; // 0x080 + uint32_t DTCR1; // 0x081 + uint32_t DTAR0; // 0x082 + uint32_t DTAR1; // 0x083 + uint32_t DTAR2; // 0x084 + uint32_t __Reserved_085__; // 0x085 + uint32_t DTDR0; // 0x086 + uint32_t DTDR1; // 0x087 + uint32_t UDDR0; // 0x088 + uint32_t UDDR1; // 0x089 + uint32_t __Reserved_08A__; // 0x08A + uint32_t __Reserved_08B__; // 0x08B + uint32_t DTEDR0; // 0x08C + uint32_t DTEDR1; // 0x08D + uint32_t DTEDR2; // 0x08E + uint32_t VTDR; // 0x08F + uint32_t CATR0; // 0x090 + uint32_t CATR1; // 0x091 + uint32_t __Reserved_092__; // 0x092 + uint32_t __Reserved_093__; // 0x093 + uint32_t DQSDR0; // 0x094 + uint32_t DQSDR1; // 0x095 + uint32_t DQSDR2; // 0x096 + uint32_t __Reserved_097__; // 0x097 + uint32_t __Reserved_098__; // 0x098 + uint32_t __Reserved_099__; // 0x099 + uint32_t __Reserved_09A__; // 0x09A + uint32_t __Reserved_09B__; // 0x09B + uint32_t __Reserved_09C__; // 0x09C + uint32_t __Reserved_09D__; // 0x09D + uint32_t __Reserved_09E__; // 0x09E + uint32_t __Reserved_09F__; // 0x09F + uint32_t __Reserved_0A0__; // 0x0A0 + uint32_t __Reserved_0A1__; // 0x0A1 + uint32_t __Reserved_0A2__; // 0x0A2 + uint32_t __Reserved_0A3__; // 0x0A3 + uint32_t __Reserved_0A4__; // 0x0A4 + uint32_t __Reserved_0A5__; // 0x0A5 + uint32_t __Reserved_0A6__; // 0x0A6 + uint32_t __Reserved_0A7__; // 0x0A7 + uint32_t __Reserved_0A8__; // 0x0A8 + uint32_t __Reserved_0A9__; // 0x0A9 + uint32_t __Reserved_0AA__; // 0x0AA + uint32_t __Reserved_0AB__; // 0x0AB + uint32_t __Reserved_0AC__; // 0x0AC + uint32_t __Reserved_0AD__; // 0x0AD + uint32_t __Reserved_0AE__; // 0x0AE + uint32_t __Reserved_0AF__; // 0x0AF + uint32_t __Reserved_0B0__; // 0x0B0 + uint32_t __Reserved_0B1__; // 0x0B1 + uint32_t __Reserved_0B2__; // 0x0B2 + uint32_t __Reserved_0B3__; // 0x0B3 + uint32_t __Reserved_0B4__; // 0x0B4 + uint32_t __Reserved_0B5__; // 0x0B5 + uint32_t __Reserved_0B6__; // 0x0B6 + uint32_t __Reserved_0B7__; // 0x0B7 + uint32_t __Reserved_0B8__; // 0x0B8 + uint32_t __Reserved_0B9__; // 0x0B9 + uint32_t __Reserved_0BA__; // 0x0BA + uint32_t __Reserved_0BB__; // 0x0BB + uint32_t __Reserved_0BC__; // 0x0BC + uint32_t __Reserved_0BD__; // 0x0BD + uint32_t __Reserved_0BE__; // 0x0BE + uint32_t __Reserved_0BF__; // 0x0BF + uint32_t DCUAR; // 0x0C0 + uint32_t DCUDR; // 0x0C1 + uint32_t DCURR; // 0x0C2 + uint32_t DCULR; // 0x0C3 + uint32_t DCUGCR; // 0x0C4 + uint32_t DCUTPR; // 0x0C5 + uint32_t DCUSR0; // 0x0C6 + uint32_t DCUSR1; // 0x0C7 + uint32_t __Reserved_0C8__; // 0x0C8 + uint32_t __Reserved_0C9__; // 0x0C9 + uint32_t __Reserved_0CA__; // 0x0CA + uint32_t __Reserved_0CB__; // 0x0CB + uint32_t __Reserved_0CC__; // 0x0CC + uint32_t __Reserved_0CD__; // 0x0CD + uint32_t __Reserved_0CE__; // 0x0CE + uint32_t __Reserved_0CF__; // 0x0CF + uint32_t __Reserved_0D0__; // 0x0D0 + uint32_t __Reserved_0D1__; // 0x0D1 + uint32_t __Reserved_0D2__; // 0x0D2 + uint32_t __Reserved_0D3__; // 0x0D3 + uint32_t __Reserved_0D4__; // 0x0D4 + uint32_t __Reserved_0D5__; // 0x0D5 + uint32_t __Reserved_0D6__; // 0x0D6 + uint32_t __Reserved_0D7__; // 0x0D7 + uint32_t __Reserved_0D8__; // 0x0D8 + uint32_t __Reserved_0D9__; // 0x0D9 + uint32_t __Reserved_0DA__; // 0x0DA + uint32_t __Reserved_0DB__; // 0x0DB + uint32_t __Reserved_0DC__; // 0x0DC + uint32_t __Reserved_0DD__; // 0x0DD + uint32_t __Reserved_0DE__; // 0x0DE + uint32_t __Reserved_0DF__; // 0x0DF + uint32_t __Reserved_0E0__; // 0x0E0 + uint32_t __Reserved_0E1__; // 0x0E1 + uint32_t __Reserved_0E2__; // 0x0E2 + uint32_t __Reserved_0E3__; // 0x0E3 + uint32_t __Reserved_0E4__; // 0x0E4 + uint32_t __Reserved_0E5__; // 0x0E5 + uint32_t __Reserved_0E6__; // 0x0E6 + uint32_t __Reserved_0E7__; // 0x0E7 + uint32_t __Reserved_0E8__; // 0x0E8 + uint32_t __Reserved_0E9__; // 0x0E9 + uint32_t __Reserved_0EA__; // 0x0EA + uint32_t __Reserved_0EB__; // 0x0EB + uint32_t __Reserved_0EC__; // 0x0EC + uint32_t __Reserved_0ED__; // 0x0ED + uint32_t __Reserved_0EE__; // 0x0EE + uint32_t __Reserved_0EF__; // 0x0EF + uint32_t __Reserved_0F0__; // 0x0F0 + uint32_t __Reserved_0F1__; // 0x0F1 + uint32_t __Reserved_0F2__; // 0x0F2 + uint32_t __Reserved_0F3__; // 0x0F3 + uint32_t __Reserved_0F4__; // 0x0F4 + uint32_t __Reserved_0F5__; // 0x0F5 + uint32_t __Reserved_0F6__; // 0x0F6 + uint32_t __Reserved_0F7__; // 0x0F7 + uint32_t __Reserved_0F8__; // 0x0F8 + uint32_t __Reserved_0F9__; // 0x0F9 + uint32_t __Reserved_0FA__; // 0x0FA + uint32_t __Reserved_0FB__; // 0x0FB + uint32_t __Reserved_0FC__; // 0x0FC + uint32_t __Reserved_0FD__; // 0x0FD + uint32_t __Reserved_0FE__; // 0x0FE + uint32_t __Reserved_0FF__; // 0x0FF + uint32_t BISTRR; // 0x100 + uint32_t BISTWCR; // 0x101 + uint32_t BISTMSKR0; // 0x102 + uint32_t BISTMSKR1; // 0x103 + uint32_t BISTMSKR2; // 0x104 + uint32_t BISTLSR; // 0x105 + uint32_t BISTAR0; // 0x106 + uint32_t BISTAR1; // 0x107 + uint32_t BISTAR2; // 0x108 + uint32_t BISTAR3; // 0x109 + uint32_t BISTAR4; // 0x10A + uint32_t BISTUDPR; // 0x10B + uint32_t BISTGSR; // 0x10C + uint32_t BISTWER0; // 0x10D + uint32_t BISTWER1; // 0x10E + uint32_t BISTBER0; // 0x10F + uint32_t BISTBER1; // 0x110 + uint32_t BISTBER2; // 0x111 + uint32_t BISTBER3; // 0x112 + uint32_t BISTBER4; // 0x113 + uint32_t BISTWCSR; // 0x114 + uint32_t BISTFWR0; // 0x115 + uint32_t BISTFWR1; // 0x116 + uint32_t BISTFWR2; // 0x117 + uint32_t BISTBER5; // 0x118 + uint32_t __Reserved_119__; // 0x119 + uint32_t __Reserved_11A__; // 0x11A + uint32_t __Reserved_11B__; // 0x11B + uint32_t __Reserved_11C__; // 0x11C + uint32_t __Reserved_11D__; // 0x11D + uint32_t __Reserved_11E__; // 0x11E + uint32_t __Reserved_11F__; // 0x11F + uint32_t __Reserved_120__; // 0x120 + uint32_t __Reserved_121__; // 0x121 + uint32_t __Reserved_122__; // 0x122 + uint32_t __Reserved_123__; // 0x123 + uint32_t __Reserved_124__; // 0x124 + uint32_t __Reserved_125__; // 0x125 + uint32_t __Reserved_126__; // 0x126 + uint32_t __Reserved_127__; // 0x127 + uint32_t __Reserved_128__; // 0x128 + uint32_t __Reserved_129__; // 0x129 + uint32_t __Reserved_12A__; // 0x12A + uint32_t __Reserved_12B__; // 0x12B + uint32_t __Reserved_12C__; // 0x12C + uint32_t __Reserved_12D__; // 0x12D + uint32_t __Reserved_12E__; // 0x12E + uint32_t __Reserved_12F__; // 0x12F + uint32_t __Reserved_130__; // 0x130 + uint32_t __Reserved_131__; // 0x131 + uint32_t __Reserved_132__; // 0x132 + uint32_t __Reserved_133__; // 0x133 + uint32_t __Reserved_134__; // 0x134 + uint32_t __Reserved_135__; // 0x135 + uint32_t __Reserved_136__; // 0x136 + uint32_t RANKIDR; // 0x137 + uint32_t RIOCR0; // 0x138 + uint32_t RIOCR1; // 0x139 + uint32_t RIOCR2; // 0x13A + uint32_t RIOCR3; // 0x13B + uint32_t RIOCR4; // 0x13C + uint32_t RIOCR5; // 0x13D + uint32_t __Reserved_13E__; // 0x13E + uint32_t __Reserved_13F__; // 0x13F + uint32_t ACIOCR0; // 0x140 + uint32_t ACIOCR1; // 0x141 + uint32_t ACIOCR2; // 0x142 + uint32_t ACIOCR3; // 0x143 + uint32_t ACIOCR4; // 0x144 + uint32_t ACIOCR5; // 0x145 + uint32_t __Reserved_146__; // 0x146 + uint32_t __Reserved_147__; // 0x147 + uint32_t IOVCR0; // 0x148 + uint32_t IOVCR1; // 0x149 + uint32_t VTCR0; // 0x14A + uint32_t VTCR1; // 0x14B + uint32_t __Reserved_14C__; // 0x14C + uint32_t __Reserved_14D__; // 0x14D + uint32_t __Reserved_14E__; // 0x14E + uint32_t __Reserved_14F__; // 0x14F + uint32_t ACBDLR0; // 0x150 + uint32_t ACBDLR1; // 0x151 + uint32_t ACBDLR2; // 0x152 + uint32_t ACBDLR3; // 0x153 + uint32_t ACBDLR4; // 0x154 + uint32_t ACBDLR5; // 0x155 + uint32_t ACBDLR6; // 0x156 + uint32_t ACBDLR7; // 0x157 + uint32_t ACBDLR8; // 0x158 + uint32_t ACBDLR9; // 0x159 + uint32_t ACBDLR10; // 0x15A + uint32_t ACBDLR11; // 0x15B + uint32_t ACBDLR12; // 0x15C + uint32_t ACBDLR13; // 0x15D + uint32_t ACBDLR14; // 0x15E + uint32_t __Reserved_15F__; // 0x15F + uint32_t ACLCDLR; // 0x160 + uint32_t __Reserved_161__; // 0x161 + uint32_t __Reserved_162__; // 0x162 + uint32_t __Reserved_163__; // 0x163 + uint32_t __Reserved_164__; // 0x164 + uint32_t __Reserved_165__; // 0x165 + uint32_t __Reserved_166__; // 0x166 + uint32_t __Reserved_167__; // 0x167 + uint32_t ACMDLR0; // 0x168 + uint32_t ACMDLR1; // 0x169 + uint32_t __Reserved_16A__; // 0x16A + uint32_t __Reserved_16B__; // 0x16B + uint32_t __Reserved_16C__; // 0x16C + uint32_t __Reserved_16D__; // 0x16D + uint32_t __Reserved_16E__; // 0x16E + uint32_t __Reserved_16F__; // 0x16F + uint32_t __Reserved_170__; // 0x170 + uint32_t __Reserved_171__; // 0x171 + uint32_t __Reserved_172__; // 0x172 + uint32_t __Reserved_173__; // 0x173 + uint32_t __Reserved_174__; // 0x174 + uint32_t __Reserved_175__; // 0x175 + uint32_t __Reserved_176__; // 0x176 + uint32_t __Reserved_177__; // 0x177 + uint32_t __Reserved_178__; // 0x178 + uint32_t __Reserved_179__; // 0x179 + uint32_t __Reserved_17A__; // 0x17A + uint32_t __Reserved_17B__; // 0x17B + uint32_t __Reserved_17C__; // 0x17C + uint32_t __Reserved_17D__; // 0x17D + uint32_t __Reserved_17E__; // 0x17E + uint32_t __Reserved_17F__; // 0x17F + uint32_t __Reserved_180__; // 0x180 + uint32_t __Reserved_181__; // 0x181 + uint32_t __Reserved_182__; // 0x182 + uint32_t __Reserved_183__; // 0x183 + uint32_t __Reserved_184__; // 0x184 + uint32_t __Reserved_185__; // 0x185 + uint32_t __Reserved_186__; // 0x186 + uint32_t __Reserved_187__; // 0x187 + uint32_t __Reserved_188__; // 0x188 + uint32_t __Reserved_189__; // 0x189 + uint32_t __Reserved_18A__; // 0x18A + uint32_t __Reserved_18B__; // 0x18B + uint32_t __Reserved_18C__; // 0x18C + uint32_t __Reserved_18D__; // 0x18D + uint32_t __Reserved_18E__; // 0x18E + uint32_t __Reserved_18F__; // 0x18F + uint32_t __Reserved_190__; // 0x190 + uint32_t __Reserved_191__; // 0x191 + uint32_t __Reserved_192__; // 0x192 + uint32_t __Reserved_193__; // 0x193 + uint32_t __Reserved_194__; // 0x194 + uint32_t __Reserved_195__; // 0x195 + uint32_t __Reserved_196__; // 0x196 + uint32_t __Reserved_197__; // 0x197 + uint32_t __Reserved_198__; // 0x198 + uint32_t __Reserved_199__; // 0x199 + uint32_t __Reserved_19A__; // 0x19A + uint32_t __Reserved_19B__; // 0x19B + uint32_t __Reserved_19C__; // 0x19C + uint32_t __Reserved_19D__; // 0x19D + uint32_t __Reserved_19E__; // 0x19E + uint32_t __Reserved_19F__; // 0x19F + uint32_t ZQCR; // 0x1A0 + uint32_t ZQ0PR; // 0x1A1 + uint32_t ZQ0DR; // 0x1A2 + uint32_t ZQ0SR; // 0x1A3 + uint32_t __Reserved_1A4__; // 0x1A4 + uint32_t ZQ1PR; // 0x1A5 + uint32_t ZQ1DR; // 0x1A6 + uint32_t ZQ1SR; // 0x1A7 + uint32_t __Reserved_1A8__; // 0x1A8 + uint32_t ZQ2PR; // 0x1A9 + uint32_t ZQ2DR; // 0x1AA + uint32_t ZQ2SR; // 0x1AB + uint32_t __Reserved_1AC__; // 0x1AC + uint32_t ZQ3PR; // 0x1AD + uint32_t ZQ3DR; // 0x1AE + uint32_t ZQ3SR; // 0x1AF + uint32_t __Reserved_1B0__; // 0x1B0 + uint32_t __Reserved_1B1__; // 0x1B1 + uint32_t __Reserved_1B2__; // 0x1B2 + uint32_t __Reserved_1B3__; // 0x1B3 + uint32_t __Reserved_1B4__; // 0x1B4 + uint32_t __Reserved_1B5__; // 0x1B5 + uint32_t __Reserved_1B6__; // 0x1B6 + uint32_t __Reserved_1B7__; // 0x1B7 + uint32_t __Reserved_1B8__; // 0x1B8 + uint32_t __Reserved_1B9__; // 0x1B9 + uint32_t __Reserved_1BA__; // 0x1BA + uint32_t __Reserved_1BB__; // 0x1BB + uint32_t __Reserved_1BC__; // 0x1BC + uint32_t __Reserved_1BD__; // 0x1BD + uint32_t __Reserved_1BE__; // 0x1BE + uint32_t __Reserved_1BF__; // 0x1BF + uint32_t DX0GCR0; // 0x1C0 + uint32_t DX0GCR1; // 0x1C1 + uint32_t DX0GCR2; // 0x1C2 + uint32_t DX0GCR3; // 0x1C3 + uint32_t DX0GCR4; // 0x1C4 + uint32_t DX0GCR5; // 0x1C5 + uint32_t DX0GCR6; // 0x1C6 + uint32_t DX0GCR7; // 0x1C7 + uint32_t DX0GCR8; // 0x1C8 + uint32_t DX0GCR9; // 0x1C9 + uint32_t __Reserved_1CA__; // 0x1CA + uint32_t __Reserved_1CB__; // 0x1CB + uint32_t __Reserved_1CC__; // 0x1CC + uint32_t __Reserved_1CD__; // 0x1CD + uint32_t __Reserved_1CE__; // 0x1CE + uint32_t __Reserved_1CF__; // 0x1CF + uint32_t DX0BDLR0; // 0x1D0 + uint32_t DX0BDLR1; // 0x1D1 + uint32_t DX0BDLR2; // 0x1D2 + uint32_t __Reserved_1D3__; // 0x1D3 + uint32_t DX0BDLR3; // 0x1D4 + uint32_t DX0BDLR4; // 0x1D5 + uint32_t DX0BDLR5; // 0x1D6 + uint32_t __Reserved_1D7__; // 0x1D7 + uint32_t DX0BDLR6; // 0x1D8 + uint32_t DX0BDLR7; // 0x1D9 + uint32_t DX0BDLR8; // 0x1DA + uint32_t DX0BDLR9; // 0x1DB + uint32_t __Reserved_1DC__; // 0x1DC + uint32_t __Reserved_1DD__; // 0x1DD + uint32_t __Reserved_1DE__; // 0x1DE + uint32_t __Reserved_1DF__; // 0x1DF + uint32_t DX0LCDLR0; // 0x1E0 + uint32_t DX0LCDLR1; // 0x1E1 + uint32_t DX0LCDLR2; // 0x1E2 + uint32_t DX0LCDLR3; // 0x1E3 + uint32_t DX0LCDLR4; // 0x1E4 + uint32_t DX0LCDLR5; // 0x1E5 + uint32_t __Reserved_1E6__; // 0x1E6 + uint32_t __Reserved_1E7__; // 0x1E7 + uint32_t DX0MDLR0; // 0x1E8 + uint32_t DX0MDLR1; // 0x1E9 + uint32_t __Reserved_1EA__; // 0x1EA + uint32_t __Reserved_1EB__; // 0x1EB + uint32_t __Reserved_1EC__; // 0x1EC + uint32_t __Reserved_1ED__; // 0x1ED + uint32_t __Reserved_1EE__; // 0x1EE + uint32_t __Reserved_1EF__; // 0x1EF + uint32_t DX0GTR0; // 0x1F0 + uint32_t __Reserved_1F1__; // 0x1F1 + uint32_t __Reserved_1F2__; // 0x1F2 + uint32_t __Reserved_1F3__; // 0x1F3 + uint32_t DX0RSR0; // 0x1F4 + uint32_t DX0RSR1; // 0x1F5 + uint32_t DX0RSR2; // 0x1F6 + uint32_t DX0RSR3; // 0x1F7 + uint32_t DX0GSR0; // 0x1F8 + uint32_t DX0GSR1; // 0x1F9 + uint32_t DX0GSR2; // 0x1FA + uint32_t DX0GSR3; // 0x1FB + uint32_t DX0GSR4; // 0x1FC + uint32_t DX0GSR5; // 0x1FD + uint32_t DX0GSR6; // 0x1FE + uint32_t __Reserved_1FF__; // 0x1FF + uint32_t DX1GCR0; // 0x200 + uint32_t DX1GCR1; // 0x201 + uint32_t DX1GCR2; // 0x202 + uint32_t DX1GCR3; // 0x203 + uint32_t DX1GCR4; // 0x204 + uint32_t DX1GCR5; // 0x205 + uint32_t DX1GCR6; // 0x206 + uint32_t DX1GCR7; // 0x207 + uint32_t DX1GCR8; // 0x208 + uint32_t DX1GCR9; // 0x209 + uint32_t __Reserved_20A__; // 0x20A + uint32_t __Reserved_20B__; // 0x20B + uint32_t __Reserved_20C__; // 0x20C + uint32_t __Reserved_20D__; // 0x20D + uint32_t __Reserved_20E__; // 0x20E + uint32_t __Reserved_20F__; // 0x20F + uint32_t DX1BDLR0; // 0x210 + uint32_t DX1BDLR1; // 0x211 + uint32_t DX1BDLR2; // 0x212 + uint32_t __Reserved_213__; // 0x213 + uint32_t DX1BDLR3; // 0x214 + uint32_t DX1BDLR4; // 0x215 + uint32_t DX1BDLR5; // 0x216 + uint32_t __Reserved_217__; // 0x217 + uint32_t DX1BDLR6; // 0x218 + uint32_t DX1BDLR7; // 0x219 + uint32_t DX1BDLR8; // 0x21A + uint32_t DX1BDLR9; // 0x21B + uint32_t __Reserved_21C__; // 0x21C + uint32_t __Reserved_21D__; // 0x21D + uint32_t __Reserved_21E__; // 0x21E + uint32_t __Reserved_21F__; // 0x21F + uint32_t DX1LCDLR0; // 0x220 + uint32_t DX1LCDLR1; // 0x221 + uint32_t DX1LCDLR2; // 0x222 + uint32_t DX1LCDLR3; // 0x223 + uint32_t DX1LCDLR4; // 0x224 + uint32_t DX1LCDLR5; // 0x225 + uint32_t __Reserved_226__; // 0x226 + uint32_t __Reserved_227__; // 0x227 + uint32_t DX1MDLR0; // 0x228 + uint32_t DX1MDLR1; // 0x229 + uint32_t __Reserved_22A__; // 0x22A + uint32_t __Reserved_22B__; // 0x22B + uint32_t __Reserved_22C__; // 0x22C + uint32_t __Reserved_22D__; // 0x22D + uint32_t __Reserved_22E__; // 0x22E + uint32_t __Reserved_22F__; // 0x22F + uint32_t DX1GTR0; // 0x230 + uint32_t __Reserved_231__; // 0x231 + uint32_t __Reserved_232__; // 0x232 + uint32_t __Reserved_233__; // 0x233 + uint32_t DX1RSR0; // 0x234 + uint32_t DX1RSR1; // 0x235 + uint32_t DX1RSR2; // 0x236 + uint32_t DX1RSR3; // 0x237 + uint32_t DX1GSR0; // 0x238 + uint32_t DX1GSR1; // 0x239 + uint32_t DX1GSR2; // 0x23A + uint32_t DX1GSR3; // 0x23B + uint32_t DX1GSR4; // 0x23C + uint32_t DX1GSR5; // 0x23D + uint32_t DX1GSR6; // 0x23E + uint32_t __Reserved_23F__; // 0x23F + uint32_t DX2GCR0; // 0x240 + uint32_t DX2GCR1; // 0x241 + uint32_t DX2GCR2; // 0x242 + uint32_t DX2GCR3; // 0x243 + uint32_t DX2GCR4; // 0x244 + uint32_t DX2GCR5; // 0x245 + uint32_t DX2GCR6; // 0x246 + uint32_t DX2GCR7; // 0x247 + uint32_t DX2GCR8; // 0x248 + uint32_t DX2GCR9; // 0x249 + uint32_t __Reserved_24A__; // 0x24A + uint32_t __Reserved_24B__; // 0x24B + uint32_t __Reserved_24C__; // 0x24C + uint32_t __Reserved_24D__; // 0x24D + uint32_t __Reserved_24E__; // 0x24E + uint32_t __Reserved_24F__; // 0x24F + uint32_t DX2BDLR0; // 0x250 + uint32_t DX2BDLR1; // 0x251 + uint32_t DX2BDLR2; // 0x252 + uint32_t __Reserved_253__; // 0x253 + uint32_t DX2BDLR3; // 0x254 + uint32_t DX2BDLR4; // 0x255 + uint32_t DX2BDLR5; // 0x256 + uint32_t __Reserved_257__; // 0x257 + uint32_t DX2BDLR6; // 0x258 + uint32_t DX2BDLR7; // 0x259 + uint32_t DX2BDLR8; // 0x25A + uint32_t DX2BDLR9; // 0x25B + uint32_t __Reserved_25C__; // 0x25C + uint32_t __Reserved_25D__; // 0x25D + uint32_t __Reserved_25E__; // 0x25E + uint32_t __Reserved_25F__; // 0x25F + uint32_t DX2LCDLR0; // 0x260 + uint32_t DX2LCDLR1; // 0x261 + uint32_t DX2LCDLR2; // 0x262 + uint32_t DX2LCDLR3; // 0x263 + uint32_t DX2LCDLR4; // 0x264 + uint32_t DX2LCDLR5; // 0x265 + uint32_t __Reserved_266__; // 0x266 + uint32_t __Reserved_267__; // 0x267 + uint32_t DX2MDLR0; // 0x268 + uint32_t DX2MDLR1; // 0x269 + uint32_t __Reserved_26A__; // 0x26A + uint32_t __Reserved_26B__; // 0x26B + uint32_t __Reserved_26C__; // 0x26C + uint32_t __Reserved_26D__; // 0x26D + uint32_t __Reserved_26E__; // 0x26E + uint32_t __Reserved_26F__; // 0x26F + uint32_t DX2GTR0; // 0x270 + uint32_t __Reserved_271__; // 0x271 + uint32_t __Reserved_272__; // 0x272 + uint32_t __Reserved_273__; // 0x273 + uint32_t DX2RSR0; // 0x274 + uint32_t DX2RSR1; // 0x275 + uint32_t DX2RSR2; // 0x276 + uint32_t DX2RSR3; // 0x277 + uint32_t DX2GSR0; // 0x278 + uint32_t DX2GSR1; // 0x279 + uint32_t DX2GSR2; // 0x27A + uint32_t DX2GSR3; // 0x27B + uint32_t DX2GSR4; // 0x27C + uint32_t DX2GSR5; // 0x27D + uint32_t DX2GSR6; // 0x27E + uint32_t __Reserved_27F__; // 0x27F + uint32_t DX3GCR0; // 0x280 + uint32_t DX3GCR1; // 0x281 + uint32_t DX3GCR2; // 0x282 + uint32_t DX3GCR3; // 0x283 + uint32_t DX3GCR4; // 0x284 + uint32_t DX3GCR5; // 0x285 + uint32_t DX3GCR6; // 0x286 + uint32_t DX3GCR7; // 0x287 + uint32_t DX3GCR8; // 0x288 + uint32_t DX3GCR9; // 0x289 + uint32_t __Reserved_28A__; // 0x28A + uint32_t __Reserved_28B__; // 0x28B + uint32_t __Reserved_28C__; // 0x28C + uint32_t __Reserved_28D__; // 0x28D + uint32_t __Reserved_28E__; // 0x28E + uint32_t __Reserved_28F__; // 0x28F + uint32_t DX3BDLR0; // 0x290 + uint32_t DX3BDLR1; // 0x291 + uint32_t DX3BDLR2; // 0x292 + uint32_t __Reserved_293__; // 0x293 + uint32_t DX3BDLR3; // 0x294 + uint32_t DX3BDLR4; // 0x295 + uint32_t DX3BDLR5; // 0x296 + uint32_t __Reserved_297__; // 0x297 + uint32_t DX3BDLR6; // 0x298 + uint32_t DX3BDLR7; // 0x299 + uint32_t DX3BDLR8; // 0x29A + uint32_t DX3BDLR9; // 0x29B + uint32_t __Reserved_29C__; // 0x29C + uint32_t __Reserved_29D__; // 0x29D + uint32_t __Reserved_29E__; // 0x29E + uint32_t __Reserved_29F__; // 0x29F + uint32_t DX3LCDLR0; // 0x2A0 + uint32_t DX3LCDLR1; // 0x2A1 + uint32_t DX3LCDLR2; // 0x2A2 + uint32_t DX3LCDLR3; // 0x2A3 + uint32_t DX3LCDLR4; // 0x2A4 + uint32_t DX3LCDLR5; // 0x2A5 + uint32_t __Reserved_2A6__; // 0x2A6 + uint32_t __Reserved_2A7__; // 0x2A7 + uint32_t DX3MDLR0; // 0x2A8 + uint32_t DX3MDLR1; // 0x2A9 + uint32_t __Reserved_2AA__; // 0x2AA + uint32_t __Reserved_2AB__; // 0x2AB + uint32_t __Reserved_2AC__; // 0x2AC + uint32_t __Reserved_2AD__; // 0x2AD + uint32_t __Reserved_2AE__; // 0x2AE + uint32_t __Reserved_2AF__; // 0x2AF + uint32_t DX3GTR0; // 0x2B0 + uint32_t __Reserved_2B1__; // 0x2B1 + uint32_t __Reserved_2B2__; // 0x2B2 + uint32_t __Reserved_2B3__; // 0x2B3 + uint32_t DX3RSR0; // 0x2B4 + uint32_t DX3RSR1; // 0x2B5 + uint32_t DX3RSR2; // 0x2B6 + uint32_t DX3RSR3; // 0x2B7 + uint32_t DX3GSR0; // 0x2B8 + uint32_t DX3GSR1; // 0x2B9 + uint32_t DX3GSR2; // 0x2BA + uint32_t DX3GSR3; // 0x2BB + uint32_t DX3GSR4; // 0x2BC + uint32_t DX3GSR5; // 0x2BD + uint32_t DX3GSR6; // 0x2BE + uint32_t __Reserved_2BF__; // 0x2BF + uint32_t DX4GCR0; // 0x2C0 + uint32_t DX4GCR1; // 0x2C1 + uint32_t DX4GCR2; // 0x2C2 + uint32_t DX4GCR3; // 0x2C3 + uint32_t DX4GCR4; // 0x2C4 + uint32_t DX4GCR5; // 0x2C5 + uint32_t DX4GCR6; // 0x2C6 + uint32_t DX4GCR7; // 0x2C7 + uint32_t DX4GCR8; // 0x2C8 + uint32_t DX4GCR9; // 0x2C9 + uint32_t __Reserved_2CA__; // 0x2CA + uint32_t __Reserved_2CB__; // 0x2CB + uint32_t __Reserved_2CC__; // 0x2CC + uint32_t __Reserved_2CD__; // 0x2CD + uint32_t __Reserved_2CE__; // 0x2CE + uint32_t __Reserved_2CF__; // 0x2CF + uint32_t DX4BDLR0; // 0x2D0 + uint32_t DX4BDLR1; // 0x2D1 + uint32_t DX4BDLR2; // 0x2D2 + uint32_t __Reserved_2D3__; // 0x2D3 + uint32_t DX4BDLR3; // 0x2D4 + uint32_t DX4BDLR4; // 0x2D5 + uint32_t DX4BDLR5; // 0x2D6 + uint32_t __Reserved_2D7__; // 0x2D7 + uint32_t DX4BDLR6; // 0x2D8 + uint32_t DX4BDLR7; // 0x2D9 + uint32_t DX4BDLR8; // 0x2DA + uint32_t DX4BDLR9; // 0x2DB + uint32_t __Reserved_2DC__; // 0x2DC + uint32_t __Reserved_2DD__; // 0x2DD + uint32_t __Reserved_2DE__; // 0x2DE + uint32_t __Reserved_2DF__; // 0x2DF + uint32_t DX4LCDLR0; // 0x2E0 + uint32_t DX4LCDLR1; // 0x2E1 + uint32_t DX4LCDLR2; // 0x2E2 + uint32_t DX4LCDLR3; // 0x2E3 + uint32_t DX4LCDLR4; // 0x2E4 + uint32_t DX4LCDLR5; // 0x2E5 + uint32_t __Reserved_2E6__; // 0x2E6 + uint32_t __Reserved_2E7__; // 0x2E7 + uint32_t DX4MDLR0; // 0x2E8 + uint32_t DX4MDLR1; // 0x2E9 + uint32_t __Reserved_2EA__; // 0x2EA + uint32_t __Reserved_2EB__; // 0x2EB + uint32_t __Reserved_2EC__; // 0x2EC + uint32_t __Reserved_2ED__; // 0x2ED + uint32_t __Reserved_2EE__; // 0x2EE + uint32_t __Reserved_2EF__; // 0x2EF + uint32_t DX4GTR0; // 0x2F0 + uint32_t __Reserved_2F1__; // 0x2F1 + uint32_t __Reserved_2F2__; // 0x2F2 + uint32_t __Reserved_2F3__; // 0x2F3 + uint32_t DX4RSR0; // 0x2F4 + uint32_t DX4RSR1; // 0x2F5 + uint32_t DX4RSR2; // 0x2F6 + uint32_t DX4RSR3; // 0x2F7 + uint32_t DX4GSR0; // 0x2F8 + uint32_t DX4GSR1; // 0x2F9 + uint32_t DX4GSR2; // 0x2FA + uint32_t DX4GSR3; // 0x2FB + uint32_t DX4GSR4; // 0x2FC + uint32_t DX4GSR5; // 0x2FD + uint32_t DX4GSR6; // 0x2FE + uint32_t __Reserved_2FF__; // 0x2FF + uint32_t DX5GCR0; // 0x300 + uint32_t DX5GCR1; // 0x301 + uint32_t DX5GCR2; // 0x302 + uint32_t DX5GCR3; // 0x303 + uint32_t DX5GCR4; // 0x304 + uint32_t DX5GCR5; // 0x305 + uint32_t DX5GCR6; // 0x306 + uint32_t DX5GCR7; // 0x307 + uint32_t DX5GCR8; // 0x308 + uint32_t DX5GCR9; // 0x309 + uint32_t __Reserved_30A__; // 0x30A + uint32_t __Reserved_30B__; // 0x30B + uint32_t __Reserved_30C__; // 0x30C + uint32_t __Reserved_30D__; // 0x30D + uint32_t __Reserved_30E__; // 0x30E + uint32_t __Reserved_30F__; // 0x30F + uint32_t DX5BDLR0; // 0x310 + uint32_t DX5BDLR1; // 0x311 + uint32_t DX5BDLR2; // 0x312 + uint32_t __Reserved_313__; // 0x313 + uint32_t DX5BDLR3; // 0x314 + uint32_t DX5BDLR4; // 0x315 + uint32_t DX5BDLR5; // 0x316 + uint32_t __Reserved_317__; // 0x317 + uint32_t DX5BDLR6; // 0x318 + uint32_t DX5BDLR7; // 0x319 + uint32_t DX5BDLR8; // 0x31A + uint32_t DX5BDLR9; // 0x31B + uint32_t __Reserved_31C__; // 0x31C + uint32_t __Reserved_31D__; // 0x31D + uint32_t __Reserved_31E__; // 0x31E + uint32_t __Reserved_31F__; // 0x31F + uint32_t DX5LCDLR0; // 0x320 + uint32_t DX5LCDLR1; // 0x321 + uint32_t DX5LCDLR2; // 0x322 + uint32_t DX5LCDLR3; // 0x323 + uint32_t DX5LCDLR4; // 0x324 + uint32_t DX5LCDLR5; // 0x325 + uint32_t __Reserved_326__; // 0x326 + uint32_t __Reserved_327__; // 0x327 + uint32_t DX5MDLR0; // 0x328 + uint32_t DX5MDLR1; // 0x329 + uint32_t __Reserved_32A__; // 0x32A + uint32_t __Reserved_32B__; // 0x32B + uint32_t __Reserved_32C__; // 0x32C + uint32_t __Reserved_32D__; // 0x32D + uint32_t __Reserved_32E__; // 0x32E + uint32_t __Reserved_32F__; // 0x32F + uint32_t DX5GTR0; // 0x330 + uint32_t __Reserved_331__; // 0x331 + uint32_t __Reserved_332__; // 0x332 + uint32_t __Reserved_333__; // 0x333 + uint32_t DX5RSR0; // 0x334 + uint32_t DX5RSR1; // 0x335 + uint32_t DX5RSR2; // 0x336 + uint32_t DX5RSR3; // 0x337 + uint32_t DX5GSR0; // 0x338 + uint32_t DX5GSR1; // 0x339 + uint32_t DX5GSR2; // 0x33A + uint32_t DX5GSR3; // 0x33B + uint32_t DX5GSR4; // 0x33C + uint32_t DX5GSR5; // 0x33D + uint32_t DX5GSR6; // 0x33E + uint32_t __Reserved_33F__; // 0x33F + uint32_t DX6GCR0; // 0x340 + uint32_t DX6GCR1; // 0x341 + uint32_t DX6GCR2; // 0x342 + uint32_t DX6GCR3; // 0x343 + uint32_t DX6GCR4; // 0x344 + uint32_t DX6GCR5; // 0x345 + uint32_t DX6GCR6; // 0x346 + uint32_t DX6GCR7; // 0x347 + uint32_t DX6GCR8; // 0x348 + uint32_t DX6GCR9; // 0x349 + uint32_t __Reserved_34A__; // 0x34A + uint32_t __Reserved_34B__; // 0x34B + uint32_t __Reserved_34C__; // 0x34C + uint32_t __Reserved_34D__; // 0x34D + uint32_t __Reserved_34E__; // 0x34E + uint32_t __Reserved_34F__; // 0x34F + uint32_t DX6BDLR0; // 0x350 + uint32_t DX6BDLR1; // 0x351 + uint32_t DX6BDLR2; // 0x352 + uint32_t __Reserved_353__; // 0x353 + uint32_t DX6BDLR3; // 0x354 + uint32_t DX6BDLR4; // 0x355 + uint32_t DX6BDLR5; // 0x356 + uint32_t __Reserved_357__; // 0x357 + uint32_t DX6BDLR6; // 0x358 + uint32_t DX6BDLR7; // 0x359 + uint32_t DX6BDLR8; // 0x35A + uint32_t DX6BDLR9; // 0x35B + uint32_t __Reserved_35C__; // 0x35C + uint32_t __Reserved_35D__; // 0x35D + uint32_t __Reserved_35E__; // 0x35E + uint32_t __Reserved_35F__; // 0x35F + uint32_t DX6LCDLR0; // 0x360 + uint32_t DX6LCDLR1; // 0x361 + uint32_t DX6LCDLR2; // 0x362 + uint32_t DX6LCDLR3; // 0x363 + uint32_t DX6LCDLR4; // 0x364 + uint32_t DX6LCDLR5; // 0x365 + uint32_t __Reserved_366__; // 0x366 + uint32_t __Reserved_367__; // 0x367 + uint32_t DX6MDLR0; // 0x368 + uint32_t DX6MDLR1; // 0x369 + uint32_t __Reserved_36A__; // 0x36A + uint32_t __Reserved_36B__; // 0x36B + uint32_t __Reserved_36C__; // 0x36C + uint32_t __Reserved_36D__; // 0x36D + uint32_t __Reserved_36E__; // 0x36E + uint32_t __Reserved_36F__; // 0x36F + uint32_t DX6GTR0; // 0x370 + uint32_t __Reserved_371__; // 0x371 + uint32_t __Reserved_372__; // 0x372 + uint32_t __Reserved_373__; // 0x373 + uint32_t DX6RSR0; // 0x374 + uint32_t DX6RSR1; // 0x375 + uint32_t DX6RSR2; // 0x376 + uint32_t DX6RSR3; // 0x377 + uint32_t DX6GSR0; // 0x378 + uint32_t DX6GSR1; // 0x379 + uint32_t DX6GSR2; // 0x37A + uint32_t DX6GSR3; // 0x37B + uint32_t DX6GSR4; // 0x37C + uint32_t DX6GSR5; // 0x37D + uint32_t DX6GSR6; // 0x37E + uint32_t __Reserved_37F__; // 0x37F + uint32_t DX7GCR0; // 0x380 + uint32_t DX7GCR1; // 0x381 + uint32_t DX7GCR2; // 0x382 + uint32_t DX7GCR3; // 0x383 + uint32_t DX7GCR4; // 0x384 + uint32_t DX7GCR5; // 0x385 + uint32_t DX7GCR6; // 0x386 + uint32_t DX7GCR7; // 0x387 + uint32_t DX7GCR8; // 0x388 + uint32_t DX7GCR9; // 0x389 + uint32_t __Reserved_38A__; // 0x38A + uint32_t __Reserved_38B__; // 0x38B + uint32_t __Reserved_38C__; // 0x38C + uint32_t __Reserved_38D__; // 0x38D + uint32_t __Reserved_38E__; // 0x38E + uint32_t __Reserved_38F__; // 0x38F + uint32_t DX7BDLR0; // 0x390 + uint32_t DX7BDLR1; // 0x391 + uint32_t DX7BDLR2; // 0x392 + uint32_t __Reserved_393__; // 0x393 + uint32_t DX7BDLR3; // 0x394 + uint32_t DX7BDLR4; // 0x395 + uint32_t DX7BDLR5; // 0x396 + uint32_t __Reserved_397__; // 0x397 + uint32_t DX7BDLR6; // 0x398 + uint32_t DX7BDLR7; // 0x399 + uint32_t DX7BDLR8; // 0x39A + uint32_t DX7BDLR9; // 0x39B + uint32_t __Reserved_39C__; // 0x39C + uint32_t __Reserved_39D__; // 0x39D + uint32_t __Reserved_39E__; // 0x39E + uint32_t __Reserved_39F__; // 0x39F + uint32_t DX7LCDLR0; // 0x3A0 + uint32_t DX7LCDLR1; // 0x3A1 + uint32_t DX7LCDLR2; // 0x3A2 + uint32_t DX7LCDLR3; // 0x3A3 + uint32_t DX7LCDLR4; // 0x3A4 + uint32_t DX7LCDLR5; // 0x3A5 + uint32_t __Reserved_3A6__; // 0x3A6 + uint32_t __Reserved_3A7__; // 0x3A7 + uint32_t DX7MDLR0; // 0x3A8 + uint32_t DX7MDLR1; // 0x3A9 + uint32_t __Reserved_3AA__; // 0x3AA + uint32_t __Reserved_3AB__; // 0x3AB + uint32_t __Reserved_3AC__; // 0x3AC + uint32_t __Reserved_3AD__; // 0x3AD + uint32_t __Reserved_3AE__; // 0x3AE + uint32_t __Reserved_3AF__; // 0x3AF + uint32_t DX7GTR0; // 0x3B0 + uint32_t __Reserved_3B1__; // 0x3B1 + uint32_t __Reserved_3B2__; // 0x3B2 + uint32_t __Reserved_3B3__; // 0x3B3 + uint32_t DX7RSR0; // 0x3B4 + uint32_t DX7RSR1; // 0x3B5 + uint32_t DX7RSR2; // 0x3B6 + uint32_t DX7RSR3; // 0x3B7 + uint32_t DX7GSR0; // 0x3B8 + uint32_t DX7GSR1; // 0x3B9 + uint32_t DX7GSR2; // 0x3BA + uint32_t DX7GSR3; // 0x3BB + uint32_t DX7GSR4; // 0x3BC + uint32_t DX7GSR5; // 0x3BD + uint32_t DX7GSR6; // 0x3BE + uint32_t __Reserved_3BF__; // 0x3BF + uint32_t DX8GCR0; // 0x3C0 + uint32_t DX8GCR1; // 0x3C1 + uint32_t DX8GCR2; // 0x3C2 + uint32_t DX8GCR3; // 0x3C3 + uint32_t DX8GCR4; // 0x3C4 + uint32_t DX8GCR5; // 0x3C5 + uint32_t DX8GCR6; // 0x3C6 + uint32_t DX8GCR7; // 0x3C7 + uint32_t DX8GCR8; // 0x3C8 + uint32_t DX8GCR9; // 0x3C9 + uint32_t __Reserved_3CA__; // 0x3CA + uint32_t __Reserved_3CB__; // 0x3CB + uint32_t __Reserved_3CC__; // 0x3CC + uint32_t __Reserved_3CD__; // 0x3CD + uint32_t __Reserved_3CE__; // 0x3CE + uint32_t __Reserved_3CF__; // 0x3CF + uint32_t DX8BDLR0; // 0x3D0 + uint32_t DX8BDLR1; // 0x3D1 + uint32_t DX8BDLR2; // 0x3D2 + uint32_t __Reserved_3D3__; // 0x3D3 + uint32_t DX8BDLR3; // 0x3D4 + uint32_t DX8BDLR4; // 0x3D5 + uint32_t DX8BDLR5; // 0x3D6 + uint32_t __Reserved_3D7__; // 0x3D7 + uint32_t DX8BDLR6; // 0x3D8 + uint32_t DX8BDLR7; // 0x3D9 + uint32_t DX8BDLR8; // 0x3DA + uint32_t DX8BDLR9; // 0x3DB + uint32_t __Reserved_3DC__; // 0x3DC + uint32_t __Reserved_3DD__; // 0x3DD + uint32_t __Reserved_3DE__; // 0x3DE + uint32_t __Reserved_3DF__; // 0x3DF + uint32_t DX8LCDLR0; // 0x3E0 + uint32_t DX8LCDLR1; // 0x3E1 + uint32_t DX8LCDLR2; // 0x3E2 + uint32_t DX8LCDLR3; // 0x3E3 + uint32_t DX8LCDLR4; // 0x3E4 + uint32_t DX8LCDLR5; // 0x3E5 + uint32_t __Reserved_3E6__; // 0x3E6 + uint32_t __Reserved_3E7__; // 0x3E7 + uint32_t DX8MDLR0; // 0x3E8 + uint32_t DX8MDLR1; // 0x3E9 + uint32_t __Reserved_3EA__; // 0x3EA + uint32_t __Reserved_3EB__; // 0x3EB + uint32_t __Reserved_3EC__; // 0x3EC + uint32_t __Reserved_3ED__; // 0x3ED + uint32_t __Reserved_3EE__; // 0x3EE + uint32_t __Reserved_3EF__; // 0x3EF + uint32_t DX8GTR0; // 0x3F0 + uint32_t __Reserved_3F1__; // 0x3F1 + uint32_t __Reserved_3F2__; // 0x3F2 + uint32_t __Reserved_3F3__; // 0x3F3 + uint32_t DX8RSR0; // 0x3F4 + uint32_t DX8RSR1; // 0x3F5 + uint32_t DX8RSR2; // 0x3F6 + uint32_t DX8RSR3; // 0x3F7 + uint32_t DX8GSR0; // 0x3F8 + uint32_t DX8GSR1; // 0x3F9 + uint32_t DX8GSR2; // 0x3FA + uint32_t DX8GSR3; // 0x3FB + uint32_t DX8GSR4; // 0x3FC + uint32_t DX8GSR5; // 0x3FD + uint32_t DX8GSR6; // 0x3FE + uint32_t __Reserved_3FF__; // 0x3FF +} REG_ST_DDRPHY_CONFIG_t; + +#endif // REG_DDRPHY_CONFIG_H diff --git a/product/synquacer/module/synquacer_memc/include/internal/reg_DMA330.h b/product/synquacer/module/synquacer_memc/include/internal/reg_DMA330.h new file mode 100644 index 000000000..955c7c164 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/include/internal/reg_DMA330.h @@ -0,0 +1,202 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REG_DMA330_H +#define REG_DMA330_H + +#include +#include + +#ifdef RESERVED_AREA_BYTE +#undef RESERVED_AREA_BYTE +#endif +#define RESERVED_AREA_BYTE(var1, var2) \ + unsigned char reserved_##var1_##var2 \ + [(((var2) + 1) - (var1)) / sizeof(unsigned char)] + +#ifdef RESERVED_AREA_HALF +#undef RESERVED_AREA_HALF +#endif +#define RESERVED_AREA_HALF(var1, var2) \ + unsigned short reserved_##var1_##var2 \ + [(((var2) + 1) - (var1)) / sizeof(unsigned short)] + +#ifdef RESERVED_AREA_WORD +#undef RESERVED_AREA_WORD +#endif +#define RESERVED_AREA_WORD(var1, var2) \ + unsigned long reserved_##var1_##var2 \ + [(((var2) + 1) - (var1)) / sizeof(unsigned long)] + +typedef struct { + uint32_t CSR; /* 0x100,...,0x138 Channel status for DMA channel 0~7 */ + uint32_t CPC; /* 0x104,...,0x13C Channel PC for DMA channel 0~7 */ +} REG_ST_DMA330_CT_t; + +typedef struct { + uint32_t SAR; /* 0x400,...,0x4E0 Source address for DMA channel 0~7 */ + uint32_t DAR; /* 0x404,...,0x4E4 Destination address for DMA channel 0~7 */ + uint32_t CCR; /* 0x408,...,0x4E8 Channel control for DMA channel 0~7 */ + uint32_t LC0; /* 0x40C,...,0x4EC Loop counter 0 for DMA channel 0~7 */ + uint32_t LC1; /* 0x410,...,0x4F0 Loop counter 1 for DMA channel 0~7 */ + uint32_t reserved[3]; +} REG_ST_DMA330_AS_t; + +typedef union { + uint32_t DATA; + struct { + uint32_t SRC_INC : 1; /* B00 */ + uint32_t SRC_BURST_SIZE : 3; /* B01-B03 */ + uint32_t SRC_BURST_LEN : 4; /* B04-B07 */ + uint32_t SRC_PROT_CTRL : 3; /* B08-B10 */ + uint32_t SRC_CACHE_CTRL : 3; /* B11-B13 */ + uint32_t DST_INC : 1; /* B14 */ + uint32_t DST_BURST_SIZE : 3; /* B15-B17 */ + uint32_t DST_BURST_LEN : 4; /* B18-B21 */ + uint32_t DST_PROT_CTRL : 3; /* B22-B24 */ + uint32_t DST_CACHE_CTRL : 3; /* B25-B27 */ + uint32_t ENDIAN_SWAP_SIZE : 3; /* B28-B30 */ + uint32_t reserved1 : 1; /* B31 Reserved */ + } bit; +} DMA330_UN_CCR_t; + +#define DMA330_MAKE_CCR(ES, DC, DP, DL, DS, DI, SC, SP, SL, SS, SI) \ + (((ES) << 28) | ((DC) << 25) | ((DP) << 22) | ((DL) << 18) | \ + ((DS) << 15) | ((DI) << 14) | ((SC) << 11) | ((SP) << 8) | ((SL) << 4) | \ + ((SS) << 1) | ((SI) << 0)) + +typedef union { + uint32_t DATA; + struct { + uint32_t FS_MGR : 1; /* B00 */ + uint32_t reserved1 : 31; /* B01-B31 Reserved */ + } bit; +} DMA330_UN_FSRD_t; + +typedef union { + uint32_t DATA; + struct { + uint32_t CH0 : 1; /* B00 */ + uint32_t CH1 : 1; /* B01 */ + uint32_t CH2 : 1; /* B02 */ + uint32_t CH3 : 1; /* B03 */ + uint32_t CH4 : 1; /* B04 */ + uint32_t CH5 : 1; /* B05 */ + uint32_t CH6 : 1; /* B06 */ + uint32_t CH7 : 1; /* B07 */ + uint32_t reserved1 : 24; /* B08-B31 Reserved */ + } bit; +} DMA330_UN_FSRC_t; + +// 3.3.9 Fault Type DMA Manager Register +typedef union { + uint32_t DATA; + struct { + uint32_t UNDEF_INSTR : 1; /* B00 */ + uint32_t OPERAND_INVALID : 1; /* B01 */ + uint32_t reserved1 : 2; /* B02-B03 Reserved */ + uint32_t DMAGO_ERR : 1; /* B04 */ + uint32_t MGR_EVNT_ERR : 1; /* B05 */ + uint32_t reserved2 : 10; /* B06-B15 Reserved */ + uint32_t INSTR_FETCH_ERR : 1; /* B16 */ + uint32_t reserved3 : 13; /* B17-B29 Reserved */ + uint32_t DBG_INSTR : 1; /* B30 */ + uint32_t reserved4 : 1; /* B31 Reserved */ + } bit; +} DMA330_UN_FTRD_t; + +// Fault Type DMA Channel Registers +typedef union { + uint32_t DATA; + struct { + uint32_t UNDEF_INSTR : 1; /* B00 */ + uint32_t OPERAND_INVALID : 1; /* B01 */ + uint32_t reserved1 : 3; /* B02-B04 Reserved */ + uint32_t CH_EVNT_ERR : 1; /* B05 */ + uint32_t CH_PERIPH_ERR : 1; /* B06 */ + uint32_t CH_RDWR_ERR : 1; /* B07 */ + uint32_t reserved2 : 4; /* B08-B11 Reserved */ + uint32_t MFIFO_ERR : 1; /* B12 */ + uint32_t ST_DATA_UNAVAILABLE : 1; /* B13 */ + uint32_t reserved3 : 2; /* B14-B15 Reserved */ + uint32_t INSTR_FETCH_ERR : 1; /* B16 */ + uint32_t DATA_WRITE_ERR : 1; /* B17 */ + uint32_t DATA_READ_ERR : 1; /* B18 */ + uint32_t reserved4 : 11; /* B19-B29 Reserved */ + uint32_t DBG_INSTR : 1; /* B30 */ + uint32_t LOCKUP_ERR : 1; /* B31 */ + } bit; +} DMA330_UN_FTR_t; + +typedef struct { + uint32_t DSR; /* +0x000 DMA Manager Status Register */ + uint32_t DPC; /* +0x004 DMA Program Counter Register */ + RESERVED_AREA_WORD(0x008, 0x01F); + uint32_t INTEN; /* +0x020 Interrupt Enable Register */ + uint32_t INT_EVENT_RIS; /* +0x024 Event-Interrupt Raw Status Register */ + uint32_t INTMIS; /* +0x028 Interrupt Status Register */ + uint32_t INTCLR; /* +0x02C Interrupt Clear Register */ + uint32_t FSRD; /* +0x030 Fault Status DMA Manager Register */ + uint32_t FSRC; /* +0x034 Fault Status DMA Channel Register */ + uint32_t FTRD; /* +0x038 Fault Type DMA Manager Register */ + RESERVED_AREA_WORD(0x03C, 0x03F); + uint32_t FTR[8]; /* +0x040-0x05C Fault Type DMA Channel Registers */ + RESERVED_AREA_WORD(0x060, 0x0FF); + REG_ST_DMA330_CT_t + CT[8]; /* +0x100-0x13C DMA Channel Thread Status Register */ + RESERVED_AREA_WORD(0x140, 0x3FF); + REG_ST_DMA330_AS_t + AS[8]; /* +0x400-0x4FC AXI Status And Loop Counter Register */ + RESERVED_AREA_WORD(0x500, 0xCFF); + uint32_t DBGSTATUS; /* +0xD00 Debug Status Register */ + uint32_t DBGCMD; /* +0xD04 Debug Command Register */ + uint32_t DBGINST[2]; /* +0xD08-0xD0C Debug Instruction-0,1 Register */ + RESERVED_AREA_WORD(0xD10, 0xDFF); + uint32_t CR[5]; /* +0xE00-0xE10 Configuration Register 0~4 */ + uint32_t CRD; /* +0xE14 DMA Configuration Register */ + RESERVED_AREA_WORD(0xE18, 0xE7F); + uint32_t WD; /* +0xE80 Watchdog Register */ + RESERVED_AREA_WORD(0xE84, 0xFDF); + uint32_t + PERIPH_ID[4]; /* +0xFE0-0xFEC Peripheral Identification Registers */ + uint32_t + PCELL_ID[4]; /* +0xFF0-0xFFC Component Identification Registers 0-3 */ +} REG_ST_DMA330_S_t; + +typedef struct { + uint32_t DSR; /* +0x000 */ + uint32_t DPC; /* +0x004 */ + RESERVED_AREA_WORD(0x008, 0x01F); + uint32_t INTEN; /* +0x020 */ + uint32_t INT_EVENT_RIS; /* +0x024 */ + uint32_t INTMIS; /* +0x028 */ + uint32_t INTCLR; /* +0x02C */ + uint32_t FSRD; /* +0x030 */ + uint32_t FSRC; /* +0x034 */ + uint32_t FTRD; /* +0x038 */ + RESERVED_AREA_WORD(0x03C, 0x03F); + uint32_t FTR[8]; /* +0x040-0x05C */ + RESERVED_AREA_WORD(0x060, 0x0FF); + REG_ST_DMA330_CT_t CT[8]; /* +0x100-0x13C */ + RESERVED_AREA_WORD(0x140, 0x3FF); + REG_ST_DMA330_AS_t AS[8]; /* +0x400-0x4FC */ + RESERVED_AREA_WORD(0x500, 0xCFF); + uint32_t DBGSTATUS; /* +0xD00 */ + uint32_t DBGCMD; /* +0xD04 */ + uint32_t DBGINST[2]; /* +0xD08-0xD0C */ + RESERVED_AREA_WORD(0xD10, 0xDFF); + uint32_t CR[5]; /* +0xE00-0xE10 */ + uint32_t CRD; /* +0xE14 */ + RESERVED_AREA_WORD(0xE18, 0xE7F); + uint32_t WD; /* +0xE80 */ + RESERVED_AREA_WORD(0xE84, 0xFDF); + uint32_t PERIPH_ID[4]; /* +0xFE0-0xFEC */ + uint32_t PCELL_ID[4]; /* +0xFF0-0xFFC */ + +} REG_ST_DMA330_NS_t; + +#endif /* REG_DMA330_H */ diff --git a/product/synquacer/module/synquacer_memc/include/internal/reg_DMC520.h b/product/synquacer/module/synquacer_memc/include/internal/reg_DMC520.h new file mode 100644 index 000000000..90352317c --- /dev/null +++ b/product/synquacer/module/synquacer_memc/include/internal/reg_DMC520.h @@ -0,0 +1,427 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REG_DMC520_H +#define REG_DMC520_H + +#include + +typedef volatile struct { + uint32_t memc_status; // 0x000 + uint32_t memc_config; // 0x004 + uint32_t memc_cmd; // 0x008 + uint32_t __RESERVED_0x000C_0x000C_[1]; + uint32_t address_control_next; // 0x010 + uint32_t decode_control_next; // 0x014 + uint32_t format_control; // 0x018 + uint32_t address_map_next; // 0x01C + uint32_t low_power_control_next; // 0x020 + uint32_t __RESERVED_0x0024_0x0024_[1]; + uint32_t turnaround_control_next; // 0x028 + uint32_t hit_turnaround_control_next; // 0x02C + uint32_t qos_class_control_next; // 0x030 + uint32_t escalation_control_next; // 0x034 + uint32_t qv_control_31_00_next; // 0x038 + uint32_t qv_control_63_32_next; // 0x03C + uint32_t rt_control_31_00_next; // 0x040 + uint32_t rt_control_63_32_next; // 0x044 + uint32_t timeout_control_next; // 0x048 + uint32_t credit_control_next; // 0x04C + uint32_t write_priority_control_31_00_next; // 0x050 + uint32_t write_priority_control_63_32_next; // 0x054 + uint32_t __RESERVED_0x0058_0x005C_[2]; + uint32_t queue_threshold_control_31_00_next; // 0x060 + uint32_t queue_threshold_control_63_32_next; // 0x064 + uint32_t __RESERVED_0x0068_0x0074_[4]; + uint32_t memory_address_max_31_00_next; // 0x078 + uint32_t memory_address_max_43_32_next; // 0x07C + uint32_t access_address_min0_31_00_next; // 0x080 + uint32_t access_address_min0_43_32_next; // 0x084 + uint32_t access_address_max0_31_00_next; // 0x088 + uint32_t access_address_max0_43_32_next; // 0x08C + uint32_t access_address_min1_31_00_next; // 0x090 + uint32_t access_address_min1_43_32_next; // 0x094 + uint32_t access_address_max1_31_00_next; // 0x098 + uint32_t access_address_max1_43_32_next; // 0x09C + uint32_t access_address_min2_31_00_next; // 0x0A0 + uint32_t access_address_min2_43_32_next; // 0x0A4 + uint32_t access_address_max2_31_00_next; // 0x0A8 + uint32_t access_address_max2_43_32_next; // 0x0AC + uint32_t access_address_min3_31_00_next; // 0x0B0 + uint32_t access_address_min3_43_32_next; // 0x0B4 + uint32_t access_address_max3_31_00_next; // 0x0B8 + uint32_t access_address_max3_43_32_next; // 0x0BC + uint32_t access_address_min4_31_00_next; // 0x0C0 + uint32_t access_address_min4_43_32_next; // 0x0C4 + uint32_t access_address_max4_31_00_next; // 0x0C8 + uint32_t access_address_max4_43_32_next; // 0x0CC + uint32_t access_address_min5_31_00_next; // 0x0D0 + uint32_t access_address_min5_43_32_next; // 0x0D4 + uint32_t access_address_max5_31_00_next; // 0x0D8 + uint32_t access_address_max5_43_32_next; // 0x0DC + uint32_t access_address_min6_31_00_next; // 0x0E0 + uint32_t access_address_min6_43_32_next; // 0x0E4 + uint32_t access_address_max6_31_00_next; // 0x0E8 + uint32_t access_address_max6_43_32_next; // 0x0EC + uint32_t access_address_min7_31_00_next; // 0x0F0 + uint32_t access_address_min7_43_32_next; // 0x0F4 + uint32_t access_address_max7_31_00_next; // 0x0F8 + uint32_t access_address_max7_43_32_next; // 0x0FC + uint32_t channel_status; // 0x100 + uint32_t __RESERVED_0x0104_0x0104_[1]; + uint32_t direct_addr; // 0x108 + uint32_t direct_cmd; // 0x10C + uint32_t dci_replay_type_next; // 0x110 + uint32_t __RESERVED_0x0114_0x0114_[1]; + uint32_t dci_strb; // 0x118 + uint32_t dci_data; // 0x11C + uint32_t refresh_control_next; // 0x120 + uint32_t __RESERVED_0x0124_0x0124_[1]; + uint32_t memory_type_next; // 0x128 + uint32_t __RESERVED_0x012C_0x012C_[1]; + uint32_t feature_config; // 0x130 + uint32_t __RESERVED_0x0134_0x0134_[1]; + uint32_t nibble_failed_031_000; // 0x138 + uint32_t nibble_failed_063_032; // 0x13C + uint32_t nibble_failed_095_064; // 0x140 + uint32_t nibble_failed_127_096; // 0x144 + uint32_t queue_allocate_control_031_000; // 0x148 + uint32_t queue_allocate_control_063_032; // 0x14C + uint32_t queue_allocate_control_095_064; // 0x150 + uint32_t queue_allocate_control_127_096; // 0x154 + uint32_t ecc_errc_count_31_00; // 0x158 + uint32_t ecc_errc_count_63_32; // 0x15C + uint32_t ecc_errd_count_31_00; // 0x160 + uint32_t ecc_errd_count_63_32; // 0x164 + uint32_t ram_err_count; // 0x168 + uint32_t link_err_count; // 0x16C + uint32_t scrub_control0_next; // 0x170 + uint32_t scrub_address_min0_next; // 0x174 + uint32_t scrub_address_max0_next; // 0x178 + uint32_t __RESERVED_0x017C_0x017C_[1]; + uint32_t scrub_control1_next; // 0x180 + uint32_t scrub_address_min1_next; // 0x184 + uint32_t scrub_address_max1_next; // 0x188 + uint32_t __RESERVED_0x018C_0x018C_[1]; + uint32_t scrub_control2_next; // 0x190 + uint32_t scrub_address_min2_next; // 0x194 + uint32_t scrub_address_max2_next; // 0x198 + uint32_t __RESERVED_0x019C_0x019C_[1]; + uint32_t scrub_control3_next; // 0x1A0 + uint32_t scrub_address_min3_next; // 0x1A4 + uint32_t scrub_address_max3_next; // 0x1A8 + uint32_t __RESERVED_0x01AC_0x01AC_[1]; + uint32_t scrub_control4_next; // 0x1B0 + uint32_t scrub_address_min4_next; // 0x1B4 + uint32_t scrub_address_max4_next; // 0x1B8 + uint32_t __RESERVED_0x01BC_0x01BC_[1]; + uint32_t scrub_control5_next; // 0x1C0 + uint32_t scrub_address_min5_next; // 0x1C4 + uint32_t scrub_address_max5_next; // 0x1C8 + uint32_t __RESERVED_0x01CC_0x01CC_[1]; + uint32_t scrub_control6_next; // 0x1D0 + uint32_t scrub_address_min6_next; // 0x1D4 + uint32_t scrub_address_max6_next; // 0x1D8 + uint32_t __RESERVED_0x01DC_0x01DC_[1]; + uint32_t scrub_control7_next; // 0x1E0 + uint32_t scrub_address_min7_next; // 0x1E4 + uint32_t scrub_address_max7_next; // 0x1E8 + uint32_t __RESERVED_0x01EC_0x01EC_[1]; + uint32_t feature_control_next; // 0x1F0 + uint32_t mux_control_next; // 0x1F4 + uint32_t rank_remap_control_next; // 0x1F8 + uint32_t scrub_control_next; // 0x1FC + uint32_t t_refi_next; // 0x200 + uint32_t t_rfc_next; // 0x204 + uint32_t t_mrr_next; // 0x208 + uint32_t t_mrw_next; // 0x20C + uint32_t t_rdpden_next; // 0x210 + uint32_t __RESERVED_0x0214_0x0214_[1]; + uint32_t t_rcd_next; // 0x218 + uint32_t t_ras_next; // 0x21C + uint32_t t_rp_next; // 0x220 + uint32_t t_rpall_next; // 0x224 + uint32_t t_rrd_next; // 0x228 + uint32_t t_act_window_next; // 0x22C + uint32_t __RESERVED_0x0230_0x0230_[1]; + uint32_t t_rtr_next; // 0x234 + uint32_t t_rtw_next; // 0x238 + uint32_t t_rtp_next; // 0x23C + uint32_t __RESERVED_0x0240_0x0240_[1]; + uint32_t t_wr_next; // 0x244 + uint32_t t_wtr_next; // 0x248 + uint32_t t_wtw_next; // 0x24C + uint32_t __RESERVED_0x0250_0x0250_[1]; + uint32_t t_xmpd_next; // 0x254 + uint32_t t_ep_next; // 0x258 + uint32_t t_xp_next; // 0x25C + uint32_t t_esr_next; // 0x260 + uint32_t t_xsr_next; // 0x264 + uint32_t t_esrck_next; // 0x268 + uint32_t t_ckxsr_next; // 0x26C + uint32_t t_cmd_next; // 0x270 + uint32_t t_parity_next; // 0x274 + uint32_t t_zqcs_next; // 0x278 + uint32_t t_rw_odt_clr_next; // 0x27C + uint32_t __RESERVED_0x0280_0x02FC_[32]; + uint32_t t_rddata_en_next; // 0x300 + uint32_t t_phyrdlat_next; // 0x304 + uint32_t t_phywrlat_next; // 0x308 + uint32_t __RESERVED_0x030C_0x030C_[1]; + uint32_t rdlvl_control_next; // 0x310 + uint32_t rdlvl_mrs_next; // 0x314 + uint32_t t_rdlvl_en_next; // 0x318 + uint32_t t_rdlvl_rr_next; // 0x31C + uint32_t wrlvl_control_next; // 0x320 + uint32_t wrlvl_mrs_next; // 0x324 + uint32_t t_wrlvl_en_next; // 0x328 + uint32_t t_wrlvl_ww_next; // 0x32C + uint32_t __RESERVED_0x0330_0x0344_[6]; + uint32_t phy_power_control_next; // 0x348 + uint32_t t_lpresp_next; // 0x34C + uint32_t phy_update_control_next; // 0x350 + uint32_t __RESERVED_0x0354_0x0354_[1]; + uint32_t odt_timing_next; // 0x358 + uint32_t t_odth_next; // 0x35C + uint32_t odt_wr_control_31_00_next; // 0x360 + uint32_t odt_wr_control_63_32_next; // 0x364 + uint32_t odt_rd_control_31_00_next; // 0x368 + uint32_t odt_rd_control_63_32_next; // 0x36C + uint32_t temperature_readout; // 0x370 + uint32_t __RESERVED_0x0374_0x0374_[1]; + uint32_t training_status; // 0x378 + uint32_t update_status; // 0x37C + uint32_t dq_map_control_15_00_next; // 0x380 + uint32_t dq_map_control_31_16_next; // 0x384 + uint32_t dq_map_control_47_32_next; // 0x388 + uint32_t dq_map_control_63_48_next; // 0x38C + uint32_t dq_map_control_71_64_next; // 0x390 + uint32_t __RESERVED_0x0394_0x0394_[1]; + uint32_t rank_status; // 0x398 + uint32_t mode_change_status; // 0x39C + uint32_t phy_rdwrdata_cs_mask_31_00; // 0x3A0 + uint32_t phy_rdwrdata_cs_mask_63_32; // 0x3A4 + uint32_t phy_request_cs_remap; // 0x3A8 + uint32_t __RESERVED_0x03AC_0x03AC_[1]; + uint32_t odt_cp_control_31_00_next; // 0x3B0 + uint32_t odt_cp_control_63_32_next; // 0x3B4 + uint32_t __RESERVED_0x03B8_0x03FC_[18]; + uint32_t user_status; // 0x400 + uint32_t __RESERVED_0x0404_0x0404_[1]; + uint32_t user_config0_next; // 0x408 + uint32_t user_config1_next; // 0x40C + uint32_t user_config2; // 0x410 + uint32_t user_config3; // 0x414 + uint32_t __RESERVED_0x0418_0x04FC_[58]; + uint32_t interrupt_control; // 0x500 + uint32_t __RESERVED_0x0504_0x0504_[1]; + uint32_t interrupt_clr; // 0x508 + uint32_t __RESERVED_0x050C_0x050C_[1]; + uint32_t interrupt_status; // 0x510 + uint32_t __RESERVED_0x0514_0x0514_[1]; + uint32_t ram_ecc_errc_int_info_31_00; // 0x518 + uint32_t ram_ecc_errc_int_info_63_32; // 0x51C + uint32_t ram_ecc_errd_int_info_31_00; // 0x520 + uint32_t ram_ecc_errd_int_info_63_32; // 0x524 + uint32_t dram_ecc_errc_int_info_31_00; // 0x528 + uint32_t dram_ecc_errc_int_info_63_32; // 0x52C + uint32_t dram_ecc_errd_int_info_31_00; // 0x530 + uint32_t dram_ecc_errd_int_info_63_32; // 0x534 + uint32_t failed_access_int_info_31_00; // 0x538 + uint32_t failed_access_int_info_63_32; // 0x53C + uint32_t failed_prog_int_info_31_00; // 0x540 + uint32_t failed_prog_int_info_63_32; // 0x544 + uint32_t link_err_int_info_31_00; // 0x548 + uint32_t link_err_int_info_63_32; // 0x54C + uint32_t arch_fsm_int_info_31_00; // 0x550 + uint32_t arch_fsm_int_info_63_32; // 0x554 + uint32_t __RESERVED_0x0558_0x0DFC_[554]; + uint32_t integ_cfg; // 0xE00 + uint32_t __RESERVED_0x0E04_0x0E04_[1]; + uint32_t integ_outputs; // 0xE08 + uint32_t __RESERVED_0x0E0C_0x100C_[129]; + uint32_t address_control_now; // 0x1010 + uint32_t decode_control_now; // 0x1014 + uint32_t __RESERVED_0x1018_0x1018_[1]; + uint32_t address_map_now; // 0x101C + uint32_t low_power_control_now; // 0x1020 + uint32_t __RESERVED_0x1024_0x1024_[1]; + uint32_t turnaround_control_now; // 0x1028 + uint32_t hit_turnaround_control_now; // 0x102C + uint32_t qos_class_control_now; // 0x1030 + uint32_t escalation_control_now; // 0x1034 + uint32_t qv_control_31_00_now; // 0x1038 + uint32_t qv_control_63_32_now; // 0x103C + uint32_t rt_control_31_00_now; // 0x1040 + uint32_t rt_control_63_32_now; // 0x1044 + uint32_t timeout_control_now; // 0x1048 + uint32_t credit_control_now; // 0x104C + uint32_t write_priority_control_31_00_now; // 0x1050 + uint32_t write_priority_control_63_32_now; // 0x1054 + uint32_t __RESERVED_0x1058_0x105C_[2]; + uint32_t queue_threshold_control_31_00_now; // 0x1060 + uint32_t queue_threshold_control_63_32_now; // 0x1064 + uint32_t __RESERVED_0x1068_0x1074_[4]; + uint32_t memory_address_max_31_00_now; // 0x1078 + uint32_t memory_address_max_43_32_now; // 0x107C + uint32_t access_address_min0_31_00_now; // 0x1080 + uint32_t access_address_min0_43_32_now; // 0x1084 + uint32_t access_address_max0_31_00_now; // 0x1088 + uint32_t access_address_max0_43_32_now; // 0x108C + uint32_t access_address_min1_31_00_now; // 0x1090 + uint32_t access_address_min1_43_32_now; // 0x1094 + uint32_t access_address_max1_31_00_now; // 0x1098 + uint32_t access_address_max1_43_32_now; // 0x109C + uint32_t access_address_min2_31_00_now; // 0x10A0 + uint32_t access_address_min2_43_32_now; // 0x10A4 + uint32_t access_address_max2_31_00_now; // 0x10A8 + uint32_t access_address_max2_43_32_now; // 0x10AC + uint32_t access_address_min3_31_00_now; // 0x10B0 + uint32_t access_address_min3_43_32_now; // 0x10B4 + uint32_t access_address_max3_31_00_now; // 0x10B8 + uint32_t access_address_max3_43_32_now; // 0x10BC + uint32_t access_address_min4_31_00_now; // 0x10C0 + uint32_t access_address_min4_43_32_now; // 0x10C4 + uint32_t access_address_max4_31_00_now; // 0x10C8 + uint32_t access_address_max4_43_32_now; // 0x10CC + uint32_t access_address_min5_31_00_now; // 0x10D0 + uint32_t access_address_min5_43_32_now; // 0x10D4 + uint32_t access_address_max5_31_00_now; // 0x10D8 + uint32_t access_address_max5_43_32_now; // 0x10DC + uint32_t access_address_min6_31_00_now; // 0x10E0 + uint32_t access_address_min6_43_32_now; // 0x10E4 + uint32_t access_address_max6_31_00_now; // 0x10E8 + uint32_t access_address_max6_43_32_now; // 0x10EC + uint32_t access_address_min7_31_00_now; // 0x10F0 + uint32_t access_address_min7_43_32_now; // 0x10F4 + uint32_t access_address_max7_31_00_now; // 0x10F8 + uint32_t access_address_max7_43_32_now; // 0x10FC + uint32_t __RESERVED_0x1100_0x110C_[4]; + uint32_t dci_replay_type_now; // 0x1110 + uint32_t __RESERVED_0x1114_0x111C_[3]; + uint32_t refresh_control_now; // 0x1120 + uint32_t __RESERVED_0x1124_0x1124_[1]; + uint32_t memory_type_now; // 0x1128 + uint32_t __RESERVED_0x112C_0x116C_[17]; + uint32_t scrub_control0_now; // 0x1170 + uint32_t scrub_address_min0_now; // 0x1174 + uint32_t scrub_address_max0_now; // 0x1178 + uint32_t __RESERVED_0x117C_0x117C_[1]; + uint32_t scrub_control1_now; // 0x1180 + uint32_t scrub_address_min1_now; // 0x1184 + uint32_t scrub_address_max1_now; // 0x1188 + uint32_t __RESERVED_0x118C_0x118C_[1]; + uint32_t scrub_control2_now; // 0x1190 + uint32_t scrub_address_min2_now; // 0x1194 + uint32_t scrub_address_max2_now; // 0x1198 + uint32_t __RESERVED_0x119C_0x119C_[1]; + uint32_t scrub_control3_now; // 0x11A0 + uint32_t scrub_address_min3_now; // 0x11A4 + uint32_t scrub_address_max3_now; // 0x11A8 + uint32_t __RESERVED_0x11AC_0x11AC_[1]; + uint32_t scrub_control4_now; // 0x11B0 + uint32_t scrub_address_min4_now; // 0x11B4 + uint32_t scrub_address_max4_now; // 0x11B8 + uint32_t __RESERVED_0x11BC_0x11BC_[1]; + uint32_t scrub_control5_now; // 0x11C0 + uint32_t scrub_address_min5_now; // 0x11C4 + uint32_t scrub_address_max5_now; // 0x11C8 + uint32_t __RESERVED_0x11CC_0x11CC_[1]; + uint32_t scrub_control6_now; // 0x11D0 + uint32_t scrub_address_min6_now; // 0x11D4 + uint32_t scrub_address_max6_now; // 0x11D8 + uint32_t __RESERVED_0x11DC_0x11DC_[1]; + uint32_t scrub_control7_now; // 0x11E0 + uint32_t scrub_address_min7_now; // 0x11E4 + uint32_t scrub_address_max7_now; // 0x11E8 + uint32_t __RESERVED_0x11EC_0x11EC_[1]; + uint32_t feature_control_now; // 0x11F0 + uint32_t mux_control_now; // 0x11F4 + uint32_t rank_remap_control_now; // 0x11F8 + uint32_t scrub_control_now; // 0x11FC + uint32_t t_refi_now; // 0x1200 + uint32_t t_rfc_now; // 0x1204 + uint32_t t_mrr_now; // 0x1208 + uint32_t t_mrw_now; // 0x120C + uint32_t t_rdpden_now; // 0x1210 + uint32_t __RESERVED_0x1214_0x1214_[1]; + uint32_t t_rcd_now; // 0x1218 + uint32_t t_ras_now; // 0x121C + uint32_t t_rp_now; // 0x1220 + uint32_t t_rpall_now; // 0x1224 + uint32_t t_rrd_now; // 0x1228 + uint32_t t_act_window_now; // 0x122C + uint32_t __RESERVED_0x1230_0x1230_[1]; + uint32_t t_rtr_now; // 0x1234 + uint32_t t_rtw_now; // 0x1238 + uint32_t t_rtp_now; // 0x123C + uint32_t __RESERVED_0x1240_0x1240_[1]; + uint32_t t_wr_now; // 0x1244 + uint32_t t_wtr_now; // 0x1248 + uint32_t t_wtw_now; // 0x124C + uint32_t __RESERVED_0x1250_0x1250_[1]; + uint32_t t_xmpd_now; // 0x1254 + uint32_t t_ep_now; // 0x1258 + uint32_t t_xp_now; // 0x125C + uint32_t t_esr_now; // 0x1260 + uint32_t t_xsr_now; // 0x1264 + uint32_t t_esrck_now; // 0x1268 + uint32_t t_ckxsr_now; // 0x126C + uint32_t t_cmd_now; // 0x1270 + uint32_t t_parity_now; // 0x1274 + uint32_t t_zqcs_now; // 0x1278 + uint32_t t_rw_odt_clr_now; // 0x127C + uint32_t __RESERVED_0x1280_0x12FC_[32]; + uint32_t t_rddata_en_now; // 0x1300 + uint32_t t_phyrdlat_now; // 0x1304 + uint32_t t_phywrlat_now; // 0x1308 + uint32_t __RESERVED_0x130C_0x130C_[1]; + uint32_t rdlvl_control_now; // 0x1310 + uint32_t rdlvl_mrs_now; // 0x1314 + uint32_t t_rdlvl_en_now; // 0x1318 + uint32_t t_rdlvl_rr_now; // 0x131C + uint32_t wrlvl_control_now; // 0x1320 + uint32_t wrlvl_mrs_now; // 0x1324 + uint32_t t_wrlvl_en_now; // 0x1328 + uint32_t t_wrlvl_ww_now; // 0x132C + uint32_t __RESERVED_0x1330_0x1344_[6]; + uint32_t phy_power_control_now; // 0x1348 + uint32_t t_lpresp_now; // 0x134C + uint32_t phy_update_control_now; // 0x1350 + uint32_t __RESERVED_0x1354_0x1354_[1]; + uint32_t odt_timing_now; // 0x1358 + uint32_t t_odth_now; // 0x135C + uint32_t odt_wr_control_31_00_now; // 0x1360 + uint32_t odt_wr_control_63_32_now; // 0x1364 + uint32_t odt_rd_control_31_00_now; // 0x1368 + uint32_t odt_rd_control_63_32_now; // 0x136C + uint32_t __RESERVED_0x1370_0x137C_[4]; + uint32_t dq_map_control_15_00_now; // 0x1380 + uint32_t dq_map_control_31_16_now; // 0x1384 + uint32_t dq_map_control_47_32_now; // 0x1388 + uint32_t dq_map_control_63_48_now; // 0x138C + uint32_t dq_map_control_71_64_now; // 0x1390 + uint32_t __RESERVED_0x1394_0x13AC_[7]; + uint32_t odt_cp_control_31_00_now; // 0x13B0 + uint32_t odt_cp_control_63_32_now; // 0x13B4 + uint32_t __RESERVED_0x13B8_0x1404_[20]; + uint32_t user_config0_now; // 0x1408 + uint32_t user_config1_now; // 0x140C + uint32_t __RESERVED_0x1410_0x1FCC_[752]; + uint32_t periph_id_4; // 0x1FD0 + uint32_t __RESERVED_0x1FD4_0x1FDC_[3]; + uint32_t periph_id_0; // 0x1FE0 + uint32_t periph_id_1; // 0x1FE4 + uint32_t periph_id_2; // 0x1FE8 + uint32_t periph_id_3; // 0x1FEC + uint32_t component_id_0; // 0x1FF0 + uint32_t component_id_1; // 0x1FF4 + uint32_t component_id_2; // 0x1FF8 + uint32_t component_id_3; // 0x1FFC +} REG_ST_DMC520; + +#endif /* REG_DMC520_H */ diff --git a/product/synquacer/module/synquacer_memc/include/mod_synquacer_memc.h b/product/synquacer/module/synquacer_memc/include/mod_synquacer_memc.h new file mode 100644 index 000000000..433dee546 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/include/mod_synquacer_memc.h @@ -0,0 +1,38 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_SYNQUACER_MEMC_H +#define MOD_SYNQUACER_MEMC_H + +#include +#include +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupSYNQUACER_MEMC Memory Controller Driver + * + * \brief SynQuacer MEMC device driver + * + * \details This module implements a device driver for the memory controller + * + * @{ + */ + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_SYNQUACER_MEMC_H */ diff --git a/product/synquacer/module/synquacer_memc/include/synquacer_ddr.h b/product/synquacer/module/synquacer_memc/include/synquacer_ddr.h new file mode 100644 index 000000000..aed75e574 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/include/synquacer_ddr.h @@ -0,0 +1,73 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_DDR_H +#define SYNQUACER_DDR_H + +#include +#include + +#define DRAM_DDR4 0x00000002 +#define DIMM_SLOT_NUM 4 +#define SPD_BYTE_TOP_ADDR 0x00 +#define SPD_READ_BYTE_NUM 128 + +#define MODULE_TYPE_RDIMM 0x01 +#define MODULE_TYPE_UDIMM 0x02 +#define MODULE_TYPE_72BITSOUDIMM 0x09 + +#define FW_MODULE_CAPACITY_16GB 0x4000 +#define FW_MODULE_CAPACITY_8GB 0x2000 +#define FW_MODULE_CAPACITY_4GB 0x1000 + +#define DDR_USE_CH0 0x1 +#define DDR_USE_CH1 0x2 +#define DDR_USE_DUAL_CH (DDR_USE_CH0 | DDR_USE_CH1) + +#define RDIMM_16GBPERSLOT_1SLOTPERCH 0x1 +#define RDIMM_16GBPERSLOT_2SLOTPERCH 0x2 +#define UDIMM_4GBPERSLOT_1SLOTPERCH 0x3 +#define SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH 0x4 +#define SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH 0x5 +#define UDIMM_8GBPERSLOT_1SLOTPERCH 0x6 + +#define BANK_BIT_NEXT 0x00040000 + +#define DRAM_AREA_1_START_ADDR UINT64_C(0x0080000000) + +/* top 64MiB in DRAM1 region is reserved for Secure App */ +#define DRAM_RESERVED_FOR_SECURE_APP_SIZE UINT64_C(0x04000000) +#define DRAM_AREA_1_END_ADDR UINT64_C(0x0100000000) +#define DRAM_AREA_2_START_ADDR UINT64_C(0x0880000000) +#define DRAM_AREA_2_END_ADDR UINT64_C(0x1000000000) +#define DRAM_AREA_3_START_ADDR UINT64_C(0x8800000000) +#define DRAM_AREA_3_END_ADDR UINT64_C(0x9000000000) + +#define DRAM_AREA_1_SIZE (DRAM_AREA_1_END_ADDR - DRAM_AREA_1_START_ADDR) +#define DRAM_AREA_2_SIZE (DRAM_AREA_2_END_ADDR - DRAM_AREA_2_START_ADDR) +#define DRAM_AREA_3_SIZE (DRAM_AREA_3_END_ADDR - DRAM_AREA_3_START_ADDR) + +#define SPD_DTIC_SPA0 (0x36) /* set page address to 0 */ +#define SPD_DTIC_SPA1 (0x37) /* set page address to 1 */ +#define SPD_PAGE_SIZE (256) +#define SPD_NUM_OF_PAGE (2) + +#define SPD_STORE_AREA_OFFSET (0x0000F000) +#define SPD_STORE_AREA_SIZE (DIMM_SLOT_NUM * (SPD_PAGE_SIZE * SPD_NUM_OF_PAGE)) +#define SPD_STORE_ADDR (NONTRUSTED_RAM_BASE + SPD_STORE_AREA_OFFSET) + +void fw_ddr_init(void); +int fw_ddr_spd_param_check(void); +bool fw_get_ddr4_sdram_ecc_available(void); +uint8_t fw_get_used_memory_ch(void); +uint32_t fw_get_memory_type_next(void); +uint32_t fw_get_address_control_next(void); +uint32_t fw_get_ddr4_sdram_dq_map_control(uint8_t i); +uint32_t fw_get_ddr4_sdram_total_size(void); +uint32_t fw_get_memory_type(void); + +#endif /* SYNQUACER_DDR_H */ diff --git a/product/synquacer/module/synquacer_memc/src/Makefile b/product/synquacer/module/synquacer_memc/src/Makefile new file mode 100644 index 000000000..61af3cd2a --- /dev/null +++ b/product/synquacer/module/synquacer_memc/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := synauacer_memc +BS_LIB_SOURCES += mod_synquacer_memc.c synquacer_ddr.c ddr_init.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/synquacer_memc/src/ddr_init.c b/product/synquacer/module/synquacer_memc/src/ddr_init.c new file mode 100644 index 000000000..700e90ab2 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/src/ddr_init.c @@ -0,0 +1,1340 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +extern void usleep_en(uint32_t usec); + +int ddr_init_mc0_mp(REG_ST_DMC520 *REG_DMC520); +int ddr_init_phy0_mp(REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en); +int ddr_init_phy1_mp(REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en); +int ddr_init_sdram_mp( + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en); +int ddr_init_mc1_mp(REG_ST_DMC520 *REG_DMC520); +int ddr_init_train_mp( + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en); +int ddr_init_mc2_mp(REG_ST_DMC520 *REG_DMC520); + +int g_DDR4_DMC520_INIT_CH = 0; + +#define DDR_DIP_SW3_SECURE_DRAM_ENABLE (0x04) +uint8_t ddr_is_secure_dram_enabled(void) +{ + return get_dsw3_status(DDR_DIP_SW3_SECURE_DRAM_ENABLE); +} + +void Wait_for_ddr(uint32_t count) +{ + uint32_t i; + for (i = 0; i < count; i++) + __NOP(); +} + +void usleep_en(uint32_t usec) +{ + dmb(); + usleep(usec); + return; +} + +int ddr_dual_ch_init_mp(void) +{ + int ret_val; + REG_ST_DMC520 *REG_DMC520_0; + REG_ST_DMC520 *REG_DMC520_1; + + ret_val = ddr_ch0_init_mp(); + if (ret_val != 0) + return ret_val; + + ret_val = ddr_ch1_init_mp(); + if (ret_val != 0) + return ret_val; + + REG_DMC520_0 = (REG_ST_DMC520 *)(uint32_t)REG_DMC520_0_BA; + + REG_DMC520_1 = (REG_ST_DMC520 *)(uint32_t)REG_DMC520_1_BA; + REG_DMC520_0->memc_cmd = 0x00000000; + + ddr_wait( + (REG_DMC520_0->memc_status & 0x7) != 0x0, DDR_WAIT_TIMEOUT_US, 0x1001); + + REG_DMC520_0->address_map_next = 0xFF000005; + REG_DMC520_0->memc_status; + REG_DMC520_0->memc_status; + REG_DMC520_0->memc_status; + REG_DMC520_0->memc_status; + REG_DMC520_0->memc_cmd = 0x00000003; + REG_DMC520_0->memc_status; + REG_DMC520_0->memc_cmd = 0x00000004; + + ddr_wait( + (REG_DMC520_0->memc_status & 0x7) != 0x3, DDR_WAIT_TIMEOUT_US, 0x1002); + + REG_DMC520_1->memc_cmd = 0x00000000; + + ddr_wait( + (REG_DMC520_1->memc_status & 0x7) != 0x0, DDR_WAIT_TIMEOUT_US, 0x1003); + + REG_DMC520_1->address_map_next = 0xFF000005; + REG_DMC520_1->memc_status; + REG_DMC520_1->memc_status; + REG_DMC520_1->memc_status; + REG_DMC520_1->memc_status; + REG_DMC520_1->memc_cmd = 0x00000003; + REG_DMC520_1->memc_status; + REG_DMC520_1->memc_cmd = 0x00000004; + + ddr_wait( + (REG_DMC520_1->memc_status & 0x7) != 0x3, DDR_WAIT_TIMEOUT_US, 0x1004); + + return 0; +} + +/* ch0 : DMC 0 + PHY 0 */ +int ddr_ch0_init_mp(void) +{ + int status; + REG_ST_DMC520 *REG_DMC520_0; + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG_0; + + REG_DMC520_0 = (REG_ST_DMC520 *)(uint32_t)REG_DMC520_0_BA; + REG_DDRPHY_CONFIG_0 = + (REG_ST_DDRPHY_CONFIG_t *)(uint32_t)REG_DDRPHY_CONFIG_0_BA; + + g_DDR4_DMC520_INIT_CH = 0; + + printf("Initializing DDR ch0\n"); + + ddr_init_mc0_mp(REG_DMC520_0); + + /* allocate 60MiB secure DRAM for OP-TEE */ + if (ddr_is_secure_dram_enabled()) { + printf("secure DRAM enabled\n"); + REG_DMC520_0->access_address_min0_31_00_next = 0xFC00000C; + REG_DMC520_0->access_address_min0_43_32_next = 0x00000000; + REG_DMC520_0->access_address_max0_31_00_next = 0xFFBF0000; + REG_DMC520_0->access_address_max0_43_32_next = 0x00000000; + } + + status = ddr_init_phy0_mp(REG_DDRPHY_CONFIG_0, 0); + if (status != 0) { + pr_err("[DDR] ch0 initialize failed. ddr_init_phy0_mp()\n"); + return status; + } + status = ddr_init_phy1_mp(REG_DDRPHY_CONFIG_0, 0); + if (status != 0) { + pr_err("[DDR] ch0 initialize failed. ddr_init_phy1_mp()\n"); + return status; + } + + status = ddr_init_sdram_mp(REG_DDRPHY_CONFIG_0, 0); + if (status != 0) { + pr_err("[DDR] ch0 initialize failed. ddr_init_sdram_mp()\n"); + return status; + } + + status = ddr_init_mc1_mp(REG_DMC520_0); + if (status != 0) { + pr_err("[DDR] ch0 initialize failed. ddr_init_mc1_mp()\n"); + return status; + } + + status = ddr_init_train_mp(REG_DDRPHY_CONFIG_0, 0); + if (status != 0) { + pr_err("[DDR] ch0 fatal error occurred.\n"); + return status; + } + status = ddr_init_mc2_mp(REG_DMC520_0); + if (status != 0) { + pr_err("[DDR] ch0 initialize failed. ddr_init_mc1_mp()\n"); + return status; + } + + printf("Finished initializing DDR ch0\n"); + + return 0; +} + +/* ch1 : DMC 1 + PHY 1 */ +int ddr_ch1_init_mp(void) +{ + int status; + REG_ST_DMC520 *REG_DMC520_1; + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG_1; + + REG_DMC520_1 = (REG_ST_DMC520 *)(uint32_t)REG_DMC520_1_BA; + REG_DDRPHY_CONFIG_1 = + (REG_ST_DDRPHY_CONFIG_t *)(uint32_t)REG_DDRPHY_CONFIG_1_BA; + + g_DDR4_DMC520_INIT_CH = 1; + + printf("Initializing DDR ch1\n"); + + status = ddr_init_mc0_mp(REG_DMC520_1); + if (status != 0) { + pr_err("[DDR] ch1 initialize failed. ddr_init_mc0_mp()\n"); + return status; + } + + status = ddr_init_phy0_mp(REG_DDRPHY_CONFIG_1, 0); + if (status != 0) { + pr_err("[DDR] ch1 initialize failed. ddr_init_phy0_mp()\n"); + return status; + } + + status = ddr_init_phy1_mp(REG_DDRPHY_CONFIG_1, 0); + if (status != 0) { + pr_err("[DDR] ch1 initialize failed. ddr_init_phy1_mp()\n"); + return status; + } + + status = ddr_init_sdram_mp(REG_DDRPHY_CONFIG_1, 0); + if (status != 0) { + pr_err("[DDR] ch1 initialize failed. ddr_init_sdram_mp()\n"); + return status; + } + + status = ddr_init_mc1_mp(REG_DMC520_1); + if (status != 0) { + pr_err("[DDR] ch1 initialize failed. ddr_init_mc1_mp()\n"); + return status; + } + + status = ddr_init_train_mp(REG_DDRPHY_CONFIG_1, 0); + if (status != 0) { + pr_err("[DDR] ch1 fatal error occurred.\n"); + return status; + } + + status = ddr_init_mc2_mp(REG_DMC520_1); + if (status != 0) { + pr_err("[DDR] ch1 initialize failed. ddr_init_mc2_mp()\n"); + return status; + } + + printf("Finished initializing DDR ch1\n"); + + return 0; +} + +int ddr_init_mc0_mp(REG_ST_DMC520 *REG_DMC520) +{ + uint32_t ddr_memory_type; + ddr_memory_type = fw_get_memory_type(); + + REG_DMC520->memc_status; + REG_DMC520->memc_config; + + REG_DMC520->address_control_next = fw_get_address_control_next(); + REG_DMC520->decode_control_next = 0x00000002; + REG_DMC520->format_control = 0x00000003; + REG_DMC520->address_map_next = 0xFF800004; + REG_DMC520->memory_address_max_31_00_next = 0xFFFF001F; + REG_DMC520->memory_address_max_43_32_next = 0x00000007; + REG_DMC520->access_address_min0_31_00_next = 0x00000000; + REG_DMC520->access_address_min0_43_32_next = 0x00000000; + REG_DMC520->access_address_max0_31_00_next = 0x00000000; + REG_DMC520->access_address_max0_43_32_next = 0x00000000; + REG_DMC520->access_address_min1_31_00_next = 0x00000000; + REG_DMC520->access_address_min1_43_32_next = 0x00000000; + REG_DMC520->access_address_max1_31_00_next = 0x00000000; + REG_DMC520->access_address_max1_43_32_next = 0x00000000; + REG_DMC520->access_address_min2_31_00_next = 0x00000000; + REG_DMC520->access_address_min2_43_32_next = 0x00000000; + REG_DMC520->access_address_max2_31_00_next = 0x00000000; + REG_DMC520->access_address_max2_43_32_next = 0x00000000; + REG_DMC520->access_address_min3_31_00_next = 0x00000000; + REG_DMC520->access_address_min3_43_32_next = 0x00000000; + REG_DMC520->access_address_max3_31_00_next = 0x00000000; + REG_DMC520->access_address_max3_43_32_next = 0x00000000; + REG_DMC520->access_address_min4_31_00_next = 0x00000000; + REG_DMC520->access_address_min4_43_32_next = 0x00000000; + REG_DMC520->access_address_max4_31_00_next = 0x00000000; + REG_DMC520->access_address_max4_43_32_next = 0x00000000; + REG_DMC520->access_address_min5_31_00_next = 0x00000000; + REG_DMC520->access_address_min5_43_32_next = 0x00000000; + REG_DMC520->access_address_max5_31_00_next = 0x00000000; + REG_DMC520->access_address_max5_43_32_next = 0x00000000; + REG_DMC520->access_address_min6_31_00_next = 0x00000000; + REG_DMC520->access_address_min6_43_32_next = 0x00000000; + REG_DMC520->access_address_max6_31_00_next = 0x00000000; + REG_DMC520->access_address_max6_43_32_next = 0x00000000; + REG_DMC520->access_address_min7_31_00_next = 0x00000000; + REG_DMC520->access_address_min7_43_32_next = 0x00000000; + REG_DMC520->access_address_max7_31_00_next = 0x00000000; + REG_DMC520->access_address_max7_43_32_next = 0x00000000; + REG_DMC520->dci_replay_type_next = 0x00000002; + REG_DMC520->dci_strb = 0x0000000F; + REG_DMC520->refresh_control_next = 0x00000000; + REG_DMC520->memory_type_next = fw_get_memory_type_next(); + REG_DMC520->feature_config = 0x00000000; + REG_DMC520->scrub_control0_next = 0x08000000; + REG_DMC520->scrub_control1_next = 0x08000000; + REG_DMC520->scrub_control2_next = 0x08000000; + REG_DMC520->scrub_control3_next = 0x08000000; + REG_DMC520->scrub_control4_next = 0x08000000; + REG_DMC520->scrub_control5_next = 0x08000000; + REG_DMC520->scrub_control6_next = 0x08000000; + REG_DMC520->scrub_control7_next = 0x08000000; + + if ((ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH)) + REG_DMC520->feature_control_next = 0x00A100F0; + else if ( + (ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DMC520->feature_control_next = 0x000000F8; + else if ( + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH)) + REG_DMC520->feature_control_next = 0x00A100F8; + + REG_DMC520->mux_control_next = 0x000000D0; + + if (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) + REG_DMC520->rank_remap_control_next = 0xFEDC10BA; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DMC520->rank_remap_control_next = 0xFEDC3210; + else if (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) + REG_DMC520->rank_remap_control_next = 0xFEDCBA10; + else if (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) + REG_DMC520->rank_remap_control_next = 0xFEDCBA90; + else if ( + (ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DMC520->rank_remap_control_next = 0xFEDC90BA; + + REG_DMC520->t_refi_next = 0x0009040F; + REG_DMC520->t_rfc_next = 0x0005D976; + REG_DMC520->t_mrr_next = 0x00000001; + REG_DMC520->t_mrw_next = 0x00180018; + REG_DMC520->t_rdpden_next = 0x00000014; + REG_DMC520->t_rcd_next = 0x00000010; + REG_DMC520->t_ras_next = 0x00000024; + REG_DMC520->t_rp_next = 0x00000010; + REG_DMC520->t_rpall_next = 0x00000010; + REG_DMC520->t_rrd_next = 0x00000604; + REG_DMC520->t_act_window_next = 0x00000017; + REG_DMC520->t_rtr_next = 0x000E0604; + REG_DMC520->t_rtw_next = 0x000F0F0F; + REG_DMC520->t_rtp_next = 0x00000009; + REG_DMC520->t_wr_next = 0x00000021; + REG_DMC520->t_wtr_next = 0x00181818; + REG_DMC520->t_wtw_next = 0x000A0604; + REG_DMC520->t_xmpd_next = 0x00000480; + REG_DMC520->t_ep_next = 0x00000006; + REG_DMC520->t_xp_next = 0x00100007; + REG_DMC520->t_esr_next = 0x00000007; + REG_DMC520->t_xsr_next = 0x03000180; + REG_DMC520->t_esrck_next = 0x0000000B; + REG_DMC520->t_ckxsr_next = 0x0000000B; + REG_DMC520->t_cmd_next = 0x00000000; + REG_DMC520->t_parity_next = 0x00001A00; + REG_DMC520->t_zqcs_next = 0x00000080; + REG_DMC520->t_rw_odt_clr_next = 0x0000000C; + + if ((ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH)) { + REG_DMC520->t_rddata_en_next = 0x0000000C; + REG_DMC520->t_phyrdlat_next = 0x0000001E; + REG_DMC520->t_phywrlat_next = 0x0000000A; + } else if ( + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH)) { + REG_DMC520->t_rddata_en_next = 0x0000000B; + REG_DMC520->t_phyrdlat_next = 0x00000022; + REG_DMC520->t_phywrlat_next = 0x00000009; + } else if ( + (ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) { + REG_DMC520->t_rddata_en_next = 0x0000000B; + REG_DMC520->t_phyrdlat_next = 0x00000021; + REG_DMC520->t_phywrlat_next = 0x00000009; + } + + REG_DMC520->rdlvl_control_next = 0x00000000; + REG_DMC520->rdlvl_mrs_next = 0x00000000; + REG_DMC520->t_rdlvl_en_next = 0x00000000; + REG_DMC520->t_rdlvl_rr_next = 0x00000000; + REG_DMC520->wrlvl_control_next = 0x00000000; + REG_DMC520->wrlvl_mrs_next = 0x00000000; + REG_DMC520->t_wrlvl_en_next = 0x00000000; + REG_DMC520->t_wrlvl_ww_next = 0x00000000; + REG_DMC520->phy_power_control_next = 0x09999900; + REG_DMC520->t_lpresp_next = 0x00000000; + REG_DMC520->phy_update_control_next = 0x001F0000; + REG_DMC520->odt_timing_next = 0x0C020800; + REG_DMC520->t_odth_next = 0x00000008; + + if (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) + REG_DMC520->odt_wr_control_31_00_next = 0x08040000; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DMC520->odt_wr_control_31_00_next = 0x0A050A05; + else if (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) + REG_DMC520->odt_wr_control_31_00_next = 0x00000201; + else if (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) + REG_DMC520->odt_wr_control_31_00_next = 0x00000001; + else if ( + (ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DMC520->odt_wr_control_31_00_next = 0x00040000; + + REG_DMC520->odt_wr_control_63_32_next = 0x00000000; + + if ((ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DMC520->odt_rd_control_31_00_next = 0x00000000; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DMC520->odt_rd_control_31_00_next = 0x02010804; + + REG_DMC520->odt_rd_control_63_32_next = 0x00000000; + + if (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) { + // for bit swap on sever board + if (g_DDR4_DMC520_INIT_CH == 0) { + REG_DMC520->dq_map_control_15_00_next = 0x2D032E0D; + REG_DMC520->dq_map_control_31_16_next = 0x2E0D0E24; + REG_DMC520->dq_map_control_47_32_next = 0x2B152B15; + REG_DMC520->dq_map_control_63_48_next = 0x35162C0B; + REG_DMC520->dq_map_control_71_64_next = 0x00AA2E03; + } else if (g_DDR4_DMC520_INIT_CH == 1) { + REG_DMC520->dq_map_control_15_00_next = 0x240E2D0E; + REG_DMC520->dq_map_control_31_16_next = 0x31120923; + REG_DMC520->dq_map_control_47_32_next = 0x350C2B15; + REG_DMC520->dq_map_control_63_48_next = 0x2C0B3616; + REG_DMC520->dq_map_control_71_64_next = 0x00AA3118; + } + } else if (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) { + // for bit swap on sever board + if (g_DDR4_DMC520_INIT_CH == 0) { + REG_DMC520->dq_map_control_15_00_next = 0x0B36042E; + REG_DMC520->dq_map_control_31_16_next = 0x0C2C2D0D; + REG_DMC520->dq_map_control_47_32_next = 0x2E0D0C2C; + REG_DMC520->dq_map_control_63_48_next = 0x2E03162C; + REG_DMC520->dq_map_control_71_64_next = 0x00AA2E0D; + } else if (g_DDR4_DMC520_INIT_CH == 1) { + REG_DMC520->dq_map_control_15_00_next = 0x162B032D; + REG_DMC520->dq_map_control_31_16_next = 0x0A27370E; + REG_DMC520->dq_map_control_47_32_next = 0x24040C2C; + REG_DMC520->dq_map_control_63_48_next = 0x230E0C35; + REG_DMC520->dq_map_control_71_64_next = 0x00AA3113; + } + } else { + REG_DMC520->dq_map_control_15_00_next = + fw_get_ddr4_sdram_dq_map_control(0); + REG_DMC520->dq_map_control_31_16_next = + fw_get_ddr4_sdram_dq_map_control(1); + REG_DMC520->dq_map_control_47_32_next = + fw_get_ddr4_sdram_dq_map_control(2); + REG_DMC520->dq_map_control_63_48_next = + fw_get_ddr4_sdram_dq_map_control(3); + REG_DMC520->dq_map_control_71_64_next = + (fw_get_ddr4_sdram_dq_map_control(4) | 0x00AA0000); + } + + REG_DMC520->phy_rdwrdata_cs_mask_31_00 = 0x00000000; + REG_DMC520->phy_rdwrdata_cs_mask_63_32 = 0x00000000; + REG_DMC520->phy_request_cs_remap = 0x00000000; + REG_DMC520->odt_cp_control_31_00_next = 0x08040201; + REG_DMC520->odt_cp_control_63_32_next = 0x80402010; + REG_DMC520->interrupt_control = 0x000003FF; + +#ifdef DDR_DBI_ON + REG_DMC520->t_rtw_next += 0x00030303; + REG_DMC520->t_rtp_next += 0x00000003; // + tDBI=3clk + REG_DMC520->t_rddata_en_next += 0x00000003; + REG_DMC520->odt_timing_next += 0x03030000; + REG_DMC520->t_rw_odt_clr_next += 0x00000003; + REG_DMC520->feature_config |= 0x00000010; + REG_DMC520->feature_control_next |= 0x00000005; +#endif // DDR_DBI_ON + +#ifdef DDR_CA_Parity_ON + dmb(); + REG_DMC520->t_mrw_next += 0x00040004; + REG_DMC520->t_wr_next += 0x00000004; + REG_DMC520->t_wtr_next += 0x00040404; + REG_DMC520->t_esrck_next += 0x00000004; + REG_DMC520->t_parity_next += 0x00000400; + REG_DMC520->t_rddata_en_next += 0x00000004; + REG_DMC520->t_phyrdlat_next += 0x00000004; + REG_DMC520->t_phywrlat_next += 0x00000004; +#endif // DDR_CA_Parity_ON + +#ifdef DDR_CRC_ON + dmb(); + REG_DMC520->t_wr_next += 0x00000005; + REG_DMC520->t_wtr_next += 0x00050505; + REG_DMC520->t_wtw_next += 0x00000001; + REG_DMC520->t_parity_next = 0x00002F00; + REG_DMC520->odt_timing_next += 0x00000100; + REG_DMC520->t_odth_next += 0x00000001; + REG_DMC520->feature_control_next |= 0x00000002; +#endif // DDR_CRC_ON + + if (dram_ecc_is_enabled()) + REG_DMC520->feature_config |= 0x00000015; + + // UPDATE + REG_DMC520->direct_cmd = 0x0001000C; + + // TRAIN + REG_DMC520->direct_addr = 0x00000004; + REG_DMC520->direct_cmd = 0x0001000A; + + // dfi_data_byte_disable control + if (fw_get_ddr4_sdram_ecc_available()) { + if ((REG_DMC520->feature_config & 0x3) == 0) { + // [1:0] ecc_enable = b01 (ECC BYTE dfi_data_byte_disable=0) + REG_DMC520->feature_config |= 0x00000001; + } + } else { + // [1:0] ecc_enable = b00 (ECC BYTE dfi_data_byte_disable=1) + REG_DMC520->feature_config &= 0xFFFFFFFC; + } + + REG_DMC520->memc_status; + REG_DMC520->memc_config; + + return 0; +} + +int ddr_init_phy0_mp( + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en) +{ + uint32_t ddr_memory_type; + ddr_memory_type = fw_get_memory_type(); + + REG_DDRPHY_CONFIG->PGSR0; + REG_DDRPHY_CONFIG->PGSR1; + + REG_DDRPHY_CONFIG->PGCR0 = 0x07D81E01; + REG_DDRPHY_CONFIG->PGCR1 = 0x02004660; + REG_DDRPHY_CONFIG->PGCR2 = 0x00012480; + REG_DDRPHY_CONFIG->PTR0 = 0x42C21510; + REG_DDRPHY_CONFIG->PTR1 = 0xD05612C0; + REG_DDRPHY_CONFIG->PTR3 = 0x18082356; + REG_DDRPHY_CONFIG->PTR4 = 0x10034156; + REG_DDRPHY_CONFIG->PLLCR = 0x00038000; + REG_DDRPHY_CONFIG->DXCCR = 0x20C00004; + REG_DDRPHY_CONFIG->DSGCR = 0x0020403E; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) { + REG_DDRPHY_CONFIG->RANKIDR = 0x00000002; + REG_DDRPHY_CONFIG->ODTCR = 0x00040000; + REG_DDRPHY_CONFIG->DCR = 0x38000404; + } else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) { + REG_DDRPHY_CONFIG->RANKIDR = 0x00000000; + REG_DDRPHY_CONFIG->ODTCR = 0x00050004; + REG_DDRPHY_CONFIG->RANKIDR = 0x00000001; + REG_DDRPHY_CONFIG->ODTCR = 0x000A0008; + REG_DDRPHY_CONFIG->RANKIDR = 0x00000002; + REG_DDRPHY_CONFIG->ODTCR = 0x00050001; + REG_DDRPHY_CONFIG->RANKIDR = 0x00000003; + REG_DDRPHY_CONFIG->ODTCR = 0x000A0002; + REG_DDRPHY_CONFIG->DCR = 0x08000404; + } else if (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) { + REG_DDRPHY_CONFIG->RANKIDR = 0x00000000; + REG_DDRPHY_CONFIG->ODTCR = 0x00010000; + REG_DDRPHY_CONFIG->RANKIDR = 0x00000001; + REG_DDRPHY_CONFIG->ODTCR = 0x00020000; + REG_DDRPHY_CONFIG->DCR = 0x38000404; + } else if (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) { + REG_DDRPHY_CONFIG->RANKIDR = 0x00000000; + REG_DDRPHY_CONFIG->ODTCR = 0x00010000; + REG_DDRPHY_CONFIG->DCR = 0x38000404; + } else if (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) { + REG_DDRPHY_CONFIG->RANKIDR = 0x00000002; + REG_DDRPHY_CONFIG->ODTCR = 0x00040000; + REG_DDRPHY_CONFIG->RANKIDR = 0x00000003; + REG_DDRPHY_CONFIG->ODTCR = 0x00080000; + REG_DDRPHY_CONFIG->DCR = 0x08000404; + } + + REG_DDRPHY_CONFIG->DTPR0 = 0x06241009; + REG_DDRPHY_CONFIG->DTPR1 = 0x28270008; + REG_DDRPHY_CONFIG->DTPR2 = 0x00060200; + REG_DDRPHY_CONFIG->DTPR3 = 0x22800101; + REG_DDRPHY_CONFIG->DTPR4 = 0x01760B07; + REG_DDRPHY_CONFIG->DTPR5 = 0x00341008; + REG_DDRPHY_CONFIG->DTPR6 = 0x00000505; + + if ((ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH)) { + if (retention_en == 0) + REG_DDRPHY_CONFIG->RDIMMGCR0 = 0xBC410001; + else + REG_DDRPHY_CONFIG->RDIMMGCR0 = 0xBC410009; + + REG_DDRPHY_CONFIG->RDIMMGCR1 = 0x00001903; + REG_DDRPHY_CONFIG->RDIMMGCR2 = 0x07FFFF3F; + REG_DDRPHY_CONFIG->RDIMMCR0 = 0x00555100; + REG_DDRPHY_CONFIG->RDIMMCR1 = 0x00C0A208; + REG_DDRPHY_CONFIG->RDIMMCR2 = 0x002C0100; + REG_DDRPHY_CONFIG->RDIMMCR3 = 0x00000000; + REG_DDRPHY_CONFIG->RDIMMCR4 = 0x00070000; + } + + REG_DDRPHY_CONFIG->MR0 = 0x00000830; + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) { + REG_DDRPHY_CONFIG->MR1 = 0x00000703; + REG_DDRPHY_CONFIG->MR2 = 0x00000010; + } else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) { + REG_DDRPHY_CONFIG->MR1 = 0x00000701; + REG_DDRPHY_CONFIG->MR2 = 0x00000210; + } else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH)) { + REG_DDRPHY_CONFIG->MR1 = 0x00000701; + REG_DDRPHY_CONFIG->MR2 = 0x00000010; + } + + REG_DDRPHY_CONFIG->MR3 = 0x00000200; + REG_DDRPHY_CONFIG->MR4 = 0x00000000; + REG_DDRPHY_CONFIG->MR5 = 0x00000500; + + if ((ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->MR6 = 0x0000082B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->MR6 = 0x00000829; + else if ( + (ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->MR6 = 0x0000082D; + + REG_DDRPHY_CONFIG->DTCR0 = 0x8000B0C7; + if (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) + REG_DDRPHY_CONFIG->DTCR1 = 0x000C2237; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DTCR1 = 0x000F0237; + else if (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) + REG_DDRPHY_CONFIG->DTCR1 = 0x00030237; + else if (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) + REG_DDRPHY_CONFIG->DTCR1 = 0x00010237; + else if ( + (ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DTCR1 = 0x00042237; + + REG_DDRPHY_CONFIG->DTAR0 = 0x04000000; + REG_DDRPHY_CONFIG->DTAR1 = 0x00010000; + REG_DDRPHY_CONFIG->DTAR2 = 0x00030002; + REG_DDRPHY_CONFIG->DCUTPR = 0x000000FF; + REG_DDRPHY_CONFIG->BISTRR = 0x03E40000; + REG_DDRPHY_CONFIG->BISTUDPR = 0xA5A5A5A5; + REG_DDRPHY_CONFIG->RIOCR0 = 0x0FFF0000; + REG_DDRPHY_CONFIG->RIOCR1 = 0xFF00FF00; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) { + REG_DDRPHY_CONFIG->RIOCR2 = 0x0000008A; + REG_DDRPHY_CONFIG->RIOCR4 = 0x0000008A; + REG_DDRPHY_CONFIG->RIOCR5 = 0x0000008A; + REG_DDRPHY_CONFIG->ACIOCR0 = 0x30003C10; + REG_DDRPHY_CONFIG->ACIOCR1 = 0x00000000; + REG_DDRPHY_CONFIG->ACIOCR3 = 0x0000008A; + } else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) { + REG_DDRPHY_CONFIG->RIOCR2 = 0x00000000; + REG_DDRPHY_CONFIG->RIOCR4 = 0x00000000; + REG_DDRPHY_CONFIG->RIOCR5 = 0x00000000; + REG_DDRPHY_CONFIG->ACIOCR0 = 0xF0003C10; + REG_DDRPHY_CONFIG->ACIOCR1 = 0x00000000; + REG_DDRPHY_CONFIG->ACIOCR3 = 0x00000000; + } else if (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH) { + REG_DDRPHY_CONFIG->RIOCR2 = 0x000000A0; + REG_DDRPHY_CONFIG->RIOCR4 = 0x000000A0; + REG_DDRPHY_CONFIG->RIOCR5 = 0x000000A0; + REG_DDRPHY_CONFIG->ACIOCR0 = 0x30003C10; + REG_DDRPHY_CONFIG->ACIOCR1 = 0x00000000; + REG_DDRPHY_CONFIG->ACIOCR3 = 0x000000A0; + } else if (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) { + REG_DDRPHY_CONFIG->RIOCR2 = 0x000000A8; + REG_DDRPHY_CONFIG->RIOCR4 = 0x000000A8; + REG_DDRPHY_CONFIG->RIOCR5 = 0x000000A8; + REG_DDRPHY_CONFIG->ACIOCR0 = 0x30003C10; + REG_DDRPHY_CONFIG->ACIOCR1 = 0x00000000; + REG_DDRPHY_CONFIG->ACIOCR3 = 0x000000A8; + } else if (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) { + REG_DDRPHY_CONFIG->RIOCR2 = 0x0000000A; + REG_DDRPHY_CONFIG->RIOCR4 = 0x0000000A; + REG_DDRPHY_CONFIG->RIOCR5 = 0x0000000A; + REG_DDRPHY_CONFIG->ACIOCR0 = 0x30003C10; + REG_DDRPHY_CONFIG->ACIOCR1 = 0x00000000; + REG_DDRPHY_CONFIG->ACIOCR3 = 0x0000000A; + } + + REG_DDRPHY_CONFIG->IOVCR0 = 0x0F090025; + REG_DDRPHY_CONFIG->IOVCR1 = 0x00000109; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) { + REG_DDRPHY_CONFIG->VTCR0 = 0x70030AAD; + REG_DDRPHY_CONFIG->VTCR1 = 0x0FC0F076; + REG_DDRPHY_CONFIG->ZQCR = 0x03058F00; + REG_DDRPHY_CONFIG->ZQ0PR = 0x0001DD1D; + REG_DDRPHY_CONFIG->ZQ1PR = 0x00079979; + REG_DDRPHY_CONFIG->ZQ2PR = 0x000BDDBD; + REG_DDRPHY_CONFIG->ZQ3PR = 0x000BDDBD; + } else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) { + REG_DDRPHY_CONFIG->VTCR0 = 0x7002C9A9; + REG_DDRPHY_CONFIG->VTCR1 = 0x0F77F076; + REG_DDRPHY_CONFIG->ZQCR = 0x03058F00; + REG_DDRPHY_CONFIG->ZQ0PR = 0x00019919; + REG_DDRPHY_CONFIG->ZQ1PR = 0x0005DD5D; + REG_DDRPHY_CONFIG->ZQ2PR = 0x00011111; + REG_DDRPHY_CONFIG->ZQ3PR = 0x00011111; + } else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) { + REG_DDRPHY_CONFIG->VTCR0 = 0x7002EA2B; + REG_DDRPHY_CONFIG->VTCR1 = 0x0FC0F076; + REG_DDRPHY_CONFIG->ZQCR = 0x03058F00; + REG_DDRPHY_CONFIG->ZQ0PR = 0x0001DD1D; + REG_DDRPHY_CONFIG->ZQ1PR = 0x0009DD9D; + REG_DDRPHY_CONFIG->ZQ2PR = 0x000BDDBD; + REG_DDRPHY_CONFIG->ZQ3PR = 0x000BDDBD; + } + + REG_DDRPHY_CONFIG->DX0GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX0GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX0GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX0GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX0GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX0GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX0GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX0GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX1GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX1GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX1GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX1GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX1GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX1GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX1GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX1GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX2GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX2GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX2GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX2GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX2GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX2GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX2GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX2GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX3GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX3GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX3GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX3GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX3GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX3GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX3GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX3GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX4GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX4GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX4GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX4GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX4GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX4GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX4GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX4GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX5GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX5GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX5GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX5GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX5GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX5GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX5GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX5GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX6GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX6GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX6GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX6GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX6GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX6GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX6GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX6GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX7GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX7GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX7GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX7GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX7GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX7GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX7GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX7GCR7 = 0x00810808; + REG_DDRPHY_CONFIG->DX8GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX8GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX8GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX8GCR3 = 0xFFFC0808; + + if ((ddr_memory_type == UDIMM_4GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == UDIMM_8GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX8GCR5 = 0x2B2B2B2B; + else if (ddr_memory_type == RDIMM_16GBPERSLOT_2SLOTPERCH) + REG_DDRPHY_CONFIG->DX8GCR5 = 0x3A3A3A3A; + else if ( + (ddr_memory_type == RDIMM_16GBPERSLOT_1SLOTPERCH) || + (ddr_memory_type == SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH)) + REG_DDRPHY_CONFIG->DX8GCR5 = 0x32323232; + + REG_DDRPHY_CONFIG->DX8GCR7 = 0x00810808; + +#ifdef DDR_DBI_ON + REG_DDRPHY_CONFIG->PGCR3 = + (REG_DDRPHY_CONFIG->PGCR3 & 0xF1FFFF1F) | 0x08000060; // [7:5]RDBICL=3 + REG_DDRPHY_CONFIG->MR0 = (REG_DDRPHY_CONFIG->MR0 & 0xFFFFFF8B) | + 0x00000040; // [6:5][2] CL +3 (15 -> 18) + REG_DDRPHY_CONFIG->MR5 = (REG_DDRPHY_CONFIG->MR5 & 0xFFFFE3FF) | 0x00001800; + REG_DDRPHY_CONFIG->DTCR0 = + (REG_DDRPHY_CONFIG->DTCR0 & 0xFFFF3FFF) | 0x00004000; // DBI de-skew +#endif // DDR_DBI_ON + +#ifdef DDR_CRC_ON + REG_DDRPHY_CONFIG->MR2 = (REG_DDRPHY_CONFIG->MR2 & 0xFFFFEFFF) | 0x00001000; +#endif // DDR_CRC_ON + +#ifdef DDR_CA_Parity_ON + REG_DDRPHY_CONFIG->MR5 = (REG_DDRPHY_CONFIG->MR5 & 0xFFFFFFF8) | 0x00000001; +#endif // DDR_CA_Parity_ON + + if (fw_get_ddr4_sdram_ecc_available()) { + REG_DDRPHY_CONFIG->DX8GCR0 = 0x40000205; + REG_DDRPHY_CONFIG->DX8GCR1 = 0xAAAA0000; + REG_DDRPHY_CONFIG->DX8GCR2 = 0x00000000; + REG_DDRPHY_CONFIG->DX8GCR3 = 0xFFFC0808; + REG_DDRPHY_CONFIG->DX8GCR7 = 0x00810808; + } else { + REG_DDRPHY_CONFIG->DX8GCR0 = 0x00023220; + REG_DDRPHY_CONFIG->DX8GCR1 = 0x55550000; + REG_DDRPHY_CONFIG->DX8GCR2 = 0xAAAAAAAA; + REG_DDRPHY_CONFIG->DX8GCR3 = 0xC0FCA4A4; + REG_DDRPHY_CONFIG->DX8GCR7 = 0x00E8A4A4; + } + + return 0; +} + +int ddr_init_phy1_mp( + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en) +{ + if (retention_en == 0) + REG_DDRPHY_CONFIG->PIR = + (REG_DDRPHY_CONFIG->PIR & 0xFFFFFF8C) | 0x00000073; + else + REG_DDRPHY_CONFIG->PIR = + (REG_DDRPHY_CONFIG->PIR & 0xBFFFFF8C) | 0x40000071; + + // Wait by completion of PHY initialization. + dmb(); + Wait_for_ddr(1); + usleep_en(1); + + // [0]IDONE, [1]PLDONE, [2]DCDONE, [3]ZCDONE, [31]APLOCK + ddr_wait( + (REG_DDRPHY_CONFIG->PGSR0 & 0x8000000F) != 0x8000000F, + DDR_WAIT_TIMEOUT_US, + 0x1001); + + REG_DDRPHY_CONFIG->PGSR0; + REG_DDRPHY_CONFIG->PGSR1; + + return 0; +} + +int ddr_init_sdram_mp( + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en) +{ + uint32_t mr6; + uint32_t mr6_vref_training_on; + uint32_t mr6_vref_training_off; + uint32_t Addr_Invert; + + if (retention_en == 0) { + REG_DDRPHY_CONFIG->PIR = (REG_DDRPHY_CONFIG->PIR & 0xFFF7FE7E) | + 0x00000181 | ((REG_DDRPHY_CONFIG->RDIMMGCR0 & 0x1) << 19); + dmb(); + usleep_en(500); + + // Wait by completion of DRAM initialization. + dmb(); + Wait_for_ddr(1); + // [0]IDONE, [4]DIDONE + ddr_wait( + (REG_DDRPHY_CONFIG->PGSR0 & 0x00000011) != 0x00000011, + DDR_WAIT_TIMEOUT_US, + 0x2001); + + Addr_Invert = + (((REG_DDRPHY_CONFIG->RDIMMCR0 & 0x1) == 0) && + ((REG_DDRPHY_CONFIG->RDIMMGCR0 & 0x1) == 1)); + mr6 = REG_DDRPHY_CONFIG->MR6; + mr6_vref_training_on = + (mr6 & 0xFFFFFF7F) | (1 << 7); // [7]VrefDQ Training Enable = 1 + mr6_vref_training_off = + (mr6 & 0xFFFFFF7F) | (0 << 7); // [7]VrefDQ Training Enable = 0 + + REG_DDRPHY_CONFIG->SCHCR0 = + (REG_DDRPHY_CONFIG->SCHCR0 & 0xFFFFFF0F) | 0x00000010; // [7:4]CMD + + // VrefDQ Training On + REG_DDRPHY_CONFIG->SCHCR1 = (REG_DDRPHY_CONFIG->SCHCR1 & 0xF000000F) | + ((mr6_vref_training_on << 8) | (0x1 << 6) | (0x2 << 4) | + (0x1 << 2)); //[27:8]SCADDR,[7:6]SCBG,[5:4]SCBK,[2]ALLRANK + REG_DDRPHY_CONFIG->SCHCR0 = (REG_DDRPHY_CONFIG->SCHCR0 & 0xFFFFFFF0) | + 0x00000001; // [3:0]SCHTRIG + if (Addr_Invert == 1) { // for RDIMM B-side + REG_DDRPHY_CONFIG->SCHCR1 = + (REG_DDRPHY_CONFIG->SCHCR1 & 0xF000000F) | + ((mr6_vref_training_on << 8) | (0x3 << 6) | (0x2 << 4) | + (0x1 << 2)); //[27:8]SCADDR,[7:6]SCBG,[5:4]SCBK,[2]ALLRANK + REG_DDRPHY_CONFIG->SCHCR0 = + (REG_DDRPHY_CONFIG->SCHCR0 & 0xFFFFFFF0) | + 0x00000001; // [3:0]SCHTRIG + } + // wait tVREFDQE // + // New VrefDQ Value + REG_DDRPHY_CONFIG->SCHCR1 = (REG_DDRPHY_CONFIG->SCHCR1 & 0xF000000F) | + ((mr6_vref_training_on << 8) | (0x1 << 6) | (0x2 << 4) | + (0x1 << 2)); //[27:8]SCADDR,[7:6]SCBG,[5:4]SCBK,[2]ALLRANK + REG_DDRPHY_CONFIG->SCHCR0 = (REG_DDRPHY_CONFIG->SCHCR0 & 0xFFFFFFF0) | + 0x00000001; // [3:0]SCHTRIG + if (Addr_Invert == 1) { // for RDIMM B-side + REG_DDRPHY_CONFIG->SCHCR1 = + (REG_DDRPHY_CONFIG->SCHCR1 & 0xF000000F) | + ((mr6_vref_training_on << 8) | (0x3 << 6) | (0x2 << 4) | + (0x1 << 2)); //[27:8]SCADDR,[7:6]SCBG,[5:4]SCBK,[2]ALLRANK + REG_DDRPHY_CONFIG->SCHCR0 = + (REG_DDRPHY_CONFIG->SCHCR0 & 0xFFFFFFF0) | + 0x00000001; // [3:0]SCHTRIG + } + // wait tVREFDQE // + // VrefDQ Training Off + REG_DDRPHY_CONFIG->SCHCR1 = (REG_DDRPHY_CONFIG->SCHCR1 & 0xF000000F) | + ((mr6_vref_training_off << 8) | (0x1 << 6) | (0x2 << 4) | + (0x1 << 2)); //[27:8]SCADDR,[7:6]SCBG,[5:4]SCBK,[2]ALLRANK + REG_DDRPHY_CONFIG->SCHCR0 = (REG_DDRPHY_CONFIG->SCHCR0 & 0xFFFFFFF0) | + 0x00000001; // [3:0]SCHTRIG + if (Addr_Invert == 1) { // for RDIMM B-side + REG_DDRPHY_CONFIG->SCHCR1 = + (REG_DDRPHY_CONFIG->SCHCR1 & 0xF000000F) | + ((mr6_vref_training_off << 8) | (0x3 << 6) | (0x2 << 4) | + (0x1 << 2)); //[27:8]SCADDR,[7:6]SCBG,[5:4]SCBK,[2]ALLRANK + REG_DDRPHY_CONFIG->SCHCR0 = + (REG_DDRPHY_CONFIG->SCHCR0 & 0xFFFFFFF0) | + 0x00000001; // [3:0]SCHTRIGy + } + } + + REG_DDRPHY_CONFIG->PGSR0; + dmb(); + usleep_en(500); + REG_DDRPHY_CONFIG->PGSR1; + dmb(); + usleep_en(500); + + return 0; +} + +int ddr_init_mc1_mp(REG_ST_DMC520 *REG_DMC520) +{ + REG_DMC520->memc_status; + REG_DMC520->memc_config; + + // POWERDOWN_ENTRY + REG_DMC520->direct_addr = 0x00000006; + REG_DMC520->direct_cmd = 0x000F0004; + REG_DMC520->memc_status; + + // wait + usleep_en(500); + + // INVALIDATE RESET + REG_DMC520->direct_addr = 0x00000000; + REG_DMC520->direct_cmd = 0x0001000B; + REG_DMC520->memc_status; + + // wait + usleep_en(500); + + // INVALIDATE RESET + REG_DMC520->direct_addr = 0x00000001; + REG_DMC520->direct_cmd = 0x000F000B; + REG_DMC520->memc_status; + + // wait + usleep_en(500); + + // WAIT + REG_DMC520->direct_addr = 0x000003E8; + REG_DMC520->direct_cmd = 0x0001000D; + REG_DMC520->memc_status; + REG_DMC520->direct_addr = 0x00000258; + REG_DMC520->direct_cmd = 0x0001000D; + REG_DMC520->memc_status; + + // INVALIDATE RESET + REG_DMC520->direct_addr = 0x00010001; + REG_DMC520->direct_cmd = 0x000F000B; + REG_DMC520->memc_status; + + // wait + usleep_en(500); + + // WAIT + REG_DMC520->direct_addr = 0x0000003C; + REG_DMC520->direct_cmd = 0x0001000D; + REG_DMC520->memc_status; + + // NOP + REG_DMC520->direct_addr = 0x00000000; + REG_DMC520->direct_cmd = 0x000F0000; + REG_DMC520->memc_status; + + return 0; +} + +int ddr_init_train_mp( + REG_ST_DDRPHY_CONFIG_t *REG_DDRPHY_CONFIG, + int retention_en) +{ + int status = 0; + uint32_t phy_status_0; + + REG_DDRPHY_CONFIG->PGSR0; + REG_DDRPHY_CONFIG->PGSR1; + + ///////////////////////////////////////////////////////////////////// + // 1. Write Leveling, Gate Training, Write Leveling Adjust + ///////////////////////////////////////////////////////////////////// + REG_DDRPHY_CONFIG->PGCR3 = + (REG_DDRPHY_CONFIG->PGCR3 & 0xFFFFFFE7) | 0x00000000; + dmb(); + +#ifdef DDR_DQSTRAINWA_ON + REG_DDRPHY_CONFIG->PIR = (REG_DDRPHY_CONFIG->PIR & 0xFFFFFDFE) | 0x00000201; + dmb(); + Wait_for_ddr(1); + dmb(); + // [0]IDONE, [5]WLDONE + while (((REG_DDRPHY_CONFIG->PGSR0 & 0x00000021) != 0x00000021) && + ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) == 0)) + ; + + REG_DDRPHY_CONFIG->DXCCR = + (REG_DDRPHY_CONFIG->DXCCR & 0xFFBFFFFF) | 0x00000000; + dmb(); + + REG_DDRPHY_CONFIG->PIR = (REG_DDRPHY_CONFIG->PIR & 0xFFFFFBFE) | 0x00000401; + dmb(); + Wait_for_ddr(1); + dmb(); + // [0]IDONE, [6]QSGDONE + while (((REG_DDRPHY_CONFIG->PGSR0 & 0x00000041) != 0x00000041) && + ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) == 0)) + ; + + REG_DDRPHY_CONFIG->DXCCR = + (REG_DDRPHY_CONFIG->DXCCR & 0xFFBFFFFF) | 0x00400000; + dmb(); + + REG_DDRPHY_CONFIG->PIR = (REG_DDRPHY_CONFIG->PIR & 0xFFFFF7FE) | 0x00000801; + dmb(); + Wait_for_ddr(1); + dmb(); + // [0]IDONE, [7]WLADONE + while (((REG_DDRPHY_CONFIG->PGSR0 & 0x00000081) != 0x00000081) && + ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) == 0)) + ; + +#else + REG_DDRPHY_CONFIG->PIR = (REG_DDRPHY_CONFIG->PIR & 0xFFFFF1FE) | 0x00000E01; + dmb(); + // Wait by completion of Data Training. + Wait_for_ddr(1); + dmb(); + + // [0]IDONE, [5]WLDONE, [6]QSGDONE, [7]WLADONE + ddr_wait( + ((REG_DDRPHY_CONFIG->PGSR0 & 0x000000E1) != 0x000000E1) && + ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) == 0), + DDR_WAIT_TIMEOUT_US, + 0x3001); + + if ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) != 0) { + printf( + "error : Write Leveling, Gate Training, Write Leveling Adjust\n"); + status = 0x3002; + goto ERROR_END; + } +#endif + + ///////////////////////////////////////////////////////////////////// + // 2. Data Bit Deskew, Data Eye, Static Read + ///////////////////////////////////////////////////////////////////// + REG_DDRPHY_CONFIG->PGCR0 = + (REG_DDRPHY_CONFIG->PGCR0 & 0xFBFFFFFF) | 0x00000000; + dmb(); + // Wait for more than 10cycle with reference to pclk. + Wait_for_ddr(1); + + REG_DDRPHY_CONFIG->PGCR3 = + (REG_DDRPHY_CONFIG->PGCR3 & 0xFFFFFFE7) | 0x00000008; + dmb(); + + // Wait for more than 10cycle with reference to pclk. + Wait_for_ddr(1); + + REG_DDRPHY_CONFIG->PGCR0 = + (REG_DDRPHY_CONFIG->PGCR0 & 0xFBFFFFFF) | 0x04000000; + dmb(); + + // Wait for more than 10cycle with reference to pclk. + Wait_for_ddr(1); + + REG_DDRPHY_CONFIG->PIR = (REG_DDRPHY_CONFIG->PIR & 0xFFFE0FFE) | 0x0001F001; + dmb(); + + // Wait by completion of Data Training. + Wait_for_ddr(1); + // [0]IDONE, [8]RDDONE, [9]WDDONE, [10]REDONE, [11]WEDONE, [13]SRDDONE + // [note] timeout : Data Bit Deskew, Data Eye, Static Read + ddr_wait( + ((REG_DDRPHY_CONFIG->PGSR0 & 0x00002F01) != 0x00002F01) && + ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) == 0), + DDR_WAIT_TIMEOUT_US, + 0x3003); + + if ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) != 0) { + printf("error : Data Bit Deskew, Data Eye, Static Read\n"); + status = 0x3004; + goto ERROR_END; + } + + ///////////////////////////////////////////////////////////////////// + // 3. VREF Training + ///////////////////////////////////////////////////////////////////// + if (retention_en == 0) { + REG_DDRPHY_CONFIG->DTCR0 = + (REG_DDRPHY_CONFIG->DTCR0 & 0x0FFFFFFF) | 0x00000000; + dmb(); + + REG_DDRPHY_CONFIG->PIR = + (REG_DDRPHY_CONFIG->PIR & 0xFFFDFFFE) | 0x00020001; + dmb(); + + // 76 Wait by completion of Data Training. + Wait_for_ddr(20); + + // [14]VDONE + ddr_wait( + ((REG_DDRPHY_CONFIG->PGSR0 & 0x00004001) != 0x00004001) && + ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) == 0), + DDR_WAIT_TIMEOUT_US, + 0x3005); + + if ((REG_DDRPHY_CONFIG->PGSR0 & 0x4FF80000) != 0) { + printf("error : VREF Training\n"); + status = 0x3006; + goto ERROR_END; + } + + REG_DDRPHY_CONFIG->DTCR0 = + (REG_DDRPHY_CONFIG->DTCR0 & 0x0FFFFFFF) | 0x80000000; + } + +ERROR_END: + ///////////////////////////////////////////////////////////////////// + // Check Status + ///////////////////////////////////////////////////////////////////// + phy_status_0 = REG_DDRPHY_CONFIG->PGSR0; + if (((phy_status_0 >> 19) & 0x1) == 0x1) { + pr_err("%s VREF Training Error\n", __func__); + status = 0x3010; + } + if (((phy_status_0 >> 20) & 0x1) == 0x1) { + pr_err("%s Impedance Calibration Error\n", __func__); + status = 0x3011; + } + if (((phy_status_0 >> 21) & 0x1) == 0x1) { + pr_err("%s Write Leveling Error\n", __func__); + status = 0x3012; + } + if (((phy_status_0 >> 22) & 0x1) == 0x1) { + pr_err("%s DQS Gate Training Error\n", __func__); + status = 0x3013; + } + if (((phy_status_0 >> 23) & 0x1) == 0x1) { + pr_err("%s Write Leveling Adjustment Error\n", __func__); + status = 0x3014; + } + if (((phy_status_0 >> 24) & 0x1) == 0x1) { + pr_err("%s Read Bit Deskew Error\n", __func__); + status = 0x3015; + } + if (((phy_status_0 >> 25) & 0x1) == 0x1) { + pr_err("%s Write Bit Deskew Error\n", __func__); + status = 0x3016; + } + if (((phy_status_0 >> 26) & 0x1) == 0x1) { + pr_err("%s Read Eye Training Error\n", __func__); + status = 0x3017; + } + if (((phy_status_0 >> 27) & 0x1) == 0x1) { + pr_err("%s Write Eye Training Error\n", __func__); + status = 0x3018; + } + if (((phy_status_0 >> 30) & 0x1) == 0x1) { + pr_err("%s Static Read Error\n", __func__); + status = 0x3019; + } + + if (status != 0) + return status; + +#ifdef DDR_TRAINING_RESULT + ddr_init_train_result(REG_DDRPHY_CONFIG); +#endif // DDR_TRAINING_RESULT + + REG_DDRPHY_CONFIG->PGCR1 = + (REG_DDRPHY_CONFIG->PGCR1 & 0xFFFFFFBF) | 0x00000000; + + REG_DDRPHY_CONFIG->PGSR0; + REG_DDRPHY_CONFIG->PGSR1; + + return 0; +} + +int ddr_init_mc2_mp(REG_ST_DMC520 *REG_DMC520) +{ + REG_DMC520->memc_status; + REG_DMC520->memc_config; + + if (!dram_ecc_is_enabled()) + REG_DMC520->feature_config &= 0xFFFFFFFC; + + // UPDATE + REG_DMC520->direct_cmd = 0x0001000C; + + // ZQC + REG_DMC520->direct_addr = 0x00000400; + REG_DMC520->direct_cmd = 0x000F0005; + dmb(); + REG_DMC520->memc_status; + + // Wait + REG_DMC520->direct_addr = 0x000003ff; + REG_DMC520->direct_cmd = 0x0001000d; + dmb(); + REG_DMC520->memc_status; + + REG_DMC520->memc_status; + REG_DMC520->memc_status; + REG_DMC520->memc_status; + REG_DMC520->memc_status; + REG_DMC520->memc_cmd = 0x00000003; + dmb(); + REG_DMC520->memc_status; + REG_DMC520->memc_cmd = 0x00000004; + dmb(); + + ddr_wait( + (REG_DMC520->memc_status & 0x7) != 0x3, DDR_WAIT_TIMEOUT_US, 0x4001); + + REG_DMC520->memc_status; + REG_DMC520->memc_config; + + return 0; +} diff --git a/product/synquacer/module/synquacer_memc/src/mod_synquacer_memc.c b/product/synquacer/module/synquacer_memc/src/mod_synquacer_memc.c new file mode 100644 index 000000000..9ccc52307 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/src/mod_synquacer_memc.c @@ -0,0 +1,88 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +const struct mod_f_i2c_api *f_i2c_api; +static struct mod_log_api *log_api; +static int synquacer_memc_config(void); + +/* Framework API */ +static int mod_synquacer_memc_init( + fwk_id_t module_id, + unsigned int element_count, + const void *config) +{ + return FWK_SUCCESS; +} + +static int mod_synquacer_memc_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + +static int mod_synquacer_memc_bind(fwk_id_t id, unsigned int round) +{ + int status; + + /* Nothing to do in the second round of calls. */ + if (round == 1) + return FWK_SUCCESS; + + /* Nothing to do in case of elements. */ + if (fwk_module_is_valid_element_id(id)) + return FWK_SUCCESS; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_LOG), MOD_LOG_API_ID, &log_api); + if (status != FWK_SUCCESS) + return status; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_F_I2C), + FWK_ID_API(FWK_MODULE_IDX_F_I2C, 0), + &f_i2c_api); + if (status != FWK_SUCCESS) + return status; + + return FWK_SUCCESS; +} + +static int mod_synquacer_memc_start(fwk_id_t id) +{ + synquacer_memc_config(); + return FWK_SUCCESS; +} + +static int synquacer_memc_config(void) +{ + fw_ddr_init(); + + log_api->log(MOD_LOG_GROUP_INFO, "[SYNQUACER MEMC] DMC init done.\n"); + + return FWK_SUCCESS; +} + +const struct fwk_module module_synquacer_memc = { + .name = "synquacer_memc", + .type = FWK_MODULE_TYPE_DRIVER, + .init = mod_synquacer_memc_init, + .element_init = mod_synquacer_memc_element_init, + .bind = mod_synquacer_memc_bind, + .start = mod_synquacer_memc_start, + .api_count = 0, + .event_count = 0, +}; diff --git a/product/synquacer/module/synquacer_memc/src/synquacer_ddr.c b/product/synquacer/module/synquacer_memc/src/synquacer_ddr.c new file mode 100644 index 000000000..9cebba0f0 --- /dev/null +++ b/product/synquacer/module/synquacer_memc/src/synquacer_ddr.c @@ -0,0 +1,896 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const struct mod_f_i2c_api *f_i2c_api; + +#define CONFIG_DDR_ERROR_FORCE_STOP + +static char *dimm_module_type[] = { "Extended DIMM", "RDIMM", "UDIMM", + "SO-DIMM", "LRDIMM", "Mini-RDIMM", + "Mini-UDIMM", "Reserved", "72b-SO-RDIMM", + "72b-SO-UDIMM" }; + +typedef struct spd_ddr_info_s { + uint8_t base_module_type; + uint8_t ddr_memory_type; + uint8_t slot_bitmap; + uint8_t ddr_memory_used_ch; + bool ecc_available; + uint8_t rank_address_bits; + uint8_t row_address_bits; + uint8_t column_address_bits; + uint32_t set_memory_type_next; + uint32_t dmc_address_control; + uint32_t sdram_slot_total[DIMM_SLOT_NUM]; + uint32_t per_slot_dimm_size; + uint32_t dq_map_control[5]; +} spd_ddr_info_t; + +static spd_ddr_info_t spd_ddr_info = { 0 }; +static uint8_t buf[SPD_READ_BYTE_NUM]; + +void sysoc_set_reset(uint32_t sysoc_addr, uint32_t value); +int sysoc_wait_status_change( + uint32_t sysoc_addr, + bool reset_set_flag, + uint32_t set_bit); +int ddr_ch0_init_mp(void); +int ddr_ch1_init_mp(void); +static void dram_init_for_ecc(void); + +typedef enum { + SPD_READ_SLOT_AVAILABLE = 0, + SPD_READ_SLOT_NONE, + SPD_READ_ERROR, + SPD_READ_INVALID_PARAM, + SPD_READ_SET_PAGE_ADDR_ERROR +} spd_read_err_code_t; + +static uint32_t get_i2c_slave_addr_set_page(uint32_t target_page); +static spd_read_err_code_t read_spd( + uint32_t slot, + uint8_t *dst, + int32_t total_len); +static void store_spd_to_nssram(void); + +static uint32_t config_ddr4_sdram_total_size; + +enum ddr_freq_e { + DDR_FREQ_1333 = 0, + DDR_FREQ_1600, + DDR_FREQ_1800, + DDR_FREQ_1866, + DDR_FREQ_2133, + DDR_FREQ_MAX, +}; + +typedef enum ddr_freq_e ddr_freq_t; + +static void fw_ddr_change_freq(ddr_freq_t freq); + +void fw_ddr_init(void) +{ + int result = 0; + + fw_ddr_change_freq(CONFIG_SCB_DDR_FREQ); + + if (spd_ddr_info.ddr_memory_used_ch == DDR_USE_CH0) + result = ddr_ch0_init_mp(); + else if (spd_ddr_info.ddr_memory_used_ch == DDR_USE_CH1) + result = ddr_ch1_init_mp(); + else + result = ddr_dual_ch_init_mp(); + + if (result != 0) { + /* Tentative workaround. Need to implement retrying. */ + do { + SYNQUACER_DEV_LOG_ERROR("DDR Initialize Failed.(0x%x)\n", result); + osDelay(10000); + } while (1); + } + + if (fw_get_ddr4_sdram_ecc_available() && dram_ecc_is_enabled()) { + SYNQUACER_DEV_LOG_INFO("[DDR] DRAM ECC enabled\n"); + dram_init_for_ecc(); + } else { + SYNQUACER_DEV_LOG_INFO("[DDR] DRAM ECC disabled\n"); + } + + /* + * save SPD information to non-secure SRAM + * will be used for system information such as SMBIOS. + */ + store_spd_to_nssram(); +} + +static void fw_ddr_change_freq(ddr_freq_t freq) +{ + uint32_t value = 0; + if (freq >= DDR_FREQ_MAX) + return; + + switch (freq) { + case DDR_FREQ_1333: + SYNQUACER_DEV_LOG_INFO("[DDR] 1333MHz\n"); + value = 0x00000027U; /* 1333MHz */ + break; + case DDR_FREQ_1600: + SYNQUACER_DEV_LOG_INFO("[DDR] 1600MHz\n"); + value = 0x0000002FU; /* 1600MHz */ + break; + case DDR_FREQ_1800: + SYNQUACER_DEV_LOG_INFO("[DDR] 1800MHz\n"); + value = 0x00000035U; /* 1800MHz */ + break; + case DDR_FREQ_1866: + SYNQUACER_DEV_LOG_INFO("[DDR] 1866MHz\n"); + value = 0x00000037U; /* 1866MHz */ + break; + case DDR_FREQ_2133: + SYNQUACER_DEV_LOG_INFO("[DDR] 2133MHz\n"); + value = 0x0000003FU; /* 2133MHz */ + break; + default: + SYNQUACER_DEV_LOG_INFO("[DDR] Invalid DDR frequency\n"); + assert(false); + } + + /* set value */ + writel(0x48370000, value); + + /* change freq value kick */ + writel(0x48370080, 0x00000004); + + /* wait for change freq done */ + while (readl(0x48370080) != 0x00000000) + ; + + /* set value */ + writel(0x48378000, value); + + /* change freq value kick */ + writel(0x48378080, 0x00000004); + + /* wait for change freq done */ + while (readl(0x48378080) != 0x00000000) + ; +} + +static uint32_t get_i2c_slave_addr_set_page(uint32_t target_page) +{ + if (target_page == 0) + return SPD_DTIC_SPA0; + else + return SPD_DTIC_SPA1; +} + +static spd_read_err_code_t read_spd( + uint32_t slot, + uint8_t *dst, + int32_t total_len) +{ + I2C_ERR_t i2c_err; + uint8_t dummy = 0; + int32_t read_len; + uint32_t spd_page; + uint32_t i2c_slave_addr_read_spd; + uint32_t i2c_slave_addr_set_page; + + /* + * SPD for DDR4 consists of 512 bytes information and it is divided into + * two 256 bytes pages. + * Setting page address to 0 selects the lower 256 bytes, + * Setting it to 1 selects upper 256 bytes. + * To set the page address, dummy write to the SPA0/SPA1. + */ + + if (total_len > (SPD_PAGE_SIZE * SPD_NUM_OF_PAGE)) + return SPD_READ_INVALID_PARAM; + + i2c_slave_addr_read_spd = slot + sysdef_option_get_i2c_for_spd_read_addr(); + + for (spd_page = 0; spd_page < SPD_NUM_OF_PAGE; spd_page++) { + /* dummy write to switch the spd page */ + i2c_slave_addr_set_page = get_i2c_slave_addr_set_page(spd_page); + i2c_err = f_i2c_api->send_data( + I2C_EN_CH0, i2c_slave_addr_set_page, 0, &dummy, sizeof(dummy)); + if (i2c_err != I2C_ERR_OK) + return SPD_READ_SET_PAGE_ADDR_ERROR; + + read_len = (total_len > SPD_PAGE_SIZE) ? SPD_PAGE_SIZE : total_len; + + i2c_err = f_i2c_api->recv_data( + I2C_EN_CH0, i2c_slave_addr_read_spd, 0, dst, read_len); + if (i2c_err == I2C_ERR_UNAVAILABLE) { + SYNQUACER_DEV_LOG_DEBUG( + "[SYSTEM] slot DIMM%d: not detected\n", slot); + return SPD_READ_SLOT_NONE; + } + if (i2c_err != I2C_ERR_OK) { + SYNQUACER_DEV_LOG_INFO( + "[SYSTEM] Error detected while reading the first byte of SPD. " + "slave_addr:0x%02x, errror code = %d\n", + i2c_slave_addr_read_spd, + i2c_err); + return SPD_READ_ERROR; + } + + total_len -= read_len; + if (total_len <= 0) + break; + + dst += SPD_PAGE_SIZE; + } + + return SPD_READ_SLOT_AVAILABLE; +} + +bool fw_spd_ddr_info_get(spd_ddr_info_t *spd_ddr_info_p) +{ + int i; + spd_read_err_code_t i2c_err_check; + int check_dimm_slot; + bool error_flag = false; + + spd_ddr_info_p->slot_bitmap = 0; + spd_ddr_info_p->base_module_type = 0; + + for (check_dimm_slot = 0; check_dimm_slot < DIMM_SLOT_NUM; + check_dimm_slot++) { + /* SPD parameter */ + uint32_t sdram_capacity, logical_ranks_per_dimm, primary_bus_width, + sdram_width, bank_group_bits; + + /* spd parameter initialize */ + memset(buf, 0, SPD_READ_BYTE_NUM); + + i2c_err_check = read_spd(check_dimm_slot, buf, SPD_READ_BYTE_NUM); + + if (i2c_err_check == SPD_READ_SLOT_NONE) + continue; + + if (i2c_err_check != SPD_READ_SLOT_AVAILABLE) { + error_flag = true; + return error_flag; + } + + /* check base module type */ + if ((spd_ddr_info_p->base_module_type != 0) && + (spd_ddr_info_p->base_module_type != (buf[3] & 0x0F))) { + /* error! mixed base module memory */ + SYNQUACER_DEV_LOG_ERROR("[ERROR] use same sdram type!\n"); + error_flag = true; + return error_flag; + } else { + spd_ddr_info_p->base_module_type = buf[3] & 0x0F; + } + + /* Bank Group Bits */ + bank_group_bits = (buf[4] & 0xC0) >> 6; + if (bank_group_bits == 0x02) + bank_group_bits = 0x03; + + /* SDRAM capacity */ + sdram_capacity = buf[4] & 0x0F; /* SPD original data */ + + /* Row Address Bits */ + spd_ddr_info_p->row_address_bits = ((buf[5] & 0x38) >> 3) + 1; + + /* Column Address Bits */ + spd_ddr_info_p->column_address_bits = (buf[5] & 0x07) + 1; + + /* bus width */ + sdram_width = buf[12] & 0x03; + + /* make memory_type_next */ + spd_ddr_info_p->set_memory_type_next = + (bank_group_bits << 16) | (sdram_width << 8) | DRAM_DDR4; + + logical_ranks_per_dimm = ((buf[12] & 0x38) >> 3) + 1; + + /* DDR4 package Type check */ + if ((buf[6] & 0x3) == 0x02 || (buf[6] & 0x3) == 0x03) { + SYNQUACER_DEV_LOG_ERROR("[ERROR] not support sdram type!\n"); + error_flag = true; + return error_flag; + } + /* Number of Package Ranks per DIMM */ + spd_ddr_info_p->rank_address_bits = logical_ranks_per_dimm - 1; + + spd_ddr_info_p->ecc_available = (buf[13] & 0x08) != 0; + primary_bus_width = 8 * (1 << (buf[13] & 0x07)); + + /* + * Total[MB] = SDRAM Capacity[GB] / 8 * Primary Bus Width / + * SDRAM Width * Logical Ranks per DIMM * 1024[GB->MB] + */ + spd_ddr_info.sdram_slot_total[check_dimm_slot] = + (((1 << sdram_capacity) >> 3) * primary_bus_width / + (4 * (1 << sdram_width)) * logical_ranks_per_dimm) + << 8; + spd_ddr_info_p->slot_bitmap |= (1 << check_dimm_slot); + SYNQUACER_DEV_LOG_INFO( + "[SYSTEM] slot DIMM%d: %dMB %s %s\n", + check_dimm_slot, + spd_ddr_info_p->sdram_slot_total[check_dimm_slot], + dimm_module_type[spd_ddr_info_p->base_module_type], + ((spd_ddr_info_p->ecc_available) ? "ECC" : "non-ECC")); + + /* dq_map_control data make */ + for (i = 0; i < 5; i++) { + spd_ddr_info_p->dq_map_control[i] = buf[60 + i * 4]; + spd_ddr_info_p->dq_map_control[i] |= (uint32_t)buf[61 + i * 4] << 8; + spd_ddr_info_p->dq_map_control[i] |= (uint32_t)buf[62 + i * 4] + << 16; + spd_ddr_info_p->dq_map_control[i] |= (uint32_t)buf[63 + i * 4] + << 24; + } + } + return error_flag; +} + +bool fw_spd_rdimm_support_check(spd_ddr_info_t *spd_ddr_info_p) +{ + bool error_flag = false; + + assert(spd_ddr_info_p->per_slot_dimm_size == FW_MODULE_CAPACITY_16GB); + + /* !ERROR CHECK! and memory kinds select */ + /* 16GB module RDIMM */ + switch (spd_ddr_info_p->slot_bitmap) { + /* 4slot */ + case 0x0FU: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_DUAL_CH; + spd_ddr_info_p->ddr_memory_type = RDIMM_16GBPERSLOT_2SLOTPERCH; + spd_ddr_info_p->rank_address_bits *= 2; + break; + + /* 2slot one side ch1 */ + case 0x0CU: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH1; + spd_ddr_info_p->ddr_memory_type = RDIMM_16GBPERSLOT_2SLOTPERCH; + spd_ddr_info_p->rank_address_bits *= 2; + break; + + /* 2slot one side ch0 */ + case 0x03U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH0; + spd_ddr_info_p->ddr_memory_type = RDIMM_16GBPERSLOT_2SLOTPERCH; + spd_ddr_info_p->rank_address_bits *= 2; + break; + + /* 2slot far side dual ch*/ + case 0x0AU: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_DUAL_CH; + spd_ddr_info_p->ddr_memory_type = RDIMM_16GBPERSLOT_1SLOTPERCH; + break; + + /* 1slot ch0 far side */ + case 0x02U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH0; + spd_ddr_info_p->ddr_memory_type = RDIMM_16GBPERSLOT_1SLOTPERCH; + break; + + /* 1slot ch1 far side */ + case 0x08U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH1; + spd_ddr_info_p->ddr_memory_type = RDIMM_16GBPERSLOT_1SLOTPERCH; + break; + + /* non support dimm slot layout! */ + default: + SYNQUACER_DEV_LOG_ERROR( + "[ERROR] read spd at sdram non support dimm slot layout!\n"); + error_flag = true; + return error_flag; + } + + return error_flag; +} + +bool fw_spd_udimm_support_check(spd_ddr_info_t *spd_ddr_info_p) +{ + bool error_flag = false; + + switch (spd_ddr_info_p->per_slot_dimm_size) { + case FW_MODULE_CAPACITY_8GB: + spd_ddr_info_p->ddr_memory_type = UDIMM_8GBPERSLOT_1SLOTPERCH; + break; + + case FW_MODULE_CAPACITY_4GB: + spd_ddr_info_p->ddr_memory_type = UDIMM_4GBPERSLOT_1SLOTPERCH; + break; + + default: + SYNQUACER_DEV_LOG_ERROR("[ERROR] non support capability dimm!\n"); + error_flag = true; + return error_flag; + } + + switch (spd_ddr_info_p->slot_bitmap) { + /* 2slot far side */ + case 0x0AU: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_DUAL_CH; + break; + + /* 1slot ch0 far side */ + case 0x02U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH0; + break; + + /* 1slot ch1 far side */ + case 0x08U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH1; + break; + + /* non support dimm slot layout! */ + default: + SYNQUACER_DEV_LOG_ERROR( + "[ERROR] read spd at sdram non support dimm slot layout!\n"); + error_flag = true; + return error_flag; + } + return error_flag; +} + +bool fw_spd_72bitsoudimm_support_check(spd_ddr_info_t *spd_ddr_info_p) +{ + bool error_flag = false; + + switch (spd_ddr_info_p->per_slot_dimm_size) { + case FW_MODULE_CAPACITY_16GB: + spd_ddr_info_p->ddr_memory_type = SOUDIMM_72BIT_16GBPERSLOT_1SLOTPERCH; + break; + + case FW_MODULE_CAPACITY_8GB: + spd_ddr_info_p->ddr_memory_type = SOUDIMM_72BIT_8GBPERSLOT_1SLOTPERCH; + break; + + default: + SYNQUACER_DEV_LOG_ERROR("[ERROR] non support capability dimm!\n"); + error_flag = true; + return error_flag; + } + + switch (spd_ddr_info_p->slot_bitmap) { + /* 2slot */ + case 0x03U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_DUAL_CH; + break; + + /* 1slot ch1 */ + case 0x02U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH1; + break; + + /* 1slot ch0 */ + case 0x01U: + spd_ddr_info_p->ddr_memory_used_ch = DDR_USE_CH0; + break; + + /* non support dimm slot layout! */ + default: + error_flag = true; + SYNQUACER_DEV_LOG_ERROR( + "[ERROR] read spd at sdram non support dimm slot layout!\n"); + } + + return error_flag; +} + +bool fw_spd_read_dimm_capacity_check(spd_ddr_info_t *spd_ddr_info_p) +{ + int i; + bool error_flag = false; + + spd_ddr_info_p->per_slot_dimm_size = 0; + config_ddr4_sdram_total_size = 0; + + for (i = 0; i < DIMM_SLOT_NUM; i++) { + if (spd_ddr_info_p->slot_bitmap & (1 << i)) { + if ((spd_ddr_info_p->per_slot_dimm_size != 0) && + (spd_ddr_info_p->per_slot_dimm_size != + spd_ddr_info_p->sdram_slot_total[i])) { + SYNQUACER_DEV_LOG_ERROR( + "[ERROR] Please use same capacity DDR memory!\n"); + error_flag = true; + return error_flag; + } + spd_ddr_info_p->per_slot_dimm_size = + spd_ddr_info_p->sdram_slot_total[i]; + config_ddr4_sdram_total_size += spd_ddr_info_p->sdram_slot_total[i]; + } + } + return error_flag; +} + +bool fw_spd_read_dimm_kinds_check(spd_ddr_info_t *spd_ddr_info_p) +{ + bool error_flag = false; + + /* !ERROR CHECK! and memory kinds select */ + switch (spd_ddr_info_p->base_module_type) { + /* RDIMM */ + case MODULE_TYPE_RDIMM: + error_flag = fw_spd_rdimm_support_check(spd_ddr_info_p); + break; + + /* UDIMM */ + case MODULE_TYPE_UDIMM: + error_flag = fw_spd_udimm_support_check(spd_ddr_info_p); + break; + + /* SODIMM */ + case MODULE_TYPE_72BITSOUDIMM: + error_flag = fw_spd_72bitsoudimm_support_check(spd_ddr_info_p); + break; + + /* other type memory module */ + default: + SYNQUACER_DEV_LOG_ERROR("[ERROR] sdram other type memory module\n"); + error_flag = true; + return error_flag; + } + + spd_ddr_info_p->dmc_address_control = + (uint32_t)(spd_ddr_info_p->rank_address_bits << 24) | BANK_BIT_NEXT | + (uint32_t)(spd_ddr_info_p->row_address_bits << 8) | + (uint32_t)(spd_ddr_info_p->column_address_bits); + + return error_flag; +} + +int fw_ddr_spd_param_check(void) +{ + SYNQUACER_DEV_LOG_INFO("[SYSTEM] Starting check DRAM\n"); + + if (fw_spd_ddr_info_get(&spd_ddr_info)) + return FWK_E_SUPPORT; + + if (fw_spd_read_dimm_capacity_check(&spd_ddr_info)) + return FWK_E_SUPPORT; + + if (fw_spd_read_dimm_kinds_check(&spd_ddr_info)) + return FWK_E_SUPPORT; + + SYNQUACER_DEV_LOG_INFO( + "[SYSTEM] Finished check DRAM memory total %dGB\n", + (config_ddr4_sdram_total_size / 1024)); + + return FWK_SUCCESS; +} + +bool fw_get_ddr4_sdram_ecc_available(void) +{ + return spd_ddr_info.ecc_available; +} + +uint8_t fw_get_used_memory_ch(void) +{ + return spd_ddr_info.ddr_memory_used_ch; +} + +uint32_t fw_get_memory_type_next(void) +{ + return spd_ddr_info.set_memory_type_next; +} + +uint32_t fw_get_address_control_next(void) +{ + return spd_ddr_info.dmc_address_control; +} + +uint32_t fw_get_ddr4_sdram_dq_map_control(uint8_t i) +{ + return spd_ddr_info.dq_map_control[i]; +} + +uint32_t fw_get_ddr4_sdram_total_size(void) +{ + return config_ddr4_sdram_total_size; +} + +uint32_t fw_get_memory_type(void) +{ + return spd_ddr_info.ddr_memory_type; +} + +#define CM3_TO_AP_ADDR(addr) ((addr)-EXTERNAL_DEV_BASE) + +/* 16MB zero clear*/ +static void dma330_zero_clear( + uint32_t inst_start_addr, + uint32_t clear_start_addr) +{ + volatile REG_ST_DMA330_S_t *REG_DMA330_S; + + REG_DMA330_S = (volatile REG_ST_DMA330_S_t *)CONFIG_SOC_DMA330_REG_BASE; + + /** + * Instruction for DMA330 + * DMAMOV CCR SB1 SS8 SP3 SC0 DB16 DS128 DP3 DC1 + * DMAMOV DAR 0x80000000 + * DMALP 256 + * DMALP 256 + * DMASTZ + * DMALPEND + * DMALPEND + * DMAWMB + * DMASEV 0 + * DMAEND + */ + writel(inst_start_addr + 0x000U, 0x430101bcU); + writel(inst_start_addr + 0x004U, 0x02bc02feU); + writel(inst_start_addr + 0x008U, clear_start_addr); + /** + * DMA330 0 clear size setting + * DMALP(1) 256(1), in loop DMAL 256(0) + * 16 * 128bit * 256 * 256 = 16MBytes + */ + writel(inst_start_addr + 0x00cU, 0xff22ff20U); + writel(inst_start_addr + 0x010U, 0x38013c0cU); + writel(inst_start_addr + 0x014U, 0x00341305U); + writel(inst_start_addr + 0x018U, 0xffffff00U); + writel(inst_start_addr + 0x01cU, 0xffffffffU); + + REG_DMA330_S->INTEN = 0xffffffffU; + + while (REG_DMA330_S->DBGSTATUS != 0) { + SYNQUACER_DEV_LOG_INFO("[SYSTEM] Wait DMA330 busy.\n"); + osDelay(10); + } + + REG_DMA330_S->DBGINST[0] = 0xa2U << 16; + REG_DMA330_S->DBGINST[1] = CM3_TO_AP_ADDR(inst_start_addr); + REG_DMA330_S->DBGCMD = 0; + + /* Wait for DMA done */ + while (REG_DMA330_S->INTMIS == 0) + osDelay(1U); + + REG_DMA330_S->INTCLR = 0xffffffffU; +} + +#define REG_DMAB_REG_dma330_boot_manager \ + (CONFIG_SOC_DMAB_WRAPPER_REG + 0x00000010) +#define REG_DMAB_REG_mmu500_wsb_ns_zero_0_s \ + (CONFIG_SOC_DMAB_WRAPPER_REG + 0x00000118) +#define REG_DMAB_REG_mmu500_rsb_ns_zero_0_s \ + (CONFIG_SOC_DMAB_WRAPPER_REG + 0x00000128) +#define REG_DMAB_REG_mmu500_awdomain_zero_s \ + (CONFIG_SOC_DMAB_WRAPPER_REG + 0x00000110) +#define REG_DMAB_REG_mmu500_ardomain_zero_s \ + (CONFIG_SOC_DMAB_WRAPPER_REG + 0x00000120) + +static void dmab_mmu500_init(uint64_t output_addr) +{ + uint32_t i; + uint32_t page_table_top_ap_addr; + uint32_t page_table_top_addr; + uint32_t upper_addr; + uint32_t lower_addr; + MMU500_ContextInfo_t context_info; + MMU500_Type_t *p_mmu_dmab; + p_mmu_dmab = (MMU500_Type_t *)CONFIG_SOC_DMAB_SMMU_REG_BASE; + + page_table_top_addr = TRUSTED_RAM_BASE; + page_table_top_ap_addr = CM3_TO_AP_ADDR(page_table_top_addr); + + /* lv1 Excel(TTBR Descriptor address, Level2 Table address) */ + writel( + page_table_top_addr + 0x00000000 + 0x0, + 3 | (page_table_top_ap_addr + 0x00010000)); + writel(page_table_top_addr + 0x00000000 + 0x4, 0); + + /* Input Address = 0x2e000000 */ + /* lv2 Excel(Level1 Descriptor address, Level3 Table address) */ + writel( + page_table_top_addr + 0x00010008 + 0x0, + 3 | (page_table_top_ap_addr + 0x00020000)); + writel(page_table_top_addr + 0x00010008 + 0x4, 0); + + /* Input Address = 0x80000000 */ + /* lv2 Excel(Level1 Descriptor address, Level3 Table address) */ + writel( + page_table_top_addr + 0x00010020 + 0x0, + 3 | (page_table_top_ap_addr + 0x00030000)); + writel(page_table_top_addr + 0x00010020 + 0x4, 0); + + /* Input Address = 0x2e000000 */ + /* Output Address = 0x2e000000 */ + /* lv3 Excel(Level2 Descriptor address) */ + upper_addr = 0x00000000; + lower_addr = 0x2e000000; + + /* 0x0000 - 0x0001 ( 64KB * 1 = 64KB : 0x00010000 ) */ + for (i = 0; i < 0x0001; i++) { + writel( + page_table_top_addr + 0x00027000 + 0x0 + (i * 0x8), + 3 | (lower_addr) | (1 << 10) | (1 << 7) | (1 << 6) | (0 << 5) | + (0 << 4) | (0 << 3) | (0 << 2)); + + writel(page_table_top_addr + 0x00027000 + 0x4 + (i * 0x8), upper_addr); + lower_addr = (lower_addr + 0x10000); + } + + /* Input Address = 0x80000000 */ + /* Output Address = output_addr */ + /* lv3 Excel(Level2 Descriptor address) */ + /* 0x00000 - 0x02000 ( 64KB * 8192 = 512MB : 0x200000000 */ + for (i = 0; i < 0x02000; i++, output_addr += 0x10000) { + upper_addr = output_addr >> 32; + lower_addr = output_addr; + + writel( + page_table_top_addr + 0x00030000 + 0x0 + (i * 0x8), + 3 | (lower_addr) | (1 << 10) | (0 << 7) | (1 << 6) | (0 << 5) | + (0 << 4) | (0 << 3) | (1 << 2)); + + writel(page_table_top_addr + 0x00030000 + 0x4 + (i * 0x8), upper_addr); + } + + context_info.stream_match_mask = 0x7c00U; + context_info.stream_match_id = 0; + context_info.base_addr = (uint64_t)page_table_top_ap_addr; + + SMMU_s_init( + (MMU500_Type_t *)p_mmu_dmab, + 1, + (const MMU500_ContextInfo_t *)&context_info, + MMU500_GRANULE_64KB); +} + +#define addr_trans(addr_39_20, size, write) (0) + +#define DMA330_ERASE_BLOCK_SIZE UINT32_C(0x1000000) + +static void dma330_wrapper_init(void) +{ + uint32_t value; + + /* Change to Non Secure bit0 : 0=Secure */ + value = readl(REG_DMAB_REG_dma330_boot_manager); + writel(REG_DMAB_REG_dma330_boot_manager, value & 0xFFFFFFFE); + + /* Change to Non Secure bit0 = 0 : mmu500_wsb_ns_zero_0_s */ + value = readl(REG_DMAB_REG_mmu500_wsb_ns_zero_0_s); + writel(REG_DMAB_REG_mmu500_wsb_ns_zero_0_s, value & 0xFFFFFFFE); + + /* Change to Non Secure bit0 = 0 : mmu500_rsb_ns_zero_0_s */ + value = readl(REG_DMAB_REG_mmu500_rsb_ns_zero_0_s); + writel(REG_DMAB_REG_mmu500_rsb_ns_zero_0_s, value & 0xFFFFFFFE); + + /* REG_DMAB_REG_mmu500_awdomain_zero_s &= 0xFFFFFFFC; */ + /* bit1:0 = 2'b00(Non shareable) */ + value = readl(REG_DMAB_REG_mmu500_awdomain_zero_s); + writel(REG_DMAB_REG_mmu500_awdomain_zero_s, value | 0x00000003); + + /* bit1:0 = 2'b11 : System */ + value = readl(REG_DMAB_REG_mmu500_ardomain_zero_s); + writel(REG_DMAB_REG_mmu500_ardomain_zero_s, value | 0x00000003); +} + +#define TEST_SIZE (1024 * 1024) +static void dram_init_for_ecc(void) +{ + uint64_t dst_ddr_addr, dram_size; + uint32_t dma_dst_addr; + + SMMU_s_disable((MMU500_Type_t *)CONFIG_SOC_DMAB_SMMU_REG_BASE, 1); + + (void)addr_trans(0x00800U, TEST_SIZE, true); + (void)addr_trans(0x008ffU, TEST_SIZE, true); + (void)addr_trans(0x00fffU, TEST_SIZE, true); + (void)addr_trans(0x08800U, TEST_SIZE, true); + (void)addr_trans(0x088ffU, TEST_SIZE, true); + (void)addr_trans(0x0ff00U, TEST_SIZE, true); + (void)addr_trans(0x0ffffU, TEST_SIZE, true); + + dram_size = (uint64_t)config_ddr4_sdram_total_size * 1024 * 1024; + + SYNQUACER_DEV_LOG_INFO( + "[DDR] Initializing DRAM for ECC\nNow Initializing["); + + dma330_wrapper_init(); + + /* 0x00_8000_0000 - 0x00_ffff_ffff */ + for (dst_ddr_addr = DRAM_AREA_1_START_ADDR, dma_dst_addr = 0x80000000U; + (dst_ddr_addr < DRAM_AREA_1_END_ADDR) && (dram_size != 0); + dma_dst_addr += DMA330_ERASE_BLOCK_SIZE) { + if ((dst_ddr_addr & 0x3fffffffULL) == 0) + SYNQUACER_DEV_LOG_INFO("+"); + + dma330_zero_clear(0xce000000U, dma_dst_addr); + dst_ddr_addr += DMA330_ERASE_BLOCK_SIZE; + dram_size -= DMA330_ERASE_BLOCK_SIZE; + } + + /* 0x08_8000_0000 - 0x0f_ffff_ffff */ + for (dst_ddr_addr = DRAM_AREA_2_START_ADDR, dma_dst_addr = 0x80000000U; + (dst_ddr_addr < DRAM_AREA_2_END_ADDR) && (dram_size != 0); + dma_dst_addr += DMA330_ERASE_BLOCK_SIZE) { + if ((dst_ddr_addr & 0x3fffffffULL) == 0) + SYNQUACER_DEV_LOG_INFO("-"); + + if ((dst_ddr_addr & 0x1fffffffULL) == 0) { + dmab_mmu500_init(dst_ddr_addr); + dma_dst_addr = 0x80000000U; + } + + dma330_zero_clear(0xce000000U, dma_dst_addr); + dst_ddr_addr += DMA330_ERASE_BLOCK_SIZE; + dram_size -= DMA330_ERASE_BLOCK_SIZE; + } + + /* 0x88_0000_0000 - 0x8f_ffff_ffff */ + for (dst_ddr_addr = DRAM_AREA_3_START_ADDR, dma_dst_addr = 0x80000000U; + (dst_ddr_addr < DRAM_AREA_3_END_ADDR) && (dram_size != 0); + dma_dst_addr += DMA330_ERASE_BLOCK_SIZE) { + if ((dst_ddr_addr & 0x3fffffffULL) == 0) + SYNQUACER_DEV_LOG_INFO("x"); + + if ((dst_ddr_addr & 0x1fffffffULL) == 0) { + dmab_mmu500_init(dst_ddr_addr); + dma_dst_addr = 0x80000000U; + } + + dma330_zero_clear(0xce000000U, dma_dst_addr); + dst_ddr_addr += DMA330_ERASE_BLOCK_SIZE; + dram_size -= DMA330_ERASE_BLOCK_SIZE; + } + + SYNQUACER_DEV_LOG_INFO("]\n[DDR] Finished initializing DRAM for ECC\n"); + + (void)addr_trans(0x00800U, TEST_SIZE, false); + (void)addr_trans(0x008ffU, TEST_SIZE, false); + (void)addr_trans(0x00fffU, TEST_SIZE, false); + (void)addr_trans(0x08800U, TEST_SIZE, false); + (void)addr_trans(0x088ffU, TEST_SIZE, false); + (void)addr_trans(0x0ff00U, TEST_SIZE, false); + (void)addr_trans(0x0ffffU, TEST_SIZE, false); + + SMMU_s_disable((MMU500_Type_t *)CONFIG_SOC_DMAB_SMMU_REG_BASE, 1); + + /* Clear Secure SRAM */ + memset((void *)TRUSTED_RAM_BASE, 0, 256 * 1024); +} + +static void store_spd_to_nssram(void) +{ + uint32_t slot; + uint8_t *dst = (uint8_t *)SPD_STORE_ADDR; + spd_read_err_code_t ret; + + memset(dst, 0, SPD_STORE_AREA_SIZE); + + for (slot = 0; slot < DIMM_SLOT_NUM; slot++) { + ret = read_spd(slot, dst, (SPD_PAGE_SIZE * SPD_NUM_OF_PAGE)); + if (ret != SPD_READ_SLOT_AVAILABLE) { + /* clear invalid data */ + memset(dst, 0, (SPD_PAGE_SIZE * SPD_NUM_OF_PAGE)); + } + dst += (SPD_PAGE_SIZE * SPD_NUM_OF_PAGE); + } +} diff --git a/product/synquacer/module/synquacer_pik_clock/include/mod_synquacer_pik_clock.h b/product/synquacer/module/synquacer_pik_clock/include/mod_synquacer_pik_clock.h new file mode 100644 index 000000000..6083f3ee3 --- /dev/null +++ b/product/synquacer/module/synquacer_pik_clock/include/mod_synquacer_pik_clock.h @@ -0,0 +1,287 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_SYNQUACER_PIK_CLOCK_H +#define MOD_SYNQUACER_PIK_CLOCK_H + +#include +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupSYNQUACER_PIKClock PIK Clock Driver + * + * \details A driver for clock devices that are part of a PIK. + * + * @{ + */ + +/*! + * \brief APIs provided by the driver. + */ +enum mod_pik_clock_api_type { + /*! An implementation of the Clock HAL module's clock driver API */ + MOD_PIK_CLOCK_API_TYPE_CLOCK, + /*! A low-level API for direct control of CSS clocks */ + MOD_PIK_CLOCK_API_TYPE_CSS, + MOD_PIK_CLOCK_API_COUNT, +}; + +/*! + * \brief Sub-types of PIK clock. + */ +enum mod_pik_clock_type { + /*! A clock with a fixed source. Only its divider can be changed. */ + MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + /*! A clock with multiple, selectable sources and at least one divider. */ + MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + /*! + * A clock with multiple, selectable sources, at least one divider, and + * support for modulation. + */ + MOD_PIK_CLOCK_TYPE_CLUSTER, +}; + +/*! + * \brief Divider register types. + */ +enum mod_pik_clock_msclock_divider { + /*! Divider affecting the system PLL clock source. */ + MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + /*! Divider affecting the private or external PLL clock sources. */ + MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT, +}; + +/*! + * \brief Selectable clock sources for multi-source clocks. + */ +enum mod_pik_clock_msclock_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_MSCLOCK_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSREFCLK = 1, + /*! The clock source is set to the system PLL clock */ + MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK = 2, + /*! The clock source is set to a private PLL */ + MOD_PIK_CLOCK_MSCLOCK_SOURCE_PRIVPLLCLK = 4, + /*! Number of valid clock sources */ + MOD_PIK_CLOCK_MSCLOCK_SOURCE_MAX +}; + +/*! + * \brief Selectable clock sources for V8.2 cluster clocks. + */ +enum mod_clusclock_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_SYSREFCLK = 1, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL0 = 2, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL1 = 3, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL2 = 4, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL3 = 5, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL4 = 6, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL5 = 7, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL6 = 8, + /*! The clock source is set to a private cluster PLL */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL7 = 9, + /*! The clock source is set to the system PLL clock */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_SYSPLLCLK = 10, + /*! Number of valid clock sources */ + MOD_PIK_CLOCK_CLUSCLK_SOURCE_MAX +}; + +/*! + * \brief Selectable clock sources for GPU clocks. + */ +enum mod_pik_clock_gpuclock_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_GPUCLK_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_GPUCLK_SOURCE_SYSREFCLK = 1, + /*! The clock source is set to the system PLL clock */ + MOD_PIK_CLOCK_GPUCLK_SOURCE_SYSPLLCLK = 2, + /*! The clock source is set to the dedicated GPU PLL */ + MOD_PIK_CLOCK_GPUCLK_SOURCE_GPUPLLCLK = 4, + /*! Number of valid clock sources */ + MOD_PIK_CLOCK_GPUCLK_SOURCE_MAX +}; + +/*! + * \brief Selectable clock sources for DPU scaler clocks. + */ +enum mod_pik_clock_dpuclock_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_DPUCLK_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_DPUCLK_SOURCE_SYSREFCLK = 1, + /*! The clock source is set to the dedicated display PLL */ + MOD_PIK_CLOCK_DPUCLK_SOURCE_DISPLAYPLLCLK = 2, + /*! The clock source is set to a pixel clock PLL */ + MOD_PIK_CLOCK_DPUCLK_SOURCE_PIXELCLK = 4, + /*! Number of valid clock sources */ + MOD_PIK_CLOCK_DPUCLK_SOURCE_MAX +}; + +/*! + * \brief Selectable clock sources for the DPU AXI clock. + */ +enum mod_pik_clock_aclkdpu_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_ACLKDPU_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_ACLKDPU_SOURCE_SYSREFCLK = 1, + /*! The clock source is set to the dedicated display PLL */ + MOD_PIK_CLOCK_ACLKDPU_SOURCE_DISPLAYPLLCLK = 2, + /*! The clock source is set to the system PLL clock */ + MOD_PIK_CLOCK_ACLKDPU_SOURCE_SYSPLLCLK = 4, + /*! Number of valid clock sources */ + MOD_PIK_CLOCK_ACLKDPU_SOURCE_MAX +}; + +/*! + * \brief Selectable clock sources for the video processor clock. + */ +enum mod_pik_clock_vpuclk_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_VPUCLK_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_VPUCLK_SOURCE_SYSREFCLK = 1, + /*! The clock source is set to the system PLL clock */ + MOD_PIK_CLOCK_VPUCLK_SOURCE_SYSPLLCLK = 2, + /*! The clock source is set to the dedicated video PLL */ + MOD_PIK_CLOCK_VPUCLK_SOURCE_VIDEOPLLCLK = 4, + /*! Number of valid clock sources */ + MOD_PIK_CLOCK_VPUCLK_SOURCE_MAX +}; + +/*! + * \brief Selectable clock sources for interconnect clock. + */ +enum mod_pik_clock_intclk_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_INTCLK_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_INTCLK_SOURCE_SYSREFCLK = 1, + /*! The clock source is set to a private PLL */ + MOD_PIK_CLOCK_INTCLK_SOURCE_INTPLL = 2, +}; + +/*! + * \brief Selectable clock sources for DMC clock. + */ +enum mod_pik_clock_dmcclk_source { + /*! The clock is gated */ + MOD_PIK_CLOCK_DMCCLK_SOURCE_GATED = 0, + /*! The clock source is set to the system reference clock */ + MOD_PIK_CLOCK_DMCCLK_SOURCE_REFCLK = 1, + /*! The clock source is set to a private PLL */ + MOD_PIK_CLOCK_DMCCLK_SOURCE_DDRPLL = 2, +}; + +/*! + * \brief Divider bitfield width. + */ +enum mod_pik_clock_divider_bitfield_width { + /*! PIK clock with 4-bit divider. */ + MOD_PIK_CLOCK_DIVIDER_BITFIELD_WIDTH_4BITS = 4, + /*! PIK clock with 5-bit divider. */ + MOD_PIK_CLOCK_DIVIDER_BITFIELD_WIDTH_5BITS = 5, +}; + +/*! + * \brief PIK clock module configuration. + */ +struct mod_pik_clock_module_config { + /*! The maximum divider value. */ + unsigned int divider_max; +}; + +/*! + * \brief Rate lookup entry. + */ +struct mod_pik_clock_rate { + /*! Rate in Hertz. */ + uint64_t rate; + /*! Clock source used to obtain the rate (multi-source clocks only). */ + uint32_t source; + /*! The divider register to use (multi-source clocks only). */ + enum mod_pik_clock_msclock_divider divider_reg; + /*! Divider used to obtain the rate. */ + uint8_t divider; +}; + +/*! + * \brief Subsystem clock device configuration. + */ +struct mod_pik_clock_dev_config { + /*! The type of the clock device. */ + enum mod_pik_clock_type type; + + /*! + * \brief Indicates whether the clock is part of a CSS clock group (\c true) + * or operating as an independent clock (\c false). + * + * \details The value determines the API that the clock exposes during + * binding. If the clock is part of a group then the \ref + * mod_pik_clock_api_type.MOD_PIK_CLOCK_API_TYPE_CSS API is exposed for + * direct control via the CSS Clock module, otherwise the \ref + * mod_pik_clock_api_type.MOD_PIK_CLOCK_API_TYPE_CLOCK API, defined by + * the Clock HAL, is exposed. + */ + bool is_group_member; + + /*! Pointer to the clock's control register. */ + volatile uint32_t *const control_reg; + + /*! Pointer to the clock's modulator register, if any. */ + volatile uint32_t *const modulator_reg; + + /*! Pointer to the clock's DIV_SYS divider register, if any. */ + volatile uint32_t *const divsys_reg; + + /*! Pointer to the clock's DIV_EXT divider register, if any. */ + volatile uint32_t *const divext_reg; + + /*! Pointer to the clock's rate lookup table. */ + const struct mod_pik_clock_rate *rate_table; + + /*! The number of rates in the rate lookup table. */ + uint32_t rate_count; + + /*! The rate, in Hz, to set during module initialization. */ + uint64_t initial_rate; + + /*! + * If \c true, the driver will not attempt to set a default frequency, or to + * otherwise configure the PLL during the pre-runtime phase. The PLL is + * expected to be initialized later in response to a notification or other + * event. + */ + const bool defer_initialization; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_SYNQUACER_PIK_CLOCK_H */ diff --git a/product/synquacer/module/synquacer_pik_clock/src/Makefile b/product/synquacer/module/synquacer_pik_clock/src/Makefile new file mode 100644 index 000000000..5cf705086 --- /dev/null +++ b/product/synquacer/module/synquacer_pik_clock/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := SynQuacer PIK Clock Driver +BS_LIB_SOURCES := mod_synquacer_pik_clock.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/synquacer_pik_clock/src/mod_synquacer_pik_clock.c b/product/synquacer/module/synquacer_pik_clock/src/mod_synquacer_pik_clock.c new file mode 100644 index 000000000..85cfcacac --- /dev/null +++ b/product/synquacer/module/synquacer_pik_clock/src/mod_synquacer_pik_clock.c @@ -0,0 +1,802 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Masks for single-source clock divider control. + */ +#define SSCLK_CONTROL_CLKDIV UINT32_C(0x000000F0) +#define SSCLK_CONTROL_CRNTCLKDIV UINT32_C(0x0000F000) +#define SSCLK_CONTROL_ENTRY_DLY UINT32_C(0xFF000000) + +/* + * Offsets for single-source clock divider control. + */ +#define SSCLK_CONTROL_CLKDIV_POS 4 +#define SSCLK_CONTROL_CRNTCLKDIV_POS 12 +#define SSCLK_CONTROL_ENTRY_DLY_POS 24 + +/* + * Masks for multi-source clock divider control (both DIV1 and DIV2). + */ +#define MSCLK_DIV_CLKDIV UINT32_C(0x0000001F) +#define MSCLK_DIV_CRNTCLKDIV UINT32_C(0x001F0000) +#define MSCLK_DIV_ENTRY_DLY UINT32_C(0xFF000000) + +/* + * Offsets for multi-source clock divider control (both DIV1 and DIV2). + */ +#define MSCLK_DIV_CLKDIV_POS 0 +#define MSCLK_DIV_CRNTCLKDIV_POS 16 +#define MSCLK_DIV_ENTRY_DLY_POS 24 + +/* + * Masks for multi-source clock source selection. + */ +#define MSCLK_CONTROL_CLKSEL UINT32_C(0x000000FF) +#define MSCLK_CONTROL_CLKSEL_GATED UINT32_C(0x00000000) +#define MSCLK_CONTROL_CLKSEL_SYSREFCLK UINT32_C(0x00000001) +#define MSCLK_CONTROL_CLKSEL_SYSPLLCLK UINT32_C(0x00000002) +#define MSCLK_CONTROL_CLKSEL_PRIVPLLCLK UINT32_C(0x00000004) +#define MSCLK_CONTROL_CRNTCLK UINT32_C(0x0000FF00) + +/* + * Offsets for multi-source clock source selection. + */ +#define MSCLK_CONTROL_CLKSEL_POS 0 +#define MSCLK_CONTROL_CRNTCLK_POS 8 + +/* + * Masks for cluster clock source selection. + * + * Note: The CLKSEL field mask is shared with the multi-source clock subtype, as + * are the masks for the GATED and REFCLK sources. + */ +#define CLUSCLK_CONTROL_CLKSEL_PLL0 UINT32_C(0x00000002) +#define CLUSCLK_CONTROL_CLKSEL_PLL1 UINT32_C(0x00000003) +#define CLUSCLK_CONTROL_CLKSEL_PLL2 UINT32_C(0x00000004) +#define CLUSCLK_CONTROL_CLKSEL_PLL3 UINT32_C(0x00000005) +#define CLUSCLK_CONTROL_CLKSEL_PLL4 UINT32_C(0x00000006) +#define CLUSCLK_CONTROL_CLKSEL_PLL5 UINT32_C(0x00000007) +#define CLUSCLK_CONTROL_CLKSEL_PLL6 UINT32_C(0x00000008) +#define CLUSCLK_CONTROL_CLKSEL_PLL7 UINT32_C(0x00000009) +#define CLUSCLK_CONTROL_CLKSEL_SYSPLLCLK UINT32_C(0x0000000A) + +/* + * Masks for cluster clock modulator control. + */ +#define CLUSCLK_MOD_DENOMINATOR UINT32_C(0x000000FF) +#define CLUSCLK_MOD_NUMERATOR UINT32_C(0x0000FF00) +#define CLUSCLK_MOD_CRNTDENOMINATOR UINT32_C(0x00FF0000) +#define CLUSCLK_MOD_CRNTNUMERATOR UINT32_C(0xFF000000) + +/* + * Offsets for cluster clock modulator control. + */ +#define CLUSCLK_MOD_DENOMINATOR_POS 0 +#define CLUSCLK_MOD_NUMERATOR_POS 8 +#define CLUSCLK_MOD_CRNTDENOMINATOR_POS 16 +#define CLUSCLK_MOD_CRNTNUMERATOR_POS 24 + +/* Device context */ +struct pik_clock_dev_ctx { + bool initialized; + uint64_t current_rate; + uint8_t current_source; + enum mod_clock_state current_state; + const struct mod_pik_clock_dev_config *config; +}; + +/* Module context */ +struct pik_clock_ctx { + struct pik_clock_dev_ctx *dev_ctx_table; + unsigned int dev_count; + unsigned int divider_max; +}; + +static struct pik_clock_ctx module_ctx; + +/* + * Static helper functions + */ + +static int compare_rate_entry(const void *a, const void *b) +{ + struct mod_pik_clock_rate *key = (struct mod_pik_clock_rate *)a; + struct mod_pik_clock_rate *element = (struct mod_pik_clock_rate *)b; + + return (key->rate - element->rate); +} + +static int get_rate_entry( + struct pik_clock_dev_ctx *ctx, + uint64_t target_rate, + struct mod_pik_clock_rate **entry) +{ + struct mod_pik_clock_rate *current_rate_entry; + + if (ctx == NULL) + return FWK_E_PARAM; + if (entry == NULL) + return FWK_E_PARAM; + + /* Perform a binary search to find the entry matching the requested rate */ + current_rate_entry = (struct mod_pik_clock_rate *)bsearch( + &target_rate, + ctx->config->rate_table, + ctx->config->rate_count, + sizeof(struct mod_pik_clock_rate), + compare_rate_entry); + + if (current_rate_entry == NULL) + return FWK_E_PARAM; + + *entry = current_rate_entry; + return FWK_SUCCESS; +} + +static int ssclock_set_div( + struct pik_clock_dev_ctx *ctx, + uint32_t divider, + bool wait_after_set) +{ + uint32_t clkdiv; + + if (divider == 0) + return FWK_E_PARAM; + if (divider > module_ctx.divider_max) + return FWK_E_PARAM; + if (ctx == NULL) + return FWK_E_PARAM; + if (ctx->config->type != MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE) + return FWK_E_PARAM; + + /* The resulting divider is the programmed value plus one */ + clkdiv = divider - 1; + + /* Set */ + *ctx->config->control_reg = + (*ctx->config->control_reg & ~SSCLK_CONTROL_CLKDIV) | + (clkdiv << SSCLK_CONTROL_CLKDIV_POS); + + if (wait_after_set) { + while ((*ctx->config->control_reg & SSCLK_CONTROL_CRNTCLKDIV) != + (clkdiv << SSCLK_CONTROL_CRNTCLKDIV_POS)) + continue; + } + + return FWK_SUCCESS; +} + +static int msclock_set_div( + struct pik_clock_dev_ctx *ctx, + enum mod_pik_clock_msclock_divider divider_type, + uint32_t divider, + bool wait_after_set) +{ + volatile uint32_t *divider_reg; + uint32_t clkdiv; + + if (ctx == NULL) + return FWK_E_PARAM; + if (divider == 0) + return FWK_E_PARAM; + if (divider > module_ctx.divider_max) + return FWK_E_PARAM; + if (ctx->config->type == MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE) + return FWK_E_PARAM; + + /* The resulting divider is the programmed value plus one */ + clkdiv = divider - 1; + + if (divider_type == MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS) + divider_reg = ctx->config->divsys_reg; + else if (divider_type == MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT) + divider_reg = ctx->config->divext_reg; + else + return FWK_E_PARAM; + + /* Set */ + *divider_reg = + (*divider_reg & ~MSCLK_DIV_CLKDIV) | (clkdiv << MSCLK_DIV_CLKDIV_POS); + + if (wait_after_set) { + while ((*divider_reg & MSCLK_DIV_CRNTCLKDIV) != + (clkdiv << MSCLK_DIV_CRNTCLKDIV_POS)) + continue; + } + + return FWK_SUCCESS; +} + +static int msclock_set_source( + struct pik_clock_dev_ctx *ctx, + uint32_t source, + bool wait_after_set) +{ + if (ctx == NULL) + return FWK_E_PARAM; + if (ctx->config->type == MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE) + return FWK_E_PARAM; + + /* Set */ + *ctx->config->control_reg = + (*ctx->config->control_reg & ~MSCLK_CONTROL_CLKSEL) | + (source << MSCLK_CONTROL_CLKSEL_POS); + + if (wait_after_set) { + while ((*ctx->config->control_reg & MSCLK_CONTROL_CRNTCLK) != + ((uint32_t)(source << MSCLK_CONTROL_CRNTCLK_POS))) + continue; + } + + return FWK_SUCCESS; +} + +static int cluster_set_modulator( + struct pik_clock_dev_ctx *ctx, + uint32_t numerator, + uint32_t denominator, + bool wait_after_set) +{ + uint32_t modulator_setting; + + if (ctx == NULL) + return FWK_E_PARAM; + if (ctx->config->type != MOD_PIK_CLOCK_TYPE_CLUSTER) + return FWK_E_PARAM; + if (ctx->config->modulator_reg == NULL) + return FWK_E_PARAM; + if (denominator > 255) + return FWK_E_PARAM; + if (denominator == 0) + return FWK_E_PARAM; + if (numerator > 255) + return FWK_E_PARAM; + + modulator_setting = (denominator << CLUSCLK_MOD_DENOMINATOR_POS) | + (numerator << CLUSCLK_MOD_NUMERATOR_POS); + + *ctx->config->modulator_reg = + ((*ctx->config->modulator_reg & + ~(CLUSCLK_MOD_DENOMINATOR | CLUSCLK_MOD_NUMERATOR)) | + modulator_setting); + + if (wait_after_set) { + while ((*ctx->config->modulator_reg & CLUSCLK_MOD_CRNTNUMERATOR) != + (numerator << CLUSCLK_MOD_CRNTNUMERATOR_POS)) + continue; + + while ((*ctx->config->modulator_reg & CLUSCLK_MOD_CRNTDENOMINATOR) != + (denominator << CLUSCLK_MOD_CRNTDENOMINATOR_POS)) + continue; + } + + return FWK_SUCCESS; +} + +static int do_pik_clock_set_rate( + fwk_id_t dev_id, + uint64_t rate, + enum mod_clock_round_mode round_mode) +{ + int status; + struct pik_clock_dev_ctx *ctx; + struct mod_pik_clock_rate *rate_entry; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + /* Look up the divider and source settings */ + status = get_rate_entry(ctx, rate, &rate_entry); + if (status != FWK_SUCCESS) + return status; + + switch (ctx->config->type) { + case MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE: + status = ssclock_set_div(ctx, rate_entry->divider, false); + if (status != FWK_SUCCESS) + goto exit; + break; + case MOD_PIK_CLOCK_TYPE_CLUSTER: + /* Modulator feature not currently used */ + cluster_set_modulator(ctx, 1, 1, false); + /* Intentional fall-through */ + case MOD_PIK_CLOCK_TYPE_MULTI_SOURCE: + if (ctx->current_source == MOD_PIK_CLOCK_MSCLOCK_SOURCE_GATED) + /* Leave the new rate to be applied when the clock is (re)started */ + goto exit; + + status = msclock_set_div( + ctx, rate_entry->divider_reg, rate_entry->divider, false); + if (status != FWK_SUCCESS) + goto exit; + + status = msclock_set_source(ctx, rate_entry->source, false); + if (status != FWK_SUCCESS) + goto exit; + + ctx->current_source = rate_entry->source; + break; + default: + return FWK_E_SUPPORT; + } + +exit: + if (status == FWK_SUCCESS) + ctx->current_rate = rate; + return status; +} + +/* + * Clock driver API functions + */ + +static int pik_clock_set_rate( + fwk_id_t dev_id, + uint64_t rate, + enum mod_clock_round_mode round_mode) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + if (!ctx->initialized) + return FWK_E_INIT; + + if (ctx->current_state == MOD_CLOCK_STATE_STOPPED) + return FWK_E_PWRSTATE; + + return do_pik_clock_set_rate(dev_id, rate, round_mode); +} + +static int pik_clock_get_rate(fwk_id_t dev_id, uint64_t *rate) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + if (rate == NULL) + return FWK_E_PARAM; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + if (ctx->config->type == MOD_PIK_CLOCK_TYPE_MULTI_SOURCE && + ctx->current_source == MOD_PIK_CLOCK_MSCLOCK_SOURCE_GATED) + /* Indicate that the clock is not running */ + *rate = 0; + else + *rate = ctx->current_rate; + + return FWK_SUCCESS; +} + +static int pik_clock_get_rate_from_index( + fwk_id_t dev_id, + unsigned int rate_index, + uint64_t *rate) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + if (rate == NULL) + return FWK_E_PARAM; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + if (rate_index >= ctx->config->rate_count) + return FWK_E_PARAM; + + *rate = ctx->config->rate_table[rate_index].rate; + return FWK_SUCCESS; +} + +static int pik_clock_set_state( + fwk_id_t dev_id, + enum mod_clock_state target_state) +{ + int status; + struct pik_clock_dev_ctx *ctx; + struct mod_pik_clock_rate *rate_entry; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + if (ctx->config->type == MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE) + /* Cannot gate single-source clocks */ + return FWK_E_SUPPORT; + + if (!ctx->initialized) + return FWK_E_INIT; + + if (ctx->current_state == MOD_CLOCK_STATE_STOPPED) + /* + * This state from the device context relates only to the clock state + * that is derived from its parent power domain. + */ + return FWK_E_PWRSTATE; + + if (target_state == MOD_CLOCK_STATE_STOPPED) { + /* The clock is powered and will be gated. */ + status = + msclock_set_source(ctx, MOD_PIK_CLOCK_MSCLOCK_SOURCE_GATED, false); + if (status == FWK_SUCCESS) + ctx->current_source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_GATED; + + return status; + } else { + /* Look up the divider and source settings */ + status = get_rate_entry(ctx, ctx->current_rate, &rate_entry); + if (status != FWK_SUCCESS) + return status; + + status = msclock_set_source(ctx, rate_entry->source, false); + if (status == FWK_SUCCESS) + ctx->current_source = rate_entry->source; + + return status; + } +} + +static int pik_clock_get_state(fwk_id_t dev_id, enum mod_clock_state *state) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + if (ctx->config->type == MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE) { + /* + * Single-source clocks cannot be gated so their running state will be + * derived purely from the state of their parent power domain, if any. + */ + *state = ctx->current_state; + return FWK_SUCCESS; + } + + /* + * Multi-source clocks may be stopped due to gating as well as the state of + * their parent power domain. + */ + if (ctx->current_source == MOD_PIK_CLOCK_MSCLOCK_SOURCE_GATED) + *state = MOD_CLOCK_STATE_STOPPED; + else + *state = ctx->current_state; + + return FWK_SUCCESS; +} + +static int pik_clock_get_range(fwk_id_t dev_id, struct mod_clock_range *range) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + if (range == NULL) + return FWK_E_PARAM; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + range->rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE; + range->min = ctx->config->rate_table[0].rate; + range->max = ctx->config->rate_table[ctx->config->rate_count - 1].rate; + range->rate_count = ctx->config->rate_count; + + return FWK_SUCCESS; +} + +static int pik_clock_power_state_change(fwk_id_t dev_id, unsigned int state) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + if (ctx->config->is_group_member) + return FWK_E_ACCESS; + + if (state == MOD_PD_STATE_ON) { + if (ctx->initialized) + /* Restore the previous rate */ + return do_pik_clock_set_rate( + dev_id, ctx->current_rate, MOD_CLOCK_ROUND_MODE_NONE); + else { + /* Perform deferred initialization and set the initial rate */ + ctx->current_state = MOD_CLOCK_STATE_RUNNING; + ctx->initialized = true; + return do_pik_clock_set_rate( + dev_id, ctx->config->initial_rate, MOD_CLOCK_ROUND_MODE_NONE); + } + } else + ctx->current_state = MOD_CLOCK_STATE_STOPPED; + + return FWK_SUCCESS; +} + +static const struct mod_clock_drv_api api_clock = { + .set_rate = pik_clock_set_rate, + .get_rate = pik_clock_get_rate, + .get_rate_from_index = pik_clock_get_rate_from_index, + .set_state = pik_clock_set_state, + .get_state = pik_clock_get_state, + .get_range = pik_clock_get_range, + .process_power_transition = pik_clock_power_state_change, +}; + +/* + * Direct driver API functions + */ + +#if BUILD_HAS_MOD_CSS_CLOCK +static int pik_clock_direct_set_div( + fwk_id_t clock_id, + uint32_t divider_type, + uint32_t divider) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(clock_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(clock_id); + assert(ctx->config->is_group_member); + + if (ctx->current_state == MOD_CLOCK_STATE_STOPPED) + return FWK_E_PWRSTATE; + + switch (ctx->config->type) { + case MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE: + status = ssclock_set_div(ctx, divider, false); + break; + case MOD_PIK_CLOCK_TYPE_CLUSTER: + case MOD_PIK_CLOCK_TYPE_MULTI_SOURCE: + status = msclock_set_div( + ctx, + (enum mod_pik_clock_msclock_divider)divider_type, + divider, + false); + break; + default: + return FWK_E_SUPPORT; + } + + return status; +} + +static int pik_clock_direct_set_source(fwk_id_t clock_id, uint8_t source) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(clock_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(clock_id); + assert(ctx->config->is_group_member); + + if (ctx->current_state == MOD_CLOCK_STATE_STOPPED) + return FWK_E_PWRSTATE; + + return msclock_set_source(ctx, source, false); +} + +static int pik_clock_direct_set_mod( + fwk_id_t clock_id, + uint32_t numerator, + uint32_t denominator) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(clock_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(clock_id); + assert(ctx->config->is_group_member); + + if (ctx->current_state == MOD_CLOCK_STATE_STOPPED) + return FWK_E_PWRSTATE; + + return cluster_set_modulator(ctx, numerator, denominator, false); +} + +static int pik_clock_direct_power_state_change( + fwk_id_t dev_id, + unsigned int state) +{ + int status; + struct pik_clock_dev_ctx *ctx; + + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + if (!ctx->config->is_group_member) + return FWK_E_ACCESS; + + if (state == MOD_PD_STATE_ON) { + if (!ctx->initialized) + /* Perform delayed initialization */ + ctx->initialized = true; + ctx->current_state = MOD_CLOCK_STATE_RUNNING; + } else + ctx->current_state = MOD_CLOCK_STATE_STOPPED; + + return FWK_SUCCESS; +} + +static const struct mod_css_clock_direct_api api_direct = { + .set_div = pik_clock_direct_set_div, + .set_source = pik_clock_direct_set_source, + .set_mod = pik_clock_direct_set_mod, + .process_power_transition = pik_clock_direct_power_state_change, +}; +#endif + +/* + * Framework handler functions + */ + +static int pik_clock_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + struct mod_pik_clock_module_config *config = + (struct mod_pik_clock_module_config *)data; + module_ctx.dev_count = element_count; + + if (element_count == 0) + return FWK_SUCCESS; + + module_ctx.divider_max = + ((config == NULL) ? (1 << MOD_PIK_CLOCK_DIVIDER_BITFIELD_WIDTH_5BITS) : + config->divider_max); + + module_ctx.dev_ctx_table = + fwk_mm_calloc(element_count, sizeof(struct pik_clock_dev_ctx)); + if (module_ctx.dev_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int pik_clock_element_init( + fwk_id_t element_id, + unsigned int sub_element_count, + const void *data) +{ + unsigned int i = 0; + uint64_t current_rate; + uint64_t last_rate = 0; + struct pik_clock_dev_ctx *ctx; + const struct mod_pik_clock_dev_config *dev_config = data; + + if (!fwk_module_is_valid_element_id(element_id)) + return FWK_E_PARAM; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id); + + /* Verify that the rate entries in the device's lookup table are ordered */ + while (i < dev_config->rate_count) { + current_rate = dev_config->rate_table[i].rate; + + /* The rate entries must be in ascending order */ + if (current_rate < last_rate) + return FWK_E_DATA; + + last_rate = current_rate; + i++; + } + + ctx->config = dev_config; + + /* Begin with an invalid source */ + ctx->current_source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_MAX; + + if (ctx->config->defer_initialization) + return FWK_SUCCESS; + + ctx->current_state = MOD_CLOCK_STATE_RUNNING; + ctx->initialized = true; + + /* + * Clock devices that are members of a clock group must skip initialization + * at this time since they will be set to a specific rate by the CSS Clock + * driver during the start stage or in response to a notification. + */ + if (ctx->config->is_group_member) + return FWK_SUCCESS; + + return do_pik_clock_set_rate( + element_id, dev_config->initial_rate, MOD_CLOCK_ROUND_MODE_NONE); +} + +static int pik_clock_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + struct pik_clock_dev_ctx *ctx; + + /* Only elements can be bound to as the API depends on the element type */ + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT)) + return FWK_E_ACCESS; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(target_id); + + if (ctx->config->is_group_member) { +#if BUILD_HAS_MOD_CSS_CLOCK + /* Only the CSS Clock module can bind to group members. */ + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_CSS_CLOCK) { + *api = &api_direct; + return FWK_SUCCESS; + } else + return FWK_E_ACCESS; +#else + /* The CSS Clock module is required to support group members. */ + return FWK_E_SUPPORT; +#endif + } else + *api = &api_clock; + + return FWK_SUCCESS; +} + +const struct fwk_module module_synquacer_pik_clock = { + .name = "SynQuacer PIK Clock Driver", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = MOD_PIK_CLOCK_API_COUNT, + .event_count = 0, + .init = pik_clock_init, + .element_init = pik_clock_element_init, + .process_bind_request = pik_clock_process_bind_request, +}; diff --git a/product/synquacer/module/synquacer_rom/include/mod_synquacer_rom.h b/product/synquacer/module/synquacer_rom/include/mod_synquacer_rom.h new file mode 100644 index 000000000..8f8a41615 --- /dev/null +++ b/product/synquacer/module/synquacer_rom/include/mod_synquacer_rom.h @@ -0,0 +1,50 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_SYNQUACER_ROM_H +#define MOD_SYNQUACER_ROM_H + +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupSYNQUACER_ROM ROM Support + * + * \brief SynQuacer ROM support. + * + * \details This module implements a service for the ROM firmware + * + * @{ + */ + +/*! + * \brief Module configuration data. + */ +struct synquacer_rom_config { + /*! Base address of the RAM firmware image */ + const uintptr_t ramfw_base; + + /*! Base address of the NOR flash memory */ + const uintptr_t nor_base; + + /*! The RAM size to load */ + const unsigned int load_ram_size; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_SYNQUACER_ROM_H */ diff --git a/product/synquacer/module/synquacer_rom/src/Makefile b/product/synquacer/module/synquacer_rom/src/Makefile new file mode 100644 index 000000000..7d7534fa0 --- /dev/null +++ b/product/synquacer/module/synquacer_rom/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := SynQuacer ROM +BS_LIB_SOURCES := mod_synquacer_rom.c synquacer_init.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/synquacer_rom/src/mod_synquacer_rom.c b/product/synquacer/module/synquacer_rom/src/mod_synquacer_rom.c new file mode 100644 index 000000000..462ee3f67 --- /dev/null +++ b/product/synquacer/module/synquacer_rom/src/mod_synquacer_rom.c @@ -0,0 +1,125 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void synquacer_system_init(void); + +static const struct synquacer_rom_config *rom_config; +static struct mod_log_api *log_api; + +enum rom_event { ROM_EVENT_RUN, ROM_EVENT_COUNT }; + +/* + * This function assumes that the RAM firmware image is located at the beginning + * of the SCP SRAM. The reset handler will be at offset 0x4 (the second entry of + * the vector table). + */ +static void jump_to_ramfw(void) +{ + uintptr_t const *reset_base = (uintptr_t *)(rom_config->ramfw_base + 0x4); + void (*ramfw_reset_handler)(void); + + /* + * Disable interrupts for the duration of the ROM firmware to RAM firmware + * transition. + */ + fwk_interrupt_global_disable(); + + ramfw_reset_handler = (void (*)(void))(*reset_base); + + /* + * Execute the RAM firmware's reset handler to pass control from ROM + * firmware to the RAM firmware. + */ + ramfw_reset_handler(); +} + +/* + * Framework API + */ +static int synquacer_rom_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + rom_config = data; + + synquacer_system_init(); + + return FWK_SUCCESS; +} + +static int synquacer_rom_bind(fwk_id_t id, unsigned int round) +{ + int status; + + /* Use second round only (round numbering is zero-indexed) */ + if (round == 1) { + /* Bind to the log component */ + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_LOG), + FWK_ID_API(FWK_MODULE_IDX_LOG, 0), + &log_api); + + if (status != FWK_SUCCESS) + return FWK_E_PANIC; + } + + return FWK_SUCCESS; +} + +static int synquacer_rom_start(fwk_id_t id) +{ + int status; + struct fwk_event event = { + .source_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_ROM), + .target_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_ROM), + .id = FWK_ID_EVENT(FWK_MODULE_IDX_SYNQUACER_ROM, ROM_EVENT_RUN), + }; + + status = fwk_thread_put_event(&event); + + return status; +} + +static int synquacer_rom_process_event( + const struct fwk_event *event, + struct fwk_event *resp) +{ + log_api->log(MOD_LOG_GROUP_INFO, "[scp_romfw] Launch scp_ramfw\n"); + + if (rom_config->load_ram_size != 0) { + memcpy( + (void *)rom_config->ramfw_base, + (uint8_t *)rom_config->nor_base, + rom_config->load_ram_size); + } + + jump_to_ramfw(); + + return FWK_SUCCESS; +} + +/* Module descriptor */ +const struct fwk_module module_synquacer_rom = { + .name = "synquacer_ROM", + .type = FWK_MODULE_TYPE_SERVICE, + .event_count = ROM_EVENT_COUNT, + .init = synquacer_rom_init, + .bind = synquacer_rom_bind, + .start = synquacer_rom_start, + .process_event = synquacer_rom_process_event, +}; diff --git a/product/synquacer/module/synquacer_rom/src/synquacer_init.c b/product/synquacer/module/synquacer_rom/src/synquacer_init.c new file mode 100644 index 000000000..3130b3e57 --- /dev/null +++ b/product/synquacer/module/synquacer_rom/src/synquacer_init.c @@ -0,0 +1,228 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +void fw_clk_init(void); +void fw_sysoc_init(void); +void fw_lpcm_init(void); + +#define REG_ADDR_RSTSTA (0) +#define REG_ADDR_RSTSET (0x4U) +#define REG_ADDR_RSTCLR (0x8U) + +#define LPCM_RESET_CTRL_ADDR UINT32_C(0x400) +#define LPCM_RESET_CTRL_OFFSET UINT32_C(0x8) + +#define LPCM_RESET_STA_ADDR 0x404U +#define LPCM_RESET_CLR 0x1U + +#define STATUS_WAIT true +#define STATUS_NO_WAIT false + +#define REG_ADDR_RSTSTA (0) +#define REG_ADDR_RSTSET (0x4U) +#define REG_ADDR_RSTCLR (0x8U) + +#define LPCM_RESET_CTRL_ADDR UINT32_C(0x400) +#define LPCM_RESET_CTRL_OFFSET UINT32_C(0x8) + +#define LPCM_RESET_STA_ADDR 0x404U +#define LPCM_RESET_CLR 0x1U + +static void fw_clock_pll_init(void) +{ + /* 1 bit for each cluster */ + const uint32_t pll_mask = 0x00000FFF; + + while ((PIK_SCP->PLL_STATUS[1] & pll_mask) != pll_mask || + (PIK_SCP->PLL_STATUS[9] & pll_mask) != pll_mask) + continue; +} + +static void pll_init(void) +{ + uint32_t pll_mask = PLL_STATUS_0_REFCLK | PLL_STATUS_0_SYSPLLLOCK; + /* Wait for PLL to lock */ + while ((PIK_SCP->PLL_STATUS[0] & pll_mask) != pll_mask) + continue; +} + +void fw_sysoc_init(void) +{ + uint32_t i, value; + + const uint32_t init_sysoc_addr_infos[] = { + CONFIG_SOC_REG_ADDR_SYSOC_DMA_TOP, + CONFIG_SOC_REG_ADDR_SYSOC_PCIE_TOP, + CONFIG_SOC_REG_ADDR_SYSOC_DDR_TOP + }; + + const uint32_t init_sysoc_reset_infos[] = { UINT32_C(0x3), /* DMA */ + UINT32_C(0x3), /* PCIE */ + UINT32_C(0xff), + /* DDR */ }; + + for (i = 0; i < FWK_ARRAY_SIZE(init_sysoc_addr_infos); i++) { + value = readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA); + if (value == 0) + continue; /* reset all not active */ + + /* reset set only active bit */ + writel( + init_sysoc_addr_infos[i] + REG_ADDR_RSTCLR, + (init_sysoc_reset_infos[i] & value)); + + while ((readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA) & + init_sysoc_reset_infos[i]) != 0) + ; + } +} + +void fw_lpcm_init(void) +{ + uint32_t i, j; + + const uint32_t lpcm_reset_addr_infos[] = { + CONFIG_SOC_LPCM_PCIE_TOP_ADDR + LPCM_RESET_CTRL_ADDR, + CONFIG_SOC_LPCM_DMAB_TOP_ADDR + LPCM_RESET_CTRL_ADDR + }; + + const uint32_t lpcm_reset_flag[] = { CONFIG_SOC_LPCM_PCIE_RESET_FLAG, + CONFIG_SOC_LPCM_DMAB_RESET_FLAG }; + + for (i = 0; i < FWK_ARRAY_SIZE(lpcm_reset_addr_infos); i++) { + for (j = 0; j < (sizeof(uint32_t) * 8); j++) { + if ((lpcm_reset_flag[i] & (0x1U << j)) == 0) + continue; /* no reset signal */ + + /* reset clr set lpcm reset_ctrl*/ + writel( + lpcm_reset_addr_infos[i] + (LPCM_RESET_CTRL_OFFSET * j), + LPCM_RESET_CLR); + } + } +} + +static void set_clkforce_set(void) +{ + /* 0x0A04 : CLKFORCE_SET HW BUG WORKAROUND bit8 bit6 bit 2 */ + /* 0 = clock gated. 1 = Clock is forced to always operate. */ + /* bit8 : SYSPLLCLKDBGFORCE*/ + /* bit7 : DMCCLKFORCE */ + /* bit6 : SYSPERCLKFORCE */ + /* bit5 : PCLKSCPFORCE */ + /* bit2 : CCNCLKFORCE */ + /* bit0 : PPUCLKFORCE */ + PIK_SYSTEM->CLKFORCE_SET = 0x00000144U; +} + +void fw_clear_clkforce(uint32_t value) +{ + /* + * Writing 1 to a bit enables dynamic hardware clock-gating. + * Writing 0 to a bit is ignored. + * bit8 : SYSPLLCLKDBGFORCE + * bit7 : DMCCLKFORCE + * bit6 : SYSPERCLKFORCE + * bit5 : PCLKSCPFORCE + * bit2 : CCNCLKFORCE + * bit0 : PPUCLKFORCE + */ + PIK_SYSTEM->CLKFORCE_CLR = value; +} + +uint32_t fw_get_clkforce_status(void) +{ + return PIK_SYSTEM->CLKFORCE_STATUS; +} + +static struct ppu_v0_reg *const ppu_reg_p[] = { + (struct ppu_v0_reg *)0x50041000, /* SYS-LOGIC-PPU0 */ + (struct ppu_v0_reg *)0x50042000, /* SYS-L3RAM0-PPU0 */ + (struct ppu_v0_reg *)0x50043000, /* SYS-L3RAM1-PPU0 */ + (struct ppu_v0_reg *)0x50044000, /* SYS-SFRAM-PPU0 */ + (struct ppu_v0_reg *)0x50045000, /* SYS-SRAM-PPU0 */ + (struct ppu_v0_reg *)0x50021000, /* SYS-DEBUG-PPU0 */ +}; + +static void peri_ppu_on(void) +{ + uint32_t i; + + for (i = 0; i < FWK_ARRAY_SIZE(ppu_reg_p); i++) + ppu_reg_p[i]->POWER_POLICY = PPU_V0_MODE_ON; +} + +static void peri_ppu_wait(void) +{ + uint32_t i; + + for (i = 0; i < FWK_ARRAY_SIZE(ppu_reg_p); i++) { + while ((ppu_reg_p[i]->POWER_STATUS & PPU_V0_PSR_POWSTAT) != + PPU_V0_MODE_ON) + ; + } +} + +void fw_clk_init(void) +{ + pll_init(); + set_clkforce_set(); + + peri_ppu_on(); + + fw_clock_pll_init(); + + peri_ppu_wait(); +} + +static void fw_sram_sysoc_init(void) +{ + uint32_t i, value; + + const uint32_t init_sysoc_addr_infos[] = CONFIG_SOC_INIT_SYSOC_ADDR_INFOS; + const uint32_t init_sysoc_reset_infos[] = CONFIG_SOC_INIT_SYSOC_RESET_INFOS; + + for (i = 0; i < FWK_ARRAY_SIZE(init_sysoc_addr_infos); i++) { + value = readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA); + if (value == 0) + continue; /* reset all not active */ + + /* reset set only active bit */ + writel( + (init_sysoc_addr_infos[i] + REG_ADDR_RSTCLR), + (init_sysoc_reset_infos[i] & value)); + + while ((readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA) & + init_sysoc_reset_infos[i]) != 0) + ; + } +} + +static void fw_sram_lpcm_init(void) +{ + /* reset clr set lpcm reset_ctrl*/ + writel(CONFIG_SOC_LPCM_SCB_TOP_ADDR + LPCM_RESET_CTRL_ADDR, LPCM_RESET_CLR); +} + +void synquacer_system_init(void) +{ + fw_sram_sysoc_init(); + + fw_sram_lpcm_init(); + + fw_clk_init(); + + fw_sysoc_init(); + + fw_lpcm_init(); +} diff --git a/product/synquacer/module/synquacer_system/include/boot_ctl.h b/product/synquacer/module/synquacer_system/include/boot_ctl.h new file mode 100644 index 000000000..80305b293 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/boot_ctl.h @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_CTL_H +#define BOOT_CTL_H + +#include + +uint8_t get_dsw3_status(uint8_t bit_mask); +void set_memory_remap(uint32_t value); + +#endif /* BOOT_CTL_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/crg11.h b/product/synquacer/module/synquacer_system/include/internal/crg11.h new file mode 100644 index 000000000..4327db673 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/crg11.h @@ -0,0 +1,36 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CRG11_H +#define CRG11_H + +#include +#include +#include +#include + +/* CRG11 is only used to reboot system */ +#define CRG11_CRSWR(crg11_top_reg_addr) (crg11_top_reg_addr + 0x0024U) + +#define INVALID_CRG11_ID (-1) +#define INVALID_LCRG (-1) + +typedef struct crg11_state_s { + unsigned int ps_mode : 4; + unsigned int fb_mode : 6; + uint32_t src_frequency; + int8_t lcrg_numerator; + uint32_t reg_addr; + uint16_t clock_domain_div_modifiable_mask; + uint8_t clock_domain_div[16]; + uint8_t port_gate[16]; + uint8_t gate_enable[16]; + uint8_t ref_count; + unsigned int ap_change_allowed_flag : 1; +} crg11_state_t; + +#endif /* CRG11_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/gpio.h b/product/synquacer/module/synquacer_system/include/internal/gpio.h new file mode 100644 index 000000000..96f3bc9fe --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/gpio.h @@ -0,0 +1,26 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPIO_H +#define GPIO_H + +#include +#include + +#define PRMUX_MAX_IDX CONFIG_SOC_PRMUX_MAX_IDX +#define GPIO_MAX_IDX 3 + +void fw_gpio_init(void); +void prmux_set_pingrp(void *prmux_base_addr, uint32_t idx, uint32_t pingrp); +void gpio_set_data(void *gpio_base_addr, uint32_t idx, uint8_t value); +uint8_t gpio_get_data(void *gpio_base_addr, uint32_t idx); +void gpio_set_direction(void *gpio_base_addr, uint32_t idx, uint8_t value); +uint8_t gpio_get_direction(void *gpio_base_addr, uint32_t idx); +void gpio_set_function(void *gpio_base_addr, uint32_t idx, uint8_t value); +uint8_t gpio_get_function(void *gpio_base_addr, uint32_t idx); + +#endif /* GPIO_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/nic400.h b/product/synquacer/module/synquacer_system/include/internal/nic400.h new file mode 100644 index 000000000..8adc7216d --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/nic400.h @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NIC400_H +#define NIC400_H + +#define END_OF_NIC_LIST 0xffU +#define NIC_SETUP_SKIP 0 + +void nic_secure_access_ctrl_init(void); + +#endif /* NIC_400_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/pmu.h b/product/synquacer/module/synquacer_system/include/internal/pmu.h new file mode 100644 index 000000000..f40b1dab7 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/pmu.h @@ -0,0 +1,34 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_H +#define PMU_H + +#include + +/** interrupt factor bits */ +#define PMU_INT_ST_PDIE (1U << 6) +#define PMU_INT_ST_PDNIE (1U << 5) +#define PMU_INT_ST_PONIE (1U << 4) +#define PMU_INT_ST_WUIE1 (1U << 1) +#define PMU_INT_ST_WUIE0 (1U << 0) + +void pmu_on(uint32_t pd_on_flag); +void pmu_off(uint32_t pd_off_flag); +uint32_t pmu_read_pd_power_status(void); +void pmu_write_power_on_cycle(uint8_t pd_no, uint8_t value); +uint8_t pmu_read_power_on_cycle(uint8_t pd_no); +void pmu_enable_int(uint32_t enable_bit); +void pmu_disable_int(uint32_t disable_bit); +uint8_t pmu_read_int_satus(void); +void pmu_clr_int_satus(uint32_t clr_bit); +void pmu_on_wakeup(uint8_t pd_no); +void pmu_write_power_on_priority(uint8_t pd_no, uint8_t value); +void pmu_write_pwr_cyc_sel(uint32_t value); +uint32_t pmu_read_pwr_cyc_sel(void); + +#endif /* PMU_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/reg_PPU.h b/product/synquacer/module/synquacer_system/include/internal/reg_PPU.h new file mode 100644 index 000000000..9e5822071 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/reg_PPU.h @@ -0,0 +1,69 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REG_PPU_H +#define REG_PPU_H + +#define PPU_BASE_AP 0x54120000 +#define PPU_BASE_SCP 0x48120000 + +#define PPU_BASE PPU_BASE_SCP + +#define PPU_PPR_OFFSET 0x000 +#define PPU_PSR_OFFSET 0x004 +#define PPU_PCR_OFFSET 0x00C + +#define PPU0_BASE (PPU_BASE + 0x000) +#define PPU1_BASE (PPU_BASE + 0x020) +#define PPU2_BASE (PPU_BASE + 0x040) +#define PPU3_BASE (PPU_BASE + 0x060) +#define PPU4_BASE (PPU_BASE + 0x080) +#define PPU5_BASE (PPU_BASE + 0x0A0) +#define PPU6_BASE (PPU_BASE + 0x0C0) +#define PPU7_BASE (PPU_BASE + 0x0E0) +#define PPU8_BASE (PPU_BASE + 0x100) + +#define PPU0_PPR (PPU0_BASE + PPU_PPR_OFFSET) +#define PPU0_PSR (PPU0_BASE + PPU_PSR_OFFSET) +#define PPU0_PCR (PPU0_BASE + PPU_PCR_OFFSET) +#define PPU1_PPR (PPU1_BASE + PPU_PPR_OFFSET) +#define PPU1_PSR (PPU1_BASE + PPU_PSR_OFFSET) +#define PPU1_PCR (PPU1_BASE + PPU_PCR_OFFSET) +#define PPU2_PPR (PPU2_BASE + PPU_PPR_OFFSET) +#define PPU2_PSR (PPU2_BASE + PPU_PSR_OFFSET) +#define PPU2_PCR (PPU2_BASE + PPU_PCR_OFFSET) +#define PPU3_PPR (PPU3_BASE + PPU_PPR_OFFSET) +#define PPU3_PSR (PPU3_BASE + PPU_PSR_OFFSET) +#define PPU3_PCR (PPU3_BASE + PPU_PCR_OFFSET) +#define PPU4_PPR (PPU4_BASE + PPU_PPR_OFFSET) +#define PPU4_PSR (PPU4_BASE + PPU_PSR_OFFSET) +#define PPU4_PCR (PPU4_BASE + PPU_PCR_OFFSET) +#define PPU5_PPR (PPU5_BASE + PPU_PPR_OFFSET) +#define PPU5_PSR (PPU5_BASE + PPU_PSR_OFFSET) +#define PPU5_PCR (PPU5_BASE + PPU_PCR_OFFSET) +#define PPU6_PPR (PPU6_BASE + PPU_PPR_OFFSET) +#define PPU6_PSR (PPU6_BASE + PPU_PSR_OFFSET) +#define PPU6_PCR (PPU6_BASE + PPU_PCR_OFFSET) +#define PPU7_PPR (PPU7_BASE + PPU_PPR_OFFSET) +#define PPU7_PSR (PPU7_BASE + PPU_PSR_OFFSET) +#define PPU7_PCR (PPU7_BASE + PPU_PCR_OFFSET) +#define PPU8_PPR (PPU8_BASE + PPU_PPR_OFFSET) +#define PPU8_PSR (PPU8_BASE + PPU_PSR_OFFSET) +#define PPU8_PCR (PPU8_BASE + PPU_PCR_OFFSET) +#define PPU_HWCACTIVE_SR (PPU_BASE + 0x800) +#define PPU_WFI_WFE_SR (PPU_BASE + 0x804) +#define PPU_PID_4 (PPU_BASE + 0xFD0) +#define PPU_PID_0 (PPU_BASE + 0xFE0) +#define PPU_PID_1 (PPU_BASE + 0xFE4) +#define PPU_PID_2 (PPU_BASE + 0xFE8) +#define PPU_PID_3 (PPU_BASE + 0xFEC) +#define PPU_COMP_ID0 (PPU_BASE + 0xFF0) +#define PPU_COMP_ID1 (PPU_BASE + 0xFF4) +#define PPU_COMP_ID2 (PPU_BASE + 0xFF8) +#define PPU_COMP_ID3 (PPU_BASE + 0xFFC) + +#endif /* REG_PPU_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/reset.h b/product/synquacer/module/synquacer_system/include/internal/reset.h new file mode 100644 index 000000000..627347b20 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/reset.h @@ -0,0 +1,113 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RESET_H +#define RESET_H + +typedef enum { RST_TYPE_ALL = 0, RST_TYPE_WO_BUS, RST_TYPE_BUS } RST_TYPE_t; + +typedef enum { + RST_PCIE_TOP = 0, + RST_PCIE0, + RST_PCIE1, + RST_DMA, + RST_DDR +} RST_BLOCK; + +#define RST_ADDR_SYSOC_BUS 0x48300000 +#define RST_ADDR_SYSOC_SCP 0x48300010 +#define RST_ADDR_SYSOC_DMA 0x48300040 +#define RST_ADDR_SYSOC_PCIE 0x48300050 +#define RST_ADDR_SYSOC_DDR 0x48300060 + +#define RST_SYSOC_BUS_TOP 0x00000001 +#define RST_SYSOC_BUS_PCIE0 0x00000004 +#define RST_SYSOC_BUS_PCIE1 0x00000002 +#define RST_SYSOC_BUS_PCIE_TOP 0x00000008 + +#define RST_SYSOC_SCP_SCB 0x00000001 +#define RST_SYSOC_SCP_SCBM 0x00000002 +#define RST_SYSOC_SCP_CSS_PORST 0x00000004 +#define RST_SYSOC_SCP_CSS_SYSRST 0x00000008 +#define RST_SYSOC_SCP_CSS_SRST 0x00000010 + +#define RST_SYSOC_DMA_DMA 0x00000001 +#define RST_SYSOC_DMA_DMAB 0x00000002 + +#define RST_SYSOC_PCIE_PCIE0 0x00000002 +#define RST_SYSOC_PCIE_PCIE1 0x00000001 + +#define RST_SYSOC_DDR 0x00000001 + +#define RST_ADDR_LPCM_SCB 0x48318400 +#define RST_ADDR_LPCM_PCIE 0x48319400 +#define RST_ADDR_LPCM_DMA 0x4831A400 + +#define RST_LPCM_SCB_BUS 0x00000001 +#define RST_LPCM_PCIE0 0x00000002 +#define RST_LPCM_PCIE1 0x00000001 +#define RST_LPCM_PCIE0_BUS 0x00000020 +#define RST_LPCM_PCIE1_BUS 0x00000010 +#define RST_LPCM_PCIE_TOP 0x00000040 +#define RST_LPCM_DMA_BUS 0x00000001 +#define RST_LPCM_DMAB 0x00000002 + +#define RST_NO_USE 0 + +#define RESET_INFO \ + { \ + { \ + /* PCIe TOP */ /* block sosoc */ RST_NO_USE, \ + /* block lpcm */ RST_NO_USE, \ + /* bus sosoc */ RST_SYSOC_BUS_PCIE_TOP, \ + /* bus lpcm */ RST_LPCM_PCIE_TOP, \ + /* addr sysoc blk */ RST_NO_USE, \ + /* addr sysoc bus */ RST_ADDR_SYSOC_BUS, \ + /* addr lpcm */ RST_ADDR_LPCM_PCIE, \ + }, \ + { \ + /* PCIe PCIe0 */ /* block sosoc */ RST_SYSOC_PCIE_PCIE0, \ + /* block lpcm */ RST_LPCM_PCIE0, \ + /* bus sosoc */ RST_SYSOC_BUS_PCIE0, \ + /* bus lpcm */ RST_LPCM_PCIE0_BUS, \ + /* addr sysoc blk */ RST_ADDR_SYSOC_PCIE, \ + /* addr sysoc bus */ RST_ADDR_SYSOC_BUS, \ + /* addr lpcm */ RST_ADDR_LPCM_PCIE, \ + }, \ + { \ + /* PCIe PCIe1 */ /* block sosoc */ RST_SYSOC_PCIE_PCIE1, \ + /* block lpcm */ RST_LPCM_PCIE1, \ + /* bus sosoc */ RST_SYSOC_BUS_PCIE1, \ + /* bus lpcm */ RST_LPCM_PCIE1_BUS, \ + /* addr sysoc blk */ RST_ADDR_SYSOC_PCIE, \ + /* addr sysoc bus */ RST_ADDR_SYSOC_BUS, \ + /* addr lpcm */ RST_ADDR_LPCM_PCIE, \ + }, \ + { \ + /* DMA */ /* block sosoc */ RST_SYSOC_DMA_DMAB, \ + /* block lpcm */ RST_LPCM_DMAB, \ + /* bus sosoc */ RST_SYSOC_DMA_DMA, \ + /* bus lpcm */ RST_LPCM_DMA_BUS, \ + /* addr sysoc blk */ RST_ADDR_SYSOC_DMA, \ + /* addr sysoc bus */ RST_ADDR_SYSOC_DMA, \ + /* addr lpcm */ RST_ADDR_LPCM_DMA, \ + }, \ + { /* DDR */ \ + /* block sosoc */ RST_SYSOC_DDR, \ + /* block lpcm */ RST_NO_USE, \ + /* bus sosoc */ RST_NO_USE, \ + /* bus lpcm */ RST_NO_USE, \ + /* addr sysoc blk */ RST_ADDR_SYSOC_DDR, \ + /* addr sysoc bus */ RST_NO_USE, \ + /* addr lpcm */ RST_NO_USE, \ + } \ + } + +void lpcm_sysoc_reset(RST_TYPE_t type, RST_BLOCK block); +void lpcm_sysoc_reset_clear(RST_TYPE_t type, RST_BLOCK block); + +#endif /* RESET_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/smmu_wrapper.h b/product/synquacer/module/synquacer_system/include/internal/smmu_wrapper.h new file mode 100644 index 000000000..328b0c4f3 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/smmu_wrapper.h @@ -0,0 +1,33 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMMU_WRAPPER_H +#define SMMU_WRAPPER_H + +#include +#include + +#ifdef CONFIG_SCB_USE_PCIE_INTERCONNECT + +/** + * Initialize and setup System MMU(s) + * + * @param mir_id mir_id of myself. + * @param mav_id mav_id of myself. Only valid for SynQuacer SCP-firmware. + */ +void smmu_wrapper_initialize(uint8_t mir_id, uint8_t mav_id); + +#else /* CONFIG_SCB_USE_PCIE_INTERCONNECT */ + +/** + * Initialize and setup System MMU(s) + * + */ +void smmu_wrapper_initialize(void); +#endif /* CONFIG_SCB_USE_PCIE_INTERCONNECT */ + +#endif /* SMMU_WRAPPER_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/synquacer_pd.h b/product/synquacer/module/synquacer_system/include/internal/synquacer_pd.h new file mode 100644 index 000000000..b54d1ca4d --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/synquacer_pd.h @@ -0,0 +1,284 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_PD_H +#define SYNQUACER_PD_H + +#include +#include + +#define PD_TIMEOUT_MS 200 +#define PD_CHECK_CYCLE_MS 1 + +#define OFFCHIP_CYCLE_MS_PCIE 10 +#define OFFCHIP_CYCLE_MS_DDR 10 + +#define DEV_BMAP_CA53(cluster) (1 << (cluster + 16)) +#define DEV_BMAP_CA53_ALL 0x0FFF0000 +#define DEV_BMAP_DDR0 0x00001000 +#define DEV_BMAP_DDR1 0x00002000 +#define DEV_BMAP_PCIE_BLK 0x00000800 +#define DEV_BMAP_PCIE0 0x00000100 +#define DEV_BMAP_PCIE1 0x00000200 + +#define DEV_BMAP_SCB_AM 0x00000001 +#define DEV_BMAP_SCB_SUBSYS 0x00000004 +#define DEV_BMAP_DMA_BLK 0x00000010 +//#define DEV_BMAP_SCB_TOP 0x00000002 /* can't change now */ +//#define DEV_BMAP_FE_TOP 0x00000008 /* can't change now */ + +#define PD_PRESET_ALL 0x0FFF3B15 +#define PD_PRESET_ALL_WO_CA53 (PD_PRESET_ALL & ~(DEV_BMAP_CA53_ALL)) + +#define PD_PRESET_COLDBOOT PD_PRESET_ALL + +#define PD_PRESET_CM3_REBOOT PD_PRESET_ALL +#define PD_PRESET_AP_REBOOT \ + (PD_PRESET_CM3_REBOOT & ~(DEV_BMAP_SCB_SUBSYS | DEV_BMAP_PCIE_BLK)) + +#define PD_PRESET_AP_REBOOT_WO_PCIE0 (PD_PRESET_AP_REBOOT & ~(DEV_BMAP_PCIE0)) +#define PD_PRESET_AP_REBOOT_WO_PCIE1 (PD_PRESET_AP_REBOOT & ~(DEV_BMAP_PCIE1)) + +#define PD_PRESET_SHUTDOWN PD_PRESET_ALL + +#define NOT_USE (-1) + +#define CLUSTER_PMU_NO(no) (19 + no) +#define OFFCHIP_PCIE_PMU_NO(no) (10 + no) +#define OFFCHIP_DDR_PMU_NO(no) (12 + no) +#define ONCHIP_PCIE_PMU_NO(no) (14 + no) +#define ONCHIP_DDR_PMU_NO(no) (16 + no) + +#define SNI_PPU_INFO_MP \ + { \ + { \ + /* "DDRPHY_BLK_0" */ /* no */ 2, \ + /* dev_bitmap */ DEV_BMAP_DDR0, \ + /* booting_force_off */ false, \ + /* force_off */ false, \ + }, \ + { \ + /* "DDRPHY_BLK_1" */ /* no */ 3, \ + /* dev_bitmap */ DEV_BMAP_DDR1, \ + /* booting_force_off */ false, \ + /* force_off */ false, \ + }, \ + { \ + /* "PCIEB" */ /* no */ 4, \ + /* dev_bitmap */ DEV_BMAP_PCIE_BLK, \ + /* booting_force_off */ false, \ + /* force_off */ false, \ + }, \ + { \ + /* "PCIE_BLK_0" */ /* no */ 6, \ + /* dev_bitmap */ DEV_BMAP_PCIE0, \ + /* booting_force_off */ false, \ + /* force_off */ false, \ + }, \ + { \ + /* "PCIE_BLK_1" */ /* no */ 5, \ + /* dev_bitmap */ DEV_BMAP_PCIE1, \ + /* booting_force_off */ false, \ + /* force_off */ false, \ + }, \ + { \ + /* "DMAB" */ /* no */ 7, \ + /* dev_bitmap */ DEV_BMAP_DMA_BLK, \ + /* booting_force_off */ false, \ + /* force_off */ false, \ + }, \ + { \ + /* "SCB_A_MASTER" */ /* no */ 8, \ + /* dev_bitmap */ DEV_BMAP_SCB_AM, \ + /* booting_force_off */ true, \ + /* force_off */ true, \ + }, \ + } + +#define TRANSW_NO_PCIE 0 +#define TRANSW_NO_SCBM 1 +#define TRANSW_NO_CM3 2 +#define TRANSW_NO_DDR 3 + +#define TRANSW_REG_NUM 4 + +#define SNI_TRANSACTIONSW_INFO_MP \ + { \ + { \ + /* "PCIe#0" */ /* dev_bitmap */ DEV_BMAP_PCIE0, \ + /* reg_no */ TRANSW_NO_PCIE, \ + /* sw_bitmap */ 0x2, \ + }, \ + { \ + /* "PCIe#1" */ /* dev_bitmap */ DEV_BMAP_PCIE1, \ + /* reg_no */ TRANSW_NO_PCIE, \ + /* sw_bitmap */ 0x1, \ + }, \ + { \ + /* "SCBM" */ /* dev_bitmap */ DEV_BMAP_SCB_AM, \ + /* reg_no */ TRANSW_NO_SCBM, \ + /* sw_bitmap */ 0x7, \ + }, \ + { \ + /* "CM3" */ /* dev_bitmap */ DEV_BMAP_SCB_SUBSYS, \ + /* reg_no */ TRANSW_NO_CM3, \ + /* sw_bitmap */ 0x7, \ + }, \ + { \ + /* "DDR#0" */ /* dev_bitmap */ DEV_BMAP_DDR0, \ + /* reg_no */ TRANSW_NO_DDR, \ + /* sw_bitmap */ 0x1, \ + }, \ + { \ + /* "DDR#1" */ /* dev_bitmap */ DEV_BMAP_DDR1, \ + /* reg_no */ TRANSW_NO_DDR, \ + /* sw_bitmap */ 0x2, \ + }, \ + } + +#ifdef CONFIG_SCB_DIST_FIRM +#define PD_REBOOT_DEV_BITMAP PD_PRESET_AP_REBOOT_WO_PCIE0 +#else /* CONFIG_SCB_DIST_FIRM */ +#define PD_REBOOT_DEV_BITMAP PD_PRESET_AP_REBOOT +#endif /* CONFIG_SCB_DIST_FIRM */ + +#define SNI_PMU_INFO_MP \ + { \ + { \ + /* [0]: "SCB_AM" */ /* on_priority */ 0, \ + /* dev_bitmap */ DEV_BMAP_SCB_AM, \ + /* onchip_pd */ 18, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [1]: "SCB_Subsys" */ /* on_priority */ 0, \ + /* dev_bitmap */ DEV_BMAP_SCB_SUBSYS, \ + /* onchip_pd */ 31, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [2]: "Cluster#0(A)" */ /* on_priority */ 1, \ + /* dev_bitmap */ DEV_BMAP_CA53(0), \ + /* onchip_pd */ 19, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [3]: "Cluster#5(A)" */ /* on_priority */ 1, \ + /* dev_bitmap */ DEV_BMAP_CA53(5), \ + /* onchip_pd */ 24, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [4]: "Cluster#9(A)" */ /* on_priority */ 1, \ + /* dev_bitmap */ DEV_BMAP_CA53(9), \ + /* onchip_pd */ 28, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [5]: "Cluster#10(A)" */ /* on_priority */ 1,\ + /* dev_bitmap */ DEV_BMAP_CA53(10), \ + /* onchip_pd */ 29, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [6]: "Cluster#1(B)" */ /* on_priority */ 2, \ + /* dev_bitmap */ DEV_BMAP_CA53(1), \ + /* onchip_pd */ 20, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [7]: "Cluster#6(B)" */ /* on_priority */ 2, \ + /* dev_bitmap */ DEV_BMAP_CA53(6), \ + /* onchip_pd */ 25, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [8]: "Cluster#7(B)" */ /* on_priority */ 2, \ + /* dev_bitmap */ DEV_BMAP_CA53(7), \ + /* onchip_pd */ 26, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [9]: "Cluster#11(B)" */ /* on_priority */ 2,\ + /* dev_bitmap */ DEV_BMAP_CA53(11), \ + /* onchip_pd */ 30, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [10]: "Cluster#2(C)" */ /* on_priority */ 3,\ + /* dev_bitmap */ DEV_BMAP_CA53(2), \ + /* onchip_pd */ 21, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [11]: "Cluster#3(C)" */ /* on_priority */ 3,\ + /* dev_bitmap */ DEV_BMAP_CA53(3), \ + /* onchip_pd */ 22, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [12]: "Cluster#4(C)" */ /* on_priority */ 3,\ + /* dev_bitmap */ DEV_BMAP_CA53(4), \ + /* onchip_pd */ 23, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [13]: "Cluster#8(C)" */ /* on_priority */ 3,\ + /* dev_bitmap */ DEV_BMAP_CA53(8), \ + /* onchip_pd */ 27, \ + /* offchip_pd */ NOT_USE, \ + /* offchip_cycle_ms */ 0, \ + }, \ + { \ + /* [14]: "DDR#0" */ /* on_priority */ 4, \ + /* dev_bitmap */ DEV_BMAP_DDR0, \ + /* onchip_pd */ 16, \ + /* offchip_pd */ 12, \ + /* offchip_cycle_ms */ OFFCHIP_CYCLE_MS_DDR, \ + }, \ + { \ + /* [15]: "DDR#1" */ /* on_priority */ 5, \ + /* dev_bitmap */ DEV_BMAP_DDR1, \ + /* onchip_pd */ 17, \ + /* offchip_pd */ 13, \ + /* offchip_cycle_ms */ OFFCHIP_CYCLE_MS_DDR, \ + },\ + { \ + /* [16]: "PCIe#0" */ /* on_priority */ 6, \ + /* dev_bitmap */ DEV_BMAP_PCIE0, \ + /* onchip_pd */ 15, \ + /* offchip_pd */ 11, \ + /* offchip_cycle_ms */ OFFCHIP_CYCLE_MS_PCIE, \ + }, \ + { \ + /* [17]: "PCIe#1" */ /* on_priority */ 7, \ + /* dev_bitmap */ DEV_BMAP_PCIE1, \ + /* onchip_pd */ 14, \ + /* offchip_pd */ 10, \ + /* offchip_cycle_ms */ OFFCHIP_CYCLE_MS_PCIE, \ + }, \ + } + +int32_t get_cluster_pmu_no(struct ppu_v0_reg *ppu); +uint32_t pmu_wait(uint32_t pmu_bitmap, bool on); +void power_domain_coldboot(void); +void power_domain_reboot(void); + +#endif /* SYNQUACER_PD_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/synquacer_ppu_driver.h b/product/synquacer/module/synquacer_system/include/internal/synquacer_ppu_driver.h new file mode 100644 index 000000000..0f3571d30 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/synquacer_ppu_driver.h @@ -0,0 +1,42 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_PPU_DRIVER_H +#define SYNQUACER_PPU_DRIVER_H + +#include + +#define PPU_INT_PPU0 20 +#define PPU_INT_PPU1 21 +#define PPU_INT_PPU2 22 +#define PPU_INT_PPU3 23 +#define PPU_INT_PPU4 24 +#define PPU_INT_PPU5 25 +#define PPU_INT_PPU6 26 +#define PPU_INT_PPU7 27 +#define PPU_INT_PPU8 28 + +#define PPU_PP_OFF 0x01 +#define PPU_PP_MEM_RET 0x02 +#define PPU_PP_ON 0x10 + +#define PPU_STATUS_MASK 0x1F + +#define PPU_Error 1 +#define PPU_NoError 0 + +uint32_t get_domain_base_address(int domain); + +int change_power_state( + int domain, + int next_power_policy, + int hwcactiveen, + int hwcsysreqen, + int reten); +int read_power_status(int domain); + +#endif /* SYNQUACER_PPU_DRIVER_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/sysoc.h b/product/synquacer/module/synquacer_system/include/internal/sysoc.h new file mode 100644 index 000000000..a18ea7c5f --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/sysoc.h @@ -0,0 +1,25 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYSOC_H +#define SYSOC_H + +#include +#include + +void sysoc_set_reset(uint32_t sysoc_addr, uint32_t value); + +void sysoc_clr_reset(uint32_t sysoc_addr, uint32_t value); + +uint32_t sysoc_read_reset_status(uint32_t sysoc_addr); + +int sysoc_wait_status_change( + uint32_t sysoc_addr, + bool reset_set_flag, + uint32_t set_bit); + +#endif /* SYSOC_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/thermal_sensor.h b/product/synquacer/module/synquacer_system/include/internal/thermal_sensor.h new file mode 100644 index 000000000..b49ce861d --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/thermal_sensor.h @@ -0,0 +1,69 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef THERMAL_SENSOR_H +#define THERMAL_SENSOR_H + +#define THERMAL_BASE_ADDRESS 0x48190000 +#define THERMAL_INDIVIDUAL_BASE_OFFSET 0x800 +#define THERMAL_INDIVIDUAL_SENSOR_OFFSET 0x80 + +/* base address of the thermal sensor */ +#define THERMAL_SENSOR0_BASE_ADDRESS_OFFSET 0x800 +#define THERMAL_SENSOR1_BASE_ADDRESS_OFFSET 0x880 +#define THERMAL_SENSOR2_BASE_ADDRESS_OFFSET 0x900 +#define THERMAL_SENSOR3_BASE_ADDRESS_OFFSET 0x980 +#define THERMAL_SENSOR4_BASE_ADDRESS_OFFSET 0xA00 +#define THERMAL_SENSOR5_BASE_ADDRESS_OFFSET 0xA80 +#define THERMAL_SENSOR6_BASE_ADDRESS_OFFSET 0xB00 +#define THERMAL_SENSOR7_BASE_ADDRESS_OFFSET 0xB80 +#define THERMAL_SENSOR8_BASE_ADDRESS_OFFSET 0xC00 +#define THERMAL_SENSOR9_BASE_ADDRESS_OFFSET 0xC80 +#define THERMAL_SENSOR10_BASE_ADDRESS_OFFSET 0xD00 +#define THERMAL_SENSOR11_BASE_ADDRESS_OFFSET 0xD80 +#define THERMAL_SENSOR12_BASE_ADDRESS_OFFSET 0xE00 +#define THERMAL_SENSOR13_BASE_ADDRESS_OFFSET 0xE80 +#define THERMAL_SENSOR14_BASE_ADDRESS_OFFSET 0xF00 +#define THERMAL_SENSOR15_BASE_ADDRESS_OFFSET 0xF80 + +/* register offset */ +#define THERMAL_MACROINFO_G_OFFSET 0x000 +#define THERMAL_ALLCONFIG_OFFSET 0x00C + +#define THERMAL_TS_RESET_OFFSET 0x010 +#define THERMAL_TS_EN_OFFSET 0x014 +#define THERMAL_TS_CT_OFFSET 0x018 +#define THERMAL_TS_ADJ_OFFSET 0x01C + +#define THERMAL_IRQOUT_OFFSET 0x020 +#define THERMAL_IRQCLR_OFFSET 0x024 +#define THERMAL_IRQMASK_OFFSET 0x028 +#define THERMAL_IRQSTATUS_OFFSET 0x02C + +#define THERMAL_TSDATA_VALID_X_OFFSET 0x030 +#define THERMAL_TSDATA_X_OFFSET 0x034 + +#define THERMAL_HI_FULL_TEMP_OFFSET 0x040 +#define THERMAL_HI_NEAR_TEMP_OFFSET 0x044 +#define THERMAL_LO_NEAR_TEMP_OFFSET 0x048 +#define THERMAL_LO_FULL_TEMP_OFFSET 0x04C + +#define THERMAL_HYS_TEMP_OFFSET 0x050 + +#define THERMAL_ENABLE 0x1 +#define THERMAL_DISABLE 0x0 + +#define THERMAL_SUCCESS 0x0 +#define THERMAL_FAIL 0x1 + +#define THERMAL_SENSOR_BASE(a) \ + (THERMAL_BASE_ADDRESS + THERMAL_INDIVIDUAL_BASE_OFFSET + \ + (a * (THERMAL_INDIVIDUAL_SENSOR_OFFSET))) + +int thermal_enable(void); + +#endif /* THERMAL_SENSOR_H */ diff --git a/product/synquacer/module/synquacer_system/include/internal/transaction_sw.h b/product/synquacer/module/synquacer_system/include/internal/transaction_sw.h new file mode 100644 index 000000000..5accb88de --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/internal/transaction_sw.h @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRANSACTION_SW_H +#define TRANSACTION_SW_H + +void set_transactionsw_off( + uint32_t transactionsw_reg_addr, + uint32_t disable_bit); + +void set_transactionsw_on(uint32_t transactionsw_reg_addr, uint32_t enable_bit); + +#endif /* TRANSACTION_SW_H */ diff --git a/product/synquacer/module/synquacer_system/include/mod_synquacer_system.h b/product/synquacer/module/synquacer_system/include/mod_synquacer_system.h new file mode 100644 index 000000000..d74bb6487 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/mod_synquacer_system.h @@ -0,0 +1,91 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_SYNQUACER_SYSTEM_H +#define MOD_SYNQUACER_SYSTEM_H + +#include + +/*! + * \addtogroup GroupSYNQUACERModule SYNQUACER Product Modules + * @{ + */ + +/*! + * \defgroup GroupSYNQUACERSystem SYNQUACER System Support + * + * \brief SynQuacer System module. + * + * \details This module implements a SynQuacer system driver + * + * @{ + */ + +/*! + * \brief Additional SYNQUACER system power states. + */ +enum mod_synquacer_system_power_states { + MOD_SYNQUACER_SYSTEM_POWER_STATE_SLEEP0 = MOD_PD_STATE_COUNT, + MOD_SYNQUACER_SYSTEM_POWER_STATE_SLEEP1, + MOD_SYNQUACER_SYSTEM_POWER_STATE_COUNT +}; + +/*! + * \brief System power state masks. + */ +enum mod_synquacer_system_power_state_masks { + MOD_SYNQUACER_SYSTEM_POWER_STATE_SLEEP0_MASK = + (1 << MOD_SYNQUACER_SYSTEM_POWER_STATE_SLEEP0), + MOD_SYNQUACER_SYSTEM_POWER_STATE_SLEEP1_MASK = + (1 << MOD_SYNQUACER_SYSTEM_POWER_STATE_SLEEP1), +}; + +/*! + * \brief Indices of the interfaces exposed by the module. + */ +enum mod_synquacer_system_api_idx { + /*! API index for the driver interface of the SYSTEM POWER module */ + MOD_SYNQUACER_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER, + + /*! Number of exposed interfaces */ + MOD_SYNQUACER_SYSTEM_API_COUNT +}; + +/*! + * \brief Module Context + */ +struct synquacer_system_ctx { + /*! pointer to the log module. */ + const struct mod_log_api *log_api; + + /*! pointer to the power domain module. */ + const struct mod_pd_restricted_api *mod_pd_restricted_api; + + /*! pointer to the ccn512 module. */ + const struct mod_ccn512_api *ccn512_api; + + /*! pointer to the f_i2c module. */ + const struct mod_f_i2c_api *f_i2c_api; + + /*! pointer to the hsspi module. */ + const struct mod_hsspi_api *hsspi_api; +}; + +/*! + * \brief SynQuacer System Module Context + */ +extern struct synquacer_system_ctx synquacer_system_ctx; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_SYNQUACER_SYSTEM_H */ diff --git a/product/synquacer/module/synquacer_system/include/sysdef_option.h b/product/synquacer/module/synquacer_system/include/sysdef_option.h new file mode 100644 index 000000000..5c8de54e3 --- /dev/null +++ b/product/synquacer/module/synquacer_system/include/sysdef_option.h @@ -0,0 +1,47 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYSDEF_OPTION_H +#define SYSDEF_OPTION_H + +#define NIC_CONFIG_NUM 6 + +#define I2C_TEG_START_ADDR 0x51 +#define I2C_MP_START_ADDR 0x50 + +/** + * GPIO-pin auto descriptor settings + * + * pin_no: GPIO pin # + * inv: true if using inverted logic + * str: description + */ +/*! + * \brief GPIO-pin auto descriptor settings + */ +struct sysdef_option_gpio_desc { + /*! GPIO pin number. */ + int pin_no; + /*! true if using inverted logic */ + bool inv; + /*! description. */ + char *str; +}; + +uint32_t sysdef_option_get_clear_clkforce(void); +bool sysdef_option_get_ap_reboot_enable(void); +const uint32_t *sysdef_option_get_scbm_mv_nic_config(void); +char *sysdef_option_get_chip_version(void); +bool sysdef_option_get_gic500_preits_bug_tweak_enabled(void); +bool sysdef_option_get_ddr_addr_trans_bug_tweak_enabled(void); +uint32_t sysdef_option_get_i2c_for_spd_read_addr(void); +uint32_t sysdef_option_get_sensor_num(void); +uint32_t sysdef_option_get_gpio_desc( + const struct sysdef_option_gpio_desc **gpio_desc_pp); +void sysdef_option_init_synquacer(void); + +#endif /* SYSDEF_OPTION_H */ diff --git a/product/synquacer/module/synquacer_system/src/Makefile b/product/synquacer/module/synquacer_system/src/Makefile new file mode 100644 index 000000000..20868ec9b --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/Makefile @@ -0,0 +1,24 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := SYNQUACER SYSTEM +BS_LIB_SOURCES = mod_synquacer_system.c \ + sysdef_option.c \ + synquacer_main.c \ + load_secure_fw.c \ + boot_ctl.c \ + synquacer_pd_manage.c \ + pmu_driver.c \ + transaction_sw.c \ + nic400.c \ + sysoc.c \ + mmu500.c \ + smmu_config.c \ + thermal_sensor.c \ + gpio.c + +include $(BS_DIR)/lib.mk diff --git a/product/synquacer/module/synquacer_system/src/boot_ctl.c b/product/synquacer/module/synquacer_system/src/boot_ctl.c new file mode 100644 index 000000000..9bd374b0e --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/boot_ctl.c @@ -0,0 +1,33 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#define REG_ADDR_OFFSET_BOOT_REMAP UINT32_C(0x000) +#define REG_ADDR_OFFSET_BOOT_FE UINT32_C(0x004) +#define REG_ADDR_OFFSET_BOOT_HSSPI UINT32_C(0x008) +#define REG_ADDR_OFFSET_BOOT_EMMC UINT32_C(0x010) +#define REG_ADDR_OFFSET_BOOT_MODE UINT32_C(0x014) +#define REG_ADDR_OFFSET_DSW3_STATUS UINT32_C(0x018) + +void set_memory_remap(uint32_t value) +{ + writel( + CONFIG_SOC_REG_ADDR_BOOT_CTL_TOP + REG_ADDR_OFFSET_BOOT_REMAP, value); +} + +uint8_t get_dsw3_status(uint8_t bit_mask) +{ + uint8_t value = + readb(CONFIG_SOC_REG_ADDR_BOOT_CTL_TOP + REG_ADDR_OFFSET_DSW3_STATUS); + + return (value & bit_mask); +} diff --git a/product/synquacer/module/synquacer_system/src/gpio.c b/product/synquacer/module/synquacer_system/src/gpio.c new file mode 100644 index 000000000..a122c4a37 --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/gpio.c @@ -0,0 +1,134 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +static const uint8_t prmux_pingrp[] = CONFIG_SCB_PRMUX_PINGRP; +static const uint8_t gpio_direction[] = CONFIG_SCB_GPIO_DIRECTION; +static const uint8_t gpio_function[] = CONFIG_SCB_GPIO_FUNCTION; + +void prmux_set_pingrp(void *prmux_base_addr, uint32_t idx, uint32_t pingrp) +{ + if (idx > PRMUX_MAX_IDX) { + SYNQUACER_DEV_LOG_ERROR("Error@%s idx(%d) too big\n", __func__, idx); + return; + } + + writel((uint32_t)prmux_base_addr + (idx << 2), pingrp); +} + +void gpio_set_data(void *gpio_base_addr, uint32_t idx, uint8_t value) +{ + if (idx > GPIO_MAX_IDX) { + SYNQUACER_DEV_LOG_ERROR("Error@%s idx(%d) too big\n", __func__, idx); + return; + } + + writel((uint32_t)gpio_base_addr + (idx << 2), value); +} + +uint8_t gpio_get_data(void *gpio_base_addr, uint32_t idx) +{ + if (idx > GPIO_MAX_IDX) { + SYNQUACER_DEV_LOG_ERROR("Error@%s idx(%d) too big\n", __func__, idx); + return 0; + } + + return readl((uint32_t)gpio_base_addr + (idx << 2)); +} + +void gpio_set_direction(void *gpio_base_addr, uint32_t idx, uint8_t value) +{ + if (idx > GPIO_MAX_IDX) { + SYNQUACER_DEV_LOG_ERROR("Error@%s idx(%d) too big\n", __func__, idx); + return; + } + + writel((uint32_t)gpio_base_addr + 0x10 + (idx << 2), value); +} + +uint8_t gpio_get_direction(void *gpio_base_addr, uint32_t idx) +{ + if (idx > GPIO_MAX_IDX) { + SYNQUACER_DEV_LOG_ERROR("Error@%s idx(%d) too big\n", __func__, idx); + return 0; + } + + return readl((uint32_t)gpio_base_addr + 0x10 + (idx << 2)); +} + +void gpio_set_function(void *gpio_base_addr, uint32_t idx, uint8_t value) +{ + if (idx > GPIO_MAX_IDX) { + SYNQUACER_DEV_LOG_ERROR("Error@%s idx(%d) too big\n", __func__, idx); + return; + } + + writel((uint32_t)gpio_base_addr + 0x20 + (idx << 2), value); +} + +uint8_t gpio_get_function(void *gpio_base_addr, uint32_t idx) +{ + if (idx > GPIO_MAX_IDX) { + SYNQUACER_DEV_LOG_ERROR("Error@%s idx(%d) too big\n", __func__, idx); + return 0; + } + + return readl((uint32_t)gpio_base_addr + 0x20 + (idx << 2)); +} + +void fw_gpio_init(void) +{ + size_t i; + uint32_t gpio_initial_values; + + uint32_t gpio_desc_num; + const struct sysdef_option_gpio_desc *gpio_desc_p; + + SYNQUACER_DEV_LOG_INFO("[SYSTEM] Setting up PRMUX\n"); + for (i = 0; i < FWK_ARRAY_SIZE(prmux_pingrp); i++) { + prmux_set_pingrp( + (void *)CONFIG_SOC_PRMUX_BASE_ADDR, i, prmux_pingrp[i]); + } + SYNQUACER_DEV_LOG_INFO("[SYSTEM] Finished setting up PRMUX\n"); + + SYNQUACER_DEV_LOG_INFO("[SYSTEM] Setting up GPIO\n"); + for (i = 0; i < FWK_ARRAY_SIZE(gpio_function); i++) + gpio_set_function((void *)CONFIG_SOC_AP_GPIO_BASE, i, gpio_function[i]); + + for (i = 0; i < FWK_ARRAY_SIZE(gpio_direction); i++) + gpio_set_direction( + (void *)CONFIG_SOC_AP_GPIO_BASE, i, gpio_direction[i]); + + SYNQUACER_DEV_LOG_INFO("[SYSTEM] Finished setting up GPIO\n"); + + gpio_initial_values = + (gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 3) << 24) | + (gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 2) << 16) | + (gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 1) << 8) | + gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 0); + + SYNQUACER_DEV_LOG_INFO( + "[SYSTEM] Initial GPIO input values = 0x%08x: ", gpio_initial_values); + + gpio_desc_num = sysdef_option_get_gpio_desc(&gpio_desc_p); + for (i = 0; i < gpio_desc_num; i++) { + if (((gpio_initial_values >> gpio_desc_p->pin_no) & 0x1) == + (gpio_desc_p->inv ? 1 : 0)) { + /* prepend "!" if the target signal is not asserted */ + SYNQUACER_DEV_LOG_INFO("!"); + } + SYNQUACER_DEV_LOG_INFO("%s ", gpio_desc_p->str); + } + + SYNQUACER_DEV_LOG_INFO("\n"); +} diff --git a/product/synquacer/module/synquacer_system/src/load_secure_fw.c b/product/synquacer/module/synquacer_system/src/load_secure_fw.c new file mode 100644 index 000000000..35ffbd254 --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/load_secure_fw.c @@ -0,0 +1,155 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +#include + +struct fip_toc_header_s { + uint32_t name; + uint32_t serial_num; + uint64_t flags; +} __attribute__((packed)); + +typedef struct fip_toc_header_s fip_toc_header_t; +/* fip toc header 16 byte*/ + +struct fip_toc_entry_s { + uint8_t uuid[16]; + uint64_t offset_addr; + uint64_t size; + uint64_t flags; +} __attribute__((packed)); + +typedef struct fip_toc_entry_s fip_toc_entry_t; +/* fip toc entry 40 byte*/ + +struct fip_package_s { + fip_toc_header_t fip_toc_header; + fip_toc_entry_t fip_toc_entry[5]; + uint32_t data[1]; +} __attribute__((packed)); + +typedef struct fip_package_s fip_package_t; + +struct arm_tf_fip_package_s { + fip_toc_header_t fip_toc_header; + fip_toc_entry_t fip_toc_entry[4]; +} __attribute__((packed)); + +typedef struct arm_tf_fip_package_s arm_tf_fip_package_t; + +#define ADDR_TRANS_EN (0x1 /* ADDR_TRANS_EN */ << 20) +#define REG_ASH_SCP_POW_CTL UINT32_C(0x50000000) +#define ADDR_TRANS_OFFSET UINT32_C(0x34) +#define OPTEE_OS_BINARY_SIZE UINT32_C(0x80000) +#define SCP_ADDR_TRANS_AREA UINT32_C(0xCB000000) +#define BL32_TOC_ENTRY_INDEX (3) + +#define UUID_SECURE_PAYLOAD_BL32 \ + { \ + 0x05, 0xd0, 0xe1, 0x89, 0x53, 0xdc, 0x13, 0x47, 0x8d, 0x2b, 0x50, \ + 0x0a, 0x4b, 0x7a, 0x3e, 0x38 \ + } + +/* + * Current implementation expects bl32 is located as 4th binary + * in the arm-tf fip package. + */ +static void fw_fip_load_bl32(void) +{ + uint32_t trans_addr_39_20; + void *src, *dst; + uint8_t bl32_uuid[] = UUID_SECURE_PAYLOAD_BL32; + + arm_tf_fip_package_t *fip_package_p = + (arm_tf_fip_package_t *)CONFIG_SCB_ARM_TF_BASE_ADDR; + + if (memcmp( + (void *)bl32_uuid, + (void *)fip_package_p->fip_toc_entry[BL32_TOC_ENTRY_INDEX].uuid, + sizeof(bl32_uuid)) != 0) { + SYNQUACER_DEV_LOG_ERROR("[FIP] BL32 UUID is wrong, skip loading\n"); + return; + } + + SYNQUACER_DEV_LOG_ERROR("[FIP] load BL32\n"); + + /* enable DRAM access by configuring address trans register */ + trans_addr_39_20 = + ((CONFIG_SCB_ARM_TB_BL32_BASE_ADDR >> 20) | ADDR_TRANS_EN); + *((volatile uint32_t *)(REG_ASH_SCP_POW_CTL + ADDR_TRANS_OFFSET)) = + trans_addr_39_20; + + src = (void *)((uint32_t)fip_package_p + + (uint32_t)fip_package_p->fip_toc_entry[BL32_TOC_ENTRY_INDEX].offset_addr); + dst = (void *)SCP_ADDR_TRANS_AREA; + memcpy(dst, src, fip_package_p->fip_toc_entry[BL32_TOC_ENTRY_INDEX].size); + + /* disable DRAM access */ + trans_addr_39_20 = + ((CONFIG_SCB_ARM_TB_BL32_BASE_ADDR >> 20) & ~ADDR_TRANS_EN); + *((volatile uint32_t *)(REG_ASH_SCP_POW_CTL + ADDR_TRANS_OFFSET)) = + trans_addr_39_20; + + SYNQUACER_DEV_LOG_ERROR("[FIP] BL32 is loaded\n"); +} + +void fw_fip_load_arm_tf(void) +{ + uint32_t i; + + const uint32_t arm_tf_dst_addr[3] = { CONFIG_SCB_ARM_TB_BL1_BASE_ADDR, + CONFIG_SCB_ARM_TB_BL2_BASE_ADDR, + CONFIG_SCB_ARM_TB_BL3_BASE_ADDR }; + + arm_tf_fip_package_t *fip_package_p = + (arm_tf_fip_package_t *)CONFIG_SCB_ARM_TF_BASE_ADDR; + + static_assert( + sizeof(fip_toc_header_t) == 16, "sizeof(fip_toc_header_t) is wrong"); + static_assert( + sizeof(fip_toc_entry_t) == 40, "sizeof(fip_toc_entry_t) is wrong"); + static_assert( + sizeof(arm_tf_fip_package_t) == 176, + "sizeof(arm_tf_fip_package_t) is wrong"); + + for (i = 0; i < FWK_ARRAY_SIZE(arm_tf_dst_addr); i++) { + SYNQUACER_DEV_LOG_DEBUG( + "[FIP] fip_toc_entry[%d] offset_addr %lx\n", + i, + fip_package_p->fip_toc_entry[i].offset_addr); + + SYNQUACER_DEV_LOG_DEBUG( + "[FIP] fip_toc_entry[%d] size %lu\n", + i, + fip_package_p->fip_toc_entry[i].size); + + SYNQUACER_DEV_LOG_DEBUG( + "[FIP] dst addr[%d] %x\n", i, arm_tf_dst_addr[i]); + + SYNQUACER_DEV_LOG_DEBUG( + "[FIP] src addr[%d] %x\n", + i, + ((uint32_t)fip_package_p + + (uint32_t)fip_package_p->fip_toc_entry[i].offset_addr)); + + memcpy((void *)arm_tf_dst_addr[i], + (void *)((uint32_t)fip_package_p + + (uint32_t)fip_package_p->fip_toc_entry[i].offset_addr), + (uint32_t)fip_package_p->fip_toc_entry[i].size); + } + + if (ddr_is_secure_dram_enabled()) + fw_fip_load_bl32(); +} diff --git a/product/synquacer/module/synquacer_system/src/mmu500.c b/product/synquacer/module/synquacer_system/src/mmu500.c new file mode 100644 index 000000000..b97ab7410 --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/mmu500.c @@ -0,0 +1,145 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void SMMU_setup_PMU(MMU500_Type_t *SMMU) +{ + volatile uint32_t *pmu_regs; + int page_size; + + page_size = ((SMMU->GR0.IDR1 & SMMU_IDR1_PAGESIZE) == 0) ? 0x1000 : 0x10000; + + pmu_regs = (volatile uint32_t *)(((uint32_t)SMMU) + 3 * page_size); + + pmu_regs[0x0400 / 4] = + 0x00000010U; /* PMEVTYPER0: P=U=NSP=NSU=0, EVENT=0x0010(access) */ + pmu_regs[0x0404 / 4] = + 0x00000011U; /* PMEVTYPER1: P=U=NSP=NSU=0, EVENT=0x0011(read) */ + pmu_regs[0x0408 / 4] = + 0x00000012U; /* PMEVTYPER2: P=U=NSP=NSU=0, EVENT=0x0012(write) */ + pmu_regs[0x0c00 / 4] = + 0x00000007U; /* PMCNTENSET0: enable counter #0, #1, #2 */ + pmu_regs[0x0800 / 4] = 0x00000800U; /* PMCGCR0: enable=1, global_basis */ + pmu_regs[0x0e04 / 4] = 0x00000003U; /* PMCR: enable=1, reset=1 */ + + SYNQUACER_DEV_LOG_DEBUG( + "[MMU500] setup PMU for MMU-500@0x%08x. page_size=%d." + "0x%08x(access), 0x%08x(read), 0x%08x(write).\n", + (uint32_t)SMMU, + page_size, + (uint32_t)&pmu_regs[0], + (uint32_t)&pmu_regs[1], + (uint32_t)&pmu_regs[2]); +} + +int32_t SMMU_s_init( + MMU500_Type_t *SMMU, + uint32_t num_context, + const MMU500_ContextInfo_t *context_info, + enum mmu500_granule granule) +{ + uint32_t temp; + uint32_t i; + + SMMU->GR0.ACR |= + SMMU_ACR_S2CRB_TLBEN | SMMU_ACR_MMUDISB_TLBEN | SMMU_ACR_SMTNMB_TLBEN; + + if ((num_context > (SMMU->GR0.IDR1 & SMMU_IDR1_NUMCB)) || + (num_context > (SMMU->GR0.IDR0 & SMMU_IDR0_NUMSMRG))) { + /* num_context too large */ + return -1; + } + + /* Use all context banks for secure access */ + temp = SMMU->GR0.SCR1; + temp &= ~(SMMU_SCR1_NSNUMCBO | SMMU_SCR1_NSNUMSMRGO); + SMMU->GR0.SCR1 = temp | (0 << SMMU_SCR1_NSNUMCBO_OFFSET) | + (0 << SMMU_SCR1_NSNUMSMRGO_OFFSET) | SMMU_SCR1_SPMEN; + + SMMU->GR0.CR0 = + (SMMU_CR0_SMCFCFG | SMMU_CR0_USFCFG | SMMU_CR0_STALLD | + SMMU_CR0_GCFGFIE | SMMU_CR0_GCFGFRE | SMMU_CR0_GFIE | SMMU_CR0_GFRE); + + for (i = 0; i < num_context; i++) { + SMMU->GR0.S2CR[i] = SMMU_S2CRn_TYPE_CONTEXT | i; + SMMU->GR0.SMR[i] = SMMU_SMRn_VALID | + (context_info[i].stream_match_mask << 16) | + context_info[i].stream_match_id; + SMMU_ns_cb_stage1_init(SMMU, i, context_info[i].base_addr, granule); + } + + SMMU_setup_PMU(SMMU); + + return 0; +} + +void SMMU_ns_cb_stage1_init( + MMU500_Type_t *SMMU, + uint32_t cb, + uint64_t base_addr, + enum mmu500_granule granule) +{ + uint64_t temp; + + SMMU->GR1.CBAR[cb] = SMMU_CBAR_TYPE_STAGE1 | SMMU_CBAR_MEM_NORMAL; + SMMU->GR1.CBA2R[cb] = SMMU_CBA2R_VA64; + + SMMU->TCB[cb].CB_TCR = + (SMMU_TCR_EPD1 | SMMU_TCR_SH0_OUTER | SMMU_TCR_ORGN0_WBWA | + SMMU_TCR_IRGN0_WBWA | SMMU_TCR_T0SZ_256TB); + + switch (granule) { + case MMU500_GRANULE_4KB: + SMMU->TCB[cb].CB_TCR |= SMMU_TCR_TG0_4KB; + break; + case MMU500_GRANULE_16KB: + SMMU->TCB[cb].CB_TCR |= SMMU_TCR_TG0_16KB; + break; + case MMU500_GRANULE_64KB: + SMMU->TCB[cb].CB_TCR |= SMMU_TCR_TG0_64KB; + break; + } + + SMMU->TCB[cb].CB_TCR2 = SMMU_TCR2_SEP_47 | SMMU_TCR2_PASIZE_48; + SMMU->TCB[cb].CB_TTBR0 = + (((uint64_t)0) << SMMU_TTBRn_ASID_OFFSET) | ((uint64_t)base_addr); + + /* + * AttrIndx[2:0]: setting + * 2'b000: 0xFF=Outer write-back,non-transient normal memory, + * read-write/Inner write-back.non-transient normal + * memory,read-write 2'b001: 0x00=Device-nGnRnE 2'b010-111: (not used) + */ + temp = 0x00000000000000ffLLU; + SMMU->TCB[cb].CB_MAIR0 = (uint32_t)temp; + SMMU->TCB[cb].CB_MAIR1 = (uint32_t)(temp >> 32); + + SMMU->TCB[cb].CB_FSR = 0xffffffff; + + SMMU->TCB[cb].CB_SCTLR = + (SMMU_SCTLR_MEM_NORMAL | SMMU_SCTLR_UWXN | SMMU_SCTLR_CFIE | + SMMU_SCTLR_CFRE | SMMU_SCTLR_M); +} + +void SMMU_s_disable(MMU500_Type_t *SMMU, uint32_t num_context) +{ + uint32_t i; + + if ((num_context > (SMMU->GR0.IDR1 & SMMU_IDR1_NUMCB)) || + (num_context > (SMMU->GR0.IDR0 & SMMU_IDR0_NUMSMRG))) { + /* num_context too large */ + return; + } + + SMMU->GR0.ACR &= ~( + SMMU_ACR_S2CRB_TLBEN | SMMU_ACR_MMUDISB_TLBEN | SMMU_ACR_SMTNMB_TLBEN); + + for (i = 0; i < num_context; i++) + SMMU->TCB[i].CB_SCTLR &= ~(SMMU_SCTLR_M); +} diff --git a/product/synquacer/module/synquacer_system/src/mod_synquacer_system.c b/product/synquacer/module/synquacer_system/src/mod_synquacer_system.c new file mode 100644 index 000000000..246195bec --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/mod_synquacer_system.c @@ -0,0 +1,185 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct synquacer_system_ctx synquacer_system_ctx; +const struct fwk_module_config config_synquacer_system = { 0 }; + +enum synquacer_system_event { + SYNQUACER_SYSTEM_EVENT_START, + SYNQUACER_SYSTEM_EVENT_COUNT +}; + +int reboot_chip(void); +void power_domain_reboot(void); +void main_initialize(void); +int synquacer_main(void); + +/* + * SYSTEM POWER driver API + */ + +static int synquacer_system_shutdown( + enum mod_pd_system_shutdown system_shutdown) +{ + synquacer_system_ctx.log_api->log( + MOD_LOG_GROUP_DEBUG, + "[SYNQUACER SYSTEM] requesting synquacer system_shutdown\n"); + + reboot_chip(); + + return FWK_E_DEVICE; +} + +static const struct mod_system_power_driver_api + synquacer_system_power_driver_api = { + .system_shutdown = synquacer_system_shutdown, + }; + +/* + * Functions fulfilling the framework's module interface + */ + +static int synquacer_system_mod_init( + fwk_id_t module_id, + unsigned int unused, + const void *unused2) +{ + return FWK_SUCCESS; +} + +static int synquacer_system_bind(fwk_id_t id, unsigned int round) +{ + int status; + + if (round == 0) { + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_LOG), + FWK_ID_API(FWK_MODULE_IDX_LOG, 0), + &synquacer_system_ctx.log_api); + if (status != FWK_SUCCESS) + return status; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_CCN512), + FWK_ID_API(FWK_MODULE_IDX_CCN512, 0), + &synquacer_system_ctx.ccn512_api); + if (status != FWK_SUCCESS) + return status; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_F_I2C), + FWK_ID_API(FWK_MODULE_IDX_F_I2C, 0), + &synquacer_system_ctx.f_i2c_api); + if (status != FWK_SUCCESS) + return status; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_HSSPI), + FWK_ID_API(FWK_MODULE_IDX_HSSPI, 0), + &synquacer_system_ctx.hsspi_api); + if (status != FWK_SUCCESS) + return status; + + status = fwk_module_bind( + FWK_ID_MODULE(FWK_MODULE_IDX_POWER_DOMAIN), + FWK_ID_API(FWK_MODULE_IDX_POWER_DOMAIN, MOD_PD_API_IDX_RESTRICTED), + &synquacer_system_ctx.mod_pd_restricted_api); + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + +static int synquacer_system_process_bind_request( + fwk_id_t requester_id, + fwk_id_t pd_id, + fwk_id_t api_id, + const void **api) +{ + *api = &synquacer_system_power_driver_api; + return FWK_SUCCESS; +} + +static int synquacer_system_start(fwk_id_t id) +{ + int status; + struct fwk_event req; + + main_initialize(); + + synquacer_system_ctx.log_api->log( + MOD_LOG_GROUP_DEBUG, + "[SYNQUACER SYSTEM] Request system initialization.\n"); + + status = fwk_thread_create(FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_SYSTEM)); + if (status != FWK_SUCCESS) + return status; + + req = (struct fwk_event){ + .id = FWK_ID_EVENT( + FWK_MODULE_IDX_SYNQUACER_SYSTEM, SYNQUACER_SYSTEM_EVENT_START), + .source_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_SYSTEM), + .target_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_SYSTEM), + .response_requested = false, + }; + + status = fwk_thread_put_event(&req); + if (status != FWK_SUCCESS) + return status; + + return FWK_SUCCESS; +} + +int synquacer_process_event( + const struct fwk_event *event, + struct fwk_event *resp) +{ + if (fwk_id_get_event_idx(event->id) == SYNQUACER_SYSTEM_EVENT_START) { + synquacer_system_ctx.log_api->log( + MOD_LOG_GROUP_DEBUG, + "[SYNQUACER SYSTEM] Process system start event.\n"); + synquacer_main(); + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_synquacer_system = { + .name = "SYNQUACER_SYSTEM", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .event_count = 1, + .init = synquacer_system_mod_init, + .bind = synquacer_system_bind, + .process_bind_request = synquacer_system_process_bind_request, + .start = synquacer_system_start, + .process_event = synquacer_process_event, +}; diff --git a/product/synquacer/module/synquacer_system/src/nic400.c b/product/synquacer/module/synquacer_system/src/nic400.c new file mode 100644 index 000000000..a42e73bb6 --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/nic400.c @@ -0,0 +1,61 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#define NIC_TOP_ADDR_SEC_REG (0x00000008) +#define NIC_SEC_REG_OFFSET (0x04) + +static void nic_sec_slave_security( + uint32_t nic_top_addr, + uint32_t slave_index, + uint32_t value) +{ + SYNQUACER_DEV_LOG_DEBUG( + "%s addr 0x%08x value 0x%08x\n", + __func__, + (nic_top_addr + NIC_TOP_ADDR_SEC_REG + + NIC_SEC_REG_OFFSET * slave_index), + value); + + writel( + (nic_top_addr + NIC_TOP_ADDR_SEC_REG + + NIC_SEC_REG_OFFSET * slave_index), + value); +} + +void nic_secure_access_ctrl_init(void) +{ + uint32_t n, m; + static const uint32_t nic_base_addr[] = CONFIG_SOC_NIC_ADDR_INFO; + static const uint32_t nic_config[][32] = CONFIG_SCB_NIC_INFO; + const uint32_t *config; + + for (n = 0; n < FWK_ARRAY_SIZE(nic_base_addr); n++) { + for (m = 0; nic_config[n][m] != END_OF_NIC_LIST; m++) { + if (nic_config[n][m] == NIC_SETUP_SKIP) + continue; + + nic_sec_slave_security(nic_base_addr[n], m, nic_config[n][m]); + } + } + + config = sysdef_option_get_scbm_mv_nic_config(); + for (n = 0; config[n] != END_OF_NIC_LIST; n++) { + if (config[n] == NIC_SETUP_SKIP) + continue; + + nic_sec_slave_security(SCBM_MV_NIC, n, config[n]); + } +} diff --git a/product/synquacer/module/synquacer_system/src/pmu_driver.c b/product/synquacer/module/synquacer_system/src/pmu_driver.c new file mode 100644 index 000000000..ef9374f3c --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/pmu_driver.c @@ -0,0 +1,267 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#define CONFIG_SOC_REG_ADDR_PMU_CTL (CONFIG_SOC_REG_ADDR_PMU_TOP + 0) +#define CONFIG_SOC_REG_ADDR_PMU_INT_EN (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x8U) +#define CONFIG_SOC_REG_ADDR_PMU_INT_ST (CONFIG_SOC_REG_ADDR_PMU_TOP + 0xCU) +#define CONFIG_SOC_REG_ADDR_PMU_INT_CLR (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x10U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_STR (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x18U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_EN0 (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x20U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_EN1 (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x28U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_DN_EN (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x40U) + +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC0 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x51U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC1 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x54U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC2 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x58U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC3 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x5CU) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC4 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x60U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC5 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x64U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC6 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x68U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC7 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x6CU) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_CYC_SEL \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x70U) + +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY0 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x80U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY1 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x84U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY2 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x88U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY3 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x8CU) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY4 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x90U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY5 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x94U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY6 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x98U) +#define CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY7 \ + (CONFIG_SOC_REG_ADDR_PMU_TOP + 0x9CU) + +#define PD_MAX_NO 31U + +/** @name bit fields for PMU_CTL */ +//@{ +/** ClocK Gating Enabel */ +#define CONFIG_SOC_PMU_CTL_REG_CKGE (1UL << 31) +/** SET ENable */ +#define CONFIG_SOC_PMU_CTL_REG_SETEN (0xAAUL << 8) +/** All Down SET */ +#define CONFIG_SOC_PMU_CTL_REG_ADSET (1UL << 2) +/** Power Down SET */ +#define CONFIG_SOC_PMU_CTL_REG_PDSET (1UL << 1) +/** Power Up SET */ +#define CONFIG_SOC_PMU_CTL_REG_PUSET (1UL << 0) +//@} + +static const uint32_t pmu_power_on_cycle_reg_addr[] = { + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC0, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC1, + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC2, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC3, + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC4, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC5, + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC6, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_CYC7 +}; + +static const uint32_t pmu_pwr_on_dly_reg_addr[] = { + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY0, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY1, + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY2, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY3, + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY4, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY5, + CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY6, CONFIG_SOC_REG_ADDR_PMU_PWR_ON_DLY7 +}; + +void pmu_on(uint32_t pd_on_flag) +{ + writel(CONFIG_SOC_REG_ADDR_PMU_PWR_ON_EN0, pd_on_flag); + + writel( + CONFIG_SOC_REG_ADDR_PMU_CTL, + (CONFIG_SOC_PMU_CTL_REG_SETEN | CONFIG_SOC_PMU_CTL_REG_PUSET)); +} + +void pmu_off(uint32_t pd_off_flag) +{ + writel(CONFIG_SOC_REG_ADDR_PMU_PWR_DN_EN, pd_off_flag); + + writel( + CONFIG_SOC_REG_ADDR_PMU_CTL, + (CONFIG_SOC_PMU_CTL_REG_SETEN | CONFIG_SOC_PMU_CTL_REG_PDSET)); +} + +uint32_t pmu_read_pd_power_status(void) +{ + return readl(CONFIG_SOC_REG_ADDR_PMU_PWR_STR); +} + +void pmu_write_power_on_cycle(uint8_t pd_no, uint8_t value) +{ + uint32_t tmp; + uint32_t idx, bit_field_offset, intsts; + + if (pd_no > PD_MAX_NO) + return; + + /* calc on cycle idx*/ + idx = (pd_no >> 2); + + /* calc field offset*/ + bit_field_offset = (pd_no & 0x3U); + + DI(intsts); + + tmp = readl(pmu_power_on_cycle_reg_addr[idx]); + + /* clear on cycle*/ + tmp &= ~(0xffUL << (8 * bit_field_offset)); + + /* set new on cycle*/ + tmp |= (value << (8 * bit_field_offset)); + + writel(pmu_power_on_cycle_reg_addr[idx], tmp); + + EI(intsts); +} + +uint8_t pmu_read_power_on_cycle(uint8_t pd_no) +{ + uint32_t tmp; + uint8_t value = 0; + uint32_t idx, bit_field_offset; + + if (pd_no > PD_MAX_NO) + return value; + + /* calc on cycle idx*/ + idx = (pd_no >> 2); + + /* calc field offset*/ + bit_field_offset = (pd_no & 0x3U); + + tmp = readl(pmu_power_on_cycle_reg_addr[idx]); + + value = (tmp >> (8 * bit_field_offset)) & 0xffU; + + return value; +} + +void pmu_enable_int(uint32_t enable_bit) +{ + uint32_t value; + uint32_t intsts; + + DI(intsts); + + /* read and set int enable */ + value = (readl(CONFIG_SOC_REG_ADDR_PMU_INT_EN) | enable_bit); + + /* write int enable */ + writel(CONFIG_SOC_REG_ADDR_PMU_INT_EN, value); + + EI(intsts); +} + +void pmu_disable_int(uint32_t disable_bit) +{ + uint32_t value; + uint32_t intsts; + + DI(intsts); + + /* read int enable */ + value = readl(CONFIG_SOC_REG_ADDR_PMU_INT_EN); + + /* read clear int enable */ + value &= (~(disable_bit)); + + writel(CONFIG_SOC_REG_ADDR_PMU_INT_EN, value); + + EI(intsts); +} + +uint8_t pmu_read_int_satus(void) +{ + return (readl(CONFIG_SOC_REG_ADDR_PMU_INT_ST) & 0xffU); +} + +void pmu_clr_int_satus(uint32_t clr_bit) +{ + writel(CONFIG_SOC_REG_ADDR_PMU_INT_CLR, clr_bit); +} + +void pmu_on_wakeup(uint8_t pd_no) +{ + uint32_t value; + uint32_t intsts; + + if (pd_no > PD_MAX_NO) + return; + + DI(intsts); + + value = (readl(CONFIG_SOC_REG_ADDR_PMU_PWR_ON_EN1) | (1UL << pd_no)); + + writel(CONFIG_SOC_REG_ADDR_PMU_PWR_ON_EN1, value); + + EI(intsts); +} + +#define PMU_PRIORITY_MASK 0x1fU +#define PMU_PRIORITY_FIELD_MAX 0x1fU + +void pmu_write_power_on_priority(uint8_t pd_no, uint8_t value) +{ + uint32_t tmp, idx, bit_field_offset; + uint32_t intsts; + + if (pd_no > PD_MAX_NO) + return; + + if (value > PMU_PRIORITY_FIELD_MAX) + return; + + /* calc on cycle idx*/ + idx = (pd_no >> 2); + + /* calc field offset*/ + bit_field_offset = (pd_no & 0x3U); + + DI(intsts); + + tmp = readl(pmu_pwr_on_dly_reg_addr[idx]); + + /* clear on cycle*/ + tmp &= ~(PMU_PRIORITY_MASK << (8 * bit_field_offset)); + + /* set new on cycle*/ + tmp |= (value << (8 * bit_field_offset)); + + writel(pmu_pwr_on_dly_reg_addr[idx], tmp); + + EI(intsts); +} + +void pmu_write_pwr_cyc_sel(uint32_t value) +{ + writel(CONFIG_SOC_REG_ADDR_PMU_PWR_CYC_SEL, value); +} + +uint32_t pmu_read_pwr_cyc_sel(void) +{ + return readl(CONFIG_SOC_REG_ADDR_PMU_PWR_CYC_SEL); +} diff --git a/product/synquacer/module/synquacer_system/src/smmu_config.c b/product/synquacer/module/synquacer_system/src/smmu_config.c new file mode 100644 index 000000000..447540656 --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/smmu_config.c @@ -0,0 +1,494 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include + +typedef struct { + uint64_t desc[0x1000 / 8]; +} smmu_granule4kb_desc_t; + +typedef struct { + uint64_t desc[0x10000 / 8]; +} smmu_granule16kb_desc_t; + +typedef struct { + uint64_t desc[0x40000 / 8]; +} smmu_granule64kb_desc_t; + +enum upper_attr { + MMU500_UPPER_ATTR_CONTIGUOUS = (1 << 0), + MMU500_UPPER_ATTR_PXN = (1 << 1), + MMU500_UPPER_ATTR_XN = (1 << 2), +}; + +enum lower_attr { + MMU500_LOWER_ATTR_ATTRINDX_0 = 0, + MMU500_LOWER_ATTR_ATTRINDX_1 = 1, + MMU500_LOWER_ATTR_ATTRINDX_2 = 2, + MMU500_LOWER_ATTR_ATTRINDX_3 = 3, + MMU500_LOWER_ATTR_ATTRINDX_4 = 4, + MMU500_LOWER_ATTR_ATTRINDX_5 = 5, + MMU500_LOWER_ATTR_ATTRINDX_6 = 6, + MMU500_LOWER_ATTR_ATTRINDX_7 = 7, + MMU500_LOWER_ATTR_NS = (1 << 3), + MMU500_LOWER_ATTR_AP_RW = (1 << 4), + MMU500_LOWER_ATTR_AP_RO = (3 << 4), + MMU500_LOWER_ATTR_SH_NON_SHAREABLE = 0, + MMU500_LOWER_ATTR_SH_OUTER_SHAREABLE = (2 << 6), + MMU500_LOWER_ATTR_SH_INNER_SHAREABLE = (3 << 6), + MMU500_LOWER_ATTR_AF = (1 << 8), + MMU500_LOWER_ATTR_NG = (1 << 9) +}; + +enum pagetable_valid { + MMU500_PAGETABLE_VALID_OFF = 0, + MMU500_PAGETABLE_VALID_ON = 1 +}; + +#define SMMU_DESC_T smmu_granule4kb_desc_t + +uint64_t smmu_convert_to_axi_addr(void *addr_cm3view); +void smmu_wrapper_pcie(void); + +static uint64_t mmu500_make_next_level_table_addr_desc( + enum mmu500_granule granule, + int level, + void *next_level_table_addr_cm3view) +{ + return (smmu_convert_to_axi_addr(next_level_table_addr_cm3view) | 0x3); +} + +static uint64_t mmu500_make_block_desc( + enum mmu500_granule granule, + int level, + uint64_t output_addr, + uint64_t upper_attr, + uint64_t lower_attr) +{ + return ((upper_attr << 52) | output_addr | (lower_attr << 2) | 0x1); +} + +static uint64_t mmu500_make_level3_desc( + enum mmu500_granule granule, + uint64_t output_addr, + uint64_t upper_attr, + uint64_t lower_attr) +{ + return ((upper_attr << 52) | output_addr | (lower_attr << 2) | 0x3); +} + +uint64_t smmu_convert_to_axi_addr(void *addr_cm3view) +{ + uint32_t addr = (uint32_t)addr_cm3view; + + return (uint64_t)(addr - 0xa0000000U); +} + +void smmu_wrapper_initialize(void) +{ + SYNQUACER_DEV_LOG_INFO("Configure System MMUs starts\n"); + + /* Basic Configuration */ + smmu_wrapper_pcie(); + + SYNQUACER_DEV_LOG_INFO("Configure System MMUs finished\n"); +} + +void smmu_wrapper_pcie(void) +{ + uint64_t upper_attr = 0; + uint64_t lower_attr_noncoherent = + (MMU500_LOWER_ATTR_SH_NON_SHAREABLE | MMU500_LOWER_ATTR_AP_RW | + MMU500_LOWER_ATTR_AF | MMU500_LOWER_ATTR_ATTRINDX_1); + + uint64_t lower_attr_coherent = + (MMU500_LOWER_ATTR_SH_OUTER_SHAREABLE | MMU500_LOWER_ATTR_AP_RW | + MMU500_LOWER_ATTR_AF | MMU500_LOWER_ATTR_ATTRINDX_0); + + SMMU_DESC_T *curr_smmu_desc = + (SMMU_DESC_T *)CONFIG_SCB_SMMU_PAGE_TABLE_BASE_ADDR; + SMMU_DESC_T *tbu0_smmu_desc_addr; + SMMU_DESC_T *tbu2_smmu_desc_addr; + SMMU_DESC_T *tbu3_smmu_desc_addr; + + MMU500_ContextInfo_t context_info[3]; + int i; + uint64_t w_lower_attr_tbu3, w_lower_attr_tbu2; + + /* attribute set(TBU3) */ + if (eeprom_config.pcie_cache_snoop_valid[0] == 0) + w_lower_attr_tbu3 = lower_attr_noncoherent | MMU500_LOWER_ATTR_NS; + else + w_lower_attr_tbu3 = lower_attr_coherent | MMU500_LOWER_ATTR_NS; + + /* attribute set(TBU2) */ + if (eeprom_config.pcie_cache_snoop_valid[1] == 0) + w_lower_attr_tbu2 = lower_attr_noncoherent | MMU500_LOWER_ATTR_NS; + else + w_lower_attr_tbu2 = lower_attr_coherent | MMU500_LOWER_ATTR_NS; + + memset( + (void *)CONFIG_SCB_SMMU_PAGE_TABLE_BASE_ADDR, + 0, + sizeof(SMMU_DESC_T) * 15); + + /********************************************************************** + * North MMU(TBU0) settings + **********************************************************************/ + tbu0_smmu_desc_addr = curr_smmu_desc; + + /* page#0: level0 descriptor */ + + /* 0x0000_0000_0000_0000/39 */ + curr_smmu_desc->desc[0x000] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 1)); + + /* page#1: level1 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0000_4000_0000/30 */ + curr_smmu_desc->desc[0x001] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 1, (curr_smmu_desc + 1)); + + /* 0x0000_003e_0000_0000/32 */ + for (i = 0xf8; i < 0xfc; i++) { + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0xcLLU << 44) | 0x3e00000000LLU | (((uint64_t)(i & 0x3)) << 30)), + upper_attr, + lower_attr_noncoherent); + } + + /* 0x0000_003f_0000_0000/32 */ + for (i = 0xfc; i < 0x100; i++) { + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x8LLU << 44) | 0x3f00000000LLU | (((uint64_t)(i & 0x3)) << 30)), + upper_attr, + lower_attr_noncoherent); + } + +#ifndef PCIE_FILTER_BUS0_TYPE0_CONFIG + /* page#2: level2 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0000_6000_0000/28 */ + for (i = 0x100; i < 0x180; i++) { + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0xcLLU << 44) | 0x60000000LLU | (((uint64_t)(i & 0x7f)) << 21)), + upper_attr, + lower_attr_noncoherent); + } + + /* 0x0000_0000_7000_0000/28 */ + for (i = 0x180; i < 0x200; i++) { + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x8LLU << 44) | 0x70000000LLU | (((uint64_t)(i & 0x7f)) << 21)), + upper_attr, + lower_attr_noncoherent); + } + +#else + /* page#2: level2 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0000_6000_0000/21 */ + curr_smmu_desc->desc[0x100] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 1)); + + /* 0x0000_0000_6020_0000/28 */ + for (i = 0x101; i < 0x180; i++) { + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0xcLLU << 44) | 0x60000000LLU | (((uint64_t)(i & 0x7f)) << 21)), + upper_attr, + lower_attr_noncoherent); + } + + /* 0x0000_0000_7000_0000/28 */ + curr_smmu_desc->desc[0x180] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 2)); + + /* 0x0000_0000_7020_0000/28 */ + for (i = 0x181; i < 0x200; i++) { + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x8LLU << 44) | 0x70000000LLU | (((uint64_t)(i & 0x7f)) << 21)), + upper_attr, + lower_attr_noncoherent); + } + + /* page#3: level3 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0000_6000_0000/15 - 0x0000_0000_6000_7FFF/15 */ + /* direct mapping to PCIe bus#0 dev#0(32KB) */ + for (i = 0x0; i < 0x8; i++) { + curr_smmu_desc->desc[i] = mmu500_make_level3_desc( + MMU500_GRANULE_4KB, + ((0xcLLU << 44) | 0x60000000LLU | (((uint64_t)(i & 0x7)) << 12)), + upper_attr, + lower_attr_noncoherent); + } + + /* 0x0000_0000_6000_8000/20 - 0x0000_0000_600F_FFFF/20 */ + /* translate PCIe bus#0 dev#1-31 access to the region always return 0xFF..F + */ + for (i = 0x8; i < 0x100; i++) { + curr_smmu_desc->desc[i] = mmu500_make_level3_desc( + MMU500_GRANULE_4KB, + ((0xcLLU << 44) | 0x67F10000LLU | (((uint64_t)(i & 0x7)) << 12)), + upper_attr, + lower_attr_noncoherent); + } + + /* 0x0000_0000_6010_0000/21 - 0x0000_0000_601F_FFFF/21 */ + /* direct mapping to PCIe bus#1 */ + for (i = 0x100; i < 0x200; i++) { + curr_smmu_desc->desc[i] = mmu500_make_level3_desc( + MMU500_GRANULE_4KB, + ((0xcLLU << 44) | 0x60000000LLU | (((uint64_t)(i & 0x1ff)) << 12)), + upper_attr, + lower_attr_noncoherent); + } + + /* page#4: level3 descriptor #1 */ + ++curr_smmu_desc; + + /* 0x0000_0000_7000_0000/15 - 0x0000_0000_7000_7FFF/15 */ + /* direct mapping to PCIe bus#0 dev#0(32KB) */ + for (i = 0x0; i < 0x8; i++) { + curr_smmu_desc->desc[i] = mmu500_make_level3_desc( + MMU500_GRANULE_4KB, + ((0x8LLU << 44) | 0x70000000LLU | (((uint64_t)(i & 0x7)) << 12)), + upper_attr, + lower_attr_noncoherent); + } + + /* 0x0000_0000_7000_8000/20 - 0x0000_0000_700F_FFFF/20 */ + /* translate PCIe bus#0 dev#1-31 access to the region always return 0xFF..F + */ + for (i = 0x8; i < 0x100; i++) { + curr_smmu_desc->desc[i] = mmu500_make_level3_desc( + MMU500_GRANULE_4KB, + ((0x8LLU << 44) | 0x77F10000LLU | (((uint64_t)(i & 0x7)) << 12)), + upper_attr, + lower_attr_noncoherent); + } + + /* 0x0000_0000_7010_0000/21 - 0x0000_0000_701F_FFFF/21 */ + /* direct mapping to PCIe bus#1 */ + for (i = 0x100; i < 0x200; i++) { + curr_smmu_desc->desc[i] = mmu500_make_level3_desc( + MMU500_GRANULE_4KB, + ((0x8LLU << 44) | 0x70000000LLU | (((uint64_t)(i & 0x1ff)) << 12)), + upper_attr, + lower_attr_noncoherent); + } +#endif /* PCIE_FILTER_BUS0_TYPE0_CONFIG */ + + /********************************************************************** + * North MMU(TBU3) settings + **********************************************************************/ + + /* page#5: level0 descriptor */ + ++curr_smmu_desc; + tbu3_smmu_desc_addr = curr_smmu_desc; + + /* 0x0000_0000_0000_0000/39 */ + curr_smmu_desc->desc[0x000] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 1)); + + /* 0x0000_0080_0000_0000/39 */ + curr_smmu_desc->desc[0x001] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 2)); + + /* 0x0000_0800_0000_0000/39 */ + curr_smmu_desc->desc[0x010] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 3)); + + /* page#6: level1 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0000_0000_0000-0x0000_0000_7fff_ffff: always non-coherent */ + for (i = 0x000; i < 0x002; i++) { + uint64_t phy_base_addr = (((uint64_t)i) << 30); + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x4LLU << 44) | phy_base_addr), + upper_attr, + lower_attr_noncoherent); + } + /* 0x0000_0000_8000_0000-0x0000_007f_ffff_ffff: user-configured coherence */ + for (i = 0x002; i < 0x200; i++) { + uint64_t phy_base_addr = (((uint64_t)i) << 30); + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x4LLU << 44) | phy_base_addr), + upper_attr, + w_lower_attr_tbu3); + } + + /* page#7: level1 descriptor #1 */ + ++curr_smmu_desc; + + /* 0x0000_0080_0000_0000/39 */ + for (i = 0x000; i < 0x200; i++) { + uint64_t phy_base_addr = (((uint64_t)i) << 30); + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x4LLU << 44) | phy_base_addr | 0x008000000000LLU), + upper_attr, + w_lower_attr_tbu3); + } + + /* page#8: level1 descriptor #2 */ + ++curr_smmu_desc; + + /* 0x0000_0800_0000_0000/30 */ + curr_smmu_desc->desc[0x000] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 1, (curr_smmu_desc + 1)); + + /* page#9: level2 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0800_0000_0000/22 */ + for (i = 0x000; i < 0x002; i++) { + uint64_t peri_phys_base_addr = (((uint64_t)i) << 21) | 0x58000000LLU; + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 2, + ((0x4LLU << 44) | peri_phys_base_addr), + upper_attr, + lower_attr_noncoherent); + } + + /********************************************************************** + * North MMU(TBU2) settings + **********************************************************************/ + + /* page#10: level0 descriptor */ + ++curr_smmu_desc; + tbu2_smmu_desc_addr = curr_smmu_desc; + + /* 0x0000_0000_0000_0000/39 */ + curr_smmu_desc->desc[0x000] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 1)); + + /* 0x0000_0080_0000_0000/39 */ + curr_smmu_desc->desc[0x001] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 2)); + + /* 0x0000_0800_0000_0000/39 */ + curr_smmu_desc->desc[0x010] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 0, (curr_smmu_desc + 3)); + + /* page#11: level1 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0000_0000_0000-0x0000_0000_7fff_ffff: always non-coherent */ + for (i = 0x000; i < 0x002; i++) { + uint64_t phy_base_addr = (((uint64_t)i) << 30); + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x4LLU << 44) | phy_base_addr), + upper_attr, + lower_attr_noncoherent); + } + /* 0x0000_0000_8000_0000-0x0000_007f_ffff_ffff: user-configured coherence */ + for (i = 0x002; i < 0x200; i++) { + uint64_t phy_base_addr = (((uint64_t)i) << 30); + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x4LLU << 44) | phy_base_addr), + upper_attr, + w_lower_attr_tbu2); + } + + /* page#12: level1 descriptor #1 */ + ++curr_smmu_desc; + + /* 0x0000_0080_0000_0000/39 */ + for (i = 0x000; i < 0x200; i++) { + uint64_t phy_base_addr = (((uint64_t)i) << 30); + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 1, + ((0x4LLU << 44) | phy_base_addr | 0x008000000000LLU), + upper_attr, + w_lower_attr_tbu2); + } + + /* page#13: level1 descriptor #2 */ + ++curr_smmu_desc; + + /* 0x0000_0800_0000_0000/30 */ + curr_smmu_desc->desc[0x000] = mmu500_make_next_level_table_addr_desc( + MMU500_GRANULE_4KB, 1, (curr_smmu_desc + 1)); + + /* page#14: level2 descriptor #0 */ + ++curr_smmu_desc; + + /* 0x0000_0800_0000_0000/22 */ + for (i = 0x000; i < 0x002; i++) { + uint64_t peri_phys_base_addr = (((uint64_t)i) << 21) | 0x58000000LLU; + + curr_smmu_desc->desc[i] = mmu500_make_block_desc( + MMU500_GRANULE_4KB, + 2, + ((0x4LLU << 44) | peri_phys_base_addr), + upper_attr, + lower_attr_noncoherent); + } + + /* stream id mapping */ + /* TBU0 */ + context_info[0].stream_match_mask = 0x3ff; + context_info[0].stream_match_id = 0; + context_info[0].base_addr = smmu_convert_to_axi_addr(tbu0_smmu_desc_addr); + /* TBU3 */ + context_info[1].stream_match_mask = 0x3ff; + context_info[1].stream_match_id = 0xC00; + context_info[1].base_addr = smmu_convert_to_axi_addr(tbu3_smmu_desc_addr); + /* TBU2 */ + context_info[2].stream_match_mask = 0x3ff; + context_info[2].stream_match_id = 0x800; + context_info[2].base_addr = smmu_convert_to_axi_addr(tbu2_smmu_desc_addr); + + SMMU_s_init( + (MMU500_Type_t *)CONFIG_SOC_NORTH_SMMU_REG_BASE, + (uint32_t)3, + context_info, + MMU500_GRANULE_4KB); +} diff --git a/product/synquacer/module/synquacer_system/src/synquacer_main.c b/product/synquacer/module/synquacer_system/src/synquacer_main.c new file mode 100644 index 000000000..f979b5b2f --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/synquacer_main.c @@ -0,0 +1,368 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define SEC_OVERRIDE_CONVERT_MASK UINT32_C(0x3) + +#define SEC_OVERRIDE_CONVERT_TO_SEC UINT8_C(0) +#define SEC_OVERRIDE_CONVERT_TO_NONSEC UINT8_C(1) +#define SEC_OVERRIDE_CONVERT_TO_NO_CHANGE UINT8_C(2) + +#define SEC_OVERRIDE_REG_PCIEIF0_MMU UINT8_C(0) +#define SEC_OVERRIDE_REG_PCIEIF1_MMU UINT8_C(2) +#define SEC_OVERRIDE_REG_EMMC_XDMAC_NETSEC_MMU UINT8_C(4) +#define SEC_OVERRIDE_REG_XDMAC_NIC UINT8_C(16) +#define SEC_OVERRIDE_REG_EMMC_NIC UINT8_C(18) +#define SEC_OVERRIDE_REG_NETSEC_NIC UINT8_C(20) + +eeprom_config_t eeprom_config; + +void power_domain_coldboot(void); +int fw_ddr_spd_param_check(void); +void bus_sysoc_init(void); +void fw_fip_load_arm_tf(void); +void smmu_wrapper_initialize(void); +void pcie_wrapper_configure(void); + +static void fw_prepare_debug_pik(void) +{ + /* DEBUG ack */ + /* + * bit2 : CSYSPWRUPACK + * bit1 : CDBGPWRUPACK + * bit0 : CDBGPWRUPACK + */ + writel(PIK_DEBUG_BASE, 0x00000007); +} + +void fw_ap_data_clk_preparation(void) +{ + struct ap_data { + /* Use 8 bit temporarily until SCP and TF team get aligned*/ + volatile uint64_t a72_cluster_mask : 8; + volatile uint32_t primary_cpu : 6; + volatile uint32_t unused : 18; + } *ap_data; + + /* Initialise AP context area */ + memset((void *)AP_CONTEXT_BASE, 0, AP_CONTEXT_SIZE); + + /* + * Pass data to the AP using the MHU secure payload area for cluster 1. + * Avoid using cluster 0's payload area as this will be overwritten by the + * SCP Ready message before the AP is powered-up and has a chance to copy + * the data. + */ + ap_data = ((struct ap_data *)MHU_PAYLOAD_S_CLUSTER_BASE(1)); + ap_data->a72_cluster_mask = 0; + ap_data->primary_cpu = 0; + ap_data->unused = 0; + __DMB(); + + fw_prepare_debug_pik(); +} + +eeprom_config_t *fw_get_config_table(void) +{ + return &eeprom_config; +} + +void fw_set_sec_override(uint8_t value, uint8_t change_bit_offset) +{ + uint32_t temp, intsts; + + if (value >= 0x3U) + return; + + if (change_bit_offset > 20U) + return; + + DI(intsts); + + temp = readl( + CONFIG_SOC_REG_ADDR_SYS_OVER_REG_TOP + + CONFIG_SOC_SYS_OVER_OFFSET_SEC_OVERRIDE); + + /* SEC_OVERRIDE_SCBM_MMU Set Convert to the Secure Transaction. */ + temp &= (~(SEC_OVERRIDE_CONVERT_MASK << change_bit_offset)); + temp |= (value << change_bit_offset); + writel( + CONFIG_SOC_REG_ADDR_SYS_OVER_REG_TOP + + CONFIG_SOC_SYS_OVER_OFFSET_SEC_OVERRIDE, + temp); + + EI(intsts); +} + +static void scb_am_block_init(void) +{ + uint32_t value; + + /* + * set emmc/netsec1/xdmac to non-secure so that CA53 can use + * as a non-secure master + */ + fw_set_sec_override( + SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_EMMC_XDMAC_NETSEC_MMU); + fw_set_sec_override( + SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_XDMAC_NIC); + fw_set_sec_override( + SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_EMMC_NIC); + fw_set_sec_override( + SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_NETSEC_NIC); + +#if defined(SET_PCIE_NON_SECURE) + /* + * This is only for DeveloperBox, set non-secure transaction + * for PCIe#0/#1. + */ + fw_set_sec_override( + SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_PCIEIF0_MMU); + fw_set_sec_override( + SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_PCIEIF1_MMU); +#endif + + /* set Re-tunuing mode 0*/ + value = readl(CONFIG_SOC_SD_CTL_REG_BASE); + + value &= ~(0x3U << 8); + + writel(CONFIG_SOC_SD_CTL_REG_BASE, value); +} + +void fw_clear_clkforce(uint32_t value) +{ + /* + * Writing 1 to a bit enables dynamic hardware clock-gating. + * Writing 0 to a bit is ignored. + * bit8 : SYSPLLCLKDBGFORCE + * bit7 : DMCCLKFORCE + * bit6 : SYSPERCLKFORCE + * bit5 : PCLKSCPFORCE + * bit2 : CCNCLKFORCE + * bit0 : PPUCLKFORCE + */ + PIK_SYSTEM->CLKFORCE_CLR = value; +} + +static crg11_state_t crg11_state[CONFIG_SOC_CRG11_NUM] = { + { + /* ID0 PERI */ + .ps_mode = 0, + .fb_mode = 10U, + .src_frequency = 25000000, + .lcrg_numerator = INVALID_LCRG, + .reg_addr = CONFIG_SOC_REG_ADDR_CRG_PERI_TOP, + .clock_domain_div_modifiable_mask = 0x1fffU, + .clock_domain_div = { + 0x3, + 0x3, + 0x7, + 0xf, + 0x1, + 0x7, + 0xf, + 0x3, + 0xf9, + 0x1, + 0x1, + 0x3, + 0x7, + 0, + 0, + 0, + }, + .port_gate = { 0x1, + 0xc1, + 0x1, + 0xf, + 0x3, + 0x1, + 0x1, + 0x1, + 0x1, + 0xff, + 0x7d, + 0x6, + 0x3, + 0x0, + 0x0, + 0x0 }, + .gate_enable = { 0x1, + 0xc1, + 0x1, + 0xf, + 0x3, + 0x1, + 0x1, + 0x1, + 0x1, + 0xff, + 0x7d, + 0x6, + 0x3, + 0x0, + 0x0, + 0x0 }, + .ref_count = 1, + .ap_change_allowed_flag = false, + }, + { /* ID1 EMMC */ + .ps_mode = 0, .fb_mode = 26U, .src_frequency = 25000000, + .lcrg_numerator = INVALID_LCRG, + .reg_addr = CONFIG_SOC_REG_ADDR_CRG_EMMC_TOP, + .clock_domain_div_modifiable_mask = 0x1fU, + .clock_domain_div = { + 0, 1, 1, 7, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + .port_gate = { 0 }, .gate_enable = { 0 }, .ref_count = 1, + .ap_change_allowed_flag = false, + } +}; + +void crg11_soft_reset(uint8_t crg11_id) +{ + writel(CRG11_CRSWR(crg11_state[crg11_id].reg_addr), 1); +} + +static void fw_system_reset(void) +{ + crg11_soft_reset(CONFIG_SCB_CRG11_ID_PERI); + + for (;;) + __WFI(); +} + +int reboot_chip(void) +{ + SYNQUACER_DEV_LOG_INFO("[SYNQUACER SYSTEM] HSSPI exit start.\n"); + synquacer_system_ctx.hsspi_api->hsspi_exit(); + SYNQUACER_DEV_LOG_INFO("[SYNQUACER SYSTEM] HSSPI exit end.\n"); + + __disable_fault_irq(); + + /* set default memory remap */ + set_memory_remap(8U); + + /* do chip reboot */ + fw_system_reset(); + + /* Unreachable */ + + return FWK_SUCCESS; +} + +static void ap_dev_init(void) +{ + fw_ap_data_clk_preparation(); + fw_gpio_init(); + scb_am_block_init(); +} + +void main_initialize(void) +{ + int status = FWK_SUCCESS; + (void)status; + + sysdef_option_init_synquacer(); + + fw_clear_clkforce(sysdef_option_get_clear_clkforce()); + + SYNQUACER_DEV_LOG_INFO( + "[SYNQUACER SYSTEM] chip version %s.\n", + sysdef_option_get_chip_version()); + + power_domain_coldboot(); + nic_secure_access_ctrl_init(); + thermal_enable(); + + __enable_irq(); + __enable_fault_irq(); + + synquacer_system_ctx.f_i2c_api->init(); + + status = fw_ddr_spd_param_check(); + assert(status == FWK_SUCCESS); + + /* prepare eeprom configuration data */ + memcpy( + &eeprom_config, + (char *)(CONFIG_SCP_CONFIG_TABLE_ADDR + EEPROM_CONFIG_T_START_OFFSET), + sizeof(eeprom_config)); + + bus_sysoc_init(); + + return; +} + +static void fw_wakeup_ap(void) +{ + ap_dev_init(); + + synquacer_system_ctx.hsspi_api->hsspi_init(); + SYNQUACER_DEV_LOG_INFO( + "[SYNQUACER SYSTEM] Finished initializing HS-SPI controller.\n"); + SYNQUACER_DEV_LOG_INFO("[SYNQUACER SYSTEM] Arm tf load start.\n"); + fw_fip_load_arm_tf(); + SYNQUACER_DEV_LOG_INFO("[SYNQUACER SYSTEM] Arm tf load end.\n"); +} + +int synquacer_main(void) +{ + int status; + + smmu_wrapper_initialize(); + pcie_wrapper_configure(); + fw_wakeup_ap(); + + SYNQUACER_DEV_LOG_INFO("[SYNQUACER SYSTEM] powering up AP\n"); + status = + synquacer_system_ctx.mod_pd_restricted_api->set_composite_state_async( + FWK_ID_ELEMENT(FWK_MODULE_IDX_POWER_DOMAIN, 0), + false, + MOD_PD_COMPOSITE_STATE( + MOD_PD_LEVEL_2, + 0, + MOD_PD_STATE_ON, + MOD_PD_STATE_ON, + MOD_PD_STATE_ON)); + + if (status == FWK_SUCCESS) + SYNQUACER_DEV_LOG_INFO("[SYNQUACER SYSTEM] finished powering up AP\n"); + else + SYNQUACER_DEV_LOG_ERROR( + "[SYNQUACER SYSTEM] failed to power up AP. status=%d\n", status); + + return status; +} diff --git a/product/synquacer/module/synquacer_system/src/synquacer_pd_manage.c b/product/synquacer/module/synquacer_system/src/synquacer_pd_manage.c new file mode 100644 index 000000000..87ab6c70e --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/synquacer_pd_manage.c @@ -0,0 +1,370 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define SCB_DIV_ROUND_UP(NUMERATOR, DENOMINATOR) \ + (((NUMERATOR) + (DENOMINATOR)-1) / (DENOMINATOR)) +#define POWER_CONV_MS_TO_PWR_ON_CYC(MS) \ + (SCB_DIV_ROUND_UP(((MS)*32768), 32000) - 1) + +#define PD_TIMEOUT_COUNT ((PD_TIMEOUT_MS / PD_CHECK_CYCLE_MS) + 1) + +struct { + int32_t on_priority; + uint32_t dev_bitmap; + int32_t onchip_pd; + int32_t offchip_pd; + int32_t offchip_cycle_ms; +} sni_pmu_info[] = SNI_PMU_INFO_MP; + +static const struct { + uint32_t no; + uint32_t dev_bitmap; + bool booting_force_off; + bool force_off; +} sni_ppu_info[] = SNI_PPU_INFO_MP; + +static const struct { + uint32_t dev_bitmap; + uint32_t reg_no; + uint32_t sw_bitmap; +} sni_transw_info[] = SNI_TRANSACTIONSW_INFO_MP; + +#define FOR_EACH_PMU_INFO(index) \ + for (index = 0; index < FWK_ARRAY_SIZE(sni_pmu_info); index++) +#define FOR_EACH_PPU_INFO(index) \ + for (index = 0; index < FWK_ARRAY_SIZE(sni_ppu_info); index++) +#define FOR_EACH_TRANSW_INFO(index) \ + for (index = 0; index < FWK_ARRAY_SIZE(sni_transw_info); index++) +#define FOR_EACH_TRANSW_REG(index) \ + for (index = 0; index < TRANSW_REG_NUM; index++) + +#define CONFIG_SOC_REG_ADDR_SYSOC_TRANSW_TOP UINT32_C(0x48110000 + 0x740) + +#define TRANSW_ADDR(tran_tbl_num) \ + (CONFIG_SOC_REG_ADDR_SYSOC_TRANSW_TOP + tran_tbl_num * 8) + +uint32_t get_domain_base_address(int domain) +{ + uint32_t address; + + switch (domain) { + case 0: + address = PPU0_BASE; + break; + case 1: + address = PPU1_BASE; + break; + case 2: + address = PPU2_BASE; + break; + case 3: + address = PPU3_BASE; + break; + case 4: + address = PPU4_BASE; + break; + case 5: + address = PPU5_BASE; + break; + case 6: + address = PPU6_BASE; + break; + case 7: + address = PPU7_BASE; + break; + case 8: + address = PPU8_BASE; + break; + default: + address = ~0; + } + + return address; +} + +int change_power_state( + int domain, + int next_power_policy, + int hwcactiveen, + int hwcsysreqen, + int reten) +{ + uint32_t base_address = get_domain_base_address(domain); + uint32_t ppr = base_address + PPU_PPR_OFFSET; + uint32_t psr = base_address + PPU_PSR_OFFSET; + uint32_t pcr = base_address + PPU_PCR_OFFSET; + uint32_t wdata; + + int current_power_plicy = (readl(psr) & 0x1F); + + if (current_power_plicy == next_power_policy) + return 1; + + wdata = (reten << 4) | (hwcsysreqen << 1) | hwcactiveen; + writel(pcr, wdata); + + writel(ppr, next_power_policy); + + return 0; +} + +int read_power_status(int domain) +{ + uint32_t base_address = get_domain_base_address(domain); + uint32_t psr = base_address + PPU_PSR_OFFSET; + + if (base_address == (uint32_t)~0) + return 0; + + return readl(psr); +} + +static void sni_power_domain_workaround_mp(void) +{ + /* + * sni-ppu force off + * --- Trouble-shooting case2 by Verification-team + * + * "booting force off" is FALSE : active_en = 0, sysreq_en = 1 + * TRUE : active_en = 0, sysreq_en = 0 + * + * [CAUTION] Before this process need reset-clear of adb-400(pcie and dmab) + */ + uint32_t i, j; + int r; + + SYNQUACER_DEV_LOG_INFO("[PowerDomain] Socionext-PPU initialize .\n"); + + /* ppu off */ + for (i = 0; i < FWK_ARRAY_SIZE(sni_ppu_info); i++) { + uint32_t hwcsysreqen; + hwcsysreqen = (sni_ppu_info[i].booting_force_off) ? 0 : 1; + + r = change_power_state( + sni_ppu_info[i].no, PPU_PP_OFF, 0, hwcsysreqen, 0); + if (r != 0) { + SYNQUACER_DEV_LOG_ERROR( + "[PPU] powerdomain workaround error. " + "sni-ppu%d off-process.\n", + sni_ppu_info[i].no); + } + } + + /* ppu off-process check */ + for (i = 0; i < FWK_ARRAY_SIZE(sni_ppu_info); i++) { + for (j = 0; j < PD_TIMEOUT_COUNT; j++) { + if ((read_power_status(sni_ppu_info[i].no) & PPU_STATUS_MASK) == + PPU_PP_OFF) + break; + + osDelay(PD_CHECK_CYCLE_MS); + } + if (j >= PD_TIMEOUT_COUNT) { + SYNQUACER_DEV_LOG_ERROR( + "[PPU] powerdomain workaround error. sni-ppu%d " + "status timeout\n", + sni_ppu_info[i].no); + } + } + + /* reset */ + lpcm_sysoc_reset(RST_TYPE_WO_BUS, RST_PCIE0); /* PCIe#0 Link */ + lpcm_sysoc_reset(RST_TYPE_WO_BUS, RST_PCIE1); /* PCIe#1 Link */ + lpcm_sysoc_reset(RST_TYPE_ALL, RST_DDR); + + /* adb400 reset */ + lpcm_sysoc_reset(RST_TYPE_BUS, RST_PCIE0); /* PCIe#0 PowerOnReset */ + lpcm_sysoc_reset(RST_TYPE_BUS, RST_PCIE1); /* PCIe#1 PowerOnReset */ + lpcm_sysoc_reset(RST_TYPE_BUS, RST_PCIE_TOP); + lpcm_sysoc_reset(RST_TYPE_BUS, RST_DMA); + + SYNQUACER_DEV_LOG_INFO("[PowerDomain] Socionext-PPU initialize end .\n"); +} + +static void sni_power_domain_on_mp(uint32_t dev_bitmap) +{ + uint32_t i, j, r; + uint32_t pmu_bitmap; + uint32_t transw_reg_bitmap[TRANSW_REG_NUM] = { 0 }; + + SYNQUACER_DEV_LOG_INFO("[PowerDomain] PowerDomain All-ON start.\n"); + + /* pmu cycle time */ + FOR_EACH_PMU_INFO(i) + { + if ((sni_pmu_info[i].dev_bitmap & dev_bitmap) == 0) + continue; + + if (sni_pmu_info[i].offchip_pd == NOT_USE) + continue; + + pmu_write_power_on_cycle( + sni_pmu_info[i].offchip_pd, + POWER_CONV_MS_TO_PWR_ON_CYC(sni_pmu_info[i].offchip_cycle_ms)); + } + + /* Make pmu and transaction-sw bitmap */ + pmu_bitmap = 0; + FOR_EACH_PMU_INFO(i) + { + if ((sni_pmu_info[i].dev_bitmap & dev_bitmap) == 0) + continue; + + pmu_bitmap |= (1 << sni_pmu_info[i].onchip_pd); + + if (sni_pmu_info[i].offchip_pd != NOT_USE) + pmu_bitmap |= (1 << sni_pmu_info[i].offchip_pd); + } + FOR_EACH_TRANSW_INFO(i) + { + if ((sni_transw_info[i].dev_bitmap & dev_bitmap) == 0) + continue; + + r = sni_transw_info[i].reg_no; + transw_reg_bitmap[r] |= sni_transw_info[i].sw_bitmap; + } + + /* + * pmu all on + * (without booting_on is 'false') + */ + + pmu_on(pmu_bitmap); + + /* waiting pmu-on */ + r = pmu_wait(pmu_bitmap, true); + if (r != 0) + SYNQUACER_DEV_LOG_ERROR( + "[PPU] sni-pmu timeout expected:(0x%08x) result: " + "(0x%08x).\n", + pmu_bitmap, + pmu_read_pd_power_status()); + + /* adb400 reset clear */ + if ((dev_bitmap & DEV_BMAP_PCIE_BLK) != 0) + lpcm_sysoc_reset_clear(RST_TYPE_BUS, RST_PCIE_TOP); + + if ((dev_bitmap & DEV_BMAP_PCIE0) != 0) + lpcm_sysoc_reset_clear( + RST_TYPE_BUS, RST_PCIE0); /* PCIe#0 PowerOnReset */ + + if ((dev_bitmap & DEV_BMAP_PCIE1) != 0) + lpcm_sysoc_reset_clear( + RST_TYPE_BUS, RST_PCIE1); /* PCIe#1 PowerOnReset */ + + if ((dev_bitmap & DEV_BMAP_DMA_BLK) != 0) + lpcm_sysoc_reset_clear(RST_TYPE_BUS, RST_DMA); + + /* reset clear */ + if ((dev_bitmap & DEV_BMAP_PCIE0) != 0) + lpcm_sysoc_reset_clear(RST_TYPE_WO_BUS, RST_PCIE0); /* PCIe#0 Link */ + + if ((dev_bitmap & DEV_BMAP_PCIE1) != 0) + lpcm_sysoc_reset_clear(RST_TYPE_WO_BUS, RST_PCIE1); /* PCIe#1 Link */ + + if ((dev_bitmap & (DEV_BMAP_DDR0 | DEV_BMAP_DDR1)) != 0) + lpcm_sysoc_reset_clear(RST_TYPE_ALL, RST_DDR); + + /* set TransactionSW */ + SYNQUACER_DEV_LOG_INFO("[PowerDomain] Opening transaction switch\n"); + + FOR_EACH_TRANSW_REG(i) + { + SYNQUACER_DEV_LOG_DEBUG( + "[PowerDomain] Opening transaction switch + %d\n", i); + + set_transactionsw_off(TRANSW_ADDR(i), transw_reg_bitmap[i]); + + SYNQUACER_DEV_LOG_DEBUG( + "[PowerDomain] Finished opening transaction " + "switch + %d\n", + i); + } + SYNQUACER_DEV_LOG_INFO("[PowerDomain] Finished transaction switch\n"); + + SYNQUACER_DEV_LOG_INFO("[PowerDomain] PowerDomain All-ON finished.\n"); + + /* sni-ppu all on */ + FOR_EACH_PPU_INFO(i) + { + if ((sni_ppu_info[i].dev_bitmap & dev_bitmap) == 0) + continue; + + r = change_power_state(sni_ppu_info[i].no, PPU_PP_ON, 1, 1, 0); + if (r != 0) { + SYNQUACER_DEV_LOG_ERROR( + "[PPU] powerdomain error. sni-ppu%d on-process.\n", + sni_ppu_info[i].no); + } + } + + /* ppu on-process check */ + FOR_EACH_PPU_INFO(i) + { + if ((sni_ppu_info[i].dev_bitmap & dev_bitmap) == 0) + continue; + + for (j = 0; j < PD_TIMEOUT_COUNT; j++) { + if ((read_power_status(sni_ppu_info[i].no) & PPU_STATUS_MASK) == + PPU_PP_ON) { + break; + } + osDelay(PD_CHECK_CYCLE_MS); + } + if (j >= PD_TIMEOUT_COUNT) { + SYNQUACER_DEV_LOG_ERROR( + "[PPU] powerdomain error. sni-ppu%d status " + "timeout.\n", + sni_ppu_info[i].no); + } + } +} + +uint32_t pmu_wait(uint32_t pmu_bitmap, bool on) +{ + uint32_t i, status; + + for (i = 0; i < PD_TIMEOUT_COUNT; i++) { + status = on ? ~pmu_read_pd_power_status() : pmu_read_pd_power_status(); + if ((status & pmu_bitmap) == 0) + break; + + osDelay(PD_CHECK_CYCLE_MS); + } + + return (status & pmu_bitmap); +} + +static void power_domain_on(uint32_t dev_bitmap) +{ + sni_power_domain_on_mp(dev_bitmap); +} + +void power_domain_coldboot(void) +{ + SYNQUACER_DEV_LOG_INFO("[SYSTEM] Initializing power domain\n"); + sni_power_domain_workaround_mp(); + power_domain_on(PD_PRESET_COLDBOOT); +} diff --git a/product/synquacer/module/synquacer_system/src/sysdef_option.c b/product/synquacer/module/synquacer_system/src/sysdef_option.c new file mode 100644 index 000000000..32e9513d7 --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/sysdef_option.c @@ -0,0 +1,95 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include + +#define SYNQUACER_CHIP_VER_MP UINT32_C(1) + +static const uint32_t nic_config_mp[NIC_CONFIG_NUM] = { + 1, NIC_SETUP_SKIP, NIC_SETUP_SKIP, 1, 0x7, END_OF_NIC_LIST +}; + +static struct sysdef_option { + uint32_t clear_clkforce; /* Value to be set to CLKFORCE_SET register */ + const uint32_t *scbm_mv_nic_config; + char *chip_version; + const struct sysdef_option_gpio_desc *gpio_desc_p; + uint32_t gpio_desc_num; + bool ap_reboot_enable; + uint32_t i2c_for_spd_read_addr; + uint32_t sensor_num; +} sysdef_option; + +static const struct sysdef_option_gpio_desc gpio_desc_synquacer_mp[] = { + { 14 /* pin_no */, true /* inv */, "pcie1-ep-detected" /* str */ } +}; + +uint32_t sysdef_option_get_clear_clkforce(void) +{ + return sysdef_option.clear_clkforce; +} + +bool sysdef_option_get_ap_reboot_enable(void) +{ + return sysdef_option.ap_reboot_enable; +} + +const uint32_t *sysdef_option_get_scbm_mv_nic_config(void) +{ + return sysdef_option.scbm_mv_nic_config; +} + +char *sysdef_option_get_chip_version(void) +{ + return sysdef_option.chip_version; +} + +uint32_t sysdef_option_get_gpio_desc( + const struct sysdef_option_gpio_desc **gpio_desc_pp) +{ + if (gpio_desc_pp == NULL) + return 0; + + *gpio_desc_pp = sysdef_option.gpio_desc_p; + return sysdef_option.gpio_desc_num; +} + +uint32_t sysdef_option_get_i2c_for_spd_read_addr(void) +{ + return sysdef_option.i2c_for_spd_read_addr; +} + +#define CMN_ST2_OFFSET UINT32_C(0x7b4) + +uint32_t fw_get_chip_ver(void) +{ + return SYNQUACER_CHIP_VER_MP; +} + +uint32_t sysdef_option_get_sensor_num(void) +{ + return sysdef_option.sensor_num; +} + +void sysdef_option_init_synquacer(void) +{ + sysdef_option.clear_clkforce = 0x144U; + sysdef_option.scbm_mv_nic_config = nic_config_mp; + sysdef_option.chip_version = "2"; + sysdef_option.gpio_desc_p = gpio_desc_synquacer_mp; + sysdef_option.gpio_desc_num = FWK_ARRAY_SIZE(gpio_desc_synquacer_mp); + sysdef_option.ap_reboot_enable = false; + sysdef_option.i2c_for_spd_read_addr = I2C_MP_START_ADDR; + sysdef_option.sensor_num = 7; +} diff --git a/product/synquacer/module/synquacer_system/src/sysoc.c b/product/synquacer/module/synquacer_system/src/sysoc.c new file mode 100644 index 000000000..2eb758fd5 --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/sysoc.c @@ -0,0 +1,380 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#define MAIN_BUS_RESET_BIT (0x1) + +#define REG_ADDR_RSTSTA (0) +#define REG_ADDR_RSTSET (0x4U) +#define REG_ADDR_RSTCLR (0x8U) + +#define SYSOC_WAIT_TIME_MS 1U +#define SYSOC_WAIT_NUM 500 + +#define SYSOC_OFFSET_RESET_STATUS (0) +#define SYSOC_OFFSET_RESET (4) +#define SYSOC_OFFSET_RESET_CLEAR (8) + +#define LPCM_OFFSET_CONTROL (0) +#define LPCM_OFFSET_MON (4) + +#define LPCM_OFFSET_NUM (8) + +static const struct { + uint32_t block_sysoc; + uint32_t block_lpcm; + uint32_t bus_sysoc; + uint32_t bus_lpcm; + uint32_t addr_sysoc_blk; + uint32_t addr_sysoc_bus; + uint32_t addr_lpcm; +} reset_info[] = RESET_INFO; + +void sysoc_set_reset(uint32_t sysoc_addr, uint32_t value) +{ + if ((void *)sysoc_addr == NULL) + return; + + writel((sysoc_addr + REG_ADDR_RSTSET), value); +} + +void sysoc_clr_reset(uint32_t sysoc_addr, uint32_t value) +{ + if ((void *)sysoc_addr == NULL) + return; + + writel((sysoc_addr + REG_ADDR_RSTCLR), value); +} + +uint32_t sysoc_read_reset_status(uint32_t sysoc_addr) +{ + if ((void *)sysoc_addr == NULL) + return 0; + + return readl(sysoc_addr + REG_ADDR_RSTSTA); +} + +int sysoc_wait_status_change( + uint32_t sysoc_addr, + bool reset_set_flag, + uint32_t set_bit) +{ + uint32_t i; + uint32_t wait_bit; + int ret; + + if ((void *)sysoc_addr == NULL) + return FWK_E_PARAM; + + if (reset_set_flag) + wait_bit = set_bit; + else + wait_bit = 0; + + /* wait ppu power status change */ + for (i = 0, ret = FWK_E_TIMEOUT; i < SYSOC_WAIT_NUM; i++) { + if ((readl(sysoc_addr + REG_ADDR_RSTSTA) & set_bit) == wait_bit) { + ret = FWK_SUCCESS; + break; + } + /* sleep for wait status change */ + if (osDelay(SYSOC_WAIT_TIME_MS) != osOK) { + /* sleep error */ + return FWK_E_OS; + } + } + return ret; +} + +static void sysoc_reset(uint32_t addr_head, uint32_t bitmap) +{ + writel(addr_head + SYSOC_OFFSET_RESET, bitmap); +} + +static void sysoc_reset_clear(uint32_t addr_head, uint32_t bitmap) +{ + writel(addr_head + SYSOC_OFFSET_RESET_CLEAR, bitmap); +} + +static void lpcm_reset(uint32_t addr_head, uint32_t bitmap) +{ + int i; + + for (i = 0; i < LPCM_OFFSET_NUM; i++) { + if ((bitmap & 1) == 1) + writel(addr_head + (i * 8), 0); + + bitmap >>= 1; + } +} + +static void lpcm_reset_clear(uint32_t addr_head, uint32_t bitmap) +{ + int i; + + for (i = 0; i < LPCM_OFFSET_NUM; i++) { + if ((bitmap & 1) == 1) + writel(addr_head + (i * 8), 1); + + bitmap >>= 1; + } +} + +static uint32_t sysoc_reset_status(uint32_t addr_head, uint32_t bitmap) +{ + return readl(addr_head + SYSOC_OFFSET_RESET_STATUS) & bitmap; +} + +static uint32_t lpcm_reset_status(uint32_t addr_head, uint32_t bitmap) +{ + int i, status_bitmap, b; + status_bitmap = 0; + + for (i = 0; i < LPCM_OFFSET_NUM; i++) { + if ((bitmap & 1) == 1) { + b = readl(addr_head + (i * 8) + LPCM_OFFSET_MON) & 1; + status_bitmap |= b << i; + } + bitmap >>= 1; + } + return status_bitmap; +} + +#define RESET_TIMEOUT_MS 100 +#define RESET_CHECK_CYCLE_MS 1 + +void lpcm_sysoc_reset(RST_TYPE_t type, RST_BLOCK block) +{ + uint32_t lpcm_bitmap, sysoc_bitmap_blk, sysoc_bitmap_bus; + uint32_t status_check_num, i, r; + + lpcm_bitmap = 0; + sysoc_bitmap_blk = 0; + sysoc_bitmap_bus = 0; + + status_check_num = (RESET_TIMEOUT_MS / RESET_CHECK_CYCLE_MS); + + if (type != RST_TYPE_BUS) { + sysoc_bitmap_blk |= reset_info[block].block_sysoc; + lpcm_bitmap |= reset_info[block].block_lpcm; + } + if (type != RST_TYPE_WO_BUS) { + sysoc_bitmap_bus |= reset_info[block].bus_sysoc; + lpcm_bitmap |= reset_info[block].bus_lpcm; + } + + if (lpcm_bitmap != 0) + lpcm_reset(reset_info[block].addr_lpcm, lpcm_bitmap); + + if (sysoc_bitmap_bus != 0) + sysoc_reset(reset_info[block].addr_sysoc_bus, sysoc_bitmap_bus); + + if (sysoc_bitmap_blk != 0) + sysoc_reset(reset_info[block].addr_sysoc_blk, sysoc_bitmap_blk); + + if (lpcm_bitmap != 0) { + for (i = 0; i < status_check_num; i++) { + r = lpcm_reset_status(reset_info[block].addr_lpcm, lpcm_bitmap); + if (r == 0) + break; + + osDelay(RESET_CHECK_CYCLE_MS); + } + if (i == status_check_num) { + SYNQUACER_DEV_LOG_ERROR( + "[LPCM] Reset timeout.(%dms, %08x)\n", + RESET_TIMEOUT_MS, + reset_info[block].addr_lpcm); + } + } + + if (sysoc_bitmap_bus != 0) { + for (i = 0; i < status_check_num; i++) { + r = sysoc_reset_status( + reset_info[block].addr_sysoc_bus, sysoc_bitmap_bus); + if (r == sysoc_bitmap_bus) + break; + + osDelay(RESET_CHECK_CYCLE_MS); + } + if (i == status_check_num) { + SYNQUACER_DEV_LOG_ERROR( + "[SYSOC] Reset timeout.(%dms, %08x)\n", + RESET_TIMEOUT_MS, + reset_info[block].addr_sysoc_bus); + } + } + + if (sysoc_bitmap_blk != 0) { + for (i = 0; i < status_check_num; i++) { + r = sysoc_reset_status( + reset_info[block].addr_sysoc_blk, sysoc_bitmap_blk); + if (r == sysoc_bitmap_blk) + break; + + osDelay(RESET_CHECK_CYCLE_MS); + } + if (i == status_check_num) { + SYNQUACER_DEV_LOG_ERROR( + "[SYSOC] Reset timeout.(%dms, %08x)\n", + RESET_TIMEOUT_MS, + reset_info[block].addr_sysoc_blk); + } + } +} + +void lpcm_sysoc_reset_clear(RST_TYPE_t type, RST_BLOCK block) +{ + uint32_t lpcm_bitmap, sysoc_bitmap_blk, sysoc_bitmap_bus; + uint32_t status_check_num, i, r; + + lpcm_bitmap = 0; + sysoc_bitmap_blk = 0; + sysoc_bitmap_bus = 0; + + status_check_num = (RESET_TIMEOUT_MS / RESET_CHECK_CYCLE_MS); + + if (type != RST_TYPE_BUS) { + sysoc_bitmap_blk |= reset_info[block].block_sysoc; + lpcm_bitmap |= reset_info[block].block_lpcm; + } + if (type != RST_TYPE_WO_BUS) { + sysoc_bitmap_bus |= reset_info[block].bus_sysoc; + lpcm_bitmap |= reset_info[block].bus_lpcm; + } + + if (sysoc_bitmap_blk != 0) + sysoc_reset_clear(reset_info[block].addr_sysoc_blk, sysoc_bitmap_blk); + + if (sysoc_bitmap_bus != 0) + sysoc_reset_clear(reset_info[block].addr_sysoc_bus, sysoc_bitmap_bus); + + if (lpcm_bitmap != 0) + lpcm_reset_clear(reset_info[block].addr_lpcm, lpcm_bitmap); + + if (sysoc_bitmap_blk != 0) { + for (i = 0; i < status_check_num; i++) { + r = sysoc_reset_status( + reset_info[block].addr_sysoc_blk, sysoc_bitmap_blk); + if (r == 0) + break; + + osDelay(RESET_CHECK_CYCLE_MS); + } + if (i == status_check_num) { + SYNQUACER_DEV_LOG_ERROR( + "[SYSOC] Reset clear timeout.(%dms, %08x)\n", + RESET_TIMEOUT_MS, + reset_info[block].addr_sysoc_blk); + } + } + + if (sysoc_bitmap_bus != 0) { + for (i = 0; i < status_check_num; i++) { + r = sysoc_reset_status( + reset_info[block].addr_sysoc_bus, sysoc_bitmap_bus); + if (r == 0) + break; + + osDelay(RESET_CHECK_CYCLE_MS); + } + if (i == status_check_num) { + SYNQUACER_DEV_LOG_ERROR( + "[SYSOC] Reset clear timeout.(%dms, %08x)\n", + RESET_TIMEOUT_MS, + reset_info[block].addr_sysoc_bus); + } + } + + if (lpcm_bitmap != 0) { + for (i = 0; i < status_check_num; i++) { + r = lpcm_reset_status(reset_info[block].addr_lpcm, lpcm_bitmap); + if (r == lpcm_bitmap) + break; + + osDelay(RESET_CHECK_CYCLE_MS); + } + if (i == status_check_num) { + SYNQUACER_DEV_LOG_ERROR( + "[LPCM] Reset clear timeout.(%dms, %08x)\n", + RESET_TIMEOUT_MS, + reset_info[block].addr_lpcm); + } + } +} + +void bus_sysoc_init(void) +{ + int result; + uint32_t value; + + (void)result; + + value = sysoc_read_reset_status(CONFIG_SOC_REG_ADDR_SYSOC_BUS_TOP); + if (value == 0) + return; /* reset bit not active */ + + /* reset set only active bit */ + sysoc_clr_reset( + CONFIG_SOC_REG_ADDR_SYSOC_BUS_TOP, (MAIN_BUS_RESET_BIT & value)); + result = sysoc_wait_status_change( + CONFIG_SOC_REG_ADDR_SYSOC_BUS_TOP, false, MAIN_BUS_RESET_BIT); + + assert(result == FWK_SUCCESS); +} + +#define CONFIG_SOC_PCIEB_SYSOC_REG_BASE UINT32_C(0x78240000) + +/* configure PCIEB SYSOC as secure */ +void pcie_wrapper_configure_pcieb_sysoc(void) +{ + const struct { + uint32_t offset; + uint32_t value; + } pcieb_sysoc_config[] = { + { 0x00, 0 }, /* CFG_CTTW */ + { 0x04, 0 }, /* CFG_NORMALIZE */ + { 0x08, 0 }, /* INTEG_SEC_OVERRIDE */ + { 0x0C, 0 }, /* SYSBARDISABLE_TBU */ + { 0x10, 0 }, /* WSB_NS */ + { 0x14, 0 }, /* RSB_NS */ + { 0x18, 0 }, /* AWDOMAIN */ + { 0x1C, 0 } /* ARDOMAIN */ + }; + + size_t i; + + for (i = 0; i < FWK_ARRAY_SIZE(pcieb_sysoc_config); i++) { + writel( + CONFIG_SOC_PCIEB_SYSOC_REG_BASE + pcieb_sysoc_config[i].offset, + pcieb_sysoc_config[i].value); + } +} + +void pcie_wrapper_tweak_slv_axmisc_info_tph(uint32_t tweak) +{ + writel(0x7FFF0080, tweak); +} + +void pcie_wrapper_configure(void) +{ + pcie_wrapper_configure_pcieb_sysoc(); + pcie_wrapper_tweak_slv_axmisc_info_tph( + CONFIG_SCB_TWEAK_PCIE_TLP_BE_OVERRIDE); +} diff --git a/product/synquacer/module/synquacer_system/src/thermal_sensor.c b/product/synquacer/module/synquacer_system/src/thermal_sensor.c new file mode 100644 index 000000000..86d9ffa6c --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/thermal_sensor.c @@ -0,0 +1,58 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include + +#define DELAY_COUNTER 10 + +int thermal_enable(void) +{ + int32_t sensor_num = sysdef_option_get_sensor_num(); + int32_t i = 0; + + SYNQUACER_DEV_LOG_INFO("[THERMAL] Thermal enable start\n"); + writel(THERMAL_BASE_ADDRESS + THERMAL_ALLCONFIG_OFFSET, 0); + for (i = 0; i < sensor_num; i++) { + uint32_t sensor_offset = THERMAL_SENSOR_BASE(i); + + writel(sensor_offset + THERMAL_TS_EN_OFFSET, THERMAL_ENABLE); + if (readl(sensor_offset + THERMAL_TS_EN_OFFSET) == 0) { + SYNQUACER_DEV_LOG_INFO( + "[THERMAL] Enable individual sensor #%x fail\n", i); + return FWK_E_DEVICE; + } + + writel(sensor_offset + THERMAL_TS_RESET_OFFSET, THERMAL_ENABLE); + if (readl(sensor_offset + THERMAL_TS_RESET_OFFSET) == 0) { + SYNQUACER_DEV_LOG_INFO( + "[THERMAL] Reset individual sensor #%x fail\n", i); + return FWK_E_DEVICE; + } + } + + for (i = 0; i < sensor_num; i++) { + uint32_t sensor_offset = THERMAL_SENSOR_BASE(i); + int32_t delay_counter; + for (delay_counter = 0; delay_counter < DELAY_COUNTER; + delay_counter++) { + if (readl(sensor_offset + THERMAL_TSDATA_VALID_X_OFFSET) == 1) + break; + + osDelay(1); + } + } + + SYNQUACER_DEV_LOG_INFO("[THERMAL] Thermal enable end\n"); + return FWK_SUCCESS; +} diff --git a/product/synquacer/module/synquacer_system/src/transaction_sw.c b/product/synquacer/module/synquacer_system/src/transaction_sw.c new file mode 100644 index 000000000..4d7b48fcf --- /dev/null +++ b/product/synquacer/module/synquacer_system/src/transaction_sw.c @@ -0,0 +1,68 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#define STATUS_ADDR 4 + +void set_transactionsw_off( + uint32_t transactionsw_reg_addr, + uint32_t disable_bit) +{ + unsigned int intsts; + uint32_t value; + + SYNQUACER_DEV_LOG_DEBUG(" traSW disable_bit = %08x\n", disable_bit); + + DI(intsts); + + /* read transactionsw */ + value = readl(transactionsw_reg_addr); + + /* Clear transationsw disable bit */ + value &= (~disable_bit); + + /* transation sw enable */ + writel(transactionsw_reg_addr, value); + + EI(intsts); + + /* setting wait */ + while ((readl(transactionsw_reg_addr + STATUS_ADDR) & disable_bit) != 0) + continue; +} + +void set_transactionsw_on(uint32_t transactionsw_reg_addr, uint32_t enable_bit) +{ + unsigned int intsts; + uint32_t value; + + SYNQUACER_DEV_LOG_DEBUG(" traSW enable_bit = %08x\n", enable_bit); + + DI(intsts); + + /* read transactionsw */ + value = readl(transactionsw_reg_addr); + + /* Clear transactionsw disable bit */ + value |= (enable_bit); + + /* transaction sw enable */ + writel(transactionsw_reg_addr, value); + + EI(intsts); + + /* setting wait */ + while ((readl(transactionsw_reg_addr + STATUS_ADDR) & enable_bit) != + enable_bit) { + continue; + } +} diff --git a/product/synquacer/product.mk b/product/synquacer/product.mk new file mode 100644 index 000000000..a5348cad9 --- /dev/null +++ b/product/synquacer/product.mk @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_PRODUCT_NAME := synquacer +BS_FIRMWARE_LIST := scp_romfw scp_ramfw +#BS_FIRMWARE_LIST := scp_romfw +#BS_FIRMWARE_LIST := scp_ramfw diff --git a/product/synquacer/scp_ramfw/RTX_Config.h b/product/synquacer/scp_ramfw/RTX_Config.h new file mode 100644 index 000000000..498895f60 --- /dev/null +++ b/product/synquacer/scp_ramfw/RTX_Config.h @@ -0,0 +1,56 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * RTX2 v5 configuration file. + * The file must be called RTX_Config.h as it is included by the an RTX + * file in order to create a object file containing the configuration. + */ + +#ifndef RTX_CONFIG_H +#define RTX_CONFIG_H + +/* System */ +#define OS_DYNAMIC_MEM_SIZE 0 +#define OS_TICK_FREQ 1000 /* Hz */ +#define OS_ROBIN_ENABLE 0 +#define OS_ROBIN_TIMEOUT 0 +#define OS_ISR_FIFO_QUEUE 16 + +/* Thread */ +#define OS_THREAD_OBJ_MEM 0 +#define OS_THREAD_NUM 3 +#define OS_THREAD_DEF_STACK_NUM 0 +#define OS_THREAD_USER_STACK_SIZE 0 +#define OS_STACK_SIZE 200 +#define OS_IDLE_THREAD_STACK_SIZE 200 +#define OS_STACK_CHECK 1 +#define OS_STACK_WATERMARK 0 +#define OS_PRIVILEGE_MODE 1 + +/* Timer */ +#define OS_TIMER_OBJ_MEM 0 +#define OS_TIMER_NUM 1 +#define OS_TIMER_THREAD_PRIO 40 +#define OS_TIMER_THREAD_STACK_SIZE 200 +#define OS_TIMER_CB_QUEUE 4 + +/* Event flags */ +#define OS_EVFLAGS_OBJ_MEM 0 +#define OS_EVFLAGS_NUM 3 + +#define OS_MUTEX_OBJ_MEM 0 +#define OS_MUTEX_NUM 3 +#define OS_SEMAPHORE_OBJ_MEM 0 +#define OS_SEMAPHORE_NUM 3 +#define OS_MEMPOOL_OBJ_MEM 0 +#define OS_MEMPOOL_NUM 3 +#define OS_MEMPOOL_DATA_SIZE 0 +#define OS_MSGQUEUE_OBJ_MEM 0 +#define OS_MSGQUEUE_NUM 3 +#define OS_MSGQUEUE_DATA_SIZE 0 + +#endif /* RTX_CONFIG_H */ diff --git a/product/synquacer/scp_ramfw/config_armv7m_mpu.c b/product/synquacer/scp_ramfw/config_armv7m_mpu.c new file mode 100644 index 000000000..e223febd4 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_armv7m_mpu.c @@ -0,0 +1,62 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define ROM_BASE 0x00000000UL +#define AP_RAM_BASE UINT32_C(0xA4000000) + +static const ARM_MPU_Region_t regions[] = { + { + /* 0x0000_0000 - 0xFFFF_FFFF */ + .RBAR = ARM_MPU_RBAR(0, ROM_BASE), + .RASR = ARM_MPU_RASR( + 1, + ARM_MPU_AP_FULL, + 0, + 1, + 0, + 0, + 0, + ARM_MPU_REGION_SIZE_4GB), + }, + { + /* 0x0000_0000 - 0x1FFF_FFFF */ + .RBAR = ARM_MPU_RBAR(1, ROM_BASE), + .RASR = ARM_MPU_RASR( + 0, + ARM_MPU_AP_FULL, + 0, + 0, + 1, + 1, + 0, + ARM_MPU_REGION_SIZE_512MB), + }, + { + /* 0xA400_0000 - 0xA407_FFFF */ + .RBAR = ARM_MPU_RBAR(2, AP_RAM_BASE), + .RASR = ARM_MPU_RASR( + 0, + ARM_MPU_AP_FULL, + 0, + 0, + 1, + 1, + 0, + ARM_MPU_REGION_SIZE_512KB), + }, +}; + +const struct fwk_module_config config_armv7m_mpu = { + .data = &((struct mod_armv7m_mpu_config){ + .region_count = FWK_ARRAY_SIZE(regions), + .regions = regions, + }), +}; diff --git a/product/synquacer/scp_ramfw/config_ccn512.c b/product/synquacer/scp_ramfw/config_ccn512.c new file mode 100644 index 000000000..6ba007646 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_ccn512.c @@ -0,0 +1,22 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * CCN512 module + */ +struct fwk_module_config config_ccn512 = { + .get_element_table = NULL, + .data = &((struct mod_ccn512_module_config){ + .reg_base = (ccn512_reg_t *)CCN512_BASE, + }), +}; diff --git a/product/synquacer/scp_ramfw/config_clock.c b/product/synquacer/scp_ramfw/config_clock.c new file mode 100644 index 000000000..8e7817626 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_clock.c @@ -0,0 +1,10 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const struct fwk_module_config config_clock = { 0 }; diff --git a/product/synquacer/scp_ramfw/config_clock.h b/product/synquacer/scp_ramfw/config_clock.h new file mode 100644 index 000000000..fb17807a2 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_clock.h @@ -0,0 +1,118 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_CLOCK_H +#define CONFIG_CLOCK_H + +/* + * PIK clock indexes. + */ +enum clock_pik_idx { + CLOCK_PIK_IDX_CLUS0_CPUCLK, + CLOCK_PIK_IDX_CLUS0_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS0_ATCLKDBG, + CLOCK_PIK_IDX_CLUS0_PCLKDBG, + CLOCK_PIK_IDX_CLUS0_ACLKCPU, + CLOCK_PIK_IDX_CLUS0_PPUCLK, + CLOCK_PIK_IDX_CLUS0_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS1_CPUCLK, + CLOCK_PIK_IDX_CLUS1_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS1_ATCLKDBG, + CLOCK_PIK_IDX_CLUS1_PCLKDBG, + CLOCK_PIK_IDX_CLUS1_ACLKCPU, + CLOCK_PIK_IDX_CLUS1_PPUCLK, + CLOCK_PIK_IDX_CLUS1_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS2_CPUCLK, + CLOCK_PIK_IDX_CLUS2_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS2_ATCLKDBG, + CLOCK_PIK_IDX_CLUS2_PCLKDBG, + CLOCK_PIK_IDX_CLUS2_ACLKCPU, + CLOCK_PIK_IDX_CLUS2_PPUCLK, + CLOCK_PIK_IDX_CLUS2_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS3_CPUCLK, + CLOCK_PIK_IDX_CLUS3_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS3_ATCLKDBG, + CLOCK_PIK_IDX_CLUS3_PCLKDBG, + CLOCK_PIK_IDX_CLUS3_ACLKCPU, + CLOCK_PIK_IDX_CLUS3_PPUCLK, + CLOCK_PIK_IDX_CLUS3_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS4_CPUCLK, + CLOCK_PIK_IDX_CLUS4_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS4_ATCLKDBG, + CLOCK_PIK_IDX_CLUS4_PCLKDBG, + CLOCK_PIK_IDX_CLUS4_ACLKCPU, + CLOCK_PIK_IDX_CLUS4_PPUCLK, + CLOCK_PIK_IDX_CLUS4_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS5_CPUCLK, + CLOCK_PIK_IDX_CLUS5_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS5_ATCLKDBG, + CLOCK_PIK_IDX_CLUS5_PCLKDBG, + CLOCK_PIK_IDX_CLUS5_ACLKCPU, + CLOCK_PIK_IDX_CLUS5_PPUCLK, + CLOCK_PIK_IDX_CLUS5_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS6_CPUCLK, + CLOCK_PIK_IDX_CLUS6_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS6_ATCLKDBG, + CLOCK_PIK_IDX_CLUS6_PCLKDBG, + CLOCK_PIK_IDX_CLUS6_ACLKCPU, + CLOCK_PIK_IDX_CLUS6_PPUCLK, + CLOCK_PIK_IDX_CLUS6_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS7_CPUCLK, + CLOCK_PIK_IDX_CLUS7_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS7_ATCLKDBG, + CLOCK_PIK_IDX_CLUS7_PCLKDBG, + CLOCK_PIK_IDX_CLUS7_ACLKCPU, + CLOCK_PIK_IDX_CLUS7_PPUCLK, + CLOCK_PIK_IDX_CLUS7_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS8_CPUCLK, + CLOCK_PIK_IDX_CLUS8_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS8_ATCLKDBG, + CLOCK_PIK_IDX_CLUS8_PCLKDBG, + CLOCK_PIK_IDX_CLUS8_ACLKCPU, + CLOCK_PIK_IDX_CLUS8_PPUCLK, + CLOCK_PIK_IDX_CLUS8_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS9_CPUCLK, + CLOCK_PIK_IDX_CLUS9_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS9_ATCLKDBG, + CLOCK_PIK_IDX_CLUS9_PCLKDBG, + CLOCK_PIK_IDX_CLUS9_ACLKCPU, + CLOCK_PIK_IDX_CLUS9_PPUCLK, + CLOCK_PIK_IDX_CLUS9_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS10_CPUCLK, + CLOCK_PIK_IDX_CLUS10_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS10_ATCLKDBG, + CLOCK_PIK_IDX_CLUS10_PCLKDBG, + CLOCK_PIK_IDX_CLUS10_ACLKCPU, + CLOCK_PIK_IDX_CLUS10_PPUCLK, + CLOCK_PIK_IDX_CLUS10_PPUCLK_DIV2, + + CLOCK_PIK_IDX_CLUS11_CPUCLK, + CLOCK_PIK_IDX_CLUS11_CPUCLK_DIV2, + CLOCK_PIK_IDX_CLUS11_ATCLKDBG, + CLOCK_PIK_IDX_CLUS11_PCLKDBG, + CLOCK_PIK_IDX_CLUS11_ACLKCPU, + CLOCK_PIK_IDX_CLUS11_PPUCLK, + CLOCK_PIK_IDX_CLUS11_PPUCLK_DIV2, + + CLOCK_PIK_IDX_DEBUG_TRACECLK, + CLOCK_PIK_IDX_DEBUG_ATCLKDBG, + CLOCK_PIK_IDX_DEBUG_PCLKDBG, + + CLOCK_PIK_IDX_COUNT +}; + +#endif /* CONFIG_CLOCK_H */ diff --git a/product/synquacer/scp_ramfw/config_css_clock.c b/product/synquacer/scp_ramfw/config_css_clock.c new file mode 100644 index 000000000..d950d71ad --- /dev/null +++ b/product/synquacer/scp_ramfw/config_css_clock.c @@ -0,0 +1,28 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct fwk_element css_clock_element_table[] = { + [0] = { 0 }, +}; + +static const struct fwk_element *css_clock_get_element_table(fwk_id_t module_id) +{ + return css_clock_element_table; +} + +const struct fwk_module_config config_css_clock = { + .get_element_table = css_clock_get_element_table, +}; diff --git a/product/synquacer/scp_ramfw/config_f_i2c.c b/product/synquacer/scp_ramfw/config_f_i2c.c new file mode 100644 index 000000000..5585d888e --- /dev/null +++ b/product/synquacer/scp_ramfw/config_f_i2c.c @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* Configuration of the F_I2C module. */ +const struct fwk_module_config config_f_i2c = { + .get_element_table = NULL, +}; diff --git a/product/synquacer/scp_ramfw/config_hsspi.c b/product/synquacer/scp_ramfw/config_hsspi.c new file mode 100644 index 000000000..4edb33cec --- /dev/null +++ b/product/synquacer/scp_ramfw/config_hsspi.c @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* Configuration of the HSSPI module. */ +const struct fwk_module_config config_hsspi = { + .get_element_table = NULL, +}; diff --git a/product/synquacer/scp_ramfw/config_log_f_uart3.c b/product/synquacer/scp_ramfw/config_log_f_uart3.c new file mode 100644 index 000000000..0b4d2d9ce --- /dev/null +++ b/product/synquacer/scp_ramfw/config_log_f_uart3.c @@ -0,0 +1,57 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * F_UART3 module + */ +static const struct fwk_element f_uart3_element_desc_table[] = { + [0] = { + .name = "F_UART3", + .data = &((struct mod_f_uart3_device_config) { + .reg_base = F_UART3_BASE_ADDR, + .dla_reg_base = F_UART3_BASE_ADDR, + .baud_rate_bps = 115200, + .clock_rate_hz = 62500 * FWK_KHZ, + .clock_id = FWK_ID_NONE_INIT, + }), + }, + [1] = { 0 }, +}; + +static const struct fwk_element *get_f_uart3_table(fwk_id_t module_id) +{ + return f_uart3_element_desc_table; +} + +struct fwk_module_config config_f_uart3 = { + .get_element_table = get_f_uart3_table, +}; + +/* + * Log module + */ +static const struct mod_log_config log_data = { + .device_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_F_UART3, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_F_UART3, 0), + .log_groups = MOD_LOG_GROUP_ERROR | MOD_LOG_GROUP_INFO | + MOD_LOG_GROUP_WARNING | MOD_LOG_GROUP_DEBUG, + .banner = + FWK_BANNER_SCP FWK_BANNER_RAM_FIRMWARE BUILD_VERSION_DESCRIBE_STRING + "\n", +}; + +struct fwk_module_config config_log = { + .data = &log_data, +}; diff --git a/product/synquacer/scp_ramfw/config_log_pl011.c b/product/synquacer/scp_ramfw/config_log_pl011.c new file mode 100644 index 000000000..57d191902 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_log_pl011.c @@ -0,0 +1,56 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * PL011 module + */ +static const struct fwk_element pl011_element_desc_table[] = { + [0] = { + .name = "scp-uart0", + .data = &((struct mod_pl011_device_config) { + .reg_base = SCP_UART_BASE, + .baud_rate_bps = 115200, + .clock_rate_hz = 62500 * FWK_KHZ, + .clock_id = FWK_ID_NONE_INIT, + }), + }, + [1] = { 0 }, +}; + +static const struct fwk_element *get_pl011_table(fwk_id_t module_id) +{ + return pl011_element_desc_table; +} + +struct fwk_module_config config_pl011 = { + .get_element_table = get_pl011_table, +}; + +/* + * Log module + */ +static const struct mod_log_config log_data = { + .device_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PL011, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PL011, 0), + .log_groups = MOD_LOG_GROUP_ERROR | MOD_LOG_GROUP_INFO | + MOD_LOG_GROUP_WARNING | MOD_LOG_GROUP_DEBUG, + .banner = + FWK_BANNER_SCP FWK_BANNER_RAM_FIRMWARE BUILD_VERSION_DESCRIBE_STRING + "\n", +}; + +struct fwk_module_config config_log = { + .data = &log_data, +}; diff --git a/product/synquacer/scp_ramfw/config_mhu.c b/product/synquacer/scp_ramfw/config_mhu.c new file mode 100644 index 000000000..28092f2fd --- /dev/null +++ b/product/synquacer/scp_ramfw/config_mhu.c @@ -0,0 +1,43 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +static const struct fwk_element mhu_element_table[] = { + [SCP_SYNQUACER_MHU_DEVICE_IDX_SCP_AP_S] = { + .name = "MHU_SCP_AP_S", + .sub_element_count = 1, + .data = &((struct mod_mhu_device_config) { + .irq = MHU_SEC_SCP_AP_IRQn, + .in = MHU_AP_TO_SCP_S(0), + .out = MHU_SCP_TO_AP_S(0), + }) }, + [SCP_SYNQUACER_MHU_DEVICE_IDX_SCP_AP_NS] = { + .name = "MHU_SCP_AP_NS", + .sub_element_count = 1, + .data = &((struct mod_mhu_device_config) { + .irq = MHU_NON_SEC_SCP_AP_IRQn, + .in = MHU_AP_TO_SCP_NS(0), + .out = MHU_SCP_TO_AP_NS(0), + }) }, + [SCP_SYNQUACER_MHU_DEVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *mhu_get_element_table(fwk_id_t module_id) +{ + return mhu_element_table; +} + +const struct fwk_module_config config_mhu = { + .get_element_table = mhu_get_element_table, +}; diff --git a/product/synquacer/scp_ramfw/config_mhu.h b/product/synquacer/scp_ramfw/config_mhu.h new file mode 100644 index 000000000..946dc1ad3 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_mhu.h @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MHU_H +#define CONFIG_MHU_H + +enum scp_synquacer_mhu_device_idx { + SCP_SYNQUACER_MHU_DEVICE_IDX_SCP_AP_S, + SCP_SYNQUACER_MHU_DEVICE_IDX_SCP_AP_NS, + SCP_SYNQUACER_MHU_DEVICE_IDX_COUNT +}; + +#endif /* CONFIG_MHU_H */ diff --git a/product/synquacer/scp_ramfw/config_pik_clock.c b/product/synquacer/scp_ramfw/config_pik_clock.c new file mode 100644 index 000000000..ba08a39ce --- /dev/null +++ b/product/synquacer/scp_ramfw/config_pik_clock.c @@ -0,0 +1,1148 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PIK_DEBUG_TRACECLK_CTRL UINT32_C(0x0810) +#define PIK_DEBUG_TRACECLK_DIV1 UINT32_C(0x0814) +#define PIK_DEBUG_PCLKDBG_CTRL UINT32_C(0x0820) +#define PIK_DEBUG_ATCLKDBG_CTRL UINT32_C(0x0830) +#define PIK_DEBUG_ATCLKDBG_DIV1 UINT32_C(0x0834) + +/* + * Rate lookup tables + */ +static const struct mod_pik_clock_rate rate_table_dbgtraceclk[] = { + { + .rate = 125 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 125 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_dbgatclk[] = { + { + .rate = 500 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 500 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_dbgpclk[] = { + { + .rate = 500 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 500 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_clus_cpuclk[] = { + { + .rate = 1000 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 1000 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_clus_atclkdbg[] = { + { + .rate = 500 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 500 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_clus_pclkdbg[] = { + { + .rate = 500 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 500 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_clus_aclkcpu[] = { + { + .rate = 1000 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 1000 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_clus_ppuclk[] = { + { + .rate = 125 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSREFCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 125 * FWK_MHZ), + }, +}; + +static const struct fwk_element pik_clock_element_table[] = { + [CLOCK_PIK_IDX_CLUS0_CPUCLK] = { + .name = "CLUS0", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(0)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(0)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS0_CPUCLK_DIV2] = { + .name = "CLUS0_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(0)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(0)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS0_ATCLKDBG] = { + .name = "CLUS0_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(0)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS0_PCLKDBG] = { + .name = "CLUS0_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(0)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS0_ACLKCPU] = { + .name = "CLUS0_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(0)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS0_PPUCLK] = { + .name = "CLUS0_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(0)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(0)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS0_PPUCLK_DIV2] = { + .name = "CLUS0_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(0)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(0)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS1_CPUCLK] = { + .name = "CLUS1", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(1)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(1)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS1_CPUCLK_DIV2] = { + .name = "CLUS1_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(1)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(1)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS1_ATCLKDBG] = { + .name = "CLUS1_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(1)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS1_PCLKDBG] = { + .name = "CLUS1_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(1)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS1_ACLKCPU] = { + .name = "CLUS1_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(1)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS1_PPUCLK] = { + .name = "CLUS1_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(1)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(1)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS1_PPUCLK_DIV2] = { + .name = "CLUS1_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(1)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(1)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS2_CPUCLK] = { + .name = "CLUS2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(2)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(2)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS2_CPUCLK_DIV2] = { + .name = "CLUS2_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(2)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(2)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS2_ATCLKDBG] = { + .name = "CLUS2_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(2)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS2_PCLKDBG] = { + .name = "CLUS2_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(2)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS2_ACLKCPU] = { + .name = "CLUS2_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(2)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS2_PPUCLK] = { + .name = "CLUS2_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(2)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(2)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS2_PPUCLK_DIV2] = { + .name = "CLUS2_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(2)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(2)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS3_CPUCLK] = { + .name = "CLUS3", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(3)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(3)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS3_CPUCLK_DIV2] = { + .name = "CLUS3_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(3)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(3)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS3_ATCLKDBG] = { + .name = "CLUS3_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(3)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS3_PCLKDBG] = { + .name = "CLUS3_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(3)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS3_ACLKCPU] = { + .name = "CLUS3_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(3)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS3_PPUCLK] = { + .name = "CLUS3_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(3)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(3)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS3_PPUCLK_DIV2] = { + .name = "CLUS3_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(3)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(3)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS4_CPUCLK] = { + .name = "CLUS4", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(4)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(4)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS4_CPUCLK_DIV2] = { + .name = "CLUS4_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(4)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(4)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS4_ATCLKDBG] = { + .name = "CLUS4_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(4)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS4_PCLKDBG] = { + .name = "CLUS4_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(4)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS4_ACLKCPU] = { + .name = "CLUS4_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(4)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS4_PPUCLK] = { + .name = "CLUS4_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(4)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(4)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS4_PPUCLK_DIV2] = { + .name = "CLUS4_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(4)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(4)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS5_CPUCLK] = { + .name = "CLUS5", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(5)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(5)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS5_CPUCLK_DIV2] = { + .name = "CLUS5_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(5)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(5)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS5_ATCLKDBG] = { + .name = "CLUS5_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(5)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS5_PCLKDBG] = { + .name = "CLUS5_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(5)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS5_ACLKCPU] = { + .name = "CLUS5_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(5)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS5_PPUCLK] = { + .name = "CLUS5_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(5)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(5)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS5_PPUCLK_DIV2] = { + .name = "CLUS5_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(5)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(5)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS6_CPUCLK] = { + .name = "CLUS6", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(6)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(6)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS6_CPUCLK_DIV2] = { + .name = "CLUS6_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(6)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(6)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS6_ATCLKDBG] = { + .name = "CLUS6_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(6)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS6_PCLKDBG] = { + .name = "CLUS6_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(6)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS6_ACLKCPU] = { + .name = "CLUS6_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(6)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS6_PPUCLK] = { + .name = "CLUS6_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(6)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(6)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS6_PPUCLK_DIV2] = { + .name = "CLUS6_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(6)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(6)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS7_CPUCLK] = { + .name = "CLUS7", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(7)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(7)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS7_CPUCLK_DIV2] = { + .name = "CLUS7_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(7)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(7)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS7_ATCLKDBG] = { + .name = "CLUS7_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(7)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS7_PCLKDBG] = { + .name = "CLUS7_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(7)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS7_ACLKCPU] = { + .name = "CLUS7_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(7)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS7_PPUCLK] = { + .name = "CLUS7_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(7)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(7)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS7_PPUCLK_DIV2] = { + .name = "CLUS7_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(7)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(7)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS8_CPUCLK] = { + .name = "CLUS8", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(8)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(8)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS8_CPUCLK_DIV2] = { + .name = "CLUS8_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(8)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(8)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS8_ATCLKDBG] = { + .name = "CLUS8_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(8)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS8_PCLKDBG] = { + .name = "CLUS8_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(8)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS8_ACLKCPU] = { + .name = "CLUS8_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(8)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS8_PPUCLK] = { + .name = "CLUS8_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(8)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(8)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS8_PPUCLK_DIV2] = { + .name = "CLUS8_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(8)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(8)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS9_CPUCLK] = { + .name = "CLUS9", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(9)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(9)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS9_CPUCLK_DIV2] = { + .name = "CLUS9_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(9)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(9)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS9_ATCLKDBG] = { + .name = "CLUS9_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(9)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS9_PCLKDBG] = { + .name = "CLUS9_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(9)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS9_ACLKCPU] = { + .name = "CLUS9_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(9)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS9_PPUCLK] = { + .name = "CLUS9_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(9)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(9)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS9_PPUCLK_DIV2] = { + .name = "CLUS9_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(9)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(9)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS10_CPUCLK] = { + .name = "CLUS10", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(10)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(10)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS10_CPUCLK_DIV2] = { + .name = "CLUS10_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(10)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(10)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS10_ATCLKDBG] = { + .name = "CLUS10_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(10)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS10_PCLKDBG] = { + .name = "CLUS10_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(10)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS10_ACLKCPU] = { + .name = "CLUS10_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(10)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS10_PPUCLK] = { + .name = "CLUS10_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(10)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(10)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS10_PPUCLK_DIV2] = { + .name = "CLUS10_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(10)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(10)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_CLUS11_CPUCLK] = { + .name = "CLUS11", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(11)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(11)->CPUCLK_DIV1, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS11_CPUCLK_DIV2] = { + .name = "CLUS11_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(11)->CPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(11)->CPUCLK_DIV2, + .rate_table = rate_table_clus_cpuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_cpuclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS11_ATCLKDBG] = { + .name = "CLUS11_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(11)->ATCLKDBG_CTRL, + .rate_table = rate_table_clus_atclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_atclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS11_PCLKDBG] = { + .name = "CLUS11_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(11)->PCLKDBG_CTRL, + .rate_table = rate_table_clus_pclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_pclkdbg), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS11_ACLKCPU] = { + .name = "CLUS11_ACLKCPU", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(11)->ACLKCPU_CTRL, + .rate_table = rate_table_clus_aclkcpu, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_aclkcpu), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS11_PPUCLK] = { + .name = "CLUS11_PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(11)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(11)->PPUCLK_DIV1, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CLUS11_PPUCLK_DIV2] = { + .name = "CLUS11_PPUCLK_DIV2", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_CLUSTER(11)->PPUCLK_CTRL, + .divsys_reg = &PIK_CLUSTER(11)->PPUCLK_DIV2, + .rate_table = rate_table_clus_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_clus_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + + + [CLOCK_PIK_IDX_DEBUG_TRACECLK] = { + .name = "DEBUG_TRACECLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = + (volatile uint32_t *)(PIK_DEBUG_BASE + PIK_DEBUG_TRACECLK_CTRL), + .divsys_reg = + (volatile uint32_t *)(PIK_DEBUG_BASE + PIK_DEBUG_TRACECLK_DIV1), + .rate_table = rate_table_dbgtraceclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_dbgtraceclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_DEBUG_ATCLKDBG] = { + .name = "DEBUG_ATCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = + (volatile uint32_t *)(PIK_DEBUG_BASE + PIK_DEBUG_ATCLKDBG_CTRL), + .divsys_reg = + (volatile uint32_t *)(PIK_DEBUG_BASE + PIK_DEBUG_ATCLKDBG_DIV1), + .rate_table = rate_table_dbgatclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_dbgatclk), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_DEBUG_PCLKDBG] = { + .name = "DEBUG_PCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_SINGLE_SOURCE, + .is_group_member = false, + .control_reg = + (volatile uint32_t *)(PIK_DEBUG_BASE + PIK_DEBUG_PCLKDBG_CTRL), + .rate_table = rate_table_dbgpclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_dbgpclk), + .initial_rate = 500 * FWK_MHZ, + }), + }, + + [CLOCK_PIK_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *pik_clock_get_element_table( + fwk_id_t module_id) +{ + return pik_clock_element_table; +} + +const struct fwk_module_config config_pik_clock = { + .get_element_table = pik_clock_get_element_table, +}; diff --git a/product/synquacer/scp_ramfw/config_power_domain.c b/product/synquacer/scp_ramfw/config_power_domain.c new file mode 100644 index 000000000..bf9ddb0e5 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_power_domain.c @@ -0,0 +1,238 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Maximum power domain name size including the null terminator */ +#define PD_NAME_SIZE 12 + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + */ +static const uint32_t systop_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK +}; + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + */ +static const uint32_t cluster_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK +}; + +/* Mask of the allowed states for a core depending on the cluster states. */ +static const uint32_t core_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK +}; + +/* Power module specific configuration data (none) */ +static const struct mod_power_domain_config synquacer_power_domain_config = { + 0 +}; + +/* Tree position should follow the ascending order */ +static struct fwk_element synquacer_power_domain_static_element_table[] = { + [PD_STATIC_DEV_IDX_CHILD_SYS3] = { + .name = "SYS3", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .tree_pos = MOD_PD_TREE_POS(MOD_PD_LEVEL_1, 0, 0, 12, 0), + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_SYS3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + .allowed_state_mask_table = systop_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(systop_allowed_state_mask_table) }), + }, + [PD_STATIC_DEV_IDX_CHILD_SYS1] = { + .name = "SYS1", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .tree_pos = MOD_PD_TREE_POS(MOD_PD_LEVEL_1, 0, 0, 13, 0), + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_SYS1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + .allowed_state_mask_table = systop_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(systop_allowed_state_mask_table) }), + }, + [PD_STATIC_DEV_IDX_CHILD_SYS2] = { + .name = "SYS2", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .tree_pos = MOD_PD_TREE_POS(MOD_PD_LEVEL_1, 0, 0, 14, 0), + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_SYS2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + .allowed_state_mask_table = systop_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(systop_allowed_state_mask_table) }), + }, + + /* PPU_SYS4 is managed by romfw */ + + [PD_STATIC_DEV_IDX_CHILD_DEBUG] = { + .name = "DEBUG", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .tree_pos = MOD_PD_TREE_POS(MOD_PD_LEVEL_1, 0, 0, 16, 0), + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_DEBUG), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + .allowed_state_mask_table = systop_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(systop_allowed_state_mask_table) }), + }, + [PD_STATIC_DEV_IDX_SYSTOP] = { + .name = "SYSTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_SYSTEM, + .tree_pos = MOD_PD_TREE_POS(MOD_PD_LEVEL_2, 0, 0, 0, 0), + .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYSTEM_POWER), + .api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_SYSTEM_POWER, + MOD_SYSTEM_POWER_API_IDX_PD_DRIVER), + .allowed_state_mask_table = systop_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(systop_allowed_state_mask_table) }), + }, + [PD_STATIC_DEV_IDX_COUNT] = { 0 }, /* Termination entry */ +}; + +static const struct fwk_element *synquacer_power_domain_get_element_table( + fwk_id_t module_id) +{ + struct fwk_element *element_table, *element; + struct mod_power_domain_element_config *pd_config_table, *pd_config; + unsigned int core_idx; + unsigned int cluster_idx; + unsigned int core_count; + unsigned int cluster_count; + unsigned int core_per_cluster_count; + unsigned int element_count = 0; + + core_count = synquacer_core_get_core_count(); + cluster_count = synquacer_core_get_cluster_count(); + core_per_cluster_count = synquacer_core_get_core_per_cluster_count(); + + element_table = fwk_mm_calloc( + cluster_count + core_count + + FWK_ARRAY_SIZE(synquacer_power_domain_static_element_table) + + 1, /* Terminator */ + sizeof(struct fwk_element)); + if (element_table == NULL) + return NULL; + + pd_config_table = fwk_mm_calloc( + (cluster_count + core_count), + sizeof(struct mod_power_domain_element_config)); + if (pd_config_table == NULL) + return NULL; + + /* + * power domain element table should follow the ascending order + * of tree position. + * It means first element must be cluster0_core0, + * last element should be system power element(SYSTOP) + */ + /* prepare core config table */ + for (cluster_idx = 0; cluster_idx < cluster_count; cluster_idx++) { + for (core_idx = 0; core_idx < core_per_cluster_count; core_idx++) { + element = &element_table[element_count]; + pd_config = &pd_config_table[element_count]; + + element->name = fwk_mm_alloc(PD_NAME_SIZE, 1); + if (element->name == NULL) + return NULL; + + snprintf( + (char *)element->name, + PD_NAME_SIZE, + "CLUS%uCORE%u", + cluster_idx, + core_idx); + + element->data = pd_config; + + pd_config->attributes.pd_type = MOD_PD_TYPE_CORE; + pd_config->tree_pos = + MOD_PD_TREE_POS(MOD_PD_LEVEL_0, 0, 0, cluster_idx, core_idx); + pd_config->driver_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, element_count); + pd_config->api_id = FWK_ID_API(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0); + pd_config->allowed_state_mask_table = + core_pd_allowed_state_mask_table; + pd_config->allowed_state_mask_table_size = + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table); + element_count++; + } + } + + /* prepare cluster config table */ + for (cluster_idx = 0; cluster_idx < cluster_count; cluster_idx++) { + element = &element_table[element_count]; + pd_config = &pd_config_table[element_count]; + + element->name = fwk_mm_alloc(PD_NAME_SIZE, 1); + if (element->name == NULL) + return NULL; + + snprintf((char *)element->name, PD_NAME_SIZE, "CLUS%u", cluster_idx); + + element->data = pd_config; + + pd_config->attributes.pd_type = MOD_PD_TYPE_CLUSTER; + pd_config->tree_pos = + MOD_PD_TREE_POS(MOD_PD_LEVEL_1, 0, 0, cluster_idx, 0); + pd_config->driver_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, element_count); + pd_config->api_id = FWK_ID_API(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0); + pd_config->allowed_state_mask_table = + cluster_pd_allowed_state_mask_table; + pd_config->allowed_state_mask_table_size = + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table); + element_count++; + } + + memcpy( + element_table + element_count, + synquacer_power_domain_static_element_table, + sizeof(synquacer_power_domain_static_element_table)); + + return element_table; +} + +/* + * Power module configuration data + */ +const struct fwk_module_config config_power_domain = { + .get_element_table = synquacer_power_domain_get_element_table, + .data = &synquacer_power_domain_config, +}; diff --git a/product/synquacer/scp_ramfw/config_power_domain.h b/product/synquacer/scp_ramfw/config_power_domain.h new file mode 100644 index 000000000..cbcd1b353 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_power_domain.h @@ -0,0 +1,30 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_POWER_DOMAIN_H +#define CONFIG_POWER_DOMAIN_H + +/* + * Power domain indices for the statically defined domains used for: + * - Indexing the domains in the synquacer_power_domain_static_element_table + * - Indexing the SYSTOP children in the power domain tree + * + * When calculating a power domain element index, use the formula: + * core_count + pd_static_dev_idx + */ +enum pd_static_dev_idx { + PD_STATIC_DEV_IDX_CHILD_SYS3, + PD_STATIC_DEV_IDX_CHILD_SYS1, + PD_STATIC_DEV_IDX_CHILD_SYS2, + /* PPU_SYS4 is managed by romfw */ + PD_STATIC_DEV_IDX_CHILD_DEBUG, + PD_STATIC_DEV_IDX_SYSTOP, + + PD_STATIC_DEV_IDX_COUNT +}; + +#endif /* CONFIG_POWER_DOMAIN_H */ diff --git a/product/synquacer/scp_ramfw/config_ppu_v0.h b/product/synquacer/scp_ramfw/config_ppu_v0.h new file mode 100644 index 000000000..fd7184c85 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_ppu_v0.h @@ -0,0 +1,59 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_PPU_V0_H +#define CONFIG_PPU_V0_H + +enum ppu_v0_element_idx { + PPU_V0_ELEMENT_IDX_CLUSTER0_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER0_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER1_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER1_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER2_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER2_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER3_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER3_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER4_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER4_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER5_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER5_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER6_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER6_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER7_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER7_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER8_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER8_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER9_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER9_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER10_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER10_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER11_CPU0, + PPU_V0_ELEMENT_IDX_CLUSTER11_CPU1, + PPU_V0_ELEMENT_IDX_CLUSTER0, + PPU_V0_ELEMENT_IDX_CLUSTER1, + PPU_V0_ELEMENT_IDX_CLUSTER2, + PPU_V0_ELEMENT_IDX_CLUSTER3, + PPU_V0_ELEMENT_IDX_CLUSTER4, + PPU_V0_ELEMENT_IDX_CLUSTER5, + PPU_V0_ELEMENT_IDX_CLUSTER6, + PPU_V0_ELEMENT_IDX_CLUSTER7, + PPU_V0_ELEMENT_IDX_CLUSTER8, + PPU_V0_ELEMENT_IDX_CLUSTER9, + PPU_V0_ELEMENT_IDX_CLUSTER10, + PPU_V0_ELEMENT_IDX_CLUSTER11, + + PPU_V0_ELEMENT_IDX_SYS3, + PPU_V0_ELEMENT_IDX_SYS1, + PPU_V0_ELEMENT_IDX_SYS2, + /* PPU_SYS4 is always ON and managed by romfw */ + PPU_V0_ELEMENT_IDX_DEBUG, + PPU_V0_ELEMENT_IDX_SYSTOP, + + PPU_V0_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/synquacer/scp_ramfw/config_ppu_v0_synquacer.c b/product/synquacer/scp_ramfw/config_ppu_v0_synquacer.c new file mode 100644 index 000000000..26560f3ca --- /dev/null +++ b/product/synquacer/scp_ramfw/config_ppu_v0_synquacer.c @@ -0,0 +1,159 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PPU_V0_NAME_SIZE (12) + +static struct fwk_element ppu_v0_static_element_table[] = { + [0] = { + .name = "SYS3", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)PPU_SYS3, + .default_power_on = false, + }), + }, + [1] = { + .name = "SYS1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)PPU_SYS1, + .default_power_on = false, + }), + }, + [2] = { + .name = "SYS2", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)PPU_SYS2, + .default_power_on = false, + }), + }, + [3] = { + .name = "DEBUG", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .ppu.reg_base = (uintptr_t)PPU_DEBUG, + .default_power_on = false, + }), + }, + [4] = { + .name = "SYSTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)PPU_SYS0, + .default_power_on = false, + }), + }, + [5] = { 0 }, /* Termination entry */ + + /* PPU_SYS4 is always ON and managed by romfw */ + +}; + +static const struct fwk_element *ppu_v0_get_element_table(fwk_id_t module_id) +{ + struct fwk_element *element_table, *element; + struct mod_ppu_v0_pd_config *ppu_v0_config_table, *ppu_v0_config; + unsigned int core_idx; + unsigned int cluster_idx; + unsigned int core_count; + unsigned int cluster_count; + unsigned int core_per_cluster_count; + unsigned int element_count = 0; + + core_count = synquacer_core_get_core_count(); + cluster_count = synquacer_core_get_cluster_count(); + core_per_cluster_count = synquacer_core_get_core_per_cluster_count(); + + element_table = fwk_mm_calloc( + cluster_count + core_count + + FWK_ARRAY_SIZE(ppu_v0_static_element_table) + 1, /* Terminator */ + sizeof(struct fwk_element)); + if (element_table == NULL) + return NULL; + + ppu_v0_config_table = fwk_mm_calloc( + (cluster_count + core_count), sizeof(struct mod_ppu_v0_pd_config)); + if (ppu_v0_config_table == NULL) + return NULL; + + element_count = 0; + + for (cluster_idx = 0; cluster_idx < cluster_count; cluster_idx++) { + /* prepare core config table */ + for (core_idx = 0; core_idx < core_per_cluster_count; core_idx++) { + element = &element_table[element_count]; + ppu_v0_config = &ppu_v0_config_table[element_count]; + + element->name = fwk_mm_alloc(PPU_V0_NAME_SIZE, 1); + if (element->name == NULL) + return NULL; + + snprintf( + (char *)element->name, + PPU_V0_NAME_SIZE, + "CLUS%uCORE%u", + cluster_idx, + core_idx); + + element->data = ppu_v0_config; + ppu_v0_config->pd_type = MOD_PD_TYPE_CORE; + ppu_v0_config->ppu.reg_base = + (uintptr_t)PPU_CPU(cluster_idx, core_idx); + ppu_v0_config->ppu.irq = FWK_INTERRUPT_NONE; + ppu_v0_config->default_power_on = false; + element_count++; + } + } + + for (cluster_idx = 0; cluster_idx < cluster_count; cluster_idx++) { + element = &element_table[element_count]; + ppu_v0_config = &ppu_v0_config_table[element_count]; + + /* prepare cluster config table */ + element->name = fwk_mm_alloc(PPU_V0_NAME_SIZE, 1); + if (element->name == NULL) + return NULL; + + snprintf( + (char *)element->name, PPU_V0_NAME_SIZE, "CLUS%u", cluster_idx); + + element->data = ppu_v0_config; + ppu_v0_config->pd_type = MOD_PD_TYPE_CLUSTER; + ppu_v0_config->ppu.reg_base = (uintptr_t)PPU_CLUSTER(cluster_idx); + ppu_v0_config->ppu.irq = FWK_INTERRUPT_NONE; + ppu_v0_config->default_power_on = false; + element_count++; + } + + memcpy( + element_table + element_count, + ppu_v0_static_element_table, + sizeof(ppu_v0_static_element_table)); + return element_table; +} + +/* + * Power module configuration data + */ +const struct fwk_module_config config_ppu_v0_synquacer = { + .get_element_table = ppu_v0_get_element_table, +}; diff --git a/product/synquacer/scp_ramfw/config_scmi.c b/product/synquacer/scp_ramfw/config_scmi.c new file mode 100644 index 000000000..4bad20cb5 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_scmi.c @@ -0,0 +1,58 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct fwk_element service_table[] = { + [SCP_SYNQUACER_SCMI_SERVICE_IDX_PSCI] = { + .name = "SERVICE0", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SMT, + SCP_SYNQUACER_SCMI_SERVICE_IDX_PSCI), + .transport_notification_init_id = FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_SMT, + MOD_SMT_NOTIFICATION_IDX_INITIALIZED), + .transport_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_SMT, + MOD_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCP_SCMI_AGENT_ID_PSCI, + }), + }, + [SCP_SYNQUACER_SCMI_SERVICE_IDX_COUNT] = { 0 } +}; + +static const struct fwk_element *get_service_table(fwk_id_t module_id) +{ + return service_table; +} + +static struct mod_scmi_agent agent_table[] = { + [SCP_SCMI_AGENT_ID_PSCI] = { + .type = SCMI_AGENT_TYPE_PSCI, + .name = "PSCI", + }, +}; + +const struct fwk_module_config config_scmi = { + .get_element_table = get_service_table, + .data = &((struct mod_scmi_config) { + .protocol_count_max = 9, + .agent_count = FWK_ARRAY_SIZE(agent_table) - 1, + .agent_table = agent_table, + .vendor_identifier = "socionext", + .sub_vendor_identifier = "socionext", + }), +}; diff --git a/product/synquacer/scp_ramfw/config_scmi.h b/product/synquacer/scp_ramfw/config_scmi.h new file mode 100644 index 000000000..7747be7d5 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_scmi.h @@ -0,0 +1,23 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_SCMI_H +#define CONFIG_SCMI_H + +/* SCMI agent identifiers */ +enum scp_synquacer_scmi_agent_id { + /* 0 is reserved for the platform */ + SCP_SCMI_AGENT_ID_PSCI = 1, +}; + +/* SCMI service indexes */ +enum scp_synquacer_scmi_service_idx { + SCP_SYNQUACER_SCMI_SERVICE_IDX_PSCI, + SCP_SYNQUACER_SCMI_SERVICE_IDX_COUNT, +}; + +#endif /* CONFIG_SCMI_H */ diff --git a/product/synquacer/scp_ramfw/config_scmi_apcore.c b/product/synquacer/scp_ramfw/config_scmi_apcore.c new file mode 100644 index 000000000..1443620f7 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_scmi_apcore.c @@ -0,0 +1,29 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +static const struct mod_scmi_apcore_reset_register_group + reset_reg_group_table[] = { + { + .base_register = (uintptr_t)&PIK_CLUSTER(0)->RVBARADDR0_LW, + .register_count = SYNQUACER_CSS_CPUS_MAX, + }, + }; + +const struct fwk_module_config config_scmi_apcore = { + .data = &((struct mod_scmi_apcore_config){ + .reset_register_width = MOD_SCMI_APCORE_REG_WIDTH_64, + .reset_register_group_count = FWK_ARRAY_SIZE(reset_reg_group_table), + .reset_register_group_table = &reset_reg_group_table[0], + }), +}; diff --git a/product/synquacer/scp_ramfw/config_scmi_system_power.c b/product/synquacer/scp_ramfw/config_scmi_system_power.c new file mode 100644 index 000000000..f0e70ac25 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_scmi_system_power.c @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +const struct fwk_module_config config_scmi_system_power = { + .data = &((struct mod_scmi_system_power_config){ + .system_view = MOD_SCMI_SYSTEM_VIEW_FULL, + .system_suspend_state = MOD_SYSTEM_POWER_POWER_STATE_SLEEP0 }), +}; diff --git a/product/synquacer/scp_ramfw/config_smt.c b/product/synquacer/scp_ramfw/config_smt.c new file mode 100644 index 000000000..41a9f63ba --- /dev/null +++ b/product/synquacer/scp_ramfw/config_smt.c @@ -0,0 +1,55 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct fwk_element smt_element_table[] = { + [SCP_SYNQUACER_SCMI_SERVICE_IDX_PSCI] = { + .name = "PSCI", + .data = &((struct mod_smt_channel_config) { + .type = MOD_SMT_CHANNEL_TYPE_SLAVE, + .policies = MOD_SMT_POLICY_INIT_MAILBOX | MOD_SMT_POLICY_SECURE, + .mailbox_address = (uintptr_t)MHU_PAYLOAD_S_BASE, + .mailbox_size = 256, + .driver_id = FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU, + SCP_SYNQUACER_MHU_DEVICE_IDX_SCP_AP_S, + 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MHU, 0), + }) }, + [SCP_SYNQUACER_SCMI_SERVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *smt_get_element_table(fwk_id_t module_id) +{ + unsigned int idx; + struct mod_smt_channel_config *config; + + for (idx = 0; idx < SCP_SYNQUACER_SCMI_SERVICE_IDX_COUNT; idx++) { + config = (struct mod_smt_channel_config *)(smt_element_table[idx].data); + config->pd_source_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_POWER_DOMAIN, + synquacer_core_get_core_count() + + synquacer_core_get_cluster_count() + PD_STATIC_DEV_IDX_SYSTOP); + } + + return smt_element_table; +} + +const struct fwk_module_config config_smt = { + .get_element_table = smt_get_element_table, +}; diff --git a/product/synquacer/scp_ramfw/config_synquacer_memc.c b/product/synquacer/scp_ramfw/config_synquacer_memc.c new file mode 100644 index 000000000..7f8f98ffe --- /dev/null +++ b/product/synquacer/scp_ramfw/config_synquacer_memc.c @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* Configuration of the SynQuacerMEMC module. */ +const struct fwk_module_config config_synquacer_memc = { + .get_element_table = NULL, +}; diff --git a/product/synquacer/scp_ramfw/config_system_power.c b/product/synquacer/scp_ramfw/config_system_power.c new file mode 100644 index 000000000..852119c59 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_system_power.c @@ -0,0 +1,92 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct mod_system_power_ext_ppu_config ext_ppus[] = { + { + .ppu_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_SYS1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + }, + { + .ppu_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_SYS2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + }, + { + .ppu_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_SYSTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + }, +}; + +static const uint8_t system_power_to_sys_debug_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_OFF, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static const uint8_t system_power_to_sys3_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_ON, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static const struct fwk_element system_power_element_table[] = { + [0] = { + .name = "DEBUG", + .data = &((struct mod_system_power_dev_config) { + .sys_ppu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_DEBUG), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + .sys_state_table = system_power_to_sys_debug_state, + }), + }, + + [1] = { + .name = "SYS3", + .data = &((struct mod_system_power_dev_config) { + .sys_ppu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, + PPU_V0_ELEMENT_IDX_SYS3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0_SYNQUACER, 0), + .sys_state_table = system_power_to_sys3_state, + }), + }, + + [2] = { 0 }, /* Termination description */ +}; + +static const struct fwk_element *system_power_get_element_table( + fwk_id_t module_id) +{ + return system_power_element_table; +} + +const struct fwk_module_config config_system_power = { + .data = &((struct mod_system_power_config) { + .soc_wakeup_irq = FWK_INTERRUPT_NONE, + .ext_ppus = ext_ppus, + .ext_ppus_count = FWK_ARRAY_SIZE(ext_ppus), + .initial_system_power_state = MOD_PD_STATE_ON, + .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYNQUACER_SYSTEM), + .driver_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_SYNQUACER_SYSTEM, + MOD_SYNQUACER_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER) + }), + .get_element_table = system_power_get_element_table, +}; diff --git a/product/synquacer/scp_ramfw/config_timer.c b/product/synquacer/scp_ramfw/config_timer.c new file mode 100644 index 000000000..9ad133561 --- /dev/null +++ b/product/synquacer/scp_ramfw/config_timer.c @@ -0,0 +1,66 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Generic timer driver config + */ +static const struct fwk_element gtimer_dev_table[] = { + [0] = { .name = "REFCLK", + .data = &((struct mod_gtimer_dev_config) { + .hw_timer = REFCLK_CNTBASE0_BASE, + .hw_counter = REFCLK_CNTCTL_BASE, + .control = REFCLK_CNTCONTROL_BASE, + .frequency = CLOCK_RATE_REFCLK, + .clock_id = FWK_ID_NONE_INIT, + }) }, + [1] = { 0 }, +}; + +static const struct fwk_element *gtimer_get_dev_table(fwk_id_t module_id) +{ + return gtimer_dev_table; +} + +struct fwk_module_config config_gtimer = { + .get_element_table = gtimer_get_dev_table, +}; + +/* + * Timer HAL config + */ +static const struct mod_timer_dev_config refclk_config = { + .id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_GTIMER, 0), + .timer_irq = TIMREFCLK_IRQn, +}; + +static const struct fwk_element timer_dev_table[] = { + [0] = { + .name = "REFCLK", + .data = &refclk_config, + .sub_element_count = 8, /* Number of alarms */ + }, + [1] = { 0 }, +}; + +static const struct fwk_element *timer_get_dev_table(fwk_id_t module_id) +{ + return timer_dev_table; +} + +struct fwk_module_config config_timer = { + .get_element_table = timer_get_dev_table, +}; diff --git a/product/synquacer/scp_ramfw/firmware.mk b/product/synquacer/scp_ramfw/firmware.mk new file mode 100644 index 000000000..28fc093a1 --- /dev/null +++ b/product/synquacer/scp_ramfw/firmware.mk @@ -0,0 +1,74 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_FIRMWARE_CPU := cortex-m3 +BS_FIRMWARE_HAS_MULTITHREADING := yes +BS_FIRMWARE_HAS_NOTIFICATION := yes + +DEFINES += HAS_RTOS +DEFINES += SYNQUACER_LOG_GROUP_ERROR +DEFINES += SYNQUACER_LOG_GROUP_INFO +DEFINES += SYNQUACER_LOG_GROUP_WARNING +#DEFINES += SYNQUACER_LOG_GROUP_DEBUG +DEFINES += PCIE_FILTER_BUS0_TYPE0_CONFIG +DEFINES += ENABLE_OPTEE +DEFINES += SET_PCIE_NON_SECURE +#DEFINES += CA53_USE_F_UART + +INCLUDES += $(OS_DIR)/RTX/Include1 + + +BS_FIRMWARE_MODULES := \ + armv7m_mpu \ + f_uart3 \ + log \ + gtimer \ + timer \ + ppu_v0_synquacer \ + system_power \ + power_domain \ + clock \ + synquacer_system \ + pik_clock \ + css_clock \ + ccn512 \ + f_i2c \ + hsspi \ + synquacer_memc \ + mhu \ + smt \ + scmi \ + scmi_power_domain \ + scmi_system_power \ + scmi_apcore \ + scmi_vendor_ext + + +BS_FIRMWARE_SOURCES := \ + config_armv7m_mpu.c \ + config_ccn512.c \ + config_clock.c \ + config_css_clock.c \ + config_f_i2c.c \ + config_hsspi.c \ + config_log_f_uart3.c \ + config_mhu.c \ + config_pik_clock.c \ + config_power_domain.c \ + config_ppu_v0_synquacer.c \ + config_scmi.c \ + config_scmi_apcore.c \ + config_scmi_system_power.c \ + config_smt.c \ + config_synquacer_memc.c \ + config_system_power.c \ + config_timer.c \ + rtx_config.c \ + synquacer_core.c + + +include $(BS_DIR)/firmware.mk diff --git a/product/synquacer/scp_ramfw/fmw_memory.ld.S b/product/synquacer/scp_ramfw/fmw_memory.ld.S new file mode 100644 index 000000000..5afda052e --- /dev/null +++ b/product/synquacer/scp_ramfw/fmw_memory.ld.S @@ -0,0 +1,32 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * RAM firmware memory layout for the linker script. + */ + +#ifndef FMW_MEMORY_LD_S +#define FMW_MEMORY_LD_S + +#include + +#define FIRMWARE_MEM_MODE FWK_MEM_MODE_DUAL_REGION_RELOCATION + +/* + * RAM instruction memory + */ +#define FIRMWARE_MEM0_SIZE SCP_RAM0_SIZE +#define FIRMWARE_MEM0_BASE SCP_RAM0_BASE + +/* + * RAM data memory + */ +#define FIRMWARE_MEM1_SIZE SCP_RAM2_SIZE +#define FIRMWARE_MEM1_BASE SCP_RAM2_BASE + +#define FIRMWARE_STACK_SIZE (1 * 1024) + +#endif /* FMW_MEMORY_LD_S */ diff --git a/product/synquacer/scp_ramfw/rtx_config.c b/product/synquacer/scp_ramfw/rtx_config.c new file mode 100644 index 000000000..1dbd3a964 --- /dev/null +++ b/product/synquacer/scp_ramfw/rtx_config.c @@ -0,0 +1,84 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Required by RTX to configure the SysTick timer. + */ +uint32_t SystemCoreClock = CLOCK_RATE_REFCLK; + +/* + * Idle thread + */ +__NO_RETURN void osRtxIdleThread(void *argument) +{ + (void)argument; + + while (true) + __WFI(); +} + +/* + * OS error handler + */ +uint32_t osRtxErrorNotify(uint32_t code, void *object_id) +{ + (void)object_id; + + switch (code) { + case osRtxErrorStackUnderflow: + /* + * Stack underflow detected for thread + * thread_id=object_id + */ + SYNQUACER_DEV_LOG_ERROR("[SYSTEM] osRtxErrorStackUnderflow.\n"); + break; + + case osRtxErrorISRQueueOverflow: + /* + * ISR Queue overflow detected when inserting object + * object_id + */ + SYNQUACER_DEV_LOG_ERROR("[SYSTEM] osRtxErrorISRQueueOverflow.\n"); + break; + + case osRtxErrorTimerQueueOverflow: + /* + * User Timer Callback Queue overflow detected for timer + * timer_id=object_id + */ + SYNQUACER_DEV_LOG_ERROR("[SYSTEM] osRtxErrorTimerQueueOverflow.\n"); + break; + + case osRtxErrorClibSpace: + /* + * Standard C/C++ library libspace not available: + * increase OS_THREAD_LIBSPACE_NUM + */ + SYNQUACER_DEV_LOG_ERROR("[SYSTEM] osRtxErrorClibSpace.\n"); + break; + + case osRtxErrorClibMutex: + /* + * Standard C/C++ library mutex initialization failed + */ + SYNQUACER_DEV_LOG_ERROR("[SYSTEM] oosRtxErrorClibMutex.\n"); + break; + + default: + break; + } + + osRtxIdleThread(object_id); +} diff --git a/product/synquacer/scp_romfw/config_armv7m_mpu.c b/product/synquacer/scp_romfw/config_armv7m_mpu.c new file mode 100644 index 000000000..e223febd4 --- /dev/null +++ b/product/synquacer/scp_romfw/config_armv7m_mpu.c @@ -0,0 +1,62 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define ROM_BASE 0x00000000UL +#define AP_RAM_BASE UINT32_C(0xA4000000) + +static const ARM_MPU_Region_t regions[] = { + { + /* 0x0000_0000 - 0xFFFF_FFFF */ + .RBAR = ARM_MPU_RBAR(0, ROM_BASE), + .RASR = ARM_MPU_RASR( + 1, + ARM_MPU_AP_FULL, + 0, + 1, + 0, + 0, + 0, + ARM_MPU_REGION_SIZE_4GB), + }, + { + /* 0x0000_0000 - 0x1FFF_FFFF */ + .RBAR = ARM_MPU_RBAR(1, ROM_BASE), + .RASR = ARM_MPU_RASR( + 0, + ARM_MPU_AP_FULL, + 0, + 0, + 1, + 1, + 0, + ARM_MPU_REGION_SIZE_512MB), + }, + { + /* 0xA400_0000 - 0xA407_FFFF */ + .RBAR = ARM_MPU_RBAR(2, AP_RAM_BASE), + .RASR = ARM_MPU_RASR( + 0, + ARM_MPU_AP_FULL, + 0, + 0, + 1, + 1, + 0, + ARM_MPU_REGION_SIZE_512KB), + }, +}; + +const struct fwk_module_config config_armv7m_mpu = { + .data = &((struct mod_armv7m_mpu_config){ + .region_count = FWK_ARRAY_SIZE(regions), + .regions = regions, + }), +}; diff --git a/product/synquacer/scp_romfw/config_clock.c b/product/synquacer/scp_romfw/config_clock.c new file mode 100644 index 000000000..8e7817626 --- /dev/null +++ b/product/synquacer/scp_romfw/config_clock.c @@ -0,0 +1,10 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const struct fwk_module_config config_clock = { 0 }; diff --git a/product/synquacer/scp_romfw/config_clock.h b/product/synquacer/scp_romfw/config_clock.h new file mode 100644 index 000000000..aa8ebe778 --- /dev/null +++ b/product/synquacer/scp_romfw/config_clock.h @@ -0,0 +1,29 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_CLOCK_H +#define CONFIG_CLOCK_H + +/* + * PIK clock indexes. + */ +enum clock_pik_idx { + CLOCK_PIK_IDX_CORECLK, + CLOCK_PIK_IDX_ACLK, + CLOCK_PIK_IDX_PPUCLK, + CLOCK_PIK_IDX_CCNCLK, + CLOCK_PIK_IDX_GICCLK, + CLOCK_PIK_IDX_PCLKSCP, + CLOCK_PIK_IDX_SYSPERCLK, + CLOCK_PIK_IDX_SYSPCLKDBG, + CLOCK_PIK_IDX_UARTCLK, + CLOCK_PIK_IDX_DMCCLK, + + CLOCK_PIK_IDX_COUNT +}; + +#endif /* CONFIG_CLOCK_H */ diff --git a/product/synquacer/scp_romfw/config_log_f_uart3.c b/product/synquacer/scp_romfw/config_log_f_uart3.c new file mode 100644 index 000000000..e4b20f95b --- /dev/null +++ b/product/synquacer/scp_romfw/config_log_f_uart3.c @@ -0,0 +1,57 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * F_UART3 module + */ +static const struct fwk_element f_uart3_element_desc_table[] = { + [0] = { + .name = "F_UART3", + .data = &((struct mod_f_uart3_device_config) { + .reg_base = F_UART3_BASE_ADDR, + .dla_reg_base = F_UART3_BASE_ADDR, + .baud_rate_bps = 115200, + .clock_rate_hz = 62500 * FWK_KHZ, + .clock_id = FWK_ID_NONE_INIT, + }), + }, + [1] = { 0 }, +}; + +static const struct fwk_element *get_f_uart3_table(fwk_id_t module_id) +{ + return f_uart3_element_desc_table; +} + +struct fwk_module_config config_f_uart3 = { + .get_element_table = get_f_uart3_table, +}; + +/* + * Log module + */ +static const struct mod_log_config log_data = { + .device_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_F_UART3, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_F_UART3, 0), + .log_groups = MOD_LOG_GROUP_ERROR | MOD_LOG_GROUP_INFO | + MOD_LOG_GROUP_WARNING | MOD_LOG_GROUP_DEBUG, + .banner = + FWK_BANNER_SCP FWK_BANNER_ROM_FIRMWARE BUILD_VERSION_DESCRIBE_STRING + "\n", +}; + +struct fwk_module_config config_log = { + .data = &log_data, +}; diff --git a/product/synquacer/scp_romfw/config_synquacer_pik_clock.c b/product/synquacer/scp_romfw/config_synquacer_pik_clock.c new file mode 100644 index 000000000..57fd69260 --- /dev/null +++ b/product/synquacer/scp_romfw/config_synquacer_pik_clock.c @@ -0,0 +1,243 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Rate lookup tables + */ +static const struct mod_pik_clock_rate rate_table_coreclk[] = { + { + .rate = CONFIG_SOC_CORE_CLOCK, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, CONFIG_SOC_CORE_CLOCK), + }, +}; + +static const struct mod_pik_clock_rate rate_table_aclk[] = { + { + .rate = 125 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 125 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_ppuclk[] = { + { + .rate = 125 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 125 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_ccnclk[] = { + { + .rate = 1000 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 1000 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_gicclk[] = { + { + .rate = 500 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 500 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_pclkscp[] = { + { + .rate = 125 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 125 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_sysperclk[] = { + { + .rate = 500 * FWK_MHZ, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 500 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_syspclkdbg[] = { + { + .rate = 125 * FWK_MHZ, + .source = (MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK | (0x1U << 16)), + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, 125 * FWK_MHZ), + }, +}; + +static const struct mod_pik_clock_rate rate_table_uartclk[] = { + { + .rate = CLOCK_RATE_AP_PL011CLK, + .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK, + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_SYSINCLK, CLOCK_RATE_AP_PL011CLK), + }, +}; + +static const struct mod_pik_clock_rate rate_table_dmcclk[] = { + { + .rate = 1066 * FWK_MHZ, + .source = (MOD_PIK_CLOCK_DMCCLK_SOURCE_DDRPLL | (0x1U << 16)), + .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS, + .divider = DIV_FROM_CLOCK(CLOCK_RATE_DDRPLLCLK, 1066 * FWK_MHZ), + }, +}; + +static const struct fwk_element pik_clock_element_table[] = { + [CLOCK_PIK_IDX_CORECLK] = { + .name = "CORECLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SCP->CORECLK_CNTRL, + .divsys_reg = &PIK_SCP->CORECLK_DIV1, + .rate_table = rate_table_coreclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_coreclk), + .initial_rate = CONFIG_SOC_CORE_CLOCK, + }), + }, + [CLOCK_PIK_IDX_ACLK] = { + .name = "ACLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SCP->ACLK_CNTRL, + .divsys_reg = &PIK_SCP->ACLK_DIV1, + .rate_table = rate_table_aclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_aclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_PPUCLK] = { + .name = "PPUCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->PPUCLK_CTRL, + .divsys_reg = &PIK_SYSTEM->PPUCLK_DIV1, + .rate_table = rate_table_ppuclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_ppuclk), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_CCNCLK] = { + .name = "CCNCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->CCNCLK_CTRL, + .divsys_reg = &PIK_SYSTEM->CCNCLK_DIV1, + .rate_table = rate_table_ccnclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_ccnclk), + .initial_rate = 1000 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_GICCLK] = { + .name = "GICCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->GICCLK_CTRL, + .divsys_reg = &PIK_SYSTEM->GICCLK_DIV1, + .rate_table = rate_table_gicclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_gicclk), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_PCLKSCP] = { + .name = "PCLKSCP", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->PCLKSCP_CTRL, + .divsys_reg = &PIK_SYSTEM->PCLKSCP_DIV1, + .rate_table = rate_table_pclkscp, + .rate_count = FWK_ARRAY_SIZE(rate_table_pclkscp), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_SYSPERCLK] = { + .name = "SYSPERCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->SYSPERCLK_CTRL, + .divsys_reg = &PIK_SYSTEM->SYSPERCLK_DIV1, + .rate_table = rate_table_sysperclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_sysperclk), + .initial_rate = 500 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_SYSPCLKDBG] = { + .name = "SYSPCLKDBG", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->SYSPCLKDBG_CTRL, + .divsys_reg = &PIK_SYSTEM->SYSPCLKDBG_DIV1, + .rate_table = rate_table_syspclkdbg, + .rate_count = FWK_ARRAY_SIZE(rate_table_syspclkdbg), + .initial_rate = 125 * FWK_MHZ, + }), + }, + [CLOCK_PIK_IDX_UARTCLK] = { + .name = "UARTCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->UARTCLK_CTRL, + .divsys_reg = &PIK_SYSTEM->UARTCLK_DIV1, + .rate_table = rate_table_uartclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_uartclk), + .initial_rate = CLOCK_RATE_AP_PL011CLK, + }), + }, + [CLOCK_PIK_IDX_DMCCLK] = { + .name = "DMCCLK", + .data = &((struct mod_pik_clock_dev_config) { + .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE, + .is_group_member = false, + .control_reg = &PIK_SYSTEM->DMCCLK_CTRL, + .divsys_reg = &PIK_SYSTEM->DMCCLK_DIV1, + .rate_table = rate_table_dmcclk, + .rate_count = FWK_ARRAY_SIZE(rate_table_dmcclk), + .initial_rate = 1066 * FWK_MHZ, + }), + }, + + [CLOCK_PIK_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *pik_clock_get_element_table(fwk_id_t module_id) +{ + return pik_clock_element_table; +} + +const struct fwk_module_config config_synquacer_pik_clock = { + .get_element_table = pik_clock_get_element_table, +}; diff --git a/product/synquacer/scp_romfw/config_synquacer_rom.c b/product/synquacer/scp_romfw/config_synquacer_rom.c new file mode 100644 index 000000000..41301dad8 --- /dev/null +++ b/product/synquacer/scp_romfw/config_synquacer_rom.c @@ -0,0 +1,18 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +const struct fwk_module_config config_synquacer_rom = { + .data = &((struct synquacer_rom_config){ + .ramfw_base = SCP_RAM0_BASE, + .nor_base = SCP_RAMFW_ROM_BASE, + .load_ram_size = SCP_RAMFW_IMAGE_SIZE, + }) +}; diff --git a/product/synquacer/scp_romfw/config_timer.c b/product/synquacer/scp_romfw/config_timer.c new file mode 100644 index 000000000..9ad133561 --- /dev/null +++ b/product/synquacer/scp_romfw/config_timer.c @@ -0,0 +1,66 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Generic timer driver config + */ +static const struct fwk_element gtimer_dev_table[] = { + [0] = { .name = "REFCLK", + .data = &((struct mod_gtimer_dev_config) { + .hw_timer = REFCLK_CNTBASE0_BASE, + .hw_counter = REFCLK_CNTCTL_BASE, + .control = REFCLK_CNTCONTROL_BASE, + .frequency = CLOCK_RATE_REFCLK, + .clock_id = FWK_ID_NONE_INIT, + }) }, + [1] = { 0 }, +}; + +static const struct fwk_element *gtimer_get_dev_table(fwk_id_t module_id) +{ + return gtimer_dev_table; +} + +struct fwk_module_config config_gtimer = { + .get_element_table = gtimer_get_dev_table, +}; + +/* + * Timer HAL config + */ +static const struct mod_timer_dev_config refclk_config = { + .id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_GTIMER, 0), + .timer_irq = TIMREFCLK_IRQn, +}; + +static const struct fwk_element timer_dev_table[] = { + [0] = { + .name = "REFCLK", + .data = &refclk_config, + .sub_element_count = 8, /* Number of alarms */ + }, + [1] = { 0 }, +}; + +static const struct fwk_element *timer_get_dev_table(fwk_id_t module_id) +{ + return timer_dev_table; +} + +struct fwk_module_config config_timer = { + .get_element_table = timer_get_dev_table, +}; diff --git a/product/synquacer/scp_romfw/firmware.mk b/product/synquacer/scp_romfw/firmware.mk new file mode 100644 index 000000000..c398a36c8 --- /dev/null +++ b/product/synquacer/scp_romfw/firmware.mk @@ -0,0 +1,37 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_FIRMWARE_CPU := cortex-m7 +BS_FIRMWARE_HAS_MULTITHREADING := no +BS_FIRMWARE_HAS_NOTIFICATION := yes +BS_FIRMWARE_MODULE_HEADERS_ONLY := \ + power_domain \ + ppu_v0_synquacer \ + css_clock + +INCLUDES += $(OS_DIR)/../Core/Include + + +BS_FIRMWARE_MODULES := \ + armv7m_mpu \ + synquacer_rom \ + f_uart3 \ + log \ + clock \ + synquacer_pik_clock \ + gtimer \ + timer + +BS_FIRMWARE_SOURCES := \ + config_armv7m_mpu.c \ + config_clock.c \ + config_log_f_uart3.c \ + config_synquacer_pik_clock.c \ + config_synquacer_rom.c \ + config_timer.c + +include $(BS_DIR)/firmware.mk diff --git a/product/synquacer/scp_romfw/fmw_memory.ld.S b/product/synquacer/scp_romfw/fmw_memory.ld.S new file mode 100644 index 000000000..40354a8d8 --- /dev/null +++ b/product/synquacer/scp_romfw/fmw_memory.ld.S @@ -0,0 +1,32 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * ROM firmware memory layout for the linker script. + */ + +#ifndef FMW_MEMORY_LD_S +#define FMW_MEMORY_LD_S + +#include + +#define FIRMWARE_MEM_MODE FWK_MEM_MODE_DUAL_REGION_RELOCATION + +/* + * ROM memory + */ +#define FIRMWARE_MEM0_SIZE SCP_ROM_SIZE +#define FIRMWARE_MEM0_BASE SCP_ROM_BASE + +/* + * RAM memory + */ +#define FIRMWARE_MEM1_SIZE SCP_RAM1_SIZE +#define FIRMWARE_MEM1_BASE SCP_RAM1_BASE + +#define FIRMWARE_STACK_SIZE (1 * 1024) + +#endif /* FMW_MEMORY_LD_S */ diff --git a/product/synquacer/src/synquacer_core.c b/product/synquacer/src/synquacer_core.c new file mode 100644 index 000000000..5be497bda --- /dev/null +++ b/product/synquacer/src/synquacer_core.c @@ -0,0 +1,23 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +uint32_t synquacer_core_get_core_count(void) +{ + return SYNQUACER_CSS_CPUS_MAX; +} + +uint32_t synquacer_core_get_cluster_count(void) +{ + return SYNQUACER_CSS_CPUS_CLUSTER_MAX; +} + +uint32_t synquacer_core_get_core_per_cluster_count(void) +{ + return SYNQUACER_CSS_CPUS_PER_CLUSTER_MAX; +} diff --git a/tools/ci.py b/tools/ci.py index 575b120e7..c1dd9c45e 100755 --- a/tools/ci.py +++ b/tools/ci.py @@ -263,6 +263,40 @@ def main(): result = subprocess.call(cmd, shell=True) results.append(('Product Juno release build (ARM)', result)) + banner('Test building synquacer product') + + cmd = \ + 'CC=arm-none-eabi-gcc ' \ + 'PRODUCT=synquacer ' \ + 'MODE=release ' \ + 'make clean all' + result = subprocess.call(cmd, shell=True) + results.append(('Product synquacer release build (GCC)', result)) + + cmd = \ + 'CC=armclang ' \ + 'PRODUCT=synquacer ' \ + 'MODE=release ' \ + 'make clean all' + result = subprocess.call(cmd, shell=True) + results.append(('Product synquacer release build (ARM)', result)) + + cmd = \ + 'CC=arm-none-eabi-gcc ' \ + 'PRODUCT=synquacer ' \ + 'MODE=debug ' \ + 'make clean all' + result = subprocess.call(cmd, shell=True) + results.append(('Product synquacer debug build (GCC)', result)) + + cmd = \ + 'CC=armclang ' \ + 'PRODUCT=synquacer ' \ + 'MODE=debug ' \ + 'make clean all' + result = subprocess.call(cmd, shell=True) + results.append(('Product synquacer debug build (ARM)', result)) + banner('Tests summary') total_success = 0 -- GitLab