VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
2c162f9b41722 (Thomas Gleixner        2019-06-03 07:45:02 +0200   1) // SPDX-License-Identifier: GPL-2.0-only
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   2) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   3)  * Windfarm PowerMac thermal control. iMac G5
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   4)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   5)  * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   6)  *                    <benh@kernel.crashing.org>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   7)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   8)  * The algorithm used is the PID control algorithm, used the same
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100   9)  * way the published Darwin code does, using the same values that
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  10)  * are present in the Darwin 8.2 snapshot property lists (note however
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  11)  * that none of the code has been re-used, it's a complete re-implementation
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  12)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  13)  * The various control loops found in Darwin config file are:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  14)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  15)  * PowerMac8,1 and PowerMac8,2
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  16)  * ===========================
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  17)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  18)  * System Fans control loop. Different based on models. In addition to the
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  19)  * usual PID algorithm, the control loop gets 2 additional pairs of linear
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  20)  * scaling factors (scale/offsets) expressed as 4.12 fixed point values
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  21)  * signed offset, unsigned scale)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  22)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  23)  * The targets are modified such as:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  24)  *  - the linked control (second control) gets the target value as-is
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  25)  *    (typically the drive fan)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  26)  *  - the main control (first control) gets the target value scaled with
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  27)  *    the first pair of factors, and is then modified as below
943ffb587cfdf (Adrian Bunk            2006-01-10 00:10:13 +0100  28)  *  - the value of the target of the CPU Fan control loop is retrieved,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  29)  *    scaled with the second pair of factors, and the max of that and
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  30)  *    the scaled target is applied to the main control.
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  31)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  32)  * # model_id: 2
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  33)  *   controls       : system-fan, drive-bay-fan
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  34)  *   sensors        : hd-temp
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  35)  *   PID params     : G_d = 0x15400000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  36)  *                    G_p = 0x00200000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  37)  *                    G_r = 0x000002fd
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  38)  *                    History = 2 entries
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  39)  *                    Input target = 0x3a0000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  40)  *                    Interval = 5s
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  41)  *   linear-factors : offset = 0xff38 scale  = 0x0ccd
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  42)  *                    offset = 0x0208 scale  = 0x07ae
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  43)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  44)  * # model_id: 3
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  45)  *   controls       : system-fan, drive-bay-fan
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  46)  *   sensors        : hd-temp
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  47)  *   PID params     : G_d = 0x08e00000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  48)  *                    G_p = 0x00566666
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  49)  *                    G_r = 0x0000072b
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  50)  *                    History = 2 entries
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  51)  *                    Input target = 0x350000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  52)  *                    Interval = 5s
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  53)  *   linear-factors : offset = 0xff38 scale  = 0x0ccd
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  54)  *                    offset = 0x0000 scale  = 0x0000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  55)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  56)  * # model_id: 5
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  57)  *   controls       : system-fan
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  58)  *   sensors        : hd-temp
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  59)  *   PID params     : G_d = 0x15400000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  60)  *                    G_p = 0x00233333
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  61)  *                    G_r = 0x000002fd
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  62)  *                    History = 2 entries
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  63)  *                    Input target = 0x3a0000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  64)  *                    Interval = 5s
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  65)  *   linear-factors : offset = 0x0000 scale  = 0x1000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  66)  *                    offset = 0x0091 scale  = 0x0bae
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  67)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  68)  * CPU Fan control loop. The loop is identical for all models. it
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  69)  * has an additional pair of scaling factor. This is used to scale the
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  70)  * systems fan control loop target result (the one before it gets scaled
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  71)  * by the System Fans control loop itself). Then, the max value of the
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  72)  * calculated target value and system fan value is sent to the fans
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  73)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  74)  *   controls       : cpu-fan
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  75)  *   sensors        : cpu-temp cpu-power
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  76)  *   PID params     : From SMU sdb partition
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  77)  *   linear-factors : offset = 0xfb50 scale  = 0x1000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  78)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  79)  * CPU Slew control loop. Not implemented. The cpufreq driver in linux is
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  80)  * completely separate for now, though we could find a way to link it, either
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  81)  * as a client reacting to overtemp notifications, or directling monitoring
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  82)  * the CPU temperature
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  83)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  84)  * WARNING ! The CPU control loop requires the CPU tmax for the current
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  85)  * operating point. However, we currently are completely separated from
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  86)  * the cpufreq driver and thus do not know what the current operating
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  87)  * point is. Fortunately, we also do not have any hardware supporting anything
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  88)  * but operating point 0 at the moment, thus we just peek that value directly
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  89)  * from the SDB partition. If we ever end up with actually slewing the system
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  90)  * clock and thus changing operating points, we'll have to find a way to
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  91)  * communicate with the CPU freq driver;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  92)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  93) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  94) #include <linux/types.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  95) #include <linux/errno.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  96) #include <linux/kernel.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  97) #include <linux/delay.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  98) #include <linux/slab.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100  99) #include <linux/init.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 100) #include <linux/spinlock.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 101) #include <linux/wait.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 102) #include <linux/kmod.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 103) #include <linux/device.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 104) #include <linux/platform_device.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 105) #include <asm/prom.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 106) #include <asm/machdep.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 107) #include <asm/io.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 108) #include <asm/sections.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 109) #include <asm/smu.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 110) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 111) #include "windfarm.h"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 112) #include "windfarm_pid.h"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 113) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 114) #define VERSION "0.4"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 115) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 116) #undef DEBUG
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 117) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 118) #ifdef DEBUG
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 119) #define DBG(args...)	printk(args)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 120) #else
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 121) #define DBG(args...)	do { } while(0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 122) #endif
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 123) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 124) /* define this to force CPU overtemp to 74 degree, useful for testing
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 125)  * the overtemp code
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 126)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 127) #undef HACKED_OVERTEMP
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 128) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 129) static int wf_smu_mach_model;	/* machine model id */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 130) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 131) /* Controls & sensors */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 132) static struct wf_sensor	*sensor_cpu_power;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 133) static struct wf_sensor	*sensor_cpu_temp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 134) static struct wf_sensor	*sensor_hd_temp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 135) static struct wf_control *fan_cpu_main;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 136) static struct wf_control *fan_hd;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 137) static struct wf_control *fan_system;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 138) static struct wf_control *cpufreq_clamp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 139) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 140) /* Set to kick the control loop into life */
4f256d561447c (Gustavo A. R. Silva    2018-01-23 19:42:28 -0600 141) static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok;
4f256d561447c (Gustavo A. R. Silva    2018-01-23 19:42:28 -0600 142) static bool wf_smu_started;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 143) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 144) /* Failure handling.. could be nicer */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 145) #define FAILURE_FAN		0x01
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 146) #define FAILURE_SENSOR		0x02
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 147) #define FAILURE_OVERTEMP	0x04
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 148) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 149) static unsigned int wf_smu_failure_state;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 150) static int wf_smu_readjust, wf_smu_skipping;
4bb2971134330 (Aaro Koskinen          2013-06-30 22:00:42 +0300 151) static bool wf_smu_overtemp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 152) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 153) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 154)  * ****** System Fans Control Loop ******
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 155)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 156)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 157) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 158) /* Parameters for the System Fans control loop. Parameters
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 159)  * not in this table such as interval, history size, ...
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 160)  * are common to all versions and thus hard coded for now.
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 161)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 162) struct wf_smu_sys_fans_param {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 163) 	int	model_id;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 164) 	s32	itarget;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 165) 	s32	gd, gp, gr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 166) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 167) 	s16	offset0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 168) 	u16	scale0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 169) 	s16	offset1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 170) 	u16	scale1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 171) };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 172) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 173) #define WF_SMU_SYS_FANS_INTERVAL	5
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 174) #define WF_SMU_SYS_FANS_HISTORY_SIZE	2
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 175) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 176) /* State data used by the system fans control loop
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 177)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 178) struct wf_smu_sys_fans_state {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 179) 	int			ticks;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 180) 	s32			sys_setpoint;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 181) 	s32			hd_setpoint;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 182) 	s16			offset0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 183) 	u16			scale0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 184) 	s16			offset1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 185) 	u16			scale1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 186) 	struct wf_pid_state	pid;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 187) };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 188) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 189) /*
8839316121049 (Thomas Weber           2010-03-16 11:47:56 +0100 190)  * Configs for SMU System Fan control loop
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 191)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 192) static struct wf_smu_sys_fans_param wf_smu_sys_all_params[] = {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 193) 	/* Model ID 2 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 194) 	{
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 195) 		.model_id	= 2,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 196) 		.itarget	= 0x3a0000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 197) 		.gd		= 0x15400000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 198) 		.gp		= 0x00200000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 199) 		.gr		= 0x000002fd,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 200) 		.offset0	= 0xff38,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 201) 		.scale0		= 0x0ccd,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 202) 		.offset1	= 0x0208,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 203) 		.scale1		= 0x07ae,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 204) 	},
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 205) 	/* Model ID 3 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 206) 	{
326743ead7d0c (Michal Ostrowski       2005-12-08 16:56:17 +1100 207) 		.model_id	= 3,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 208) 		.itarget	= 0x350000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 209) 		.gd		= 0x08e00000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 210) 		.gp		= 0x00566666,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 211) 		.gr		= 0x0000072b,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 212) 		.offset0	= 0xff38,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 213) 		.scale0		= 0x0ccd,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 214) 		.offset1	= 0x0000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 215) 		.scale1		= 0x0000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 216) 	},
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 217) 	/* Model ID 5 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 218) 	{
326743ead7d0c (Michal Ostrowski       2005-12-08 16:56:17 +1100 219) 		.model_id	= 5,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 220) 		.itarget	= 0x3a0000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 221) 		.gd		= 0x15400000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 222) 		.gp		= 0x00233333,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 223) 		.gr		= 0x000002fd,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 224) 		.offset0	= 0x0000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 225) 		.scale0		= 0x1000,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 226) 		.offset1	= 0x0091,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 227) 		.scale1		= 0x0bae,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 228) 	},
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 229) };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 230) #define WF_SMU_SYS_FANS_NUM_CONFIGS ARRAY_SIZE(wf_smu_sys_all_params)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 231) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 232) static struct wf_smu_sys_fans_state *wf_smu_sys_fans;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 233) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 234) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 235)  * ****** CPU Fans Control Loop ******
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 236)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 237)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 238) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 239) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 240) #define WF_SMU_CPU_FANS_INTERVAL	1
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 241) #define WF_SMU_CPU_FANS_MAX_HISTORY	16
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 242) #define WF_SMU_CPU_FANS_SIBLING_SCALE	0x00001000
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 243) #define WF_SMU_CPU_FANS_SIBLING_OFFSET	0xfffffb50
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 244) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 245) /* State data used by the cpu fans control loop
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 246)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 247) struct wf_smu_cpu_fans_state {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 248) 	int			ticks;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 249) 	s32			cpu_setpoint;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 250) 	s32			scale;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 251) 	s32			offset;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 252) 	struct wf_cpu_pid_state	pid;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 253) };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 254) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 255) static struct wf_smu_cpu_fans_state *wf_smu_cpu_fans;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 256) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 257) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 258) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 259) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 260)  * ***** Implementation *****
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 261)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 262)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 263) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 264) static void wf_smu_create_sys_fans(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 265) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 266) 	struct wf_smu_sys_fans_param *param = NULL;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 267) 	struct wf_pid_param pid_param;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 268) 	int i;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 269) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 270) 	/* First, locate the params for this model */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 271) 	for (i = 0; i < WF_SMU_SYS_FANS_NUM_CONFIGS; i++)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 272) 		if (wf_smu_sys_all_params[i].model_id == wf_smu_mach_model) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 273) 			param = &wf_smu_sys_all_params[i];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 274) 			break;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 275) 		}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 276) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 277) 	/* No params found, put fans to max */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 278) 	if (param == NULL) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 279) 		printk(KERN_WARNING "windfarm: System fan config not found "
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 280) 		       "for this machine model, max fan speed\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 281) 		goto fail;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 282) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 283) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 284) 	/* Alloc & initialize state */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 285) 	wf_smu_sys_fans = kmalloc(sizeof(struct wf_smu_sys_fans_state),
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 286) 				  GFP_KERNEL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 287) 	if (wf_smu_sys_fans == NULL) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 288) 		printk(KERN_WARNING "windfarm: Memory allocation error"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 289) 		       " max fan speed\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 290) 		goto fail;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 291) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 292) 	wf_smu_sys_fans->ticks = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 293) 	wf_smu_sys_fans->scale0 = param->scale0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 294) 	wf_smu_sys_fans->offset0 = param->offset0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 295) 	wf_smu_sys_fans->scale1 = param->scale1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 296) 	wf_smu_sys_fans->offset1 = param->offset1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 297) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 298) 	/* Fill PID params */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 299) 	pid_param.gd = param->gd;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 300) 	pid_param.gp = param->gp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 301) 	pid_param.gr = param->gr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 302) 	pid_param.interval = WF_SMU_SYS_FANS_INTERVAL;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 303) 	pid_param.history_len = WF_SMU_SYS_FANS_HISTORY_SIZE;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 304) 	pid_param.itarget = param->itarget;
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 305) 	pid_param.min = wf_control_get_min(fan_system);
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 306) 	pid_param.max = wf_control_get_max(fan_system);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 307) 	if (fan_hd) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 308) 		pid_param.min =
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 309) 			max(pid_param.min, wf_control_get_min(fan_hd));
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 310) 		pid_param.max =
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 311) 			min(pid_param.max, wf_control_get_max(fan_hd));
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 312) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 313) 	wf_pid_init(&wf_smu_sys_fans->pid, &pid_param);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 314) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 315) 	DBG("wf: System Fan control initialized.\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 316) 	DBG("    itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 317) 	    FIX32TOPRINT(pid_param.itarget), pid_param.min, pid_param.max);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 318) 	return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 319) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 320)  fail:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 321) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 322) 	if (fan_system)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 323) 		wf_control_set_max(fan_system);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 324) 	if (fan_hd)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 325) 		wf_control_set_max(fan_hd);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 326) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 327) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 328) static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 329) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 330) 	s32 new_setpoint, temp, scaled, cputarget;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 331) 	int rc;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 332) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 333) 	if (--st->ticks != 0) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 334) 		if (wf_smu_readjust)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 335) 			goto readjust;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 336) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 337) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 338) 	st->ticks = WF_SMU_SYS_FANS_INTERVAL;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 339) 
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 340) 	rc = wf_sensor_get(sensor_hd_temp, &temp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 341) 	if (rc) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 342) 		printk(KERN_WARNING "windfarm: HD temp sensor error %d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 343) 		       rc);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 344) 		wf_smu_failure_state |= FAILURE_SENSOR;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 345) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 346) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 347) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 348) 	DBG("wf_smu: System Fans tick ! HD temp: %d.%03d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 349) 	    FIX32TOPRINT(temp));
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 350) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 351) 	if (temp > (st->pid.param.itarget + 0x50000))
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 352) 		wf_smu_failure_state |= FAILURE_OVERTEMP;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 353) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 354) 	new_setpoint = wf_pid_run(&st->pid, temp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 355) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 356) 	DBG("wf_smu: new_setpoint: %d RPM\n", (int)new_setpoint);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 357) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 358) 	scaled = ((((s64)new_setpoint) * (s64)st->scale0) >> 12) + st->offset0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 359) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 360) 	DBG("wf_smu: scaled setpoint: %d RPM\n", (int)scaled);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 361) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 362) 	cputarget = wf_smu_cpu_fans ? wf_smu_cpu_fans->pid.target : 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 363) 	cputarget = ((((s64)cputarget) * (s64)st->scale1) >> 12) + st->offset1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 364) 	scaled = max(scaled, cputarget);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 365) 	scaled = max(scaled, st->pid.param.min);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 366) 	scaled = min(scaled, st->pid.param.max);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 367) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 368) 	DBG("wf_smu: adjusted setpoint: %d RPM\n", (int)scaled);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 369) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 370) 	if (st->sys_setpoint == scaled && new_setpoint == st->hd_setpoint)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 371) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 372) 	st->sys_setpoint = scaled;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 373) 	st->hd_setpoint = new_setpoint;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 374)  readjust:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 375) 	if (fan_system && wf_smu_failure_state == 0) {
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 376) 		rc = wf_control_set(fan_system, st->sys_setpoint);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 377) 		if (rc) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 378) 			printk(KERN_WARNING "windfarm: Sys fan error %d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 379) 			       rc);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 380) 			wf_smu_failure_state |= FAILURE_FAN;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 381) 		}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 382) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 383) 	if (fan_hd && wf_smu_failure_state == 0) {
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 384) 		rc = wf_control_set(fan_hd, st->hd_setpoint);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 385) 		if (rc) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 386) 			printk(KERN_WARNING "windfarm: HD fan error %d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 387) 			       rc);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 388) 			wf_smu_failure_state |= FAILURE_FAN;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 389) 		}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 390) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 391) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 392) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 393) static void wf_smu_create_cpu_fans(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 394) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 395) 	struct wf_cpu_pid_param pid_param;
018a3d1db7cdb (Jeremy Kerr            2006-07-12 15:40:29 +1000 396) 	const struct smu_sdbp_header *hdr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 397) 	struct smu_sdbp_cpupiddata *piddata;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 398) 	struct smu_sdbp_fvt *fvt;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 399) 	s32 tmax, tdelta, maxpow, powadj;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 400) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 401) 	/* First, locate the PID params in SMU SBD */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 402) 	hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 403) 	if (hdr == 0) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 404) 		printk(KERN_WARNING "windfarm: CPU PID fan config not found "
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 405) 		       "max fan speed\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 406) 		goto fail;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 407) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 408) 	piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 409) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 410) 	/* Get the FVT params for operating point 0 (the only supported one
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 411) 	 * for now) in order to get tmax
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 412) 	 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 413) 	hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 414) 	if (hdr) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 415) 		fvt = (struct smu_sdbp_fvt *)&hdr[1];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 416) 		tmax = ((s32)fvt->maxtemp) << 16;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 417) 	} else
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 418) 		tmax = 0x5e0000; /* 94 degree default */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 419) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 420) 	/* Alloc & initialize state */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 421) 	wf_smu_cpu_fans = kmalloc(sizeof(struct wf_smu_cpu_fans_state),
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 422) 				  GFP_KERNEL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 423) 	if (wf_smu_cpu_fans == NULL)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 424) 		goto fail;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 425)        	wf_smu_cpu_fans->ticks = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 426) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 427) 	wf_smu_cpu_fans->scale = WF_SMU_CPU_FANS_SIBLING_SCALE;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 428) 	wf_smu_cpu_fans->offset = WF_SMU_CPU_FANS_SIBLING_OFFSET;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 429) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 430) 	/* Fill PID params */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 431) 	pid_param.interval = WF_SMU_CPU_FANS_INTERVAL;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 432) 	pid_param.history_len = piddata->history_len;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 433) 	if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 434) 		printk(KERN_WARNING "windfarm: History size overflow on "
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 435) 		       "CPU control loop (%d)\n", piddata->history_len);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 436) 		pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 437) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 438) 	pid_param.gd = piddata->gd;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 439) 	pid_param.gp = piddata->gp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 440) 	pid_param.gr = piddata->gr / pid_param.history_len;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 441) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 442) 	tdelta = ((s32)piddata->target_temp_delta) << 16;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 443) 	maxpow = ((s32)piddata->max_power) << 16;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 444) 	powadj = ((s32)piddata->power_adj) << 16;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 445) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 446) 	pid_param.tmax = tmax;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 447) 	pid_param.ttarget = tmax - tdelta;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 448) 	pid_param.pmaxadj = maxpow - powadj;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 449) 
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 450) 	pid_param.min = wf_control_get_min(fan_cpu_main);
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 451) 	pid_param.max = wf_control_get_max(fan_cpu_main);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 452) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 453) 	wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 454) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 455) 	DBG("wf: CPU Fan control initialized.\n");
942cc40ae4354 (Colin Ian King         2018-05-10 16:54:39 +0100 456) 	DBG("    ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 457) 	    FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 458) 	    pid_param.min, pid_param.max);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 459) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 460) 	return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 461) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 462)  fail:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 463) 	printk(KERN_WARNING "windfarm: CPU fan config not found\n"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 464) 	       "for this machine model, max fan speed\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 465) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 466) 	if (cpufreq_clamp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 467) 		wf_control_set_max(cpufreq_clamp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 468) 	if (fan_cpu_main)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 469) 		wf_control_set_max(fan_cpu_main);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 470) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 471) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 472) static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 473) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 474) 	s32 new_setpoint, temp, power, systarget;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 475) 	int rc;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 476) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 477) 	if (--st->ticks != 0) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 478) 		if (wf_smu_readjust)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 479) 			goto readjust;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 480) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 481) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 482) 	st->ticks = WF_SMU_CPU_FANS_INTERVAL;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 483) 
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 484) 	rc = wf_sensor_get(sensor_cpu_temp, &temp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 485) 	if (rc) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 486) 		printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 487) 		       rc);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 488) 		wf_smu_failure_state |= FAILURE_SENSOR;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 489) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 490) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 491) 
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 492) 	rc = wf_sensor_get(sensor_cpu_power, &power);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 493) 	if (rc) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 494) 		printk(KERN_WARNING "windfarm: CPU power sensor error %d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 495) 		       rc);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 496) 		wf_smu_failure_state |= FAILURE_SENSOR;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 497) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 498) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 499) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 500) 	DBG("wf_smu: CPU Fans tick ! CPU temp: %d.%03d, power: %d.%03d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 501) 	    FIX32TOPRINT(temp), FIX32TOPRINT(power));
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 502) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 503) #ifdef HACKED_OVERTEMP
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 504) 	if (temp > 0x4a0000)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 505) 		wf_smu_failure_state |= FAILURE_OVERTEMP;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 506) #else
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 507) 	if (temp > st->pid.param.tmax)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 508) 		wf_smu_failure_state |= FAILURE_OVERTEMP;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 509) #endif
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 510) 	new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 511) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 512) 	DBG("wf_smu: new_setpoint: %d RPM\n", (int)new_setpoint);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 513) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 514) 	systarget = wf_smu_sys_fans ? wf_smu_sys_fans->pid.target : 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 515) 	systarget = ((((s64)systarget) * (s64)st->scale) >> 12)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 516) 		+ st->offset;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 517) 	new_setpoint = max(new_setpoint, systarget);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 518) 	new_setpoint = max(new_setpoint, st->pid.param.min);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 519) 	new_setpoint = min(new_setpoint, st->pid.param.max);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 520) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 521) 	DBG("wf_smu: adjusted setpoint: %d RPM\n", (int)new_setpoint);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 522) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 523) 	if (st->cpu_setpoint == new_setpoint)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 524) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 525) 	st->cpu_setpoint = new_setpoint;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 526)  readjust:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 527) 	if (fan_cpu_main && wf_smu_failure_state == 0) {
33e6820b767a5 (Benjamin Herrenschmidt 2012-04-18 22:16:51 +0000 528) 		rc = wf_control_set(fan_cpu_main, st->cpu_setpoint);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 529) 		if (rc) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 530) 			printk(KERN_WARNING "windfarm: CPU main fan"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 531) 			       " error %d\n", rc);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 532) 			wf_smu_failure_state |= FAILURE_FAN;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 533) 		}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 534) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 535) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 536) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 537) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 538)  * ****** Setup / Init / Misc ... ******
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 539)  *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 540)  */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 541) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 542) static void wf_smu_tick(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 543) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 544) 	unsigned int last_failure = wf_smu_failure_state;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 545) 	unsigned int new_failure;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 546) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 547) 	if (!wf_smu_started) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 548) 		DBG("wf: creating control loops !\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 549) 		wf_smu_create_sys_fans();
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 550) 		wf_smu_create_cpu_fans();
4f256d561447c (Gustavo A. R. Silva    2018-01-23 19:42:28 -0600 551) 		wf_smu_started = true;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 552) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 553) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 554) 	/* Skipping ticks */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 555) 	if (wf_smu_skipping && --wf_smu_skipping)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 556) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 557) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 558) 	wf_smu_failure_state = 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 559) 	if (wf_smu_sys_fans)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 560) 		wf_smu_sys_fans_tick(wf_smu_sys_fans);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 561) 	if (wf_smu_cpu_fans)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 562) 		wf_smu_cpu_fans_tick(wf_smu_cpu_fans);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 563) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 564) 	wf_smu_readjust = 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 565) 	new_failure = wf_smu_failure_state & ~last_failure;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 566) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 567) 	/* If entering failure mode, clamp cpufreq and ramp all
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 568) 	 * fans to full speed.
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 569) 	 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 570) 	if (wf_smu_failure_state && !last_failure) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 571) 		if (cpufreq_clamp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 572) 			wf_control_set_max(cpufreq_clamp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 573) 		if (fan_system)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 574) 			wf_control_set_max(fan_system);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 575) 		if (fan_cpu_main)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 576) 			wf_control_set_max(fan_cpu_main);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 577) 		if (fan_hd)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 578) 			wf_control_set_max(fan_hd);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 579) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 580) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 581) 	/* If leaving failure mode, unclamp cpufreq and readjust
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 582) 	 * all fans on next iteration
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 583) 	 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 584) 	if (!wf_smu_failure_state && last_failure) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 585) 		if (cpufreq_clamp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 586) 			wf_control_set_min(cpufreq_clamp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 587) 		wf_smu_readjust = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 588) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 589) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 590) 	/* Overtemp condition detected, notify and start skipping a couple
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 591) 	 * ticks to let the temperature go down
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 592) 	 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 593) 	if (new_failure & FAILURE_OVERTEMP) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 594) 		wf_set_overtemp();
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 595) 		wf_smu_skipping = 2;
4bb2971134330 (Aaro Koskinen          2013-06-30 22:00:42 +0300 596) 		wf_smu_overtemp = true;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 597) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 598) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 599) 	/* We only clear the overtemp condition if overtemp is cleared
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 600) 	 * _and_ no other failure is present. Since a sensor error will
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 601) 	 * clear the overtemp condition (can't measure temperature) at
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 602) 	 * the control loop levels, but we don't want to keep it clear
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 603) 	 * here in this case
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 604) 	 */
4bb2971134330 (Aaro Koskinen          2013-06-30 22:00:42 +0300 605) 	if (!wf_smu_failure_state && wf_smu_overtemp) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 606) 		wf_clear_overtemp();
4bb2971134330 (Aaro Koskinen          2013-06-30 22:00:42 +0300 607) 		wf_smu_overtemp = false;
4bb2971134330 (Aaro Koskinen          2013-06-30 22:00:42 +0300 608) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 609) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 610) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 611) static void wf_smu_new_control(struct wf_control *ct)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 612) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 613) 	if (wf_smu_all_controls_ok)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 614) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 615) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 616) 	if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 617) 		if (wf_get_control(ct) == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 618) 			fan_cpu_main = ct;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 619) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 620) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 621) 	if (fan_system == NULL && !strcmp(ct->name, "system-fan")) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 622) 		if (wf_get_control(ct) == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 623) 			fan_system = ct;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 624) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 625) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 626) 	if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 627) 		if (wf_get_control(ct) == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 628) 			cpufreq_clamp = ct;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 629) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 630) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 631) 	/* Darwin property list says the HD fan is only for model ID
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 632) 	 * 0, 1, 2 and 3
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 633) 	 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 634) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 635) 	if (wf_smu_mach_model > 3) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 636) 		if (fan_system && fan_cpu_main && cpufreq_clamp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 637) 			wf_smu_all_controls_ok = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 638) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 639) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 640) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 641) 	if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 642) 		if (wf_get_control(ct) == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 643) 			fan_hd = ct;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 644) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 645) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 646) 	if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 647) 		wf_smu_all_controls_ok = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 648) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 649) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 650) static void wf_smu_new_sensor(struct wf_sensor *sr)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 651) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 652) 	if (wf_smu_all_sensors_ok)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 653) 		return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 654) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 655) 	if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 656) 		if (wf_get_sensor(sr) == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 657) 			sensor_cpu_power = sr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 658) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 659) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 660) 	if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 661) 		if (wf_get_sensor(sr) == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 662) 			sensor_cpu_temp = sr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 663) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 664) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 665) 	if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 666) 		if (wf_get_sensor(sr) == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 667) 			sensor_hd_temp = sr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 668) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 669) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 670) 	if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 671) 		wf_smu_all_sensors_ok = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 672) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 673) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 674) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 675) static int wf_smu_notify(struct notifier_block *self,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 676) 			       unsigned long event, void *data)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 677) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 678) 	switch(event) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 679) 	case WF_EVENT_NEW_CONTROL:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 680) 		DBG("wf: new control %s detected\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 681) 		    ((struct wf_control *)data)->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 682) 		wf_smu_new_control(data);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 683) 		wf_smu_readjust = 1;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 684) 		break;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 685) 	case WF_EVENT_NEW_SENSOR:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 686) 		DBG("wf: new sensor %s detected\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 687) 		    ((struct wf_sensor *)data)->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 688) 		wf_smu_new_sensor(data);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 689) 		break;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 690) 	case WF_EVENT_TICK:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 691) 		if (wf_smu_all_controls_ok && wf_smu_all_sensors_ok)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 692) 			wf_smu_tick();
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 693) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 694) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 695) 	return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 696) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 697) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 698) static struct notifier_block wf_smu_events = {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 699) 	.notifier_call	= wf_smu_notify,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 700) };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 701) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 702) static int wf_init_pm(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 703) {
018a3d1db7cdb (Jeremy Kerr            2006-07-12 15:40:29 +1000 704) 	const struct smu_sdbp_header *hdr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 705) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 706) 	hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 707) 	if (hdr != 0) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 708) 		struct smu_sdbp_sensortree *st =
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 709) 			(struct smu_sdbp_sensortree *)&hdr[1];
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 710) 		wf_smu_mach_model = st->model_id;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 711) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 712) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 713) 	printk(KERN_INFO "windfarm: Initializing for iMacG5 model ID %d\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 714) 	       wf_smu_mach_model);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 715) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 716) 	return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 717) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 718) 
10270613fb4d5 (Benjamin Herrenschmidt 2006-10-10 11:47:31 +1000 719) static int wf_smu_probe(struct platform_device *ddev)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 720) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 721) 	wf_register_client(&wf_smu_events);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 722) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 723) 	return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 724) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 725) 
1da42fb6bf6fc (Greg Kroah-Hartman     2012-12-21 15:03:50 -0800 726) static int wf_smu_remove(struct platform_device *ddev)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 727) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 728) 	wf_unregister_client(&wf_smu_events);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 729) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 730) 	/* XXX We don't have yet a guarantee that our callback isn't
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 731) 	 * in progress when returning from wf_unregister_client, so
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 732) 	 * we add an arbitrary delay. I'll have to fix that in the core
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 733) 	 */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 734) 	msleep(1000);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 735) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 736) 	/* Release all sensors */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 737) 	/* One more crappy race: I don't think we have any guarantee here
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 738) 	 * that the attribute callback won't race with the sensor beeing
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 739) 	 * disposed of, and I'm not 100% certain what best way to deal
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 740) 	 * with that except by adding locks all over... I'll do that
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 741) 	 * eventually but heh, who ever rmmod this module anyway ?
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 742) 	 */
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 743) 	if (sensor_cpu_power)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 744) 		wf_put_sensor(sensor_cpu_power);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 745) 	if (sensor_cpu_temp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 746) 		wf_put_sensor(sensor_cpu_temp);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 747) 	if (sensor_hd_temp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 748) 		wf_put_sensor(sensor_hd_temp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 749) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 750) 	/* Release all controls */
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 751) 	if (fan_cpu_main)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 752) 		wf_put_control(fan_cpu_main);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 753) 	if (fan_hd)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 754) 		wf_put_control(fan_hd);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 755) 	if (fan_system)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 756) 		wf_put_control(fan_system);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 757) 	if (cpufreq_clamp)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 758) 		wf_put_control(cpufreq_clamp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 759) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 760) 	/* Destroy control loops state structures */
6d1bdd2afbed7 (d binderman            2010-03-18 23:01:42 +0000 761) 	kfree(wf_smu_sys_fans);
6d1bdd2afbed7 (d binderman            2010-03-18 23:01:42 +0000 762) 	kfree(wf_smu_cpu_fans);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 763) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 764) 	return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 765) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 766) 
10270613fb4d5 (Benjamin Herrenschmidt 2006-10-10 11:47:31 +1000 767) static struct platform_driver wf_smu_driver = {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 768)         .probe = wf_smu_probe,
1da42fb6bf6fc (Greg Kroah-Hartman     2012-12-21 15:03:50 -0800 769)         .remove = wf_smu_remove,
10270613fb4d5 (Benjamin Herrenschmidt 2006-10-10 11:47:31 +1000 770) 	.driver = {
10270613fb4d5 (Benjamin Herrenschmidt 2006-10-10 11:47:31 +1000 771) 		.name = "windfarm",
10270613fb4d5 (Benjamin Herrenschmidt 2006-10-10 11:47:31 +1000 772) 	},
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 773) };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 774) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 775) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 776) static int __init wf_smu_init(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 777) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 778) 	int rc = -ENODEV;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 779) 
71a157e8edca5 (Grant Likely           2010-02-01 21:34:14 -0700 780) 	if (of_machine_is_compatible("PowerMac8,1") ||
71a157e8edca5 (Grant Likely           2010-02-01 21:34:14 -0700 781) 	    of_machine_is_compatible("PowerMac8,2"))
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 782) 		rc = wf_init_pm();
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 783) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 784) 	if (rc == 0) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 785) #ifdef MODULE
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 786) 		request_module("windfarm_smu_controls");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 787) 		request_module("windfarm_smu_sensors");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 788) 		request_module("windfarm_lm75_sensor");
d31e817183a4c (Benjamin Herrenschmidt 2006-11-16 14:00:57 +1100 789) 		request_module("windfarm_cpufreq_clamp");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 790) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 791) #endif /* MODULE */
10270613fb4d5 (Benjamin Herrenschmidt 2006-10-10 11:47:31 +1000 792) 		platform_driver_register(&wf_smu_driver);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 793) 	}
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 794) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 795) 	return rc;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 796) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 797) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 798) static void __exit wf_smu_exit(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 799) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 800) 
10270613fb4d5 (Benjamin Herrenschmidt 2006-10-10 11:47:31 +1000 801) 	platform_driver_unregister(&wf_smu_driver);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 802) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 803) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 804) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 805) module_init(wf_smu_init);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 806) module_exit(wf_smu_exit);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 807) 
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 808) MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 809) MODULE_DESCRIPTION("Thermal control logic for iMac G5");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 810) MODULE_LICENSE("GPL");
23386fe572028 (Kay Sievers            2008-04-18 13:33:53 -0700 811) MODULE_ALIAS("platform:windfarm");