diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 545fc3e243..6ff201fa81 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -164,18 +164,16 @@ config TARGET_NSIM config TARGET_AXS101 bool "Support Synopsys Designware SDP board AXS101" - select BOUNCE_BUFFER if CMD_NAND config TARGET_AXS103 bool "Support Synopsys Designware SDP board AXS103" - select BOUNCE_BUFFER if CMD_NAND config TARGET_EMSDP bool "Synopsys EM Software Development Platform" select CPU_ARCEM6 config TARGET_HSDK - bool "Support Synpsys HS DevelopmentKit board" + bool "Support Synopsys HSDK or HSDK-4xD board" config TARGET_IOT_DEVKIT bool "Synopsys Brite IoT Development kit" diff --git a/arch/arc/dts/Makefile b/arch/arc/dts/Makefile index 4f1e4637ce..515fe1fe53 100644 --- a/arch/arc/dts/Makefile +++ b/arch/arc/dts/Makefile @@ -5,7 +5,7 @@ dtb-$(CONFIG_TARGET_AXS103) += axs103.dtb dtb-$(CONFIG_TARGET_NSIM) += nsim.dtb dtb-$(CONFIG_TARGET_TB100) += abilis_tb100.dtb dtb-$(CONFIG_TARGET_EMSDP) += emsdp.dtb -dtb-$(CONFIG_TARGET_HSDK) += hsdk.dtb +dtb-$(CONFIG_TARGET_HSDK) += hsdk.dtb hsdk-4xd.dtb dtb-$(CONFIG_TARGET_IOT_DEVKIT) += iot_devkit.dtb targets += $(dtb-y) diff --git a/arch/arc/dts/hsdk-4xd.dts b/arch/arc/dts/hsdk-4xd.dts new file mode 100644 index 0000000000..b245eea769 --- /dev/null +++ b/arch/arc/dts/hsdk-4xd.dts @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev + */ +/dts-v1/; + +#include "hsdk-common.dtsi" + +/ { + model = "snps,hsdk-4xd"; +}; diff --git a/arch/arc/dts/hsdk-common.dtsi b/arch/arc/dts/hsdk-common.dtsi new file mode 100644 index 0000000000..fd4245e164 --- /dev/null +++ b/arch/arc/dts/hsdk-common.dtsi @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017-2020 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev + */ +/dts-v1/; + +#include "skeleton.dtsi" +#include "dt-bindings/clock/snps,hsdk-cgu.h" +#include "dt-bindings/reset/snps,hsdk-reset.h" + +/ { + #address-cells = <1>; + #size-cells = <1>; + + aliases { + console = &uart0; + spi0 = &spi0; + }; + + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <500000000>; + u-boot,dm-pre-reloc; + }; + }; + + clk-fmeas { + clocks = <&cgu_clk CLK_ARC_PLL>, <&cgu_clk CLK_SYS_PLL>, + <&cgu_clk CLK_TUN_PLL>, <&cgu_clk CLK_DDR_PLL>, + <&cgu_clk CLK_ARC>, <&cgu_clk CLK_HDMI_PLL>, + <&cgu_clk CLK_TUN_TUN>, <&cgu_clk CLK_HDMI>, + <&cgu_clk CLK_SYS_APB>, <&cgu_clk CLK_SYS_AXI>, + <&cgu_clk CLK_SYS_ETH>, <&cgu_clk CLK_SYS_USB>, + <&cgu_clk CLK_SYS_SDIO>, <&cgu_clk CLK_SYS_HDMI>, + <&cgu_clk CLK_SYS_GFX_CORE>, <&cgu_clk CLK_SYS_GFX_DMA>, + <&cgu_clk CLK_SYS_GFX_CFG>, <&cgu_clk CLK_SYS_DMAC_CORE>, + <&cgu_clk CLK_SYS_DMAC_CFG>, <&cgu_clk CLK_SYS_SDIO_REF>, + <&cgu_clk CLK_SYS_SPI_REF>, <&cgu_clk CLK_SYS_I2C_REF>, + <&cgu_clk CLK_SYS_UART_REF>, <&cgu_clk CLK_SYS_EBI_REF>, + <&cgu_clk CLK_TUN_ROM>, <&cgu_clk CLK_TUN_PWM>, + <&cgu_clk CLK_TUN_TIMER>; + clock-names = "cpu-pll", "sys-pll", + "tun-pll", "ddr-clk", + "cpu-clk", "hdmi-pll", + "tun-clk", "hdmi-clk", + "apb-clk", "axi-clk", + "eth-clk", "usb-clk", + "sdio-clk", "hdmi-sys-clk", + "gfx-core-clk", "gfx-dma-clk", + "gfx-cfg-clk", "dmac-core-clk", + "dmac-cfg-clk", "sdio-ref-clk", + "spi-clk", "i2c-clk", + "uart-clk", "ebi-clk", + "rom-clk", "pwm-clk", + "timer-clk"; + }; + + cgu_clk: cgu-clk@f0000000 { + compatible = "snps,hsdk-cgu-clock"; + reg = <0xf0000000 0x10>, <0xf00014B8 0x4>; + #clock-cells = <1>; + }; + + cgu_rst: reset-controller@f00008a0 { + compatible = "snps,hsdk-reset"; + #reset-cells = <1>; + reg = <0xf00008a0 0x4>, <0xf0000ff0 0x4>; + }; + + uart0: serial0@f0005000 { + compatible = "snps,dw-apb-uart"; + reg = <0xf0005000 0x1000>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + ethernet@f0008000 { + #interrupt-cells = <1>; + compatible = "snps,arc-dwmac-3.70a"; + reg = <0xf0008000 0x2000>; + phy-mode = "gmii"; + }; + + ehci@0xf0040000 { + compatible = "generic-ehci"; + reg = <0xf0040000 0x100>; + }; + + ohci@0xf0060000 { + compatible = "generic-ohci"; + reg = <0xf0060000 0x100>; + }; + + mmcclk_ciu: mmcclk-ciu { + compatible = "fixed-clock"; + /* + * DW sdio controller has external ciu clock divider + * controlled via register in SDIO IP. Due to its + * unexpected default value (it should divide by 1 + * but it divides by 8) SDIO IP uses wrong clock and + * works unstable (see STAR 9001204800) + * We switched to the minimum possible value of the + * divisor (div-by-2) in HSDK platform code. + * So default mmcclk ciu clock is 50000000 Hz. + */ + clock-frequency = <50000000>; + #clock-cells = <0>; + }; + + mmc: mmc0@f000a000 { + compatible = "snps,dw-mshc"; + reg = <0xf000a000 0x400>; + bus-width = <4>; + fifo-depth = <256>; + clocks = <&cgu_clk CLK_SYS_SDIO>, <&mmcclk_ciu>; + clock-names = "biu", "ciu"; + max-frequency = <25000000>; + }; + + spi0: spi@f0020000 { + compatible = "snps,dw-apb-ssi"; + reg = <0xf0020000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <4000000>; + clocks = <&cgu_clk CLK_SYS_SPI_REF>; + clock-names = "spi_clk"; + cs-gpio = <&cs_gpio 0>; + spi_flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <4000000>; + }; + }; + + cs_gpio: gpio@f00014b0 { + compatible = "snps,creg-gpio"; + reg = <0xf00014b0 0x4>; + gpio-controller; + #gpio-cells = <1>; + gpio-bank-name = "hsdk-spi-cs"; + gpio-count = <1>; + gpio-first-shift = <0>; + gpio-bit-per-line = <2>; + gpio-activate-val = <2>; + gpio-deactivate-val = <3>; + gpio-default-val = <1>; + }; +}; diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts index cf2ce8a1f6..1a2e3d4322 100644 --- a/arch/arc/dts/hsdk.dts +++ b/arch/arc/dts/hsdk.dts @@ -1,151 +1,12 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2017 Synopsys, Inc. All rights reserved. + * Copyright (C) 2017-2020 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev */ /dts-v1/; -#include "skeleton.dtsi" -#include "dt-bindings/clock/snps,hsdk-cgu.h" -#include "dt-bindings/reset/snps,hsdk-reset.h" +#include "hsdk-common.dtsi" / { model = "snps,hsdk"; - - #address-cells = <1>; - #size-cells = <1>; - - aliases { - console = &uart0; - spi0 = &spi0; - }; - - cpu_card { - core_clk: core_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <500000000>; - u-boot,dm-pre-reloc; - }; - }; - - clk-fmeas { - clocks = <&cgu_clk CLK_ARC_PLL>, <&cgu_clk CLK_SYS_PLL>, - <&cgu_clk CLK_TUN_PLL>, <&cgu_clk CLK_DDR_PLL>, - <&cgu_clk CLK_ARC>, <&cgu_clk CLK_HDMI_PLL>, - <&cgu_clk CLK_TUN_TUN>, <&cgu_clk CLK_HDMI>, - <&cgu_clk CLK_SYS_APB>, <&cgu_clk CLK_SYS_AXI>, - <&cgu_clk CLK_SYS_ETH>, <&cgu_clk CLK_SYS_USB>, - <&cgu_clk CLK_SYS_SDIO>, <&cgu_clk CLK_SYS_HDMI>, - <&cgu_clk CLK_SYS_GFX_CORE>, <&cgu_clk CLK_SYS_GFX_DMA>, - <&cgu_clk CLK_SYS_GFX_CFG>, <&cgu_clk CLK_SYS_DMAC_CORE>, - <&cgu_clk CLK_SYS_DMAC_CFG>, <&cgu_clk CLK_SYS_SDIO_REF>, - <&cgu_clk CLK_SYS_SPI_REF>, <&cgu_clk CLK_SYS_I2C_REF>, - <&cgu_clk CLK_SYS_UART_REF>, <&cgu_clk CLK_SYS_EBI_REF>, - <&cgu_clk CLK_TUN_ROM>, <&cgu_clk CLK_TUN_PWM>; - clock-names = "cpu-pll", "sys-pll", - "tun-pll", "ddr-clk", - "cpu-clk", "hdmi-pll", - "tun-clk", "hdmi-clk", - "apb-clk", "axi-clk", - "eth-clk", "usb-clk", - "sdio-clk", "hdmi-sys-clk", - "gfx-core-clk", "gfx-dma-clk", - "gfx-cfg-clk", "dmac-core-clk", - "dmac-cfg-clk", "sdio-ref-clk", - "spi-clk", "i2c-clk", - "uart-clk", "ebi-clk", - "rom-clk", "pwm-clk"; - }; - - cgu_clk: cgu-clk@f0000000 { - compatible = "snps,hsdk-cgu-clock"; - reg = <0xf0000000 0x10>, <0xf00014B8 0x4>; - #clock-cells = <1>; - }; - - cgu_rst: reset-controller@f00008a0 { - compatible = "snps,hsdk-reset"; - #reset-cells = <1>; - reg = <0xf00008a0 0x4>, <0xf0000ff0 0x4>; - }; - - uart0: serial0@f0005000 { - compatible = "snps,dw-apb-uart"; - reg = <0xf0005000 0x1000>; - reg-shift = <2>; - reg-io-width = <4>; - }; - - ethernet@f0008000 { - #interrupt-cells = <1>; - compatible = "snps,arc-dwmac-3.70a"; - reg = <0xf0008000 0x2000>; - phy-mode = "gmii"; - }; - - ehci@0xf0040000 { - compatible = "generic-ehci"; - reg = <0xf0040000 0x100>; - }; - - ohci@0xf0060000 { - compatible = "generic-ohci"; - reg = <0xf0060000 0x100>; - }; - - mmcclk_ciu: mmcclk-ciu { - compatible = "fixed-clock"; - /* - * DW sdio controller has external ciu clock divider - * controlled via register in SDIO IP. Due to its - * unexpected default value (it should divide by 1 - * but it divides by 8) SDIO IP uses wrong clock and - * works unstable (see STAR 9001204800) - * We switched to the minimum possible value of the - * divisor (div-by-2) in HSDK platform code. - * So default mmcclk ciu clock is 50000000 Hz. - */ - clock-frequency = <50000000>; - #clock-cells = <0>; - }; - - mmc: mmc0@f000a000 { - compatible = "snps,dw-mshc"; - reg = <0xf000a000 0x400>; - bus-width = <4>; - fifo-depth = <256>; - clocks = <&cgu_clk CLK_SYS_SDIO>, <&mmcclk_ciu>; - clock-names = "biu", "ciu"; - max-frequency = <25000000>; - }; - - spi0: spi@f0020000 { - compatible = "snps,dw-apb-ssi"; - reg = <0xf0020000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - spi-max-frequency = <4000000>; - clocks = <&cgu_clk CLK_SYS_SPI_REF>; - clock-names = "spi_clk"; - cs-gpio = <&cs_gpio 0>; - spi_flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <4000000>; - }; - }; - - cs_gpio: gpio@f00014b0 { - compatible = "snps,creg-gpio"; - reg = <0xf00014b0 0x4>; - gpio-controller; - #gpio-cells = <1>; - gpio-bank-name = "hsdk-spi-cs"; - gpio-count = <1>; - gpio-first-shift = <0>; - gpio-bit-per-line = <2>; - gpio-activate-val = <2>; - gpio-deactivate-val = <3>; - gpio-default-val = <1>; - }; }; diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index fff6591c68..516c14e105 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -51,6 +51,9 @@ #define ARC_AUX_DCCM_BASE 0x18 /* DCCM Base Addr ARCv2 */ #define ARC_AUX_ICCM_BASE 0x208 /* ICCM Base Addr ARCv2 */ +/* CSM auxiliary registers */ +#define ARC_AUX_CSM_ENABLE 0x9A0 + /* Timer related auxiliary registers */ #define ARC_AUX_TIMER0_CNT 0x21 /* Timer 0 count */ #define ARC_AUX_TIMER0_CTRL 0x22 /* Timer 0 control */ @@ -100,6 +103,7 @@ /* DSP-extensions related auxiliary registers */ #define ARC_AUX_DSP_BUILD 0x7A +#define ARC_AUX_DSP_CTRL 0x59F /* ARC Subsystems related auxiliary registers */ #define ARC_AUX_SUBSYS_BUILD 0xF0 diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S index 8c744f5be7..016ae85be2 100644 --- a/arch/arc/lib/start.S +++ b/arch/arc/lib/start.S @@ -61,6 +61,21 @@ ENTRY(_start) 1: #endif +#ifdef CONFIG_ISA_ARCV2 + ; In case of DSP extension presence in HW some instructions + ; (related to integer multiply, multiply-accumulate, and divide + ; operation) executes on this DSP execution unit. So their + ; execution will depend on dsp configuration register (DSP_CTRL) + ; As we want these instructions to execute the same way regardless + ; of DSP presence we need to set DSP_CTRL properly. + lr r5, [ARC_AUX_DSP_BUILD] + bmsk r5, r5, 7 + breq r5, 0, 1f + mov r5, 0 + sr r5, [ARC_AUX_DSP_CTRL] +1: +#endif + #ifdef __ARC_UNALIGNED__ /* * Enable handling of unaligned access in the CPU as by default diff --git a/board/synopsys/hsdk/Kconfig b/board/synopsys/hsdk/Kconfig index e8c00a6e7d..d9c0e27a41 100644 --- a/board/synopsys/hsdk/Kconfig +++ b/board/synopsys/hsdk/Kconfig @@ -7,6 +7,24 @@ config SYS_VENDOR default "synopsys" config SYS_CONFIG_NAME - default "hsdk" + default "hsdk" if BOARD_HSDK + default "hsdk-4xd" if BOARD_HSDK_4XD + +choice + prompt "HSDK board type" + default BOARD_HSDK + +config BOARD_HSDK + bool "ARC HS Development Kit" + help + ARC HS Development Kit based on quard core ARC HS38 processor + +config BOARD_HSDK_4XD + bool "ARC HS4x/HS4xD Development Kit" + help + ARC HS4x/HS4xD Development Kit based on quard core ARC HS48/HS47D + processor + +endchoice endif diff --git a/board/synopsys/hsdk/MAINTAINERS b/board/synopsys/hsdk/MAINTAINERS index e22bd1e40b..73f71fd06b 100644 --- a/board/synopsys/hsdk/MAINTAINERS +++ b/board/synopsys/hsdk/MAINTAINERS @@ -1,5 +1,8 @@ -HSDK BOARD +HSDK BOARDs M: Eugeniy Paltsev S: Maintained F: board/synopsys/hsdk/ F: configs/hsdk_defconfig +F: configs/hsdk_4xd_defconfig +F: include/configs/hsdk-4xd.h +F: include/configs/hsdk.h diff --git a/board/synopsys/hsdk/config.mk b/board/synopsys/hsdk/config.mk index 5ae22fa2b7..def944aad2 100644 --- a/board/synopsys/hsdk/config.mk +++ b/board/synopsys/hsdk/config.mk @@ -2,6 +2,7 @@ # # Copyright (C) 2018 Synopsys, Inc. All rights reserved. +ifdef CONFIG_BOARD_HSDK PLATFORM_CPPFLAGS += -mcpu=hs38_linux -mlittle-endian -matomic -mll64 \ -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ -mfpu=fpud_all @@ -13,3 +14,18 @@ bsp-generate: u-boot u-boot.bin $(Q)tools/mkimage -T script -C none -n 'uboot update script' \ -d $(srctree)/u-boot-update.txt \ $(srctree)/u-boot-update.scr &> /dev/null +endif + +ifdef CONFIG_BOARD_HSDK_4XD +PLATFORM_CPPFLAGS += -mcpu=hs4x_rel31 -mlittle-endian -matomic -mll64 \ + -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ + -mfpu=fpud_all + +bsp-generate: u-boot u-boot.bin + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ + --arc-id 0x54 --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot + $(Q)tools/mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.scr &> /dev/null +endif diff --git a/board/synopsys/hsdk/headerize-hsdk.py b/board/synopsys/hsdk/headerize-hsdk.py index fce749723e..7b047cf4a3 100644 --- a/board/synopsys/hsdk/headerize-hsdk.py +++ b/board/synopsys/hsdk/headerize-hsdk.py @@ -27,7 +27,7 @@ def calc_check_sum(filename): def arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id): - if arc_id not in [0x52, 0x53]: + if arc_id not in [0x52, 0x53, 0x54]: print("unknown ARC ID: " + hex(arc_id)) sys.exit(2) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 67a29e334d..a3e0563ff4 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -40,6 +40,9 @@ DECLARE_GLOBAL_DATA_PTR; #define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000) #define CREG_CPU_START (CREG_BASE + 0x400) #define CREG_CPU_START_MASK 0xF +#define CREG_CPU_START_POL BIT(4) + +#define CREG_CPU_0_ENTRY (CREG_BASE + 0x404) #define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000) #define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108) @@ -79,6 +82,9 @@ struct hsdk_env_common_ctl { u32_env nvlim; u32_env icache; u32_env dcache; + u32_env csm_location; + u32_env l2_cache; + u32_env haps_apb; }; /* @@ -128,6 +134,11 @@ static const struct env_map_common env_map_common[] = { { "non_volatile_limit", ENV_HEX, true, 0, 0xF, &env_common.nvlim }, { "icache_ena", ENV_HEX, true, 0, 1, &env_common.icache }, { "dcache_ena", ENV_HEX, true, 0, 1, &env_common.dcache }, +#if defined(CONFIG_BOARD_HSDK_4XD) + { "l2_cache_ena", ENV_HEX, true, 0, 1, &env_common.l2_cache }, + { "csm_location", ENV_HEX, true, 0, NO_CCM, &env_common.csm_location }, + { "haps_apb_location", ENV_HEX, true, 0, 1, &env_common.haps_apb }, +#endif /* CONFIG_BOARD_HSDK_4XD */ {} }; @@ -154,6 +165,61 @@ static const struct env_map_percpu env_map_go[] = { {} }; +enum board_type { + T_BOARD_NONE, + T_BOARD_HSDK, + T_BOARD_HSDK_4XD +}; + +static inline enum board_type get_board_type_runtime(void) +{ + u32 arc_id = read_aux_reg(ARC_AUX_IDENTITY) & 0xFF; + + if (arc_id == 0x52) + return T_BOARD_HSDK; + else if (arc_id == 0x54) + return T_BOARD_HSDK_4XD; + else + return T_BOARD_NONE; +} + +static inline enum board_type get_board_type_config(void) +{ + if (IS_ENABLED(CONFIG_BOARD_HSDK)) + return T_BOARD_HSDK; + else if (IS_ENABLED(CONFIG_BOARD_HSDK_4XD)) + return T_BOARD_HSDK_4XD; + else + return T_BOARD_NONE; +} + +static bool is_board_match_runtime(enum board_type type_req) +{ + return get_board_type_runtime() == type_req; +} + +static bool is_board_match_config(enum board_type type_req) +{ + return get_board_type_config() == type_req; +} + +static const char * board_name(enum board_type type) +{ + switch (type) { + case T_BOARD_HSDK: + return "ARC HS Development Kit"; + case T_BOARD_HSDK_4XD: + return "ARC HS4x/HS4xD Development Kit"; + default: + return "?"; + } +} + +static bool board_mismatch(void) +{ + return get_board_type_config() != get_board_type_runtime(); +} + static void sync_cross_cpu_data(void) { u32 value; @@ -221,10 +287,48 @@ static void init_cluster_nvlim(void) flush_dcache_all(); write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val); - write_aux_reg(AUX_AUX_CACHE_LIMIT, val); + /* AUX_AUX_CACHE_LIMIT reg is missing starting from HS48 */ + if (is_board_match_runtime(T_BOARD_HSDK)) + write_aux_reg(AUX_AUX_CACHE_LIMIT, val); flush_n_invalidate_dcache_all(); } +static void init_cluster_slc(void) +{ + /* ARC HS38 doesn't support SLC disabling */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.l2_cache.val) + slc_enable(); + else + slc_disable(); +} + +#define CREG_CSM_BASE (CREG_BASE + 0x210) + +static void init_cluster_csm(void) +{ + /* ARC HS38 in HSDK SoC doesn't include CSM */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.csm_location.val == NO_CCM) { + write_aux_reg(ARC_AUX_CSM_ENABLE, 0); + } else { + /* + * CSM base address is 256kByte aligned but we allow to map + * CSM only to aperture start (256MByte aligned) + * The field in CREG_CSM_BASE is in 17:2 bits itself so we need + * to shift it. + */ + u32 csm_base = (env_common.csm_location.val * SZ_1K) << 2; + + write_aux_reg(ARC_AUX_CSM_ENABLE, 1); + writel(csm_base, (void __iomem *)CREG_CSM_BASE); + } +} + static void init_master_icache(void) { if (icache_status()) { @@ -279,25 +383,36 @@ static inline void halt_this_cpu(void) __builtin_arc_flag(1); } -static void smp_kick_cpu_x(u32 cpu_id) +static u32 get_masked_cpu_ctart_reg(void) { int cmd = readl((void __iomem *)CREG_CPU_START); + /* + * Quirk for HSDK-4xD - due to HW issues HSDK can use any pulse polarity + * and HSDK-4xD require active low polarity of cpu_start pulse. + */ + cmd &= ~CREG_CPU_START_POL; + + cmd &= ~CREG_CPU_START_MASK; + + return cmd; +} + +static void smp_kick_cpu_x(u32 cpu_id) +{ + int cmd; + if (cpu_id > NR_CPUS) return; - cmd &= ~CREG_CPU_START_MASK; + cmd = get_masked_cpu_ctart_reg(); cmd |= (1 << cpu_id); writel(cmd, (void __iomem *)CREG_CPU_START); } static u32 prepare_cpu_ctart_reg(void) { - int cmd = readl((void __iomem *)CREG_CPU_START); - - cmd &= ~CREG_CPU_START_MASK; - - return cmd | env_common.core_mask.val; + return get_masked_cpu_ctart_reg() | env_common.core_mask.val; } /* slave CPU entry for configuration */ @@ -560,6 +675,61 @@ void init_memory_bridge(void) writel(UPDATE_VAL, CREG_PAE_UPDT); } +/* + * For HSDK-4xD we do additional AXI bridge tweaking in hsdk_init command: + * - we shrink IOC region. + * - we configure HS CORE SLV1 aperture depending on haps_apb_location + * environment variable. + * + * As we've already configured AXI bridge in init_memory_bridge we don't + * do full configuration here but reconfigure changed part. + * + * m master AXI_M_m_SLV0 AXI_M_m_SLV1 AXI_M_m_OFFSET0 AXI_M_m_OFFSET1 + * 0 HS (CBU) 0x11111111 0x63111111 0xFEDCBA98 0x0E543210 [haps_apb_location = 0] + * 0 HS (CBU) 0x11111111 0x61111111 0xFEDCBA98 0x06543210 [haps_apb_location = 1] + * 1 HS (RTT) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 2 AXI Tunnel 0x88888888 0x88888888 0xFEDCBA98 0x76543210 + * 3 HDMI-VIDEO 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 4 HDMI-ADUIO 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 5 USB-HOST 0x77777777 0x77779999 0xFEDCBA98 0x7654BA98 + * 6 ETHERNET 0x77777777 0x77779999 0xFEDCBA98 0x7654BA98 + * 7 SDIO 0x77777777 0x77779999 0xFEDCBA98 0x7654BA98 + * 8 GPU 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 9 DMAC (port #1) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 10 DMAC (port #2) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 11 DVFS 0x00000000 0x60000000 0x00000000 0x00000000 + */ +void tweak_memory_bridge_cfg(void) +{ + /* + * Only HSDK-4xD requre additional AXI bridge tweaking depending on + * haps_apb_location environment variable + */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.haps_apb.val) { + writel(0x61111111, CREG_AXI_M_SLV1(M_HS_CORE)); + writel(0x06543210, CREG_AXI_M_OFT1(M_HS_CORE)); + } else { + writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE)); + writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE)); + } + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE)); + + writel(0x77779999, CREG_AXI_M_SLV1(M_USB_HOST)); + writel(0x7654BA98, CREG_AXI_M_OFT1(M_USB_HOST)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST)); + + writel(0x77779999, CREG_AXI_M_SLV1(M_ETHERNET));; + writel(0x7654BA98, CREG_AXI_M_OFT1(M_ETHERNET)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET)); + + writel(0x77779999, CREG_AXI_M_SLV1(M_SDIO)); + writel(0x7654BA98, CREG_AXI_M_OFT1(M_SDIO)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO)); +} + static void setup_clocks(void) { ulong rate; @@ -593,6 +763,9 @@ static void do_init_cluster(void) * cores. */ init_cluster_nvlim(); + init_cluster_csm(); + init_cluster_slc(); + tweak_memory_bridge_cfg(); } static int check_master_cpu_id(void) @@ -758,6 +931,11 @@ static int do_hsdk_go(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; + if (board_mismatch()) { + printf("ERR: U-boot is not configured for this board!\n"); + return CMD_RET_FAILURE; + } + /* * Check for 'halt' parameter. 'halt' = enter halt-mode just before * starting the application; can be used for debug. @@ -793,20 +971,45 @@ U_BOOT_CMD( "hsdk_go halt - Boot stand-alone application on HSDK, halt CPU just before application run\n" ); +/* + * We may simply use static variable here to store init status, but we also want + * to avoid the situation when we reload U-boot via MDB after previous + * init is done but HW reset (board reset) isn't done. So let's store the + * init status in any unused register (i.e CREG_CPU_0_ENTRY) so status will + * survive after U-boot is reloaded via MDB. + */ +#define INIT_MARKER_REGISTER ((void __iomem *)CREG_CPU_0_ENTRY) +/* must be equal to INIT_MARKER_REGISTER reset value */ +#define INIT_MARKER_PENDING 0 + +static bool init_marker_get(void) +{ + return readl(INIT_MARKER_REGISTER) != INIT_MARKER_PENDING; +} + +static void init_mark_done(void) +{ + writel(~INIT_MARKER_PENDING, INIT_MARKER_REGISTER); +} + static int do_hsdk_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - static bool done = false; int ret; + if (board_mismatch()) { + printf("ERR: U-boot is not configured for this board!\n"); + return CMD_RET_FAILURE; + } + /* hsdk_init can be run only once */ - if (done) { + if (init_marker_get()) { printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n"); return CMD_RET_FAILURE; } ret = prepare_cpus(); if (!ret) - done = true; + init_mark_done(); return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS; } @@ -911,10 +1114,13 @@ static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc, soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ); -/* soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); */ + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) + soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ); - soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ); - soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); + if (is_board_match_runtime(T_BOARD_HSDK)) { + soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); + } soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ); @@ -929,15 +1135,19 @@ static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc, printf("\n"); /* HDMI clock domain */ -/* soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ); */ -/* soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ); */ -/* printf("\n"); */ + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) { + soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ); + printf("\n"); + } /* TUN clock domain */ soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ); soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ); + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) + soc_clk_ctl("timer-clk", NULL, CLK_PRINT | CLK_MHZ); printf("\n"); return CMD_RET_SUCCESS; @@ -1031,6 +1241,11 @@ int board_late_init(void) int checkboard(void) { - puts("Board: Synopsys ARC HS Development Kit\n"); + printf("Board: Synopsys %s\n", board_name(get_board_type_runtime())); + + if (board_mismatch()) + printf("WARN: U-boot is configured NOT for this board but for %s!\n", + board_name(get_board_type_config())); + return 0; }; diff --git a/configs/hsdk_4xd_defconfig b/configs/hsdk_4xd_defconfig new file mode 100644 index 0000000000..64832ecbdf --- /dev/null +++ b/configs/hsdk_4xd_defconfig @@ -0,0 +1,67 @@ +CONFIG_ARC=y +CONFIG_ISA_ARCV2=y +CONFIG_TARGET_HSDK=y +CONFIG_BOARD_HSDK_4XD=y +CONFIG_SYS_TEXT_BASE=0x81000000 +CONFIG_DM_GPIO=y +CONFIG_DEBUG_UART_BASE=0xf0005000 +CONFIG_DEBUG_UART_CLOCK=33333333 +CONFIG_SYS_CLK_FREQ=500000000 +CONFIG_DEBUG_UART=y +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyS0,115200n8" +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_BOARD_EARLY_INIT_R=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="hsdk-4xd# " +CONFIG_CMD_ENV_FLAGS=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_OF_CONTROL=y +CONFIG_OF_EMBED=y +CONFIG_DEFAULT_DEVICE_TREE="hsdk-4xd" +CONFIG_ENV_IS_IN_FAT=y +CONFIG_ENV_FAT_INTERFACE="mmc" +CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_DM=y +CONFIG_CLK_HSDK=y +CONFIG_HSDK_CREG_GPIO=y +CONFIG_MMC=y +CONFIG_DM_MMC=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_SNPS=y +CONFIG_MTD=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH_SST=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_MII=y +CONFIG_DM_RESET=y +CONFIG_DM_SERIAL=y +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_DESIGNWARE_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +CONFIG_USB_STORAGE=y +CONFIG_USE_PRIVATE_LIBGCC=y +CONFIG_PANIC_HANG=y diff --git a/drivers/clk/clk-hsdk-cgu.c b/drivers/clk/clk-hsdk-cgu.c index 6eaafdeaf9..3035c5fb38 100644 --- a/drivers/clk/clk-hsdk-cgu.c +++ b/drivers/clk/clk-hsdk-cgu.c @@ -67,6 +67,7 @@ #define CGU_TUN_IDIV_TUN 0x380 #define CGU_TUN_IDIV_ROM 0x390 #define CGU_TUN_IDIV_PWM 0x3A0 +#define CGU_TUN_IDIV_TIMER 0x3B0 #define CGU_HDMI_IDIV_APB 0x480 #define CGU_SYS_IDIV_APB 0x180 #define CGU_SYS_IDIV_AXI 0x190 @@ -123,12 +124,12 @@ #define MIN_PLL_RATE 100000000 /* 100 MHz */ #define PARENT_RATE_33 33333333 /* fixed clock - xtal */ #define PARENT_RATE_27 27000000 /* fixed clock - xtal */ -#define CGU_MAX_CLOCKS 26 +#define CGU_MAX_CLOCKS 27 #define CGU_SYS_CLOCKS 16 #define MAX_AXI_CLOCKS 4 -#define CGU_TUN_CLOCKS 3 +#define CGU_TUN_CLOCKS 4 #define MAX_TUN_CLOCKS 6 struct hsdk_tun_idiv_cfg { @@ -147,7 +148,8 @@ static const struct hsdk_tun_clk_cfg tun_clk_cfg = { { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, { { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } }, { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } }, - { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } } + { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } }, + { CGU_TUN_IDIV_TIMER, { 12, 12, 12, 12, 15, 12 } } } }; @@ -316,6 +318,7 @@ static const struct hsdk_cgu_clock_map clock_map[] = { { CGU_TUN_PLL, 0, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off }, { CGU_TUN_PLL, 0, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, { CGU_TUN_PLL, 0, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, + { CGU_TUN_PLL, 0, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, { CGU_HDMI_PLL, 0, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, { CGU_HDMI_PLL, 0, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } }; diff --git a/include/configs/hsdk-4xd.h b/include/configs/hsdk-4xd.h new file mode 100644 index 0000000000..4628108075 --- /dev/null +++ b/include/configs/hsdk-4xd.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev + */ + +#ifndef _CONFIG_HSDK_H_ +#define _CONFIG_HSDK_H_ + +#include + +/* + * CPU configuration + */ +#define NR_CPUS 4 +#define ARC_PERIPHERAL_BASE 0xF0000000 +#define ARC_DWMMC_BASE (ARC_PERIPHERAL_BASE + 0xA000) +#define ARC_DWGMAC_BASE (ARC_PERIPHERAL_BASE + 0x18000) + +/* + * Memory configuration + */ +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE + +#define CONFIG_SYS_DDR_SDRAM_BASE 0x80000000 +#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_DDR_SDRAM_BASE +#define CONFIG_SYS_SDRAM_SIZE SZ_1G + +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) + +#define CONFIG_SYS_MALLOC_LEN SZ_2M +#define CONFIG_SYS_BOOTM_LEN SZ_128M +#define CONFIG_SYS_LOAD_ADDR 0x82000000 + +/* + * UART configuration + */ +#define CONFIG_SYS_NS16550_SERIAL +#define CONFIG_SYS_NS16550_CLK 33330000 +#define CONFIG_SYS_NS16550_MEM32 + +/* + * Ethernet PHY configuration + */ + +/* + * USB 1.1 configuration + */ +#define CONFIG_USB_OHCI_NEW +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 + +/* + * Environment settings + */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "upgrade=if mmc rescan && " \ + "fatload mmc 0:1 ${loadaddr} u-boot-update.scr && " \ + "iminfo ${loadaddr} && source ${loadaddr}; then; else echo " \ + "\"Fail to upgrade.\n" \ + "Do you have u-boot-update.scr and u-boot.head on first (FAT) SD card partition?\"" \ + "; fi\0" \ + "core_mask=0xF\0" \ + "hsdk_hs45d=setenv core_mask 0x2; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x0; setenv icache_ena 0x0; setenv csm_location 0x10; \ +setenv dcache_ena 0x0; setenv core_iccm_1 0x7; \ +setenv core_dccm_1 0x8; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs47d=setenv core_mask 0x1; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x0; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs47d_ccm=setenv core_mask 0x2; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x0; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_1 0x7; \ +setenv core_dccm_1 0x8; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs48=setenv core_mask 0x1; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs48_ccm=setenv core_mask 0x2; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_1 0x7; \ +setenv core_dccm_1 0x8; setenv non_volatile_limit 0xF;\0" \ + "hsdk_hs48x2=run hsdk_hs47dx2;\0" \ + "hsdk_hs47dx2=setenv core_mask 0x3; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_volatile_limit 0xF; \ +setenv core_iccm_1 0x6; setenv core_dccm_1 0x6;\0" \ + "hsdk_hs48x3=run hsdk_hs47dx3;\0" \ + "hsdk_hs47dx3=setenv core_mask 0x7; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_volatile_limit 0xF; \ +setenv core_iccm_1 0x6; setenv core_dccm_1 0x6; \ +setenv core_iccm_2 0x10; setenv core_dccm_2 0x10;\0" \ + "hsdk_hs48x4=run hsdk_hs47dx4;\0" \ + "hsdk_hs47dx4=setenv core_mask 0xF; setenv haps_apb_location 0x1; \ +setenv l2_cache_ena 0x1; setenv icache_ena 0x1; setenv csm_location 0x10; \ +setenv dcache_ena 0x1; setenv core_iccm_0 0x10; \ +setenv core_dccm_0 0x10; setenv non_volatile_limit 0xF; \ +setenv core_iccm_1 0x6; setenv core_dccm_1 0x6; \ +setenv core_iccm_2 0x10; setenv core_dccm_2 0x10; \ +setenv core_iccm_3 0x6; setenv core_dccm_3 0x6;\0" + +/* + * Environment configuration + */ +#define CONFIG_BOOTFILE "uImage" +#define CONFIG_LOADADDR CONFIG_SYS_LOAD_ADDR + +/* Cli configuration */ +#define CONFIG_SYS_CBSIZE SZ_2K + +/* + * Callback configuration + */ +#define CONFIG_BOARD_LATE_INIT + +#endif /* _CONFIG_HSDK_H_ */ diff --git a/include/dt-bindings/clock/snps,hsdk-cgu.h b/include/dt-bindings/clock/snps,hsdk-cgu.h index 2cfe34eb35..1ce7661cd9 100644 --- a/include/dt-bindings/clock/snps,hsdk-cgu.h +++ b/include/dt-bindings/clock/snps,hsdk-cgu.h @@ -36,7 +36,8 @@ #define CLK_TUN_TUN 21 #define CLK_TUN_ROM 22 #define CLK_TUN_PWM 23 -#define CLK_HDMI_PLL 24 -#define CLK_HDMI 25 +#define CLK_TUN_TIMER 24 +#define CLK_HDMI_PLL 25 +#define CLK_HDMI 26 #endif /* __DT_BINDINGS_CLK_HSDK_CGU_H_ */