Merge "Ensure lockdown fan runs at 23KHz."
diff --git a/gpio-mailbox/brcm-direct.c b/gpio-mailbox/brcm-direct.c
index 6de0934..8abacbb 100644
--- a/gpio-mailbox/brcm-direct.c
+++ b/gpio-mailbox/brcm-direct.c
@@ -13,8 +13,6 @@
#define UNUSED __attribute__((unused))
#define DEVMEM "/dev/mem"
-const int PWM_CYCLE_PERIOD = 0x63;
-
static volatile void* mmap_addr = MAP_FAILED;
static size_t mmap_size = 0;
static int mmap_fd = -1;
@@ -104,6 +102,7 @@
.offset_data = 0x6580, // PWM_CTRL ...
.channel = 0,
.open_drain = 1,
+ .period = 0x63,
},
.temp_monitor = {
.is_present = 1, // 7425 AVS_RO_REGISTERS_0
@@ -177,6 +176,7 @@
.offset_data = 0x6580, // PWM_CTRL ...
.channel = 0,
.open_drain = 1,
+ .period = 0x63,
},
.temp_monitor = {
.is_present = 1, // 7425 AVS_RO_REGISTERS_0
@@ -293,6 +293,7 @@
.offset_data = 0x9000, // PWM_2
.channel = 0,
.old_percent = -1,
+ .period = 0x63,
},
},
.reset_button = {
@@ -325,6 +326,7 @@
.offset_data = 0x9000, // PWM_CTRL ...
.channel = 1,
.open_drain = 0,
+ .period = 0x91,
},
.temp_monitor = {
.is_present = 1, // 7252 AVS_RO_REGISTERS_0
@@ -421,8 +423,9 @@
// The fan is connected to PWM3, the register PWM3_CWORD_LSB is set to 1,
// this is the frequency of the PWM, the other pwm register control
// the duty cycle.
- reg = mmap_addr + 0x9014; // PWM3_CWORD_LSB
- reg[0] = 1;
+ reg = mmap_addr + 0x9010; // PWM3_CWORD_MSB
+ reg[0] = 0x20;
+ reg[1] = 0x0; // PWM3_CWORD_LSB
// LEDs are connected to PWM2. Setting CWORD_LSB to 0xf to control
// the output freq of the var rate clock.
@@ -571,6 +574,21 @@
return (value == g->on_value);
}
+/*
+ Set the PWM duty duty cycle. Percent bounded [0, 100].
+
+ The output period of the constant-freq PWM is calculated
+ by (period_programmed + 1) / Fv, where Fv is the output
+ of the variable-frequency PWM (in mhz).
+
+ Fv is calculated by the following formula:
+
+ Fv = (cword) * 2^-16 * 27MHz
+
+ cword is the programmed frequency control word.
+
+ The fan on lockdown must stay at a constant 23KHz
+*/
void set_pwm(struct PwmControl *f, int percent) {
volatile uint32_t* reg;
uint32_t mask0, val0, mask1, val1, on;
@@ -600,21 +618,8 @@
}
reg[0] = (reg[0] & mask0) | val0;
reg[1] = (reg[1] & mask1) | val1;
- reg[on] = (PWM_CYCLE_PERIOD * percent)/100; // 0x63 is what old code used
- reg[on+1] = PWM_CYCLE_PERIOD;
-}
-
-/* PWM operates on either channel 0 or 1. We want to get the duty cycle value
- by calculating it from the "ON" register, located offset 6 for channel 0
- and 8 for channel 1.
-
- Duty cycle is calculated by ON / Period.
-*/
-int get_pwm(struct PwmControl *f) {
- volatile uint32_t* reg = mmap_addr + f->offset_data;
- uint8_t offset = f->channel ? 8 : 6;
- uint32_t val = reg[offset];
- return ((uint64_t)val * 100) / PWM_CYCLE_PERIOD;
+ reg[on] = (f->period * percent)/100;
+ reg[on+1] = f->period;
}
void set_direction(struct Gpio *g) {
diff --git a/gpio-mailbox/brcm-nexus.c b/gpio-mailbox/brcm-nexus.c
index d52e5f1..f559c1b 100644
--- a/gpio-mailbox/brcm-nexus.c
+++ b/gpio-mailbox/brcm-nexus.c
@@ -24,8 +24,6 @@
static double get_avs_voltage_7252(struct Voltage* v);
static double get_avs_temperature_7252(struct Temp* t);
-const int PWM_CYCLE_PERIOD = 0x63;
-
/* This is an array. Of structs! It contains structs of
the type platform_info. The platform_info struct provides
much useful information for use in all sorts of fun
@@ -192,10 +190,10 @@
NEXUS_Pwm_CloseChannel(pwm);
- /* Set the control word for the fan to 0x1. */
+ /* Set the control word for the fan to 0x2000. */
NEXUS_Pwm_GetDefaultChannelSettings(&pwmSettings);
pwm = NEXUS_Pwm_OpenChannel(3, &pwmSettings);
- if (NEXUS_Pwm_SetControlWord(pwm, 0x1)) {
+ if (NEXUS_Pwm_SetControlWord(pwm, 0x2000)) {
fprintf(stderr, "Failed setting control word for PWM.\n");
platform_cleanup();
exit(EXIT_FAILURE);
@@ -292,22 +290,27 @@
return status.value != NEXUS_GpioValue_eLow;
}
+/*
+ Set the pwm. See set_pwm in brcm-direct.c
+ for details.
+*/
void set_pwm(struct PwmControl *f, int percent) {
if (percent < 0) percent = 0;
if (percent > 100) percent = 100;
if (percent == f->old_percent) return;
f->old_percent = percent;
+ uint32_t period = f->pwm_index % 2 ? 0x91 : 0x63;
NEXUS_PwmChannelSettings pwmSettings;
NEXUS_PwmChannelHandle pwm;
- uint16_t onInterval = (PWM_CYCLE_PERIOD * percent)/100;
+ uint16_t onInterval = (period * percent)/100;
NEXUS_Pwm_GetDefaultChannelSettings(&pwmSettings);
pwmSettings.openDrain = f->open_drain;
pwmSettings.eFreqMode = NEXUS_PwmFreqModeType_eConstant;
pwm = NEXUS_Pwm_OpenChannel(f->pwm_index, &pwmSettings);
- if (NEXUS_Pwm_SetOnAndPeriodInterval(pwm, onInterval, PWM_CYCLE_PERIOD)) {
+ if (NEXUS_Pwm_SetOnAndPeriodInterval(pwm, onInterval, period)) {
fprintf(stderr, "Could not set ON and PERIOD for PWM. Aborting...\n");
platform_cleanup();
exit(EXIT_FAILURE);
diff --git a/gpio-mailbox/brcm-platform.h b/gpio-mailbox/brcm-platform.h
index 1322c60..4b53be9 100644
--- a/gpio-mailbox/brcm-platform.h
+++ b/gpio-mailbox/brcm-platform.h
@@ -41,6 +41,7 @@
unsigned int pwm_index; // index of this pwm.
unsigned int channel;
int old_percent;
+ int period;
};
struct Temp {
@@ -101,9 +102,6 @@
/* Set the provided PWM to the given duty cycle percent */
extern void set_pwm(struct PwmControl *, int);
-/* Return the duty cycle for the given PWM */
-extern int get_pwm(struct PwmControl *);
-
/* Init GPIO to input or output. */
extern void set_direction(struct Gpio *);