1
0
Files
2022-09-29 17:59:04 +03:00

188 lines
4.3 KiB
C

#ifdef IP21 /* whole file */
#include "libsc.h"
#include "libsk.h"
#include "sys/cpu.h"
#include "sys/loaddrs.h"
#include "sys/EVEREST/evmp.h"
#define EV_REVISION_ALLZERO 0xffffffffffffff00LL
static int parse_margin_args(int, char **);
static void set_voltages(int);
static void set_cpu_voltage(int);
int
margin_voltage_cmd(int argc, char *argv[])
{
int margin_vector;
if ((margin_vector = parse_margin_args(argc, argv)) == -1) {
Usage:
printf("Usage: margin {command} {command}\n");
printf("\n");
printf("Command can be one of the following:\n");
printf(" <nothing> Set Both Supplies to Nominal.\n");
printf(" 3V=high Set 3V Supply to Plus Five Percent.\n");
printf(" 3V=low Set 3V Supply to Minus Five Percent.\n");
printf(" 5V=high Set 5V Supply to Plus Five Percent.\n");
printf(" 5V=low Set 5V Supply to Minus Five Percent.\n");
printf("\n");
return(1);
}
if ((margin_vector & (EV_VCR_LOW3V | EV_VCR_HIGH3V)) ==
(EV_VCR_LOW3V | EV_VCR_HIGH3V))
goto Usage;
else if (margin_vector & EV_VCR_LOW3V)
printf("Lowering 3V Power to Minus Five Percent...\n");
else if (margin_vector & EV_VCR_HIGH3V)
printf("Raising 3V Power to Plus Five Percent...\n");
else
printf("Returning 3V Power to Nominal...\n");
if ((margin_vector & (EV_VCR_LOW5V | EV_VCR_HIGH5V)) ==
(EV_VCR_LOW5V | EV_VCR_HIGH5V))
goto Usage;
else if (margin_vector & EV_VCR_LOW5V)
printf("Lowering 5V Power to Minus Five Percent...\n");
else if (margin_vector & EV_VCR_HIGH5V)
printf("Raising 5V Power to Plus Five Percent...\n");
else
printf("Returning 5V Power to Nominal...\n");
set_voltages(margin_vector);
return 0;
}
static int
parse_margin_args(int argc, char *argv[])
{
int margin_vector = 0;
int i;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "3V=low")) {
margin_vector |= EV_VCR_LOW3V;
continue;
}
if (!strcmp(argv[i], "5V=low")) {
margin_vector |= EV_VCR_LOW5V;
continue;
}
if (!strcmp(argv[i], "3V=high")) {
margin_vector |= EV_VCR_HIGH3V;
continue;
}
if (!strcmp(argv[i], "5V=high")) {
margin_vector |= EV_VCR_HIGH5V;
continue;
}
return(-1);
}
return(margin_vector);
}
static volatile int cpu_synchronize;
static void
set_voltages(int margin_vector)
{
unsigned int cpu;
for (cpu = 0; cpu < EV_MAX_CPUS; cpu++) {
if (cpu == cpuid())
continue;
if ((MPCONF[cpu].mpconf_magic != MPCONF_MAGIC) ||
(MPCONF[cpu].virt_id != cpu))
continue;
cpu_synchronize = 1;
us_delay(10000);
launch_slave(cpu, set_cpu_voltage, margin_vector, 0, 0, 0);
while (cpu_synchronize != 0)
;
us_delay(10000);
}
us_delay(10000);
set_cpu_voltage(margin_vector);
us_delay(10000);
printf("...Done\n");
}
static void
set_cpu_voltage(int margin_vector)
{
/* Attempt to make sure that this board does indeed
* have a voltage control register.
* Note that the voltage control register also incorporates
* the revision register.
*/
machreg_t revision = read_revision();
if ((revision & EV_REVISION_ALLZERO) == 0 &&
(revision & EV_IP21REV_MASK) >= EV_IP21REV_VCR)
write_vcr((long)margin_vector);
else
printf(
"Cpu %d, board revision must be >= 7 for Voltage Margining\n"
"Revision register read was 0x%lx\n",
cpuid(), revision);
cpu_synchronize = 0;
}
static void
print_board_revision(int cpu)
{
machreg_t revision = read_revision();
/* Print out the board revision. Since the revision register
* did not appear on the board until rev 6, attempt to
* disambiguate whether we are reading garbage EAROM
* or the actual revision register.
*/
if ((revision & EV_REVISION_ALLZERO) == 0 &&
(revision & EV_IP21REV_MASK) >= EV_IP21LOWREV)
printf("Cpu %d, Board Revision %ld\n",
cpu, (revision & EV_IP21REV_MASK) >> EV_IP21REV_SHFT);
else
printf("Cpu %d Board Revision < 6 "
" (Revision register read was 0x%lx)\n",
cpu, revision);
cpu_synchronize = 0;
}
int
board_revision_cmd(void)
{
unsigned int cpu;
for (cpu = 0; cpu < EV_MAX_CPUS; cpu++) {
if (cpu == cpuid()) {
print_board_revision(cpu);
continue;
}
if ((MPCONF[cpu].mpconf_magic != MPCONF_MAGIC) ||
(MPCONF[cpu].virt_id != cpu))
continue;
cpu_synchronize = 1;
us_delay(10000);
launch_slave(cpu, print_board_revision, cpu, 0, 0, 0);
while (cpu_synchronize != 0)
;
us_delay(10000);
}
return 0;
}
#endif /* IP21 */