Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Windfarm PowerMac thermal control. FCU fan control
0004  *
0005  * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
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  * This option is "weird" :) Basically, if you define this to 1
0035  * the control loop for the RPMs fans (not PWMs) will apply the
0036  * correction factor obtained from the PID to the actual RPM
0037  * speed read from the FCU.
0038  *
0039  * If you define the below constant to 0, then it will be
0040  * applied to the setpoint RPM speed, that is basically the
0041  * speed we proviously "asked" for.
0042  *
0043  * I'm using 0 for now which is what therm_pm72 used to do and
0044  * what Darwin -apparently- does based on observed behaviour.
0045  */
0046 #define RPM_PID_USE_ACTUAL_SPEED    0
0047 
0048 /* Default min/max for pumps */
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     /* Programmed value or real current speed */
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     /* Try to fetch pumps min/max infos from eeprom */
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     /* Double check the values, this _IS_ needed as the EEPROM on
0304      * some dual 2.5Ghz G5s seem, at least, to have both min & max
0305      * same to the same value ... (grrrr)
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     /* Default */
0326     fan->min = 2400 >> pv->rpm_shift;
0327     fan->max = 56000 >> pv->rpm_shift;
0328 
0329     /* CPU fans have min/max in MPU */
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     /* Rackmac variants, we just use mpu0 intake */
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     /* min/max is oddball but the code comes from
0375      * therm_pm72 which seems to work so ...
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     /* Translation of device-tree location properties to
0403      * windfarm fan names
0404      */
0405     static const struct {
0406         const char *dt_name;    /* Device-tree name */
0407         const char *ct_name;    /* Control 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         /* Detect control type */
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         /* Only care about fans for now */
0448         if (type == -1)
0449             continue;
0450 
0451         /* Lookup for a matching location */
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     /* We only support the default fans for PowerMac7,2 */
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      * First we must start the FCU which will query the
0533      * shift value to apply to RPMs
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     /* First lookup fans in the device-tree */
0542     wf_fcu_lookup_fans(pv);
0543 
0544     /*
0545      * Older machines don't have the device-tree entries
0546      * we are looking for, just hard code the list
0547      */
0548     if (list_empty(&pv->fan_list))
0549         wf_fcu_default_fans(pv);
0550 
0551     /* Still no fans ? FAIL */
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