Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 20086
b: refs/heads/master
c: ac171c4
h: refs/heads/master
v: v3
  • Loading branch information
Benjamin Herrenschmidt authored and Linus Torvalds committed Feb 8, 2006
1 parent e0df1db commit ba19dfb
Show file tree
Hide file tree
Showing 15 changed files with 1,480 additions and 200 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 746f956beb534ddf73da4346de81f2941c8573f8
refs/heads/master: ac171c46667c1cb2ee9e22312291df6ed78e1b6e
8 changes: 8 additions & 0 deletions trunk/drivers/macintosh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ config WINDFARM_PM91
This driver provides thermal control for the PowerMac9,1
which is the recent (SMU based) single CPU desktop G5

config WINDFARM_PM112
tristate "Support for thermal management on PowerMac11,2"
depends on WINDFARM && I2C && PMAC_SMU
select I2C_PMAC_SMU
help
This driver provides thermal control for the PowerMac11,2
which are the recent dual and quad G5 machines using the
970MP dual-core processor.

config ANSLCD
tristate "Support for ANS LCD display"
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/macintosh/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ obj-$(CONFIG_WINDFARM_PM91) += windfarm_smu_controls.o \
windfarm_smu_sensors.o \
windfarm_lm75_sensor.o windfarm_pid.o \
windfarm_cpufreq_clamp.o windfarm_pm91.o
obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \
windfarm_smu_controls.o \
windfarm_smu_sensors.o \
windfarm_max6690_sensor.o \
windfarm_lm75_sensor.o windfarm_pid.o
3 changes: 3 additions & 0 deletions trunk/drivers/macintosh/windfarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/device.h>

/* Display a 16.16 fixed point value */
#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16)
Expand All @@ -39,6 +40,7 @@ struct wf_control {
char *name;
int type;
struct kref ref;
struct device_attribute attr;
};

#define WF_CONTROL_TYPE_GENERIC 0
Expand Down Expand Up @@ -87,6 +89,7 @@ struct wf_sensor {
struct wf_sensor_ops *ops;
char *name;
struct kref ref;
struct device_attribute attr;
};

/* Same lifetime rules as controls */
Expand Down
69 changes: 65 additions & 4 deletions trunk/drivers/macintosh/windfarm_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ static unsigned int wf_overtemp;
static unsigned int wf_overtemp_counter;
struct task_struct *wf_thread;

static struct platform_device wf_platform_device = {
.name = "windfarm",
};

/*
* Utilities & tick thread
*/
Expand Down Expand Up @@ -157,6 +161,40 @@ static void wf_control_release(struct kref *kref)
kfree(ct);
}

static ssize_t wf_show_control(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
s32 val = 0;
int err;

err = ctrl->ops->get_value(ctrl, &val);
if (err < 0)
return err;
return sprintf(buf, "%d\n", val);
}

/* This is really only for debugging... */
static ssize_t wf_store_control(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
int val;
int err;
char *endp;

val = simple_strtoul(buf, &endp, 0);
while (endp < buf + count && (*endp == ' ' || *endp == '\n'))
++endp;
if (endp - buf < count)
return -EINVAL;
err = ctrl->ops->set_value(ctrl, val);
if (err < 0)
return err;
return count;
}

int wf_register_control(struct wf_control *new_ct)
{
struct wf_control *ct;
Expand All @@ -173,6 +211,13 @@ int wf_register_control(struct wf_control *new_ct)
kref_init(&new_ct->ref);
list_add(&new_ct->link, &wf_controls);

new_ct->attr.attr.name = new_ct->name;
new_ct->attr.attr.owner = THIS_MODULE;
new_ct->attr.attr.mode = 0644;
new_ct->attr.show = wf_show_control;
new_ct->attr.store = wf_store_control;
device_create_file(&wf_platform_device.dev, &new_ct->attr);

DBG("wf: Registered control %s\n", new_ct->name);

wf_notify(WF_EVENT_NEW_CONTROL, new_ct);
Expand Down Expand Up @@ -247,6 +292,19 @@ static void wf_sensor_release(struct kref *kref)
kfree(sr);
}

static ssize_t wf_show_sensor(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr);
s32 val = 0;
int err;

err = sens->ops->get_value(sens, &val);
if (err < 0)
return err;
return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val));
}

int wf_register_sensor(struct wf_sensor *new_sr)
{
struct wf_sensor *sr;
Expand All @@ -263,6 +321,13 @@ int wf_register_sensor(struct wf_sensor *new_sr)
kref_init(&new_sr->ref);
list_add(&new_sr->link, &wf_sensors);

new_sr->attr.attr.name = new_sr->name;
new_sr->attr.attr.owner = THIS_MODULE;
new_sr->attr.attr.mode = 0444;
new_sr->attr.show = wf_show_sensor;
new_sr->attr.store = NULL;
device_create_file(&wf_platform_device.dev, &new_sr->attr);

DBG("wf: Registered sensor %s\n", new_sr->name);

wf_notify(WF_EVENT_NEW_SENSOR, new_sr);
Expand Down Expand Up @@ -396,10 +461,6 @@ int wf_is_overtemp(void)
}
EXPORT_SYMBOL_GPL(wf_is_overtemp);

static struct platform_device wf_platform_device = {
.name = "windfarm",
};

static int __init windfarm_core_init(void)
{
DBG("wf: core loaded\n");
Expand Down
169 changes: 169 additions & 0 deletions trunk/drivers/macintosh/windfarm_max6690_sensor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Windfarm PowerMac thermal control. MAX6690 sensor.
*
* Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
*
* Use and redistribute under the terms of the GNU GPL v2.
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <asm/prom.h>
#include <asm/pmac_low_i2c.h>

#include "windfarm.h"

#define VERSION "0.1"

/* This currently only exports the external temperature sensor,
since that's all the control loops need. */

/* Some MAX6690 register numbers */
#define MAX6690_INTERNAL_TEMP 0
#define MAX6690_EXTERNAL_TEMP 1

struct wf_6690_sensor {
struct i2c_client i2c;
struct wf_sensor sens;
};

#define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens)
#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c)

static int wf_max6690_attach(struct i2c_adapter *adapter);
static int wf_max6690_detach(struct i2c_client *client);

static struct i2c_driver wf_max6690_driver = {
.driver = {
.name = "wf_max6690",
},
.attach_adapter = wf_max6690_attach,
.detach_client = wf_max6690_detach,
};

static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
{
struct wf_6690_sensor *max = wf_to_6690(sr);
s32 data;

if (max->i2c.adapter == NULL)
return -ENODEV;

/* chip gets initialized by firmware */
data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP);
if (data < 0)
return data;
*value = data << 16;
return 0;
}

static void wf_max6690_release(struct wf_sensor *sr)
{
struct wf_6690_sensor *max = wf_to_6690(sr);

if (max->i2c.adapter) {
i2c_detach_client(&max->i2c);
max->i2c.adapter = NULL;
}
kfree(max);
}

static struct wf_sensor_ops wf_max6690_ops = {
.get_value = wf_max6690_get,
.release = wf_max6690_release,
.owner = THIS_MODULE,
};

static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr)
{
struct wf_6690_sensor *max;
char *name = "u4-temp";

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);
return;
}

max->sens.ops = &wf_max6690_ops;
max->sens.name = name;
max->i2c.addr = addr >> 1;
max->i2c.adapter = adapter;
max->i2c.driver = &wf_max6690_driver;
strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);

if (i2c_attach_client(&max->i2c)) {
printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
goto fail;
}

if (wf_register_sensor(&max->sens)) {
i2c_detach_client(&max->i2c);
goto fail;
}

return;

fail:
kfree(max);
}

static int wf_max6690_attach(struct i2c_adapter *adapter)
{
struct device_node *busnode, *dev = NULL;
struct pmac_i2c_bus *bus;
const char *loc;
u32 *reg;

bus = pmac_i2c_adapter_to_bus(adapter);
if (bus == NULL)
return -ENODEV;
busnode = pmac_i2c_get_bus_node(bus);

while ((dev = of_get_next_child(busnode, dev)) != NULL) {
if (!device_is_compatible(dev, "max6690"))
continue;
loc = get_property(dev, "hwsensor-location", NULL);
reg = (u32 *) get_property(dev, "reg", NULL);
if (!loc || !reg)
continue;
printk("found max6690, loc=%s reg=%x\n", loc, *reg);
if (strcmp(loc, "BACKSIDE"))
continue;
wf_max6690_create(adapter, *reg);
}

return 0;
}

static int wf_max6690_detach(struct i2c_client *client)
{
struct wf_6690_sensor *max = i2c_to_6690(client);

max->i2c.adapter = NULL;
wf_unregister_sensor(&max->sens);

return 0;
}

static int __init wf_max6690_sensor_init(void)
{
return i2c_add_driver(&wf_max6690_driver);
}

static void __exit wf_max6690_sensor_exit(void)
{
i2c_del_driver(&wf_max6690_driver);
}

module_init(wf_max6690_sensor_init);
module_exit(wf_max6690_sensor_exit);

MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
MODULE_LICENSE("GPL");
8 changes: 4 additions & 4 deletions trunk/drivers/macintosh/windfarm_pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ EXPORT_SYMBOL_GPL(wf_cpu_pid_init);

s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
{
s64 error, integ, deriv, prop;
s32 target, sval, adj;
s64 integ, deriv, prop;
s32 error, target, sval, adj;
int i, hlen = st->param.history_len;

/* Calculate error term */
Expand Down Expand Up @@ -117,7 +117,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
integ += st->errors[(st->index + hlen - i) % hlen];
integ *= st->param.interval;
integ *= st->param.gr;
sval = st->param.tmax - ((integ >> 20) & 0xffffffff);
sval = st->param.tmax - (s32)(integ >> 20);
adj = min(st->param.ttarget, sval);

DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj);
Expand All @@ -129,7 +129,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp)
deriv *= st->param.gd;

/* Calculate proportional term */
prop = (new_temp - adj);
prop = st->last_delta = (new_temp - adj);
prop *= st->param.gp;

DBG("deriv: %lx, prop: %lx\n", deriv, prop);
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/macintosh/windfarm_pid.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct wf_cpu_pid_state {
int index; /* index of current power */
int tindex; /* index of current temp */
s32 target; /* current target value */
s32 last_delta; /* last Tactual - Ttarget */
s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */
s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */
s32 temps[2]; /* temp. history buffer */
Expand Down
Loading

0 comments on commit ba19dfb

Please sign in to comment.