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 enum nv40_sensor_style { INVALID_STYLE = -1, OLD_STYLE = 0, NEW_STYLE = 1 };
0028
0029 static enum nv40_sensor_style
0030 nv40_sensor_style(struct nvkm_therm *therm)
0031 {
0032 switch (therm->subdev.device->chipset) {
0033 case 0x43:
0034 case 0x44:
0035 case 0x4a:
0036 case 0x47:
0037 return OLD_STYLE;
0038 case 0x46:
0039 case 0x49:
0040 case 0x4b:
0041 case 0x4e:
0042 case 0x4c:
0043 case 0x67:
0044 case 0x68:
0045 case 0x63:
0046 return NEW_STYLE;
0047 default:
0048 return INVALID_STYLE;
0049 }
0050 }
0051
0052 static int
0053 nv40_sensor_setup(struct nvkm_therm *therm)
0054 {
0055 struct nvkm_device *device = therm->subdev.device;
0056 enum nv40_sensor_style style = nv40_sensor_style(therm);
0057
0058
0059 if (style == NEW_STYLE) {
0060 nvkm_mask(device, 0x15b8, 0x80000000, 0);
0061 nvkm_wr32(device, 0x15b0, 0x80003fff);
0062 mdelay(20);
0063 return nvkm_rd32(device, 0x15b4) & 0x3fff;
0064 } else if (style == OLD_STYLE) {
0065 nvkm_wr32(device, 0x15b0, 0xff);
0066 mdelay(20);
0067 return nvkm_rd32(device, 0x15b4) & 0xff;
0068 } else
0069 return -ENODEV;
0070 }
0071
0072 static int
0073 nv40_temp_get(struct nvkm_therm *therm)
0074 {
0075 struct nvkm_device *device = therm->subdev.device;
0076 struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
0077 enum nv40_sensor_style style = nv40_sensor_style(therm);
0078 int core_temp;
0079
0080 if (style == NEW_STYLE) {
0081 nvkm_wr32(device, 0x15b0, 0x80003fff);
0082 core_temp = nvkm_rd32(device, 0x15b4) & 0x3fff;
0083 } else if (style == OLD_STYLE) {
0084 nvkm_wr32(device, 0x15b0, 0xff);
0085 core_temp = nvkm_rd32(device, 0x15b4) & 0xff;
0086 } else
0087 return -ENODEV;
0088
0089
0090 if (!sensor->slope_div || !sensor->slope_mult ||
0091 !sensor->offset_num || !sensor->offset_den)
0092 return -ENODEV;
0093
0094 core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
0095 core_temp = core_temp + sensor->offset_num / sensor->offset_den;
0096 core_temp = core_temp + sensor->offset_constant - 8;
0097
0098
0099 if (core_temp < 0)
0100 core_temp = 0;
0101
0102 return core_temp;
0103 }
0104
0105 static int
0106 nv40_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
0107 {
0108 struct nvkm_subdev *subdev = &therm->subdev;
0109 struct nvkm_device *device = subdev->device;
0110 u32 mask = enable ? 0x80000000 : 0x00000000;
0111 if (line == 2) nvkm_mask(device, 0x0010f0, 0x80000000, mask);
0112 else if (line == 9) nvkm_mask(device, 0x0015f4, 0x80000000, mask);
0113 else {
0114 nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line);
0115 return -ENODEV;
0116 }
0117 return 0;
0118 }
0119
0120 static int
0121 nv40_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty)
0122 {
0123 struct nvkm_subdev *subdev = &therm->subdev;
0124 struct nvkm_device *device = subdev->device;
0125 if (line == 2) {
0126 u32 reg = nvkm_rd32(device, 0x0010f0);
0127 if (reg & 0x80000000) {
0128 *duty = (reg & 0x7fff0000) >> 16;
0129 *divs = (reg & 0x00007fff);
0130 return 0;
0131 }
0132 } else
0133 if (line == 9) {
0134 u32 reg = nvkm_rd32(device, 0x0015f4);
0135 if (reg & 0x80000000) {
0136 *divs = nvkm_rd32(device, 0x0015f8);
0137 *duty = (reg & 0x7fffffff);
0138 return 0;
0139 }
0140 } else {
0141 nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line);
0142 return -ENODEV;
0143 }
0144
0145 return -EINVAL;
0146 }
0147
0148 static int
0149 nv40_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty)
0150 {
0151 struct nvkm_subdev *subdev = &therm->subdev;
0152 struct nvkm_device *device = subdev->device;
0153 if (line == 2) {
0154 nvkm_mask(device, 0x0010f0, 0x7fff7fff, (duty << 16) | divs);
0155 } else
0156 if (line == 9) {
0157 nvkm_wr32(device, 0x0015f8, divs);
0158 nvkm_mask(device, 0x0015f4, 0x7fffffff, duty);
0159 } else {
0160 nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line);
0161 return -ENODEV;
0162 }
0163
0164 return 0;
0165 }
0166
0167 void
0168 nv40_therm_intr(struct nvkm_therm *therm)
0169 {
0170 struct nvkm_subdev *subdev = &therm->subdev;
0171 struct nvkm_device *device = subdev->device;
0172 uint32_t stat = nvkm_rd32(device, 0x1100);
0173
0174
0175
0176
0177 nvkm_wr32(device, 0x1100, 0x70000);
0178
0179 nvkm_error(subdev, "THERM received an IRQ: stat = %x\n", stat);
0180 }
0181
0182 static void
0183 nv40_therm_init(struct nvkm_therm *therm)
0184 {
0185 nv40_sensor_setup(therm);
0186 }
0187
0188 static const struct nvkm_therm_func
0189 nv40_therm = {
0190 .init = nv40_therm_init,
0191 .intr = nv40_therm_intr,
0192 .pwm_ctrl = nv40_fan_pwm_ctrl,
0193 .pwm_get = nv40_fan_pwm_get,
0194 .pwm_set = nv40_fan_pwm_set,
0195 .temp_get = nv40_temp_get,
0196 .program_alarms = nvkm_therm_program_alarms_polling,
0197 };
0198
0199 int
0200 nv40_therm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0201 struct nvkm_therm **ptherm)
0202 {
0203 return nvkm_therm_new_(&nv40_therm, device, type, inst, ptherm);
0204 }