From fe352ad7beb6e1c7e6cc074e0124141b0436c9a4 Mon Sep 17 00:00:00 2001 From: Gustavo de Souza dos Reis Date: Mon, 7 Aug 2023 14:28:09 -0300 Subject: [PATCH] Add ipmi command to configure clock switch and save it in eeprom --- README.md | 24 +++++ modules/CMakeLists.txt | 5 ++ modules/adn4604.c | 62 ------------- modules/adn4604.h | 8 -- modules/clock_config.c | 26 ++++++ modules/clock_config.h | 7 ++ modules/ipmi.h | 2 + port/board/afc-bpm/v3_1/CMakeLists.txt | 2 + port/board/afc-bpm/v3_1/adn4604_usercfg.h | 63 ------------- port/board/afc-bpm/v3_1/payload.c | 103 +++++++++++++++++++--- port/board/afc-bpm/v3_1/payload.h | 7 ++ port/board/afc-timing/CMakeLists.txt | 2 + port/board/afc-timing/adn4604_usercfg.h | 63 ------------- port/board/afc-timing/payload.c | 89 +++++++++++++++++-- port/board/afc-timing/payload.h | 8 ++ port/board/afc-v4/CMakeLists.txt | 2 + port/board/afc-v4/board_config.c | 6 -- port/board/afc-v4/payload.c | 36 +++++--- port/board/afc-v4/payload.h | 1 + 19 files changed, 288 insertions(+), 228 deletions(-) create mode 100644 modules/clock_config.c create mode 100644 modules/clock_config.h delete mode 100644 port/board/afc-bpm/v3_1/adn4604_usercfg.h delete mode 100644 port/board/afc-timing/adn4604_usercfg.h diff --git a/README.md b/README.md index 6c751d14a..205a16eae 100644 --- a/README.md +++ b/README.md @@ -130,3 +130,27 @@ Now you can use the typical GDB commands to inspect the program flow and variabl (gdb) monitor reset halt # Resets the microcontroller and immediately halts (gdb) monitor reset run # Resets the microcontroller and starts executing (gdb) load # Reload the firmware into flash + + +## IPMI Custom Commands +The IPMI allow us to create custom commands according to the project needs. [ipmitool](https://codeberg.org/IPMITool/ipmitool) can be used to send the commands + +### Clock switch configuration +It's possible to configure the clock switch. For the AFC v3.1 (ADN4604ASVZ) you can use the following scheme: +- **Port I/O (bit 7)**: Use it to configure the port as an input ('0') or output ('1'). Unused ports should be left configured as inputs; +- **Output Port Signal Source (bits 0 to 3)**: Select the input port for the respective output port. + +For the AFC v4 (IDT 8V54816) you can use the following scheme: +- **Port I/O (bit 7)**: Use it to configure the port as an input ('0') or output ('1'). Unused ports should be left configured as inputs; +- **Termination On/Off (bit 6)**: Use to set the internal termination. '0' is off (high-impedance), '1' is on (100 $\Omega$) +- **Polarity (bit 5)**: Set the channel polarity. '0' for inverted, '1' for non-inverted +- **Output Port Signal Source (bits 0 to 3)**: Select the input port for the respective output port. + + +The command to write the configuration is the above: + + ipmitool -I lan -H mch_host_name -A none -T 0x82 -m 0x20 -t (112 + num_slot*2) raw 0x32 0x03 + +To read the actual configuration, use: + + ipmitool -I lan -H mch_host_name -A none -T 0x82 -m 0x20 -t (112 + num_slot*2) raw 0x32 0x04 diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index f27bc838a..dd36ea369 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -25,6 +25,11 @@ if (";${TARGET_MODULES};" MATCHES ";FRU;") set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_FRU") endif() +if (";${TARGET_MODULES};" MATCHES ";CLOCK_CONFIG;") + set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/clock_config.c ) + set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_CLOCK_CONFIG") +endif() + if (";${TARGET_MODULES};" MATCHES ";EEPROM_24XX02;") set(PROJ_SRCS ${PROJ_SRCS} ${MODULE_PATH}/eeprom_24xx02.c ) set(MODULES_FLAGS "${MODULES_FLAGS} -DMODULE_EEPROM_24XX02") diff --git a/modules/adn4604.c b/modules/adn4604.c index 564f10521..21d1baca3 100644 --- a/modules/adn4604.c +++ b/modules/adn4604.c @@ -34,73 +34,11 @@ /* Project Includes */ #include "port.h" #include "adn4604.h" -#include "adn4604_usercfg.h" #include "i2c.h" #include "i2c_mapping.h" adn_connect_map_t con; -void adn4604_init( void ) -{ - uint16_t out_enable_flag = { - ADN4604_EN_OUT_0 << 0 | - ADN4604_EN_OUT_1 << 1 | - ADN4604_EN_OUT_2 << 2 | - ADN4604_EN_OUT_3 << 3 | - ADN4604_EN_OUT_4 << 4 | - ADN4604_EN_OUT_5 << 5 | - ADN4604_EN_OUT_6 << 6 | - ADN4604_EN_OUT_7 << 7 | - ADN4604_EN_OUT_8 << 8 | - ADN4604_EN_OUT_9 << 9 | - ADN4604_EN_OUT_10 << 10 | - ADN4604_EN_OUT_11 << 11 | - ADN4604_EN_OUT_12 << 12 | - ADN4604_EN_OUT_13 << 13 | - ADN4604_EN_OUT_14 << 14 | - ADN4604_EN_OUT_15 << 15 - }; - - /* Disable UPDATE' pin by pulling it GPIO_LEVEL_HIGH */ - gpio_set_pin_state( PIN_PORT(GPIO_ADN_UPDATE), PIN_NUMBER(GPIO_ADN_UPDATE), GPIO_LEVEL_HIGH ); - - /* There's a delay circuit in the Reset pin of the clock switch, we must wait until it clears out */ - while( gpio_read_pin( PIN_PORT(GPIO_ADN_RESETN), PIN_NUMBER(GPIO_ADN_RESETN) ) == 0 ) { - vTaskDelay( 50 ); - } - - /* Configure the interconnects */ - con.out0 = ADN4604_CFG_OUT_0; - con.out1 = ADN4604_CFG_OUT_1; - con.out2 = ADN4604_CFG_OUT_2; - con.out3 = ADN4604_CFG_OUT_3; - con.out4 = ADN4604_CFG_OUT_4; - con.out5 = ADN4604_CFG_OUT_5; - con.out6 = ADN4604_CFG_OUT_6; - con.out7 = ADN4604_CFG_OUT_7; - con.out8 = ADN4604_CFG_OUT_8; - con.out9 = ADN4604_CFG_OUT_9; - con.out10 = ADN4604_CFG_OUT_10; - con.out11 = ADN4604_CFG_OUT_11; - con.out12 = ADN4604_CFG_OUT_12; - con.out13 = ADN4604_CFG_OUT_13; - con.out14 = ADN4604_CFG_OUT_14; - con.out15 = ADN4604_CFG_OUT_15; - - adn4604_xpt_config( ADN_XPT_MAP0_CON_REG, con ); - - /* Enable desired outputs */ - for ( uint8_t i = 0; i < 16; i++ ) { - if ( ( out_enable_flag >> i ) & 0x1 ) { - adn4604_tx_control( i, TX_ENABLED ); - } - } - - adn4604_active_map( ADN_XPT_MAP0 ); - - adn4604_update(); -} - void adn4604_tx_control( uint8_t output, uint8_t tx_mode ) { uint8_t i2c_addr, i2c_interf; diff --git a/modules/adn4604.h b/modules/adn4604.h index 04ecb9e81..f6b01ea99 100644 --- a/modules/adn4604.h +++ b/modules/adn4604.h @@ -112,14 +112,6 @@ enum adn4604_tx_ctl { TX_ENABLED }; -/** - * @brief Initializes the ADN4604 Clock switch hardware - * - * This IC starts with a pre-defined configuration provided by the board port in the adn4604_usercfg.h file. - * The current port status may be changed with OEM IPMI commands. - */ -void adn4604_init( void ); - /** * @brief Sets the output status * diff --git a/modules/clock_config.c b/modules/clock_config.c new file mode 100644 index 000000000..f6af30603 --- /dev/null +++ b/modules/clock_config.c @@ -0,0 +1,26 @@ +#include "clock_config.h" + +uint8_t clock_config[16]; + +/* + * Function to configure the clock switch via ipmi. + * The configuration is sent as an array in the data field. + * +*/ +IPMI_HANDLER(ipmi_custom_cmd_write_clock_config, NETFN_CUSTOM, IPMI_CUSTOM_CMD_WRITE_CLOCK_CONFIG, ipmi_msg *req, ipmi_msg *rsp) +{ + memcpy(clock_config, req->data, req->data_len); + payload_send_message(FRU_AMC, PAYLOAD_MESSAGE_CLOCK_CONFIG); + rsp->completion_code = IPMI_CC_OK; +} + + +/* + * Function to read the clock switch configuration via ipmi. + */ +IPMI_HANDLER(ipmi_custom_cmd_read_clock_config, NETFN_CUSTOM, IPMI_CUSTOM_CMD_READ_CLOCK_CONFIG, ipmi_msg *req, ipmi_msg *rsp) +{ + rsp->data_len = 16; + memcpy(rsp->data, clock_config, rsp->data_len); + rsp->completion_code = IPMI_CC_OK; +} diff --git a/modules/clock_config.h b/modules/clock_config.h new file mode 100644 index 000000000..c2769419d --- /dev/null +++ b/modules/clock_config.h @@ -0,0 +1,7 @@ +#include +#include +#include "ipmi.h" +#include "fru.h" +#include "payload.h" + +extern uint8_t clock_config[16]; diff --git a/modules/ipmi.h b/modules/ipmi.h index 74057f311..4a363d917 100644 --- a/modules/ipmi.h +++ b/modules/ipmi.h @@ -468,6 +468,8 @@ */ #define IPMI_CUSTOM_CMD_MMC_GET_FREE_HEAP 0x01 #define IPMI_CUSTOM_CMD_GET_GIT_HASH 0x02 +#define IPMI_CUSTOM_CMD_WRITE_CLOCK_CONFIG 0x03 +#define IPMI_CUSTOM_CMD_READ_CLOCK_CONFIG 0x04 /** * @} */ diff --git a/port/board/afc-bpm/v3_1/CMakeLists.txt b/port/board/afc-bpm/v3_1/CMakeLists.txt index 456ea228b..05759cd2e 100644 --- a/port/board/afc-bpm/v3_1/CMakeLists.txt +++ b/port/board/afc-bpm/v3_1/CMakeLists.txt @@ -10,6 +10,7 @@ endif() #List all modules used by this board set(TARGET_MODULES "FRU" + "CLOCK_CONFIG" "PAYLOAD" "SDR" "SCANSTA1101" @@ -18,6 +19,7 @@ set(TARGET_MODULES "DAC_AD84XX" "EEPROM_AT24MAC" "EEPROM_24XX64" + "EEPROM_24XX02" "HOTSWAP_SENSOR" "LM75" "MAX6642" diff --git a/port/board/afc-bpm/v3_1/adn4604_usercfg.h b/port/board/afc-bpm/v3_1/adn4604_usercfg.h deleted file mode 100644 index f0279d532..000000000 --- a/port/board/afc-bpm/v3_1/adn4604_usercfg.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * openMMC -- Open Source modular IPM Controller firmware - * - * Copyright (C) 2015 Henrique Silva - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * @license GPL-3.0+ - */ - -#ifdef ADN4604_USERCFG_H_ -#error "User configuration for ADN4604 Clock switch already defined by other board port, check the build chain!" -#else -#define ADN4604_USERCFG_H_ - -/* User configuration defines for ADN4604 Clock switch output config */ -#define ADN4604_CFG_OUT_0 0 /* TCLKD_OUT */ -#define ADN4604_CFG_OUT_1 0 /* TCLKC_OUT */ -#define ADN4604_CFG_OUT_2 0 /* TCLKA_OUT */ -#define ADN4604_CFG_OUT_3 0 /* TCLKB_OUT */ -#define ADN4604_CFG_OUT_4 13 /* FPGA_CCLK */ -#define ADN4604_CFG_OUT_5 8 /* FP2_CLK2 */ -#define ADN4604_CFG_OUT_6 5 /* LINK01_CLK */ -#define ADN4604_CFG_OUT_7 15 /* FP2_CLK1 */ -#define ADN4604_CFG_OUT_8 8 /* PCIE_CLK1 */ -#define ADN4604_CFG_OUT_9 5 /* LINK23_CLK */ -#define ADN4604_CFG_OUT_10 5 /* FIN1_CLK3 */ -#define ADN4604_CFG_OUT_11 5 /* FIN1_CLK2 */ -#define ADN4604_CFG_OUT_12 14 /* RTM_SYNC_CLK */ -#define ADN4604_CFG_OUT_13 5 /* OP15C (Aux U-Fl connector) */ -#define ADN4604_CFG_OUT_14 5 /* FIN2_CLK2 */ -#define ADN4604_CFG_OUT_15 5 /* FIN2_CLK3 */ - -/* Output enable flags */ -#define ADN4604_EN_OUT_0 0 /* TCLKD_OUT */ -#define ADN4604_EN_OUT_1 0 /* TCLKC_OUT */ -#define ADN4604_EN_OUT_2 0 /* TCLKA_OUT */ -#define ADN4604_EN_OUT_3 0 /* TCLKB_OUT */ -#define ADN4604_EN_OUT_4 1 /* FPGA_CCLK */ -#define ADN4604_EN_OUT_5 0 /* FP2_CLK2 */ -#define ADN4604_EN_OUT_6 1 /* LINK01_CLK */ -#define ADN4604_EN_OUT_7 1 /* FP2_CLK1 */ -#define ADN4604_EN_OUT_8 1 /* PCIE_CLK1 */ -#define ADN4604_EN_OUT_9 0 /* LINK23_CLK */ -#define ADN4604_EN_OUT_10 1 /* FIN1_CLK3 */ -#define ADN4604_EN_OUT_11 1 /* FIN1_CLK2 */ -#define ADN4604_EN_OUT_12 0 /* RTM_SYNC_CLK */ -#define ADN4604_EN_OUT_13 1 /* OP15C (Aux U-Fl connector) */ -#define ADN4604_EN_OUT_14 1 /* FIN2_CLK2 */ -#define ADN4604_EN_OUT_15 1 /* FIN2_CLK3 */ - -#endif diff --git a/port/board/afc-bpm/v3_1/payload.c b/port/board/afc-bpm/v3_1/payload.c index 68ecb10d0..c45e9394a 100644 --- a/port/board/afc-bpm/v3_1/payload.c +++ b/port/board/afc-bpm/v3_1/payload.c @@ -38,6 +38,9 @@ #include "fru.h" #include "led.h" #include "board_led.h" +#include "clock_config.h" +#include "i2c_mapping.h" +#include "eeprom_24xx02.h" /* payload states * 0 - No power @@ -190,7 +193,7 @@ void payload_init( void ) while ( gpio_read_pin( PIN_PORT(GPIO_MMC_ENABLE), PIN_NUMBER(GPIO_MMC_ENABLE) ) == 1 ) {}; } - xTaskCreate( vTaskPayload, "Payload", 120, NULL, tskPAYLOAD_PRIORITY, &vTaskPayload_Handle ); + xTaskCreate( vTaskPayload, "Payload", 256, NULL, tskPAYLOAD_PRIORITY, &vTaskPayload_Handle ); amc_payload_evt = xEventGroupCreate(); #ifdef MODULE_RTM @@ -239,18 +242,29 @@ void vTaskPayload( void *pvParameters ) current_evt = xEventGroupGetBits( amc_payload_evt ); + /* + * When receive a PAYLOAD_MESSAGE_CLOCK_CONFIG command, write the new configuration + * in EEPROM memory, reset the clock configuration and perform the new configuration. + */ + if( current_evt & PAYLOAD_MESSAGE_CLOCK_CONFIG ){ + eeprom_24xx02_write(CHIP_ID_RTC_EEPROM, 0x0, clock_config, 16, 10); + adn4604_reset(); + clock_configuration(); + xEventGroupClearBits(amc_payload_evt, PAYLOAD_MESSAGE_CLOCK_CONFIG); + } + if ( current_evt & PAYLOAD_MESSAGE_QUIESCE ) { - + /* - * If you issue a shutdown fru command in the MCH shell, the payload power - * task will receive a PAYLOAD_MESSAGE_QUIESCE message and set the - * QUIESCED_req flag to '1' and the MCH will shutdown the 12VP0 power, - * making the payload power task go to PAYLOAD_NO_POWER state. + * If you issue a shutdown fru command in the MCH shell, the payload power + * task will receive a PAYLOAD_MESSAGE_QUIESCE message and set the + * QUIESCED_req flag to '1' and the MCH will shutdown the 12VP0 power, + * making the payload power task go to PAYLOAD_NO_POWER state. * So, if we are in the PAYLOAD_QUIESCED state and receive a - * PAYLOAD_MESSAGE_QUIESCE message, the QUIESCED_req flag + * PAYLOAD_MESSAGE_QUIESCE message, the QUIESCED_req flag * should be '0' */ - + if (state == PAYLOAD_QUIESCED) { QUIESCED_req = 0; } else { @@ -298,7 +312,7 @@ void vTaskPayload( void *pvParameters ) case PAYLOAD_STATE_FPGA_SETUP: #ifdef MODULE_ADN4604 /* Configure clock switch */ - adn4604_init(); + clock_configuration(); #endif new_state = PAYLOAD_FPGA_ON; break; @@ -328,7 +342,7 @@ void vTaskPayload( void *pvParameters ) new_state = PAYLOAD_NO_POWER; } break; - + case PAYLOAD_RESET: /*Reset DCDC converters*/ setDC_DC_ConvertersON( false ); @@ -461,4 +475,73 @@ uint8_t payload_hpm_activate_firmware( void ) return IPMI_CC_OK; } + +void clock_configuration() +{ + adn_connect_map_t con; + + /* Read the clock configuration from the eeprom */ + eeprom_24xx02_read(CHIP_ID_RTC_EEPROM, 0x0, clock_config, 16, 10); + + /* Translate the configuration to enable or disable the outputs */ + uint16_t out_enable_flag = { + ((clock_config[0] & 0x80) >> 7) << 0 | + ((clock_config[1] & 0x80) >> 7) << 1 | + ((clock_config[2] & 0x80) >> 7) << 2 | + ((clock_config[3] & 0x80) >> 7) << 3 | + ((clock_config[4] & 0x80) >> 7) << 4 | + ((clock_config[5] & 0x80) >> 7) << 5 | + ((clock_config[6] & 0x80) >> 7) << 6 | + ((clock_config[7] & 0x80) >> 7) << 7 | + ((clock_config[8] & 0x80) >> 7) << 8 | + ((clock_config[9] & 0x80) >> 7) << 9 | + ((clock_config[10] & 0x80) >> 7) << 10 | + ((clock_config[11] & 0x80) >> 7) << 11 | + ((clock_config[12] & 0x80) >> 7) << 12 | + ((clock_config[13] & 0x80) >> 7) << 13 | + ((clock_config[14] & 0x80) >> 7) << 14 | + ((clock_config[15] & 0x80) >> 7) << 15 + }; + + /* Disable UPDATE' pin by pulling it GPIO_LEVEL_HIGH */ + gpio_set_pin_state( PIN_PORT(GPIO_ADN_UPDATE), PIN_NUMBER(GPIO_ADN_UPDATE), GPIO_LEVEL_HIGH ); + + /* There's a delay circuit in the Reset pin of the clock switch, we must wait until it clears out */ + while( gpio_read_pin( PIN_PORT(GPIO_ADN_RESETN), PIN_NUMBER(GPIO_ADN_RESETN) ) == 0 ) { + vTaskDelay( 50 ); + } + + /* Configure the interconnects*/ + con.out0 = clock_config[0] & 0x0F; + con.out1 = clock_config[1] & 0x0F; + con.out2 = clock_config[2] & 0x0F; + con.out3 = clock_config[3] & 0x0F; + con.out4 = clock_config[4] & 0x0F; + con.out5 = clock_config[5] & 0x0F; + con.out6 = clock_config[6] & 0x0F; + con.out7 = clock_config[7] & 0x0F; + con.out8 = clock_config[8] & 0x0F; + con.out9 = clock_config[9] & 0x0F; + con.out10 = clock_config[10] & 0x0F; + con.out11 = clock_config[11] & 0x0F; + con.out12 = clock_config[12] & 0x0F; + con.out13 = clock_config[13] & 0x0F; + con.out14 = clock_config[14] & 0x0F; + con.out15 = clock_config[15] & 0x0F; + + adn4604_xpt_config( ADN_XPT_MAP0_CON_REG, con ); + + /* Enable desired outputs */ + for ( uint8_t i = 0; i < 16; i++ ) { + if ( ( out_enable_flag >> i ) & 0x1 ) { + adn4604_tx_control( i, TX_ENABLED ); + } else { + adn4604_tx_control( i, TX_DISABLED ); + } + } + + adn4604_active_map( ADN_XPT_MAP0 ); + + adn4604_update(); +} #endif diff --git a/port/board/afc-bpm/v3_1/payload.h b/port/board/afc-bpm/v3_1/payload.h index 3aec34f29..37c466376 100644 --- a/port/board/afc-bpm/v3_1/payload.h +++ b/port/board/afc-bpm/v3_1/payload.h @@ -61,6 +61,7 @@ extern enum { #define PAYLOAD_MESSAGE_WARM_RST (1 << 1) #define PAYLOAD_MESSAGE_REBOOT (1 << 2) #define PAYLOAD_MESSAGE_QUIESCE (1 << 3) +#define PAYLOAD_MESSAGE_CLOCK_CONFIG (1 << 4) /** * @} */ @@ -108,6 +109,12 @@ uint8_t payload_hpm_get_upgrade_status( void ); uint8_t payload_hpm_activate_firmware( void ); #endif +/** + * @brief Configure the clock switch interconects according to the configuration + * saved in EEPROM + */ +void clock_configuration(); + #endif /* IPMI_PAYLOAD_H_ */ /** diff --git a/port/board/afc-timing/CMakeLists.txt b/port/board/afc-timing/CMakeLists.txt index 788115b62..c22a95f1b 100644 --- a/port/board/afc-timing/CMakeLists.txt +++ b/port/board/afc-timing/CMakeLists.txt @@ -10,6 +10,7 @@ endif() #List all modules used by this board set(TARGET_MODULES "FRU" + "CLOCK_CONFIG" "PAYLOAD" "SDR" "SCANSTA1101" @@ -17,6 +18,7 @@ set(TARGET_MODULES "DAC_AD84XX" "HOTSWAP_SENSOR" "EEPROM_AT24MAC" + "EEPROM_24XX02" "LM75" "MAX6642" "INA220_VOLTAGE" diff --git a/port/board/afc-timing/adn4604_usercfg.h b/port/board/afc-timing/adn4604_usercfg.h deleted file mode 100644 index e30678288..000000000 --- a/port/board/afc-timing/adn4604_usercfg.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * openMMC -- Open Source modular IPM Controller firmware - * - * Copyright (C) 2015 Henrique Silva - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * @license GPL-3.0+ - */ - -#ifdef ADN4604_USERCFG_H_ -#error "User configuration for ADN4604 Clock switch already defined by other board port, check the build chain!" -#else -#define ADN4604_USERCFG_H_ - -/* User configuration defines for ADN4604 Clock switch output config */ -#define ADN4604_CFG_OUT_0 0 /* TCLKD_OUT */ -#define ADN4604_CFG_OUT_1 0 /* TCLKC_OUT */ -#define ADN4604_CFG_OUT_2 0 /* TCLKA_OUT */ -#define ADN4604_CFG_OUT_3 15 /* TCLKB_OUT */ -#define ADN4604_CFG_OUT_4 15 /* FPGA_CCLK */ -#define ADN4604_CFG_OUT_5 8 /* FP2_CLK2 */ -#define ADN4604_CFG_OUT_6 13 /* LINK01_CLK */ -#define ADN4604_CFG_OUT_7 8 /* FP2_CLK1 */ -#define ADN4604_CFG_OUT_8 8 /* PCIE_CLK1 */ -#define ADN4604_CFG_OUT_9 13 /* LINK23_CLK */ -#define ADN4604_CFG_OUT_10 14 /* FIN1_CLK3 */ -#define ADN4604_CFG_OUT_11 14 /* FIN1_CLK2 */ -#define ADN4604_CFG_OUT_12 14 /* RTM_SYNC_CLK */ -#define ADN4604_CFG_OUT_13 15 /* OP15C (Aux U-Fl connector) */ -#define ADN4604_CFG_OUT_14 14 /* FIN2_CLK2 */ -#define ADN4604_CFG_OUT_15 3 /* FIN2_CLK3 */ - -/* Output enable flags */ -#define ADN4604_EN_OUT_0 0 /* TCLKD_OUT */ -#define ADN4604_EN_OUT_1 0 /* TCLKC_OUT */ -#define ADN4604_EN_OUT_2 0 /* TCLKA_OUT */ -#define ADN4604_EN_OUT_3 1 /* TCLKB_OUT */ -#define ADN4604_EN_OUT_4 1 /* FPGA_CCLK */ -#define ADN4604_EN_OUT_5 0 /* FP2_CLK2 */ -#define ADN4604_EN_OUT_6 1 /* LINK01_CLK */ -#define ADN4604_EN_OUT_7 0 /* FP2_CLK1 */ -#define ADN4604_EN_OUT_8 1 /* PCIE_CLK1 */ -#define ADN4604_EN_OUT_9 0 /* LINK23_CLK */ -#define ADN4604_EN_OUT_10 0 /* FIN1_CLK3 */ -#define ADN4604_EN_OUT_11 0 /* FIN1_CLK2 */ -#define ADN4604_EN_OUT_12 0 /* RTM_SYNC_CLK */ -#define ADN4604_EN_OUT_13 1 /* OP15C (Aux U-Fl connector) */ -#define ADN4604_EN_OUT_14 0 /* FIN2_CLK2 */ -#define ADN4604_EN_OUT_15 0 /* FIN2_CLK3 */ - -#endif diff --git a/port/board/afc-timing/payload.c b/port/board/afc-timing/payload.c index 07994fb45..3d910c3a7 100644 --- a/port/board/afc-timing/payload.c +++ b/port/board/afc-timing/payload.c @@ -38,6 +38,9 @@ #include "fru.h" #include "led.h" #include "board_led.h" +#include "clock_config.h" +#include "i2c_mapping.h" +#include "eeprom_24xx02.h" /* payload states * 0 - No power @@ -178,8 +181,6 @@ TaskHandle_t vTaskPayload_Handle; void payload_init( void ) { - - /* Set standalone mode if the module is disconnected from a create*/ bool standalone_mode = false; @@ -192,8 +193,7 @@ void payload_init( void ) while ( gpio_read_pin( PIN_PORT(GPIO_MMC_ENABLE), PIN_NUMBER(GPIO_MMC_ENABLE) ) == 1 ) {}; } - - xTaskCreate( vTaskPayload, "Payload", 120, NULL, tskPAYLOAD_PRIORITY, &vTaskPayload_Handle ); + xTaskCreate( vTaskPayload, "Payload", 256, NULL, tskPAYLOAD_PRIORITY, &vTaskPayload_Handle ); amc_payload_evt = xEventGroupCreate(); #ifdef MODULE_RTM @@ -242,6 +242,16 @@ void vTaskPayload( void *pvParameters ) current_evt = xEventGroupGetBits( amc_payload_evt ); + /* + * When receive a PAYLOAD_MESSAGE_CLOCK_CONFIG command, write the new configuration + * in EEPROM memory, reset the clock configuration and perform the new configuration. + */ + if( current_evt & PAYLOAD_MESSAGE_CLOCK_CONFIG ){ + eeprom_24xx02_write(CHIP_ID_RTC_EEPROM, 0x0, clock_config, 16, 10); + adn4604_reset(); + clock_configuration(); + xEventGroupClearBits(amc_payload_evt, PAYLOAD_MESSAGE_CLOCK_CONFIG); + } if ( current_evt & PAYLOAD_MESSAGE_QUIESCE ) { /* @@ -301,7 +311,7 @@ void vTaskPayload( void *pvParameters ) case PAYLOAD_STATE_FPGA_SETUP: #ifdef MODULE_ADN4604 /* Configure clock switch */ - adn4604_init(); + clock_configuration(); #endif new_state = PAYLOAD_FPGA_ON; break; @@ -464,4 +474,73 @@ uint8_t payload_hpm_activate_firmware( void ) return IPMI_CC_OK; } + +void clock_configuration() +{ + adn_connect_map_t con; + + /* Read the clock configuration from the eeprom */ + eeprom_24xx02_read(CHIP_ID_RTC_EEPROM, 0x0, clock_config, 16, 10); + + /* Translate the configuration to enable or disable the outputs */ + uint16_t out_enable_flag = { + ((clock_config[0] & 0x80) >> 7) << 0 | + ((clock_config[1] & 0x80) >> 7) << 1 | + ((clock_config[2] & 0x80) >> 7) << 2 | + ((clock_config[3] & 0x80) >> 7) << 3 | + ((clock_config[4] & 0x80) >> 7) << 4 | + ((clock_config[5] & 0x80) >> 7) << 5 | + ((clock_config[6] & 0x80) >> 7) << 6 | + ((clock_config[7] & 0x80) >> 7) << 7 | + ((clock_config[8] & 0x80) >> 7) << 8 | + ((clock_config[9] & 0x80) >> 7) << 9 | + ((clock_config[10] & 0x80) >> 7) << 10 | + ((clock_config[11] & 0x80) >> 7) << 11 | + ((clock_config[12] & 0x80) >> 7) << 12 | + ((clock_config[13] & 0x80) >> 7) << 13 | + ((clock_config[14] & 0x80) >> 7) << 14 | + ((clock_config[15] & 0x80) >> 7) << 15 + }; + + /* Disable UPDATE' pin by pulling it GPIO_LEVEL_HIGH */ + gpio_set_pin_state( PIN_PORT(GPIO_ADN_UPDATE), PIN_NUMBER(GPIO_ADN_UPDATE), GPIO_LEVEL_HIGH ); + + /* There's a delay circuit in the Reset pin of the clock switch, we must wait until it clears out */ + while( gpio_read_pin( PIN_PORT(GPIO_ADN_RESETN), PIN_NUMBER(GPIO_ADN_RESETN) ) == 0 ) { + vTaskDelay( 50 ); + } + + /* Configure the interconnects*/ + con.out0 = clock_config[0] & 0x0F; + con.out1 = clock_config[1] & 0x0F; + con.out2 = clock_config[2] & 0x0F; + con.out3 = clock_config[3] & 0x0F; + con.out4 = clock_config[4] & 0x0F; + con.out5 = clock_config[5] & 0x0F; + con.out6 = clock_config[6] & 0x0F; + con.out7 = clock_config[7] & 0x0F; + con.out8 = clock_config[8] & 0x0F; + con.out9 = clock_config[9] & 0x0F; + con.out10 = clock_config[10] & 0x0F; + con.out11 = clock_config[11] & 0x0F; + con.out12 = clock_config[12] & 0x0F; + con.out13 = clock_config[13] & 0x0F; + con.out14 = clock_config[14] & 0x0F; + con.out15 = clock_config[15] & 0x0F; + + adn4604_xpt_config( ADN_XPT_MAP0_CON_REG, con ); + + /* Enable desired outputs */ + for ( uint8_t i = 0; i < 16; i++ ) { + if ( ( out_enable_flag >> i ) & 0x1 ) { + adn4604_tx_control( i, TX_ENABLED ); + } else { + adn4604_tx_control( i, TX_DISABLED ); + } + } + + adn4604_active_map( ADN_XPT_MAP0 ); + + adn4604_update(); +} #endif diff --git a/port/board/afc-timing/payload.h b/port/board/afc-timing/payload.h index 03ff35e3b..3746e8e2e 100644 --- a/port/board/afc-timing/payload.h +++ b/port/board/afc-timing/payload.h @@ -62,6 +62,7 @@ extern enum { #define PAYLOAD_MESSAGE_REBOOT (1 << 2) #define PAYLOAD_MESSAGE_QUIESCE (1 << 3) #define PAYLOAD_MESSAGE_RTM_ENABLE (1 << 4) +#define PAYLOAD_MESSAGE_CLOCK_CONFIG (1 << 5) /** * @} */ @@ -109,6 +110,13 @@ uint8_t payload_hpm_get_upgrade_status( void ); uint8_t payload_hpm_activate_firmware( void ); #endif +/** + * @brief Configure the clock switch interconects according to the configuration + * saved in EEPROM + */ +void clock_configuration(); + + #endif /* IPMI_PAYLOAD_H_ */ /** diff --git a/port/board/afc-v4/CMakeLists.txt b/port/board/afc-v4/CMakeLists.txt index 1ae65a93f..a858f51ff 100644 --- a/port/board/afc-v4/CMakeLists.txt +++ b/port/board/afc-v4/CMakeLists.txt @@ -10,6 +10,8 @@ endif() #List all modules used by this board set(TARGET_MODULES "FRU" + "CLOCK_CONFIG" + "EEPROM_24XX02" "PAYLOAD" "SDR" "DAC_AD84XX" diff --git a/port/board/afc-v4/board_config.c b/port/board/afc-v4/board_config.c index 19e996c38..00eba0b0d 100644 --- a/port/board/afc-v4/board_config.c +++ b/port/board/afc-v4/board_config.c @@ -22,11 +22,6 @@ /* Project Includes */ #include "port.h" - -uint8_t clock_switch_default_config() { - -} - void board_init() { /* I2C MUX Init */ gpio_set_pin_state(PIN_PORT(GPIO_I2C_MUX_ADDR1), PIN_NUMBER(GPIO_I2C_MUX_ADDR1), GPIO_LEVEL_LOW); @@ -35,5 +30,4 @@ void board_init() { } void board_config() { - clock_switch_default_config(); } diff --git a/port/board/afc-v4/payload.c b/port/board/afc-v4/payload.c index af86bf4e4..06d427cc4 100644 --- a/port/board/afc-v4/payload.c +++ b/port/board/afc-v4/payload.c @@ -35,12 +35,16 @@ #include "task_priorities.h" #include "mcp23016.h" #include "ad84xx.h" +#include "idt_8v54816.h" #include "hotswap.h" #include "utils.h" #include "fru.h" #include "led.h" #include "board_led.h" - +#include "board_config.h" +#include "clock_config.h" +#include "eeprom_24xx02.h" +#include "i2c_mapping.h" /* payload states * 0 - No power @@ -233,7 +237,7 @@ void payload_init( void ) while ( gpio_read_pin( PIN_PORT(GPIO_MMC_ENABLE), PIN_NUMBER(GPIO_MMC_ENABLE) ) == 1 ) {}; } - xTaskCreate( vTaskPayload, "Payload", 120, NULL, tskPAYLOAD_PRIORITY, &vTaskPayload_Handle ); + xTaskCreate( vTaskPayload, "Payload", 256, NULL, tskPAYLOAD_PRIORITY, &vTaskPayload_Handle ); amc_payload_evt = xEventGroupCreate(); #ifdef MODULE_RTM @@ -328,19 +332,18 @@ void vTaskPayload( void *pvParameters ) new_state = state; current_evt = xEventGroupGetBits( amc_payload_evt ); - if ( current_evt & PAYLOAD_MESSAGE_QUIESCE ) { - + /* - * If you issue a shutdown fru command in the MCH shell, the payload power - * task will receive a PAYLOAD_MESSAGE_QUIESCE message and set the - * QUIESCED_req flag to '1' and the MCH will shutdown the 12VP0 power, - * making the payload power task go to PAYLOAD_NO_POWER state. + * If you issue a shutdown fru command in the MCH shell, the payload power + * task will receive a PAYLOAD_MESSAGE_QUIESCE message and set the + * QUIESCED_req flag to '1' and the MCH will shutdown the 12VP0 power, + * making the payload power task go to PAYLOAD_NO_POWER state. * So, if we are in the PAYLOAD_QUIESCED state and receive a - * PAYLOAD_MESSAGE_QUIESCE message, the QUIESCED_req flag + * PAYLOAD_MESSAGE_QUIESCE message, the QUIESCED_req flag * should be '0' */ - + if (state == PAYLOAD_QUIESCED) { QUIESCED_req = 0; } else { @@ -349,6 +352,15 @@ void vTaskPayload( void *pvParameters ) xEventGroupClearBits( amc_payload_evt, PAYLOAD_MESSAGE_QUIESCE ); } + /* + * When receive a PAYLOAD_MESSAGE_CLOCK_CONFIG message, configure the clock switch + * and write the new configuration in EEPROM + */ + if( current_evt & PAYLOAD_MESSAGE_CLOCK_CONFIG ){ + clock_switch_write_reg(clock_config); + eeprom_24xx02_write(CHIP_ID_RTC_EEPROM, 0x0, clock_config, 16, 10); + xEventGroupClearBits(amc_payload_evt, PAYLOAD_MESSAGE_CLOCK_CONFIG); + } if ( current_evt & PAYLOAD_MESSAGE_COLD_RST ) { state = PAYLOAD_RESET; xEventGroupClearBits( amc_payload_evt, PAYLOAD_MESSAGE_COLD_RST ); @@ -397,7 +409,9 @@ void vTaskPayload( void *pvParameters ) break; case PAYLOAD_STATE_FPGA_SETUP: - + /* Configure the clock switch according to the configuration saved in EEPROM*/ + eeprom_24xx02_read(CHIP_ID_RTC_EEPROM, 0x0, clock_config, 16, 10); + clock_switch_read_reg(clock_config); new_state = PAYLOAD_FPGA_ON; break; diff --git a/port/board/afc-v4/payload.h b/port/board/afc-v4/payload.h index 432fe18c4..291c927fc 100644 --- a/port/board/afc-v4/payload.h +++ b/port/board/afc-v4/payload.h @@ -64,6 +64,7 @@ extern enum { #define PAYLOAD_MESSAGE_QUIESCE (1 << 3) #define PAYLOAD_MESSAGE_DCDC_PGOOD (1 << 4) #define PAYLOAD_MESSAGE_DCDC_PGOODn (1 << 5) +#define PAYLOAD_MESSAGE_CLOCK_CONFIG (1 << 6) /** * @} */