linux/drivers/gpu/drm/nouveau/nouveau_hwmon.c
<<
>>
Prefs
   1/*
   2 * Copyright 2010 Red Hat Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Ben Skeggs
  23 */
  24
  25#ifdef CONFIG_ACPI
  26#include <linux/acpi.h>
  27#endif
  28#include <linux/power_supply.h>
  29#include <linux/hwmon.h>
  30#include <linux/hwmon-sysfs.h>
  31
  32#include <drm/drmP.h>
  33
  34#include "nouveau_drv.h"
  35#include "nouveau_hwmon.h"
  36
  37#include <nvkm/subdev/iccsense.h>
  38#include <nvkm/subdev/volt.h>
  39
  40#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
  41
  42static ssize_t
  43nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d,
  44                                         struct device_attribute *a, char *buf)
  45{
  46        return snprintf(buf, PAGE_SIZE, "%d\n", 100);
  47}
  48static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, 0444,
  49                          nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);
  50
  51static ssize_t
  52nouveau_hwmon_temp1_auto_point1_temp(struct device *d,
  53                                     struct device_attribute *a, char *buf)
  54{
  55        struct drm_device *dev = dev_get_drvdata(d);
  56        struct nouveau_drm *drm = nouveau_drm(dev);
  57        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
  58
  59        return snprintf(buf, PAGE_SIZE, "%d\n",
  60              therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000);
  61}
  62static ssize_t
  63nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
  64                                         struct device_attribute *a,
  65                                         const char *buf, size_t count)
  66{
  67        struct drm_device *dev = dev_get_drvdata(d);
  68        struct nouveau_drm *drm = nouveau_drm(dev);
  69        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
  70        long value;
  71
  72        if (kstrtol(buf, 10, &value) == -EINVAL)
  73                return count;
  74
  75        therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST,
  76                        value / 1000);
  77
  78        return count;
  79}
  80static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, 0644,
  81                          nouveau_hwmon_temp1_auto_point1_temp,
  82                          nouveau_hwmon_set_temp1_auto_point1_temp, 0);
  83
  84static ssize_t
  85nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d,
  86                                          struct device_attribute *a, char *buf)
  87{
  88        struct drm_device *dev = dev_get_drvdata(d);
  89        struct nouveau_drm *drm = nouveau_drm(dev);
  90        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
  91
  92        return snprintf(buf, PAGE_SIZE, "%d\n",
  93         therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
  94}
  95static ssize_t
  96nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
  97                                              struct device_attribute *a,
  98                                              const char *buf, size_t count)
  99{
 100        struct drm_device *dev = dev_get_drvdata(d);
 101        struct nouveau_drm *drm = nouveau_drm(dev);
 102        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 103        long value;
 104
 105        if (kstrtol(buf, 10, &value) == -EINVAL)
 106                return count;
 107
 108        therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST,
 109                        value / 1000);
 110
 111        return count;
 112}
 113static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst, 0644,
 114                          nouveau_hwmon_temp1_auto_point1_temp_hyst,
 115                          nouveau_hwmon_set_temp1_auto_point1_temp_hyst, 0);
 116
 117static ssize_t
 118nouveau_hwmon_get_pwm1_max(struct device *d,
 119                           struct device_attribute *a, char *buf)
 120{
 121        struct drm_device *dev = dev_get_drvdata(d);
 122        struct nouveau_drm *drm = nouveau_drm(dev);
 123        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 124        int ret;
 125
 126        ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY);
 127        if (ret < 0)
 128                return ret;
 129
 130        return sprintf(buf, "%i\n", ret);
 131}
 132
 133static ssize_t
 134nouveau_hwmon_get_pwm1_min(struct device *d,
 135                           struct device_attribute *a, char *buf)
 136{
 137        struct drm_device *dev = dev_get_drvdata(d);
 138        struct nouveau_drm *drm = nouveau_drm(dev);
 139        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 140        int ret;
 141
 142        ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY);
 143        if (ret < 0)
 144                return ret;
 145
 146        return sprintf(buf, "%i\n", ret);
 147}
 148
 149static ssize_t
 150nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a,
 151                           const char *buf, size_t count)
 152{
 153        struct drm_device *dev = dev_get_drvdata(d);
 154        struct nouveau_drm *drm = nouveau_drm(dev);
 155        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 156        long value;
 157        int ret;
 158
 159        if (kstrtol(buf, 10, &value) == -EINVAL)
 160                return -EINVAL;
 161
 162        ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY, value);
 163        if (ret < 0)
 164                return ret;
 165
 166        return count;
 167}
 168static SENSOR_DEVICE_ATTR(pwm1_min, 0644,
 169                          nouveau_hwmon_get_pwm1_min,
 170                          nouveau_hwmon_set_pwm1_min, 0);
 171
 172static ssize_t
 173nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
 174                           const char *buf, size_t count)
 175{
 176        struct drm_device *dev = dev_get_drvdata(d);
 177        struct nouveau_drm *drm = nouveau_drm(dev);
 178        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 179        long value;
 180        int ret;
 181
 182        if (kstrtol(buf, 10, &value) == -EINVAL)
 183                return -EINVAL;
 184
 185        ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value);
 186        if (ret < 0)
 187                return ret;
 188
 189        return count;
 190}
 191static SENSOR_DEVICE_ATTR(pwm1_max, 0644,
 192                          nouveau_hwmon_get_pwm1_max,
 193                          nouveau_hwmon_set_pwm1_max, 0);
 194
 195static struct attribute *pwm_fan_sensor_attrs[] = {
 196        &sensor_dev_attr_pwm1_min.dev_attr.attr,
 197        &sensor_dev_attr_pwm1_max.dev_attr.attr,
 198        NULL
 199};
 200static const struct attribute_group pwm_fan_sensor_group = {
 201        .attrs = pwm_fan_sensor_attrs,
 202};
 203
 204static struct attribute *temp1_auto_point_sensor_attrs[] = {
 205        &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr,
 206        &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
 207        &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
 208        NULL
 209};
 210static const struct attribute_group temp1_auto_point_sensor_group = {
 211        .attrs = temp1_auto_point_sensor_attrs,
 212};
 213
 214#define N_ATTR_GROUPS   3
 215
 216static const u32 nouveau_config_chip[] = {
 217        HWMON_C_UPDATE_INTERVAL,
 218        0
 219};
 220
 221static const u32 nouveau_config_in[] = {
 222        HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_LABEL,
 223        0
 224};
 225
 226static const u32 nouveau_config_temp[] = {
 227        HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
 228        HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_EMERGENCY |
 229        HWMON_T_EMERGENCY_HYST,
 230        0
 231};
 232
 233static const u32 nouveau_config_fan[] = {
 234        HWMON_F_INPUT,
 235        0
 236};
 237
 238static const u32 nouveau_config_pwm[] = {
 239        HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
 240        0
 241};
 242
 243static const u32 nouveau_config_power[] = {
 244        HWMON_P_INPUT | HWMON_P_CAP_MAX | HWMON_P_CRIT,
 245        0
 246};
 247
 248static const struct hwmon_channel_info nouveau_chip = {
 249        .type = hwmon_chip,
 250        .config = nouveau_config_chip,
 251};
 252
 253static const struct hwmon_channel_info nouveau_temp = {
 254        .type = hwmon_temp,
 255        .config = nouveau_config_temp,
 256};
 257
 258static const struct hwmon_channel_info nouveau_fan = {
 259        .type = hwmon_fan,
 260        .config = nouveau_config_fan,
 261};
 262
 263static const struct hwmon_channel_info nouveau_in = {
 264        .type = hwmon_in,
 265        .config = nouveau_config_in,
 266};
 267
 268static const struct hwmon_channel_info nouveau_pwm = {
 269        .type = hwmon_pwm,
 270        .config = nouveau_config_pwm,
 271};
 272
 273static const struct hwmon_channel_info nouveau_power = {
 274        .type = hwmon_power,
 275        .config = nouveau_config_power,
 276};
 277
 278static const struct hwmon_channel_info *nouveau_info[] = {
 279        &nouveau_chip,
 280        &nouveau_temp,
 281        &nouveau_fan,
 282        &nouveau_in,
 283        &nouveau_pwm,
 284        &nouveau_power,
 285        NULL
 286};
 287
 288static umode_t
 289nouveau_chip_is_visible(const void *data, u32 attr, int channel)
 290{
 291        switch (attr) {
 292        case hwmon_chip_update_interval:
 293                return 0444;
 294        default:
 295                return 0;
 296        }
 297}
 298
 299static umode_t
 300nouveau_power_is_visible(const void *data, u32 attr, int channel)
 301{
 302        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 303        struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
 304
 305        if (!iccsense || !iccsense->data_valid || list_empty(&iccsense->rails))
 306                return 0;
 307
 308        switch (attr) {
 309        case hwmon_power_input:
 310                return 0444;
 311        case hwmon_power_max:
 312                if (iccsense->power_w_max)
 313                        return 0444;
 314                return 0;
 315        case hwmon_power_crit:
 316                if (iccsense->power_w_crit)
 317                        return 0444;
 318                return 0;
 319        default:
 320                return 0;
 321        }
 322}
 323
 324static umode_t
 325nouveau_temp_is_visible(const void *data, u32 attr, int channel)
 326{
 327        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 328        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 329
 330        if (therm && therm->attr_get && nvkm_therm_temp_get(therm) < 0)
 331                return 0;
 332
 333        switch (attr) {
 334        case hwmon_temp_input:
 335                return 0444;
 336        case hwmon_temp_max:
 337        case hwmon_temp_max_hyst:
 338        case hwmon_temp_crit:
 339        case hwmon_temp_crit_hyst:
 340        case hwmon_temp_emergency:
 341        case hwmon_temp_emergency_hyst:
 342                return 0644;
 343        default:
 344                return 0;
 345        }
 346}
 347
 348static umode_t
 349nouveau_pwm_is_visible(const void *data, u32 attr, int channel)
 350{
 351        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 352        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 353
 354        if (therm && therm->attr_get && therm->fan_get &&
 355                                therm->fan_get(therm) < 0)
 356                return 0;
 357
 358        switch (attr) {
 359        case hwmon_pwm_enable:
 360        case hwmon_pwm_input:
 361                return 0644;
 362        default:
 363                return 0;
 364        }
 365}
 366
 367static umode_t
 368nouveau_input_is_visible(const void *data, u32 attr, int channel)
 369{
 370        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 371        struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
 372
 373        if (!volt || nvkm_volt_get(volt) < 0)
 374                return 0;
 375
 376        switch (attr) {
 377        case hwmon_in_input:
 378        case hwmon_in_label:
 379        case hwmon_in_min:
 380        case hwmon_in_max:
 381                return 0444;
 382        default:
 383                return 0;
 384        }
 385}
 386
 387static umode_t
 388nouveau_fan_is_visible(const void *data, u32 attr, int channel)
 389{
 390        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 391        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 392
 393        if (!therm || !therm->attr_get || nvkm_therm_fan_sense(therm) < 0)
 394                return 0;
 395
 396        switch (attr) {
 397        case hwmon_fan_input:
 398                return 0444;
 399        default:
 400                return 0;
 401        }
 402}
 403
 404static int
 405nouveau_chip_read(struct device *dev, u32 attr, int channel, long *val)
 406{
 407        switch (attr) {
 408        case hwmon_chip_update_interval:
 409                *val = 1000;
 410                break;
 411        default:
 412                return -EOPNOTSUPP;
 413        }
 414
 415        return 0;
 416}
 417
 418static int
 419nouveau_temp_read(struct device *dev, u32 attr, int channel, long *val)
 420{
 421        struct drm_device *drm_dev = dev_get_drvdata(dev);
 422        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 423        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 424        int ret;
 425
 426        if (!therm || !therm->attr_get)
 427                return -EOPNOTSUPP;
 428
 429        switch (attr) {
 430        case hwmon_temp_input:
 431                ret = nvkm_therm_temp_get(therm);
 432                *val = ret < 0 ? ret : (ret * 1000);
 433                break;
 434        case hwmon_temp_max:
 435                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK)
 436                                        * 1000;
 437                break;
 438        case hwmon_temp_max_hyst:
 439                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST)
 440                                        * 1000;
 441                break;
 442        case hwmon_temp_crit:
 443                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL)
 444                                        * 1000;
 445                break;
 446        case hwmon_temp_crit_hyst:
 447                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST)
 448                                        * 1000;
 449                break;
 450        case hwmon_temp_emergency:
 451                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN)
 452                                        * 1000;
 453                break;
 454        case hwmon_temp_emergency_hyst:
 455                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST)
 456                                        * 1000;
 457                break;
 458        default:
 459                return -EOPNOTSUPP;
 460        }
 461
 462        return 0;
 463}
 464
 465static int
 466nouveau_fan_read(struct device *dev, u32 attr, int channel, long *val)
 467{
 468        struct drm_device *drm_dev = dev_get_drvdata(dev);
 469        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 470        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 471
 472        if (!therm)
 473                return -EOPNOTSUPP;
 474
 475        switch (attr) {
 476        case hwmon_fan_input:
 477                *val = nvkm_therm_fan_sense(therm);
 478                break;
 479        default:
 480                return -EOPNOTSUPP;
 481        }
 482
 483        return 0;
 484}
 485
 486static int
 487nouveau_in_read(struct device *dev, u32 attr, int channel, long *val)
 488{
 489        struct drm_device *drm_dev = dev_get_drvdata(dev);
 490        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 491        struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
 492        int ret;
 493
 494        if (!volt)
 495                return -EOPNOTSUPP;
 496
 497        switch (attr) {
 498        case hwmon_in_input:
 499                ret = nvkm_volt_get(volt);
 500                *val = ret < 0 ? ret : (ret / 1000);
 501                break;
 502        case hwmon_in_min:
 503                *val = volt->min_uv > 0 ? (volt->min_uv / 1000) : -ENODEV;
 504                break;
 505        case hwmon_in_max:
 506                *val = volt->max_uv > 0 ? (volt->max_uv / 1000) : -ENODEV;
 507                break;
 508        default:
 509                return -EOPNOTSUPP;
 510        }
 511
 512        return 0;
 513}
 514
 515static int
 516nouveau_pwm_read(struct device *dev, u32 attr, int channel, long *val)
 517{
 518        struct drm_device *drm_dev = dev_get_drvdata(dev);
 519        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 520        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 521
 522        if (!therm || !therm->attr_get || !therm->fan_get)
 523                return -EOPNOTSUPP;
 524
 525        switch (attr) {
 526        case hwmon_pwm_enable:
 527                *val = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MODE);
 528                break;
 529        case hwmon_pwm_input:
 530                *val = therm->fan_get(therm);
 531                break;
 532        default:
 533                return -EOPNOTSUPP;
 534        }
 535
 536        return 0;
 537}
 538
 539static int
 540nouveau_power_read(struct device *dev, u32 attr, int channel, long *val)
 541{
 542        struct drm_device *drm_dev = dev_get_drvdata(dev);
 543        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 544        struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
 545
 546        if (!iccsense)
 547                return -EOPNOTSUPP;
 548
 549        switch (attr) {
 550        case hwmon_power_input:
 551                *val = nvkm_iccsense_read_all(iccsense);
 552                break;
 553        case hwmon_power_max:
 554                *val = iccsense->power_w_max;
 555                break;
 556        case hwmon_power_crit:
 557                *val = iccsense->power_w_crit;
 558                break;
 559        default:
 560                return -EOPNOTSUPP;
 561        }
 562
 563        return 0;
 564}
 565
 566static int
 567nouveau_temp_write(struct device *dev, u32 attr, int channel, long val)
 568{
 569        struct drm_device *drm_dev = dev_get_drvdata(dev);
 570        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 571        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 572
 573        if (!therm || !therm->attr_set)
 574                return -EOPNOTSUPP;
 575
 576        switch (attr) {
 577        case hwmon_temp_max:
 578                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK,
 579                                        val / 1000);
 580        case hwmon_temp_max_hyst:
 581                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST,
 582                                        val / 1000);
 583        case hwmon_temp_crit:
 584                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL,
 585                                        val / 1000);
 586        case hwmon_temp_crit_hyst:
 587                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST,
 588                                        val / 1000);
 589        case hwmon_temp_emergency:
 590                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN,
 591                                        val / 1000);
 592        case hwmon_temp_emergency_hyst:
 593                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST,
 594                                        val / 1000);
 595        default:
 596                return -EOPNOTSUPP;
 597        }
 598}
 599
 600static int
 601nouveau_pwm_write(struct device *dev, u32 attr, int channel, long val)
 602{
 603        struct drm_device *drm_dev = dev_get_drvdata(dev);
 604        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 605        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 606
 607        if (!therm || !therm->attr_set)
 608                return -EOPNOTSUPP;
 609
 610        switch (attr) {
 611        case hwmon_pwm_input:
 612                return therm->fan_set(therm, val);
 613        case hwmon_pwm_enable:
 614                return therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MODE, val);
 615        default:
 616                return -EOPNOTSUPP;
 617        }
 618}
 619
 620static umode_t
 621nouveau_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
 622                        int channel)
 623{
 624        switch (type) {
 625        case hwmon_chip:
 626                return nouveau_chip_is_visible(data, attr, channel);
 627        case hwmon_temp:
 628                return nouveau_temp_is_visible(data, attr, channel);
 629        case hwmon_fan:
 630                return nouveau_fan_is_visible(data, attr, channel);
 631        case hwmon_in:
 632                return nouveau_input_is_visible(data, attr, channel);
 633        case hwmon_pwm:
 634                return nouveau_pwm_is_visible(data, attr, channel);
 635        case hwmon_power:
 636                return nouveau_power_is_visible(data, attr, channel);
 637        default:
 638                return 0;
 639        }
 640}
 641
 642static const char input_label[] = "GPU core";
 643
 644static int
 645nouveau_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 646                    int channel, const char **buf)
 647{
 648        if (type == hwmon_in && attr == hwmon_in_label) {
 649                *buf = input_label;
 650                return 0;
 651        }
 652
 653        return -EOPNOTSUPP;
 654}
 655
 656static int
 657nouveau_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 658                                                        int channel, long *val)
 659{
 660        switch (type) {
 661        case hwmon_chip:
 662                return nouveau_chip_read(dev, attr, channel, val);
 663        case hwmon_temp:
 664                return nouveau_temp_read(dev, attr, channel, val);
 665        case hwmon_fan:
 666                return nouveau_fan_read(dev, attr, channel, val);
 667        case hwmon_in:
 668                return nouveau_in_read(dev, attr, channel, val);
 669        case hwmon_pwm:
 670                return nouveau_pwm_read(dev, attr, channel, val);
 671        case hwmon_power:
 672                return nouveau_power_read(dev, attr, channel, val);
 673        default:
 674                return -EOPNOTSUPP;
 675        }
 676}
 677
 678static int
 679nouveau_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 680                                                        int channel, long val)
 681{
 682        switch (type) {
 683        case hwmon_temp:
 684                return nouveau_temp_write(dev, attr, channel, val);
 685        case hwmon_pwm:
 686                return nouveau_pwm_write(dev, attr, channel, val);
 687        default:
 688                return -EOPNOTSUPP;
 689        }
 690}
 691
 692static const struct hwmon_ops nouveau_hwmon_ops = {
 693        .is_visible = nouveau_is_visible,
 694        .read = nouveau_read,
 695        .read_string = nouveau_read_string,
 696        .write = nouveau_write,
 697};
 698
 699static const struct hwmon_chip_info nouveau_chip_info = {
 700        .ops = &nouveau_hwmon_ops,
 701        .info = nouveau_info,
 702};
 703#endif
 704
 705int
 706nouveau_hwmon_init(struct drm_device *dev)
 707{
 708#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 709        struct nouveau_drm *drm = nouveau_drm(dev);
 710        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 711        const struct attribute_group *special_groups[N_ATTR_GROUPS];
 712        struct nouveau_hwmon *hwmon;
 713        struct device *hwmon_dev;
 714        int ret = 0;
 715        int i = 0;
 716
 717        hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
 718        if (!hwmon)
 719                return -ENOMEM;
 720        hwmon->dev = dev;
 721
 722        if (therm && therm->attr_get && therm->attr_set) {
 723                if (nvkm_therm_temp_get(therm) >= 0)
 724                        special_groups[i++] = &temp1_auto_point_sensor_group;
 725                if (therm->fan_get && therm->fan_get(therm) >= 0)
 726                        special_groups[i++] = &pwm_fan_sensor_group;
 727        }
 728
 729        special_groups[i] = 0;
 730        hwmon_dev = hwmon_device_register_with_info(dev->dev, "nouveau", dev,
 731                                                        &nouveau_chip_info,
 732                                                        special_groups);
 733        if (IS_ERR(hwmon_dev)) {
 734                ret = PTR_ERR(hwmon_dev);
 735                NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
 736                return ret;
 737        }
 738
 739        hwmon->hwmon = hwmon_dev;
 740        return 0;
 741#else
 742        return 0;
 743#endif
 744}
 745
 746void
 747nouveau_hwmon_fini(struct drm_device *dev)
 748{
 749#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 750        struct nouveau_hwmon *hwmon = nouveau_hwmon(dev);
 751
 752        if (hwmon->hwmon)
 753                hwmon_device_unregister(hwmon->hwmon);
 754
 755        nouveau_drm(dev)->hwmon = NULL;
 756        kfree(hwmon);
 757#endif
 758}
 759