1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00
corundum/utils/mqnic-bmc.c
Alex Forencich 448fa8eb4c Use SPDX
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-06-26 11:44:57 -07:00

323 lines
8.5 KiB
C

// SPDX-License-Identifier: BSD-2-Clause-Views
/*
* Copyright (c) 2021-2023 The Regents of the University of California
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mqnic/mqnic.h>
static void usage(char *name)
{
fprintf(stderr,
"usage: %s [options]\n"
" -d name device to open (/dev/mqnic0)\n"
" -i number interface\n"
" -P number port\n",
name);
}
uint32_t mqnic_alveo_bmc_reg_read(struct mqnic_reg_block *rb, uint32_t reg)
{
mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_ADDR, reg);
mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read
return mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA);
}
void mqnic_alveo_bmc_reg_write(struct mqnic_reg_block *rb, uint32_t reg, uint32_t val)
{
mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_ADDR, reg);
mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA, val);
mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read
}
struct sensor_channel {
uint32_t reg;
char name[32];
char unit[8];
};
struct sensor_channel alveo_bmc_sensors[] = {
{0x0020, "12V_PEX", "mV"},
{0x002C, "3V3_PEX", "mV"},
{0x0038, "3V3_AUX", "mV"},
{0x0044, "12V_AUX", "mV"},
{0x0050, "DDR4_VPP_BTM", "mV"},
{0x005C, "SYS_5V5", "mV"},
{0x0068, "VCC1V2_TOP", "mV"},
{0x0074, "VCC1V8", "mV"},
{0x0080, "VCC0V85", "mV"},
{0x008C, "DDR4_VPP_TOP", "mV"},
{0x0098, "MGT0V9AVCC", "mV"},
{0x00A4, "12VSW", "mV"},
{0x00B0, "MGTAVTT", "mV"},
{0x00BC, "VCC1V2_BTM", "mV"},
{0x00C8, "12VPEX_I_IN", "mA"},
{0x00D4, "12V_AUX_I_IN", "mA"},
{0x00E0, "VCCINT", "mV"},
{0x00EC, "VCCINT_I", "mA"},
{0x00F8, "FPGA_TEMP", "C"},
{0x0104, "FAN_TEMP", "C"},
{0x0110, "DIMM_TEMP0", "C"},
{0x011C, "DIMM_TEMP1", "C"},
{0x0128, "DIMM_TEMP2", "C"},
{0x0134, "DIMM_TEMP3", "C"},
{0x0140, "SE98_TEMP0", "C"},
{0x014C, "SE98_TEMP1", "C"},
{0x0158, "SE98_TEMP2", "C"},
{0x0164, "FAN_SPEED", "RPM"},
{0x0170, "CAGE_TEMP0", "C"},
{0x017C, "CAGE_TEMP1", "C"},
{0x0188, "CAGE_TEMP2", "C"},
{0x0194, "CAGE_TEMP3", "C"},
{0x0260, "HBM_TEMP1", "C"},
{0x026C, "VCC3V3", "mV"},
{0x0278, "3V3_PEX_I_IN", "mA"},
{0x0284, "VCC0V85_I", "mA"},
{0x0290, "HBM_1V2", "mV"},
{0x029C, "VPP2V5", "mV"},
{0x02A8, "VCCINT_BRAM", "mV"},
{0x02B4, "HBM_TEMP2", "C"},
{0x02C0, "12V_AUX1", "mV"},
{0x02CC, "VCCINT_TEMP", "C"},
{0x02D8, "PEX_12V_POWER", "mW"},
{0x02E4, "PEX_3V3_POWER", "mW"},
{0x02F0, "AUX_3V3_I", "mA"},
{0x0314, "VCC1V2_I", "mA"},
{0x0320, "V12_IN_I", "mA"},
{0x032C, "V12_IN_AUX0_I", "mA"},
{0x0338, "V12_IN_AUX1_I", "mA"},
{0x0344, "VCCAUX", "mV"},
{0x0350, "VCCAUX_PMC", "mV"},
{0x035C, "VCCRAM", "mV"},
{0, "", ""}
};
int mqnic_gecko_bmc_read(struct mqnic_reg_block *rb)
{
uint32_t val;
int timeout = 20000;
while (1)
{
val = mqnic_reg_read32(rb->regs, MQNIC_RB_GECKO_BMC_REG_STATUS);
if (val & (1 << 19))
{
if (val & (1 << 18))
{
// timed out
printf("Timed out waiting for BMC\n");
usleep(10000);
return -2;
}
return val & 0xffff;
}
else
{
timeout--;
if (timeout == 0)
{
printf("Timed out waiting for operation\n");
return -1;
}
usleep(10);
}
}
return -1;
}
int mqnic_gecko_bmc_write(struct mqnic_reg_block *rb, uint16_t cmd, uint32_t data)
{
int ret;
ret = mqnic_gecko_bmc_read(rb);
if (ret == -1)
return ret;
mqnic_reg_write32(rb->regs, MQNIC_RB_GECKO_BMC_REG_DATA, data);
mqnic_reg_write32(rb->regs, MQNIC_RB_GECKO_BMC_REG_CMD, cmd << 16);
return 0;
}
int mqnic_gecko_bmc_query(struct mqnic_reg_block *rb, uint16_t cmd, uint32_t data)
{
int ret;
ret = mqnic_gecko_bmc_write(rb, cmd, data);
if (ret)
return ret;
return mqnic_gecko_bmc_read(rb);
}
int main(int argc, char *argv[])
{
char *name;
int opt;
int ret = 0;
char *device = NULL;
struct mqnic *dev;
struct mqnic_reg_block *bmc_rb;
name = strrchr(argv[0], '/');
name = name ? 1+name : argv[0];
while ((opt = getopt(argc, argv, "d:h?")) != EOF)
{
switch (opt)
{
case 'd':
device = optarg;
break;
case 'h':
case '?':
usage(name);
return 0;
default:
usage(name);
return -1;
}
}
if (!device)
{
fprintf(stderr, "Device not specified\n");
usage(name);
return -1;
}
dev = mqnic_open(device);
if (!dev)
{
fprintf(stderr, "Failed to open device\n");
return -1;
}
if (dev->pci_device_path[0])
{
char *ptr = strrchr(dev->pci_device_path, '/');
if (ptr)
printf("PCIe ID: %s\n", ptr+1);
}
mqnic_print_fw_id(dev);
if ((bmc_rb = mqnic_find_reg_block(dev->rb_list, MQNIC_RB_ALVEO_BMC_TYPE, MQNIC_RB_ALVEO_BMC_VER, 0)))
{
printf("Detected Xilinx Alveo board with MSP430 BMC\n");
printf("Attempt to communicate with CMS microblaze...\n");
if (mqnic_alveo_bmc_reg_read(bmc_rb, 0x020000) == 0 || mqnic_alveo_bmc_reg_read(bmc_rb, 0x028000) == 0)
{
printf("Resetting CMS...\n");
// reset CMS
mqnic_alveo_bmc_reg_write(bmc_rb, 0x020000, 0);
mqnic_alveo_bmc_reg_write(bmc_rb, 0x020000, 1);
usleep(200000);
}
if (mqnic_alveo_bmc_reg_read(bmc_rb, 0x028000) != 0x74736574)
{
fprintf(stderr, "CMS not responding\n");
ret = -1;
goto err;
}
// read sensor channels
printf("Sensor values:\n");
for (const struct sensor_channel *ptr = alveo_bmc_sensors; ptr->reg; ptr++)
{
uint32_t reg = 0x028000 + ptr->reg;
uint32_t val_max = mqnic_alveo_bmc_reg_read(bmc_rb, reg);
uint32_t val_avg = mqnic_alveo_bmc_reg_read(bmc_rb, reg+4);
uint32_t val_ins = mqnic_alveo_bmc_reg_read(bmc_rb, reg+8);
printf("%s: %d %s (%d %s avg, %d %s max)\n", ptr->name,
val_ins, ptr->unit, val_avg, ptr->unit, val_max, ptr->unit);
}
// read MAC addresses
printf("MAC addresses:\n");
for (int k = 0; k < 8; k++)
{
uint8_t mac[6];
uint32_t reg = 0x0281a0 + k*8;
uint32_t val = mqnic_alveo_bmc_reg_read(bmc_rb, reg);
mac[0] = (val >> 8) & 0xff;
mac[1] = val & 0xff;
val = mqnic_alveo_bmc_reg_read(bmc_rb, reg+4);
mac[2] = (val >> 24) & 0xff;
mac[3] = (val >> 16) & 0xff;
mac[4] = (val >> 8) & 0xff;
mac[5] = val & 0xff;
printf("MAC %d: ", k);
for (int i = 0; i < 6; i++)
{
if (i != 0)
printf(":");
printf("%02x", mac[i]);
}
printf("\n");
}
}
else if ((bmc_rb = mqnic_find_reg_block(dev->rb_list, MQNIC_RB_GECKO_BMC_TYPE, MQNIC_RB_GECKO_BMC_VER, 0)))
{
printf("Detected Silicom board with Gecko BMC\n");
if (mqnic_gecko_bmc_query(bmc_rb, 0x7006, 0) <= 0)
{
fprintf(stderr, "Failed to communicate with BMC\n");
ret = -1;
goto err;
}
uint16_t v_l = mqnic_gecko_bmc_query(bmc_rb, 0x7005, 0);
uint16_t v_h = mqnic_gecko_bmc_query(bmc_rb, 0x7006, 0);
printf("Gecko BMC version %d.%d.%d.%d\n", (v_h >> 8) & 0xff, v_h & 0xff, (v_l >> 8) & 0xff, v_l & 0xff);
// read MAC addresses
printf("MAC addresses:\n");
for (int k = 0; k < 8; k++)
{
uint8_t mac[6];
for (int i = 0; i < 6; i += 2)
{
uint16_t val = mqnic_gecko_bmc_query(bmc_rb, 0x2003, 0+k*6+i);
mac[i] = val & 0xff;
mac[i+1] = (val >> 8) & 0xff;
}
printf("MAC %d: ", k);
for (int i = 0; i < 6; i++)
{
if (i != 0)
printf(":");
printf("%02x", mac[i]);
}
printf("\n");
}
}
else
{
fprintf(stderr, "Board does not have BMC or BMC not currently supported\n");
ret = -1;
goto err;
}
err:
mqnic_close(dev);
return ret;
}