// This module is routines for determing which version of the MFM board
// is present. Also sets CPU speed for beaglebone
// board_initialize sets up this module.
// board_get_revision returns the revision of the MFM emulator board
//
// 09/17/2023 DJG Moved set_restore_max_cpu_speed to this file as board_
// to only have one copy
// 03/22/2019 DJG Added REV C support
// 02/08/2017 DJG Fix incorrect format for print
// 10/16/2016 DJG Improved error message
// 12/24/2015 DJG Fix wrong value in error print
// 08/01/2015 DJG New module to support revision B board.
//
// Copyright 2019 David Gesswein.
// This file is part of MFM disk utilities.
//
// MFM disk utilities 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.
//
// MFM disk utilities 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 MFM disk utilities. If not, see .
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "msg.h"
#include "cmd.h"
#include "board.h"
#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
// 0 = first/A, 1 = B. Used to index arrays so can't change encoding
static int board_revision = -1;
// Perform any setup needed by this module. Call once before any other
// routine
void board_initialize(void) {
int pins[] = {REVC_DETECT_PIN, REVB_DETECT_PIN};
int fd;
int i;
char str[128];
if (board_revision == -1) {
// Default is A
board_revision = 0;
for (i = 0; i < ARRAYSIZE(pins); i++) {
sprintf(str, "/sys/class/gpio/gpio%d/value", pins[i]);
fd = open(str, O_RDONLY);
if (fd < 0) {
msg(MSG_FATAL, "Unable to open pin %d, did you run the setup script?\n", pins[i]);
exit(1);
}
// Pin grounded to indicate version
pread(fd, str, sizeof(str), 0);
close(fd);
if (str[0] == '0') {
board_revision = ARRAYSIZE(pins) - i;
break;
}
}
}
msg(MSG_INFO, "Board revision %c detected\n", 'A' + board_revision);
}
// Return board revision
int board_get_revision(void) {
return board_revision;
}
// This routine will either set the CPU speed to maximum or restore it
// back to the previous setting. The normal governor didn't boost the
// processor sufficiently to prevent getting behind in processing.
//
// restore: 0 to set speed to maximum, 1 to restore value from previous
// call
int board_set_restore_max_cpu_speed(int restore) {
FILE *file;
static char governor[100];
static int freq_changed = 0;
char maxfreq[100];
if (!restore) {
file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r");
if (file == NULL) {
return -1;
}
if (fscanf(file, "%100s", governor) < 1) {
return -1;
}
if (strcmp(governor, "performance") == 0) {
// performance *is* guaranteed max speed
return 0;
}
file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "w");
if (file == NULL) {
return -1;
}
if (fprintf(file,"userspace") < 1) {
return -1;
}
fclose(file);
file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
if (file == NULL) {
return -1;
}
if (fscanf(file, "%100s", maxfreq) < 1) {
return -1;
}
fclose(file);
file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", "w");
if (file == NULL) {
return -1;
}
if (fprintf(file,maxfreq) < 1) {
return -1;
}
fclose(file);
freq_changed = 1;
} else {
if (freq_changed) {
file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "w");
if (file == NULL) {
return -1;
}
if (fprintf(file,governor) < 1) {
return -1;
}
fclose(file);
}
freq_changed = 0;
}
return 0;
}