* [PATCH] windfarm: add PowerMac 12,1 support
From: Benjamin Herrenschmidt @ 2008-04-29 5:39 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 32653 bytes --]
From: Etienne Bersac <bersace@gmail.com>
Implement a new driver named windfarm_pm121 which drive fans on PowerMac
12,1 machine : iMac G5 iSight (rev C) 17" and 20". It's based on
windfarm_pm81 driver from Benjamin Herrenschmidt.
Signed-off-by: Etienne Bersac <bersace@gmail.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Initial patch by Etienne, fixes by David, but they couldn't be
bothered making that a single patch for merging so here it is.
(Etienne, the accent on your name didn't survive the process sorry)
arch/powerpc/configs/g5_defconfig | 1
drivers/macintosh/Kconfig | 8
drivers/macintosh/Makefile | 5
drivers/macintosh/windfarm_lm75_sensor.c | 6
drivers/macintosh/windfarm_max6690_sensor.c | 20
drivers/macintosh/windfarm_pm121.c | 1040 ++++++++++++++++++++++++++++
drivers/macintosh/windfarm_smu_controls.c | 4
7 files changed, 1078 insertions(+), 6 deletions(-)
--- linux-work.orig/arch/powerpc/configs/g5_defconfig 2008-04-22 10:15:29.000000000 +1000
+++ linux-work/arch/powerpc/configs/g5_defconfig 2008-04-29 15:32:50.000000000 +1000
@@ -696,6 +696,7 @@ CONFIG_WINDFARM=y
CONFIG_WINDFARM_PM81=y
CONFIG_WINDFARM_PM91=y
CONFIG_WINDFARM_PM112=y
+CONFIG_WINDFARM_PM121=y
# CONFIG_PMAC_RACKMETER is not set
CONFIG_NETDEVICES=y
# CONFIG_NETDEVICES_MULTIQUEUE is not set
Index: linux-work/drivers/macintosh/Kconfig
===================================================================
--- linux-work.orig/drivers/macintosh/Kconfig 2008-03-03 11:58:43.000000000 +1100
+++ linux-work/drivers/macintosh/Kconfig 2008-04-29 15:32:50.000000000 +1000
@@ -234,6 +234,14 @@ config WINDFARM_PM112
which are the recent dual and quad G5 machines using the
970MP dual-core processor.
+config WINDFARM_PM121
+ tristate "Support for thermal management on PowerMac12,1"
+ depends on WINDFARM && I2C && PMAC_SMU
+ select I2C_POWERMAC
+ help
+ This driver provides thermal control for the PowerMac12,1
+ which is the iMac G5 (iSight)
+
config ANSLCD
tristate "Support for ANS LCD display"
depends on ADB_CUDA && PPC_PMAC
Index: linux-work/drivers/macintosh/Makefile
===================================================================
--- linux-work.orig/drivers/macintosh/Makefile 2007-09-28 11:42:07.000000000 +1000
+++ linux-work/drivers/macintosh/Makefile 2008-04-29 15:32:50.000000000 +1000
@@ -42,4 +42,9 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm
windfarm_smu_sensors.o \
windfarm_max6690_sensor.o \
windfarm_lm75_sensor.o windfarm_pid.o
+obj-$(CONFIG_WINDFARM_PM121) += windfarm_pm121.o windfarm_smu_sat.o \
+ windfarm_smu_controls.o \
+ windfarm_smu_sensors.o \
+ windfarm_max6690_sensor.o \
+ windfarm_lm75_sensor.o windfarm_pid.o
obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o
Index: linux-work/drivers/macintosh/windfarm_lm75_sensor.c
===================================================================
--- linux-work.orig/drivers/macintosh/windfarm_lm75_sensor.c 2007-09-28 11:42:07.000000000 +1000
+++ linux-work/drivers/macintosh/windfarm_lm75_sensor.c 2008-04-29 15:32:50.000000000 +1000
@@ -127,6 +127,12 @@ static struct wf_lm75_sensor *wf_lm75_cr
*/
if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
lm->sens.name = "hd-temp";
+ else if (!strcmp(loc, "Incoming Air Temp"))
+ lm->sens.name = "incoming-air-temp";
+ else if (!strcmp(loc, "ODD Temp"))
+ lm->sens.name = "optical-drive-temp";
+ else if (!strcmp(loc, "HD Temp"))
+ lm->sens.name = "hard-drive-temp";
else
goto fail;
Index: linux-work/drivers/macintosh/windfarm_max6690_sensor.c
===================================================================
--- linux-work.orig/drivers/macintosh/windfarm_max6690_sensor.c 2007-09-28 11:42:07.000000000 +1000
+++ linux-work/drivers/macintosh/windfarm_max6690_sensor.c 2008-04-29 15:32:50.000000000 +1000
@@ -77,18 +77,28 @@ static struct wf_sensor_ops wf_max6690_o
.owner = THIS_MODULE,
};
-static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
+static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
+ const char *loc)
{
struct wf_6690_sensor *max;
- char *name = "backside-temp";
+ char *name;
max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
if (max == NULL) {
printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
- "no memory\n", name);
+ "no memory\n", loc);
return;
}
+ if (!strcmp(loc, "BACKSIDE"))
+ name = "backside-temp";
+ else if (!strcmp(loc, "NB Ambient"))
+ name = "north-bridge-temp";
+ else if (!strcmp(loc, "GPU Ambient"))
+ name = "gpu-temp";
+ else
+ goto fail;
+
max->sens.ops = &wf_max6690_ops;
max->sens.name = name;
max->i2c.addr = addr >> 1;
@@ -138,9 +148,7 @@ static int wf_max6690_attach(struct i2c_
if (loc == NULL || addr == 0)
continue;
printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
- if (strcmp(loc, "BACKSIDE"))
- continue;
- wf_max6690_create(adapter, addr);
+ wf_max6690_create(adapter, addr, loc);
}
return 0;
Index: linux-work/drivers/macintosh/windfarm_pm121.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-work/drivers/macintosh/windfarm_pm121.c 2008-04-29 15:32:58.000000000 +1000
@@ -0,0 +1,1040 @@
+/*
+ * Windfarm PowerMac thermal control. iMac G5 iSight
+ *
+ * (c) Copyright 2007 Étienne Bersac <bersace@gmail.com>
+ *
+ * Bits & pieces from windfarm_pm81.c by (c) Copyright 2005 Benjamin
+ * Herrenschmidt, IBM Corp. <benh@kernel.crashing.org>
+ *
+ * Released under the term of the GNU GPL v2.
+ *
+ *
+ *
+ * PowerMac12,1
+ * ============
+ *
+ *
+ * The algorithm used is the PID control algorithm, used the same way
+ * the published Darwin code does, using the same values that are
+ * present in the Darwin 8.10 snapshot property lists (note however
+ * that none of the code has been re-used, it's a complete
+ * re-implementation
+ *
+ * There is two models using PowerMac12,1. Model 2 is iMac G5 iSight
+ * 17" while Model 3 is iMac G5 20". They do have both the same
+ * controls with a tiny difference. The control-ids of hard-drive-fan
+ * and cpu-fan is swapped.
+ *
+ *
+ * Target Correction :
+ *
+ * controls have a target correction calculated as :
+ *
+ * new_min = ((((average_power * slope) >> 16) + offset) >> 16) + min_value
+ * new_value = max(new_value, max(new_min, 0))
+ *
+ * OD Fan control correction.
+ *
+ * # model_id: 2
+ * offset : -19563152
+ * slope : 1956315
+ *
+ * # model_id: 3
+ * offset : -15650652
+ * slope : 1565065
+ *
+ * HD Fan control correction.
+ *
+ * # model_id: 2
+ * offset : -15650652
+ * slope : 1565065
+ *
+ * # model_id: 3
+ * offset : -19563152
+ * slope : 1956315
+ *
+ * CPU Fan control correction.
+ *
+ * # model_id: 2
+ * offset : -25431900
+ * slope : 2543190
+ *
+ * # model_id: 3
+ * offset : -15650652
+ * slope : 1565065
+ *
+ *
+ * Target rubber-banding :
+ *
+ * Some controls have a target correction which depends on another
+ * control value. The correction is computed in the following way :
+ *
+ * new_min = ref_value * slope + offset
+ *
+ * ref_value is the value of the reference control. If new_min is
+ * greater than 0, then we correct the target value using :
+ *
+ * new_target = max (new_target, new_min >> 16)
+ *
+ *
+ * # model_id : 2
+ * control : cpu-fan
+ * ref : optical-drive-fan
+ * offset : -15650652
+ * slope : 1565065
+ *
+ * # model_id : 3
+ * control : optical-drive-fan
+ * ref : hard-drive-fan
+ * offset : -32768000
+ * slope : 65536
+ *
+ *
+ * In order to have the moste efficient correction with those
+ * dependencies, we must trigger HD loop before OD loop before CPU
+ * loop.
+ *
+ *
+ * The various control loops found in Darwin config file are:
+ *
+ * HD Fan control loop.
+ *
+ * # model_id: 2
+ * control : hard-drive-fan
+ * sensor : hard-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x002D70A3
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x370000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : hard-drive-fan
+ * sensor : hard-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x002170A3
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x370000
+ * Interval = 5s
+ *
+ * OD Fan control loop.
+ *
+ * # model_id: 2
+ * control : optical-drive-fan
+ * sensor : optical-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x001FAE14
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x320000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : optical-drive-fan
+ * sensor : optical-drive-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x001FAE14
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x320000
+ * Interval = 5s
+ *
+ * GPU Fan control loop.
+ *
+ * # model_id: 2
+ * control : hard-drive-fan
+ * sensor : gpu-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x002A6666
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x5A0000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : cpu-fan
+ * sensor : gpu-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x0010CCCC
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x500000
+ * Interval = 5s
+ *
+ * KODIAK (aka northbridge) Fan control loop.
+ *
+ * # model_id: 2
+ * control : optical-drive-fan
+ * sensor : north-bridge-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x003BD70A
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x550000
+ * Interval = 5s
+ *
+ * # model_id: 3
+ * control : hard-drive-fan
+ * sensor : north-bridge-temp
+ * PID params : G_d = 0x00000000
+ * G_p = 0x0030F5C2
+ * G_r = 0x00019999
+ * History = 2 entries
+ * Input target = 0x550000
+ * Interval = 5s
+ *
+ * CPU Fan control loop.
+ *
+ * control : cpu-fan
+ * sensors : cpu-temp, cpu-power
+ * PID params : from SDB partition
+ *
+ *
+ * CPU Slew control loop.
+ *
+ * control : cpufreq-clamp
+ * sensor : cpu-temp
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/kmod.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/sections.h>
+#include <asm/smu.h>
+
+#include "windfarm.h"
+#include "windfarm_pid.h"
+
+#define VERSION "0.3"
+
+static int pm121_mach_model; /* machine model id */
+
+/* Controls & sensors */
+static struct wf_sensor *sensor_cpu_power;
+static struct wf_sensor *sensor_cpu_temp;
+static struct wf_sensor *sensor_cpu_voltage;
+static struct wf_sensor *sensor_cpu_current;
+static struct wf_sensor *sensor_gpu_temp;
+static struct wf_sensor *sensor_north_bridge_temp;
+static struct wf_sensor *sensor_hard_drive_temp;
+static struct wf_sensor *sensor_optical_drive_temp;
+static struct wf_sensor *sensor_incoming_air_temp; /* unused ! */
+
+enum {
+ FAN_CPU,
+ FAN_HD,
+ FAN_OD,
+ CPUFREQ,
+ N_CONTROLS
+};
+static struct wf_control *controls[N_CONTROLS] = {};
+
+/* Set to kick the control loop into life */
+static int pm121_all_controls_ok, pm121_all_sensors_ok, pm121_started;
+
+enum {
+ FAILURE_FAN = 1 << 0,
+ FAILURE_SENSOR = 1 << 1,
+ FAILURE_OVERTEMP = 1 << 2
+};
+
+/* All sys loops. Note the HD before the OD loop in order to have it
+ run before. */
+enum {
+ LOOP_GPU, /* control = hd or cpu, but luckily,
+ it doesn't matter */
+ LOOP_HD, /* control = hd */
+ LOOP_KODIAK, /* control = hd or od */
+ LOOP_OD, /* control = od */
+ N_LOOPS
+};
+
+static const char *loop_names[N_LOOPS] = {
+ "GPU",
+ "HD",
+ "KODIAK",
+ "OD",
+};
+
+#define PM121_NUM_CONFIGS 2
+
+static unsigned int pm121_failure_state;
+static int pm121_readjust, pm121_skipping;
+static s32 average_power;
+
+struct pm121_correction {
+ int offset;
+ int slope;
+};
+
+static struct pm121_correction corrections[N_CONTROLS][PM121_NUM_CONFIGS] = {
+ /* FAN_OD */
+ {
+ /* MODEL 2 */
+ { .offset = -19563152,
+ .slope = 1956315
+ },
+ /* MODEL 3 */
+ { .offset = -15650652,
+ .slope = 1565065
+ },
+ },
+ /* FAN_HD */
+ {
+ /* MODEL 2 */
+ { .offset = -15650652,
+ .slope = 1565065
+ },
+ /* MODEL 3 */
+ { .offset = -19563152,
+ .slope = 1956315
+ },
+ },
+ /* FAN_CPU */
+ {
+ /* MODEL 2 */
+ { .offset = -25431900,
+ .slope = 2543190
+ },
+ /* MODEL 3 */
+ { .offset = -15650652,
+ .slope = 1565065
+ },
+ },
+ /* CPUFREQ has no correction (and is not implemented at all) */
+};
+
+struct pm121_connection {
+ unsigned int control_id;
+ unsigned int ref_id;
+ struct pm121_correction correction;
+};
+
+static struct pm121_connection pm121_connections[] = {
+ /* MODEL 2 */
+ { .control_id = FAN_CPU,
+ .ref_id = FAN_OD,
+ { .offset = -32768000,
+ .slope = 65536
+ }
+ },
+ /* MODEL 3 */
+ { .control_id = FAN_OD,
+ .ref_id = FAN_HD,
+ { .offset = -32768000,
+ .slope = 65536
+ }
+ },
+};
+
+/* pointer to the current model connection */
+static struct pm121_connection *pm121_connection;
+
+/*
+ * ****** System Fans Control Loop ******
+ *
+ */
+
+/* Since each loop handles only one control and we want to avoid
+ * writing virtual control, we store the control correction with the
+ * loop params. Some data are not set, there are common to all loop
+ * and thus, hardcoded.
+ */
+struct pm121_sys_param {
+ /* purely informative since we use mach_model-2 as index */
+ int model_id;
+ struct wf_sensor **sensor; /* use sensor_id instead ? */
+ s32 gp, itarget;
+ unsigned int control_id;
+};
+
+static struct pm121_sys_param
+pm121_sys_all_params[N_LOOPS][PM121_NUM_CONFIGS] = {
+ /* GPU Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_gpu_temp,
+ .gp = 0x002A6666,
+ .itarget = 0x5A0000,
+ .control_id = FAN_HD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_gpu_temp,
+ .gp = 0x0010CCCC,
+ .itarget = 0x500000,
+ .control_id = FAN_CPU,
+ },
+ },
+ /* HD Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_hard_drive_temp,
+ .gp = 0x002D70A3,
+ .itarget = 0x370000,
+ .control_id = FAN_HD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_hard_drive_temp,
+ .gp = 0x002170A3,
+ .itarget = 0x370000,
+ .control_id = FAN_HD,
+ },
+ },
+ /* KODIAK Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_north_bridge_temp,
+ .gp = 0x003BD70A,
+ .itarget = 0x550000,
+ .control_id = FAN_OD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_north_bridge_temp,
+ .gp = 0x0030F5C2,
+ .itarget = 0x550000,
+ .control_id = FAN_HD,
+ },
+ },
+ /* OD Fan control loop */
+ {
+ { .model_id = 2,
+ .sensor = &sensor_optical_drive_temp,
+ .gp = 0x001FAE14,
+ .itarget = 0x320000,
+ .control_id = FAN_OD,
+ },
+ { .model_id = 3,
+ .sensor = &sensor_optical_drive_temp,
+ .gp = 0x001FAE14,
+ .itarget = 0x320000,
+ .control_id = FAN_OD,
+ },
+ },
+};
+
+/* the hardcoded values */
+#define PM121_SYS_GD 0x00000000
+#define PM121_SYS_GR 0x00019999
+#define PM121_SYS_HISTORY_SIZE 2
+#define PM121_SYS_INTERVAL 5
+
+/* State data used by the system fans control loop
+ */
+struct pm121_sys_state {
+ int ticks;
+ s32 setpoint;
+ struct wf_pid_state pid;
+};
+
+struct pm121_sys_state *pm121_sys_state[N_LOOPS] = {};
+
+/*
+ * ****** CPU Fans Control Loop ******
+ *
+ */
+
+#define PM121_CPU_INTERVAL 1
+
+/* State data used by the cpu fans control loop
+ */
+struct pm121_cpu_state {
+ int ticks;
+ s32 setpoint;
+ struct wf_cpu_pid_state pid;
+};
+
+static struct pm121_cpu_state *pm121_cpu_state;
+
+
+
+/*
+ * ***** Implementation *****
+ *
+ */
+
+/* correction the value using the output-low-bound correction algo */
+static s32 pm121_correct(s32 new_setpoint,
+ unsigned int control_id,
+ s32 min)
+{
+ s32 new_min;
+ struct pm121_correction *correction;
+ correction = &corrections[control_id][pm121_mach_model - 2];
+
+ new_min = (average_power * correction->slope) >> 16;
+ new_min += correction->offset;
+ new_min = (new_min >> 16) + min;
+
+ return max(new_setpoint, max(new_min, 0));
+}
+
+static s32 pm121_connect(unsigned int control_id, s32 setpoint)
+{
+ s32 new_min, value, new_setpoint;
+
+ if (pm121_connection->control_id == control_id) {
+ controls[control_id]->ops->get_value(controls[control_id],
+ &value);
+ new_min = value * pm121_connection->correction.slope;
+ new_min += pm121_connection->correction.offset;
+ if (new_min > 0) {
+ new_setpoint = max(setpoint, (new_min >> 16));
+ if (new_setpoint != setpoint) {
+ pr_debug("pm121: %s depending on %s, "
+ "corrected from %d to %d RPM\n",
+ controls[control_id]->name,
+ controls[pm121_connection->ref_id]->name,
+ (int) setpoint, (int) new_setpoint);
+ }
+ } else
+ new_setpoint = setpoint;
+ }
+ /* no connection */
+ else
+ new_setpoint = setpoint;
+
+ return new_setpoint;
+}
+
+/* FAN LOOPS */
+static void pm121_create_sys_fans(int loop_id)
+{
+ struct pm121_sys_param *param = NULL;
+ struct wf_pid_param pid_param;
+ struct wf_control *control = NULL;
+ int i;
+
+ /* First, locate the params for this model */
+ for (i = 0; i < PM121_NUM_CONFIGS; i++) {
+ if (pm121_sys_all_params[loop_id][i].model_id == pm121_mach_model) {
+ param = &(pm121_sys_all_params[loop_id][i]);
+ break;
+ }
+ }
+
+ /* No params found, put fans to max */
+ if (param == NULL) {
+ printk(KERN_WARNING "pm121: %s fan config not found "
+ " for this machine model\n",
+ loop_names[loop_id]);
+ goto fail;
+ }
+
+ control = controls[param->control_id];
+
+ /* Alloc & initialize state */
+ pm121_sys_state[loop_id] = kmalloc(sizeof(struct pm121_sys_state),
+ GFP_KERNEL);
+ if (pm121_sys_state[loop_id] == NULL) {
+ printk(KERN_WARNING "pm121: Memory allocation error\n");
+ goto fail;
+ }
+ pm121_sys_state[loop_id]->ticks = 1;
+
+ /* Fill PID params */
+ pid_param.gd = PM121_SYS_GD;
+ pid_param.gp = param->gp;
+ pid_param.gr = PM121_SYS_GR;
+ pid_param.interval = PM121_SYS_INTERVAL;
+ pid_param.history_len = PM121_SYS_HISTORY_SIZE;
+ pid_param.itarget = param->itarget;
+ pid_param.min = control->ops->get_min(control);
+ pid_param.max = control->ops->get_max(control);
+
+ wf_pid_init(&pm121_sys_state[loop_id]->pid, &pid_param);
+
+ pr_debug("pm121: %s Fan control loop initialized.\n"
+ " itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
+ loop_names[loop_id], FIX32TOPRINT(pid_param.itarget),
+ pid_param.min, pid_param.max);
+ return;
+
+ fail:
+ /* note that this is not optimal since another loop may still
+ control the same control */
+ printk(KERN_WARNING "pm121: failed to set up %s loop "
+ "setting \"%s\" to max speed.\n",
+ loop_names[loop_id], control->name);
+
+ if (control)
+ wf_control_set_max(control);
+}
+
+static void pm121_sys_fans_tick(int loop_id)
+{
+ struct pm121_sys_param *param;
+ struct pm121_sys_state *st;
+ struct wf_sensor *sensor;
+ struct wf_control *control;
+ s32 temp, new_setpoint;
+ int rc;
+
+ param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
+ st = pm121_sys_state[loop_id];
+ sensor = *(param->sensor);
+ control = controls[param->control_id];
+
+ if (--st->ticks != 0) {
+ if (pm121_readjust)
+ goto readjust;
+ return;
+ }
+ st->ticks = PM121_SYS_INTERVAL;
+
+ rc = sensor->ops->get_value(sensor, &temp);
+ if (rc) {
+ printk(KERN_WARNING "windfarm: %s sensor error %d\n",
+ sensor->name, rc);
+ pm121_failure_state |= FAILURE_SENSOR;
+ return;
+ }
+
+ pr_debug("pm121: %s Fan tick ! %s: %d.%03d\n",
+ loop_names[loop_id], sensor->name,
+ FIX32TOPRINT(temp));
+
+ new_setpoint = wf_pid_run(&st->pid, temp);
+
+ /* correction */
+ new_setpoint = pm121_correct(new_setpoint,
+ param->control_id,
+ st->pid.param.min);
+ /* linked corretion */
+ new_setpoint = pm121_connect(param->control_id, new_setpoint);
+
+ if (new_setpoint == st->setpoint)
+ return;
+ st->setpoint = new_setpoint;
+ pr_debug("pm121: %s corrected setpoint: %d RPM\n",
+ control->name, (int)new_setpoint);
+ readjust:
+ if (control && pm121_failure_state == 0) {
+ rc = control->ops->set_value(control, st->setpoint);
+ if (rc) {
+ printk(KERN_WARNING "windfarm: %s fan error %d\n",
+ control->name, rc);
+ pm121_failure_state |= FAILURE_FAN;
+ }
+ }
+}
+
+
+/* CPU LOOP */
+static void pm121_create_cpu_fans(void)
+{
+ struct wf_cpu_pid_param pid_param;
+ const struct smu_sdbp_header *hdr;
+ struct smu_sdbp_cpupiddata *piddata;
+ struct smu_sdbp_fvt *fvt;
+ struct wf_control *fan_cpu;
+ s32 tmax, tdelta, maxpow, powadj;
+
+ fan_cpu = controls[FAN_CPU];
+
+ /* First, locate the PID params in SMU SBD */
+ hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
+ if (hdr == 0) {
+ printk(KERN_WARNING "pm121: CPU PID fan config not found.\n");
+ goto fail;
+ }
+ piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
+
+ /* Get the FVT params for operating point 0 (the only supported one
+ * for now) in order to get tmax
+ */
+ hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
+ if (hdr) {
+ fvt = (struct smu_sdbp_fvt *)&hdr[1];
+ tmax = ((s32)fvt->maxtemp) << 16;
+ } else
+ tmax = 0x5e0000; /* 94 degree default */
+
+ /* Alloc & initialize state */
+ pm121_cpu_state = kmalloc(sizeof(struct pm121_cpu_state),
+ GFP_KERNEL);
+ if (pm121_cpu_state == NULL)
+ goto fail;
+ pm121_cpu_state->ticks = 1;
+
+ /* Fill PID params */
+ pid_param.interval = PM121_CPU_INTERVAL;
+ pid_param.history_len = piddata->history_len;
+ if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
+ printk(KERN_WARNING "pm121: History size overflow on "
+ "CPU control loop (%d)\n", piddata->history_len);
+ pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
+ }
+ pid_param.gd = piddata->gd;
+ pid_param.gp = piddata->gp;
+ pid_param.gr = piddata->gr / pid_param.history_len;
+
+ tdelta = ((s32)piddata->target_temp_delta) << 16;
+ maxpow = ((s32)piddata->max_power) << 16;
+ powadj = ((s32)piddata->power_adj) << 16;
+
+ pid_param.tmax = tmax;
+ pid_param.ttarget = tmax - tdelta;
+ pid_param.pmaxadj = maxpow - powadj;
+
+ pid_param.min = fan_cpu->ops->get_min(fan_cpu);
+ pid_param.max = fan_cpu->ops->get_max(fan_cpu);
+
+ wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param);
+
+ pr_debug("pm121: CPU Fan control initialized.\n");
+ pr_debug(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
+ FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
+ pid_param.min, pid_param.max);
+
+ return;
+
+ fail:
+ printk(KERN_WARNING "pm121: CPU fan config not found, max fan speed\n");
+
+ if (controls[CPUFREQ])
+ wf_control_set_max(controls[CPUFREQ]);
+ if (fan_cpu)
+ wf_control_set_max(fan_cpu);
+}
+
+
+static void pm121_cpu_fans_tick(struct pm121_cpu_state *st)
+{
+ s32 new_setpoint, temp, power;
+ struct wf_control *fan_cpu = NULL;
+ int rc;
+
+ if (--st->ticks != 0) {
+ if (pm121_readjust)
+ goto readjust;
+ return;
+ }
+ st->ticks = PM121_CPU_INTERVAL;
+
+ fan_cpu = controls[FAN_CPU];
+
+ rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
+ if (rc) {
+ printk(KERN_WARNING "pm121: CPU temp sensor error %d\n",
+ rc);
+ pm121_failure_state |= FAILURE_SENSOR;
+ return;
+ }
+
+ rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
+ if (rc) {
+ printk(KERN_WARNING "pm121: CPU power sensor error %d\n",
+ rc);
+ pm121_failure_state |= FAILURE_SENSOR;
+ return;
+ }
+
+ pr_debug("pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
+ FIX32TOPRINT(temp), FIX32TOPRINT(power));
+
+ if (temp > st->pid.param.tmax)
+ pm121_failure_state |= FAILURE_OVERTEMP;
+
+ new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
+
+ /* correction */
+ new_setpoint = pm121_correct(new_setpoint,
+ FAN_CPU,
+ st->pid.param.min);
+
+ /* connected correction */
+ new_setpoint = pm121_connect(FAN_CPU, new_setpoint);
+
+ if (st->setpoint == new_setpoint)
+ return;
+ st->setpoint = new_setpoint;
+ pr_debug("pm121: CPU corrected setpoint: %d RPM\n", (int)new_setpoint);
+
+ readjust:
+ if (fan_cpu && pm121_failure_state == 0) {
+ rc = fan_cpu->ops->set_value(fan_cpu, st->setpoint);
+ if (rc) {
+ printk(KERN_WARNING "pm121: %s fan error %d\n",
+ fan_cpu->name, rc);
+ pm121_failure_state |= FAILURE_FAN;
+ }
+ }
+}
+
+/*
+ * ****** Common ******
+ *
+ */
+
+static void pm121_tick(void)
+{
+ unsigned int last_failure = pm121_failure_state;
+ unsigned int new_failure;
+ s32 total_power;
+ int i;
+
+ if (!pm121_started) {
+ pr_debug("pm121: creating control loops !\n");
+ for (i = 0; i < N_LOOPS; i++)
+ pm121_create_sys_fans(i);
+
+ pm121_create_cpu_fans();
+ pm121_started = 1;
+ }
+
+ /* skipping ticks */
+ if (pm121_skipping && --pm121_skipping)
+ return;
+
+ /* compute average power */
+ total_power = 0;
+ for (i = 0; i < pm121_cpu_state->pid.param.history_len; i++)
+ total_power += pm121_cpu_state->pid.powers[i];
+
+ average_power = total_power / pm121_cpu_state->pid.param.history_len;
+
+
+ pm121_failure_state = 0;
+ for (i = 0 ; i < N_LOOPS; i++) {
+ if (pm121_sys_state[i])
+ pm121_sys_fans_tick(i);
+ }
+
+ if (pm121_cpu_state)
+ pm121_cpu_fans_tick(pm121_cpu_state);
+
+ pm121_readjust = 0;
+ new_failure = pm121_failure_state & ~last_failure;
+
+ /* If entering failure mode, clamp cpufreq and ramp all
+ * fans to full speed.
+ */
+ if (pm121_failure_state && !last_failure) {
+ for (i = 0; i < N_CONTROLS; i++) {
+ if (controls[i])
+ wf_control_set_max(controls[i]);
+ }
+ }
+
+ /* If leaving failure mode, unclamp cpufreq and readjust
+ * all fans on next iteration
+ */
+ if (!pm121_failure_state && last_failure) {
+ if (controls[CPUFREQ])
+ wf_control_set_min(controls[CPUFREQ]);
+ pm121_readjust = 1;
+ }
+
+ /* Overtemp condition detected, notify and start skipping a couple
+ * ticks to let the temperature go down
+ */
+ if (new_failure & FAILURE_OVERTEMP) {
+ wf_set_overtemp();
+ pm121_skipping = 2;
+ }
+
+ /* We only clear the overtemp condition if overtemp is cleared
+ * _and_ no other failure is present. Since a sensor error will
+ * clear the overtemp condition (can't measure temperature) at
+ * the control loop levels, but we don't want to keep it clear
+ * here in this case
+ */
+ if (new_failure == 0 && last_failure & FAILURE_OVERTEMP)
+ wf_clear_overtemp();
+}
+
+
+static struct wf_control* pm121_register_control(struct wf_control *ct,
+ const char *match,
+ unsigned int id)
+{
+ if (controls[id] == NULL && !strcmp(ct->name, match)) {
+ if (wf_get_control(ct) == 0)
+ controls[id] = ct;
+ }
+ return controls[id];
+}
+
+static void pm121_new_control(struct wf_control *ct)
+{
+ int all = 1;
+
+ if (pm121_all_controls_ok)
+ return;
+
+ all = pm121_register_control(ct, "optical-drive-fan", FAN_OD) && all;
+ all = pm121_register_control(ct, "hard-drive-fan", FAN_HD) && all;
+ all = pm121_register_control(ct, "cpu-fan", FAN_CPU) && all;
+ all = pm121_register_control(ct, "cpufreq-clamp", CPUFREQ) && all;
+
+ if (all)
+ pm121_all_controls_ok = 1;
+}
+
+
+
+
+static struct wf_sensor* pm121_register_sensor(struct wf_sensor *sensor,
+ const char *match,
+ struct wf_sensor **var)
+{
+ if (*var == NULL && !strcmp(sensor->name, match)) {
+ if (wf_get_sensor(sensor) == 0)
+ *var = sensor;
+ }
+ return *var;
+}
+
+static void pm121_new_sensor(struct wf_sensor *sr)
+{
+ int all = 1;
+
+ if (pm121_all_sensors_ok)
+ return;
+
+ all = pm121_register_sensor(sr, "cpu-temp",
+ &sensor_cpu_temp) && all;
+ all = pm121_register_sensor(sr, "cpu-current",
+ &sensor_cpu_current) && all;
+ all = pm121_register_sensor(sr, "cpu-voltage",
+ &sensor_cpu_voltage) && all;
+ all = pm121_register_sensor(sr, "cpu-power",
+ &sensor_cpu_power) && all;
+ all = pm121_register_sensor(sr, "hard-drive-temp",
+ &sensor_hard_drive_temp) && all;
+ all = pm121_register_sensor(sr, "optical-drive-temp",
+ &sensor_optical_drive_temp) && all;
+ all = pm121_register_sensor(sr, "incoming-air-temp",
+ &sensor_incoming_air_temp) && all;
+ all = pm121_register_sensor(sr, "north-bridge-temp",
+ &sensor_north_bridge_temp) && all;
+ all = pm121_register_sensor(sr, "gpu-temp",
+ &sensor_gpu_temp) && all;
+
+ if (all)
+ pm121_all_sensors_ok = 1;
+}
+
+
+
+static int pm121_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ switch (event) {
+ case WF_EVENT_NEW_CONTROL:
+ pr_debug("pm121: new control %s detected\n",
+ ((struct wf_control *)data)->name);
+ pm121_new_control(data);
+ break;
+ case WF_EVENT_NEW_SENSOR:
+ pr_debug("pm121: new sensor %s detected\n",
+ ((struct wf_sensor *)data)->name);
+ pm121_new_sensor(data);
+ break;
+ case WF_EVENT_TICK:
+ if (pm121_all_controls_ok && pm121_all_sensors_ok)
+ pm121_tick();
+ break;
+ }
+
+ return 0;
+}
+
+static struct notifier_block pm121_events = {
+ .notifier_call = pm121_notify,
+};
+
+static int pm121_init_pm(void)
+{
+ const struct smu_sdbp_header *hdr;
+
+ hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
+ if (hdr != 0) {
+ struct smu_sdbp_sensortree *st =
+ (struct smu_sdbp_sensortree *)&hdr[1];
+ pm121_mach_model = st->model_id;
+ }
+
+ pm121_connection = &pm121_connections[pm121_mach_model - 2];
+
+ printk(KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
+ pm121_mach_model);
+
+ return 0;
+}
+
+
+static int pm121_probe(struct platform_device *ddev)
+{
+ wf_register_client(&pm121_events);
+
+ return 0;
+}
+
+static int __devexit pm121_remove(struct platform_device *ddev)
+{
+ wf_unregister_client(&pm121_events);
+ return 0;
+}
+
+static struct platform_driver pm121_driver = {
+ .probe = pm121_probe,
+ .remove = __devexit_p(pm121_remove),
+ .driver = {
+ .name = "windfarm",
+ .bus = &platform_bus_type,
+ },
+};
+
+
+static int __init pm121_init(void)
+{
+ int rc = -ENODEV;
+
+ if (machine_is_compatible("PowerMac12,1"))
+ rc = pm121_init_pm();
+
+ if (rc == 0) {
+ request_module("windfarm_smu_controls");
+ request_module("windfarm_smu_sensors");
+ request_module("windfarm_smu_sat");
+ request_module("windfarm_lm75_sensor");
+ request_module("windfarm_max6690_sensor");
+ request_module("windfarm_cpufreq_clamp");
+ platform_driver_register(&pm121_driver);
+ }
+
+ return rc;
+}
+
+static void __exit pm121_exit(void)
+{
+
+ platform_driver_unregister(&pm121_driver);
+}
+
+
+module_init(pm121_init);
+module_exit(pm121_exit);
+
+MODULE_AUTHOR("Étienne Bersac <bersace@gmail.com>");
+MODULE_DESCRIPTION("Thermal control logic for iMac G5 (iSight)");
+MODULE_LICENSE("GPL");
+
Index: linux-work/drivers/macintosh/windfarm_smu_controls.c
===================================================================
--- linux-work.orig/drivers/macintosh/windfarm_smu_controls.c 2007-09-28 11:42:07.000000000 +1000
+++ linux-work/drivers/macintosh/windfarm_smu_controls.c 2008-04-29 15:32:50.000000000 +1000
@@ -218,6 +218,10 @@ static struct smu_fan_control *smu_fan_c
fct->ctrl.name = "cpu-fan";
else if (!strcmp(l, "Hard Drive") || !strcmp(l, "Hard drive"))
fct->ctrl.name = "drive-bay-fan";
+ else if (!strcmp(l, "HDD Fan")) /* seen on iMac G5 iSight */
+ fct->ctrl.name = "hard-drive-fan";
+ else if (!strcmp(l, "ODD Fan")) /* same */
+ fct->ctrl.name = "optical-drive-fan";
/* Unrecognized fan, bail out */
if (fct->ctrl.name == NULL)
^ permalink raw reply
* HAVE_CONFIG
From: David H. Lynch Jr. @ 2008-04-29 5:34 UTC (permalink / raw)
To: linuxppc-embedded
Why does CONFIG_PPC set CONFIG_HAVE_IDE ?
--
Dave Lynch DLA Systems
Software Development: Embedded Linux
717.627.3770 dhlii@dlasys.net http://www.dlasys.net
fax: 1.253.369.9244 Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.
"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein
^ permalink raw reply
* [PATCH] [POWERPC] Add struct iommu_table argument to iommu_map_sg()
From: Mark Nelson @ 2008-04-29 5:17 UTC (permalink / raw)
To: PowerPC dev list; +Cc: fujita.tomonori
Make iommu_map_sg take a struct iommu_table. It did so before commit
740c3ce66700640a6e6136ff679b067e92125794 (iommu sg merging: ppc: make
iommu respect the segment size limits).
This stops the function looking in the archdata.dma_data for the iommu
table because in the future it will be called with a device that has
no table there.
This also has the nice side effect of making iommu_map_sg() match the
other map functions.
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
arch/powerpc/kernel/dma_64.c | 2 +-
arch/powerpc/kernel/iommu.c | 7 +++----
include/asm-powerpc/iommu.h | 6 +++---
3 files changed, 7 insertions(+), 8 deletions(-)
Index: upstream/arch/powerpc/kernel/dma_64.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/dma_64.c
+++ upstream/arch/powerpc/kernel/dma_64.c
@@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struc
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(dev, sglist, nelems,
+ return iommu_map_sg(dev, dev->archdata.dma_data, sglist, nelems,
device_to_mask(dev), direction);
}
Index: upstream/arch/powerpc/kernel/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/iommu.c
+++ upstream/arch/powerpc/kernel/iommu.c
@@ -267,11 +267,10 @@ static void iommu_free(struct iommu_tabl
spin_unlock_irqrestore(&(tbl->it_lock), flags);
}
-int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, unsigned long mask,
- enum dma_data_direction direction)
+int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
+ struct scatterlist *sglist, int nelems,
+ unsigned long mask, enum dma_data_direction direction)
{
- struct iommu_table *tbl = dev->archdata.dma_data;
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
struct scatterlist *s, *outs, *segstart;
Index: upstream/include/asm-powerpc/iommu.h
===================================================================
--- upstream.orig/include/asm-powerpc/iommu.h
+++ upstream/include/asm-powerpc/iommu.h
@@ -79,9 +79,9 @@ extern void iommu_free_table(struct iomm
extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
int nid);
-extern int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, unsigned long mask,
- enum dma_data_direction direction);
+extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
+ struct scatterlist *sglist, int nelems,
+ unsigned long mask, enum dma_data_direction direction);
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction);
^ permalink raw reply
* Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Paul Mackerras @ 2008-04-29 5:08 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, Sean MacLennan, Stephen Rothwell
In-Reply-To: <20080428232855.22c13830@lappy.seanm.ca>
It doesn't help that both of these patches have the same subject line,
nor that it starts with "Re:". :(
Also, I find the statement "A change to the dts to get gpios correct
broke the led code" a bit opaque. It doesn't tell me in what way it
was broken or what this patch does to correct, or even what the change
was in enough detail that I could find the change in the git
repository.
Paul.
^ permalink raw reply
* Re: [PATCH 1/7] Implement arch disable/enable irq hooks.
From: Paul Mackerras @ 2008-04-29 5:04 UTC (permalink / raw)
To: Scott Wood, Guennadi Liakhovetski, linuxppc-dev
In-Reply-To: <18454.42926.213374.977098@cargo.ozlabs.ibm.com>
I wrote:
> +7: rlwinm r12,r12,0,~TLF_SLEEPING
That should be rlwinm r12,r12,0,~_TLF_SLEEPING (with the leading
underscore), of course. Thanks to Stephen Rothwell for pointing that
out.
Paul.
^ permalink raw reply
* Re: [PATCH 1/7] Implement arch disable/enable irq hooks.
From: Paul Mackerras @ 2008-04-29 4:44 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Guennadi Liakhovetski
In-Reply-To: <20080428203322.GD15223@ld0162-tx32.am.freescale.net>
Scott Wood writes:
> On Fri, Apr 25, 2008 at 02:57:24PM +0200, Guennadi Liakhovetski wrote:
> > is there any specific reason, why out of these 7 patches only the first
> > one made it into the mainline? AFAICS, there has been only one comment,
> > suggesting to replace printk with dev_err on two occasions in one of
> > the patches...
>
> A while ago Paul said on IRC he'd prefer to do the TLF_SLEEPING hack more
> like the soft IRQ disabling that 64-bit uses. I haven't yet had a chance
> to look into it, so the patch collects dust, despite the current
> implementation of TLF_SLEEPING working just fine.
I have taken a closer look at the TLF_SLEEPING patch and crystallized
my thoughts about it a bit:
1. Too many ifdefs - it's only a few instructions extra, so if we're
going to have the TLF_SLEEPING stuff we might as well have it
unconditionally.
2. It seems convoluted to me to go through transfer_to_handler_cont
and ret_from_except when we could just get out directly through
fast_exception_return, given that we are not calling a handler. The
only thing to watch out for there is that r7 and r8 haven't been
modified (or have been restored if they have).
3. The style in all the assembly code is not to have spaces after
commas separating instruction operands.
The untested patch below is what I was thinking of. If you'd like to
try it out, I'd be interested to hear how it goes.
Paul.
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 84c8686..162500f 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -146,6 +146,7 @@ transfer_to_handler:
lwz r12,TI_LOCAL_FLAGS(r9)
mtcrf 0x01,r12
bt- 31-TLF_NAPPING,4f
+ bt- 31-TLF_SLEEPING,7f
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
transfer_to_handler_cont:
@@ -163,6 +164,13 @@ transfer_to_handler_cont:
4: rlwinm r12,r12,0,~_TLF_NAPPING
stw r12,TI_LOCAL_FLAGS(r9)
b power_save_6xx_restore
+
+7: rlwinm r12,r12,0,~TLF_SLEEPING
+ stw r12,TI_LOCAL_FLAGS(r9)
+ lwz r9,_MSR(r11) /* if sleeping, clear MSR.EE */
+ rlwinm r9,r9,0,~MSR_EE
+ lwz r12,_LINK(r11) /* and return to address in LR */
+ b fast_exception_return
#endif
/*
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index d030f5c..1cd8c8f 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -147,8 +147,10 @@ static inline struct thread_info *current_thread_info(void)
/* Bits in local_flags */
/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
#define TLF_NAPPING 0 /* idle thread enabled NAP mode */
+#define TLF_SLEEPING 1 /* suspend code enabled SLEEP mode */
#define _TLF_NAPPING (1 << TLF_NAPPING)
+#define _TLF_SLEEPING (1 << TLF_SLEEPING)
#endif /* __KERNEL__ */
^ permalink raw reply related
* RE: [PATCH v2] MSI driver for Freescale 83xx/85xx/86xx cpu
From: Jin Zhengxiong @ 2008-04-29 3:39 UTC (permalink / raw)
To: Gala Kumar; +Cc: linuxppc-dev
In-Reply-To: <65D1ED37-6B8D-436C-A994-E8764922FE6D@freescale.com>
=20
> -----Original Message-----
> From: Gala Kumar=20
> Sent: Tuesday, April 22, 2008 9:38 PM
> To: Jin Zhengxiong
> Cc: linuxppc-dev@ozlabs.org
> Subject: Re: [PATCH v2] MSI driver for Freescale 83xx/85xx/86xx cpu
>=20
> > diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/=20
> > Makefile index 6d386d0..e60a238 100644
> > --- a/arch/powerpc/sysdev/Makefile
> > +++ b/arch/powerpc/sysdev/Makefile
> > @@ -4,6 +4,7 @@ endif
> >
> > mpic-msi-obj-$(CONFIG_PCI_MSI) +=3D mpic_msi.o mpic_u3msi.o =20
> > mpic_pasemi_msi.o
> > obj-$(CONFIG_MPIC) +=3D mpic.o $(mpic-msi-obj-y)
> > +obj-$(CONFIG_FSL_PCI) +=3D fsl_msi.o
>=20
> can we do something like:
> fsl_pci-$(CONFIG_MSI) +=3D fsl_msi.o
> obj-$(CONFIG_FSL_PCI) +=3D fsl_pci.o $(fsl_pci-y)
>=20
> > obj-$(CONFIG_PPC_MPC106) +=3D grackle.o
> > obj-$(CONFIG_PPC_DCR_NATIVE) +=3D dcr-low.o
OK, Thanks
>=20
> > +static int fsl_msi_init_allocator(struct fsl_msi *msi_data) {
> > + int rc, size;
> > +
> > + size =3D BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(long);
>=20
> should this be long or u32?
>=20
> > +
> > + msi_data->fsl_msi_bitmap =3D kzalloc(size, GFP_KERNEL);
> > +
> > + if (msi_data->fsl_msi_bitmap =3D=3D NULL) {
> > + pr_debug("%s: ENOMEM allocating allocator bitmap!\n",
> > + __func__);
> > + return -ENOMEM;
> > + }
> > +
> > + rc =3D fsl_msi_free_dt_hwirqs(msi_data);
> > + if (rc)
> > + goto out_free;
> > +
> > + return 0;
> > +out_free:
> > + kfree(msi_data->fsl_msi_bitmap);
> > +
> > + msi_data->fsl_msi_bitmap =3D NULL;
> > + return rc;
> > +
> > +}
> > +
> > +static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int
> > type)
> > +{
> > + if (type =3D=3D PCI_CAP_ID_MSIX)
> > + pr_debug("fslmsi: MSI-X untested, trying anyway.\n");
> > +
> > + return 0;
> > +}
> > +
> > +static void fsl_teardown_msi_irqs(struct pci_dev *pdev) {
> > + struct msi_desc *entry;
> > + struct fsl_msi *msi_data =3D fsl_msi;
> > +
> > + list_for_each_entry(entry, &pdev->msi_list, list) {
> > + if (entry->irq =3D=3D NO_IRQ)
> > + continue;
> > + set_irq_msi(entry->irq, NULL);
> > + fsl_msi_free_hwirqs(msi_data,=20
> virq_to_hw(entry->irq), 1);
> > + irq_dispose_mapping(entry->irq);
> > + }
> > +
> > + return;
> > +}
> > +
> > +static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
> > + struct msi_msg *msg)
> > +{
> > + struct fsl_msi *msi_data =3D fsl_msi;
> > +
> > + msg->address_lo =3D msi_data->msi_addr_lo;
> > + msg->address_hi =3D msi_data->msi_addr_hi;
> > + msg->data =3D hwirq;
> > +
> > + pr_debug("%s: allocated srs: %d, ibs: %d\n",
> > + __func__, hwirq / INT_PER_MSIR, hwirq % INT_PER_MSIR); }
> > +
> > +static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int
> > type)
> > +{
> > + irq_hw_number_t hwirq;
> > + int rc;
> > + unsigned int virq;
> > + struct msi_desc *entry;
> > + struct msi_msg msg;
> > + struct fsl_msi *msi_data =3D fsl_msi;
> > +
> > + list_for_each_entry(entry, &pdev->msi_list, list) {
> > + hwirq =3D fsl_msi_alloc_hwirqs(msi_data, 1);
> > + if (hwirq < 0) {
> > + rc =3D hwirq;
> > + pr_debug("%s: fail allocating msi interrupt\n",
> > + __func__);
> > + goto out_free;
> > + }
> > +
> > + virq =3D irq_create_mapping(msi_data->irqhost, hwirq);
> > +
> > + if (virq =3D=3D NO_IRQ) {
> > + pr_debug("%s: fail mapping hwirq 0x%lx\n",
> > + __func__, hwirq);
> > + fsl_msi_free_hwirqs(msi_data, hwirq, 1);
> > + rc =3D -ENOSPC;
> > + goto out_free;
> > + }
> > + set_irq_msi(virq, entry);
> > +
> > + fsl_compose_msi_msg(pdev, hwirq, &msg);
> > + write_msi_msg(virq, &msg);
> > + }
> > + return 0;
> > +
> > +out_free:
> > + return rc;
> > +}
> > +
> > +void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) {
> > + unsigned int cascade_irq;
> > + struct fsl_msi *msi_data =3D fsl_msi;
> > + int msir_index =3D -1;
> > + u32 msir_value =3D 0;
> > + u32 intr_index;
> > + u32 have_shift =3D 0;
> > +
> > + spin_lock(&desc->lock);
> > + if ((msi_data->feature & FSL_PIC_IP_MASK) =3D=3D FSL_PIC_IP_IPIC) =
{
> > + if (desc->chip->mask_ack)
> > + desc->chip->mask_ack(irq);
> > + else {
> > + desc->chip->mask(irq);
> > + desc->chip->ack(irq);
> > + }
> > + }
> > +
> > + if (unlikely(desc->status & IRQ_INPROGRESS))
> > + goto unlock;
> > +
> > + msir_index =3D (int)(desc->handler_data);
> > +
> > + if (msir_index >=3D NR_MSIR)
> > + cascade_irq =3D NO_IRQ;
> > +
> > + desc->status |=3D IRQ_INPROGRESS;
> > + switch (fsl_msi->feature & FSL_PIC_IP_MASK) {
> > + case FSL_PIC_IP_MPIC:
> > + msir_value =3D fsl_msi_read(msi_data->msi_regs,
> > + msir_index * 0x10);
> > + break;
> > + case FSL_PIC_IP_IPIC:
> > + msir_value =3D fsl_msi_read(msi_data->msi_regs,=20
> msir_index * 0x4);
> > + break;
> > + }
> > +
> > + while (msir_value) {
> > + intr_index =3D ffs(msir_value) - 1;
> > +
> > + cascade_irq =3D irq_linear_revmap(msi_data->irqhost,
> > + (msir_index * INT_PER_MSIR + intr_index=20
> + have_shift));
> > +
> > + if (cascade_irq !=3D NO_IRQ)
> > + generic_handle_irq(cascade_irq);
> > + have_shift +=3D (intr_index + 1);
> > + msir_value =3D (msir_value >> (intr_index + 1));
> > + }
> > + desc->status &=3D ~IRQ_INPROGRESS;
> > +
> > + switch (msi_data->feature & FSL_PIC_IP_MASK) {
> > + case FSL_PIC_IP_MPIC:
> > + desc->chip->eoi(irq);
> > + break;
> > + case FSL_PIC_IP_IPIC:
> > + if (!(desc->status & IRQ_DISABLED) &&=20
> desc->chip->unmask)
> > + desc->chip->unmask(irq);
> > + break;
> > + }
> > +unlock:
> > + spin_unlock(&desc->lock);
> > +}
> > +
> > +static int __devinit fsl_of_msi_probe(struct of_device *dev,
> > + const struct of_device_id *match) {
> > + struct fsl_msi *msi;
> > + struct resource res;
> > + int err, i, count;
> > + int rc;
> > + int virt_msir;
> > + const u32 *p;
> > + struct fsl_msi_feature *tmp_data;
> > +
> > + printk(KERN_DEBUG "Setting up fsl msi support\n");
> > +
> > + msi =3D kzalloc(sizeof(struct fsl_msi), GFP_KERNEL);
> > + if (!msi) {
> > + dev_err(&dev->dev, "No memory for MSI structure\n");
> > + err =3D -ENOMEM;
> > + goto error_out;
> > + }
> > +
> > + msi->of_node =3D dev->node;
> > +
> > + msi->irqhost =3D irq_alloc_host(of_node_get(dev->node),
> > + IRQ_HOST_MAP_LINEAR,
> > + NR_MSI_IRQS, &fsl_msi_host_ops, 0);
> > + if (msi->irqhost =3D=3D NULL) {
> > + dev_err(&dev->dev, "No memory for MSI irqhost\n");
> > + of_node_put(dev->node);
> > + err =3D -ENOMEM;
> > + goto error_out;
> > + }
> > +
> > + /* Get the MSI reg base */
> > + err =3D of_address_to_resource(dev->node, 0, &res);
> > + if (err) {
> > + dev_err(&dev->dev, "%s resource error!\n",
> > + dev->node->full_name);
> > + goto error_out;
> > + }
> > +
> > + msi->msi_regs =3D ioremap(res.start, res.end - res.start + 1);
> > + if (!msi->msi_regs) {
> > + dev_err(&dev->dev, "ioremap problem failed\n");
> > + goto error_out;
> > + }
> > +
> > + tmp_data =3D (struct fsl_msi_feature *)match->data;
> > +
> > + msi->feature =3D tmp_data->fsl_pic_ip;
> > +
> > + msi->irqhost->host_data =3D msi;
> > +
> > + msi->msi_addr_hi =3D 0x0;
> > + msi->msi_addr_lo =3D res.start + tmp_data->msiir_offset;
> > +
> > + rc =3D fsl_msi_init_allocator(msi);
> > + if (rc) {
> > + dev_err(&dev->dev, "Error allocating MSI bitmap\n");
> > + goto error_out;
> > + }
> > +
> > + p =3D of_get_property(dev->node, "interrupts", &count);
> > + if (!p) {
> > + dev_err(&dev->dev, "no interrupts property=20
> found on %s\n",
> > + dev->node->full_name);
> > + err =3D -ENODEV;
> > + goto error_out;
> > + }
> > + if (count % 8 !=3D 0) {
> > + dev_err(&dev->dev, "Malformed interrupts=20
> property on %s\n",
> > + dev->node->full_name);
> > + err =3D -EINVAL;
> > + goto error_out;
> > + }
> > +
> > + count /=3D sizeof(u32);
> > + for (i =3D 0; i < count / 2; i++) {
> > + if (i > NR_MSIR)
> > + break;
> > + virt_msir =3D irq_of_parse_and_map(dev->node, i);
> > + if (virt_msir !=3D NO_IRQ) {
> > + set_irq_data(virt_msir, (void *)i);
> > + set_irq_chained_handler(virt_msir,=20
> fsl_msi_cascade);
> > + }
> > + }
> > +
> > + fsl_msi =3D msi;
> > +
> > + WARN_ON(ppc_md.setup_msi_irqs);
> > + ppc_md.setup_msi_irqs =3D fsl_setup_msi_irqs;
> > + ppc_md.teardown_msi_irqs =3D fsl_teardown_msi_irqs;
> > + ppc_md.msi_check_device =3D fsl_msi_check_device;
> > + return 0;
> > +error_out:
> > + kfree(msi);
> > + return err;
> > +}
> > +
> > +static const struct fsl_msi_feature mpic_msi_feature =3D
> > {FSL_PIC_IP_MPIC, 0x140};
> > +static const struct fsl_msi_feature ipic_msi_feature =3D
> > {FSL_PIC_IP_IPIC, 0x38};
>=20
> make this
> {
> .fsl_pic_ip =3D FSL_PIC_IP_MPIC
> .offset =3D 0x140
> };
>=20
> for readability.
>=20
OK!
> > +
> > +static const struct of_device_id fsl_of_msi_ids[] =3D {
> > + {
> > + .compatible =3D "fsl,MPIC-MSI",
> > + .data =3D (void *)&mpic_msi_feature,
> > + },
> > + {
> > + .compatible =3D "fsl,IPIC-MSI",
> > + .data =3D (void *)&ipic_msi_feature,
> > + },
> > + {}
> > +};
> > +
> > +static struct of_platform_driver fsl_of_msi_driver =3D {
> > + .name =3D "fsl-of-msi",
> > + .match_table =3D fsl_of_msi_ids,
> > + .probe =3D fsl_of_msi_probe,
> > +};
> > +
> > +static __init int fsl_of_msi_init(void) {
> > + return of_register_platform_driver(&fsl_of_msi_driver);
> > +}
> > +
> > +subsys_initcall(fsl_of_msi_init);
> > diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/=20
> > fsl_msi.h new file mode 100644 index 0000000..628b6c0
> > --- /dev/null
> > +++ b/arch/powerpc/sysdev/fsl_msi.h
> > @@ -0,0 +1,36 @@
> > +#ifndef _POWERPC_SYSDEV_FSL_MSI_H
> > +#define _POWERPC_SYSDEV_FSL_MSI_H
> > +
> > +#define NR_MSIR 8
>=20
> NR_MSR_REG
>=20
> > +#define INT_PER_MSIR 32
>=20
> IRQS_PER_MSI_REG
>=20
> >
> > +#define NR_MSI_IRQS (NR_MSIR * INT_PER_MSIR)
> > +
> > +#define FSL_PIC_IP_MASK 0x0000000F
> > +#define FSL_PIC_IP_MPIC 0x00000001
> > +#define FSL_PIC_IP_IPIC 0x00000002
> > +
> > +struct fsl_msi {
> > + /* Device node of the MSI interrupt*/
> > + struct device_node *of_node;
> > +
> > + struct irq_host *irqhost;
> > +
> > + unsigned long cascade_irq;
> > +
> > + u32 msi_addr_lo;
> > + u32 msi_addr_hi;
> > + void __iomem *msi_regs;
> > + u32 feature;
> > +
> > + unsigned long *fsl_msi_bitmap;
> > + spinlock_t bitmap_lock;
> > + const char *name;
> > +};
> > +
> > +struct fsl_msi_feature {
> > + u32 fsl_pic_ip;
> > + u32 msiir_offset;
> > +};
>=20
> move this struct into .c
OK
> >
> > +
> > +#endif /* _POWERPC_SYSDEV_FSL_MSI_H */
> > +
> > diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/=20
> > fsl_pci.c index bf13c21..fede767 100644
> > --- a/arch/powerpc/sysdev/fsl_pci.c
> > +++ b/arch/powerpc/sysdev/fsl_pci.c
> > @@ -106,6 +106,16 @@ void __init setup_pci_cmd(struct pci_controller
> > *hose)
> > }
> > }
> >
> > +#ifdef CONFIG_PCI_MSI
> > +void __init setup_pci_pcsrbar(struct pci_controller *hose) {
> > + phys_addr_t immr_base;
> > +
> > + immr_base =3D get_immrbase();
> > + early_write_config_dword(hose, 0, 0,=20
> PCI_BASE_ADDRESS_0, immr_base);=20
> > +} #endif
> > +
> > static int fsl_pcie_bus_fixup;
> >
> > static void __init quirk_fsl_pcie_header(struct pci_dev *dev) @@=20
> > -211,6 +221,10 @@ int __init fsl_add_bridge(struct=20
> device_node *dev,=20
> > int is_primary)
> > /* Setup PEX window registers */
> > setup_pci_atmu(hose, &rsrc);
> >
> > + /*Setup PEXCSRBAR */
> > +#ifdef CONFIG_PCI_MSI
> > + setup_pci_pcsrbar(hose);
> > +#endif
>=20
> I'm not convinced this is safe. we need to be careful to=20
> make sure the pcsrbar doesn't overlap with any other device.
>=20
The PCI MEM inbound/outband map seems 'one-one map' in our system and=20
the dts may guard the outband space not overlap(No one wish to set the
space
the same as immrbase :) ). =20
But the 2G inbound MEM was set in our system directly, So far the
pcsrbar is=20
not overlap with other device.
Thanks
Jason
=20
^ permalink raw reply
* Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Sean MacLennan @ 2008-04-29 3:28 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, Stephen Rothwell
In-Reply-To: <20080428214711.240419c3@lappy.seanm.ca>
A change to the dts to get gpios correct broke the led code.
PIKA Warp: Update platform code to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Full DTM support including critical temperature.
* Added POST information.
* Removed LED function, moved to new LED driver.
* Moved ad7414 to new style I2C initialization.
Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index eb108a8..2178021 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -10,6 +10,7 @@
#include "ops.h"
#include "4xx.h"
#include "cuboot.h"
+#include "stdio.h"
#define TARGET_4xx
#define TARGET_44x
@@ -17,14 +18,54 @@
static bd_t bd;
-static void warp_fixups(void)
+static void warp_fixup_one_nor(u32 from, u32 to)
{
- unsigned long sysclk = 66000000;
+ void *devp;
+ char name[50];
+ u32 v[2];
+
+ sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
+
+ devp = finddevice(name);
+ if (!devp)
+ return;
+
+ if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+ v[0] = to;
+ setprop(devp, "reg", v, sizeof(v));
+
+ printf("NOR 64M fixup %x -> %x\r\n", from, to);
+ }
+}
+
- ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+static void warp_fixups(void)
+{
+ ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
ibm4xx_sdram_fixup_memsize();
ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+
+ /* Fixup for 64M flash on Rev A boards. */
+ if (bd.bi_flashsize == 0x4000000) {
+ void *devp;
+ u32 v[3];
+
+ devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
+ if (!devp)
+ return;
+
+ /* Fixup the size */
+ if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+ v[2] = bd.bi_flashsize;
+ setprop(devp, "reg", v, sizeof(v));
+ }
+
+ /* Fixup parition offsets */
+ warp_fixup_one_nor(0x300000, 0x3f00000);
+ warp_fixup_one_nor(0x340000, 0x3f40000);
+ warp_fixup_one_nor(0x380000, 0x3f80000);
+ }
}
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318..d293c70 100644
--- a/arch/powerpc/platforms/44x/warp-nand.c
+++ b/arch/powerpc/platforms/44x/warp-nand.c
@@ -11,8 +11,10 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/ndfc.h>
+#include <linux/of.h>
#include <asm/machdep.h>
+
#ifdef CONFIG_MTD_NAND_NDFC
#define CS_NAND_0 1 /* use chip select 1 for NAND device 0 */
@@ -35,13 +37,23 @@ static struct mtd_partition nand_parts[] = {
{
.name = "root",
.offset = 0x0200000,
- .size = 0x3400000
+ .size = 0x3E00000
+ },
+ {
+ .name = "persistent",
+ .offset = 0x4000000,
+ .size = 0x4000000
},
{
- .name = "user",
- .offset = 0x3600000,
- .size = 0x0A00000
+ .name = "persistent1",
+ .offset = 0x8000000,
+ .size = 0x4000000
},
+ {
+ .name = "persistent2",
+ .offset = 0xC000000,
+ .size = 0x4000000
+ }
};
struct ndfc_controller_settings warp_ndfc_settings = {
@@ -67,19 +79,15 @@ static struct platform_device warp_ndfc_device = {
.resource = &warp_ndfc,
};
-static struct nand_ecclayout nand_oob_16 = {
- .eccbytes = 3,
- .eccpos = { 0, 1, 2, 3, 6, 7 },
- .oobfree = { {.offset = 8, .length = 16} }
-};
-
+/* Do NOT set the ecclayout: let it default so it is correct for both
+ * 64M and 256M flash chips.
+ */
static struct platform_nand_chip warp_nand_chip0 = {
.nr_chips = 1,
.chip_offset = CS_NAND_0,
.nr_partitions = ARRAY_SIZE(nand_parts),
.partitions = nand_parts,
- .chip_delay = 50,
- .ecclayout = &nand_oob_16,
+ .chip_delay = 20,
.priv = &warp_chip0_settings,
};
@@ -96,6 +104,23 @@ static struct platform_device warp_nand_device = {
static int warp_setup_nand_flash(void)
{
+ struct device_node *np;
+
+ /* Try to detect a rev A based on NOR size. */
+ np = of_find_compatible_node(NULL, NULL, "cfi-flash");
+ if (np) {
+ struct property *pp;
+
+ pp = of_find_property(np, "reg", NULL);
+ if (pp && (pp->length == 12)) {
+ u32 *v = pp->value;
+ if (v[2] == 0x4000000)
+ /* Rev A = 64M NAND */
+ warp_nand_chip0.nr_partitions = 2;
+ }
+ of_node_put(np);
+ }
+
platform_device_register(&warp_ndfc_device);
platform_device_register(&warp_nand_device);
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
index 39cf615..318f859 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -12,6 +12,10 @@
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pika.h>
+#include <linux/delay.h>
#include <asm/machdep.h>
#include <asm/prom.h>
@@ -27,6 +31,18 @@ static __initdata struct of_device_id warp_of_bus[] = {
{},
};
+static __initdata struct i2c_board_info warp_i2c_info[] = {
+ { I2C_BOARD_INFO("ad7414", 0x4a) }
+};
+
+static int __init warp_arch_init(void)
+{
+ /* This should go away once support is moved to the dts. */
+ i2c_register_board_info(0, warp_i2c_info, ARRAY_SIZE(warp_i2c_info));
+ return 0;
+}
+machine_arch_initcall(warp, warp_arch_init);
+
static int __init warp_device_probe(void)
{
of_platform_bus_probe(NULL, warp_of_bus, NULL);
@@ -52,61 +68,232 @@ define_machine(warp) {
};
-#define LED_GREEN (0x80000000 >> 0)
-#define LED_RED (0x80000000 >> 1)
+/* I am not sure this is the best place for this... */
+static int __init warp_post_info(void)
+{
+ struct device_node *np;
+ void __iomem *fpga;
+ u32 post1, post2;
+
+ /* Sighhhh... POST information is in the sd area. */
+ np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
+ if (np == NULL)
+ return -ENOENT;
+
+ fpga = of_iomap(np, 0);
+ of_node_put(np);
+ if (fpga == NULL)
+ return -ENOENT;
+
+ post1 = in_be32(fpga + 0x40);
+ post2 = in_be32(fpga + 0x44);
+
+ iounmap(fpga);
+
+ if (post1 || post2)
+ printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
+ else
+ printk(KERN_INFO "Warp POST OK\n");
+
+ return 0;
+}
+machine_late_initcall(warp, warp_post_info);
+
+
+#ifdef CONFIG_SENSORS_AD7414
+
+static LIST_HEAD(dtm_shutdown_list);
+static void __iomem *dtm_fpga;
+static void __iomem *gpio_base;
+
+
+struct dtm_shutdown {
+ struct list_head list;
+ void (*func)(void *arg);
+ void *arg;
+};
-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */
-void warp_set_power_leds(int green, int red)
+int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
{
- static void __iomem *gpio_base = NULL;
- unsigned leds;
-
- if (gpio_base == NULL) {
- struct device_node *np;
-
- /* Power LEDS are on the second GPIO controller */
- np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP");
- if (np)
- np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP");
- if (np == NULL) {
- printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
- return;
+ struct dtm_shutdown *shutdown;
+
+ shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
+ if (shutdown == NULL)
+ return -ENOMEM;
+
+ shutdown->func = func;
+ shutdown->arg = arg;
+
+ list_add(&shutdown->list, &dtm_shutdown_list);
+
+ return 0;
+}
+
+int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+ struct dtm_shutdown *shutdown;
+
+ list_for_each_entry(shutdown, &dtm_shutdown_list, list)
+ if (shutdown->func == func && shutdown->arg == arg) {
+ list_del(&shutdown->list);
+ kfree(shutdown);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t temp_isr(int irq, void *context)
+{
+ struct dtm_shutdown *shutdown;
+
+ local_irq_disable();
+
+ /* Run through the shutdown list. */
+ list_for_each_entry(shutdown, &dtm_shutdown_list, list)
+ shutdown->func(shutdown->arg);
+
+ printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n");
+
+ while (1) {
+ if (dtm_fpga) {
+ unsigned reset = in_be32(dtm_fpga + 0x14);
+ out_be32(dtm_fpga + 0x14, reset);
}
- gpio_base = of_iomap(np, 0);
- of_node_put(np);
- if (gpio_base == NULL) {
- printk(KERN_ERR __FILE__ ": Unable to map gpio");
- return;
+ if (gpio_base) {
+ unsigned leds = in_be32(gpio_base);
+
+ /* green off, red toggle */
+ leds &= ~0x80000000;
+ leds ^= 0x40000000;
+
+ out_be32(gpio_base, leds);
}
+
+ mdelay(500);
+ }
+}
+
+static int pika_setup_leds(void)
+{
+ struct device_node *np;
+ const u32 *gpios;
+ int len;
+
+ np = of_find_compatible_node(NULL, NULL, "linux,gpio-led");
+ if (!np) {
+ printk(KERN_ERR __FILE__ ": Unable to find gpio-led\n");
+ return -ENOENT;
}
- leds = in_be32(gpio_base);
+ gpios = of_get_property(np, "gpios", &len);
+ of_node_put(np);
+ if (!gpios || len < 4) {
+ printk(KERN_ERR __FILE__
+ ": Unable to get gpios property (%d)\n", len);
+ return -ENOENT;
+ }
- switch (green) {
- case 0: leds &= ~LED_GREEN; break;
- case 1: leds |= LED_GREEN; break;
+ np = of_find_node_by_phandle(gpios[0]);
+ if (!np) {
+ printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
+ return -ENOENT;
}
- switch (red) {
- case 0: leds &= ~LED_RED; break;
- case 1: leds |= LED_RED; break;
+
+ gpio_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!gpio_base) {
+ printk(KERN_ERR __FILE__ ": Unable to map gpio");
+ return -ENOMEM;
}
- out_be32(gpio_base, leds);
+ return 0;
}
-EXPORT_SYMBOL(warp_set_power_leds);
+static void pika_setup_critical_temp(struct i2c_client *client)
+{
+ struct device_node *np;
+ int irq, rc;
+
+ /* Do this before enabling critical temp interrupt since we
+ * may immediately interrupt.
+ */
+ pika_setup_leds();
+
+ /* These registers are in 1 degree increments. */
+ i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
+ i2c_smbus_write_byte_data(client, 3, 55); /* Tlow */
+
+ np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
+ if (np == NULL) {
+ printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
+ return;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ of_node_put(np);
+ if (irq == NO_IRQ) {
+ printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
+ return;
+ }
+
+ rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
+ if (rc) {
+ printk(KERN_ERR __FILE__
+ ": Unable to request ad7414 irq %d = %d\n", irq, rc);
+ return;
+ }
+}
+
+static inline void pika_dtm_check_fan(void __iomem *fpga)
+{
+ static int fan_state;
+ u32 fan = in_be32(fpga + 0x34) & (1 << 14);
+
+ if (fan_state != fan) {
+ fan_state = fan;
+ if (fan)
+ printk(KERN_WARNING "Fan rotation error detected."
+ " Please check hardware.\n");
+ }
+}
-#ifdef CONFIG_SENSORS_AD7414
static int pika_dtm_thread(void __iomem *fpga)
{
- extern int ad7414_get_temp(int index);
+ struct i2c_adapter *adap;
+ struct i2c_client *client;
+
+ /* We loop in case either driver was compiled as a module and
+ * has not been insmoded yet.
+ */
+ while (!(adap = i2c_get_adapter(0))) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+
+ while (1) {
+ list_for_each_entry(client, &adap->clients, list)
+ if (client->addr == 0x4a)
+ goto found_it;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+
+found_it:
+ i2c_put_adapter(adap);
+
+ pika_setup_critical_temp(client);
+
+ printk(KERN_INFO "PIKA DTM thread running.\n");
while (!kthread_should_stop()) {
- int temp = ad7414_get_temp(0);
+ u16 temp = swab16(i2c_smbus_read_word_data(client, 0));
+ out_be32(fpga + 0x20, temp);
- out_be32(fpga, temp);
+ pika_dtm_check_fan(fpga);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
@@ -115,37 +302,44 @@ static int pika_dtm_thread(void __iomem *fpga)
return 0;
}
+
static int __init pika_dtm_start(void)
{
struct task_struct *dtm_thread;
struct device_node *np;
- struct resource res;
- void __iomem *fpga;
np = of_find_compatible_node(NULL, NULL, "pika,fpga");
if (np == NULL)
return -ENOENT;
- /* We do not call of_iomap here since it would map in the entire
- * fpga space, which is over 8k.
- */
- if (of_address_to_resource(np, 0, &res)) {
- of_node_put(np);
- return -ENOENT;
- }
+ dtm_fpga = of_iomap(np, 0);
of_node_put(np);
-
- fpga = ioremap(res.start, 0x24);
- if (fpga == NULL)
+ if (dtm_fpga == NULL)
return -ENOENT;
- dtm_thread = kthread_run(pika_dtm_thread, fpga + 0x20, "pika-dtm");
+ dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
if (IS_ERR(dtm_thread)) {
- iounmap(fpga);
+ iounmap(dtm_fpga);
return PTR_ERR(dtm_thread);
}
return 0;
}
-device_initcall(pika_dtm_start);
+machine_late_initcall(warp, pika_dtm_start);
+
+#else /* !CONFIG_SENSORS_AD7414 */
+
+int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
+{
+ return 0;
+}
+
+int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+ return 0;
+}
+
#endif
+
+EXPORT_SYMBOL(pika_dtm_register_shutdown);
+EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
^ permalink raw reply related
* Re: [RESEND][PATCH 2/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Sean MacLennan @ 2008-04-29 3:27 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, Sean MacLennan, Stephen Rothwell
In-Reply-To: <fa686aa40804281858r6b2a1f9eva16983d0a3680fc0@mail.gmail.com>
PIKA Warp: Update DTS to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Added led entries.
* Added fpga-sd entry.
* Added ad7414 entry.
Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index b04a52e..c086501 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -132,40 +132,33 @@
fpga@2,0 {
compatible = "pika,fpga";
- reg = <2 0 2200>;
+ reg = <2 0 1000>;
interrupts = <18 8>;
interrupt-parent = <&UIC0>;
};
+ fpga@2,4000 {
+ compatible = "pika,fpga-sd";
+ reg = <2 4000 A00>;
+ };
+
nor_flash@0,0 {
- compatible = "amd,s29gl512n", "cfi-flash";
+ compatible = "amd,s29gl032a", "cfi-flash";
bank-width = <2>;
- reg = <0 0 4000000>;
+ reg = <0 0 400000>;
#address-cells = <1>;
#size-cells = <1>;
- partition@0 {
- label = "kernel";
- reg = <0 180000>;
- };
- partition@180000 {
- label = "root";
- reg = <180000 3480000>;
- };
- partition@3600000 {
- label = "user";
- reg = <3600000 900000>;
- };
- partition@3f00000 {
+ partition@300000 {
label = "fpga";
- reg = <3f00000 40000>;
+ reg = <300000 40000>;
};
- partition@3f40000 {
+ partition@340000 {
label = "env";
- reg = <3f40000 40000>;
+ reg = <340000 40000>;
};
- partition@3f80000 {
+ partition@380000 {
label = "u-boot";
- reg = <3f80000 80000>;
+ reg = <380000 80000>;
};
};
};
@@ -186,18 +179,45 @@
reg = <ef600700 14>;
interrupt-parent = <&UIC0>;
interrupts = <2 4>;
+ index = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ad7414@4a {
+ compatible = "adi,ad7414";
+ reg = <4a>;
+ interrupts = <19 8>;
+ interrupt-parent = <&UIC0>;
+ };
};
GPIO0: gpio@ef600b00 {
compatible = "ibm,gpio-440ep";
reg = <ef600b00 48>;
+ #gpio-cells = <2>;
+ gpio-controller;
};
GPIO1: gpio@ef600c00 {
compatible = "ibm,gpio-440ep";
reg = <ef600c00 48>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ led@31 {
+ compatible = "linux,gpio-led";
+ linux,name = ":green:";
+ gpios = <&GPIO1 31 0>;
+ };
+
+ led@30 {
+ compatible = "linux,gpio-led";
+ linux,name = ":red:";
+ gpios = <&GPIO1 30 0>;
+ };
};
+
ZMII0: emac-zmii@ef600d00 {
compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
reg = <ef600d00 c>;
^ permalink raw reply related
* Re: [PATCH] Add fast little-endian switch system call
From: Paul Mackerras @ 2008-04-29 2:46 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-arch, linuxppc-dev, mtk.manpages
In-Reply-To: <20080428144332.GA17109@lst.de>
Christoph Hellwig writes:
> Am I missing something here or does this add a branch for every normal
> syscall?
It does, but the impact is so small as to be unmeasurable with
lmbench, even on the null syscall measurement. The overhead of the
easily-predicted not-taken branch is completely swamped by the amount
of time that the sc and rfid instructions take. I had it under a
config option at one point but then decided not to bother with that
when I couldn't measure any difference.
Paul.
^ permalink raw reply
* Re: UCD-SNMP 4.2.1 and SNMP v3
From: 이명식 @ 2008-04-29 1:51 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1.1: Type: text/plain, Size: 664 bytes --]
Hi,
llandre.
I am a engineer with KMW Korea.
I had tried with LoriotPro debugging tools and ucd-snmp version 4.2.7.
And I compiled win32 version of ucd-snmp version 4.2.7.
If you see the command prompt of the below picture, there is a "Verification failed" message with sc_check_keyed_hash routine.
And the key data is null.
I can't find why this has happened.
The real problem is that I supplied the snmp version 3 in ARM7 proceessor (STR710FZ2 with 256kbyte eeprom, 64kbytes ram, and 512kbytes external ram).
And there is no real-time OS in my processor as you guess.
Please give me some advice.
Thanks,
MyongSik, Lee.
<<ole0.bmp>>
[-- Attachment #1.2: Type: text/html, Size: 2343 bytes --]
[-- Attachment #2: ole0.bmp --]
[-- Type: image/bmp, Size: 684910 bytes --]
^ permalink raw reply
* Re: [RESEND][PATCH 2/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Grant Likely @ 2008-04-29 1:58 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, Stephen Rothwell
In-Reply-To: <20080428215029.0e38a0d2@lappy.seanm.ca>
On Mon, Apr 28, 2008 at 7:50 PM, Sean MacLennan <smaclennan@pikatech.com> wrote:
> diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
> index b04a52e..3e95e99 100644
You still need to have *some* kind of change log and a signed-off-by
line in this patch. :-)
There is one minor change that needs to be added below; otherwise:
Acked-by: Grant Likely <grant.likely@secretlab.ca>
(You can add my acked-by line to the next version of this patch if
you're only changing the thing I comment on).
Josh, when he respins it I think the dts changes are ready to be picked up.
> @@ -186,18 +179,45 @@
> GPIO1: gpio@ef600c00 {
> compatible = "ibm,gpio-440ep";
> reg = <ef600c00 48>;
> + #gpio-cells = <2>;
> + gpio-controller;
> +
> + led@31 {
>
> + compatible = "linux,gpio-led";
> + linux,name = ":green:";
> + gpios = <&GPIO1 31>;
Since #gpio-cells is '2'; the gpios property needs to reflect that.
It should be:
gpios = <&GPIO1 31 0>;
The second cell the GPIO controller would use for flags (inverted,
open-drain, etc).
> + };
> +
> + led@30 {
> + compatible = "linux,gpio-led";
> + linux,name = ":red:";
> + gpios = <&GPIO1 30>;
ditto
> + };
>
>
> };
>
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH] sysdev,mv64x60: MV64x60 device bus
From: Stephen Rothwell @ 2008-04-29 1:54 UTC (permalink / raw)
To: Remi Machet; +Cc: Paul Mackerras, linuxppc-dev
In-Reply-To: <1209402729.14407.2.camel@pcds-ts102.slac.stanford.edu>
[-- Attachment #1: Type: text/plain, Size: 286 bytes --]
Hi Remi,
On Mon, 28 Apr 2008 10:12:09 -0700 Remi Machet <rmachet@slac.stanford.edu> wrote:
>
> +static struct of_device_id of_mv64x60_devices[] = {
__initdata, please.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [RESEND][PATCH 2/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Sean MacLennan @ 2008-04-29 1:50 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, Stephen Rothwell
In-Reply-To: <20080428214711.240419c3@lappy.seanm.ca>
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index b04a52e..3e95e99 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -132,40 +132,33 @@
fpga@2,0 {
compatible = "pika,fpga";
- reg = <2 0 2200>;
+ reg = <2 0 1000>;
interrupts = <18 8>;
interrupt-parent = <&UIC0>;
};
+ fpga@2,4000 {
+ compatible = "pika,fpga-sd";
+ reg = <2 4000 A00>;
+ };
+
nor_flash@0,0 {
- compatible = "amd,s29gl512n", "cfi-flash";
+ compatible = "amd,s29gl032a", "cfi-flash";
bank-width = <2>;
- reg = <0 0 4000000>;
+ reg = <0 0 400000>;
#address-cells = <1>;
#size-cells = <1>;
- partition@0 {
- label = "kernel";
- reg = <0 180000>;
- };
- partition@180000 {
- label = "root";
- reg = <180000 3480000>;
- };
- partition@3600000 {
- label = "user";
- reg = <3600000 900000>;
- };
- partition@3f00000 {
+ partition@300000 {
label = "fpga";
- reg = <3f00000 40000>;
+ reg = <300000 40000>;
};
- partition@3f40000 {
+ partition@340000 {
label = "env";
- reg = <3f40000 40000>;
+ reg = <340000 40000>;
};
- partition@3f80000 {
+ partition@380000 {
label = "u-boot";
- reg = <3f80000 80000>;
+ reg = <380000 80000>;
};
};
};
@@ -186,18 +179,45 @@
reg = <ef600700 14>;
interrupt-parent = <&UIC0>;
interrupts = <2 4>;
+ index = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ad7414@4a {
+ compatible = "adi,ad7414";
+ reg = <4a>;
+ interrupts = <19 8>;
+ interrupt-parent = <&UIC0>;
+ };
};
GPIO0: gpio@ef600b00 {
compatible = "ibm,gpio-440ep";
reg = <ef600b00 48>;
+ #gpio-cells = <2>;
+ gpio-controller;
};
GPIO1: gpio@ef600c00 {
compatible = "ibm,gpio-440ep";
reg = <ef600c00 48>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ led@31 {
+ compatible = "linux,gpio-led";
+ linux,name = ":green:";
+ gpios = <&GPIO1 31>;
+ };
+
+ led@30 {
+ compatible = "linux,gpio-led";
+ linux,name = ":red:";
+ gpios = <&GPIO1 30>;
+ };
};
+
ZMII0: emac-zmii@ef600d00 {
compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
reg = <ef600d00 c>;
^ permalink raw reply related
* Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Sean MacLennan @ 2008-04-29 1:47 UTC (permalink / raw)
To: Josh Boyer, linuxppc-dev; +Cc: Stephen Rothwell
In-Reply-To: <20080417152251.2bf07219@lappy.seanm.ca>
Ok, I think I have everybodys changes in. I will split out the DTS into
a separate patch. The changelog is in this one.
Cheers,
Sean
PIKA Warp: Update platform code to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Full DTM support including critical temperature.
* Added POST information.
* Removed LED function, moved to new LED driver.
* Moved ad7414 to new style I2C initialization.
Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index eb108a8..2178021 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -10,6 +10,7 @@
#include "ops.h"
#include "4xx.h"
#include "cuboot.h"
+#include "stdio.h"
#define TARGET_4xx
#define TARGET_44x
@@ -17,14 +18,54 @@
static bd_t bd;
-static void warp_fixups(void)
+static void warp_fixup_one_nor(u32 from, u32 to)
{
- unsigned long sysclk = 66000000;
+ void *devp;
+ char name[50];
+ u32 v[2];
+
+ sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
+
+ devp = finddevice(name);
+ if (!devp)
+ return;
+
+ if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+ v[0] = to;
+ setprop(devp, "reg", v, sizeof(v));
+
+ printf("NOR 64M fixup %x -> %x\r\n", from, to);
+ }
+}
+
- ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+static void warp_fixups(void)
+{
+ ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
ibm4xx_sdram_fixup_memsize();
ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+
+ /* Fixup for 64M flash on Rev A boards. */
+ if (bd.bi_flashsize == 0x4000000) {
+ void *devp;
+ u32 v[3];
+
+ devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
+ if (!devp)
+ return;
+
+ /* Fixup the size */
+ if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+ v[2] = bd.bi_flashsize;
+ setprop(devp, "reg", v, sizeof(v));
+ }
+
+ /* Fixup parition offsets */
+ warp_fixup_one_nor(0x300000, 0x3f00000);
+ warp_fixup_one_nor(0x340000, 0x3f40000);
+ warp_fixup_one_nor(0x380000, 0x3f80000);
+ }
}
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318..d293c70 100644
--- a/arch/powerpc/platforms/44x/warp-nand.c
+++ b/arch/powerpc/platforms/44x/warp-nand.c
@@ -11,8 +11,10 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/ndfc.h>
+#include <linux/of.h>
#include <asm/machdep.h>
+
#ifdef CONFIG_MTD_NAND_NDFC
#define CS_NAND_0 1 /* use chip select 1 for NAND device 0 */
@@ -35,13 +37,23 @@ static struct mtd_partition nand_parts[] = {
{
.name = "root",
.offset = 0x0200000,
- .size = 0x3400000
+ .size = 0x3E00000
+ },
+ {
+ .name = "persistent",
+ .offset = 0x4000000,
+ .size = 0x4000000
},
{
- .name = "user",
- .offset = 0x3600000,
- .size = 0x0A00000
+ .name = "persistent1",
+ .offset = 0x8000000,
+ .size = 0x4000000
},
+ {
+ .name = "persistent2",
+ .offset = 0xC000000,
+ .size = 0x4000000
+ }
};
struct ndfc_controller_settings warp_ndfc_settings = {
@@ -67,19 +79,15 @@ static struct platform_device warp_ndfc_device = {
.resource = &warp_ndfc,
};
-static struct nand_ecclayout nand_oob_16 = {
- .eccbytes = 3,
- .eccpos = { 0, 1, 2, 3, 6, 7 },
- .oobfree = { {.offset = 8, .length = 16} }
-};
-
+/* Do NOT set the ecclayout: let it default so it is correct for both
+ * 64M and 256M flash chips.
+ */
static struct platform_nand_chip warp_nand_chip0 = {
.nr_chips = 1,
.chip_offset = CS_NAND_0,
.nr_partitions = ARRAY_SIZE(nand_parts),
.partitions = nand_parts,
- .chip_delay = 50,
- .ecclayout = &nand_oob_16,
+ .chip_delay = 20,
.priv = &warp_chip0_settings,
};
@@ -96,6 +104,23 @@ static struct platform_device warp_nand_device = {
static int warp_setup_nand_flash(void)
{
+ struct device_node *np;
+
+ /* Try to detect a rev A based on NOR size. */
+ np = of_find_compatible_node(NULL, NULL, "cfi-flash");
+ if (np) {
+ struct property *pp;
+
+ pp = of_find_property(np, "reg", NULL);
+ if (pp && (pp->length == 12)) {
+ u32 *v = pp->value;
+ if (v[2] == 0x4000000)
+ /* Rev A = 64M NAND */
+ warp_nand_chip0.nr_partitions = 2;
+ }
+ of_node_put(np);
+ }
+
platform_device_register(&warp_ndfc_device);
platform_device_register(&warp_nand_device);
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
index 39cf615..aa0f737 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -12,6 +12,10 @@
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pika.h>
+#include <linux/delay.h>
#include <asm/machdep.h>
#include <asm/prom.h>
@@ -27,6 +31,18 @@ static __initdata struct of_device_id warp_of_bus[] = {
{},
};
+static __initdata struct i2c_board_info warp_i2c_info[] = {
+ { I2C_BOARD_INFO("ad7414", 0x4a) }
+};
+
+static int __init warp_arch_init(void)
+{
+ /* This should go away once support is moved to the dts. */
+ i2c_register_board_info(0, warp_i2c_info, ARRAY_SIZE(warp_i2c_info));
+ return 0;
+}
+machine_arch_initcall(warp, warp_arch_init);
+
static int __init warp_device_probe(void)
{
of_platform_bus_probe(NULL, warp_of_bus, NULL);
@@ -52,61 +68,232 @@ define_machine(warp) {
};
-#define LED_GREEN (0x80000000 >> 0)
-#define LED_RED (0x80000000 >> 1)
+/* I am not sure this is the best place for this... */
+static int __init warp_post_info(void)
+{
+ struct device_node *np;
+ void __iomem *fpga;
+ u32 post1, post2;
+
+ /* Sighhhh... POST information is in the sd area. */
+ np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
+ if (np == NULL)
+ return -ENOENT;
+
+ fpga = of_iomap(np, 0);
+ of_node_put(np);
+ if (fpga == NULL)
+ return -ENOENT;
+
+ post1 = in_be32(fpga + 0x40);
+ post2 = in_be32(fpga + 0x44);
+
+ iounmap(fpga);
+
+ if (post1 || post2)
+ printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
+ else
+ printk(KERN_INFO "Warp POST OK\n");
+
+ return 0;
+}
+machine_late_initcall(warp, warp_post_info);
+
+
+#ifdef CONFIG_SENSORS_AD7414
+
+static LIST_HEAD(dtm_shutdown_list);
+static void __iomem *dtm_fpga;
+static void __iomem *gpio_base;
+
+
+struct dtm_shutdown {
+ struct list_head list;
+ void (*func)(void *arg);
+ void *arg;
+};
-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */
-void warp_set_power_leds(int green, int red)
+int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
{
- static void __iomem *gpio_base = NULL;
- unsigned leds;
-
- if (gpio_base == NULL) {
- struct device_node *np;
-
- /* Power LEDS are on the second GPIO controller */
- np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP");
- if (np)
- np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP");
- if (np == NULL) {
- printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
- return;
+ struct dtm_shutdown *shutdown;
+
+ shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
+ if (shutdown == NULL)
+ return -ENOMEM;
+
+ shutdown->func = func;
+ shutdown->arg = arg;
+
+ list_add(&shutdown->list, &dtm_shutdown_list);
+
+ return 0;
+}
+
+int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+ struct dtm_shutdown *shutdown;
+
+ list_for_each_entry(shutdown, &dtm_shutdown_list, list)
+ if (shutdown->func == func && shutdown->arg == arg) {
+ list_del(&shutdown->list);
+ kfree(shutdown);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t temp_isr(int irq, void *context)
+{
+ struct dtm_shutdown *shutdown;
+
+ local_irq_disable();
+
+ /* Run through the shutdown list. */
+ list_for_each_entry(shutdown, &dtm_shutdown_list, list)
+ shutdown->func(shutdown->arg);
+
+ printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n");
+
+ while (1) {
+ if (dtm_fpga) {
+ unsigned reset = in_be32(dtm_fpga + 0x14);
+ out_be32(dtm_fpga + 0x14, reset);
}
- gpio_base = of_iomap(np, 0);
- of_node_put(np);
- if (gpio_base == NULL) {
- printk(KERN_ERR __FILE__ ": Unable to map gpio");
- return;
+ if (gpio_base) {
+ unsigned leds = in_be32(gpio_base);
+
+ /* green off, red toggle */
+ leds &= ~0x80000000;
+ leds ^= 0x40000000;
+
+ out_be32(gpio_base, leds);
}
+
+ mdelay(500);
+ }
+}
+
+static int pika_setup_leds(void)
+{
+ struct device_node *np;
+ const u32 *gpios;
+ int lenp;
+
+ np = of_find_compatible_node(NULL, NULL, "linux,gpio-led");
+ if (!np) {
+ printk(KERN_ERR __FILE__ ": Unable to find gpio-led\n");
+ return -ENOENT;
}
- leds = in_be32(gpio_base);
+ gpios = of_get_property(np, "gpios", &lenp);
+ of_node_put(np);
+ if (!gpios || lenp != 8) {
+ printk(KERN_ERR __FILE__
+ ": Unable to get gpios property (%d)\n", lenp);
+ return -ENOENT;
+ }
- switch (green) {
- case 0: leds &= ~LED_GREEN; break;
- case 1: leds |= LED_GREEN; break;
+ np = of_find_node_by_phandle(gpios[0]);
+ if (!np) {
+ printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
+ return -ENOENT;
}
- switch (red) {
- case 0: leds &= ~LED_RED; break;
- case 1: leds |= LED_RED; break;
+
+ gpio_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!gpio_base) {
+ printk(KERN_ERR __FILE__ ": Unable to map gpio");
+ return -ENOMEM;
}
- out_be32(gpio_base, leds);
+ return 0;
}
-EXPORT_SYMBOL(warp_set_power_leds);
+static void pika_setup_critical_temp(struct i2c_client *client)
+{
+ struct device_node *np;
+ int irq, rc;
+
+ /* Do this before enabling critical temp interrupt since we
+ * may immediately interrupt.
+ */
+ pika_setup_leds();
+
+ /* These registers are in 1 degree increments. */
+ i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
+ i2c_smbus_write_byte_data(client, 3, 55); /* Tlow */
+
+ np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
+ if (np == NULL) {
+ printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
+ return;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ of_node_put(np);
+ if (irq == NO_IRQ) {
+ printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
+ return;
+ }
+
+ rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
+ if (rc) {
+ printk(KERN_ERR __FILE__
+ ": Unable to request ad7414 irq %d = %d\n", irq, rc);
+ return;
+ }
+}
+
+static inline void pika_dtm_check_fan(void __iomem *fpga)
+{
+ static int fan_state;
+ u32 fan = in_be32(fpga + 0x34) & (1 << 14);
+
+ if (fan_state != fan) {
+ fan_state = fan;
+ if (fan)
+ printk(KERN_WARNING "Fan rotation error detected."
+ " Please check hardware.\n");
+ }
+}
-#ifdef CONFIG_SENSORS_AD7414
static int pika_dtm_thread(void __iomem *fpga)
{
- extern int ad7414_get_temp(int index);
+ struct i2c_adapter *adap;
+ struct i2c_client *client;
+
+ /* We loop in case either driver was compiled as a module and
+ * has not been insmoded yet.
+ */
+ while (!(adap = i2c_get_adapter(0))) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+
+ while (1) {
+ list_for_each_entry(client, &adap->clients, list)
+ if (client->addr == 0x4a)
+ goto found_it;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+
+found_it:
+ i2c_put_adapter(adap);
+
+ pika_setup_critical_temp(client);
+
+ printk(KERN_INFO "PIKA DTM thread running.\n");
while (!kthread_should_stop()) {
- int temp = ad7414_get_temp(0);
+ u16 temp = swab16(i2c_smbus_read_word_data(client, 0));
+ out_be32(fpga + 0x20, temp);
- out_be32(fpga, temp);
+ pika_dtm_check_fan(fpga);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
@@ -115,37 +302,44 @@ static int pika_dtm_thread(void __iomem *fpga)
return 0;
}
+
static int __init pika_dtm_start(void)
{
struct task_struct *dtm_thread;
struct device_node *np;
- struct resource res;
- void __iomem *fpga;
np = of_find_compatible_node(NULL, NULL, "pika,fpga");
if (np == NULL)
return -ENOENT;
- /* We do not call of_iomap here since it would map in the entire
- * fpga space, which is over 8k.
- */
- if (of_address_to_resource(np, 0, &res)) {
- of_node_put(np);
- return -ENOENT;
- }
+ dtm_fpga = of_iomap(np, 0);
of_node_put(np);
-
- fpga = ioremap(res.start, 0x24);
- if (fpga == NULL)
+ if (dtm_fpga == NULL)
return -ENOENT;
- dtm_thread = kthread_run(pika_dtm_thread, fpga + 0x20, "pika-dtm");
+ dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
if (IS_ERR(dtm_thread)) {
- iounmap(fpga);
+ iounmap(dtm_fpga);
return PTR_ERR(dtm_thread);
}
return 0;
}
-device_initcall(pika_dtm_start);
+machine_late_initcall(warp, pika_dtm_start);
+
+#else /* !CONFIG_SENSORS_AD7414 */
+
+int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
+{
+ return 0;
+}
+
+int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+ return 0;
+}
+
#endif
+
+EXPORT_SYMBOL(pika_dtm_register_shutdown);
+EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
^ permalink raw reply related
* [PATCH] Allow builing of pmac32 when CONFIG_NVRAM=m
From: Tony Breeds @ 2008-04-29 1:42 UTC (permalink / raw)
To: Paul Mackerras, linuxppc-dev; +Cc: Kamalesh Babulal
In-Reply-To: <alpine.DEB.1.10.0804271951190.11017@sheep.housecafe.de>
Kamalesh Babulal (kamalesh@linux.vnet.ibm.com) reports that CONFIG_NVRAM=m
is valid in terms of Kconfig but fails to build with:
Building modules, stage 2.
MODPOST 1401 modules
ERROR: "pmac_newworld" [arch/powerpc/platforms/powermac/nvram.ko] undefined!
ERROR: "__alloc_bootmem" [arch/powerpc/platforms/powermac/nvram.ko] undefined!
make[1]: *** [__modpost] Error
The arch/powerpc/platforms/powermac/nvram.c code really needs to be builtin,
but as it's compilation is dependant on a generic Kconfig symbol we
force nvram.c to be builtin if CONFIG_NVRAM is 'y' or 'm'
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/platforms/powermac/Makefile | 5 ++++-
arch/powerpc/platforms/powermac/setup.c | 3 ++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
index 78093d7..4d72c8f 100644
--- a/arch/powerpc/platforms/powermac/Makefile
+++ b/arch/powerpc/platforms/powermac/Makefile
@@ -6,7 +6,10 @@ obj-y += pic.o setup.o time.o feature.o pci.o \
obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o
obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o
-obj-$(CONFIG_NVRAM) += nvram.o
+# CONFIG_NVRAM is an arch. independant tristate symbol, for pmac32 we really
+# need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really
+# CONFIG_NVRAM=y
+obj-$(CONFIG_NVRAM:m=y) += nvram.o
# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
obj-$(CONFIG_PPC64) += nvram.o
obj-$(CONFIG_PPC32) += bootx_init.o
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index bf44c54..00bd016 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -337,7 +337,8 @@ static void __init pmac_setup_arch(void)
find_via_pmu();
smu_init();
-#if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64)
+#if defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) || \
+ defined(CONFIG_PPC64)
pmac_nvram_init();
#endif
--
1.5.5.1
Yours Tony
linux.conf.au http://www.marchsouth.org/
Jan 19 - 24 2009 The Australian Linux Technical Conference!
^ permalink raw reply related
* [PATCH v2] sysdev,mv64x60: MV64x60 device bus
From: Remi Machet @ 2008-04-29 1:24 UTC (permalink / raw)
To: Paul Mackerras, Dale Farnsworth; +Cc: linuxppc-dev
Follow up of my email of 4/16/2008 titled "MV64x60 device bus".
For each mv64360 entry in the OpenFirmware database, add the
registration of an of_bus to take care of devices connected to
the MV64x60 asynchronous devices controller.
Signed-off-by: Remi Machet (rmachet@slac.stanford.edu)
---
arch/powerpc/sysdev/mv64x60_dev.c | 10 ++++++++++
1 files changed, 10 insertions(+)
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 41af122..c3e28c4 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -15,6 +15,7 @@
#include <linux/console.h>
#include <linux/mv643xx.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <asm/prom.h>
@@ -25,6 +26,11 @@
* PowerPC of_platform_bus_type. They support platform_bus_type instead.
*/
+static struct of_device_id of_mv64x60_devices[] = {
+ { .compatible = "marvell,mv64306-devctrl", },
+ {}
+};
+
/*
* Create MPSC platform devices
*/
@@ -482,6 +488,10 @@ static int __init mv64x60_device_setup(void)
of_node_put(np);
}
+ /* Now add every node that is on the device bus (type is devicectrl */
+ for_each_compatible_node(np, NULL, "marvell,mv64360")
+ of_platform_bus_probe(np, of_mv64x60_devices, NULL);
+
return 0;
}
arch_initcall(mv64x60_device_setup);
^ permalink raw reply related
* Re: [PATCH] Change the default link address for pSeries zImage kernels.
From: Tony Breeds @ 2008-04-28 23:06 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: LinuxPPC-dev, Paul Mackerras
In-Reply-To: <1209103970.9060.226.camel@pasglop>
On Fri, Apr 25, 2008 at 04:12:50PM +1000, Benjamin Herrenschmidt wrote:
> Considering how bad OF can be on some machines, I'd like this to be
> boot-tested on a wider range of machines. Also, it might depend on the
> OF real-base setting as well...
>
> At least, we should be able to test at ozlabs on cell blades, POWER4
> bare metal (ie "SMP mode"), POWER5 and POWER5+.
Hmm okay it fails on POWER4, I'll see what can be done there.
Yours Tony
linux.conf.au http://www.marchsouth.org/
Jan 19 - 24 2009 The Australian Linux Technical Conference!
^ permalink raw reply
* Re: IB/ehca: handle negative return value from ibmebus_request_irq() properly in ehca_create_eq()
From: Roland Dreier @ 2008-04-28 23:00 UTC (permalink / raw)
To: Hoang-Nam Nguyen
Cc: linuxppc-dev, Christoph Raisch, Roel Kluin, linux-kernel, general
In-Reply-To: <200804281847.44968.hnguyen@linux.vnet.ibm.com>
thanks, applied
^ permalink raw reply
* Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Grant Likely @ 2008-04-28 22:07 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev
In-Reply-To: <20080428173738.6b1a2896@lappy.seanm.ca>
On Mon, Apr 28, 2008 at 3:37 PM, Sean MacLennan <seanm@seanm.ca> wrote:
> On Mon, 28 Apr 2008 13:56:11 -0600
>
> "Grant Likely" <grant.likely@secretlab.ca> wrote:
>
> >
>
> > You need to add the gpio-controller and #gpio-cells properties to the
> > GPIO nodes for the LED's gpios property to work correctly. Search for
> > "2) gpio-controller nodes" in
> > Documentation/powerpc/booting-without-of.txt for details. #gpio-cells
> > should probably be '2' for this gpio controller; 1 cell for the gpio
> > pin and 1 cell for flags.
>
> I believe these gpio nodes predate that text, but I added the fields
> anyway.
>
>
> >
> > These should not be children of the soc node (they are not part of the
> > SoC internal bus). However, I think it would be perfectly valid to
> > make them children of the gpio node since they don't have any
> > connections to other device on the platform.
>
> I put them in gpio. That was where I put them initialy.
>
>
> > Why is this information in the dts *and* the platform file? I haven't
> > been following the flash partition map binding conventions, but having
> > it in both places looks wrong....
> >
> > oh, wait... the one in the dts is for NOR and this one is for NAND,
> > right? And we don't have a binding yet for NAND partitions yet,
> > correct?
>
> Correct. Josh originally asked me to split out the warp-nand.c file so
> that once the NAND is in the dts, we can just delete the file. NAND is
> much more complicated that NOR to configure.
>
>
> > When exporting symbols for platform code you should avoid polluting
> > the global Linux namespace and prefix the functions with your platform
> > name.
>
> I was hoping dtm was good enough. I prefixed them with the company name.
> We are expecting to have a "family" of Asterisk appliances and I am
> trying to make educated guesses as to what will be family wide
> (prefixed with pika) and what will be warp specific.
Its just kernel code; it can be changed easily at later date. When
the company has *2* boards supported mainline in the kernel, then make
it generic. :-P
My experience is that educated guesses in this context are almost
always wrong (ie. the API won't be what you think it should be now).
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Sean MacLennan @ 2008-04-28 22:07 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20080428215424.GA15973@ld0162-tx32.am.freescale.net>
On Mon, 28 Apr 2008 16:54:24 -0500
Scott Wood <scottwood@freescale.com> wrote:
> Why can't the existing partition binding be used with NAND? It's
> what we do with Freescale FCM NAND.
I guess I could put the partitions in the dts. But I would have to
read them and dynamically create an array to pass to the ndfc driver.
It seems simpler to just statically initialize the array. Once the ndfc
is modified to use the dts, I will switch to that method.
Cheers,
Sean
^ permalink raw reply
* Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Scott Wood @ 2008-04-28 21:54 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev
In-Reply-To: <20080428173738.6b1a2896@lappy.seanm.ca>
On Mon, Apr 28, 2008 at 05:37:38PM -0400, Sean MacLennan wrote:
> > Why is this information in the dts *and* the platform file? I haven't
> > been following the flash partition map binding conventions, but having
> > it in both places looks wrong....
> >
> > oh, wait... the one in the dts is for NOR and this one is for NAND,
> > right? And we don't have a binding yet for NAND partitions yet,
> > correct?
>
> Correct.
Why can't the existing partition binding be used with NAND? It's what we
do with Freescale FCM NAND.
-Scott
^ permalink raw reply
* Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code tosupportRev B boards
From: Richard Purdie @ 2008-04-28 21:36 UTC (permalink / raw)
To: Sean MacLennan; +Cc: Stephen Rothwell, linuxppc-dev
In-Reply-To: <20080428172454.06988461@lappy.seanm.ca>
On Mon, 2008-04-28 at 17:24 -0400, Sean MacLennan wrote:
> On Mon, 28 Apr 2008 21:44:05 +0100
> "Richard Purdie" <rpurdie@rpsys.net> wrote:
>
> > You can leave sections blank but it pays to leave the separator in so
> > use ":red:" or ":red", not "red".
>
> Ok, :red: and :green: it is.
>
> What would be the advantage of pika:red: or warp:red:?
It makes it more obvious which driver is involved which can be useful
when reading bug reports and helps identify things in cases where LEDs
may be plugged in, e.g. USB.
Cheers,
Richard
^ permalink raw reply
* Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards
From: Sean MacLennan @ 2008-04-28 21:37 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40804281256y722d8cf6pcae462d68b04e01f@mail.gmail.com>
On Mon, 28 Apr 2008 13:56:11 -0600
"Grant Likely" <grant.likely@secretlab.ca> wrote:
>
> You need to add the gpio-controller and #gpio-cells properties to the
> GPIO nodes for the LED's gpios property to work correctly. Search for
> "2) gpio-controller nodes" in
> Documentation/powerpc/booting-without-of.txt for details. #gpio-cells
> should probably be '2' for this gpio controller; 1 cell for the gpio
> pin and 1 cell for flags.
I believe these gpio nodes predate that text, but I added the fields
anyway.
>
> These should not be children of the soc node (they are not part of the
> SoC internal bus). However, I think it would be perfectly valid to
> make them children of the gpio node since they don't have any
> connections to other device on the platform.
I put them in gpio. That was where I put them initialy.
> Why is this information in the dts *and* the platform file? I haven't
> been following the flash partition map binding conventions, but having
> it in both places looks wrong....
>
> oh, wait... the one in the dts is for NOR and this one is for NAND,
> right? And we don't have a binding yet for NAND partitions yet,
> correct?
Correct. Josh originally asked me to split out the warp-nand.c file so
that once the NAND is in the dts, we can just delete the file. NAND is
much more complicated that NOR to configure.
> When exporting symbols for platform code you should avoid polluting
> the global Linux namespace and prefix the functions with your platform
> name.
I was hoping dtm was good enough. I prefixed them with the company name.
We are expecting to have a "family" of Asterisk appliances and I am
trying to make educated guesses as to what will be family wide
(prefixed with pika) and what will be warp specific.
Cheers,
Sean
^ permalink raw reply
* Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code tosupportRev B boards
From: Sean MacLennan @ 2008-04-28 21:24 UTC (permalink / raw)
To: Richard Purdie; +Cc: Stephen Rothwell, linuxppc-dev
In-Reply-To: <1209415445.5923.59.camel@dax.rpnet.com>
On Mon, 28 Apr 2008 21:44:05 +0100
"Richard Purdie" <rpurdie@rpsys.net> wrote:
> You can leave sections blank but it pays to leave the separator in so
> use ":red:" or ":red", not "red".
Ok, :red: and :green: it is.
What would be the advantage of pika:red: or warp:red:?
Cheers,
Sean
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox