r2046 - in trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian: . patches
Sven Luther
luther@haydn.debian.org
Fri, 24 Dec 2004 04:07:01 -0700
Author: luther
Date: 2004-12-24 04:06:40 -0700 (Fri, 24 Dec 2004)
New Revision: 2046
Added:
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-970fx-support
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-g5-thermal-management-update
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-misc-powermac-fixes
Modified:
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
Log:
Added couple of powermac fixes and newer g5 suport by benh. Closes: #287030
Modified: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog 2004-12-24 06:41:12 UTC (rev 2045)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog 2004-12-24 11:06:40 UTC (rev 2046)
@@ -1,3 +1,13 @@
+kernel-source-2.6.8 (2.6.8-12) UNRELEASED; urgency=high
+
+ * Added a couple of powermac patches from Benjamin Herrenschmidt :
+ - 970FX cpu support
+ - G5 thermal management update
+ - Misc powermac fixes backports
+ (Closes: #287030)
+
+ -- Sven Luther <luther@debian.org> Fri, 24 Dec 2004 11:52:01 +0100
+
kernel-source-2.6.8 (2.6.8-11) unstable; urgency=high
* [SECURITY] serialize dgram read using semaphore just like stream;
Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-970fx-support
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-970fx-support 2004-12-24 06:41:12 UTC (rev 2045)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-970fx-support 2004-12-24 11:06:40 UTC (rev 2046)
@@ -0,0 +1,55 @@
+#! /bin/sh -e
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: PPC970FX cpu support.
+## DP: Patch author: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+## DP: Upstream status: backport.
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+diff -ur kernel-source-2.6.7.orig/arch/ppc/platforms/chrp_pci.c kernel-source-2.6.7.peg2/arch/ppc/platforms/chrp_pci.c
+diff -urN debian-kernel-2.6.8/arch/ppc/kernel/cpu_setup_power4.S debian-kernel-2.6.8-patched/arch/ppc/kernel/cpu_setup_power4.S
+--- debian-kernel-2.6.8/arch/ppc/kernel/cpu_setup_power4.S 2004-08-14 07:37:37.000000000 +0200
++++ debian-kernel-2.6.8-patched/arch/ppc/kernel/cpu_setup_power4.S 2004-12-24 10:47:29.000000000 +0100
+@@ -112,7 +112,9 @@
+ /* We only deal with 970 for now */
+ mfspr r0,SPRN_PVR
+ srwi r0,r0,16
+- cmpwi r0,0x39
++ cmpwi cr0,r0,0x39
++ cmpwi cr1,r0,0x3c
++ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ bne 1f
+
+ /* Save HID0,1,4 and 5 */
+@@ -144,7 +146,9 @@
+ /* We only deal with 970 for now */
+ mfspr r0,SPRN_PVR
+ srwi r0,r0,16
+- cmpwi r0,0x39
++ cmpwi cr0,r0,0x39
++ cmpwi cr1,r0,0x3c
++ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ bne 1f
+
+ /* Clear interrupt prefix */
+diff -urN debian-kernel-2.6.8/arch/ppc/kernel/cputable.c debian-kernel-2.6.8-patched/arch/ppc/kernel/cputable.c
+--- debian-kernel-2.6.8/arch/ppc/kernel/cputable.c 2004-11-24 22:47:25.000000000 +0100
++++ debian-kernel-2.6.8-patched/arch/ppc/kernel/cputable.c 2004-12-24 10:48:47.000000000 +0100
+@@ -450,6 +450,15 @@
+ 128, 128,
+ __setup_cpu_ppc970
+ },
++ { /* PPC970FX */
++ 0xffff0000, 0x003c0000, "PPC970FX",
++ CPU_FTR_COMMON |
++ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
++ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP,
++ COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_ALTIVEC_COMP,
++ 128, 128,
++ __setup_cpu_ppc970
++ },
+ #endif /* CONFIG_POWER4 */
+ #ifdef CONFIG_8xx
+ { /* 8xx */
Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-g5-thermal-management-update
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-g5-thermal-management-update 2004-12-24 06:41:12 UTC (rev 2045)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-g5-thermal-management-update 2004-12-24 11:06:40 UTC (rev 2046)
@@ -0,0 +1,1000 @@
+#! /bin/sh -e
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: G5 thermal management update
+## DP: Patch author: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+## DP: Upstream status: backport.
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+diff -urN debian-kernel-2.6.8/drivers/macintosh/therm_pm72.c debian-kernel-2.6.8-patched/drivers/macintosh/therm_pm72.c
+--- debian-kernel-2.6.8/drivers/macintosh/therm_pm72.c 2004-08-14 07:37:38.000000000 +0200
++++ debian-kernel-2.6.8-patched/drivers/macintosh/therm_pm72.c 2004-12-05 05:20:34.000000000 +0100
+@@ -46,6 +46,9 @@
+ * overtemp conditions so userland can take some policy
+ * decisions, like slewing down CPUs
+ * - Deal with fan and i2c failures in a better way
++ * - Maybe do a generic PID based on params used for
++ * U3 and Drives ?
++ * - Add RackMac3,1 support (XServe g5)
+ *
+ * History:
+ *
+@@ -73,6 +76,15 @@
+ * values in the configuration register
+ * - Switch back to use of target fan speed for PID, thus lowering
+ * pressure on i2c
++ *
++ * Oct. 20, 2004 : 1.1
++ * - Add device-tree lookup for fan IDs, should detect liquid cooling
++ * pumps when present
++ * - Enable driver for PowerMac7,3 machines
++ * - Split the U3/Backside cooling on U3 & U3H versions as Darwin does
++ * - Add new CPU cooling algorithm for machines with liquid cooling
++ * - Workaround for some PowerMac7,3 with empty "fan" node in the devtree
++ * - Fix a signed/unsigned compare issue in some PID loops
+ */
+
+ #include <linux/config.h>
+@@ -101,7 +113,7 @@
+
+ #include "therm_pm72.h"
+
+-#define VERSION "0.9"
++#define VERSION "1.1"
+
+ #undef DEBUG
+
+@@ -121,16 +133,100 @@
+ static struct i2c_adapter * u3_1;
+ static struct i2c_client * fcu;
+ static struct cpu_pid_state cpu_state[2];
++static struct basckside_pid_params backside_params;
+ static struct backside_pid_state backside_state;
+ static struct drives_pid_state drives_state;
+ static int state;
+ static int cpu_count;
++static int cpu_pid_type;
+ static pid_t ctrl_task;
+ static struct completion ctrl_complete;
+ static int critical_state;
+ static DECLARE_MUTEX(driver_lock);
+
+ /*
++ * We have 2 types of CPU PID control. One is "split" old style control
++ * for intake & exhaust fans, the other is "combined" control for both
++ * CPUs that also deals with the pumps when present. To be "compatible"
++ * with OS X at this point, we only use "COMBINED" on the machines that
++ * are identified as having the pumps (though that identification is at
++ * least dodgy). Ultimately, we could probably switch completely to this
++ * algorithm provided we hack it to deal with the UP case
++ */
++#define CPU_PID_TYPE_SPLIT 0
++#define CPU_PID_TYPE_COMBINED 1
++
++/*
++ * This table describes all fans in the FCU. The "id" and "type" values
++ * are defaults valid for all earlier machines. Newer machines will
++ * eventually override the table content based on the device-tree
++ */
++struct fcu_fan_table
++{
++ char* loc; /* location code */
++ int type; /* 0 = rpm, 1 = pwm, 2 = pump */
++ int id; /* id or -1 */
++};
++
++#define FCU_FAN_RPM 0
++#define FCU_FAN_PWM 1
++
++#define FCU_FAN_ABSENT_ID -1
++
++#define FCU_FAN_COUNT ARRAY_SIZE(fcu_fans)
++
++struct fcu_fan_table fcu_fans[] = {
++ [BACKSIDE_FAN_PWM_INDEX] = {
++ .loc = "BACKSIDE",
++ .type = FCU_FAN_PWM,
++ .id = BACKSIDE_FAN_PWM_DEFAULT_ID,
++ },
++ [DRIVES_FAN_RPM_INDEX] = {
++ .loc = "DRIVE BAY",
++ .type = FCU_FAN_RPM,
++ .id = DRIVES_FAN_RPM_DEFAULT_ID,
++ },
++ [SLOTS_FAN_PWM_INDEX] = {
++ .loc = "SLOT",
++ .type = FCU_FAN_PWM,
++ .id = SLOTS_FAN_PWM_DEFAULT_ID,
++ },
++ [CPUA_INTAKE_FAN_RPM_INDEX] = {
++ .loc = "CPU A INTAKE",
++ .type = FCU_FAN_RPM,
++ .id = CPUA_INTAKE_FAN_RPM_DEFAULT_ID,
++ },
++ [CPUA_EXHAUST_FAN_RPM_INDEX] = {
++ .loc = "CPU A EXHAUST",
++ .type = FCU_FAN_RPM,
++ .id = CPUA_EXHAUST_FAN_RPM_DEFAULT_ID,
++ },
++ [CPUB_INTAKE_FAN_RPM_INDEX] = {
++ .loc = "CPU B INTAKE",
++ .type = FCU_FAN_RPM,
++ .id = CPUB_INTAKE_FAN_RPM_DEFAULT_ID,
++ },
++ [CPUB_EXHAUST_FAN_RPM_INDEX] = {
++ .loc = "CPU B EXHAUST",
++ .type = FCU_FAN_RPM,
++ .id = CPUB_EXHAUST_FAN_RPM_DEFAULT_ID,
++ },
++ /* pumps aren't present by default, have to be looked up in the
++ * device-tree
++ */
++ [CPUA_PUMP_RPM_INDEX] = {
++ .loc = "CPU A PUMP",
++ .type = FCU_FAN_RPM,
++ .id = FCU_FAN_ABSENT_ID,
++ },
++ [CPUB_PUMP_RPM_INDEX] = {
++ .loc = "CPU B PUMP",
++ .type = FCU_FAN_RPM,
++ .id = FCU_FAN_ABSENT_ID,
++ },
++};
++
++/*
+ * i2c_driver structure to attach to the host i2c controller
+ */
+
+@@ -139,8 +235,8 @@
+
+ static struct i2c_driver therm_pm72_driver =
+ {
++ .owner = THIS_MODULE,
+ .name = "therm_pm72",
+- .id = 0xDEADBEEF,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = therm_pm72_attach,
+ .detach_adapter = therm_pm72_detach,
+@@ -170,7 +266,6 @@
+ clt->addr = (id >> 1) & 0x7f;
+ clt->adapter = adap;
+ clt->driver = &therm_pm72_driver;
+- clt->id = 0xDEADBEEF;
+ strncpy(clt->name, name, I2C_NAME_SIZE-1);
+
+ if (i2c_attach_client(clt)) {
+@@ -331,10 +426,16 @@
+ return 0;
+ }
+
+-static int set_rpm_fan(int fan, int rpm)
++static int set_rpm_fan(int fan_index, int rpm)
+ {
+ unsigned char buf[2];
+- int rc;
++ int rc, id;
++
++ if (fcu_fans[fan_index].type != FCU_FAN_RPM)
++ return -EINVAL;
++ id = fcu_fans[fan_index].id;
++ if (id == FCU_FAN_ABSENT_ID)
++ return -EINVAL;
+
+ if (rpm < 300)
+ rpm = 300;
+@@ -342,43 +443,55 @@
+ rpm = 8191;
+ buf[0] = rpm >> 5;
+ buf[1] = rpm << 3;
+- rc = fan_write_reg(0x10 + (fan * 2), buf, 2);
++ rc = fan_write_reg(0x10 + (id * 2), buf, 2);
+ if (rc < 0)
+ return -EIO;
+ return 0;
+ }
+
+-static int get_rpm_fan(int fan, int programmed)
++static int get_rpm_fan(int fan_index, int programmed)
+ {
+ unsigned char failure;
+ unsigned char active;
+ unsigned char buf[2];
+- int rc, reg_base;
++ int rc, id, reg_base;
++
++ if (fcu_fans[fan_index].type != FCU_FAN_RPM)
++ return -EINVAL;
++ id = fcu_fans[fan_index].id;
++ if (id == FCU_FAN_ABSENT_ID)
++ return -EINVAL;
+
+ rc = fan_read_reg(0xb, &failure, 1);
+ if (rc != 1)
+ return -EIO;
+- if ((failure & (1 << fan)) != 0)
++ if ((failure & (1 << id)) != 0)
+ return -EFAULT;
+ rc = fan_read_reg(0xd, &active, 1);
+ if (rc != 1)
+ return -EIO;
+- if ((active & (1 << fan)) == 0)
++ if ((active & (1 << id)) == 0)
+ return -ENXIO;
+
+ /* Programmed value or real current speed */
+ reg_base = programmed ? 0x10 : 0x11;
+- rc = fan_read_reg(reg_base + (fan * 2), buf, 2);
++ rc = fan_read_reg(reg_base + (id * 2), buf, 2);
+ if (rc != 2)
+ return -EIO;
+
+ return (buf[0] << 5) | buf[1] >> 3;
+ }
+
+-static int set_pwm_fan(int fan, int pwm)
++static int set_pwm_fan(int fan_index, int pwm)
+ {
+ unsigned char buf[2];
+- int rc;
++ int rc, id;
++
++ if (fcu_fans[fan_index].type != FCU_FAN_PWM)
++ return -EINVAL;
++ id = fcu_fans[fan_index].id;
++ if (id == FCU_FAN_ABSENT_ID)
++ return -EINVAL;
+
+ if (pwm < 10)
+ pwm = 10;
+@@ -386,32 +499,38 @@
+ pwm = 100;
+ pwm = (pwm * 2559) / 1000;
+ buf[0] = pwm;
+- rc = fan_write_reg(0x30 + (fan * 2), buf, 1);
++ rc = fan_write_reg(0x30 + (id * 2), buf, 1);
+ if (rc < 0)
+ return rc;
+ return 0;
+ }
+
+-static int get_pwm_fan(int fan)
++static int get_pwm_fan(int fan_index)
+ {
+ unsigned char failure;
+ unsigned char active;
+ unsigned char buf[2];
+- int rc;
++ int rc, id;
++
++ if (fcu_fans[fan_index].type != FCU_FAN_PWM)
++ return -EINVAL;
++ id = fcu_fans[fan_index].id;
++ if (id == FCU_FAN_ABSENT_ID)
++ return -EINVAL;
+
+ rc = fan_read_reg(0x2b, &failure, 1);
+ if (rc != 1)
+ return -EIO;
+- if ((failure & (1 << fan)) != 0)
++ if ((failure & (1 << id)) != 0)
+ return -EFAULT;
+ rc = fan_read_reg(0x2d, &active, 1);
+ if (rc != 1)
+ return -EIO;
+- if ((active & (1 << fan)) == 0)
++ if ((active & (1 << id)) == 0)
+ return -ENXIO;
+
+ /* Programmed value or real current speed */
+- rc = fan_read_reg(0x30 + (fan * 2), buf, 1);
++ rc = fan_read_reg(0x30 + (id * 2), buf, 1);
+ if (rc != 1)
+ return -EIO;
+
+@@ -513,80 +632,84 @@
+ /*
+ * CPUs fans control loop
+ */
+-static void do_monitor_cpu(struct cpu_pid_state *state)
++
++static int do_read_one_cpu_values(struct cpu_pid_state *state, s32 *temp, s32 *power)
+ {
+- s32 temp, voltage, current_a, power, power_target;
+- s32 integral, derivative, proportional, adj_in_target, sval;
+- s64 integ_p, deriv_p, prop_p, sum;
+- int i, intake, rc;
++ s32 ltemp, volts, amps;
++ int rc = 0;
+
+- DBG("cpu %d:\n", state->index);
++ /* Default (in case of error) */
++ *temp = state->cur_temp;
++ *power = state->cur_power;
+
+ /* Read current fan status */
+ if (state->index == 0)
+- rc = get_rpm_fan(CPUA_EXHAUST_FAN_RPM_ID, !RPM_PID_USE_ACTUAL_SPEED);
++ rc = get_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED);
+ else
+- rc = get_rpm_fan(CPUB_EXHAUST_FAN_RPM_ID, !RPM_PID_USE_ACTUAL_SPEED);
++ rc = get_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED);
+ if (rc < 0) {
+- printk(KERN_WARNING "Error %d reading CPU %d exhaust fan !\n",
+- rc, state->index);
+- /* XXX What do we do now ? */
+- } else
++ /* XXX What do we do now ? Nothing for now, keep old value, but
++ * return error upstream
++ */
++ DBG(" cpu %d, fan reading error !\n", state->index);
++ } else {
+ state->rpm = rc;
+- DBG(" current rpm: %d\n", state->rpm);
++ DBG(" cpu %d, exhaust RPM: %d\n", state->index, state->rpm);
++ }
+
+ /* Get some sensor readings and scale it */
+- temp = read_smon_adc(state, 1);
+- if (temp == -1) {
++ ltemp = read_smon_adc(state, 1);
++ if (ltemp == -1) {
++ /* XXX What do we do now ? */
+ state->overtemp++;
+- return;
++ if (rc == 0)
++ rc = -EIO;
++ DBG(" cpu %d, temp reading error !\n", state->index);
++ } else {
++ /* Fixup temperature according to diode calibration
++ */
++ DBG(" cpu %d, temp raw: %04x, m_diode: %04x, b_diode: %04x\n",
++ state->index,
++ ltemp, state->mpu.mdiode, state->mpu.bdiode);
++ *temp = ((s32)ltemp * (s32)state->mpu.mdiode + ((s32)state->mpu.bdiode << 12)) >> 2;
++ state->last_temp = *temp;
++ DBG(" temp: %d.%03d\n", FIX32TOPRINT((*temp)));
+ }
+- voltage = read_smon_adc(state, 3);
+- current_a = read_smon_adc(state, 4);
+
+- /* Fixup temperature according to diode calibration
++ /*
++ * Read voltage & current and calculate power
+ */
+- DBG(" temp raw: %04x, m_diode: %04x, b_diode: %04x\n",
+- temp, state->mpu.mdiode, state->mpu.bdiode);
+- temp = ((s32)temp * (s32)state->mpu.mdiode + ((s32)state->mpu.bdiode << 12)) >> 2;
+- state->last_temp = temp;
+- DBG(" temp: %d.%03d\n", FIX32TOPRINT(temp));
++ volts = read_smon_adc(state, 3);
++ amps = read_smon_adc(state, 4);
+
+- /* Check tmax, increment overtemp if we are there. At tmax+8, we go
+- * full blown immediately and try to trigger a shutdown
+- */
+- if (temp >= ((state->mpu.tmax + 8) << 16)) {
+- printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum"
+- " (%d) !\n",
+- state->index, temp >> 16);
+- state->overtemp = CPU_MAX_OVERTEMP;
+- } else if (temp > (state->mpu.tmax << 16))
+- state->overtemp++;
+- else
+- state->overtemp = 0;
+- if (state->overtemp >= CPU_MAX_OVERTEMP)
+- critical_state = 1;
+- if (state->overtemp > 0) {
+- state->rpm = state->mpu.rmaxn_exhaust_fan;
+- state->intake_rpm = intake = state->mpu.rmaxn_intake_fan;
+- goto do_set_fans;
+- }
+-
+- /* Scale other sensor values according to fixed scales
++ /* Scale voltage and current raw sensor values according to fixed scales
+ * obtained in Darwin and calculate power from I and V
+ */
+- state->voltage = voltage *= ADC_CPU_VOLTAGE_SCALE;
+- state->current_a = current_a *= ADC_CPU_CURRENT_SCALE;
+- power = (((u64)current_a) * ((u64)voltage)) >> 16;
++ volts *= ADC_CPU_VOLTAGE_SCALE;
++ amps *= ADC_CPU_CURRENT_SCALE;
++ *power = (((u64)volts) * ((u64)amps)) >> 16;
++ state->voltage = volts;
++ state->current_a = amps;
++ state->last_power = *power;
++
++ DBG(" cpu %d, current: %d.%03d, voltage: %d.%03d, power: %d.%03d W\n",
++ state->index, FIX32TOPRINT(state->current_a),
++ FIX32TOPRINT(state->voltage), FIX32TOPRINT(*power));
++
++ return 0;
++}
++
++static void do_cpu_pid(struct cpu_pid_state *state, s32 temp, s32 power)
++{
++ s32 power_target, integral, derivative, proportional, adj_in_target, sval;
++ s64 integ_p, deriv_p, prop_p, sum;
++ int i;
+
+ /* Calculate power target value (could be done once for all)
+ * and convert to a 16.16 fp number
+ */
+ power_target = ((u32)(state->mpu.pmaxh - state->mpu.padjmax)) << 16;
+-
+- DBG(" current: %d.%03d, voltage: %d.%03d\n",
+- FIX32TOPRINT(current_a), FIX32TOPRINT(voltage));
+- DBG(" power: %d.%03d W, target: %d.%03d, error: %d.%03d\n", FIX32TOPRINT(power),
++ DBG(" power target: %d.%03d, error: %d.%03d\n",
+ FIX32TOPRINT(power_target), FIX32TOPRINT(power_target - power));
+
+ /* Store temperature and power in history array */
+@@ -626,7 +749,7 @@
+ * input target is mpu.ttarget, input max is mpu.tmax
+ */
+ integ_p = ((s64)state->mpu.pid_gr) * (s64)integral;
+- DBG(" integ_p: %d\n", (int)(deriv_p >> 36));
++ DBG(" integ_p: %d\n", (int)(integ_p >> 36));
+ sval = (state->mpu.tmax << 16) - ((integ_p >> 20) & 0xffffffff);
+ adj_in_target = (state->mpu.ttarget << 16);
+ if (adj_in_target > sval)
+@@ -655,15 +778,136 @@
+ DBG(" sum: %d\n", (int)sum);
+ state->rpm += (s32)sum;
+
+- if (state->rpm < state->mpu.rminn_exhaust_fan)
++ if (state->rpm < (int)state->mpu.rminn_exhaust_fan)
+ state->rpm = state->mpu.rminn_exhaust_fan;
+- if (state->rpm > state->mpu.rmaxn_exhaust_fan)
++ if (state->rpm > (int)state->mpu.rmaxn_exhaust_fan)
+ state->rpm = state->mpu.rmaxn_exhaust_fan;
++}
++
++static void do_monitor_cpu_combined(void)
++{
++ struct cpu_pid_state *state0 = &cpu_state[0];
++ struct cpu_pid_state *state1 = &cpu_state[1];
++ s32 temp0, power0, temp1, power1;
++ s32 temp_combi, power_combi;
++ int rc, intake, pump;
++
++ rc = do_read_one_cpu_values(state0, &temp0, &power0);
++ if (rc < 0) {
++ /* XXX What do we do now ? */
++ }
++ state1->overtemp = 0;
++ rc = do_read_one_cpu_values(state1, &temp1, &power1);
++ if (rc < 0) {
++ /* XXX What do we do now ? */
++ }
++ if (state1->overtemp)
++ state0->overtemp++;
++
++ temp_combi = max(temp0, temp1);
++ power_combi = max(power0, power1);
++
++ /* Check tmax, increment overtemp if we are there. At tmax+8, we go
++ * full blown immediately and try to trigger a shutdown
++ */
++ if (temp_combi >= ((state0->mpu.tmax + 8) << 16)) {
++ printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n",
++ temp_combi >> 16);
++ state0->overtemp = CPU_MAX_OVERTEMP;
++ } else if (temp_combi > (state0->mpu.tmax << 16))
++ state0->overtemp++;
++ else
++ state0->overtemp = 0;
++ if (state0->overtemp >= CPU_MAX_OVERTEMP)
++ critical_state = 1;
++ if (state0->overtemp > 0) {
++ state0->rpm = state0->mpu.rmaxn_exhaust_fan;
++ state0->intake_rpm = intake = state0->mpu.rmaxn_intake_fan;
++ pump = CPU_PUMP_OUTPUT_MAX;
++ goto do_set_fans;
++ }
++
++ /* Do the PID */
++ do_cpu_pid(state0, temp_combi, power_combi);
++
++ /* Calculate intake fan speed */
++ intake = (state0->rpm * CPU_INTAKE_SCALE) >> 16;
++ if (intake < (int)state0->mpu.rminn_intake_fan)
++ intake = state0->mpu.rminn_intake_fan;
++ if (intake > (int)state0->mpu.rmaxn_intake_fan)
++ intake = state0->mpu.rmaxn_intake_fan;
++ state0->intake_rpm = intake;
++
++ /* Calculate pump speed */
++ pump = (state0->rpm * CPU_PUMP_OUTPUT_MAX) /
++ state0->mpu.rmaxn_exhaust_fan;
++ if (pump > CPU_PUMP_OUTPUT_MAX)
++ pump = CPU_PUMP_OUTPUT_MAX;
++ if (pump < CPU_PUMP_OUTPUT_MIN)
++ pump = CPU_PUMP_OUTPUT_MIN;
++
++ do_set_fans:
++ /* We copy values from state 0 to state 1 for /sysfs */
++ state1->rpm = state0->rpm;
++ state1->intake_rpm = state0->intake_rpm;
++
++ DBG("** CPU %d RPM: %d Ex, %d, Pump: %d, In, overtemp: %d\n",
++ state1->index, (int)state1->rpm, intake, pump, state1->overtemp);
++
++ /* We should check for errors, shouldn't we ? But then, what
++ * do we do once the error occurs ? For FCU notified fan
++ * failures (-EFAULT) we probably want to notify userland
++ * some way...
++ */
++ set_rpm_fan(CPUA_INTAKE_FAN_RPM_INDEX, intake);
++ set_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, state0->rpm);
++ set_rpm_fan(CPUB_INTAKE_FAN_RPM_INDEX, intake);
++ set_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, state0->rpm);
++
++ if (fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID)
++ set_rpm_fan(CPUA_PUMP_RPM_INDEX, pump);
++ if (fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID)
++ set_rpm_fan(CPUB_PUMP_RPM_INDEX, pump);
++}
++
++static void do_monitor_cpu_split(struct cpu_pid_state *state)
++{
++ s32 temp, power;
++ int rc, intake;
++
++ /* Read current fan status */
++ rc = do_read_one_cpu_values(state, &temp, &power);
++ if (rc < 0) {
++ /* XXX What do we do now ? */
++ }
++
++ /* Check tmax, increment overtemp if we are there. At tmax+8, we go
++ * full blown immediately and try to trigger a shutdown
++ */
++ if (temp >= ((state->mpu.tmax + 8) << 16)) {
++ printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum"
++ " (%d) !\n",
++ state->index, temp >> 16);
++ state->overtemp = CPU_MAX_OVERTEMP;
++ } else if (temp > (state->mpu.tmax << 16))
++ state->overtemp++;
++ else
++ state->overtemp = 0;
++ if (state->overtemp >= CPU_MAX_OVERTEMP)
++ critical_state = 1;
++ if (state->overtemp > 0) {
++ state->rpm = state->mpu.rmaxn_exhaust_fan;
++ state->intake_rpm = intake = state->mpu.rmaxn_intake_fan;
++ goto do_set_fans;
++ }
++
++ /* Do the PID */
++ do_cpu_pid(state, temp, power);
+
+ intake = (state->rpm * CPU_INTAKE_SCALE) >> 16;
+- if (intake < state->mpu.rminn_intake_fan)
++ if (intake < (int)state->mpu.rminn_intake_fan)
+ intake = state->mpu.rminn_intake_fan;
+- if (intake > state->mpu.rmaxn_intake_fan)
++ if (intake > (int)state->mpu.rmaxn_intake_fan)
+ intake = state->mpu.rmaxn_intake_fan;
+ state->intake_rpm = intake;
+
+@@ -677,11 +921,11 @@
+ * some way...
+ */
+ if (state->index == 0) {
+- set_rpm_fan(CPUA_INTAKE_FAN_RPM_ID, intake);
+- set_rpm_fan(CPUA_EXHAUST_FAN_RPM_ID, state->rpm);
++ set_rpm_fan(CPUA_INTAKE_FAN_RPM_INDEX, intake);
++ set_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, state->rpm);
+ } else {
+- set_rpm_fan(CPUB_INTAKE_FAN_RPM_ID, intake);
+- set_rpm_fan(CPUB_EXHAUST_FAN_RPM_ID, state->rpm);
++ set_rpm_fan(CPUB_INTAKE_FAN_RPM_INDEX, intake);
++ set_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, state->rpm);
+ }
+ }
+
+@@ -696,6 +940,7 @@
+ state->overtemp = 0;
+ state->adc_config = 0x00;
+
++
+ if (index == 0)
+ state->monitor = attach_i2c_chip(SUPPLY_MONITOR_ID, "CPU0_monitor");
+ else if (index == 1)
+@@ -778,7 +1023,7 @@
+ DBG("backside:\n");
+
+ /* Check fan status */
+- rc = get_pwm_fan(BACKSIDE_FAN_PWM_ID);
++ rc = get_pwm_fan(BACKSIDE_FAN_PWM_INDEX);
+ if (rc < 0) {
+ printk(KERN_WARNING "Error %d reading backside fan !\n", rc);
+ /* XXX What do we do now ? */
+@@ -790,12 +1035,12 @@
+ temp = i2c_smbus_read_byte_data(state->monitor, MAX6690_EXT_TEMP) << 16;
+ state->last_temp = temp;
+ DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+- FIX32TOPRINT(BACKSIDE_PID_INPUT_TARGET));
++ FIX32TOPRINT(backside_params.input_target));
+
+ /* Store temperature and error in history array */
+ state->cur_sample = (state->cur_sample + 1) % BACKSIDE_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+- state->error_history[state->cur_sample] = temp - BACKSIDE_PID_INPUT_TARGET;
++ state->error_history[state->cur_sample] = temp - backside_params.input_target;
+
+ /* If first loop, fill the history table */
+ if (state->first) {
+@@ -804,7 +1049,7 @@
+ BACKSIDE_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+ state->error_history[state->cur_sample] =
+- temp - BACKSIDE_PID_INPUT_TARGET;
++ temp - backside_params.input_target;
+ }
+ state->first = 0;
+ }
+@@ -816,7 +1061,7 @@
+ integral += state->error_history[i];
+ integral *= BACKSIDE_PID_INTERVAL;
+ DBG(" integral: %08x\n", integral);
+- integ_p = ((s64)BACKSIDE_PID_G_r) * (s64)integral;
++ integ_p = ((s64)backside_params.G_r) * (s64)integral;
+ DBG(" integ_p: %d\n", (int)(integ_p >> 36));
+ sum += integ_p;
+
+@@ -825,12 +1070,12 @@
+ state->error_history[(state->cur_sample + BACKSIDE_PID_HISTORY_SIZE - 1)
+ % BACKSIDE_PID_HISTORY_SIZE];
+ derivative /= BACKSIDE_PID_INTERVAL;
+- deriv_p = ((s64)BACKSIDE_PID_G_d) * (s64)derivative;
++ deriv_p = ((s64)backside_params.G_d) * (s64)derivative;
+ DBG(" deriv_p: %d\n", (int)(deriv_p >> 36));
+ sum += deriv_p;
+
+ /* Calculate the proportional term */
+- prop_p = ((s64)BACKSIDE_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
++ prop_p = ((s64)backside_params.G_p) * (s64)(state->error_history[state->cur_sample]);
+ DBG(" prop_p: %d\n", (int)(prop_p >> 36));
+ sum += prop_p;
+
+@@ -839,13 +1084,13 @@
+
+ DBG(" sum: %d\n", (int)sum);
+ state->pwm += (s32)sum;
+- if (state->pwm < BACKSIDE_PID_OUTPUT_MIN)
+- state->pwm = BACKSIDE_PID_OUTPUT_MIN;
+- if (state->pwm > BACKSIDE_PID_OUTPUT_MAX)
+- state->pwm = BACKSIDE_PID_OUTPUT_MAX;
++ if (state->pwm < backside_params.output_min)
++ state->pwm = backside_params.output_min;
++ if (state->pwm > backside_params.output_max)
++ state->pwm = backside_params.output_max;
+
+ DBG("** BACKSIDE PWM: %d\n", (int)state->pwm);
+- set_pwm_fan(BACKSIDE_FAN_PWM_ID, state->pwm);
++ set_pwm_fan(BACKSIDE_FAN_PWM_INDEX, state->pwm);
+ }
+
+ /*
+@@ -853,6 +1098,35 @@
+ */
+ static int init_backside_state(struct backside_pid_state *state)
+ {
++ struct device_node *u3;
++ int u3h = 1; /* conservative by default */
++
++ /*
++ * There are different PID params for machines with U3 and machines
++ * with U3H, pick the right ones now
++ */
++ u3 = of_find_node_by_path("/u3@0,f8000000");
++ if (u3 != NULL) {
++ u32 *vers = (u32 *)get_property(u3, "device-rev", NULL);
++ if (vers)
++ if (((*vers) & 0x3f) < 0x34)
++ u3h = 0;
++ of_node_put(u3);
++ }
++
++ backside_params.G_p = BACKSIDE_PID_G_p;
++ backside_params.G_r = BACKSIDE_PID_G_r;
++ backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX;
++ if (u3h) {
++ backside_params.G_d = BACKSIDE_PID_U3H_G_d;
++ backside_params.input_target = BACKSIDE_PID_U3H_INPUT_TARGET;
++ backside_params.output_min = BACKSIDE_PID_U3H_OUTPUT_MIN;
++ } else {
++ backside_params.G_d = BACKSIDE_PID_U3_G_d;
++ backside_params.input_target = BACKSIDE_PID_U3_INPUT_TARGET;
++ backside_params.output_min = BACKSIDE_PID_U3_OUTPUT_MIN;
++ }
++
+ state->ticks = 1;
+ state->first = 1;
+ state->pwm = 50;
+@@ -898,7 +1172,7 @@
+ DBG("drives:\n");
+
+ /* Check fan status */
+- rc = get_rpm_fan(DRIVES_FAN_RPM_ID, !RPM_PID_USE_ACTUAL_SPEED);
++ rc = get_rpm_fan(DRIVES_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED);
+ if (rc < 0) {
+ printk(KERN_WARNING "Error %d reading drives fan !\n", rc);
+ /* XXX What do we do now ? */
+@@ -965,7 +1239,7 @@
+ state->rpm = DRIVES_PID_OUTPUT_MAX;
+
+ DBG("** DRIVES RPM: %d\n", (int)state->rpm);
+- set_rpm_fan(DRIVES_FAN_RPM_ID, state->rpm);
++ set_rpm_fan(DRIVES_FAN_RPM_INDEX, state->rpm);
+ }
+
+ /*
+@@ -1032,7 +1306,7 @@
+ }
+
+ /* Set the PCI fan once for now */
+- set_pwm_fan(SLOTS_FAN_PWM_ID, SLOTS_FAN_DEFAULT_PWM);
++ set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+
+ /* Initialize ADCs */
+ initialize_adc(&cpu_state[0]);
+@@ -1047,9 +1321,13 @@
+ start = jiffies;
+
+ down(&driver_lock);
+- do_monitor_cpu(&cpu_state[0]);
+- if (cpu_state[1].monitor != NULL)
+- do_monitor_cpu(&cpu_state[1]);
++ if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
++ do_monitor_cpu_combined();
++ else {
++ do_monitor_cpu_split(&cpu_state[0]);
++ if (cpu_state[1].monitor != NULL)
++ do_monitor_cpu_split(&cpu_state[1]);
++ }
+ do_monitor_backside(&backside_state);
+ do_monitor_drives(&drives_state);
+ up(&driver_lock);
+@@ -1113,6 +1391,19 @@
+
+ DBG("counted %d CPUs in the device-tree\n", cpu_count);
+
++ /* Decide the type of PID algorithm to use based on the presence of
++ * the pumps, though that may not be the best way, that is good enough
++ * for now
++ */
++ if (machine_is_compatible("PowerMac7,3")
++ && (cpu_count > 1)
++ && fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID
++ && fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) {
++ printk(KERN_INFO "Liquid cooling pumps detected, using new algorithm !\n");
++ cpu_pid_type = CPU_PID_TYPE_COMBINED;
++ } else
++ cpu_pid_type = CPU_PID_TYPE_SPLIT;
++
+ /* Create control loops for everything. If any fail, everything
+ * fails
+ */
+@@ -1257,12 +1548,91 @@
+ return 0;
+ }
+
++static void fcu_lookup_fans(struct device_node *fcu_node)
++{
++ struct device_node *np = NULL;
++ int i;
++
++ /* The table is filled by default with values that are suitable
++ * for the old machines without device-tree informations. We scan
++ * the device-tree and override those values with whatever is
++ * there
++ */
++
++ DBG("Looking up FCU controls in device-tree...\n");
++
++ while ((np = of_get_next_child(fcu_node, np)) != NULL) {
++ int type = -1;
++ char *loc;
++ u32 *reg;
++
++ DBG(" control: %s, type: %s\n", np->name, np->type);
++
++ /* Detect control type */
++ if (!strcmp(np->type, "fan-rpm-control") ||
++ !strcmp(np->type, "fan-rpm"))
++ type = FCU_FAN_RPM;
++ if (!strcmp(np->type, "fan-pwm-control") ||
++ !strcmp(np->type, "fan-pwm"))
++ type = FCU_FAN_PWM;
++ /* Only care about fans for now */
++ if (type == -1)
++ continue;
++
++ /* Lookup for a matching location */
++ loc = (char *)get_property(np, "location", NULL);
++ reg = (u32 *)get_property(np, "reg", NULL);
++ if (loc == NULL || reg == NULL)
++ continue;
++ DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg);
++
++ for (i = 0; i < FCU_FAN_COUNT; i++) {
++ int fan_id;
++
++ if (strcmp(loc, fcu_fans[i].loc))
++ continue;
++ DBG(" location match, index: %d\n", i);
++ fcu_fans[i].id = FCU_FAN_ABSENT_ID;
++ if (type != fcu_fans[i].type) {
++ printk(KERN_WARNING "therm_pm72: Fan type mismatch "
++ "in device-tree for %s\n", np->full_name);
++ break;
++ }
++ if (type == FCU_FAN_RPM)
++ fan_id = ((*reg) - 0x10) / 2;
++ else
++ fan_id = ((*reg) - 0x30) / 2;
++ if (fan_id > 7) {
++ printk(KERN_WARNING "therm_pm72: Can't parse "
++ "fan ID in device-tree for %s\n", np->full_name);
++ break;
++ }
++ DBG(" fan id -> %d, type -> %d\n", fan_id, type);
++ fcu_fans[i].id = fan_id;
++ }
++ }
++
++ /* Now dump the array */
++ printk(KERN_INFO "Detected fan controls:\n");
++ for (i = 0; i < FCU_FAN_COUNT; i++) {
++ if (fcu_fans[i].id == FCU_FAN_ABSENT_ID)
++ continue;
++ printk(KERN_INFO " %d: %s fan, id %d, location: %s\n", i,
++ fcu_fans[i].type == FCU_FAN_RPM ? "RPM" : "PWM",
++ fcu_fans[i].id, fcu_fans[i].loc);
++ }
++}
++
+ static int fcu_of_probe(struct of_device* dev, const struct of_match *match)
+ {
+ int rc;
+
+ state = state_detached;
+
++ /* Lookup the fans in the device tree */
++ fcu_lookup_fans(dev->node);
++
++ /* Add the driver */
+ rc = i2c_add_driver(&therm_pm72_driver);
+ if (rc < 0)
+ return rc;
+@@ -1301,15 +1671,20 @@
+ {
+ struct device_node *np;
+
+- if (!machine_is_compatible("PowerMac7,2"))
++ if (!machine_is_compatible("PowerMac7,2") &&
++ !machine_is_compatible("PowerMac7,3"))
+ return -ENODEV;
+
+ printk(KERN_INFO "PowerMac G5 Thermal control driver %s\n", VERSION);
+
+ np = of_find_node_by_type(NULL, "fcu");
+ if (np == NULL) {
+- printk(KERN_ERR "Can't find FCU in device-tree !\n");
+- return -ENODEV;
++ /* Some machines have strangely broken device-tree */
++ np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e");
++ if (np == NULL) {
++ printk(KERN_ERR "Can't find FCU in device-tree !\n");
++ return -ENODEV;
++ }
+ }
+ of_dev = of_platform_device_create(np, "temperature");
+ if (of_dev == NULL) {
+diff -urN debian-kernel-2.6.8/drivers/macintosh/therm_pm72.h debian-kernel-2.6.8-patched/drivers/macintosh/therm_pm72.h
+--- debian-kernel-2.6.8/drivers/macintosh/therm_pm72.h 2004-08-14 07:36:57.000000000 +0200
++++ debian-kernel-2.6.8-patched/drivers/macintosh/therm_pm72.h 2004-11-22 01:49:45.000000000 +0100
+@@ -119,18 +119,33 @@
+ #define ADC_CPU_CURRENT_SCALE 0x1f40 /* _AD4 */
+
+ /*
+- * PID factors for the U3/Backside fan control loop
++ * PID factors for the U3/Backside fan control loop. We have 2 sets
++ * of values here, one set for U3 and one set for U3H
+ */
+-#define BACKSIDE_FAN_PWM_ID 1
+-#define BACKSIDE_PID_G_d 0x02800000
++#define BACKSIDE_FAN_PWM_DEFAULT_ID 1
++#define BACKSIDE_FAN_PWM_INDEX 0
++#define BACKSIDE_PID_U3_G_d 0x02800000
++#define BACKSIDE_PID_U3H_G_d 0x01400000
+ #define BACKSIDE_PID_G_p 0x00500000
+ #define BACKSIDE_PID_G_r 0x00000000
+-#define BACKSIDE_PID_INPUT_TARGET 0x00410000
++#define BACKSIDE_PID_U3_INPUT_TARGET 0x00410000
++#define BACKSIDE_PID_U3H_INPUT_TARGET 0x004b0000
+ #define BACKSIDE_PID_INTERVAL 5
+ #define BACKSIDE_PID_OUTPUT_MAX 100
+-#define BACKSIDE_PID_OUTPUT_MIN 20
++#define BACKSIDE_PID_U3_OUTPUT_MIN 20
++#define BACKSIDE_PID_U3H_OUTPUT_MIN 30
+ #define BACKSIDE_PID_HISTORY_SIZE 2
+
++struct basckside_pid_params
++{
++ s32 G_d;
++ s32 G_p;
++ s32 G_r;
++ s32 input_target;
++ s32 output_min;
++ s32 output_max;
++};
++
+ struct backside_pid_state
+ {
+ int ticks;
+@@ -146,7 +161,8 @@
+ /*
+ * PID factors for the Drive Bay fan control loop
+ */
+-#define DRIVES_FAN_RPM_ID 2
++#define DRIVES_FAN_RPM_DEFAULT_ID 2
++#define DRIVES_FAN_RPM_INDEX 1
+ #define DRIVES_PID_G_d 0x01e00000
+ #define DRIVES_PID_G_p 0x00500000
+ #define DRIVES_PID_G_r 0x00000000
+@@ -168,7 +184,8 @@
+ int first;
+ };
+
+-#define SLOTS_FAN_PWM_ID 2
++#define SLOTS_FAN_PWM_DEFAULT_ID 2
++#define SLOTS_FAN_PWM_INDEX 2
+ #define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */
+
+ /*
+@@ -191,10 +208,15 @@
+ * CPU B FAKE POWER 49 (I_V_inputs: 18, 19)
+ */
+
+-#define CPUA_INTAKE_FAN_RPM_ID 3
+-#define CPUA_EXHAUST_FAN_RPM_ID 4
+-#define CPUB_INTAKE_FAN_RPM_ID 5
+-#define CPUB_EXHAUST_FAN_RPM_ID 6
++#define CPUA_INTAKE_FAN_RPM_DEFAULT_ID 3
++#define CPUA_EXHAUST_FAN_RPM_DEFAULT_ID 4
++#define CPUB_INTAKE_FAN_RPM_DEFAULT_ID 5
++#define CPUB_EXHAUST_FAN_RPM_DEFAULT_ID 6
++
++#define CPUA_INTAKE_FAN_RPM_INDEX 3
++#define CPUA_EXHAUST_FAN_RPM_INDEX 4
++#define CPUB_INTAKE_FAN_RPM_INDEX 5
++#define CPUB_EXHAUST_FAN_RPM_INDEX 6
+
+ #define CPU_INTAKE_SCALE 0x0000f852
+ #define CPU_TEMP_HISTORY_SIZE 2
+@@ -202,6 +224,11 @@
+ #define CPU_PID_INTERVAL 1
+ #define CPU_MAX_OVERTEMP 30
+
++#define CPUA_PUMP_RPM_INDEX 7
++#define CPUB_PUMP_RPM_INDEX 8
++#define CPU_PUMP_OUTPUT_MAX 3700
++#define CPU_PUMP_OUTPUT_MIN 1000
++
+ struct cpu_pid_state
+ {
+ int index;
+@@ -219,6 +246,7 @@
+ s32 voltage;
+ s32 current_a;
+ s32 last_temp;
++ s32 last_power;
+ int first;
+ u8 adc_config;
+ };
Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-misc-powermac-fixes
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-misc-powermac-fixes 2004-12-24 06:41:12 UTC (rev 2045)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/powerpc-misc-powermac-fixes 2004-12-24 11:06:40 UTC (rev 2046)
@@ -0,0 +1,110 @@
+#! /bin/sh -e
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Misc powermac fixes backports
+## DP: Patch author: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+
+diff -urN debian-kernel-2.6.8/arch/ppc/kernel/pci.c debian-kernel-2.6.8-patched/arch/ppc/kernel/pci.c
+--- debian-kernel-2.6.8/arch/ppc/kernel/pci.c 2004-08-14 07:36:57.000000000 +0200
++++ debian-kernel-2.6.8-patched/arch/ppc/kernel/pci.c 2004-12-24 11:02:28.000000000 +0100
+@@ -33,6 +33,7 @@
+ unsigned long isa_io_base = 0;
+ unsigned long isa_mem_base = 0;
+ unsigned long pci_dram_offset = 0;
++int pcibios_assign_bus_offset = 1;
+
+ void pcibios_make_OF_bus_map(void);
+
+@@ -1279,7 +1280,7 @@
+ bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
+ hose->last_busno = bus->subordinate;
+ if (pci_assign_all_busses || next_busno <= hose->last_busno)
+- next_busno = hose->last_busno+1;
++ next_busno = hose->last_busno + pcibios_assign_bus_offset;
+ }
+ pci_bus_count = next_busno;
+
+diff -urN debian-kernel-2.6.8/arch/ppc/platforms/pmac_feature.c debian-kernel-2.6.8-patched/arch/ppc/platforms/pmac_feature.c
+--- debian-kernel-2.6.8/arch/ppc/platforms/pmac_feature.c 2004-08-14 07:37:41.000000000 +0200
++++ debian-kernel-2.6.8-patched/arch/ppc/platforms/pmac_feature.c 2004-12-24 10:55:34.000000000 +0100
+@@ -2169,6 +2169,10 @@
+ PMAC_TYPE_POWERMAC_G5, g5_features,
+ 0,
+ },
++ { "PowerMac7,3", "PowerMac G5",
++ PMAC_TYPE_POWERMAC_G5, g5_features,
++ 0,
++ },
+ #endif /* CONFIG_POWER4 */
+ };
+
+@@ -2665,7 +2669,7 @@
+ struct device_node *p = of_get_parent(ui2c);
+ if (p && !strcmp(p->name, "uni-n"))
+ break;
+- ui2c = of_find_node_by_type(np, "i2c");
++ ui2c = of_find_node_by_type(ui2c, "i2c");
+ }
+ if (ui2c == NULL)
+ break;
+diff -urN debian-kernel-2.6.8/arch/ppc/platforms/pmac_pci.c debian-kernel-2.6.8-patched/arch/ppc/platforms/pmac_pci.c
+--- debian-kernel-2.6.8/arch/ppc/platforms/pmac_pci.c 2004-08-14 07:36:58.000000000 +0200
++++ debian-kernel-2.6.8-patched/arch/ppc/platforms/pmac_pci.c 2004-12-24 10:51:06.000000000 +0100
+@@ -50,6 +50,7 @@
+ #endif /* CONFIG_POWER4 */
+
+ extern u8 pci_cache_line_size;
++extern int pcibios_assign_bus_offset;
+
+ struct pci_dev *k2_skiplist[2];
+
+@@ -315,6 +316,10 @@
+ unsigned int addr;
+ int i;
+
++ struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
++ if (np == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
+ /*
+ * When a device in K2 is powered down, we die on config
+ * cycle accesses. Fix that here.
+@@ -362,6 +367,9 @@
+ unsigned int addr;
+ int i;
+
++ struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
++ if (np == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * When a device in K2 is powered down, we die on config
+ * cycle accesses. Fix that here.
+@@ -565,6 +573,14 @@
+
+ init_p2pbridge();
+ fixup_nec_usb2();
++
++ /* We are still having some issues with the Xserve G4, enabling
++ * some offset between bus number and domains for now when we
++ * assign all busses should help for now
++ */
++ if (pci_assign_all_busses)
++ pcibios_assign_bus_offset = 0x10;
++
+ #ifdef CONFIG_POWER4
+ /* There is something wrong with DMA on U3/HT. I haven't figured out
+ * the details yet, but if I set the cache line size to 128 bytes like
+@@ -707,7 +723,7 @@
+ * properties or figuring out the U3 address space decoding logic and
+ * then read its configuration register (if any).
+ */
+- hose->io_base_phys = 0xf4000000 + 0x00400000;
++ hose->io_base_phys = 0xf4000000;
+ hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
+ isa_io_base = (unsigned long) hose->io_base_virt;
+ hose->io_resource.name = np->full_name;