1 /* 2 * Windfarm PowerMac thermal control. FCU fan control 3 * 4 * Copyright 2012 Benjamin Herrenschmidt, IBM Corp. 5 * 6 * Released under the term of the GNU GPL v2. 7 */ 8 #undef DEBUG 9 10 #include <linux/types.h> 11 #include <linux/errno.h> 12 #include <linux/kernel.h> 13 #include <linux/delay.h> 14 #include <linux/slab.h> 15 #include <linux/init.h> 16 #include <linux/wait.h> 17 #include <linux/i2c.h> 18 #include <asm/prom.h> 19 #include <asm/machdep.h> 20 #include <asm/io.h> 21 #include <asm/sections.h> 22 23 #include "windfarm.h" 24 #include "windfarm_mpu.h" 25 26 #define VERSION "1.0" 27 28 #ifdef DEBUG 29 #define DBG(args...) printk(args) 30 #else 31 #define DBG(args...) do { } while(0) 32 #endif 33 34 /* 35 * This option is "weird" :) Basically, if you define this to 1 36 * the control loop for the RPMs fans (not PWMs) will apply the 37 * correction factor obtained from the PID to the actual RPM 38 * speed read from the FCU. 39 * 40 * If you define the below constant to 0, then it will be 41 * applied to the setpoint RPM speed, that is basically the 42 * speed we proviously "asked" for. 43 * 44 * I'm using 0 for now which is what therm_pm72 used to do and 45 * what Darwin -apparently- does based on observed behaviour. 46 */ 47 #define RPM_PID_USE_ACTUAL_SPEED 0 48 49 /* Default min/max for pumps */ 50 #define CPU_PUMP_OUTPUT_MAX 3200 51 #define CPU_PUMP_OUTPUT_MIN 1250 52 53 #define FCU_FAN_RPM 0 54 #define FCU_FAN_PWM 1 55 56 struct wf_fcu_priv { 57 struct kref ref; 58 struct i2c_client *i2c; 59 struct mutex lock; 60 struct list_head fan_list; 61 int rpm_shift; 62 }; 63 64 struct wf_fcu_fan { 65 struct list_head link; 66 int id; 67 s32 min, max, target; 68 struct wf_fcu_priv *fcu_priv; 69 struct wf_control ctrl; 70 }; 71 72 static void wf_fcu_release(struct kref *ref) 73 { 74 struct wf_fcu_priv *pv = container_of(ref, struct wf_fcu_priv, ref); 75 76 kfree(pv); 77 } 78 79 static void wf_fcu_fan_release(struct wf_control *ct) 80 { 81 struct wf_fcu_fan *fan = ct->priv; 82 83 kref_put(&fan->fcu_priv->ref, wf_fcu_release); 84 kfree(fan); 85 } 86 87 static int wf_fcu_read_reg(struct wf_fcu_priv *pv, int reg, 88 unsigned char *buf, int nb) 89 { 90 int tries, nr, nw; 91 92 mutex_lock(&pv->lock); 93 94 buf[0] = reg; 95 tries = 0; 96 for (;;) { 97 nw = i2c_master_send(pv->i2c, buf, 1); 98 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100) 99 break; 100 msleep(10); 101 ++tries; 102 } 103 if (nw <= 0) { 104 pr_err("Failure writing address to FCU: %d", nw); 105 nr = nw; 106 goto bail; 107 } 108 tries = 0; 109 for (;;) { 110 nr = i2c_master_recv(pv->i2c, buf, nb); 111 if (nr > 0 || (nr < 0 && nr != -ENODEV) || tries >= 100) 112 break; 113 msleep(10); 114 ++tries; 115 } 116 if (nr <= 0) 117 pr_err("wf_fcu: Failure reading data from FCU: %d", nw); 118 bail: 119 mutex_unlock(&pv->lock); 120 return nr; 121 } 122 123 static int wf_fcu_write_reg(struct wf_fcu_priv *pv, int reg, 124 const unsigned char *ptr, int nb) 125 { 126 int tries, nw; 127 unsigned char buf[16]; 128 129 buf[0] = reg; 130 memcpy(buf+1, ptr, nb); 131 ++nb; 132 tries = 0; 133 for (;;) { 134 nw = i2c_master_send(pv->i2c, buf, nb); 135 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100) 136 break; 137 msleep(10); 138 ++tries; 139 } 140 if (nw < 0) 141 pr_err("wf_fcu: Failure writing to FCU: %d", nw); 142 return nw; 143 } 144 145 static int wf_fcu_fan_set_rpm(struct wf_control *ct, s32 value) 146 { 147 struct wf_fcu_fan *fan = ct->priv; 148 struct wf_fcu_priv *pv = fan->fcu_priv; 149 int rc, shift = pv->rpm_shift; 150 unsigned char buf[2]; 151 152 if (value < fan->min) 153 value = fan->min; 154 if (value > fan->max) 155 value = fan->max; 156 157 fan->target = value; 158 159 buf[0] = value >> (8 - shift); 160 buf[1] = value << shift; 161 rc = wf_fcu_write_reg(pv, 0x10 + (fan->id * 2), buf, 2); 162 if (rc < 0) 163 return -EIO; 164 return 0; 165 } 166 167 static int wf_fcu_fan_get_rpm(struct wf_control *ct, s32 *value) 168 { 169 struct wf_fcu_fan *fan = ct->priv; 170 struct wf_fcu_priv *pv = fan->fcu_priv; 171 int rc, reg_base, shift = pv->rpm_shift; 172 unsigned char failure; 173 unsigned char active; 174 unsigned char buf[2]; 175 176 rc = wf_fcu_read_reg(pv, 0xb, &failure, 1); 177 if (rc != 1) 178 return -EIO; 179 if ((failure & (1 << fan->id)) != 0) 180 return -EFAULT; 181 rc = wf_fcu_read_reg(pv, 0xd, &active, 1); 182 if (rc != 1) 183 return -EIO; 184 if ((active & (1 << fan->id)) == 0) 185 return -ENXIO; 186 187 /* Programmed value or real current speed */ 188 #if RPM_PID_USE_ACTUAL_SPEED 189 reg_base = 0x11; 190 #else 191 reg_base = 0x10; 192 #endif 193 rc = wf_fcu_read_reg(pv, reg_base + (fan->id * 2), buf, 2); 194 if (rc != 2) 195 return -EIO; 196 197 *value = (buf[0] << (8 - shift)) | buf[1] >> shift; 198 199 return 0; 200 } 201 202 static int wf_fcu_fan_set_pwm(struct wf_control *ct, s32 value) 203 { 204 struct wf_fcu_fan *fan = ct->priv; 205 struct wf_fcu_priv *pv = fan->fcu_priv; 206 unsigned char buf[2]; 207 int rc; 208 209 if (value < fan->min) 210 value = fan->min; 211 if (value > fan->max) 212 value = fan->max; 213 214 fan->target = value; 215 216 value = (value * 2559) / 1000; 217 buf[0] = value; 218 rc = wf_fcu_write_reg(pv, 0x30 + (fan->id * 2), buf, 1); 219 if (rc < 0) 220 return -EIO; 221 return 0; 222 } 223 224 static int wf_fcu_fan_get_pwm(struct wf_control *ct, s32 *value) 225 { 226 struct wf_fcu_fan *fan = ct->priv; 227 struct wf_fcu_priv *pv = fan->fcu_priv; 228 unsigned char failure; 229 unsigned char active; 230 unsigned char buf[2]; 231 int rc; 232 233 rc = wf_fcu_read_reg(pv, 0x2b, &failure, 1); 234 if (rc != 1) 235 return -EIO; 236 if ((failure & (1 << fan->id)) != 0) 237 return -EFAULT; 238 rc = wf_fcu_read_reg(pv, 0x2d, &active, 1); 239 if (rc != 1) 240 return -EIO; 241 if ((active & (1 << fan->id)) == 0) 242 return -ENXIO; 243 244 rc = wf_fcu_read_reg(pv, 0x30 + (fan->id * 2), buf, 1); 245 if (rc != 1) 246 return -EIO; 247 248 *value = (((s32)buf[0]) * 1000) / 2559; 249 250 return 0; 251 } 252 253 static s32 wf_fcu_fan_min(struct wf_control *ct) 254 { 255 struct wf_fcu_fan *fan = ct->priv; 256 257 return fan->min; 258 } 259 260 static s32 wf_fcu_fan_max(struct wf_control *ct) 261 { 262 struct wf_fcu_fan *fan = ct->priv; 263 264 return fan->max; 265 } 266 267 static const struct wf_control_ops wf_fcu_fan_rpm_ops = { 268 .set_value = wf_fcu_fan_set_rpm, 269 .get_value = wf_fcu_fan_get_rpm, 270 .get_min = wf_fcu_fan_min, 271 .get_max = wf_fcu_fan_max, 272 .release = wf_fcu_fan_release, 273 .owner = THIS_MODULE, 274 }; 275 276 static const struct wf_control_ops wf_fcu_fan_pwm_ops = { 277 .set_value = wf_fcu_fan_set_pwm, 278 .get_value = wf_fcu_fan_get_pwm, 279 .get_min = wf_fcu_fan_min, 280 .get_max = wf_fcu_fan_max, 281 .release = wf_fcu_fan_release, 282 .owner = THIS_MODULE, 283 }; 284 285 static void wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan) 286 { 287 const struct mpu_data *mpu = wf_get_mpu(0); 288 u16 pump_min = 0, pump_max = 0xffff; 289 u16 tmp[4]; 290 291 /* Try to fetch pumps min/max infos from eeprom */ 292 if (mpu) { 293 memcpy(&tmp, mpu->processor_part_num, 8); 294 if (tmp[0] != 0xffff && tmp[1] != 0xffff) { 295 pump_min = max(pump_min, tmp[0]); 296 pump_max = min(pump_max, tmp[1]); 297 } 298 if (tmp[2] != 0xffff && tmp[3] != 0xffff) { 299 pump_min = max(pump_min, tmp[2]); 300 pump_max = min(pump_max, tmp[3]); 301 } 302 } 303 304 /* Double check the values, this _IS_ needed as the EEPROM on 305 * some dual 2.5Ghz G5s seem, at least, to have both min & max 306 * same to the same value ... (grrrr) 307 */ 308 if (pump_min == pump_max || pump_min == 0 || pump_max == 0xffff) { 309 pump_min = CPU_PUMP_OUTPUT_MIN; 310 pump_max = CPU_PUMP_OUTPUT_MAX; 311 } 312 313 fan->min = pump_min; 314 fan->max = pump_max; 315 316 DBG("wf_fcu: pump min/max for %s set to: [%d..%d] RPM\n", 317 fan->ctrl.name, pump_min, pump_max); 318 } 319 320 static void wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan) 321 { 322 struct wf_fcu_priv *pv = fan->fcu_priv; 323 const struct mpu_data *mpu0 = wf_get_mpu(0); 324 const struct mpu_data *mpu1 = wf_get_mpu(1); 325 326 /* Default */ 327 fan->min = 2400 >> pv->rpm_shift; 328 fan->max = 56000 >> pv->rpm_shift; 329 330 /* CPU fans have min/max in MPU */ 331 if (mpu0 && !strcmp(fan->ctrl.name, "cpu-front-fan-0")) { 332 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan); 333 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan); 334 goto bail; 335 } 336 if (mpu1 && !strcmp(fan->ctrl.name, "cpu-front-fan-1")) { 337 fan->min = max(fan->min, (s32)mpu1->rminn_intake_fan); 338 fan->max = min(fan->max, (s32)mpu1->rmaxn_intake_fan); 339 goto bail; 340 } 341 if (mpu0 && !strcmp(fan->ctrl.name, "cpu-rear-fan-0")) { 342 fan->min = max(fan->min, (s32)mpu0->rminn_exhaust_fan); 343 fan->max = min(fan->max, (s32)mpu0->rmaxn_exhaust_fan); 344 goto bail; 345 } 346 if (mpu1 && !strcmp(fan->ctrl.name, "cpu-rear-fan-1")) { 347 fan->min = max(fan->min, (s32)mpu1->rminn_exhaust_fan); 348 fan->max = min(fan->max, (s32)mpu1->rmaxn_exhaust_fan); 349 goto bail; 350 } 351 /* Rackmac variants, we just use mpu0 intake */ 352 if (!strncmp(fan->ctrl.name, "cpu-fan", 7)) { 353 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan); 354 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan); 355 goto bail; 356 } 357 bail: 358 DBG("wf_fcu: fan min/max for %s set to: [%d..%d] RPM\n", 359 fan->ctrl.name, fan->min, fan->max); 360 } 361 362 static void wf_fcu_add_fan(struct wf_fcu_priv *pv, const char *name, 363 int type, int id) 364 { 365 struct wf_fcu_fan *fan; 366 367 fan = kzalloc(sizeof(*fan), GFP_KERNEL); 368 if (!fan) 369 return; 370 fan->fcu_priv = pv; 371 fan->id = id; 372 fan->ctrl.name = name; 373 fan->ctrl.priv = fan; 374 375 /* min/max is oddball but the code comes from 376 * therm_pm72 which seems to work so ... 377 */ 378 if (type == FCU_FAN_RPM) { 379 if (!strncmp(name, "cpu-pump", strlen("cpu-pump"))) 380 wf_fcu_get_pump_minmax(fan); 381 else 382 wf_fcu_get_rpmfan_minmax(fan); 383 fan->ctrl.type = WF_CONTROL_RPM_FAN; 384 fan->ctrl.ops = &wf_fcu_fan_rpm_ops; 385 } else { 386 fan->min = 10; 387 fan->max = 100; 388 fan->ctrl.type = WF_CONTROL_PWM_FAN; 389 fan->ctrl.ops = &wf_fcu_fan_pwm_ops; 390 } 391 392 if (wf_register_control(&fan->ctrl)) { 393 pr_err("wf_fcu: Failed to register fan %s\n", name); 394 kfree(fan); 395 return; 396 } 397 list_add(&fan->link, &pv->fan_list); 398 kref_get(&pv->ref); 399 } 400 401 static void wf_fcu_lookup_fans(struct wf_fcu_priv *pv) 402 { 403 /* Translation of device-tree location properties to 404 * windfarm fan names 405 */ 406 static const struct { 407 const char *dt_name; /* Device-tree name */ 408 const char *ct_name; /* Control name */ 409 } loc_trans[] = { 410 { "BACKSIDE", "backside-fan", }, 411 { "SYS CTRLR FAN", "backside-fan", }, 412 { "DRIVE BAY", "drive-bay-fan", }, 413 { "SLOT", "slots-fan", }, 414 { "PCI FAN", "slots-fan", }, 415 { "CPU A INTAKE", "cpu-front-fan-0", }, 416 { "CPU A EXHAUST", "cpu-rear-fan-0", }, 417 { "CPU B INTAKE", "cpu-front-fan-1", }, 418 { "CPU B EXHAUST", "cpu-rear-fan-1", }, 419 { "CPU A PUMP", "cpu-pump-0", }, 420 { "CPU B PUMP", "cpu-pump-1", }, 421 { "CPU A 1", "cpu-fan-a-0", }, 422 { "CPU A 2", "cpu-fan-b-0", }, 423 { "CPU A 3", "cpu-fan-c-0", }, 424 { "CPU B 1", "cpu-fan-a-1", }, 425 { "CPU B 2", "cpu-fan-b-1", }, 426 { "CPU B 3", "cpu-fan-c-1", }, 427 }; 428 struct device_node *np = NULL, *fcu = pv->i2c->dev.of_node; 429 int i; 430 431 DBG("Looking up FCU controls in device-tree...\n"); 432 433 while ((np = of_get_next_child(fcu, np)) != NULL) { 434 int id, type = -1; 435 const char *loc; 436 const char *name; 437 const u32 *reg; 438 439 DBG(" control: %s, type: %s\n", np->name, np->type); 440 441 /* Detect control type */ 442 if (!strcmp(np->type, "fan-rpm-control") || 443 !strcmp(np->type, "fan-rpm")) 444 type = FCU_FAN_RPM; 445 if (!strcmp(np->type, "fan-pwm-control") || 446 !strcmp(np->type, "fan-pwm")) 447 type = FCU_FAN_PWM; 448 /* Only care about fans for now */ 449 if (type == -1) 450 continue; 451 452 /* Lookup for a matching location */ 453 loc = of_get_property(np, "location", NULL); 454 reg = of_get_property(np, "reg", NULL); 455 if (loc == NULL || reg == NULL) 456 continue; 457 DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg); 458 459 for (i = 0; i < ARRAY_SIZE(loc_trans); i++) { 460 if (strncmp(loc, loc_trans[i].dt_name, 461 strlen(loc_trans[i].dt_name))) 462 continue; 463 name = loc_trans[i].ct_name; 464 465 DBG(" location match, name: %s\n", name); 466 467 if (type == FCU_FAN_RPM) 468 id = ((*reg) - 0x10) / 2; 469 else 470 id = ((*reg) - 0x30) / 2; 471 if (id > 7) { 472 pr_warning("wf_fcu: Can't parse " 473 "fan ID in device-tree for %s\n", 474 np->full_name); 475 break; 476 } 477 wf_fcu_add_fan(pv, name, type, id); 478 break; 479 } 480 } 481 } 482 483 static void wf_fcu_default_fans(struct wf_fcu_priv *pv) 484 { 485 /* We only support the default fans for PowerMac7,2 */ 486 if (!of_machine_is_compatible("PowerMac7,2")) 487 return; 488 489 wf_fcu_add_fan(pv, "backside-fan", FCU_FAN_PWM, 1); 490 wf_fcu_add_fan(pv, "drive-bay-fan", FCU_FAN_RPM, 2); 491 wf_fcu_add_fan(pv, "slots-fan", FCU_FAN_PWM, 2); 492 wf_fcu_add_fan(pv, "cpu-front-fan-0", FCU_FAN_RPM, 3); 493 wf_fcu_add_fan(pv, "cpu-rear-fan-0", FCU_FAN_RPM, 4); 494 wf_fcu_add_fan(pv, "cpu-front-fan-1", FCU_FAN_RPM, 5); 495 wf_fcu_add_fan(pv, "cpu-rear-fan-1", FCU_FAN_RPM, 6); 496 } 497 498 static int wf_fcu_init_chip(struct wf_fcu_priv *pv) 499 { 500 unsigned char buf = 0xff; 501 int rc; 502 503 rc = wf_fcu_write_reg(pv, 0xe, &buf, 1); 504 if (rc < 0) 505 return -EIO; 506 rc = wf_fcu_write_reg(pv, 0x2e, &buf, 1); 507 if (rc < 0) 508 return -EIO; 509 rc = wf_fcu_read_reg(pv, 0, &buf, 1); 510 if (rc < 0) 511 return -EIO; 512 pv->rpm_shift = (buf == 1) ? 2 : 3; 513 514 pr_debug("wf_fcu: FCU Initialized, RPM fan shift is %d\n", 515 pv->rpm_shift); 516 517 return 0; 518 } 519 520 static int wf_fcu_probe(struct i2c_client *client, 521 const struct i2c_device_id *id) 522 { 523 struct wf_fcu_priv *pv; 524 525 pv = kzalloc(sizeof(*pv), GFP_KERNEL); 526 if (!pv) 527 return -ENOMEM; 528 529 kref_init(&pv->ref); 530 mutex_init(&pv->lock); 531 INIT_LIST_HEAD(&pv->fan_list); 532 pv->i2c = client; 533 534 /* 535 * First we must start the FCU which will query the 536 * shift value to apply to RPMs 537 */ 538 if (wf_fcu_init_chip(pv)) { 539 pr_err("wf_fcu: Initialization failed !\n"); 540 kfree(pv); 541 return -ENXIO; 542 } 543 544 /* First lookup fans in the device-tree */ 545 wf_fcu_lookup_fans(pv); 546 547 /* 548 * Older machines don't have the device-tree entries 549 * we are looking for, just hard code the list 550 */ 551 if (list_empty(&pv->fan_list)) 552 wf_fcu_default_fans(pv); 553 554 /* Still no fans ? FAIL */ 555 if (list_empty(&pv->fan_list)) { 556 pr_err("wf_fcu: Failed to find fans for your machine\n"); 557 kfree(pv); 558 return -ENODEV; 559 } 560 561 dev_set_drvdata(&client->dev, pv); 562 563 return 0; 564 } 565 566 static int wf_fcu_remove(struct i2c_client *client) 567 { 568 struct wf_fcu_priv *pv = dev_get_drvdata(&client->dev); 569 struct wf_fcu_fan *fan; 570 571 while (!list_empty(&pv->fan_list)) { 572 fan = list_first_entry(&pv->fan_list, struct wf_fcu_fan, link); 573 list_del(&fan->link); 574 wf_unregister_control(&fan->ctrl); 575 } 576 kref_put(&pv->ref, wf_fcu_release); 577 return 0; 578 } 579 580 static const struct i2c_device_id wf_fcu_id[] = { 581 { "MAC,fcu", 0 }, 582 { } 583 }; 584 MODULE_DEVICE_TABLE(i2c, wf_fcu_id); 585 586 static struct i2c_driver wf_fcu_driver = { 587 .driver = { 588 .name = "wf_fcu", 589 }, 590 .probe = wf_fcu_probe, 591 .remove = wf_fcu_remove, 592 .id_table = wf_fcu_id, 593 }; 594 595 module_i2c_driver(wf_fcu_driver); 596 597 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); 598 MODULE_DESCRIPTION("FCU control objects for PowerMacs thermal control"); 599 MODULE_LICENSE("GPL"); 600 601