0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include "priv.h"
0026
0027 #include <subdev/bios/fan.h>
0028 #include <subdev/gpio.h>
0029 #include <subdev/timer.h>
0030
0031 static int
0032 nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
0033 {
0034 struct nvkm_therm *therm = fan->parent;
0035 struct nvkm_subdev *subdev = &therm->subdev;
0036 struct nvkm_timer *tmr = subdev->device->timer;
0037 unsigned long flags;
0038 int ret = 0;
0039 int duty;
0040
0041
0042 spin_lock_irqsave(&fan->lock, flags);
0043 if (target < 0)
0044 target = fan->percent;
0045 target = max_t(u8, target, fan->bios.min_duty);
0046 target = min_t(u8, target, fan->bios.max_duty);
0047 if (fan->percent != target) {
0048 nvkm_debug(subdev, "FAN target: %d\n", target);
0049 fan->percent = target;
0050 }
0051
0052
0053 duty = fan->get(therm);
0054 if (duty == target) {
0055 spin_unlock_irqrestore(&fan->lock, flags);
0056 return 0;
0057 }
0058
0059
0060 if (!immediate && duty >= 0) {
0061
0062
0063
0064
0065 if (duty < target)
0066 duty = min(duty + 3, target);
0067 else if (duty > target)
0068 duty = max(duty - 3, target);
0069 } else {
0070 duty = target;
0071 }
0072
0073 nvkm_debug(subdev, "FAN update: %d\n", duty);
0074 ret = fan->set(therm, duty);
0075 if (ret) {
0076 spin_unlock_irqrestore(&fan->lock, flags);
0077 return ret;
0078 }
0079
0080
0081
0082
0083 spin_unlock_irqrestore(&fan->lock, flags);
0084
0085
0086 if (target != duty) {
0087 u16 bump_period = fan->bios.bump_period;
0088 u16 slow_down_period = fan->bios.slow_down_period;
0089 u64 delay;
0090
0091 if (duty > target)
0092 delay = slow_down_period;
0093 else if (duty == target)
0094 delay = min(bump_period, slow_down_period) ;
0095 else
0096 delay = bump_period;
0097
0098 nvkm_timer_alarm(tmr, delay * 1000 * 1000, &fan->alarm);
0099 }
0100
0101 return ret;
0102 }
0103
0104 static void
0105 nvkm_fan_alarm(struct nvkm_alarm *alarm)
0106 {
0107 struct nvkm_fan *fan = container_of(alarm, struct nvkm_fan, alarm);
0108 nvkm_fan_update(fan, false, -1);
0109 }
0110
0111 int
0112 nvkm_therm_fan_get(struct nvkm_therm *therm)
0113 {
0114 return therm->fan->get(therm);
0115 }
0116
0117 int
0118 nvkm_therm_fan_set(struct nvkm_therm *therm, bool immediate, int percent)
0119 {
0120 return nvkm_fan_update(therm->fan, immediate, percent);
0121 }
0122
0123 int
0124 nvkm_therm_fan_sense(struct nvkm_therm *therm)
0125 {
0126 struct nvkm_device *device = therm->subdev.device;
0127 struct nvkm_timer *tmr = device->timer;
0128 struct nvkm_gpio *gpio = device->gpio;
0129 u32 cycles, cur, prev;
0130 u64 start, end, tach;
0131
0132 if (therm->func->fan_sense)
0133 return therm->func->fan_sense(therm);
0134
0135 if (therm->fan->tach.func == DCB_GPIO_UNUSED)
0136 return -ENODEV;
0137
0138
0139
0140
0141
0142 start = nvkm_timer_read(tmr);
0143 prev = nvkm_gpio_get(gpio, 0, therm->fan->tach.func,
0144 therm->fan->tach.line);
0145 cycles = 0;
0146 do {
0147 usleep_range(500, 1000);
0148
0149 cur = nvkm_gpio_get(gpio, 0, therm->fan->tach.func,
0150 therm->fan->tach.line);
0151 if (prev != cur) {
0152 if (!start)
0153 start = nvkm_timer_read(tmr);
0154 cycles++;
0155 prev = cur;
0156 }
0157 } while (cycles < 5 && nvkm_timer_read(tmr) - start < 250000000);
0158 end = nvkm_timer_read(tmr);
0159
0160 if (cycles == 5) {
0161 tach = (u64)60000000000ULL;
0162 do_div(tach, (end - start));
0163 return tach;
0164 } else
0165 return 0;
0166 }
0167
0168 int
0169 nvkm_therm_fan_user_get(struct nvkm_therm *therm)
0170 {
0171 return nvkm_therm_fan_get(therm);
0172 }
0173
0174 int
0175 nvkm_therm_fan_user_set(struct nvkm_therm *therm, int percent)
0176 {
0177 if (therm->mode != NVKM_THERM_CTRL_MANUAL)
0178 return -EINVAL;
0179
0180 return nvkm_therm_fan_set(therm, true, percent);
0181 }
0182
0183 static void
0184 nvkm_therm_fan_set_defaults(struct nvkm_therm *therm)
0185 {
0186 therm->fan->bios.pwm_freq = 0;
0187 therm->fan->bios.min_duty = 0;
0188 therm->fan->bios.max_duty = 100;
0189 therm->fan->bios.bump_period = 500;
0190 therm->fan->bios.slow_down_period = 2000;
0191 therm->fan->bios.linear_min_temp = 40;
0192 therm->fan->bios.linear_max_temp = 85;
0193 }
0194
0195 static void
0196 nvkm_therm_fan_safety_checks(struct nvkm_therm *therm)
0197 {
0198 if (therm->fan->bios.min_duty > 100)
0199 therm->fan->bios.min_duty = 100;
0200 if (therm->fan->bios.max_duty > 100)
0201 therm->fan->bios.max_duty = 100;
0202
0203 if (therm->fan->bios.min_duty > therm->fan->bios.max_duty)
0204 therm->fan->bios.min_duty = therm->fan->bios.max_duty;
0205 }
0206
0207 int
0208 nvkm_therm_fan_init(struct nvkm_therm *therm)
0209 {
0210 return 0;
0211 }
0212
0213 int
0214 nvkm_therm_fan_fini(struct nvkm_therm *therm, bool suspend)
0215 {
0216 struct nvkm_timer *tmr = therm->subdev.device->timer;
0217 if (suspend)
0218 nvkm_timer_alarm(tmr, 0, &therm->fan->alarm);
0219 return 0;
0220 }
0221
0222 int
0223 nvkm_therm_fan_ctor(struct nvkm_therm *therm)
0224 {
0225 struct nvkm_subdev *subdev = &therm->subdev;
0226 struct nvkm_device *device = subdev->device;
0227 struct nvkm_gpio *gpio = device->gpio;
0228 struct nvkm_bios *bios = device->bios;
0229 struct dcb_gpio_func func;
0230 int ret;
0231
0232
0233 ret = nvkm_gpio_find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
0234 if (ret == 0) {
0235
0236 if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
0237 nvkm_debug(subdev, "GPIO_FAN is in input mode\n");
0238 ret = -EINVAL;
0239 } else {
0240 ret = nvkm_fanpwm_create(therm, &func);
0241 if (ret != 0)
0242 ret = nvkm_fantog_create(therm, &func);
0243 }
0244 }
0245
0246
0247 if (ret != 0) {
0248 ret = nvkm_fannil_create(therm);
0249 if (ret)
0250 return ret;
0251 }
0252
0253 nvkm_debug(subdev, "FAN control: %s\n", therm->fan->type);
0254
0255
0256 therm->fan->percent = nvkm_therm_fan_get(therm);
0257
0258
0259 ret = nvkm_gpio_find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff,
0260 &therm->fan->tach);
0261 if (ret)
0262 therm->fan->tach.func = DCB_GPIO_UNUSED;
0263
0264
0265 therm->fan->parent = therm;
0266 nvkm_alarm_init(&therm->fan->alarm, nvkm_fan_alarm);
0267 spin_lock_init(&therm->fan->lock);
0268
0269
0270 nvkm_therm_fan_set_defaults(therm);
0271 nvbios_perf_fan_parse(bios, &therm->fan->perf);
0272 if (!nvbios_fan_parse(bios, &therm->fan->bios)) {
0273 nvkm_debug(subdev, "parsing the fan table failed\n");
0274 if (nvbios_therm_fan_parse(bios, &therm->fan->bios))
0275 nvkm_error(subdev, "parsing both fan tables failed\n");
0276 }
0277 nvkm_therm_fan_safety_checks(therm);
0278 return 0;
0279 }