0001
0002
0003
0004
0005
0006
0007 #undef DEBUG
0008
0009 #include <linux/types.h>
0010 #include <linux/errno.h>
0011 #include <linux/kernel.h>
0012 #include <linux/delay.h>
0013 #include <linux/slab.h>
0014 #include <linux/init.h>
0015 #include <linux/wait.h>
0016 #include <linux/i2c.h>
0017
0018 #include <asm/machdep.h>
0019 #include <asm/io.h>
0020 #include <asm/sections.h>
0021
0022 #include "windfarm.h"
0023 #include "windfarm_mpu.h"
0024
0025 #define VERSION "1.0"
0026
0027 #ifdef DEBUG
0028 #define DBG(args...) printk(args)
0029 #else
0030 #define DBG(args...) do { } while(0)
0031 #endif
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #define RPM_PID_USE_ACTUAL_SPEED 0
0047
0048
0049 #define CPU_PUMP_OUTPUT_MAX 3200
0050 #define CPU_PUMP_OUTPUT_MIN 1250
0051
0052 #define FCU_FAN_RPM 0
0053 #define FCU_FAN_PWM 1
0054
0055 struct wf_fcu_priv {
0056 struct kref ref;
0057 struct i2c_client *i2c;
0058 struct mutex lock;
0059 struct list_head fan_list;
0060 int rpm_shift;
0061 };
0062
0063 struct wf_fcu_fan {
0064 struct list_head link;
0065 int id;
0066 s32 min, max, target;
0067 struct wf_fcu_priv *fcu_priv;
0068 struct wf_control ctrl;
0069 };
0070
0071 static void wf_fcu_release(struct kref *ref)
0072 {
0073 struct wf_fcu_priv *pv = container_of(ref, struct wf_fcu_priv, ref);
0074
0075 kfree(pv);
0076 }
0077
0078 static void wf_fcu_fan_release(struct wf_control *ct)
0079 {
0080 struct wf_fcu_fan *fan = ct->priv;
0081
0082 kref_put(&fan->fcu_priv->ref, wf_fcu_release);
0083 kfree(fan);
0084 }
0085
0086 static int wf_fcu_read_reg(struct wf_fcu_priv *pv, int reg,
0087 unsigned char *buf, int nb)
0088 {
0089 int tries, nr, nw;
0090
0091 mutex_lock(&pv->lock);
0092
0093 buf[0] = reg;
0094 tries = 0;
0095 for (;;) {
0096 nw = i2c_master_send(pv->i2c, buf, 1);
0097 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
0098 break;
0099 msleep(10);
0100 ++tries;
0101 }
0102 if (nw <= 0) {
0103 pr_err("Failure writing address to FCU: %d", nw);
0104 nr = nw;
0105 goto bail;
0106 }
0107 tries = 0;
0108 for (;;) {
0109 nr = i2c_master_recv(pv->i2c, buf, nb);
0110 if (nr > 0 || (nr < 0 && nr != -ENODEV) || tries >= 100)
0111 break;
0112 msleep(10);
0113 ++tries;
0114 }
0115 if (nr <= 0)
0116 pr_err("wf_fcu: Failure reading data from FCU: %d", nw);
0117 bail:
0118 mutex_unlock(&pv->lock);
0119 return nr;
0120 }
0121
0122 static int wf_fcu_write_reg(struct wf_fcu_priv *pv, int reg,
0123 const unsigned char *ptr, int nb)
0124 {
0125 int tries, nw;
0126 unsigned char buf[16];
0127
0128 buf[0] = reg;
0129 memcpy(buf+1, ptr, nb);
0130 ++nb;
0131 tries = 0;
0132 for (;;) {
0133 nw = i2c_master_send(pv->i2c, buf, nb);
0134 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
0135 break;
0136 msleep(10);
0137 ++tries;
0138 }
0139 if (nw < 0)
0140 pr_err("wf_fcu: Failure writing to FCU: %d", nw);
0141 return nw;
0142 }
0143
0144 static int wf_fcu_fan_set_rpm(struct wf_control *ct, s32 value)
0145 {
0146 struct wf_fcu_fan *fan = ct->priv;
0147 struct wf_fcu_priv *pv = fan->fcu_priv;
0148 int rc, shift = pv->rpm_shift;
0149 unsigned char buf[2];
0150
0151 if (value < fan->min)
0152 value = fan->min;
0153 if (value > fan->max)
0154 value = fan->max;
0155
0156 fan->target = value;
0157
0158 buf[0] = value >> (8 - shift);
0159 buf[1] = value << shift;
0160 rc = wf_fcu_write_reg(pv, 0x10 + (fan->id * 2), buf, 2);
0161 if (rc < 0)
0162 return -EIO;
0163 return 0;
0164 }
0165
0166 static int wf_fcu_fan_get_rpm(struct wf_control *ct, s32 *value)
0167 {
0168 struct wf_fcu_fan *fan = ct->priv;
0169 struct wf_fcu_priv *pv = fan->fcu_priv;
0170 int rc, reg_base, shift = pv->rpm_shift;
0171 unsigned char failure;
0172 unsigned char active;
0173 unsigned char buf[2];
0174
0175 rc = wf_fcu_read_reg(pv, 0xb, &failure, 1);
0176 if (rc != 1)
0177 return -EIO;
0178 if ((failure & (1 << fan->id)) != 0)
0179 return -EFAULT;
0180 rc = wf_fcu_read_reg(pv, 0xd, &active, 1);
0181 if (rc != 1)
0182 return -EIO;
0183 if ((active & (1 << fan->id)) == 0)
0184 return -ENXIO;
0185
0186
0187 #if RPM_PID_USE_ACTUAL_SPEED
0188 reg_base = 0x11;
0189 #else
0190 reg_base = 0x10;
0191 #endif
0192 rc = wf_fcu_read_reg(pv, reg_base + (fan->id * 2), buf, 2);
0193 if (rc != 2)
0194 return -EIO;
0195
0196 *value = (buf[0] << (8 - shift)) | buf[1] >> shift;
0197
0198 return 0;
0199 }
0200
0201 static int wf_fcu_fan_set_pwm(struct wf_control *ct, s32 value)
0202 {
0203 struct wf_fcu_fan *fan = ct->priv;
0204 struct wf_fcu_priv *pv = fan->fcu_priv;
0205 unsigned char buf[2];
0206 int rc;
0207
0208 if (value < fan->min)
0209 value = fan->min;
0210 if (value > fan->max)
0211 value = fan->max;
0212
0213 fan->target = value;
0214
0215 value = (value * 2559) / 1000;
0216 buf[0] = value;
0217 rc = wf_fcu_write_reg(pv, 0x30 + (fan->id * 2), buf, 1);
0218 if (rc < 0)
0219 return -EIO;
0220 return 0;
0221 }
0222
0223 static int wf_fcu_fan_get_pwm(struct wf_control *ct, s32 *value)
0224 {
0225 struct wf_fcu_fan *fan = ct->priv;
0226 struct wf_fcu_priv *pv = fan->fcu_priv;
0227 unsigned char failure;
0228 unsigned char active;
0229 unsigned char buf[2];
0230 int rc;
0231
0232 rc = wf_fcu_read_reg(pv, 0x2b, &failure, 1);
0233 if (rc != 1)
0234 return -EIO;
0235 if ((failure & (1 << fan->id)) != 0)
0236 return -EFAULT;
0237 rc = wf_fcu_read_reg(pv, 0x2d, &active, 1);
0238 if (rc != 1)
0239 return -EIO;
0240 if ((active & (1 << fan->id)) == 0)
0241 return -ENXIO;
0242
0243 rc = wf_fcu_read_reg(pv, 0x30 + (fan->id * 2), buf, 1);
0244 if (rc != 1)
0245 return -EIO;
0246
0247 *value = (((s32)buf[0]) * 1000) / 2559;
0248
0249 return 0;
0250 }
0251
0252 static s32 wf_fcu_fan_min(struct wf_control *ct)
0253 {
0254 struct wf_fcu_fan *fan = ct->priv;
0255
0256 return fan->min;
0257 }
0258
0259 static s32 wf_fcu_fan_max(struct wf_control *ct)
0260 {
0261 struct wf_fcu_fan *fan = ct->priv;
0262
0263 return fan->max;
0264 }
0265
0266 static const struct wf_control_ops wf_fcu_fan_rpm_ops = {
0267 .set_value = wf_fcu_fan_set_rpm,
0268 .get_value = wf_fcu_fan_get_rpm,
0269 .get_min = wf_fcu_fan_min,
0270 .get_max = wf_fcu_fan_max,
0271 .release = wf_fcu_fan_release,
0272 .owner = THIS_MODULE,
0273 };
0274
0275 static const struct wf_control_ops wf_fcu_fan_pwm_ops = {
0276 .set_value = wf_fcu_fan_set_pwm,
0277 .get_value = wf_fcu_fan_get_pwm,
0278 .get_min = wf_fcu_fan_min,
0279 .get_max = wf_fcu_fan_max,
0280 .release = wf_fcu_fan_release,
0281 .owner = THIS_MODULE,
0282 };
0283
0284 static void wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan)
0285 {
0286 const struct mpu_data *mpu = wf_get_mpu(0);
0287 u16 pump_min = 0, pump_max = 0xffff;
0288 u16 tmp[4];
0289
0290
0291 if (mpu) {
0292 memcpy(&tmp, mpu->processor_part_num, 8);
0293 if (tmp[0] != 0xffff && tmp[1] != 0xffff) {
0294 pump_min = max(pump_min, tmp[0]);
0295 pump_max = min(pump_max, tmp[1]);
0296 }
0297 if (tmp[2] != 0xffff && tmp[3] != 0xffff) {
0298 pump_min = max(pump_min, tmp[2]);
0299 pump_max = min(pump_max, tmp[3]);
0300 }
0301 }
0302
0303
0304
0305
0306
0307 if (pump_min == pump_max || pump_min == 0 || pump_max == 0xffff) {
0308 pump_min = CPU_PUMP_OUTPUT_MIN;
0309 pump_max = CPU_PUMP_OUTPUT_MAX;
0310 }
0311
0312 fan->min = pump_min;
0313 fan->max = pump_max;
0314
0315 DBG("wf_fcu: pump min/max for %s set to: [%d..%d] RPM\n",
0316 fan->ctrl.name, pump_min, pump_max);
0317 }
0318
0319 static void wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan)
0320 {
0321 struct wf_fcu_priv *pv = fan->fcu_priv;
0322 const struct mpu_data *mpu0 = wf_get_mpu(0);
0323 const struct mpu_data *mpu1 = wf_get_mpu(1);
0324
0325
0326 fan->min = 2400 >> pv->rpm_shift;
0327 fan->max = 56000 >> pv->rpm_shift;
0328
0329
0330 if (mpu0 && !strcmp(fan->ctrl.name, "cpu-front-fan-0")) {
0331 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
0332 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
0333 goto bail;
0334 }
0335 if (mpu1 && !strcmp(fan->ctrl.name, "cpu-front-fan-1")) {
0336 fan->min = max(fan->min, (s32)mpu1->rminn_intake_fan);
0337 fan->max = min(fan->max, (s32)mpu1->rmaxn_intake_fan);
0338 goto bail;
0339 }
0340 if (mpu0 && !strcmp(fan->ctrl.name, "cpu-rear-fan-0")) {
0341 fan->min = max(fan->min, (s32)mpu0->rminn_exhaust_fan);
0342 fan->max = min(fan->max, (s32)mpu0->rmaxn_exhaust_fan);
0343 goto bail;
0344 }
0345 if (mpu1 && !strcmp(fan->ctrl.name, "cpu-rear-fan-1")) {
0346 fan->min = max(fan->min, (s32)mpu1->rminn_exhaust_fan);
0347 fan->max = min(fan->max, (s32)mpu1->rmaxn_exhaust_fan);
0348 goto bail;
0349 }
0350
0351 if (!strncmp(fan->ctrl.name, "cpu-fan", 7)) {
0352 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
0353 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
0354 goto bail;
0355 }
0356 bail:
0357 DBG("wf_fcu: fan min/max for %s set to: [%d..%d] RPM\n",
0358 fan->ctrl.name, fan->min, fan->max);
0359 }
0360
0361 static void wf_fcu_add_fan(struct wf_fcu_priv *pv, const char *name,
0362 int type, int id)
0363 {
0364 struct wf_fcu_fan *fan;
0365
0366 fan = kzalloc(sizeof(*fan), GFP_KERNEL);
0367 if (!fan)
0368 return;
0369 fan->fcu_priv = pv;
0370 fan->id = id;
0371 fan->ctrl.name = name;
0372 fan->ctrl.priv = fan;
0373
0374
0375
0376
0377 if (type == FCU_FAN_RPM) {
0378 if (!strncmp(name, "cpu-pump", strlen("cpu-pump")))
0379 wf_fcu_get_pump_minmax(fan);
0380 else
0381 wf_fcu_get_rpmfan_minmax(fan);
0382 fan->ctrl.type = WF_CONTROL_RPM_FAN;
0383 fan->ctrl.ops = &wf_fcu_fan_rpm_ops;
0384 } else {
0385 fan->min = 10;
0386 fan->max = 100;
0387 fan->ctrl.type = WF_CONTROL_PWM_FAN;
0388 fan->ctrl.ops = &wf_fcu_fan_pwm_ops;
0389 }
0390
0391 if (wf_register_control(&fan->ctrl)) {
0392 pr_err("wf_fcu: Failed to register fan %s\n", name);
0393 kfree(fan);
0394 return;
0395 }
0396 list_add(&fan->link, &pv->fan_list);
0397 kref_get(&pv->ref);
0398 }
0399
0400 static void wf_fcu_lookup_fans(struct wf_fcu_priv *pv)
0401 {
0402
0403
0404
0405 static const struct {
0406 const char *dt_name;
0407 const char *ct_name;
0408 } loc_trans[] = {
0409 { "BACKSIDE", "backside-fan", },
0410 { "SYS CTRLR FAN", "backside-fan", },
0411 { "DRIVE BAY", "drive-bay-fan", },
0412 { "SLOT", "slots-fan", },
0413 { "PCI FAN", "slots-fan", },
0414 { "CPU A INTAKE", "cpu-front-fan-0", },
0415 { "CPU A EXHAUST", "cpu-rear-fan-0", },
0416 { "CPU B INTAKE", "cpu-front-fan-1", },
0417 { "CPU B EXHAUST", "cpu-rear-fan-1", },
0418 { "CPU A PUMP", "cpu-pump-0", },
0419 { "CPU B PUMP", "cpu-pump-1", },
0420 { "CPU A 1", "cpu-fan-a-0", },
0421 { "CPU A 2", "cpu-fan-b-0", },
0422 { "CPU A 3", "cpu-fan-c-0", },
0423 { "CPU B 1", "cpu-fan-a-1", },
0424 { "CPU B 2", "cpu-fan-b-1", },
0425 { "CPU B 3", "cpu-fan-c-1", },
0426 };
0427 struct device_node *np, *fcu = pv->i2c->dev.of_node;
0428 int i;
0429
0430 DBG("Looking up FCU controls in device-tree...\n");
0431
0432 for_each_child_of_node(fcu, np) {
0433 int id, type = -1;
0434 const char *loc;
0435 const char *name;
0436 const u32 *reg;
0437
0438 DBG(" control: %pOFn, type: %s\n", np, of_node_get_device_type(np));
0439
0440
0441 if (of_node_is_type(np, "fan-rpm-control") ||
0442 of_node_is_type(np, "fan-rpm"))
0443 type = FCU_FAN_RPM;
0444 if (of_node_is_type(np, "fan-pwm-control") ||
0445 of_node_is_type(np, "fan-pwm"))
0446 type = FCU_FAN_PWM;
0447
0448 if (type == -1)
0449 continue;
0450
0451
0452 loc = of_get_property(np, "location", NULL);
0453 reg = of_get_property(np, "reg", NULL);
0454 if (loc == NULL || reg == NULL)
0455 continue;
0456 DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg);
0457
0458 for (i = 0; i < ARRAY_SIZE(loc_trans); i++) {
0459 if (strncmp(loc, loc_trans[i].dt_name,
0460 strlen(loc_trans[i].dt_name)))
0461 continue;
0462 name = loc_trans[i].ct_name;
0463
0464 DBG(" location match, name: %s\n", name);
0465
0466 if (type == FCU_FAN_RPM)
0467 id = ((*reg) - 0x10) / 2;
0468 else
0469 id = ((*reg) - 0x30) / 2;
0470 if (id > 7) {
0471 pr_warn("wf_fcu: Can't parse fan ID in device-tree for %pOF\n", np);
0472 break;
0473 }
0474 wf_fcu_add_fan(pv, name, type, id);
0475 break;
0476 }
0477 }
0478 }
0479
0480 static void wf_fcu_default_fans(struct wf_fcu_priv *pv)
0481 {
0482
0483 if (!of_machine_is_compatible("PowerMac7,2"))
0484 return;
0485
0486 wf_fcu_add_fan(pv, "backside-fan", FCU_FAN_PWM, 1);
0487 wf_fcu_add_fan(pv, "drive-bay-fan", FCU_FAN_RPM, 2);
0488 wf_fcu_add_fan(pv, "slots-fan", FCU_FAN_PWM, 2);
0489 wf_fcu_add_fan(pv, "cpu-front-fan-0", FCU_FAN_RPM, 3);
0490 wf_fcu_add_fan(pv, "cpu-rear-fan-0", FCU_FAN_RPM, 4);
0491 wf_fcu_add_fan(pv, "cpu-front-fan-1", FCU_FAN_RPM, 5);
0492 wf_fcu_add_fan(pv, "cpu-rear-fan-1", FCU_FAN_RPM, 6);
0493 }
0494
0495 static int wf_fcu_init_chip(struct wf_fcu_priv *pv)
0496 {
0497 unsigned char buf = 0xff;
0498 int rc;
0499
0500 rc = wf_fcu_write_reg(pv, 0xe, &buf, 1);
0501 if (rc < 0)
0502 return -EIO;
0503 rc = wf_fcu_write_reg(pv, 0x2e, &buf, 1);
0504 if (rc < 0)
0505 return -EIO;
0506 rc = wf_fcu_read_reg(pv, 0, &buf, 1);
0507 if (rc < 0)
0508 return -EIO;
0509 pv->rpm_shift = (buf == 1) ? 2 : 3;
0510
0511 pr_debug("wf_fcu: FCU Initialized, RPM fan shift is %d\n",
0512 pv->rpm_shift);
0513
0514 return 0;
0515 }
0516
0517 static int wf_fcu_probe(struct i2c_client *client,
0518 const struct i2c_device_id *id)
0519 {
0520 struct wf_fcu_priv *pv;
0521
0522 pv = kzalloc(sizeof(*pv), GFP_KERNEL);
0523 if (!pv)
0524 return -ENOMEM;
0525
0526 kref_init(&pv->ref);
0527 mutex_init(&pv->lock);
0528 INIT_LIST_HEAD(&pv->fan_list);
0529 pv->i2c = client;
0530
0531
0532
0533
0534
0535 if (wf_fcu_init_chip(pv)) {
0536 pr_err("wf_fcu: Initialization failed !\n");
0537 kfree(pv);
0538 return -ENXIO;
0539 }
0540
0541
0542 wf_fcu_lookup_fans(pv);
0543
0544
0545
0546
0547
0548 if (list_empty(&pv->fan_list))
0549 wf_fcu_default_fans(pv);
0550
0551
0552 if (list_empty(&pv->fan_list)) {
0553 pr_err("wf_fcu: Failed to find fans for your machine\n");
0554 kfree(pv);
0555 return -ENODEV;
0556 }
0557
0558 dev_set_drvdata(&client->dev, pv);
0559
0560 return 0;
0561 }
0562
0563 static int wf_fcu_remove(struct i2c_client *client)
0564 {
0565 struct wf_fcu_priv *pv = dev_get_drvdata(&client->dev);
0566 struct wf_fcu_fan *fan;
0567
0568 while (!list_empty(&pv->fan_list)) {
0569 fan = list_first_entry(&pv->fan_list, struct wf_fcu_fan, link);
0570 list_del(&fan->link);
0571 wf_unregister_control(&fan->ctrl);
0572 }
0573 kref_put(&pv->ref, wf_fcu_release);
0574 return 0;
0575 }
0576
0577 static const struct i2c_device_id wf_fcu_id[] = {
0578 { "MAC,fcu", 0 },
0579 { }
0580 };
0581 MODULE_DEVICE_TABLE(i2c, wf_fcu_id);
0582
0583 static const struct of_device_id wf_fcu_of_id[] = {
0584 { .compatible = "fcu", },
0585 { }
0586 };
0587 MODULE_DEVICE_TABLE(of, wf_fcu_of_id);
0588
0589 static struct i2c_driver wf_fcu_driver = {
0590 .driver = {
0591 .name = "wf_fcu",
0592 .of_match_table = wf_fcu_of_id,
0593 },
0594 .probe = wf_fcu_probe,
0595 .remove = wf_fcu_remove,
0596 .id_table = wf_fcu_id,
0597 };
0598
0599 module_i2c_driver(wf_fcu_driver);
0600
0601 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
0602 MODULE_DESCRIPTION("FCU control objects for PowerMacs thermal control");
0603 MODULE_LICENSE("GPL");
0604