1bda920c6SVitaly Andrianov /* 2bda920c6SVitaly Andrianov * K2G EVM : Board initialization 3bda920c6SVitaly Andrianov * 4bda920c6SVitaly Andrianov * (C) Copyright 2015 5bda920c6SVitaly Andrianov * Texas Instruments Incorporated, <www.ti.com> 6bda920c6SVitaly Andrianov * 7bda920c6SVitaly Andrianov * SPDX-License-Identifier: GPL-2.0+ 8bda920c6SVitaly Andrianov */ 9bda920c6SVitaly Andrianov #include <common.h> 10bda920c6SVitaly Andrianov #include <asm/arch/clock.h> 1191266ccbSVitaly Andrianov #include <asm/ti-common/keystone_net.h> 123b68939fSRoger Quadros #include <asm/arch/psc_defs.h> 133b68939fSRoger Quadros #include <asm/arch/mmc_host_def.h> 145f48da9aSCooper Jr., Franklin #include <fdtdec.h> 155f48da9aSCooper Jr., Franklin #include <i2c.h> 16dd78b8cfSVitaly Andrianov #include "mux-k2g.h" 17752a8311SRoger Quadros #include "../common/board_detect.h" 18bda920c6SVitaly Andrianov 195f48da9aSCooper Jr., Franklin #define K2G_GP_AUDIO_CODEC_ADDRESS 0x1B 205f48da9aSCooper Jr., Franklin 21c5f177deSLokesh Vutla const unsigned int sysclk_array[MAX_SYSCLK] = { 22c5f177deSLokesh Vutla 19200000, 23c5f177deSLokesh Vutla 24000000, 24c5f177deSLokesh Vutla 25000000, 25c5f177deSLokesh Vutla 26000000, 26c5f177deSLokesh Vutla }; 27c5f177deSLokesh Vutla 28ee3c6532SLokesh Vutla unsigned int get_external_clk(u32 clk) 29ee3c6532SLokesh Vutla { 30ee3c6532SLokesh Vutla unsigned int clk_freq; 31ee3c6532SLokesh Vutla u8 sysclk_index = get_sysclk_index(); 32ee3c6532SLokesh Vutla 33ee3c6532SLokesh Vutla switch (clk) { 34ee3c6532SLokesh Vutla case sys_clk: 35ee3c6532SLokesh Vutla clk_freq = sysclk_array[sysclk_index]; 36ee3c6532SLokesh Vutla break; 37ee3c6532SLokesh Vutla case pa_clk: 38ee3c6532SLokesh Vutla clk_freq = sysclk_array[sysclk_index]; 39ee3c6532SLokesh Vutla break; 40ee3c6532SLokesh Vutla case tetris_clk: 41ee3c6532SLokesh Vutla clk_freq = sysclk_array[sysclk_index]; 42ee3c6532SLokesh Vutla break; 43ee3c6532SLokesh Vutla case ddr3a_clk: 44ee3c6532SLokesh Vutla clk_freq = sysclk_array[sysclk_index]; 45ee3c6532SLokesh Vutla break; 46ee3c6532SLokesh Vutla case uart_clk: 47ee3c6532SLokesh Vutla clk_freq = sysclk_array[sysclk_index]; 48ee3c6532SLokesh Vutla break; 49ee3c6532SLokesh Vutla default: 50ee3c6532SLokesh Vutla clk_freq = 0; 51ee3c6532SLokesh Vutla break; 52ee3c6532SLokesh Vutla } 53ee3c6532SLokesh Vutla 54ee3c6532SLokesh Vutla return clk_freq; 55ee3c6532SLokesh Vutla } 56e6d71e1cSVitaly Andrianov 57ef76ebb1SLokesh Vutla static int arm_speeds[DEVSPEED_NUMSPDS] = { 58ef76ebb1SLokesh Vutla SPD400, 59ef76ebb1SLokesh Vutla SPD600, 60ef76ebb1SLokesh Vutla SPD800, 61ef76ebb1SLokesh Vutla SPD900, 62ef76ebb1SLokesh Vutla SPD1000, 63ef76ebb1SLokesh Vutla SPD900, 64ef76ebb1SLokesh Vutla SPD800, 65ef76ebb1SLokesh Vutla SPD600, 66ef76ebb1SLokesh Vutla SPD400, 67ef76ebb1SLokesh Vutla SPD200, 68ef76ebb1SLokesh Vutla }; 69ef76ebb1SLokesh Vutla 70ef76ebb1SLokesh Vutla static int dev_speeds[DEVSPEED_NUMSPDS] = { 71ef76ebb1SLokesh Vutla SPD600, 72ef76ebb1SLokesh Vutla SPD800, 73ef76ebb1SLokesh Vutla SPD900, 74ef76ebb1SLokesh Vutla SPD1000, 75ef76ebb1SLokesh Vutla SPD900, 76ef76ebb1SLokesh Vutla SPD800, 77ef76ebb1SLokesh Vutla SPD600, 78ef76ebb1SLokesh Vutla SPD400, 79ef76ebb1SLokesh Vutla }; 80ef76ebb1SLokesh Vutla 81c5f177deSLokesh Vutla static struct pll_init_data main_pll_config[MAX_SYSCLK][NUM_SPDS] = { 82c5f177deSLokesh Vutla [SYSCLK_19MHz] = { 83c5f177deSLokesh Vutla [SPD400] = {MAIN_PLL, 125, 3, 2}, 84c5f177deSLokesh Vutla [SPD600] = {MAIN_PLL, 125, 2, 2}, 85c5f177deSLokesh Vutla [SPD800] = {MAIN_PLL, 250, 3, 2}, 869cb5eaf2SLokesh Vutla [SPD900] = {MAIN_PLL, 187, 2, 2}, 879cb5eaf2SLokesh Vutla [SPD1000] = {MAIN_PLL, 104, 1, 2}, 88c5f177deSLokesh Vutla }, 89c5f177deSLokesh Vutla [SYSCLK_24MHz] = { 90ef76ebb1SLokesh Vutla [SPD400] = {MAIN_PLL, 100, 3, 2}, 91ef76ebb1SLokesh Vutla [SPD600] = {MAIN_PLL, 300, 6, 2}, 92ef76ebb1SLokesh Vutla [SPD800] = {MAIN_PLL, 200, 3, 2}, 939cb5eaf2SLokesh Vutla [SPD900] = {MAIN_PLL, 75, 1, 2}, 949cb5eaf2SLokesh Vutla [SPD1000] = {MAIN_PLL, 250, 3, 2}, 95c5f177deSLokesh Vutla }, 96c5f177deSLokesh Vutla [SYSCLK_25MHz] = { 97c5f177deSLokesh Vutla [SPD400] = {MAIN_PLL, 32, 1, 2}, 98c5f177deSLokesh Vutla [SPD600] = {MAIN_PLL, 48, 1, 2}, 99c5f177deSLokesh Vutla [SPD800] = {MAIN_PLL, 64, 1, 2}, 1009cb5eaf2SLokesh Vutla [SPD900] = {MAIN_PLL, 72, 1, 2}, 1019cb5eaf2SLokesh Vutla [SPD1000] = {MAIN_PLL, 80, 1, 2}, 102c5f177deSLokesh Vutla }, 103c5f177deSLokesh Vutla [SYSCLK_26MHz] = { 104c5f177deSLokesh Vutla [SPD400] = {MAIN_PLL, 400, 13, 2}, 105c5f177deSLokesh Vutla [SPD600] = {MAIN_PLL, 230, 5, 2}, 106c5f177deSLokesh Vutla [SPD800] = {MAIN_PLL, 123, 2, 2}, 1079cb5eaf2SLokesh Vutla [SPD900] = {MAIN_PLL, 69, 1, 2}, 1089cb5eaf2SLokesh Vutla [SPD1000] = {MAIN_PLL, 384, 5, 2}, 109c5f177deSLokesh Vutla }, 110ef76ebb1SLokesh Vutla }; 111ef76ebb1SLokesh Vutla 112c5f177deSLokesh Vutla static struct pll_init_data tetris_pll_config[MAX_SYSCLK][NUM_SPDS] = { 113c5f177deSLokesh Vutla [SYSCLK_19MHz] = { 114c5f177deSLokesh Vutla [SPD200] = {TETRIS_PLL, 625, 6, 10}, 115c5f177deSLokesh Vutla [SPD400] = {TETRIS_PLL, 125, 1, 6}, 116c5f177deSLokesh Vutla [SPD600] = {TETRIS_PLL, 125, 1, 4}, 117c5f177deSLokesh Vutla [SPD800] = {TETRIS_PLL, 333, 2, 4}, 118c5f177deSLokesh Vutla [SPD900] = {TETRIS_PLL, 187, 2, 2}, 119c5f177deSLokesh Vutla [SPD1000] = {TETRIS_PLL, 104, 1, 2}, 120c5f177deSLokesh Vutla }, 121c5f177deSLokesh Vutla [SYSCLK_24MHz] = { 122ef76ebb1SLokesh Vutla [SPD200] = {TETRIS_PLL, 250, 3, 10}, 123ef76ebb1SLokesh Vutla [SPD400] = {TETRIS_PLL, 100, 1, 6}, 124ef76ebb1SLokesh Vutla [SPD600] = {TETRIS_PLL, 100, 1, 4}, 125ef76ebb1SLokesh Vutla [SPD800] = {TETRIS_PLL, 400, 3, 4}, 126ef76ebb1SLokesh Vutla [SPD900] = {TETRIS_PLL, 75, 1, 2}, 127ef76ebb1SLokesh Vutla [SPD1000] = {TETRIS_PLL, 250, 3, 2}, 128c5f177deSLokesh Vutla }, 129c5f177deSLokesh Vutla [SYSCLK_25MHz] = { 130c5f177deSLokesh Vutla [SPD200] = {TETRIS_PLL, 80, 1, 10}, 131c5f177deSLokesh Vutla [SPD400] = {TETRIS_PLL, 96, 1, 6}, 132c5f177deSLokesh Vutla [SPD600] = {TETRIS_PLL, 96, 1, 4}, 133c5f177deSLokesh Vutla [SPD800] = {TETRIS_PLL, 128, 1, 4}, 134c5f177deSLokesh Vutla [SPD900] = {TETRIS_PLL, 72, 1, 2}, 135c5f177deSLokesh Vutla [SPD1000] = {TETRIS_PLL, 80, 1, 2}, 136c5f177deSLokesh Vutla }, 137c5f177deSLokesh Vutla [SYSCLK_26MHz] = { 138c5f177deSLokesh Vutla [SPD200] = {TETRIS_PLL, 307, 4, 10}, 139c5f177deSLokesh Vutla [SPD400] = {TETRIS_PLL, 369, 4, 6}, 140c5f177deSLokesh Vutla [SPD600] = {TETRIS_PLL, 369, 4, 4}, 141c5f177deSLokesh Vutla [SPD800] = {TETRIS_PLL, 123, 1, 4}, 142c5f177deSLokesh Vutla [SPD900] = {TETRIS_PLL, 69, 1, 2}, 143c5f177deSLokesh Vutla [SPD1000] = {TETRIS_PLL, 384, 5, 2}, 144c5f177deSLokesh Vutla }, 145ef76ebb1SLokesh Vutla }; 146ef76ebb1SLokesh Vutla 147c5f177deSLokesh Vutla static struct pll_init_data uart_pll_config[MAX_SYSCLK] = { 148c5f177deSLokesh Vutla [SYSCLK_19MHz] = {UART_PLL, 160, 1, 8}, 149c5f177deSLokesh Vutla [SYSCLK_24MHz] = {UART_PLL, 128, 1, 8}, 150c5f177deSLokesh Vutla [SYSCLK_25MHz] = {UART_PLL, 768, 5, 10}, 151c5f177deSLokesh Vutla [SYSCLK_26MHz] = {UART_PLL, 384, 13, 2}, 152c5f177deSLokesh Vutla }; 153c5f177deSLokesh Vutla 154c5f177deSLokesh Vutla static struct pll_init_data nss_pll_config[MAX_SYSCLK] = { 155c5f177deSLokesh Vutla [SYSCLK_19MHz] = {NSS_PLL, 625, 6, 2}, 156c5f177deSLokesh Vutla [SYSCLK_24MHz] = {NSS_PLL, 250, 3, 2}, 157c5f177deSLokesh Vutla [SYSCLK_25MHz] = {NSS_PLL, 80, 1, 2}, 158c5f177deSLokesh Vutla [SYSCLK_26MHz] = {NSS_PLL, 1000, 13, 2}, 159c5f177deSLokesh Vutla }; 160c5f177deSLokesh Vutla 161c5f177deSLokesh Vutla static struct pll_init_data ddr3_pll_config[MAX_SYSCLK] = { 162c5f177deSLokesh Vutla [SYSCLK_19MHz] = {DDR3A_PLL, 167, 1, 16}, 163c5f177deSLokesh Vutla [SYSCLK_24MHz] = {DDR3A_PLL, 133, 1, 16}, 164c5f177deSLokesh Vutla [SYSCLK_25MHz] = {DDR3A_PLL, 128, 1, 16}, 165c5f177deSLokesh Vutla [SYSCLK_26MHz] = {DDR3A_PLL, 123, 1, 16}, 166c5f177deSLokesh Vutla }; 167bda920c6SVitaly Andrianov 168bda920c6SVitaly Andrianov struct pll_init_data *get_pll_init_data(int pll) 169bda920c6SVitaly Andrianov { 170ef76ebb1SLokesh Vutla int speed; 171bda920c6SVitaly Andrianov struct pll_init_data *data = NULL; 172c5f177deSLokesh Vutla u8 sysclk_index = get_sysclk_index(); 173bda920c6SVitaly Andrianov 174bda920c6SVitaly Andrianov switch (pll) { 175bda920c6SVitaly Andrianov case MAIN_PLL: 176ef76ebb1SLokesh Vutla speed = get_max_dev_speed(dev_speeds); 177c5f177deSLokesh Vutla data = &main_pll_config[sysclk_index][speed]; 178bda920c6SVitaly Andrianov break; 179bda920c6SVitaly Andrianov case TETRIS_PLL: 180ef76ebb1SLokesh Vutla speed = get_max_arm_speed(arm_speeds); 181c5f177deSLokesh Vutla data = &tetris_pll_config[sysclk_index][speed]; 182bda920c6SVitaly Andrianov break; 183bda920c6SVitaly Andrianov case NSS_PLL: 184c5f177deSLokesh Vutla data = &nss_pll_config[sysclk_index]; 185bda920c6SVitaly Andrianov break; 186bda920c6SVitaly Andrianov case UART_PLL: 187c5f177deSLokesh Vutla data = &uart_pll_config[sysclk_index]; 188bda920c6SVitaly Andrianov break; 189bda920c6SVitaly Andrianov case DDR3_PLL: 190c5f177deSLokesh Vutla data = &ddr3_pll_config[sysclk_index]; 191bda920c6SVitaly Andrianov break; 192bda920c6SVitaly Andrianov default: 193bda920c6SVitaly Andrianov data = NULL; 194bda920c6SVitaly Andrianov } 195bda920c6SVitaly Andrianov 196bda920c6SVitaly Andrianov return data; 197bda920c6SVitaly Andrianov } 198bda920c6SVitaly Andrianov 199bda920c6SVitaly Andrianov s16 divn_val[16] = { 200bda920c6SVitaly Andrianov -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 201bda920c6SVitaly Andrianov }; 202bda920c6SVitaly Andrianov 2034aa2ba3aSMasahiro Yamada #if defined(CONFIG_MMC) 2043b68939fSRoger Quadros int board_mmc_init(bd_t *bis) 2053b68939fSRoger Quadros { 2063b68939fSRoger Quadros if (psc_enable_module(KS2_LPSC_MMC)) { 2073b68939fSRoger Quadros printf("%s module enabled failed\n", __func__); 2083b68939fSRoger Quadros return -1; 2093b68939fSRoger Quadros } 2103b68939fSRoger Quadros 2113b68939fSRoger Quadros omap_mmc_init(0, 0, 0, -1, -1); 2123b68939fSRoger Quadros omap_mmc_init(1, 0, 0, -1, -1); 2133b68939fSRoger Quadros return 0; 2143b68939fSRoger Quadros } 2153b68939fSRoger Quadros #endif 2163b68939fSRoger Quadros 2177234f215SCooper Jr., Franklin #if defined(CONFIG_FIT_EMBED) 2187234f215SCooper Jr., Franklin int board_fit_config_name_match(const char *name) 2197234f215SCooper Jr., Franklin { 2207234f215SCooper Jr., Franklin bool eeprom_read = board_ti_was_eeprom_read(); 2217234f215SCooper Jr., Franklin 2227234f215SCooper Jr., Franklin if (!strcmp(name, "keystone-k2g-generic") && !eeprom_read) 2237234f215SCooper Jr., Franklin return 0; 2247234f215SCooper Jr., Franklin else if (!strcmp(name, "keystone-k2g-evm") && board_ti_is("66AK2GGP")) 2257234f215SCooper Jr., Franklin return 0; 2267234f215SCooper Jr., Franklin else 2277234f215SCooper Jr., Franklin return -1; 2287234f215SCooper Jr., Franklin } 2297234f215SCooper Jr., Franklin #endif 2307234f215SCooper Jr., Franklin 2315f48da9aSCooper Jr., Franklin #if defined(CONFIG_DTB_RESELECT) 2325f48da9aSCooper Jr., Franklin static int k2g_alt_board_detect(void) 2335f48da9aSCooper Jr., Franklin { 2345f48da9aSCooper Jr., Franklin int rc; 2355f48da9aSCooper Jr., Franklin 2365f48da9aSCooper Jr., Franklin rc = i2c_set_bus_num(1); 2375f48da9aSCooper Jr., Franklin if (rc) 2385f48da9aSCooper Jr., Franklin return rc; 2395f48da9aSCooper Jr., Franklin 2405f48da9aSCooper Jr., Franklin rc = i2c_probe(K2G_GP_AUDIO_CODEC_ADDRESS); 2415f48da9aSCooper Jr., Franklin if (rc) 2425f48da9aSCooper Jr., Franklin return rc; 2435f48da9aSCooper Jr., Franklin 2445f48da9aSCooper Jr., Franklin ti_i2c_eeprom_am_set("66AK2GGP", "1.0X"); 2455f48da9aSCooper Jr., Franklin 2465f48da9aSCooper Jr., Franklin return 0; 2475f48da9aSCooper Jr., Franklin } 2485f48da9aSCooper Jr., Franklin 249e2924e59SLokesh Vutla static void k2g_reset_mux_config(void) 250e2924e59SLokesh Vutla { 251e2924e59SLokesh Vutla /* Unlock the reset mux register */ 252e2924e59SLokesh Vutla clrbits_le32(KS2_RSTMUX8, RSTMUX_LOCK8_MASK); 253e2924e59SLokesh Vutla 254e2924e59SLokesh Vutla /* Configure BOOTCFG_RSTMUX8 for WDT event to cause a device reset */ 255e2924e59SLokesh Vutla clrsetbits_le32(KS2_RSTMUX8, RSTMUX_OMODE8_MASK, 256e2924e59SLokesh Vutla RSTMUX_OMODE8_DEV_RESET << RSTMUX_OMODE8_SHIFT); 257e2924e59SLokesh Vutla 258e2924e59SLokesh Vutla /* lock the reset mux register to prevent any spurious writes. */ 259e2924e59SLokesh Vutla setbits_le32(KS2_RSTMUX8, RSTMUX_LOCK8_MASK); 260e2924e59SLokesh Vutla } 261e2924e59SLokesh Vutla 262e820f523SCooper Jr., Franklin int embedded_dtb_select(void) 263bda920c6SVitaly Andrianov { 264e820f523SCooper Jr., Franklin int rc; 265e820f523SCooper Jr., Franklin rc = ti_i2c_eeprom_am_get(CONFIG_EEPROM_BUS_ADDRESS, 266e820f523SCooper Jr., Franklin CONFIG_EEPROM_CHIP_ADDRESS); 267e820f523SCooper Jr., Franklin if (rc) { 268e820f523SCooper Jr., Franklin rc = k2g_alt_board_detect(); 269e820f523SCooper Jr., Franklin if (rc) { 270e820f523SCooper Jr., Franklin printf("Unable to do board detection\n"); 271e820f523SCooper Jr., Franklin return -1; 272e820f523SCooper Jr., Franklin } 273e820f523SCooper Jr., Franklin } 274bda920c6SVitaly Andrianov 275e820f523SCooper Jr., Franklin fdtdec_setup(); 276dd78b8cfSVitaly Andrianov 277*b9b342eaSCooper Jr., Franklin k2g_mux_config(); 278*b9b342eaSCooper Jr., Franklin 279e2924e59SLokesh Vutla k2g_reset_mux_config(); 280e2924e59SLokesh Vutla 28183b9bf11SLokesh Vutla /* deassert FLASH_HOLD */ 28283b9bf11SLokesh Vutla clrbits_le32(K2G_GPIO1_BANK2_BASE + K2G_GPIO_DIR_OFFSET, 28383b9bf11SLokesh Vutla BIT(9)); 28483b9bf11SLokesh Vutla setbits_le32(K2G_GPIO1_BANK2_BASE + K2G_GPIO_SETDATA_OFFSET, 28583b9bf11SLokesh Vutla BIT(9)); 28683b9bf11SLokesh Vutla 287bda920c6SVitaly Andrianov return 0; 288bda920c6SVitaly Andrianov } 289bda920c6SVitaly Andrianov #endif 290bda920c6SVitaly Andrianov 291752a8311SRoger Quadros #ifdef CONFIG_BOARD_LATE_INIT 292752a8311SRoger Quadros int board_late_init(void) 293752a8311SRoger Quadros { 294752a8311SRoger Quadros #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_TI_I2C_BOARD_DETECT) 295752a8311SRoger Quadros int rc; 296752a8311SRoger Quadros 297752a8311SRoger Quadros rc = ti_i2c_eeprom_am_get(CONFIG_EEPROM_BUS_ADDRESS, 298752a8311SRoger Quadros CONFIG_EEPROM_CHIP_ADDRESS); 299752a8311SRoger Quadros if (rc) 300752a8311SRoger Quadros printf("ti_i2c_eeprom_init failed %d\n", rc); 301752a8311SRoger Quadros 302752a8311SRoger Quadros board_ti_set_ethaddr(1); 303752a8311SRoger Quadros #endif 304752a8311SRoger Quadros 305752a8311SRoger Quadros return 0; 306752a8311SRoger Quadros } 307752a8311SRoger Quadros #endif 308752a8311SRoger Quadros 309e820f523SCooper Jr., Franklin #ifdef CONFIG_BOARD_EARLY_INIT_F 310e820f523SCooper Jr., Franklin int board_early_init_f(void) 311e820f523SCooper Jr., Franklin { 312e820f523SCooper Jr., Franklin init_plls(); 313e820f523SCooper Jr., Franklin 314e820f523SCooper Jr., Franklin k2g_mux_config(); 315e820f523SCooper Jr., Franklin 316e820f523SCooper Jr., Franklin return 0; 317e820f523SCooper Jr., Franklin } 318e820f523SCooper Jr., Franklin #endif 319e820f523SCooper Jr., Franklin 320bda920c6SVitaly Andrianov #ifdef CONFIG_SPL_BUILD 321bda920c6SVitaly Andrianov void spl_init_keystone_plls(void) 322bda920c6SVitaly Andrianov { 323bda920c6SVitaly Andrianov init_plls(); 324bda920c6SVitaly Andrianov } 325bda920c6SVitaly Andrianov #endif 32691266ccbSVitaly Andrianov 32791266ccbSVitaly Andrianov #ifdef CONFIG_DRIVER_TI_KEYSTONE_NET 32891266ccbSVitaly Andrianov struct eth_priv_t eth_priv_cfg[] = { 32991266ccbSVitaly Andrianov { 33091266ccbSVitaly Andrianov .int_name = "K2G_EMAC", 33191266ccbSVitaly Andrianov .rx_flow = 0, 33291266ccbSVitaly Andrianov .phy_addr = 0, 33391266ccbSVitaly Andrianov .slave_port = 1, 33491266ccbSVitaly Andrianov .sgmii_link_type = SGMII_LINK_MAC_PHY, 33591266ccbSVitaly Andrianov .phy_if = PHY_INTERFACE_MODE_RGMII, 33691266ccbSVitaly Andrianov }, 33791266ccbSVitaly Andrianov }; 33891266ccbSVitaly Andrianov 33991266ccbSVitaly Andrianov int get_num_eth_ports(void) 34091266ccbSVitaly Andrianov { 34191266ccbSVitaly Andrianov return sizeof(eth_priv_cfg) / sizeof(struct eth_priv_t); 34291266ccbSVitaly Andrianov } 34391266ccbSVitaly Andrianov #endif 344