mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [POWERPC] Minor comment fix for misc_64.S [POWERPC] Use H_CEDE on non-SMT [POWERPC] force 64bit mode in fwnmi handlers to workaround firmware bugs [POWERPC] PMAC_APM_EMU should depend on ADB_PMU [POWERPC] Fix new interrupt code (MPIC detection) [POWERPC] Fix new interrupt code (MPIC endianness) [POWERPC] Add cpufreq support for Xserve G5 [POWERPC] Xserve G5 thermal control fixes [POWERPC] Fix mem= handling when the memory limit is > RMO size [POWERPC] More offb/bootx fixes [POWERPC] Fix legacy_serial.c error handling on 32 bits [POWERPC] Fix default clock for udbg_16550 [POWERPC] Fix non-MPIC CHRPs with CONFIG_SMP set [POWERPC] Fix 32 bits warning in prom_init.c [POWERPC] Workaround Pegasos incorrect ISA "ranges" [POWERPC] fix up front-LED Kconfig
This commit is contained in:
commit
49b1e3ea19
20 changed files with 703 additions and 263 deletions
|
|
@ -90,6 +90,15 @@ config ADB_PMU_LED
|
|||
and the ide-disk LED trigger and configure appropriately through
|
||||
sysfs.
|
||||
|
||||
config ADB_PMU_LED_IDE
|
||||
bool "Use front LED as IDE LED by default"
|
||||
depends on ADB_PMU_LED
|
||||
select LEDS_TRIGGERS
|
||||
select LEDS_TRIGGER_IDE_DISK
|
||||
help
|
||||
This option makes the front LED default to the IDE trigger
|
||||
so that it blinks on IDE activity.
|
||||
|
||||
config PMAC_SMU
|
||||
bool "Support for SMU based PowerMacs"
|
||||
depends on PPC_PMAC64
|
||||
|
|
@ -100,7 +109,7 @@ config PMAC_SMU
|
|||
|
||||
config PMAC_APM_EMU
|
||||
tristate "APM emulation"
|
||||
depends on PPC_PMAC && PPC32 && PM
|
||||
depends on PPC_PMAC && PPC32 && PM && ADB_PMU
|
||||
|
||||
config PMAC_MEDIABAY
|
||||
bool "Support PowerBook hotswap media bay"
|
||||
|
|
|
|||
|
|
@ -95,6 +95,17 @@
|
|||
* - Use min/max macros here or there
|
||||
* - Latest darwin updated U3H min fan speed to 20% PWM
|
||||
*
|
||||
* July. 06, 2006 : 1.3
|
||||
* - Fix setting of RPM fans on Xserve G5 (they were going too fast)
|
||||
* - Add missing slots fan control loop for Xserve G5
|
||||
* - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
|
||||
* still can't properly implement the control loop for these, so let's
|
||||
* reduce the noise a little bit, it appears that 40% still gives us
|
||||
* a pretty good air flow
|
||||
* - Add code to "tickle" the FCU regulary so it doesn't think that
|
||||
* we are gone while in fact, the machine just didn't need any fan
|
||||
* speed change lately
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
|
@ -121,7 +132,7 @@
|
|||
|
||||
#include "therm_pm72.h"
|
||||
|
||||
#define VERSION "1.2b2"
|
||||
#define VERSION "1.3"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
|
|
@ -146,6 +157,7 @@ static struct basckside_pid_params backside_params;
|
|||
static struct backside_pid_state backside_state;
|
||||
static struct drives_pid_state drives_state;
|
||||
static struct dimm_pid_state dimms_state;
|
||||
static struct slots_pid_state slots_state;
|
||||
static int state;
|
||||
static int cpu_count;
|
||||
static int cpu_pid_type;
|
||||
|
|
@ -154,7 +166,8 @@ static struct completion ctrl_complete;
|
|||
static int critical_state;
|
||||
static int rackmac;
|
||||
static s32 dimm_output_clamp;
|
||||
|
||||
static int fcu_rpm_shift;
|
||||
static int fcu_tickle_ticks;
|
||||
static DECLARE_MUTEX(driver_lock);
|
||||
|
||||
/*
|
||||
|
|
@ -495,13 +508,20 @@ static int start_fcu(void)
|
|||
rc = fan_write_reg(0x2e, &buf, 1);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
rc = fan_read_reg(0, &buf, 1);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
fcu_rpm_shift = (buf == 1) ? 2 : 3;
|
||||
printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
|
||||
fcu_rpm_shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_rpm_fan(int fan_index, int rpm)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
int rc, id;
|
||||
int rc, id, min, max;
|
||||
|
||||
if (fcu_fans[fan_index].type != FCU_FAN_RPM)
|
||||
return -EINVAL;
|
||||
|
|
@ -509,12 +529,15 @@ static int set_rpm_fan(int fan_index, int rpm)
|
|||
if (id == FCU_FAN_ABSENT_ID)
|
||||
return -EINVAL;
|
||||
|
||||
if (rpm < 300)
|
||||
rpm = 300;
|
||||
else if (rpm > 8191)
|
||||
rpm = 8191;
|
||||
buf[0] = rpm >> 5;
|
||||
buf[1] = rpm << 3;
|
||||
min = 2400 >> fcu_rpm_shift;
|
||||
max = 56000 >> fcu_rpm_shift;
|
||||
|
||||
if (rpm < min)
|
||||
rpm = min;
|
||||
else if (rpm > max)
|
||||
rpm = max;
|
||||
buf[0] = rpm >> (8 - fcu_rpm_shift);
|
||||
buf[1] = rpm << fcu_rpm_shift;
|
||||
rc = fan_write_reg(0x10 + (id * 2), buf, 2);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
|
|
@ -551,7 +574,7 @@ static int get_rpm_fan(int fan_index, int programmed)
|
|||
if (rc != 2)
|
||||
return -EIO;
|
||||
|
||||
return (buf[0] << 5) | buf[1] >> 3;
|
||||
return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
|
||||
}
|
||||
|
||||
static int set_pwm_fan(int fan_index, int pwm)
|
||||
|
|
@ -609,6 +632,26 @@ static int get_pwm_fan(int fan_index)
|
|||
return (buf[0] * 1000) / 2559;
|
||||
}
|
||||
|
||||
static void tickle_fcu(void)
|
||||
{
|
||||
int pwm;
|
||||
|
||||
pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
|
||||
|
||||
DBG("FCU Tickle, slots fan is: %d\n", pwm);
|
||||
if (pwm < 0)
|
||||
pwm = 100;
|
||||
|
||||
if (!rackmac) {
|
||||
pwm = SLOTS_FAN_DEFAULT_PWM;
|
||||
} else if (pwm < SLOTS_PID_OUTPUT_MIN)
|
||||
pwm = SLOTS_PID_OUTPUT_MIN;
|
||||
|
||||
/* That is hopefully enough to make the FCU happy */
|
||||
set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Utility routine to read the CPU calibration EEPROM data
|
||||
* from the device-tree
|
||||
|
|
@ -715,6 +758,9 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
|
|||
BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
|
||||
BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
|
||||
|
||||
BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
|
||||
BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
|
||||
|
||||
BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
|
||||
|
||||
static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
|
||||
|
|
@ -735,6 +781,9 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL);
|
|||
static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
|
||||
static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
|
||||
|
||||
static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
|
||||
static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
|
||||
|
||||
static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
|
||||
|
||||
/*
|
||||
|
|
@ -1076,6 +1125,9 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
|
|||
fan_min = dimm_output_clamp;
|
||||
fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
|
||||
|
||||
DBG(" CPU min mpu = %d, min dimm = %d\n",
|
||||
state->mpu.rminn_intake_fan, dimm_output_clamp);
|
||||
|
||||
state->rpm = max(state->rpm, (int)fan_min);
|
||||
state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
|
||||
state->intake_rpm = state->rpm;
|
||||
|
|
@ -1374,7 +1426,8 @@ static void do_monitor_drives(struct drives_pid_state *state)
|
|||
DBG(" current rpm: %d\n", state->rpm);
|
||||
|
||||
/* Get some sensor readings */
|
||||
temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
|
||||
temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
|
||||
DS1775_TEMP)) << 8;
|
||||
state->last_temp = temp;
|
||||
DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
|
||||
FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
|
||||
|
|
@ -1575,7 +1628,7 @@ static int init_dimms_state(struct dimm_pid_state *state)
|
|||
}
|
||||
|
||||
/*
|
||||
* Dispose of the state data for the drives control loop
|
||||
* Dispose of the state data for the DIMM control loop
|
||||
*/
|
||||
static void dispose_dimms_state(struct dimm_pid_state *state)
|
||||
{
|
||||
|
|
@ -1588,6 +1641,127 @@ static void dispose_dimms_state(struct dimm_pid_state *state)
|
|||
state->monitor = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slots fan control loop
|
||||
*/
|
||||
static void do_monitor_slots(struct slots_pid_state *state)
|
||||
{
|
||||
s32 temp, integral, derivative;
|
||||
s64 integ_p, deriv_p, prop_p, sum;
|
||||
int i, rc;
|
||||
|
||||
if (--state->ticks != 0)
|
||||
return;
|
||||
state->ticks = SLOTS_PID_INTERVAL;
|
||||
|
||||
DBG("slots:\n");
|
||||
|
||||
/* Check fan status */
|
||||
rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
|
||||
if (rc < 0) {
|
||||
printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
|
||||
/* XXX What do we do now ? */
|
||||
} else
|
||||
state->pwm = rc;
|
||||
DBG(" current pwm: %d\n", state->pwm);
|
||||
|
||||
/* Get some sensor readings */
|
||||
temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
|
||||
DS1775_TEMP)) << 8;
|
||||
state->last_temp = temp;
|
||||
DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
|
||||
FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
|
||||
|
||||
/* Store temperature and error in history array */
|
||||
state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
|
||||
state->sample_history[state->cur_sample] = temp;
|
||||
state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
|
||||
|
||||
/* If first loop, fill the history table */
|
||||
if (state->first) {
|
||||
for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
|
||||
state->cur_sample = (state->cur_sample + 1) %
|
||||
SLOTS_PID_HISTORY_SIZE;
|
||||
state->sample_history[state->cur_sample] = temp;
|
||||
state->error_history[state->cur_sample] =
|
||||
temp - SLOTS_PID_INPUT_TARGET;
|
||||
}
|
||||
state->first = 0;
|
||||
}
|
||||
|
||||
/* Calculate the integral term */
|
||||
sum = 0;
|
||||
integral = 0;
|
||||
for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
|
||||
integral += state->error_history[i];
|
||||
integral *= SLOTS_PID_INTERVAL;
|
||||
DBG(" integral: %08x\n", integral);
|
||||
integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
|
||||
DBG(" integ_p: %d\n", (int)(integ_p >> 36));
|
||||
sum += integ_p;
|
||||
|
||||
/* Calculate the derivative term */
|
||||
derivative = state->error_history[state->cur_sample] -
|
||||
state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
|
||||
% SLOTS_PID_HISTORY_SIZE];
|
||||
derivative /= SLOTS_PID_INTERVAL;
|
||||
deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
|
||||
DBG(" deriv_p: %d\n", (int)(deriv_p >> 36));
|
||||
sum += deriv_p;
|
||||
|
||||
/* Calculate the proportional term */
|
||||
prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
|
||||
DBG(" prop_p: %d\n", (int)(prop_p >> 36));
|
||||
sum += prop_p;
|
||||
|
||||
/* Scale sum */
|
||||
sum >>= 36;
|
||||
|
||||
DBG(" sum: %d\n", (int)sum);
|
||||
state->pwm = (s32)sum;
|
||||
|
||||
state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
|
||||
state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
|
||||
|
||||
DBG("** DRIVES PWM: %d\n", (int)state->pwm);
|
||||
set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the state structure for the slots bay fan control loop
|
||||
*/
|
||||
static int init_slots_state(struct slots_pid_state *state)
|
||||
{
|
||||
state->ticks = 1;
|
||||
state->first = 1;
|
||||
state->pwm = 50;
|
||||
|
||||
state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
|
||||
if (state->monitor == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
|
||||
device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispose of the state data for the slots control loop
|
||||
*/
|
||||
static void dispose_slots_state(struct slots_pid_state *state)
|
||||
{
|
||||
if (state->monitor == NULL)
|
||||
return;
|
||||
|
||||
device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
|
||||
device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
|
||||
|
||||
detach_i2c_chip(state->monitor);
|
||||
state->monitor = NULL;
|
||||
}
|
||||
|
||||
|
||||
static int call_critical_overtemp(void)
|
||||
{
|
||||
char *argv[] = { critical_overtemp_path, NULL };
|
||||
|
|
@ -1617,14 +1791,17 @@ static int main_control_loop(void *x)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Set the PCI fan once for now */
|
||||
set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
|
||||
/* Set the PCI fan once for now on non-RackMac */
|
||||
if (!rackmac)
|
||||
set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
|
||||
|
||||
/* Initialize ADCs */
|
||||
initialize_adc(&cpu_state[0]);
|
||||
if (cpu_state[1].monitor != NULL)
|
||||
initialize_adc(&cpu_state[1]);
|
||||
|
||||
fcu_tickle_ticks = FCU_TICKLE_TICKS;
|
||||
|
||||
up(&driver_lock);
|
||||
|
||||
while (state == state_attached) {
|
||||
|
|
@ -1634,6 +1811,12 @@ static int main_control_loop(void *x)
|
|||
|
||||
down(&driver_lock);
|
||||
|
||||
/* Tickle the FCU just in case */
|
||||
if (--fcu_tickle_ticks < 0) {
|
||||
fcu_tickle_ticks = FCU_TICKLE_TICKS;
|
||||
tickle_fcu();
|
||||
}
|
||||
|
||||
/* First, we always calculate the new DIMMs state on an Xserve */
|
||||
if (rackmac)
|
||||
do_monitor_dimms(&dimms_state);
|
||||
|
|
@ -1654,7 +1837,9 @@ static int main_control_loop(void *x)
|
|||
}
|
||||
/* Then, the rest */
|
||||
do_monitor_backside(&backside_state);
|
||||
if (!rackmac)
|
||||
if (rackmac)
|
||||
do_monitor_slots(&slots_state);
|
||||
else
|
||||
do_monitor_drives(&drives_state);
|
||||
up(&driver_lock);
|
||||
|
||||
|
|
@ -1696,6 +1881,7 @@ static void dispose_control_loops(void)
|
|||
dispose_cpu_state(&cpu_state[1]);
|
||||
dispose_backside_state(&backside_state);
|
||||
dispose_drives_state(&drives_state);
|
||||
dispose_slots_state(&slots_state);
|
||||
dispose_dimms_state(&dimms_state);
|
||||
}
|
||||
|
||||
|
|
@ -1745,6 +1931,8 @@ static int create_control_loops(void)
|
|||
goto fail;
|
||||
if (rackmac && init_dimms_state(&dimms_state))
|
||||
goto fail;
|
||||
if (rackmac && init_slots_state(&slots_state))
|
||||
goto fail;
|
||||
if (!rackmac && init_drives_state(&drives_state))
|
||||
goto fail;
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp";
|
|||
#define DRIVES_DALLAS_ID 0x94
|
||||
#define BACKSIDE_MAX_ID 0x98
|
||||
#define XSERVE_DIMMS_LM87 0x25a
|
||||
#define XSERVE_SLOTS_LM75 0x290
|
||||
|
||||
/*
|
||||
* Some MAX6690, DS1775, LM87 register definitions
|
||||
|
|
@ -198,7 +199,7 @@ struct drives_pid_state
|
|||
|
||||
#define SLOTS_FAN_PWM_DEFAULT_ID 2
|
||||
#define SLOTS_FAN_PWM_INDEX 2
|
||||
#define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */
|
||||
#define SLOTS_FAN_DEFAULT_PWM 40 /* Do better here ! */
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -206,7 +207,7 @@ struct drives_pid_state
|
|||
*/
|
||||
#define DIMM_PID_G_d 0
|
||||
#define DIMM_PID_G_p 0
|
||||
#define DIMM_PID_G_r 0x6553600
|
||||
#define DIMM_PID_G_r 0x06553600
|
||||
#define DIMM_PID_INPUT_TARGET 3276800
|
||||
#define DIMM_PID_INTERVAL 1
|
||||
#define DIMM_PID_OUTPUT_MAX 14000
|
||||
|
|
@ -226,6 +227,31 @@ struct dimm_pid_state
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
* PID factors for the Xserve Slots control loop
|
||||
*/
|
||||
#define SLOTS_PID_G_d 0
|
||||
#define SLOTS_PID_G_p 0
|
||||
#define SLOTS_PID_G_r 0x00100000
|
||||
#define SLOTS_PID_INPUT_TARGET 3200000
|
||||
#define SLOTS_PID_INTERVAL 1
|
||||
#define SLOTS_PID_OUTPUT_MAX 100
|
||||
#define SLOTS_PID_OUTPUT_MIN 20
|
||||
#define SLOTS_PID_HISTORY_SIZE 20
|
||||
|
||||
struct slots_pid_state
|
||||
{
|
||||
int ticks;
|
||||
struct i2c_client * monitor;
|
||||
s32 sample_history[SLOTS_PID_HISTORY_SIZE];
|
||||
s32 error_history[SLOTS_PID_HISTORY_SIZE];
|
||||
int cur_sample;
|
||||
s32 last_temp;
|
||||
int first;
|
||||
int pwm;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Desktops */
|
||||
|
||||
|
|
@ -283,6 +309,9 @@ struct cpu_pid_state
|
|||
s32 pump_max;
|
||||
};
|
||||
|
||||
/* Tickle FCU every 10 seconds */
|
||||
#define FCU_TICKLE_TICKS 10
|
||||
|
||||
/*
|
||||
* Driver state
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ static void pmu_led_set(struct led_classdev *led_cdev,
|
|||
|
||||
static struct led_classdev pmu_led = {
|
||||
.name = "pmu-front-led",
|
||||
#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
|
||||
#ifdef CONFIG_ADB_PMU_LED_IDE
|
||||
.default_trigger = "ide-disk",
|
||||
#endif
|
||||
.brightness_set = pmu_led_set,
|
||||
|
|
|
|||
Loading…
Reference in a new issue