LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [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

* Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code tosupportRev B boards
From: Sean MacLennan @ 2008-04-29  5:42 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Stephen Rothwell
In-Reply-To: <18454.44365.719572.654726@cargo.ozlabs.ibm.com>

On Tue, 29 Apr 2008 15:08:29 +1000
"Paul Mackerras" <paulus@samba.org> wrote:

> It doesn't help that both of these patches have the same subject line,
> nor that it starts with "Re:". :(

Sorry about that. I just split up the two patches, but the same subject
does apply to both. The code currently in the mainline kernel is for a
Rev A. Since there are no Rev As outside of PIKA, that is not very
useful. These patches bring the platform code up to Rev B standards
(while still maintaining Rev A support).

So the subject is correct for both.

> 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.

You won't find it. One of the problems is that I am basically adding
patches to patches to patches, but since none of them are in a
mainline git, they all just keep showing up as one big patch. 

That comment was meant as a quick note to explain why the platform patch
changed from the previous platform patch. Short of diffing the
patches, you can't easily see how they changed.

After the Warp is released (sometime in May), the hardware churn should
end and I can submit patches one at a time rather than one massive
patch.

Cheers,
   Sean

^ permalink raw reply

* [PATCH] devres: support addresses greater than an unsigned long via dev_ioremap
From: Kumar Gala @ 2008-04-29  6:22 UTC (permalink / raw)
  To: htejun, Andrew Morton, jgarzik; +Cc: linuxppc-dev, linux-kernel

Use a resource_size_t instead of unsigned long since some arch's are
capable of having ioremap deal with addresses greater than the size of a
unsigned long.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 include/linux/io.h |    4 ++--
 lib/devres.c       |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/linux/io.h b/include/linux/io.h
index e3b2dda..831f57c 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -58,9 +58,9 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
 }
 #endif

-void __iomem * devm_ioremap(struct device *dev, unsigned long offset,
+void __iomem * devm_ioremap(struct device *dev, resource_size_t offset,
 			    unsigned long size);
-void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
+void __iomem * devm_ioremap_nocache(struct device *dev, resource_size_t offset,
 				    unsigned long size);
 void devm_iounmap(struct device *dev, void __iomem *addr);
 int check_signature(const volatile void __iomem *io_addr,
diff --git a/lib/devres.c b/lib/devres.c
index edc27a5..26c87c4 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -20,7 +20,7 @@ static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
  *
  * Managed ioremap().  Map is automatically unmapped on driver detach.
  */
-void __iomem *devm_ioremap(struct device *dev, unsigned long offset,
+void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
 			   unsigned long size)
 {
 	void __iomem **ptr, *addr;
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(devm_ioremap);
  * Managed ioremap_nocache().  Map is automatically unmapped on driver
  * detach.
  */
-void __iomem *devm_ioremap_nocache(struct device *dev, unsigned long offset,
+void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
 				   unsigned long size)
 {
 	void __iomem **ptr, *addr;
-- 
1.5.4.1

^ permalink raw reply related

* build failure on efika
From: Paul Mackerras @ 2008-04-29  6:27 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

My test builds for efika currently fail with this message:

FATAL: drivers/serial/mpc52xx_uart: struct of_device_id is not terminated with a NULL entry!
make[2]: *** [__modpost] Error 1
make[1]: *** [modules] Error 2
make: *** [sub-make] Error 2

Could you do a little patch to add the NULL entry please?

Paul.

^ permalink raw reply

* Re: [PATCH] devres: support addresses greater than an unsigned long via dev_ioremap
From: Tejun Heo @ 2008-04-29  6:30 UTC (permalink / raw)
  To: Kumar Gala; +Cc: Andrew Morton, linuxppc-dev, jgarzik, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0804290122210.10928@blarg.am.freescale.net>

Kumar Gala wrote:
> Use a resource_size_t instead of unsigned long since some arch's are
> capable of having ioremap deal with addresses greater than the size of a
> unsigned long.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

Acked-by: Tejun Heo <htejun@gmail.com>

Thanks.

-- 
tejun

^ permalink raw reply

* Re: [PATCH] devres: support addresses greater than an unsigned long via dev_ioremap
From: Jeff Garzik @ 2008-04-29  6:37 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Andrew Morton, Greg KH, Jesse Barnes, linux-kernel, linuxppc-dev
In-Reply-To: <4816C094.6030601@gmail.com>

Tejun Heo wrote:
> Kumar Gala wrote:
>> Use a resource_size_t instead of unsigned long since some arch's are
>> capable of having ioremap deal with addresses greater than the size of a
>> unsigned long.
>>
>> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> 
> Acked-by: Tejun Heo <htejun@gmail.com>

Fine with me, too.

I think devres changes should go via GregKH (device core) or Jesse (PCI) 
rather than my libata tree, unless there are obvious dependencies...

	Jeff

^ permalink raw reply

* (no subject)
From: Chen Gong @ 2008-04-29  8:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: wim, linux-kernel

this patch only makes a few fixes for latest kernel git tree

^ permalink raw reply

* [PATCH] Watchdog on MPC85xx SMP system
From: Chen Gong @ 2008-04-29  8:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: wim, Chen Gong, linux-kernel
In-Reply-To: <1209458525-8041-1-git-send-email-g.chen@freescale.com>

On Book-E SMP systems each core has its own private watchdog.
If only one watchdog is enabled, when the core that doesn't
enable the watchdog is hung, system can't reset because no
watchdog is running on it. That's bad. It means we must
enable watchdogs on both cores.

We can use smp_call_function() to send appropriate messages to
all the other cores to enable and update the watchdog.

Signed-off-by: Chen Gong <g.chen@freescale.com>
---
Now Tested on MPC8572DS platform.

 drivers/watchdog/booke_wdt.c |   31 +++++++++++++++++++++++--------
 1 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index d362f5b..8a4e7f0 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -1,12 +1,12 @@
 /*
- * drivers/char/watchdog/booke_wdt.c
+ * drivers/watchdog/booke_wdt.c
  *
  * Watchdog timer for PowerPC Book-E systems
  *
  * Author: Matthew McClintock
  * Maintainer: Kumar Gala <galak@kernel.crashing.org>
  *
- * Copyright 2005 Freescale Semiconductor Inc.
+ * Copyright 2005, 2008 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -16,6 +16,7 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/smp.h>
 #include <linux/miscdevice.h>
 #include <linux/notifier.h>
 #include <linux/watchdog.h>
@@ -47,23 +48,31 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
 #define WDTP(x)		(TCR_WP(x))
 #endif
 
+static DEFINE_SPINLOCK(booke_wdt_lock);
+
+static void __booke_wdt_ping(void *data)
+{
+	mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
+}
+
 /*
  * booke_wdt_ping:
  */
 static __inline__ void booke_wdt_ping(void)
 {
-	mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
+	smp_call_function(__booke_wdt_ping, NULL, 0, 0);
+	__booke_wdt_ping(NULL);
 }
 
 /*
- * booke_wdt_enable:
+ * __booke_wdt_enable:
  */
-static __inline__ void booke_wdt_enable(void)
+static inline void __booke_wdt_enable(void *data)
 {
 	u32 val;
 
 	/* clear status before enabling watchdog */
-	booke_wdt_ping();
+	__booke_wdt_ping(NULL);
 	val = mfspr(SPRN_TCR);
 	val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
 
@@ -137,12 +146,15 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file,
  */
 static int booke_wdt_open (struct inode *inode, struct file *file)
 {
+	spin_lock(&booke_wdt_lock);
 	if (booke_wdt_enabled == 0) {
 		booke_wdt_enabled = 1;
-		booke_wdt_enable();
+		__booke_wdt_enable(NULL);
+		smp_call_function(__booke_wdt_enable, NULL, 0, 0);
 		printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
 				booke_wdt_period);
 	}
+	spin_unlock(&booke_wdt_lock);
 
 	return nonseekable_open(inode, file);
 }
@@ -183,11 +195,14 @@ static int __init booke_wdt_init(void)
 		return ret;
 	}
 
+	spin_lock(&booke_wdt_lock);
 	if (booke_wdt_enabled == 1) {
 		printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
 				booke_wdt_period);
-		booke_wdt_enable();
+		__booke_wdt_enable(NULL);
+		smp_call_function(__booke_wdt_enable, NULL, 0, 0);
 	}
+	spin_unlock(&booke_wdt_lock);
 
 	return ret;
 }
-- 
1.5.4

^ permalink raw reply related

* Re: Virtex4FX12LC hangs in calibrating delay loop
From: wangyanlong @ 2008-04-29  8:53 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <20070621151554.GA22663@cip.informatik.uni-erlangen.de>


I meet the same problem as yours ,  have you fix your problem now ??? I am
keep trying !!!!

Thomas Glanzmann wrote:
> 
> Hello,
> I used the HEAD secretlabs kernel and used ml403 defconfig. I still see
> no serial output from the _kernel_ on the serial console. But I do see
> output from the in kernel embedded boot loader "load_kernel". I typed in
> stop in xmd and got an instruction pointer which points to:
> 
>         c00045a0 <__delay>:
>         c00045a0:       2c 03 00 00     cmpwi   r3,0
>         c00045a4:       7c 69 03 a6     mtctr   r3
>         c00045a8:       4d 82 00 20     beqlr
>         c00045ac:       42 00 00 00     bdnz-   c00045ac <__delay+0xc>      
> <<<<<<<<
>         c00045b0:       4e 80 00 20     blr
> 
> So I guess it is the calibrating delay loop and I am not sure. I can
> reproduce
> this. It is always in this function. Now I wonder is my board missing
> timer interrupts? What could be the reason for this. And of course one
> much more important question:
> 
>         - Is the serial console initialized before or after the
>           calibrating delay loop?
> 
> Is there a way to get a backtrace out of this? If that is the case what
> do I have to do? Recompile the Kernel with frame pointers and attach
> gdb?
> 
>         Thomas
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
> 
> 

-- 
View this message in context: http://www.nabble.com/Virtex4FX12LC-hangs-in-calibrating-delay-loop-tp11235297p16955743.html
Sent from the linuxppc-embedded mailing list archive at Nabble.com.

^ permalink raw reply

* overloading existing PTRACE_GET_DEBUGREG/PTRACE_SET_DEBUGREG commands
From: Kumar Gala @ 2008-04-29  8:56 UTC (permalink / raw)
  To: Paul Mackerras
  Cc: linuxppc-dev@ozlabs.org list, Anton Blanchard, Roland McGrath,
	Paralkar Anmol

It looks like when Anton added the PTRACE_GET_DEBUGREG/ 
PTRACE_SET_DEBUGREG he envisioned future chips having more than one  
IABR/DABR.

I'm wondering what the feeling is about using the commands for  
handling some of the sub-arch variants we have:

e300 (603 style machine) - adds IABR2, DABR2, IBCR (control) and DBCR  
(control).  We can use IABR1/2 (and DABR1/2) either as unique  
addresses or for various ranges (inclusive or exclusive)

Book-e class machines can have the following registers: DBCR[0-2],  
IAC1-4, DAC1-2, DVC1-2, DBSR.  IACs are roughly equivalent to IABRs,  
DACs are roughly equivalent to DABRs.  Booke has similar ability to  
the e300 to do inclusive, exclusive ranges as well as some other  
features.

My question is how to handle providing access to the debug resources  
we have on these other machine types.  Should we just use GET_DEBUGREG/ 
SET_DEBUGREG and specify what the buffers look like for these specific  
machine types?  Is it ok to overload the commands this way?  How does  
this play with utrace?

Also, what functionality can GDB take advantage of today?  Does it  
comprehend the idea of breakpoints or watchpoints that cover a range?

- k

^ permalink raw reply

* Re: HAVE_CONFIG
From: Arnd Bergmann @ 2008-04-29  9:27 UTC (permalink / raw)
  To: linuxppc-embedded, dhlii
In-Reply-To: <4816B372.10608@dlasys.net>

On Tuesday 29 April 2008, David H. Lynch Jr. wrote:
> =A0 =A0 Why does CONFIG_PPC set CONFIG_HAVE_IDE ?

Because it's possible to build ide drivers on the powerpc architecture.
It means you get the option to enable to disable the old ATA (IDE) drivers.

	Arnd <><

^ permalink raw reply

* Re: [PATCH 2/2] Raise the upper limit of NR_CPUS and move the pacas into the BSS.
From: Arnd Bergmann @ 2008-04-29  9:46 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras
In-Reply-To: <6bbf4d3637c9b72f9f0a4cf8a6f2c322c0784d7e.1209008469.git.tony@bakeyournoodle.com>

On Thursday 24 April 2008, Tony Breeds wrote:
> This patch adds the required functionality to fill in all pacas at runtim=
e.
>=20
> With NR_CPUS=3D1024
> text =A0 =A0data =A0 =A0 bss =A0 =A0 dec =A0 =A0 hex filename
> =A0137 1704032 =A0 =A0 =A0 0 1704169 =A01a00e9 arch/powerpc/kernel/paca.o=
 :Before
> =A0121 1179744 =A0524288 1704153 =A01a00d9 arch/powerpc/kernel/paca.o :Af=
ter
>=20
> Also remove unneeded #includes from arch/powerpc/kernel/paca.c
>=20
> Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>

Maybe we can go even further than this: Since it is now a substantial amount
of .bss, maybe the unused parts can be returned to the buddy allocator
using free_bootmem or similar once you know how many CPUs there are?

I know that this would be an evil hack, but it may still be worth it.
Your patch should certainly go in first though, freeing the memory would
be an additional extension.

	Arnd <><

^ permalink raw reply

* Re: HAVE_CONFIG
From: David H. Lynch Jr. @ 2008-04-29  9:56 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-embedded
In-Reply-To: <200804291127.14666.arnd@arndb.de>

Arnd Bergmann wrote:
> On Tuesday 29 April 2008, David H. Lynch Jr. wrote:
>   
>>     Why does CONFIG_PPC set CONFIG_HAVE_IDE ?
>>     
>
> Because it's possible to build ide drivers on the powerpc architecture.
> It means you get the option to enable to disable the old ATA (IDE) drivers.
>
> 	Arnd <><
>   
    So CONFIG_HAVE_IDE means the architecture could have IDE rather than
it does have IDE ?
   
    My BSP can't have IDE, does that mean I should add
   
    default n if MYBSP

    ? or somehow deselect HAVE_IDE in the config option for my BSP ?


-- 
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

* Re: HAVE_CONFIG
From: Arnd Bergmann @ 2008-04-29 10:03 UTC (permalink / raw)
  To: dhlii; +Cc: linuxppc-embedded
In-Reply-To: <4816F0CF.2080800@dlasys.net>

On Tuesday 29 April 2008, David H. Lynch Jr. wrote:
> Arnd Bergmann wrote:
> > On Tuesday 29 April 2008, David H. Lynch Jr. wrote:
> > =A0=20
> >> =A0 =A0 Why does CONFIG_PPC set CONFIG_HAVE_IDE ?
> >> =A0 =A0=20
> >
> > Because it's possible to build ide drivers on the powerpc architecture.
> > It means you get the option to enable to disable the old ATA (IDE) driv=
ers.
> >
> > =A0=A0=A0=A0=A0=A0Arnd <><
> > =A0=20
> =A0 =A0 So CONFIG_HAVE_IDE means the architecture could have IDE rather t=
han
> it does have IDE ?

Right.

> =A0 =A0 My BSP can't have IDE, does that mean I should add
> =A0 =A0
> =A0 =A0 default n if MYBSP
>=20
> =A0 =A0 ? or somehow deselect HAVE_IDE in the config option for my BSP ?

No.

You can always build multiplatform kernels, and your BSP Kconfig should do
nothing to forbid this. The only time where you don't want to set HAVE_IDE
is when it is impossible to build the IDE drivers. However, if your code
does not allow building support for IDE into the kernel, you should fix your
code rather than disable the Kconfig.

	Arnd <><

^ permalink raw reply

* [PATCH 0/2 v2] i2c: Add support for device alias names
From: Jean Delvare @ 2008-04-29 10:42 UTC (permalink / raw)
  To: Linux I2C
  Cc: Laurent, Sievers, linuxppc-dev list, Paul Mundt, Scott Wood, Kay

Hi all,

This is yesterday's patch set updated to apply cleanly (and hopefully
work) on top of 2.6.25-git13. Basically the only change since yesterday
is the sync with the rtc subsystem updates, which converted 3 drivers
(rtc-x1205, rtc-pcf8563 and rtc-isl1208).

The plan is to send this to Linus this evening. The more testing it
gets, the better. Thanks to Wolfram and Jochen for yesterday's test
reports!

-- 
Jean Delvare

^ permalink raw reply

* [PATCH 1/2 v2] i2c: Add support for device alias names
From: Jean Delvare @ 2008-04-29 10:46 UTC (permalink / raw)
  To: Linux I2C
  Cc: Laurent, Sievers, linuxppc-dev list, Paul Mundt, Scott Wood, Kay
In-Reply-To: <20080429124241.08e18ae3@hyperion.delvare>

Based on earlier work by Jon Smirl and Jochen Friedrich.

This patch allows new-style i2c chip drivers to have alias names using
the official kernel aliasing system and MODULE_DEVICE_TABLE(). At this
point, the old i2c driver binding scheme (driver_name/type) is still
supported.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Jochen Friedrich <jochen@scram.de>
Cc: Jon Smirl <jonsmirl@gmail.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
---
 Documentation/i2c/writing-clients          |    3 +
 drivers/gpio/pca953x.c                     |    3 +
 drivers/gpio/pcf857x.c                     |    3 +
 drivers/hwmon/f75375s.c                    |    8 ++--
 drivers/i2c/chips/ds1682.c                 |    3 +
 drivers/i2c/chips/menelaus.c               |    3 +
 drivers/i2c/chips/tps65010.c               |    3 +
 drivers/i2c/chips/tsl2550.c                |    3 +
 drivers/i2c/i2c-core.c                     |   51 +++++++++++++++++++++++-----
 drivers/media/video/cs5345.c               |    3 +
 drivers/media/video/cs53l32a.c             |    3 +
 drivers/media/video/cx25840/cx25840-core.c |    3 +
 drivers/media/video/m52790.c               |    3 +
 drivers/media/video/msp3400-driver.c       |    2 -
 drivers/media/video/mt9m001.c              |    3 +
 drivers/media/video/mt9v022.c              |    3 +
 drivers/media/video/saa7115.c              |    3 +
 drivers/media/video/saa7127.c              |    3 +
 drivers/media/video/saa717x.c              |    3 +
 drivers/media/video/tcm825x.c              |    3 +
 drivers/media/video/tlv320aic23b.c         |    3 +
 drivers/media/video/tuner-core.c           |    3 +
 drivers/media/video/tvaudio.c              |    2 -
 drivers/media/video/upd64031a.c            |    3 +
 drivers/media/video/upd64083.c             |    3 +
 drivers/media/video/v4l2-common.c          |    5 +-
 drivers/media/video/vp27smpx.c             |    3 +
 drivers/media/video/wm8739.c               |    3 +
 drivers/media/video/wm8775.c               |    3 +
 drivers/rtc/rtc-ds1307.c                   |    3 +
 drivers/rtc/rtc-ds1374.c                   |    3 +
 drivers/rtc/rtc-isl1208.c                  |    2 -
 drivers/rtc/rtc-m41t80.c                   |    3 +
 drivers/rtc/rtc-pcf8563.c                  |    3 +
 drivers/rtc/rtc-rs5c372.c                  |    3 +
 drivers/rtc/rtc-s35390a.c                  |    3 +
 drivers/rtc/rtc-x1205.c                    |    3 +
 include/linux/i2c.h                        |    5 +-
 include/linux/mod_devicetable.h            |   11 ++++++
 include/media/v4l2-common.h                |    4 +-
 include/media/v4l2-i2c-drv-legacy.h        |    2 -
 include/media/v4l2-i2c-drv.h               |    2 -
 scripts/mod/file2alias.c                   |   13 +++++++
 43 files changed, 146 insertions(+), 54 deletions(-)

--- linux-2.6.26-rc0.orig/Documentation/i2c/writing-clients	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/Documentation/i2c/writing-clients	2008-04-29 08:37:43.000000000 +0200
@@ -164,7 +164,8 @@ I2C device drivers using this binding mo
 kind of driver in Linux:  they provide a probe() method to bind to
 those devices, and a remove() method to unbind.
 
-	static int foo_probe(struct i2c_client *client);
+	static int foo_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id);
 	static int foo_remove(struct i2c_client *client);
 
 Remember that the i2c_driver does not create those client handles.  The
--- linux-2.6.26-rc0.orig/drivers/gpio/pca953x.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pca953x.c	2008-04-29 08:37:43.000000000 +0200
@@ -192,7 +192,8 @@ static void pca953x_setup_gpio(struct pc
 	gc->owner = THIS_MODULE;
 }
 
-static int __devinit pca953x_probe(struct i2c_client *client)
+static int __devinit pca953x_probe(struct i2c_client *client,
+				   const struct i2c_device_id *did)
 {
 	struct pca953x_platform_data *pdata;
 	struct pca953x_chip *chip;
--- linux-2.6.26-rc0.orig/drivers/gpio/pcf857x.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pcf857x.c	2008-04-29 08:37:43.000000000 +0200
@@ -142,7 +142,8 @@ static void pcf857x_set16(struct gpio_ch
 
 /*-------------------------------------------------------------------------*/
 
-static int pcf857x_probe(struct i2c_client *client)
+static int pcf857x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	struct pcf857x_platform_data	*pdata;
 	struct pcf857x			*gpio;
--- linux-2.6.26-rc0.orig/drivers/hwmon/f75375s.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/hwmon/f75375s.c	2008-04-29 08:37:43.000000000 +0200
@@ -117,7 +117,8 @@ struct f75375_data {
 static int f75375_attach_adapter(struct i2c_adapter *adapter);
 static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
 static int f75375_detach_client(struct i2c_client *client);
-static int f75375_probe(struct i2c_client *client);
+static int f75375_probe(struct i2c_client *client,
+			const struct i2c_device_id *id);
 static int f75375_remove(struct i2c_client *client);
 
 static struct i2c_driver f75375_legacy_driver = {
@@ -628,7 +629,8 @@ static void f75375_init(struct i2c_clien
 
 }
 
-static int f75375_probe(struct i2c_client *client)
+static int f75375_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
 {
 	struct f75375_data *data = i2c_get_clientdata(client);
 	struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
@@ -748,7 +750,7 @@ static int f75375_detect(struct i2c_adap
 	if ((err = i2c_attach_client(client)))
 		goto exit_free;
 
-	if ((err = f75375_probe(client)) < 0)
+	if ((err = f75375_probe(client, NULL)) < 0)
 		goto exit_detach;
 
 	return 0;
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/ds1682.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/ds1682.c	2008-04-29 08:37:43.000000000 +0200
@@ -200,7 +200,8 @@ static struct bin_attribute ds1682_eepro
 /*
  * Called when a ds1682 device is matched with this driver
  */
-static int ds1682_probe(struct i2c_client *client)
+static int ds1682_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	int rc;
 
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/menelaus.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/menelaus.c	2008-04-29 08:37:43.000000000 +0200
@@ -1149,7 +1149,8 @@ static inline void menelaus_rtc_init(str
 
 static struct i2c_driver menelaus_i2c_driver;
 
-static int menelaus_probe(struct i2c_client *client)
+static int menelaus_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
 {
 	struct menelaus_chip	*menelaus;
 	int			rev = 0, val;
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tps65010.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tps65010.c	2008-04-29 08:37:43.000000000 +0200
@@ -532,7 +532,8 @@ static int __exit tps65010_remove(struct
 	return 0;
 }
 
-static int tps65010_probe(struct i2c_client *client)
+static int tps65010_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
 {
 	struct tps65010		*tps;
 	int			status;
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tsl2550.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tsl2550.c	2008-04-29 08:37:43.000000000 +0200
@@ -364,7 +364,8 @@ static int tsl2550_init_client(struct i2
  */
 
 static struct i2c_driver tsl2550_driver;
-static int __devinit tsl2550_probe(struct i2c_client *client)
+static int __devinit tsl2550_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 	struct tsl2550_data *data;
--- linux-2.6.26-rc0.orig/drivers/i2c/i2c-core.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/i2c-core.c	2008-04-29 08:37:43.000000000 +0200
@@ -48,6 +48,17 @@ static DEFINE_IDR(i2c_adapter_idr);
 
 /* ------------------------------------------------------------------------- */
 
+static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+						const struct i2c_client *client)
+{
+	while (id->name[0]) {
+		if (strcmp(client->name, id->name) == 0)
+			return id;
+		id++;
+	}
+	return NULL;
+}
+
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
 	struct i2c_client	*client = to_i2c_client(dev);
@@ -59,6 +70,10 @@ static int i2c_device_match(struct devic
 	if (!is_newstyle_driver(driver))
 		return 0;
 
+	/* match on an id table if there is one */
+	if (driver->id_table)
+		return i2c_match_id(driver->id_table, client) != NULL;
+
 	/* new style drivers use the same kind of driver matching policy
 	 * as platform devices or SPI:  compare device and driver IDs.
 	 */
@@ -73,11 +88,17 @@ static int i2c_device_uevent(struct devi
 	struct i2c_client	*client = to_i2c_client(dev);
 
 	/* by definition, legacy drivers can't hotplug */
-	if (dev->driver || !client->driver_name)
+	if (dev->driver)
 		return 0;
 
-	if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
-		return -ENOMEM;
+	if (client->driver_name[0]) {
+		if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
+			return -ENOMEM;
+	} else {
+		if (add_uevent_var(env, "MODALIAS=%s%s",
+				   I2C_MODULE_PREFIX, client->name))
+			return -ENOMEM;
+	}
 	dev_dbg(dev, "uevent\n");
 	return 0;
 }
@@ -90,13 +111,19 @@ static int i2c_device_probe(struct devic
 {
 	struct i2c_client	*client = to_i2c_client(dev);
 	struct i2c_driver	*driver = to_i2c_driver(dev->driver);
+	const struct i2c_device_id *id;
 	int status;
 
 	if (!driver->probe)
 		return -ENODEV;
 	client->driver = driver;
 	dev_dbg(dev, "probe\n");
-	status = driver->probe(client);
+
+	if (driver->id_table)
+		id = i2c_match_id(driver->id_table, client);
+	else
+		id = NULL;
+	status = driver->probe(client, id);
 	if (status)
 		client->driver = NULL;
 	return status;
@@ -179,9 +206,9 @@ static ssize_t show_client_name(struct d
 static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	return client->driver_name
+	return client->driver_name[0]
 		? sprintf(buf, "%s\n", client->driver_name)
-		: 0;
+		: sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
 }
 
 static struct device_attribute i2c_dev_attrs[] = {
@@ -300,15 +327,21 @@ void i2c_unregister_device(struct i2c_cl
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
 
 
-static int dummy_nop(struct i2c_client *client)
+static int dummy_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	return 0;
+}
+
+static int dummy_remove(struct i2c_client *client)
 {
 	return 0;
 }
 
 static struct i2c_driver dummy_driver = {
 	.driver.name	= "dummy",
-	.probe		= dummy_nop,
-	.remove		= dummy_nop,
+	.probe		= dummy_probe,
+	.remove		= dummy_remove,
 };
 
 /**
--- linux-2.6.26-rc0.orig/drivers/media/video/cs5345.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/cs5345.c	2008-04-29 08:37:43.000000000 +0200
@@ -142,7 +142,8 @@ static int cs5345_command(struct i2c_cli
 
 /* ----------------------------------------------------------------------- */
 
-static int cs5345_probe(struct i2c_client *client)
+static int cs5345_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
--- linux-2.6.26-rc0.orig/drivers/media/video/cs53l32a.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/cs53l32a.c	2008-04-29 08:37:43.000000000 +0200
@@ -135,7 +135,8 @@ static int cs53l32a_command(struct i2c_c
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int cs53l32a_probe(struct i2c_client *client)
+static int cs53l32a_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
 {
 	int i;
 
--- linux-2.6.26-rc0.orig/drivers/media/video/cx25840/cx25840-core.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/cx25840/cx25840-core.c	2008-04-29 08:37:43.000000000 +0200
@@ -1209,7 +1209,8 @@ static int cx25840_command(struct i2c_cl
 
 /* ----------------------------------------------------------------------- */
 
-static int cx25840_probe(struct i2c_client *client)
+static int cx25840_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
 {
 	struct cx25840_state *state;
 	u32 id;
--- linux-2.6.26-rc0.orig/drivers/media/video/m52790.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/m52790.c	2008-04-29 08:37:43.000000000 +0200
@@ -126,7 +126,8 @@ static int m52790_command(struct i2c_cli
 
 /* i2c implementation */
 
-static int m52790_probe(struct i2c_client *client)
+static int m52790_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	struct m52790_state *state;
 
--- linux-2.6.26-rc0.orig/drivers/media/video/msp3400-driver.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/msp3400-driver.c	2008-04-29 08:37:43.000000000 +0200
@@ -805,7 +805,7 @@ static int msp_resume(struct i2c_client 
 
 /* ----------------------------------------------------------------------- */
 
-static int msp_probe(struct i2c_client *client)
+static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct msp_state *state;
 	int (*thread_func)(void *data) = NULL;
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9m001.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9m001.c	2008-04-29 08:37:43.000000000 +0200
@@ -620,7 +620,8 @@ static void mt9m001_video_remove(struct 
 	soc_camera_video_stop(&mt9m001->icd);
 }
 
-static int mt9m001_probe(struct i2c_client *client)
+static int mt9m001_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
 {
 	struct mt9m001 *mt9m001;
 	struct soc_camera_device *icd;
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9v022.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9v022.c	2008-04-29 08:37:43.000000000 +0200
@@ -745,7 +745,8 @@ static void mt9v022_video_remove(struct 
 	soc_camera_video_stop(&mt9v022->icd);
 }
 
-static int mt9v022_probe(struct i2c_client *client)
+static int mt9v022_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
 {
 	struct mt9v022 *mt9v022;
 	struct soc_camera_device *icd;
--- linux-2.6.26-rc0.orig/drivers/media/video/saa7115.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/saa7115.c	2008-04-29 08:37:43.000000000 +0200
@@ -1450,7 +1450,8 @@ static int saa7115_command(struct i2c_cl
 
 /* ----------------------------------------------------------------------- */
 
-static int saa7115_probe(struct i2c_client *client)
+static int saa7115_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	struct saa711x_state *state;
 	int	i;
--- linux-2.6.26-rc0.orig/drivers/media/video/saa7127.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/saa7127.c	2008-04-29 08:37:43.000000000 +0200
@@ -661,7 +661,8 @@ static int saa7127_command(struct i2c_cl
 
 /* ----------------------------------------------------------------------- */
 
-static int saa7127_probe(struct i2c_client *client)
+static int saa7127_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	struct saa7127_state *state;
 	struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };  /* set to disabled */
--- linux-2.6.26-rc0.orig/drivers/media/video/saa717x.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/saa717x.c	2008-04-29 08:37:43.000000000 +0200
@@ -1418,7 +1418,8 @@ static int saa717x_command(struct i2c_cl
 /* i2c implementation */
 
 /* ----------------------------------------------------------------------- */
-static int saa717x_probe(struct i2c_client *client)
+static int saa717x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
 {
 	struct saa717x_state *decoder;
 	u8 id = 0;
--- linux-2.6.26-rc0.orig/drivers/media/video/tcm825x.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tcm825x.c	2008-04-29 08:37:43.000000000 +0200
@@ -840,7 +840,8 @@ static struct v4l2_int_device tcm825x_in
 	},
 };
 
-static int tcm825x_probe(struct i2c_client *client)
+static int tcm825x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
 {
 	struct tcm825x_sensor *sensor = &tcm825x;
 	int rval;
--- linux-2.6.26-rc0.orig/drivers/media/video/tlv320aic23b.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tlv320aic23b.c	2008-04-29 08:37:43.000000000 +0200
@@ -125,7 +125,8 @@ static int tlv320aic23b_command(struct i
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int tlv320aic23b_probe(struct i2c_client *client)
+static int tlv320aic23b_probe(struct i2c_client *client,
+			      const struct i2c_device_id *id)
 {
 	struct tlv320aic23b_state *state;
 
--- linux-2.6.26-rc0.orig/drivers/media/video/tuner-core.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tuner-core.c	2008-04-29 08:37:43.000000000 +0200
@@ -1073,7 +1073,8 @@ static void tuner_lookup(struct i2c_adap
 /* During client attach, set_type is called by adapter's attach_inform callback.
    set_type must then be completed by tuner_probe.
  */
-static int tuner_probe(struct i2c_client *client)
+static int tuner_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
 {
 	struct tuner *t;
 	struct tuner *radio;
--- linux-2.6.26-rc0.orig/drivers/media/video/tvaudio.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tvaudio.c	2008-04-29 08:37:43.000000000 +0200
@@ -1461,7 +1461,7 @@ static struct CHIPDESC chiplist[] = {
 /* ---------------------------------------------------------------------- */
 /* i2c registration                                                       */
 
-static int chip_probe(struct i2c_client *client)
+static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct CHIPSTATE *chip;
 	struct CHIPDESC  *desc;
--- linux-2.6.26-rc0.orig/drivers/media/video/upd64031a.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/upd64031a.c	2008-04-29 08:37:43.000000000 +0200
@@ -195,7 +195,8 @@ static int upd64031a_command(struct i2c_
 
 /* i2c implementation */
 
-static int upd64031a_probe(struct i2c_client *client)
+static int upd64031a_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
 {
 	struct upd64031a_state *state;
 	int i;
--- linux-2.6.26-rc0.orig/drivers/media/video/upd64083.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/upd64083.c	2008-04-29 08:37:43.000000000 +0200
@@ -172,7 +172,8 @@ static int upd64083_command(struct i2c_c
 
 /* i2c implementation */
 
-static int upd64083_probe(struct i2c_client *client)
+static int upd64083_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
 {
 	struct upd64083_state *state;
 	int i;
--- linux-2.6.26-rc0.orig/drivers/media/video/v4l2-common.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/v4l2-common.c	2008-04-29 08:37:43.000000000 +0200
@@ -710,7 +710,8 @@ EXPORT_SYMBOL(v4l2_chip_ident_i2c_client
 /* Helper function for I2C legacy drivers */
 
 int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
-		const char *name, int (*probe)(struct i2c_client *))
+		const char *name,
+		int (*probe)(struct i2c_client *, const struct i2c_device_id *))
 {
 	struct i2c_client *client;
 	int err;
@@ -724,7 +725,7 @@ int v4l2_i2c_attach(struct i2c_adapter *
 	client->driver = driver;
 	strlcpy(client->name, name, sizeof(client->name));
 
-	err = probe(client);
+	err = probe(client, NULL);
 	if (err == 0) {
 		i2c_attach_client(client);
 	} else {
--- linux-2.6.26-rc0.orig/drivers/media/video/vp27smpx.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/vp27smpx.c	2008-04-29 08:37:43.000000000 +0200
@@ -121,7 +121,8 @@ static int vp27smpx_command(struct i2c_c
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int vp27smpx_probe(struct i2c_client *client)
+static int vp27smpx_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
 {
 	struct vp27smpx_state *state;
 
--- linux-2.6.26-rc0.orig/drivers/media/video/wm8739.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/wm8739.c	2008-04-29 08:37:43.000000000 +0200
@@ -261,7 +261,8 @@ static int wm8739_command(struct i2c_cli
 
 /* i2c implementation */
 
-static int wm8739_probe(struct i2c_client *client)
+static int wm8739_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	struct wm8739_state *state;
 
--- linux-2.6.26-rc0.orig/drivers/media/video/wm8775.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/wm8775.c	2008-04-29 08:37:43.000000000 +0200
@@ -159,7 +159,8 @@ static int wm8775_command(struct i2c_cli
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int wm8775_probe(struct i2c_client *client)
+static int wm8775_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	struct wm8775_state *state;
 
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1307.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1307.c	2008-04-29 08:37:43.000000000 +0200
@@ -326,7 +326,8 @@ static struct bin_attribute nvram = {
 
 static struct i2c_driver ds1307_driver;
 
-static int __devinit ds1307_probe(struct i2c_client *client)
+static int __devinit ds1307_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
 {
 	struct ds1307		*ds1307;
 	int			err = -ENODEV;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1374.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1374.c	2008-04-29 08:37:43.000000000 +0200
@@ -355,7 +355,8 @@ static const struct rtc_class_ops ds1374
 	.ioctl = ds1374_ioctl,
 };
 
-static int ds1374_probe(struct i2c_client *client)
+static int ds1374_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	struct ds1374 *ds1374;
 	int ret;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-isl1208.c	2008-04-29 07:41:16.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-isl1208.c	2008-04-29 08:50:01.000000000 +0200
@@ -490,7 +490,7 @@ isl1208_sysfs_unregister(struct device *
 }
 
 static int
-isl1208_probe(struct i2c_client *client)
+isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	int rc = 0;
 	struct rtc_device *rtc;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-m41t80.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-m41t80.c	2008-04-29 08:37:43.000000000 +0200
@@ -756,7 +756,8 @@ static struct notifier_block wdt_notifie
  *
  *****************************************************************************
  */
-static int m41t80_probe(struct i2c_client *client)
+static int m41t80_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	int i, rc = 0;
 	struct rtc_device *rtc = NULL;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-pcf8563.c	2008-04-29 07:41:16.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-pcf8563.c	2008-04-29 08:49:41.000000000 +0200
@@ -246,7 +246,8 @@ static const struct rtc_class_ops pcf856
 	.set_time	= pcf8563_rtc_set_time,
 };
 
-static int pcf8563_probe(struct i2c_client *client)
+static int pcf8563_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
 {
 	struct pcf8563 *pcf8563;
 
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-rs5c372.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-rs5c372.c	2008-04-29 08:37:43.000000000 +0200
@@ -494,7 +494,8 @@ static void rs5c_sysfs_unregister(struct
 
 static struct i2c_driver rs5c372_driver;
 
-static int rs5c372_probe(struct i2c_client *client)
+static int rs5c372_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	int err = 0;
 	struct rs5c372 *rs5c372;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-s35390a.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-s35390a.c	2008-04-29 08:37:43.000000000 +0200
@@ -195,7 +195,8 @@ static const struct rtc_class_ops s35390
 
 static struct i2c_driver s35390a_driver;
 
-static int s35390a_probe(struct i2c_client *client)
+static int s35390a_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	int err;
 	unsigned int i;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-x1205.c	2008-04-29 07:41:16.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-x1205.c	2008-04-29 08:48:52.000000000 +0200
@@ -494,7 +494,8 @@ static void x1205_sysfs_unregister(struc
 }
 
 
-static int x1205_probe(struct i2c_client *client)
+static int x1205_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	int err = 0;
 	unsigned char sr;
--- linux-2.6.26-rc0.orig/include/linux/i2c.h	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/include/linux/i2c.h	2008-04-29 08:37:43.000000000 +0200
@@ -126,7 +126,7 @@ struct i2c_driver {
 	 * With the driver model, device enumeration is NEVER done by drivers;
 	 * it's done by infrastructure.  (NEW STYLE DRIVERS ONLY)
 	 */
-	int (*probe)(struct i2c_client *);
+	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
 	int (*remove)(struct i2c_client *);
 
 	/* driver model interfaces that don't relate to enumeration  */
@@ -140,11 +140,10 @@ struct i2c_driver {
 	int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
 
 	struct device_driver driver;
+	const struct i2c_device_id *id_table;
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
-#define I2C_NAME_SIZE	20
-
 /**
  * struct i2c_client - represent an I2C slave device
  * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
--- linux-2.6.26-rc0.orig/include/linux/mod_devicetable.h	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/include/linux/mod_devicetable.h	2008-04-29 08:37:43.000000000 +0200
@@ -368,4 +368,15 @@ struct virtio_device_id {
 };
 #define VIRTIO_DEV_ANY_ID	0xffffffff
 
+/* i2c */
+
+#define I2C_NAME_SIZE	20
+#define I2C_MODULE_PREFIX "i2c:"
+
+struct i2c_device_id {
+	char name[I2C_NAME_SIZE];
+	kernel_ulong_t driver_data;	/* Data private to the driver */
+};
+
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
--- linux-2.6.26-rc0.orig/include/media/v4l2-common.h	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/include/media/v4l2-common.h	2008-04-29 08:37:43.000000000 +0200
@@ -107,9 +107,11 @@ int v4l2_chip_match_host(u32 id_type, u3
 struct i2c_driver;
 struct i2c_adapter;
 struct i2c_client;
+struct i2c_device_id;
 
 int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
-		const char *name, int (*probe)(struct i2c_client *));
+		const char *name,
+		int (*probe)(struct i2c_client *, const struct i2c_device_id *));
 
 /* ------------------------------------------------------------------------- */
 
--- linux-2.6.26-rc0.orig/include/media/v4l2-i2c-drv-legacy.h	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/include/media/v4l2-i2c-drv-legacy.h	2008-04-29 08:37:43.000000000 +0200
@@ -25,7 +25,7 @@ struct v4l2_i2c_driver_data {
 	const char * const name;
 	int driverid;
 	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
-	int (*probe)(struct i2c_client *client);
+	int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
 	int (*remove)(struct i2c_client *client);
 	int (*suspend)(struct i2c_client *client, pm_message_t state);
 	int (*resume)(struct i2c_client *client);
--- linux-2.6.26-rc0.orig/include/media/v4l2-i2c-drv.h	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/include/media/v4l2-i2c-drv.h	2008-04-29 08:37:43.000000000 +0200
@@ -30,7 +30,7 @@ struct v4l2_i2c_driver_data {
 	const char * const name;
 	int driverid;
 	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
-	int (*probe)(struct i2c_client *client);
+	int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
 	int (*remove)(struct i2c_client *client);
 	int (*suspend)(struct i2c_client *client, pm_message_t state);
 	int (*resume)(struct i2c_client *client);
--- linux-2.6.26-rc0.orig/scripts/mod/file2alias.c	2008-04-29 08:13:00.000000000 +0200
+++ linux-2.6.26-rc0/scripts/mod/file2alias.c	2008-04-29 08:37:43.000000000 +0200
@@ -576,6 +576,15 @@ static int do_virtio_entry(const char *f
 	return 1;
 }
 
+/* Looks like: i2c:S */
+static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
+			char *alias)
+{
+	sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
+
+	return 1;
+}
+
 /* Ignore any prefix, eg. v850 prepends _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -704,6 +713,10 @@ void handle_moddevtable(struct module *m
 		do_table(symval, sym->st_size,
 			 sizeof(struct virtio_device_id), "virtio",
 			 do_virtio_entry, mod);
+	else if (sym_is(symname, "__mod_i2c_device_table"))
+		do_table(symval, sym->st_size,
+			 sizeof(struct i2c_device_id), "i2c",
+			 do_i2c_entry, mod);
 	free(zeros);
 }
 

-- 
Jean Delvare

^ permalink raw reply

* [PATCH 2/2 v2] i2c: Convert most new-style drivers to use module aliasing
From: Jean Delvare @ 2008-04-29 10:47 UTC (permalink / raw)
  To: Linux I2C
  Cc: Laurent, Sievers, linuxppc-dev list, Paul Mundt, Scott Wood, Kay
In-Reply-To: <20080429124241.08e18ae3@hyperion.delvare>

Based on earlier work by Jon Smirl and Jochen Friedrich.

Update most new-style i2c drivers to use standard module aliasing
instead of the old driver_name/type driver matching scheme. I've
left the video drivers apart (except for SoC camera drivers) as
they're a bit more diffcult to deal with, they'll have their own
patch later.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Jon Smirl <jonsmirl@gmail.com>
Cc: Jochen Friedrich <jochen@scram.de>
---
 arch/arm/mach-at91/board-csb337.c         |    3 -
 arch/arm/mach-at91/board-dk.c             |    3 -
 arch/arm/mach-at91/board-eb9200.c         |    3 -
 arch/arm/mach-iop32x/em7210.c             |    3 -
 arch/arm/mach-iop32x/glantank.c           |    4 -
 arch/arm/mach-iop32x/n2100.c              |    4 -
 arch/arm/mach-ixp4xx/dsmg600-setup.c      |    2 
 arch/arm/mach-ixp4xx/nas100d-setup.c      |    2 
 arch/arm/mach-ixp4xx/nslu2-setup.c        |    2 
 arch/arm/mach-omap1/board-h2.c            |    2 
 arch/arm/mach-omap1/board-h3.c            |    3 -
 arch/arm/mach-omap1/board-osk.c           |    1 
 arch/arm/mach-orion5x/db88f5281-setup.c   |    4 -
 arch/arm/mach-orion5x/dns323-setup.c      |    7 --
 arch/arm/mach-orion5x/kurobox_pro-setup.c |    4 -
 arch/arm/mach-orion5x/rd88f5182-setup.c   |    4 -
 arch/arm/mach-orion5x/ts209-setup.c       |    3 -
 arch/arm/mach-pxa/pcm990-baseboard.c      |    5 -
 arch/blackfin/mach-bf533/boards/stamp.c   |    3 -
 arch/blackfin/mach-bf537/boards/stamp.c   |    3 -
 arch/blackfin/mach-bf548/boards/ezkit.c   |    2 
 arch/powerpc/sysdev/fsl_soc.c             |   27 ++++------
 arch/sh/boards/renesas/migor/setup.c      |    3 -
 arch/sh/boards/renesas/r7780rp/setup.c    |    3 -
 drivers/gpio/pca953x.c                    |   23 +-------
 drivers/gpio/pcf857x.c                    |   33 +++++++-----
 drivers/hwmon/f75375s.c                   |   23 ++++----
 drivers/i2c/busses/i2c-taos-evm.c         |    3 -
 drivers/i2c/chips/ds1682.c                |    7 ++
 drivers/i2c/chips/menelaus.c              |    7 ++
 drivers/i2c/chips/tps65010.c              |   29 ++++------
 drivers/i2c/chips/tsl2550.c               |    7 ++
 drivers/media/video/mt9m001.c             |    7 ++
 drivers/media/video/mt9v022.c             |    7 ++
 drivers/rtc/rtc-ds1307.c                  |   63 +++++++++--------------
 drivers/rtc/rtc-ds1374.c                  |    7 ++
 drivers/rtc/rtc-isl1208.c                 |    7 ++
 drivers/rtc/rtc-m41t80.c                  |   78 +++++++----------------------
 drivers/rtc/rtc-pcf8563.c                 |    7 ++
 drivers/rtc/rtc-rs5c372.c                 |   24 ++++----
 drivers/rtc/rtc-s35390a.c                 |    7 ++
 drivers/rtc/rtc-x1205.c                   |    7 ++
 include/linux/i2c.h                       |   12 ++--
 43 files changed, 211 insertions(+), 247 deletions(-)

--- linux-2.6.26-rc0.orig/arch/arm/mach-at91/board-csb337.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-at91/board-csb337.c	2008-04-29 08:55:08.000000000 +0200
@@ -79,8 +79,7 @@ static struct at91_udc_data __initdata c
 
 static struct i2c_board_info __initdata csb337_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("rtc-ds1307", 0x68),
-		.type	= "ds1307",
+		I2C_BOARD_INFO("ds1307", 0x68),
 	},
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-at91/board-dk.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-at91/board-dk.c	2008-04-29 08:55:08.000000000 +0200
@@ -132,8 +132,7 @@ static struct i2c_board_info __initdata 
 		I2C_BOARD_INFO("x9429", 0x28),
 	},
 	{
-		I2C_BOARD_INFO("at24c", 0x50),
-		.type	= "24c1024",
+		I2C_BOARD_INFO("24c1024", 0x50),
 	}
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-at91/board-eb9200.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-at91/board-eb9200.c	2008-04-29 08:55:08.000000000 +0200
@@ -93,8 +93,7 @@ static struct at91_mmc_data __initdata e
 
 static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("at24c", 0x50),
-		.type	= "24c512",
+		I2C_BOARD_INFO("24c512", 0x50),
 	},
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-iop32x/em7210.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-iop32x/em7210.c	2008-04-29 08:55:08.000000000 +0200
@@ -50,8 +50,7 @@ static struct sys_timer em7210_timer = {
  */
 static struct i2c_board_info __initdata em7210_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-		.type = "rs5c372a",
+		I2C_BOARD_INFO("rs5c372a", 0x32),
 	},
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-iop32x/glantank.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-iop32x/glantank.c	2008-04-29 08:55:08.000000000 +0200
@@ -176,12 +176,10 @@ static struct f75375s_platform_data glan
 
 static struct i2c_board_info __initdata glantank_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-		.type = "rs5c372a",
+		I2C_BOARD_INFO("rs5c372a", 0x32),
 	},
 	{
 		I2C_BOARD_INFO("f75375", 0x2e),
-		.type = "f75375",
 		.platform_data = &glantank_f75375s,
 	},
 };
--- linux-2.6.26-rc0.orig/arch/arm/mach-iop32x/n2100.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-iop32x/n2100.c	2008-04-29 08:55:08.000000000 +0200
@@ -208,12 +208,10 @@ static struct f75375s_platform_data n210
 
 static struct i2c_board_info __initdata n2100_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-		.type = "rs5c372b",
+		I2C_BOARD_INFO("rs5c372b", 0x32),
 	},
 	{
 		I2C_BOARD_INFO("f75375", 0x2e),
-		.type = "f75375",
 		.platform_data = &n2100_f75375s,
 	},
 };
--- linux-2.6.26-rc0.orig/arch/arm/mach-ixp4xx/dsmg600-setup.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-ixp4xx/dsmg600-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -65,7 +65,7 @@ static struct platform_device dsmg600_i2
 
 static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
 	{
-		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+		I2C_BOARD_INFO("pcf8563", 0x51),
 	},
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-ixp4xx/nas100d-setup.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-ixp4xx/nas100d-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -54,7 +54,7 @@ static struct platform_device nas100d_fl
 
 static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
 	{
-		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+		I2C_BOARD_INFO("pcf8563", 0x51),
 	},
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-ixp4xx/nslu2-setup.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-ixp4xx/nslu2-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -57,7 +57,7 @@ static struct i2c_gpio_platform_data nsl
 
 static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
 	{
-		I2C_BOARD_INFO("rtc-x1205", 0x6f),
+		I2C_BOARD_INFO("x1205", 0x6f),
 	},
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-omap1/board-h2.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-omap1/board-h2.c	2008-04-29 08:55:08.000000000 +0200
@@ -351,11 +351,9 @@ static void __init h2_init_smc91x(void)
 static struct i2c_board_info __initdata h2_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("tps65010", 0x48),
-		.type           = "tps65010",
 		.irq            = OMAP_GPIO_IRQ(58),
 	}, {
 		I2C_BOARD_INFO("isp1301_omap", 0x2d),
-		.type		= "isp1301_omap",
 		.irq		= OMAP_GPIO_IRQ(2),
 	},
 };
--- linux-2.6.26-rc0.orig/arch/arm/mach-omap1/board-h3.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-omap1/board-h3.c	2008-04-29 08:55:08.000000000 +0200
@@ -473,8 +473,7 @@ static struct omap_board_config_kernel h
 
 static struct i2c_board_info __initdata h3_i2c_board_info[] = {
        {
-               I2C_BOARD_INFO("tps65010", 0x48),
-               .type           = "tps65013",
+		I2C_BOARD_INFO("tps65013", 0x48),
                /* .irq         = OMAP_GPIO_IRQ(??), */
        },
 };
--- linux-2.6.26-rc0.orig/arch/arm/mach-omap1/board-osk.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-omap1/board-osk.c	2008-04-29 08:55:08.000000000 +0200
@@ -254,7 +254,6 @@ static struct tps65010_board tps_board =
 static struct i2c_board_info __initdata osk_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("tps65010", 0x48),
-		.type		= "tps65010",
 		.irq		= OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
 		.platform_data	= &tps_board,
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/db88f5281-setup.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/db88f5281-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -292,9 +292,7 @@ static struct mv643xx_eth_platform_data 
  * RTC DS1339 on I2C bus
  ****************************************************************************/
 static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
-	.driver_name	= "rtc-ds1307",
-	.type		= "ds1339",
-	.addr		= 0x68,
+	I2C_BOARD_INFO("ds1339", 0x68),
 };
 
 /*****************************************************************************
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/dns323-setup.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/dns323-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -220,19 +220,16 @@ static struct platform_device *dns323_pl
 static struct i2c_board_info __initdata dns323_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("g760a", 0x3e),
-		.type = "g760a",
 	},
 #if 0
 	/* this entry requires the new-style driver model lm75 driver,
 	 * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
 	{
-		I2C_BOARD_INFO("lm75", 0x48),
-		.type = "g751",
+		I2C_BOARD_INFO("g751", 0x48),
 	},
 #endif
 	{
-		I2C_BOARD_INFO("rtc-m41t80", 0x68),
-		.type = "m41t80",
+		I2C_BOARD_INFO("m41t80", 0x68),
 	}
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/kurobox_pro-setup.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/kurobox_pro-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -162,9 +162,7 @@ static struct mv643xx_eth_platform_data 
  * RTC 5C372a on I2C bus
  ****************************************************************************/
 static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
-       .driver_name    = "rtc-rs5c372",
-       .type           = "rs5c372a",
-       .addr           = 0x32,
+	I2C_BOARD_INFO("rs5c372a", 0x32),
 };
 
 /*****************************************************************************
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/rd88f5182-setup.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/rd88f5182-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -224,9 +224,7 @@ static struct mv643xx_eth_platform_data 
  * RTC DS1338 on I2C bus
  ****************************************************************************/
 static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
-	.driver_name	= "rtc-ds1307",
-	.type		= "ds1338",
-	.addr		= 0x68,
+	I2C_BOARD_INFO("ds1338", 0x68),
 };
 
 /*****************************************************************************
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/ts209-setup.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/ts209-setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -276,8 +276,7 @@ static void __init ts209_find_mac_addr(v
 #define TS209_RTC_GPIO	3
 
 static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
-       .driver_name = "rtc-s35390a",
-       .addr        = 0x30,
+	I2C_BOARD_INFO("s35390a", 0x30),
        .irq         = 0,
 };
 
--- linux-2.6.26-rc0.orig/arch/arm/mach-pxa/pcm990-baseboard.c	2008-04-29 07:40:33.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-pxa/pcm990-baseboard.c	2008-04-29 08:55:08.000000000 +0200
@@ -320,16 +320,13 @@ static struct soc_camera_link iclink[] =
 static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
 	{
 		/* Must initialize before the camera(s) */
-		I2C_BOARD_INFO("pca953x", 0x41),
-		.type = "pca9536",
+		I2C_BOARD_INFO("pca9536", 0x41),
 		.platform_data = &pca9536_data,
 	}, {
 		I2C_BOARD_INFO("mt9v022", 0x48),
-		.type = "mt9v022",
 		.platform_data = &iclink[0], /* With extender */
 	}, {
 		I2C_BOARD_INFO("mt9m001", 0x5d),
-		.type = "mt9m001",
 		.platform_data = &iclink[0], /* With extender */
 	},
 };
--- linux-2.6.26-rc0.orig/arch/blackfin/mach-bf533/boards/stamp.c	2008-04-29 07:40:34.000000000 +0200
+++ linux-2.6.26-rc0/arch/blackfin/mach-bf533/boards/stamp.c	2008-04-29 08:55:08.000000000 +0200
@@ -499,20 +499,17 @@ static struct i2c_board_info __initdata 
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
 	{
 		I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-		.type = "ad7142_joystick",
 		.irq = 39,
 	},
 #endif
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-		.type = "pcf8574_lcd",
 	},
 #endif
 #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-		.type = "pcf8574_keypad",
 		.irq = 39,
 	},
 #endif
--- linux-2.6.26-rc0.orig/arch/blackfin/mach-bf537/boards/stamp.c	2008-04-29 07:40:34.000000000 +0200
+++ linux-2.6.26-rc0/arch/blackfin/mach-bf537/boards/stamp.c	2008-04-29 08:55:08.000000000 +0200
@@ -751,20 +751,17 @@ static struct i2c_board_info __initdata 
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
 	{
 		I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-		.type = "ad7142_joystick",
 		.irq = 55,
 	},
 #endif
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-		.type = "pcf8574_lcd",
 	},
 #endif
 #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-		.type = "pcf8574_keypad",
 		.irq = 72,
 	},
 #endif
--- linux-2.6.26-rc0.orig/arch/blackfin/mach-bf548/boards/ezkit.c	2008-04-29 07:40:34.000000000 +0200
+++ linux-2.6.26-rc0/arch/blackfin/mach-bf548/boards/ezkit.c	2008-04-29 08:55:08.000000000 +0200
@@ -641,13 +641,11 @@ static struct i2c_board_info __initdata 
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-		.type = "pcf8574_lcd",
 	},
 #endif
 #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-		.type = "pcf8574_keypad",
 		.irq = 212,
 	},
 #endif
--- linux-2.6.26-rc0.orig/arch/powerpc/sysdev/fsl_soc.c	2008-04-29 07:40:39.000000000 +0200
+++ linux-2.6.26-rc0/arch/powerpc/sysdev/fsl_soc.c	2008-04-29 08:55:08.000000000 +0200
@@ -418,22 +418,21 @@ arch_initcall(gfar_of_init);
 #include <linux/i2c.h>
 struct i2c_driver_device {
 	char	*of_device;
-	char	*i2c_driver;
 	char	*i2c_type;
 };
 
 static struct i2c_driver_device i2c_devices[] __initdata = {
-	{"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},
-	{"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
-	{"ricoh,rv5c386",  "rtc-rs5c372", "rv5c386",},
-	{"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
-	{"dallas,ds1307",  "rtc-ds1307",  "ds1307",},
-	{"dallas,ds1337",  "rtc-ds1307",  "ds1337",},
-	{"dallas,ds1338",  "rtc-ds1307",  "ds1338",},
-	{"dallas,ds1339",  "rtc-ds1307",  "ds1339",},
-	{"dallas,ds1340",  "rtc-ds1307",  "ds1340",},
-	{"stm,m41t00",     "rtc-ds1307",  "m41t00"},
-	{"dallas,ds1374",  "rtc-ds1374",  "rtc-ds1374",},
+	{"ricoh,rs5c372a", "rs5c372a"},
+	{"ricoh,rs5c372b", "rs5c372b"},
+	{"ricoh,rv5c386",  "rv5c386"},
+	{"ricoh,rv5c387a", "rv5c387a"},
+	{"dallas,ds1307",  "ds1307"},
+	{"dallas,ds1337",  "ds1337"},
+	{"dallas,ds1338",  "ds1338"},
+	{"dallas,ds1339",  "ds1339"},
+	{"dallas,ds1340",  "ds1340"},
+	{"stm,m41t00",     "m41t00"},
+	{"dallas,ds1374",  "rtc-ds1374"},
 };
 
 static int __init of_find_i2c_driver(struct device_node *node,
@@ -444,9 +443,7 @@ static int __init of_find_i2c_driver(str
 	for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
 		if (!of_device_is_compatible(node, i2c_devices[i].of_device))
 			continue;
-		if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
-			    KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
-		    strlcpy(info->type, i2c_devices[i].i2c_type,
+		if (strlcpy(info->type, i2c_devices[i].i2c_type,
 			    I2C_NAME_SIZE) >= I2C_NAME_SIZE)
 			return -ENOMEM;
 		return 0;
--- linux-2.6.26-rc0.orig/arch/sh/boards/renesas/migor/setup.c	2008-04-29 07:40:40.000000000 +0200
+++ linux-2.6.26-rc0/arch/sh/boards/renesas/migor/setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -199,8 +199,7 @@ static struct platform_device *migor_dev
 
 static struct i2c_board_info __initdata migor_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-		.type   = "rs5c372b",
+		I2C_BOARD_INFO("rs5c372b", 0x32),
 	},
 	{
 		I2C_BOARD_INFO("migor_ts", 0x51),
--- linux-2.6.26-rc0.orig/arch/sh/boards/renesas/r7780rp/setup.c	2008-04-29 07:40:41.000000000 +0200
+++ linux-2.6.26-rc0/arch/sh/boards/renesas/r7780rp/setup.c	2008-04-29 08:55:08.000000000 +0200
@@ -199,8 +199,7 @@ static struct platform_device smbus_devi
 
 static struct i2c_board_info __initdata highlander_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-		.type	= "r2025sd",
+		I2C_BOARD_INFO("r2025sd", 0x32),
 	},
 };
 
--- linux-2.6.26-rc0.orig/drivers/gpio/pca953x.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pca953x.c	2008-04-29 08:55:08.000000000 +0200
@@ -23,13 +23,7 @@
 #define PCA953X_INVERT         2
 #define PCA953X_DIRECTION      3
 
-/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */
-struct pca953x_desc {
-	char		name[I2C_NAME_SIZE];
-	unsigned long	driver_data;
-};
-
-static const struct pca953x_desc pca953x_descs[] = {
+static const struct i2c_device_id pca953x_id[] = {
 	{ "pca9534", 8, },
 	{ "pca9535", 16, },
 	{ "pca9536", 4, },
@@ -37,7 +31,9 @@ static const struct pca953x_desc pca953x
 	{ "pca9538", 8, },
 	{ "pca9539", 16, },
 	/* REVISIT several pca955x parts should work here too */
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
 struct pca953x_chip {
 	unsigned gpio_start;
@@ -193,26 +189,16 @@ static void pca953x_setup_gpio(struct pc
 }
 
 static int __devinit pca953x_probe(struct i2c_client *client,
-				   const struct i2c_device_id *did)
+				   const struct i2c_device_id *id)
 {
 	struct pca953x_platform_data *pdata;
 	struct pca953x_chip *chip;
 	int ret, i;
-	const struct pca953x_desc *id = NULL;
 
 	pdata = client->dev.platform_data;
 	if (pdata == NULL)
 		return -ENODEV;
 
-	/* this loop vanishes when we get i2c_device_id */
-	for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++)
-		if (!strcmp(pca953x_descs[i].name, client->name)) {
-			id = pca953x_descs + i;
-			break;
-		}
-	if (!id)
-		return -ENODEV;
-
 	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
@@ -292,6 +278,7 @@ static struct i2c_driver pca953x_driver 
 	},
 	.probe		= pca953x_probe,
 	.remove		= pca953x_remove,
+	.id_table	= pca953x_id,
 };
 
 static int __init pca953x_init(void)
--- linux-2.6.26-rc0.orig/drivers/gpio/pcf857x.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pcf857x.c	2008-04-29 08:55:08.000000000 +0200
@@ -26,6 +26,21 @@
 #include <asm/gpio.h>
 
 
+static const struct i2c_device_id pcf857x_id[] = {
+	{ "pcf8574", 8 },
+	{ "pca8574", 8 },
+	{ "pca9670", 8 },
+	{ "pca9672", 8 },
+	{ "pca9674", 8 },
+	{ "pcf8575", 16 },
+	{ "pca8575", 16 },
+	{ "pca9671", 16 },
+	{ "pca9673", 16 },
+	{ "pca9675", 16 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pcf857x_id);
+
 /*
  * The pcf857x, pca857x, and pca967x chips only expose one read and one
  * write register.  Writing a "one" bit (to match the reset state) lets
@@ -173,13 +188,8 @@ static int pcf857x_probe(struct i2c_clie
 	 *
 	 * NOTE: we don't distinguish here between *4 and *4a parts.
 	 */
-	if (strcmp(client->name, "pcf8574") == 0
-			|| strcmp(client->name, "pca8574") == 0
-			|| strcmp(client->name, "pca9670") == 0
-			|| strcmp(client->name, "pca9672") == 0
-			|| strcmp(client->name, "pca9674") == 0
-			) {
-		gpio->chip.ngpio = 8;
+	gpio->chip.ngpio = id->driver_data;
+	if (gpio->chip.ngpio == 8) {
 		gpio->chip.direction_input = pcf857x_input8;
 		gpio->chip.get = pcf857x_get8;
 		gpio->chip.direction_output = pcf857x_output8;
@@ -199,13 +209,7 @@ static int pcf857x_probe(struct i2c_clie
 	 *
 	 * NOTE: we don't distinguish here between '75 and '75c parts.
 	 */
-	} else if (strcmp(client->name, "pcf8575") == 0
-			|| strcmp(client->name, "pca8575") == 0
-			|| strcmp(client->name, "pca9671") == 0
-			|| strcmp(client->name, "pca9673") == 0
-			|| strcmp(client->name, "pca9675") == 0
-			) {
-		gpio->chip.ngpio = 16;
+	} else if (gpio->chip.ngpio == 16) {
 		gpio->chip.direction_input = pcf857x_input16;
 		gpio->chip.get = pcf857x_get16;
 		gpio->chip.direction_output = pcf857x_output16;
@@ -314,6 +318,7 @@ static struct i2c_driver pcf857x_driver 
 	},
 	.probe	= pcf857x_probe,
 	.remove	= pcf857x_remove,
+	.id_table = pcf857x_id,
 };
 
 static int __init pcf857x_init(void)
--- linux-2.6.26-rc0.orig/drivers/hwmon/f75375s.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/hwmon/f75375s.c	2008-04-29 08:55:08.000000000 +0200
@@ -129,12 +129,20 @@ static struct i2c_driver f75375_legacy_d
 	.detach_client = f75375_detach_client,
 };
 
+static const struct i2c_device_id f75375_id[] = {
+	{ "f75373", f75373 },
+	{ "f75375", f75375 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, f75375_id);
+
 static struct i2c_driver f75375_driver = {
 	.driver = {
 		.name = "f75375",
 	},
 	.probe = f75375_probe,
 	.remove = f75375_remove,
+	.id_table = f75375_id,
 };
 
 static inline int f75375_read8(struct i2c_client *client, u8 reg)
@@ -645,15 +653,7 @@ static int f75375_probe(struct i2c_clien
 	i2c_set_clientdata(client, data);
 	data->client = client;
 	mutex_init(&data->update_lock);
-
-	if (strcmp(client->name, "f75375") == 0)
-		data->kind = f75375;
-	else if (strcmp(client->name, "f75373") == 0)
-		data->kind = f75373;
-	else {
-		dev_err(&client->dev, "Unsupported device: %s\n", client->name);
-		return -ENODEV;
-	}
+	data->kind = id->driver_data;
 
 	if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
 		goto exit_free;
@@ -714,6 +714,7 @@ static int f75375_detect(struct i2c_adap
 	u8 version = 0;
 	int err = 0;
 	const char *name = "";
+	struct i2c_device_id id;
 
 	if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
 		err = -ENOMEM;
@@ -750,7 +751,9 @@ static int f75375_detect(struct i2c_adap
 	if ((err = i2c_attach_client(client)))
 		goto exit_free;
 
-	if ((err = f75375_probe(client, NULL)) < 0)
+	strlcpy(id.name, name, I2C_NAME_SIZE);
+	id.driver_data = kind;
+	if ((err = f75375_probe(client, &id)) < 0)
 		goto exit_detach;
 
 	return 0;
--- linux-2.6.26-rc0.orig/drivers/i2c/busses/i2c-taos-evm.c	2008-04-28 22:58:32.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/busses/i2c-taos-evm.c	2008-04-29 08:55:08.000000000 +0200
@@ -51,7 +51,6 @@ struct taos_data {
 /* TAOS TSL2550 EVM */
 static struct i2c_board_info tsl2550_info = {
 	I2C_BOARD_INFO("tsl2550", 0x39),
-	.type	= "tsl2550",
 };
 
 /* Instantiate i2c devices based on the adapter name */
@@ -59,7 +58,7 @@ static struct i2c_client *taos_instantia
 {
 	if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) {
 		dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n",
-			tsl2550_info.driver_name, tsl2550_info.addr);
+			tsl2550_info.type, tsl2550_info.addr);
 		return i2c_new_device(adapter, &tsl2550_info);
 	}
 
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/ds1682.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/ds1682.c	2008-04-29 08:55:08.000000000 +0200
@@ -235,12 +235,19 @@ static int ds1682_remove(struct i2c_clie
 	return 0;
 }
 
+static const struct i2c_device_id ds1682_id[] = {
+	{ "ds1682", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ds1682_id);
+
 static struct i2c_driver ds1682_driver = {
 	.driver = {
 		.name = "ds1682",
 	},
 	.probe = ds1682_probe,
 	.remove = ds1682_remove,
+	.id_table = ds1682_id,
 };
 
 static int __init ds1682_init(void)
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/menelaus.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/menelaus.c	2008-04-29 08:55:08.000000000 +0200
@@ -1243,12 +1243,19 @@ static int __exit menelaus_remove(struct
 	return 0;
 }
 
+static const struct i2c_device_id menelaus_id[] = {
+	{ "menelaus", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, menelaus_id);
+
 static struct i2c_driver menelaus_i2c_driver = {
 	.driver = {
 		.name		= DRIVER_NAME,
 	},
 	.probe		= menelaus_probe,
 	.remove		= __exit_p(menelaus_remove),
+	.id_table	= menelaus_id,
 };
 
 static int __init menelaus_init(void)
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tps65010.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tps65010.c	2008-04-29 08:55:08.000000000 +0200
@@ -64,7 +64,6 @@ static struct i2c_driver tps65010_driver
  * as part of board setup by a bootloader.
  */
 enum tps_model {
-	TPS_UNKNOWN = 0,
 	TPS65010,
 	TPS65011,
 	TPS65012,
@@ -554,20 +553,7 @@ static int tps65010_probe(struct i2c_cli
 	mutex_init(&tps->lock);
 	INIT_DELAYED_WORK(&tps->work, tps65010_work);
 	tps->client = client;
-
-	if (strcmp(client->name, "tps65010") == 0)
-		tps->model = TPS65010;
-	else if (strcmp(client->name, "tps65011") == 0)
-		tps->model = TPS65011;
-	else if (strcmp(client->name, "tps65012") == 0)
-		tps->model = TPS65012;
-	else if (strcmp(client->name, "tps65013") == 0)
-		tps->model = TPS65013;
-	else {
-		dev_warn(&client->dev, "unknown chip '%s'\n", client->name);
-		status = -ENODEV;
-		goto fail1;
-	}
+	tps->model = id->driver_data;
 
 	/* the IRQ is active low, but many gpio lines can't support that
 	 * so this driver uses falling-edge triggers instead.
@@ -596,9 +582,6 @@ static int tps65010_probe(struct i2c_cli
 	case TPS65012:
 		tps->por = 1;
 		break;
-	case TPS_UNKNOWN:
-		printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME);
-		break;
 	/* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
 	}
 	tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG);
@@ -685,12 +668,22 @@ fail1:
 	return status;
 }
 
+static const struct i2c_device_id tps65010_id[] = {
+	{ "tps65010", TPS65010 },
+	{ "tps65011", TPS65011 },
+	{ "tps65012", TPS65012 },
+	{ "tps65013", TPS65013 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tps65010_id);
+
 static struct i2c_driver tps65010_driver = {
 	.driver = {
 		.name	= "tps65010",
 	},
 	.probe	= tps65010_probe,
 	.remove	= __exit_p(tps65010_remove),
+	.id_table = tps65010_id,
 };
 
 /*-------------------------------------------------------------------------*/
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tsl2550.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tsl2550.c	2008-04-29 08:55:08.000000000 +0200
@@ -452,6 +452,12 @@ static int tsl2550_resume(struct i2c_cli
 
 #endif /* CONFIG_PM */
 
+static const struct i2c_device_id tsl2550_id[] = {
+	{ "tsl2550", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tsl2550_id);
+
 static struct i2c_driver tsl2550_driver = {
 	.driver = {
 		.name	= TSL2550_DRV_NAME,
@@ -461,6 +467,7 @@ static struct i2c_driver tsl2550_driver 
 	.resume	= tsl2550_resume,
 	.probe	= tsl2550_probe,
 	.remove	= __devexit_p(tsl2550_remove),
+	.id_table = tsl2550_id,
 };
 
 static int __init tsl2550_init(void)
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9m001.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9m001.c	2008-04-29 08:55:08.000000000 +0200
@@ -697,12 +697,19 @@ static int mt9m001_remove(struct i2c_cli
 	return 0;
 }
 
+static const struct i2c_device_id mt9m001_id[] = {
+	{ "mt9m001", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m001_id);
+
 static struct i2c_driver mt9m001_i2c_driver = {
 	.driver = {
 		.name = "mt9m001",
 	},
 	.probe		= mt9m001_probe,
 	.remove		= mt9m001_remove,
+	.id_table	= mt9m001_id,
 };
 
 static int __init mt9m001_mod_init(void)
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9v022.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9v022.c	2008-04-29 08:55:08.000000000 +0200
@@ -819,12 +819,19 @@ static int mt9v022_remove(struct i2c_cli
 	return 0;
 }
 
+static const struct i2c_device_id mt9v022_id[] = {
+	{ "mt9v022", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v022_id);
+
 static struct i2c_driver mt9v022_i2c_driver = {
 	.driver = {
 		.name = "mt9v022",
 	},
 	.probe		= mt9v022_probe,
 	.remove		= mt9v022_remove,
+	.id_table	= mt9v022_id,
 };
 
 static int __init mt9v022_mod_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1307.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1307.c	2008-04-29 08:55:08.000000000 +0200
@@ -99,45 +99,38 @@ struct ds1307 {
 };
 
 struct chip_desc {
-	char			name[9];
 	unsigned		nvram56:1;
 	unsigned		alarm:1;
-	enum ds_type		type;
 };
 
-static const struct chip_desc chips[] = { {
-	.name		= "ds1307",
-	.type		= ds_1307,
+static const struct chip_desc chips[] = {
+[ds_1307] = {
 	.nvram56	= 1,
-}, {
-	.name		= "ds1337",
-	.type		= ds_1337,
+},
+[ds_1337] = {
 	.alarm		= 1,
-}, {
-	.name		= "ds1338",
-	.type		= ds_1338,
+},
+[ds_1338] = {
 	.nvram56	= 1,
-}, {
-	.name		= "ds1339",
-	.type		= ds_1339,
+},
+[ds_1339] = {
 	.alarm		= 1,
-}, {
-	.name		= "ds1340",
-	.type		= ds_1340,
-}, {
-	.name		= "m41t00",
-	.type		= m41t00,
+},
+[ds_1340] = {
+},
+[m41t00] = {
 }, };
 
-static inline const struct chip_desc *find_chip(const char *s)
-{
-	unsigned i;
-
-	for (i = 0; i < ARRAY_SIZE(chips); i++)
-		if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0)
-			return &chips[i];
-	return NULL;
-}
+static const struct i2c_device_id ds1307_id[] = {
+	{ "ds1307", ds_1307 },
+	{ "ds1337", ds_1337 },
+	{ "ds1338", ds_1338 },
+	{ "ds1339", ds_1339 },
+	{ "ds1340", ds_1340 },
+	{ "m41t00", m41t00 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ds1307_id);
 
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
@@ -332,16 +325,9 @@ static int __devinit ds1307_probe(struct
 	struct ds1307		*ds1307;
 	int			err = -ENODEV;
 	int			tmp;
-	const struct chip_desc	*chip;
+	const struct chip_desc	*chip = &chips[id->driver_data];
 	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
 
-	chip = find_chip(client->name);
-	if (!chip) {
-		dev_err(&client->dev, "unknown chip type '%s'\n",
-				client->name);
-		return -ENODEV;
-	}
-
 	if (!i2c_check_functionality(adapter,
 			I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
 		return -EIO;
@@ -362,7 +348,7 @@ static int __devinit ds1307_probe(struct
 	ds1307->msg[1].len = sizeof(ds1307->regs);
 	ds1307->msg[1].buf = ds1307->regs;
 
-	ds1307->type = chip->type;
+	ds1307->type = id->driver_data;
 
 	switch (ds1307->type) {
 	case ds_1337:
@@ -551,6 +537,7 @@ static struct i2c_driver ds1307_driver =
 	},
 	.probe		= ds1307_probe,
 	.remove		= __devexit_p(ds1307_remove),
+	.id_table	= ds1307_id,
 };
 
 static int __init ds1307_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1374.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1374.c	2008-04-29 08:55:08.000000000 +0200
@@ -41,6 +41,12 @@
 #define DS1374_REG_SR_AF	0x01 /* Alarm Flag */
 #define DS1374_REG_TCR		0x09 /* Trickle Charge */
 
+static const struct i2c_device_id ds1374_id[] = {
+	{ "ds1374", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ds1374_id);
+
 struct ds1374 {
 	struct i2c_client *client;
 	struct rtc_device *rtc;
@@ -430,6 +436,7 @@ static struct i2c_driver ds1374_driver =
 	},
 	.probe = ds1374_probe,
 	.remove = __devexit_p(ds1374_remove),
+	.id_table = ds1374_id,
 };
 
 static int __init ds1374_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-isl1208.c	2008-04-29 08:50:01.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-isl1208.c	2008-04-29 09:06:31.000000000 +0200
@@ -545,12 +545,19 @@ isl1208_remove(struct i2c_client *client
 	return 0;
 }
 
+static const struct i2c_device_id isl1208_id[] = {
+	{ "isl1208", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, isl1208_id);
+
 static struct i2c_driver isl1208_driver = {
 	.driver = {
 		   .name = "rtc-isl1208",
 		   },
 	.probe = isl1208_probe,
 	.remove = isl1208_remove,
+	.id_table = isl1208_id,
 };
 
 static int __init
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-m41t80.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-m41t80.c	2008-04-29 08:55:08.000000000 +0200
@@ -60,48 +60,21 @@
 
 #define DRV_VERSION "0.05"
 
-struct m41t80_chip_info {
-	const char *name;
-	u8 features;
-};
-
-static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
-	{
-		.name		= "m41t80",
-		.features	= 0,
-	},
-	{
-		.name		= "m41t81",
-		.features	= M41T80_FEATURE_HT,
-	},
-	{
-		.name		= "m41t81s",
-		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-	},
-	{
-		.name		= "m41t82",
-		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-	},
-	{
-		.name		= "m41t83",
-		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-	},
-	{
-		.name		= "m41st84",
-		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-	},
-	{
-		.name		= "m41st85",
-		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-	},
-	{
-		.name		= "m41st87",
-		.features	= M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-	},
+static const struct i2c_device_id m41t80_id[] = {
+	{ "m41t80", 0 },
+	{ "m41t81", M41T80_FEATURE_HT },
+	{ "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+	{ "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+	{ "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+	{ "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+	{ "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+	{ "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, m41t80_id);
 
 struct m41t80_data {
-	const struct m41t80_chip_info *chip;
+	u8 features;
 	struct rtc_device *rtc;
 };
 
@@ -208,7 +181,7 @@ static int m41t80_rtc_proc(struct device
 	struct m41t80_data *clientdata = i2c_get_clientdata(client);
 	u8 reg;
 
-	if (clientdata->chip->features & M41T80_FEATURE_BL) {
+	if (clientdata->features & M41T80_FEATURE_BL) {
 		reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
 		seq_printf(seq, "battery\t\t: %s\n",
 			   (reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
@@ -759,10 +732,9 @@ static struct notifier_block wdt_notifie
 static int m41t80_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
-	int i, rc = 0;
+	int rc = 0;
 	struct rtc_device *rtc = NULL;
 	struct rtc_time tm;
-	const struct m41t80_chip_info *chip;
 	struct m41t80_data *clientdata = NULL;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
@@ -774,19 +746,6 @@ static int m41t80_probe(struct i2c_clien
 	dev_info(&client->dev,
 		 "chip found, driver version " DRV_VERSION "\n");
 
-	chip = NULL;
-	for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
-		if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
-			chip = &m41t80_chip_info_tbl[i];
-			break;
-		}
-	}
-	if (!chip) {
-		dev_err(&client->dev, "%s is not supported\n", client->name);
-		rc = -ENODEV;
-		goto exit;
-	}
-
 	clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
 	if (!clientdata) {
 		rc = -ENOMEM;
@@ -802,7 +761,7 @@ static int m41t80_probe(struct i2c_clien
 	}
 
 	clientdata->rtc = rtc;
-	clientdata->chip = chip;
+	clientdata->features = id->driver_data;
 	i2c_set_clientdata(client, clientdata);
 
 	/* Make sure HT (Halt Update) bit is cleared */
@@ -811,7 +770,7 @@ static int m41t80_probe(struct i2c_clien
 		goto ht_err;
 
 	if (rc & M41T80_ALHOUR_HT) {
-		if (chip->features & M41T80_FEATURE_HT) {
+		if (clientdata->features & M41T80_FEATURE_HT) {
 			m41t80_get_datetime(client, &tm);
 			dev_info(&client->dev, "HT bit was set!\n");
 			dev_info(&client->dev,
@@ -843,7 +802,7 @@ static int m41t80_probe(struct i2c_clien
 		goto exit;
 
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
-	if (chip->features & M41T80_FEATURE_HT) {
+	if (clientdata->features & M41T80_FEATURE_HT) {
 		rc = misc_register(&wdt_dev);
 		if (rc)
 			goto exit;
@@ -879,7 +838,7 @@ static int m41t80_remove(struct i2c_clie
 	struct rtc_device *rtc = clientdata->rtc;
 
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
-	if (clientdata->chip->features & M41T80_FEATURE_HT) {
+	if (clientdata->features & M41T80_FEATURE_HT) {
 		misc_deregister(&wdt_dev);
 		unregister_reboot_notifier(&wdt_notifier);
 	}
@@ -897,6 +856,7 @@ static struct i2c_driver m41t80_driver =
 	},
 	.probe = m41t80_probe,
 	.remove = m41t80_remove,
+	.id_table = m41t80_id,
 };
 
 static int __init m41t80_rtc_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-pcf8563.c	2008-04-29 08:49:41.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-pcf8563.c	2008-04-29 09:07:17.000000000 +0200
@@ -300,12 +300,19 @@ static int pcf8563_remove(struct i2c_cli
 	return 0;
 }
 
+static const struct i2c_device_id pcf8563_id[] = {
+	{ "pcf8563", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8563_id);
+
 static struct i2c_driver pcf8563_driver = {
 	.driver		= {
 		.name	= "rtc-pcf8563",
 	},
 	.probe		= pcf8563_probe,
 	.remove		= pcf8563_remove,
+	.id_table	= pcf8563_id,
 };
 
 static int __init pcf8563_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-rs5c372.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-rs5c372.c	2008-04-29 08:56:12.000000000 +0200
@@ -69,6 +69,15 @@ enum rtc_type {
 	rtc_rv5c387a,
 };
 
+static const struct i2c_device_id rs5c372_id[] = {
+	{ "rs5c372a", rtc_rs5c372a },
+	{ "rs5c372b", rtc_rs5c372b },
+	{ "rv5c386", rtc_rv5c386 },
+	{ "rv5c387a", rtc_rv5c387a },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rs5c372_id);
+
 /* REVISIT:  this assumes that:
  *  - we're in the 21st century, so it's safe to ignore the century
  *    bit for rv5c38[67] (REG_MONTH bit 7);
@@ -515,6 +524,7 @@ static int rs5c372_probe(struct i2c_clie
 
 	rs5c372->client = client;
 	i2c_set_clientdata(client, rs5c372);
+	rs5c372->type = id->driver_data;
 
 	/* we read registers 0x0f then 0x00-0x0f; skip the first one */
 	rs5c372->regs = &rs5c372->buf[1];
@@ -523,19 +533,6 @@ static int rs5c372_probe(struct i2c_clie
 	if (err < 0)
 		goto exit_kfree;
 
-	if (strcmp(client->name, "rs5c372a") == 0)
-		rs5c372->type = rtc_rs5c372a;
-	else if (strcmp(client->name, "rs5c372b") == 0)
-		rs5c372->type = rtc_rs5c372b;
-	else if (strcmp(client->name, "rv5c386") == 0)
-		rs5c372->type = rtc_rv5c386;
-	else if (strcmp(client->name, "rv5c387a") == 0)
-		rs5c372->type = rtc_rv5c387a;
-	else {
-		rs5c372->type = rtc_rs5c372b;
-		dev_warn(&client->dev, "assuming rs5c372b\n");
-	}
-
 	/* clock may be set for am/pm or 24 hr time */
 	switch (rs5c372->type) {
 	case rtc_rs5c372a:
@@ -652,6 +649,7 @@ static struct i2c_driver rs5c372_driver 
 	},
 	.probe		= rs5c372_probe,
 	.remove		= rs5c372_remove,
+	.id_table	= rs5c372_id,
 };
 
 static __init int rs5c372_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-s35390a.c	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-s35390a.c	2008-04-29 08:55:08.000000000 +0200
@@ -34,6 +34,12 @@
 #define S35390A_FLAG_RESET	0x80
 #define S35390A_FLAG_TEST	0x01
 
+static const struct i2c_device_id s35390a_id[] = {
+	{ "s35390a", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, s35390a_id);
+
 struct s35390a {
 	struct i2c_client *client[8];
 	struct rtc_device *rtc;
@@ -297,6 +303,7 @@ static struct i2c_driver s35390a_driver 
 	},
 	.probe		= s35390a_probe,
 	.remove		= s35390a_remove,
+	.id_table	= s35390a_id,
 };
 
 static int __init s35390a_rtc_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-x1205.c	2008-04-29 08:48:52.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-x1205.c	2008-04-29 09:05:26.000000000 +0200
@@ -553,12 +553,19 @@ static int x1205_remove(struct i2c_clien
 	return 0;
 }
 
+static const struct i2c_device_id x1205_id[] = {
+	{ "x1205", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, x1205_id);
+
 static struct i2c_driver x1205_driver = {
 	.driver		= {
 		.name	= "rtc-x1205",
 	},
 	.probe		= x1205_probe,
 	.remove		= x1205_remove,
+	.id_table	= x1205_id,
 };
 
 static int __init x1205_init(void)
--- linux-2.6.26-rc0.orig/include/linux/i2c.h	2008-04-29 08:37:43.000000000 +0200
+++ linux-2.6.26-rc0/include/linux/i2c.h	2008-04-29 08:55:08.000000000 +0200
@@ -229,17 +229,17 @@ struct i2c_board_info {
 };
 
 /**
- * I2C_BOARD_INFO - macro used to list an i2c device and its driver
- * @driver: identifies the driver to use with the device
+ * I2C_BOARD_INFO - macro used to list an i2c device and its address
+ * @dev_type: identifies the device type
  * @dev_addr: the device's address on the bus.
  *
  * This macro initializes essential fields of a struct i2c_board_info,
  * declaring what has been provided on a particular board.  Optional
- * fields (such as the chip type, its associated irq, or device-specific
- * platform_data) are provided using conventional syntax.
+ * fields (such as associated irq, or device-specific platform_data)
+ * are provided using conventional syntax.
  */
-#define I2C_BOARD_INFO(driver,dev_addr) \
-	.driver_name = (driver), .addr = (dev_addr)
+#define I2C_BOARD_INFO(dev_type,dev_addr) \
+	.type = (dev_type), .addr = (dev_addr)
 
 
 /* Add-on boards should register/unregister their devices; e.g. a board

-- 
Jean Delvare

^ permalink raw reply

* [git pull] Please pull powerpc.git master branch
From: Paul Mackerras @ 2008-04-29 11:29 UTC (permalink / raw)
  To: torvalds; +Cc: linuxppc-dev, akpm, linux-kernel

Linus,

Please do:

git pull \
git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git master=


There are 14 commits there that Andrew Morton sent to me to merge,
from Badari Pulavarty (memory hot-remove stuff) and Zhang Wei (RapidIO
patches).  Plus there are 5 other powerpc-related patches: a patch
from me adding a fast endian-switch system call, a patch from Kumar
Gala that lets 32-bit use separate stacks for hard and soft IRQs like
64-bit already does, a build fix from Tony Breeds, a patch from me to
make powerpc build OK if inline doesn't mean __always_inline, and a
thermal driver for one of the last G5 powermac models.

Thanks,
Paul.

Badari Pulavarty (3):
      [POWERPC] Hotplug memory remove notifications for powerpc
      [POWERPC] Update lmb data structures for hotplug memory add/remov=
e
      [POWERPC] Provide walk_memory_resource() for powerpc

Kumar Gala (1):
      [POWERPC] Add IRQSTACKS support on ppc32

Paul Mackerras (2):
      [POWERPC] Add fast little-endian switch system call
      [POWERPC] Use __always_inline for xchg* and cmpxchg*

Tony Breeds (1):
      [POWERPC] Fix building of pmac32 when CONFIG_NVRAM=3Dm

Zhang Wei (11):
      [RAPIDIO] Change RIO function mpc85xx_ to fsl_
      [RAPIDIO] Add RapidIO option to kernel configuration
      [RAPIDIO] Move include/asm-ppc/rio.h to asm-powerpc
      [RAPIDIO] Add RapidIO multi mport support
      [RAPIDIO] Add OF-tree support to RapidIO controller driver
      [RAPIDIO] Auto-probe the RapidIO system size
      [RAPIDIO] Add RapidIO node into MPC8641HPCN dts file
      [RAPIDIO] Add RapidIO node probing into MPC86xx_HPCN board id tab=
le
      [RAPIDIO] Add serial RapidIO controller support, which includes M=
PC8548, MPC8641
      [RAPIDIO] Add RapidIO connection info print out and re-training f=
or broken connections
      [RAPIDIO] Change RapidIO doorbell source and target ID field to 1=
6-bit

=C9tienne Bersac (1):
      [POWERPC] windfarm: Add PowerMac 12,1 support

^ permalink raw reply

* Re: build failure on efika
From: Grant Likely @ 2008-04-29 12:08 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18454.49097.53537.474679@cargo.ozlabs.ibm.com>

On Tue, Apr 29, 2008 at 12:27 AM, Paul Mackerras <paulus@samba.org> wrote:
> My test builds for efika currently fail with this message:
>
>  FATAL: drivers/serial/mpc52xx_uart: struct of_device_id is not terminated with a NULL entry!
>  make[2]: *** [__modpost] Error 1
>  make[1]: *** [modules] Error 2
>  make: *** [sub-make] Error 2
>
>  Could you do a little patch to add the NULL entry please?

Will do.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH 1/2 v2] i2c: Add support for device alias names
From: Jon Smirl @ 2008-04-29 12:16 UTC (permalink / raw)
  To: Jean Delvare
  Cc: Kay Sievers, linuxppc-dev list, Paul Mundt, Linux I2C, Scott Wood
In-Reply-To: <20080429124621.07e6efd6@hyperion.delvare>

On 4/29/08, Jean Delvare <khali@linux-fr.org> wrote:
> Based on earlier work by Jon Smirl and Jochen Friedrich.
>  +/* Looks like: i2c:S */
>  +static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
>  +                       char *alias)
>  +{
>  +       sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);

Do you want to add the colon?

>  +
>  +       return 1;
>  +}

-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* [PATCH] [POWERPC] mpc5200: Fix unterminated of_device_id table
From: Grant Likely @ 2008-04-29 12:43 UTC (permalink / raw)
  To: linuxppc-dev, linux_kernel, paulus

From: Grant Likely <grant.likely@secretlab.ca>

If CONFIG_PPC_MPC5121 is not set, then the of_device_id table for the
mpc5200 serial driver will not get terminated with a NULL entry.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 drivers/serial/mpc52xx_uart.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index d93b357..7a3625f 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -1221,8 +1221,8 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
 #endif
 #ifdef CONFIG_PPC_MPC512x
 	{ .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
-	{},
 #endif
+	{},
 };
 
 static int __devinit

^ permalink raw reply related

* Re: [PATCH 1/2 v2] i2c: Add support for device alias names
From: Jean Delvare @ 2008-04-29 12:49 UTC (permalink / raw)
  To: Jon Smirl
  Cc: Kay Sievers, linuxppc-dev list, Paul Mundt, Linux I2C, Scott Wood
In-Reply-To: <9e4733910804290516g1fd0b653jae63e811409e00f9@mail.gmail.com>

Hi Jon,

On Tue, 29 Apr 2008 08:16:13 -0400, Jon Smirl wrote:
> On 4/29/08, Jean Delvare <khali@linux-fr.org> wrote:
> > Based on earlier work by Jon Smirl and Jochen Friedrich.
> >  +/* Looks like: i2c:S */
> >  +static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
> >  +                       char *alias)
> >  +{
> >  +       sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
> 
> Do you want to add the colon?

Not yet. This can be added later anyway, so I'd rather push the
known-to-work patches as is for now, and we fix this detail between rc1
and rc2. For now I am still in favor of removing the "*" we don't need,
I'll send a patch doing this later today (I hope) for discussion.

> >  +
> >  +       return 1;
> >  +}

Thanks,
-- 
Jean Delvare

^ permalink raw reply

* Please pull linux-2.6-mpc52xx.git
From: Grant Likely @ 2008-04-29 13:34 UTC (permalink / raw)
  To: Paul Mackerras, linuxppc-dev

The following changes since commit 6c39103ce5192bdb2195f3daab7323dfa44fb52e:
  Zhang Wei (1):
        [RAPIDIO] Change RapidIO doorbell source and target ID field to 16-bit

are available in the git repository at:

  git://git.secretlab.ca/git/linux-2.6-mpc52xx.git for-2.6.26

Bartlomiej Sieka (1):
      [POWERPC] mpc5200: defconfigs for CM5200, Lite5200B, Motion-PRO
and TQM5200

Grant Likely (2):
      [POWERPC] mpc5200: Fix unterminated of_device_id table
      [POWERPC] mpc5200: Switch mpc5200 dts files to dts-v1 format

Sascha Hauer (2):
      [POWERPC] mpc5200: add interrupt type function
      [POWERPC] mpc5200: Fix FEC error handling on FIFO errors

s.hauer@pengutronix.de (2):
      [POWERPC] mpc5200: add gpiolib support for mpc5200
      [POWERPC] mpc5200: add Phytec pcm030 board support

 .../powerpc/mpc52xx-device-tree-bindings.txt       |   12 +
 arch/powerpc/boot/dts/cm5200.dts                   |   98 +-
 arch/powerpc/boot/dts/lite5200.dts                 |  132 ++--
 arch/powerpc/boot/dts/lite5200b.dts                |  146 ++--
 arch/powerpc/boot/dts/motionpro.dts                |  118 +-
 arch/powerpc/boot/dts/pcm030.dts                   |  363 ++++++
 arch/powerpc/boot/dts/tqm5200.dts                  |   80 +-
 arch/powerpc/configs/52xx/cm5200_defconfig         | 1099 ++++++++++++++++++
 arch/powerpc/configs/52xx/lite5200b_defconfig      | 1049 +++++++++++++++++
 arch/powerpc/configs/52xx/motionpro_defconfig      | 1107 ++++++++++++++++++
 arch/powerpc/configs/52xx/pcm030_defconfig         | 1115 ++++++++++++++++++
 arch/powerpc/configs/52xx/tqm5200_defconfig        | 1214 ++++++++++++++++++++
 arch/powerpc/platforms/52xx/Kconfig                |    6 +
 arch/powerpc/platforms/52xx/Makefile               |    2 +
 arch/powerpc/platforms/52xx/mpc5200_simple.c       |    1 +
 arch/powerpc/platforms/52xx/mpc52xx_gpio.c         |  465 ++++++++
 arch/powerpc/platforms/52xx/mpc52xx_pic.c          |   38 +
 drivers/net/fec_mpc52xx.c                          |   23 +-
 drivers/serial/mpc52xx_uart.c                      |    2 +-
 19 files changed, 6771 insertions(+), 299 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/pcm030.dts
 create mode 100644 arch/powerpc/configs/52xx/cm5200_defconfig
 create mode 100644 arch/powerpc/configs/52xx/lite5200b_defconfig
 create mode 100644 arch/powerpc/configs/52xx/motionpro_defconfig
 create mode 100644 arch/powerpc/configs/52xx/pcm030_defconfig
 create mode 100644 arch/powerpc/configs/52xx/tqm5200_defconfig
 create mode 100644 arch/powerpc/platforms/52xx/mpc52xx_gpio.c


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: 2.6.25: pmac_newworld undefined
From: Adrian Bunk @ 2008-04-29 13:35 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: linuxppc-dev, LKML
In-Reply-To: <20080428193324.GC13400@uranus.ravnborg.org>

On Mon, Apr 28, 2008 at 09:33:24PM +0200, Sam Ravnborg wrote:
> On Mon, Apr 28, 2008 at 02:20:44PM +1000, Tony Breeds wrote:
> > On Sun, Apr 27, 2008 at 08:03:46PM +0200, Christian Kujau wrote:
> > > Hi,
> > > 
> > > the build failure reported[0] by Kamalesh back in 01/2008 is still 
> > > present in today's 2.6.25-git with CONFIG_NVRAM=m (instead of =y):
> > > 
> > >   Building modules, stage 2.
> > >   MODPOST 72 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 1
> > 
> > Yeah that isn't really surprising.  Essentially
> > arch/powerpc/platforms/powermac/nvram.c must be builtin (not modular)
> > but CONFIG_NVRAM is tristate, and your .config has CONFIG_NVRAM=m.
> > 
> > We can probably "fix" this by adding another config config symbol and
> > "selecting" that from CONFIG_NVRAM.  Then using this new symbol in
> > arch/powerpc/platforms/powermac/*
> > 
> > so I think with we need is:
> > config NVRAM
> >   bool "..." if PPC32
> >   tristate "..." if !PPC32
> >   ...
> >   ...
> > 
> > Sam is there some way to achieve that or should we just create an
> > secondary symbol?
> 
> In the Makefile you could just do a:
> 
> obj-$(CONFIG_NVRAM:m=y)             += nvram.o
> 
> Then you would force nvram to be build-in.
> That looks simpler than messing with Kconfig in this case.

You miss that this is only true on powerpc.

And for such issues Kconfig anyway is the right place - assume how your 
solution would break if NVRAM would some day select or depend on some 
helper code.

> 	Sam

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

^ permalink raw reply

* [PATCH] [POWERPC] convert transfer_to_handler into a macro
From: Kumar Gala @ 2008-04-29 13:56 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

We need to have unique transfer_to_handler paths for each exception level
that is supported.  We need to use the proper xSRR0/1 depending on which
exception level the interrupt was from.  The macro conversion lets up
templatize this code path.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---

Paul,

I request you apply this for v2.6.26.  I know its a bit late in the game
but I'd prefer to get this in so reduce churn later.  Also, I've built this
version on pmac_defconfig, ppc40x_defconfig, and ppc44x_config and compared
the objdump output to ensure that the code is identical before and after
this patch.

- k

 arch/powerpc/kernel/entry_32.S |  191 ++++++++++++++++++++++------------------
 1 files changed, 106 insertions(+), 85 deletions(-)

diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0c8614d..7710a02 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -43,6 +43,111 @@
 #define LOAD_MSR_KERNEL(r, x)	li r,(x)
 #endif

+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_SMP
+#define SMP_ADJUST_GLOBAL_DBCR0						       \
+	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT);				       \
+	lwz	r9,TI_CPU(r9);						       \
+	slwi	r9,r9,3;						       \
+	add	r11,r11,r9;
+#else
+#define SMP_ADJUST_GLOBAL_DBCR0
+#endif
+#define HANDLE_DBCR							       \
+	/* Check to see if the dbcr0 register is set up to debug.  Use the     \
+	   internal debug mode bit to do this. */			       \
+	lwz	r12,THREAD_DBCR0(r12);					       \
+	andis.	r12,r12,DBCR0_IDM@h;					       \
+	beq+	3f;							       \
+	/* From user and task is ptraced - load up global dbcr0 */	       \
+	li	r12,-1;			/* clear all pending debug events */   \
+	mtspr	SPRN_DBSR,r12;						       \
+	lis	r11,global_dbcr0@ha;					       \
+	tophys(r11,r11);						       \
+	addi	r11,r11,global_dbcr0@l;					       \
+	SMP_ADJUST_GLOBAL_DBCR0;					       \
+	lwz	r12,0(r11);						       \
+	mtspr	SPRN_DBCR0,r12;						       \
+	lwz	r12,4(r11);						       \
+	addi	r12,r12,-1;						       \
+	stw	r12,4(r11);
+#else
+#define HANDLE_DBCR
+#endif
+
+#ifdef CONFIG_6xx
+#define CHECK_DOZE_NAP							       \
+	rlwinm	r9,r1,0,0,31-THREAD_SHIFT;				       \
+	tophys(r9,r9);			/* check local flags */		       \
+	lwz	r12,TI_LOCAL_FLAGS(r9);					       \
+	mtcrf	0x01,r12;						       \
+	bt-	31-TLF_NAPPING,4f;
+#define RESTORE_DOZE_NAP						       \
+4:	rlwinm	r12,r12,0,~_TLF_NAPPING;				       \
+	stw	r12,TI_LOCAL_FLAGS(r9);					       \
+	b	power_save_6xx_restore;
+#else
+#define RESTORE_DOZE_NAP
+#define CHECK_DOZE_NAP
+#endif /* CONFIG_6xx */
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception, turning
+ * on address translation.
+ * Note that we rely on the caller having set cr0.eq iff the exception
+ * occurred in kernel mode (i.e. MSR:PR = 0).
+ */
+
+#define	TRANSFER_TO_HANDLER(prefix, exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi)   \
+	.globl	prefix##transfer_to_handler_full;			       \
+prefix##transfer_to_handler_full:					       \
+	SAVE_NVGPRS(r11);						       \
+	/* fall through */						       \
+									       \
+	.globl	prefix##transfer_to_handler;				       \
+prefix##transfer_to_handler:						       \
+	stw	r2,GPR2(r11);						       \
+	stw	r12,_NIP(r11);						       \
+	stw	r9,_MSR(r11);						       \
+	andi.	r2,r9,MSR_PR;						       \
+	mfctr	r12;							       \
+	mfspr	r2,SPRN_XER;						       \
+	stw	r12,_CTR(r11);						       \
+	stw	r2,_XER(r11);						       \
+	mfspr	r12,SPRN_SPRG3;						       \
+	addi	r2,r12,-THREAD;						       \
+	tovirt(r2,r2);			/* set r2 to current */		       \
+	beq	2f;			/* if from user, fix up THREAD.regs */ \
+									       \
+	addi	r11,r1,STACK_FRAME_OVERHEAD;				       \
+	stw	r11,PT_REGS(r12);					       \
+	HANDLE_DBCR;							       \
+	b	3f;							       \
+									       \
+2:	/* if from kernel, check interrupted DOZE/NAP mode and		       \
+         * check for stack overflow					       \
+         */								       \
+	lwz	r9,KSP_LIMIT(r12);					       \
+	cmplw	r1,r9;			/* if r1 <= ksp_limit */	       \
+	ble-	stack_ovf;		/* then the kernel stack overflowed */ \
+5:									       \
+	CHECK_DOZE_NAP;							       \
+									       \
+	.globl prefix##transfer_to_handler_cont;			       \
+prefix##transfer_to_handler_cont:					       \
+3:									       \
+	mflr	r9;							       \
+	lwz	r11,0(r9);		/* virtual address of handler */       \
+	lwz	r9,4(r9);		/* where to go when done */	       \
+	mtspr	exc_lvl_srr0,r11;					       \
+	mtspr	exc_lvl_srr1,r10;					       \
+	mtlr	r9;							       \
+	SYNC;								       \
+	exc_lvl_rfi;			/* jump to handler, enable MMU */      \
+									       \
+	RESTORE_DOZE_NAP;
+
 #ifdef CONFIG_BOOKE
 #include "head_booke.h"
 #define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level)	\
@@ -80,91 +185,7 @@ crit_transfer_to_handler:
 	/* fall through */
 #endif

-/*
- * This code finishes saving the registers to the exception frame
- * and jumps to the appropriate handler for the exception, turning
- * on address translation.
- * Note that we rely on the caller having set cr0.eq iff the exception
- * occurred in kernel mode (i.e. MSR:PR = 0).
- */
-	.globl	transfer_to_handler_full
-transfer_to_handler_full:
-	SAVE_NVGPRS(r11)
-	/* fall through */
-
-	.globl	transfer_to_handler
-transfer_to_handler:
-	stw	r2,GPR2(r11)
-	stw	r12,_NIP(r11)
-	stw	r9,_MSR(r11)
-	andi.	r2,r9,MSR_PR
-	mfctr	r12
-	mfspr	r2,SPRN_XER
-	stw	r12,_CTR(r11)
-	stw	r2,_XER(r11)
-	mfspr	r12,SPRN_SPRG3
-	addi	r2,r12,-THREAD
-	tovirt(r2,r2)			/* set r2 to current */
-	beq	2f			/* if from user, fix up THREAD.regs */
-	addi	r11,r1,STACK_FRAME_OVERHEAD
-	stw	r11,PT_REGS(r12)
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-	/* Check to see if the dbcr0 register is set up to debug.  Use the
-	   internal debug mode bit to do this. */
-	lwz	r12,THREAD_DBCR0(r12)
-	andis.	r12,r12,DBCR0_IDM@h
-	beq+	3f
-	/* From user and task is ptraced - load up global dbcr0 */
-	li	r12,-1			/* clear all pending debug events */
-	mtspr	SPRN_DBSR,r12
-	lis	r11,global_dbcr0@ha
-	tophys(r11,r11)
-	addi	r11,r11,global_dbcr0@l
-#ifdef CONFIG_SMP
-	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
-	lwz	r9,TI_CPU(r9)
-	slwi	r9,r9,3
-	add	r11,r11,r9
-#endif
-	lwz	r12,0(r11)
-	mtspr	SPRN_DBCR0,r12
-	lwz	r12,4(r11)
-	addi	r12,r12,-1
-	stw	r12,4(r11)
-#endif
-	b	3f
-
-2:	/* if from kernel, check interrupted DOZE/NAP mode and
-         * check for stack overflow
-         */
-	lwz	r9,KSP_LIMIT(r12)
-	cmplw	r1,r9			/* if r1 <= ksp_limit */
-	ble-	stack_ovf		/* then the kernel stack overflowed */
-5:
-#ifdef CONFIG_6xx
-	rlwinm	r9,r1,0,0,31-THREAD_SHIFT
-	tophys(r9,r9)			/* check local flags */
-	lwz	r12,TI_LOCAL_FLAGS(r9)
-	mtcrf	0x01,r12
-	bt-	31-TLF_NAPPING,4f
-#endif /* CONFIG_6xx */
-	.globl transfer_to_handler_cont
-transfer_to_handler_cont:
-3:
-	mflr	r9
-	lwz	r11,0(r9)		/* virtual address of handler */
-	lwz	r9,4(r9)		/* where to go when done */
-	mtspr	SPRN_SRR0,r11
-	mtspr	SPRN_SRR1,r10
-	mtlr	r9
-	SYNC
-	RFI				/* jump to handler, enable MMU */
-
-#ifdef CONFIG_6xx
-4:	rlwinm	r12,r12,0,~_TLF_NAPPING
-	stw	r12,TI_LOCAL_FLAGS(r9)
-	b	power_save_6xx_restore
-#endif
+	TRANSFER_TO_HANDLER(, SPRN_SRR0, SPRN_SRR1, RFI);

 /*
  * On kernel stack overflow, load up an initial stack pointer
-- 
1.5.4.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox