root/drivers/hwmon/ibmpowernv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. show_sensor
  2. show_enable
  3. store_enable
  4. show_label
  5. get_logical_cpu
  6. make_sensor_label
  7. get_sensor_index_attr
  8. convert_opal_attr_name
  9. parse_opal_node_name
  10. get_sensor_type
  11. get_sensor_hwmon_index
  12. init_sensor_group_data
  13. get_sensor_group
  14. populate_attr_groups
  15. create_hwmon_attr
  16. populate_sensor
  17. get_max_attr
  18. get_min_attr
  19. create_device_attrs
  20. ibmpowernv_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * IBM PowerNV platform sensors for temperature/fan/voltage/power
   4  * Copyright (C) 2014 IBM
   5  */
   6 
   7 #define DRVNAME         "ibmpowernv"
   8 #define pr_fmt(fmt)     DRVNAME ": " fmt
   9 
  10 #include <linux/init.h>
  11 #include <linux/module.h>
  12 #include <linux/kernel.h>
  13 #include <linux/hwmon.h>
  14 #include <linux/hwmon-sysfs.h>
  15 #include <linux/of.h>
  16 #include <linux/slab.h>
  17 
  18 #include <linux/platform_device.h>
  19 #include <asm/opal.h>
  20 #include <linux/err.h>
  21 #include <asm/cputhreads.h>
  22 #include <asm/smp.h>
  23 
  24 #define MAX_ATTR_LEN    32
  25 #define MAX_LABEL_LEN   64
  26 
  27 /* Sensor suffix name from DT */
  28 #define DT_FAULT_ATTR_SUFFIX            "faulted"
  29 #define DT_DATA_ATTR_SUFFIX             "data"
  30 #define DT_THRESHOLD_ATTR_SUFFIX        "thrs"
  31 
  32 /*
  33  * Enumerates all the types of sensors in the POWERNV platform and does index
  34  * into 'struct sensor_group'
  35  */
  36 enum sensors {
  37         FAN,
  38         TEMP,
  39         POWER_SUPPLY,
  40         POWER_INPUT,
  41         CURRENT,
  42         ENERGY,
  43         MAX_SENSOR_TYPE,
  44 };
  45 
  46 #define INVALID_INDEX (-1U)
  47 
  48 /*
  49  * 'compatible' string properties for sensor types as defined in old
  50  * PowerNV firmware (skiboot). These are ordered as 'enum sensors'.
  51  */
  52 static const char * const legacy_compatibles[] = {
  53         "ibm,opal-sensor-cooling-fan",
  54         "ibm,opal-sensor-amb-temp",
  55         "ibm,opal-sensor-power-supply",
  56         "ibm,opal-sensor-power"
  57 };
  58 
  59 static struct sensor_group {
  60         const char *name; /* matches property 'sensor-type' */
  61         struct attribute_group group;
  62         u32 attr_count;
  63         u32 hwmon_index;
  64 } sensor_groups[] = {
  65         { "fan"   },
  66         { "temp"  },
  67         { "in"    },
  68         { "power" },
  69         { "curr"  },
  70         { "energy" },
  71 };
  72 
  73 struct sensor_data {
  74         u32 id; /* An opaque id of the firmware for each sensor */
  75         u32 hwmon_index;
  76         u32 opal_index;
  77         enum sensors type;
  78         char label[MAX_LABEL_LEN];
  79         char name[MAX_ATTR_LEN];
  80         struct device_attribute dev_attr;
  81         struct sensor_group_data *sgrp_data;
  82 };
  83 
  84 struct sensor_group_data {
  85         struct mutex mutex;
  86         u32 gid;
  87         bool enable;
  88 };
  89 
  90 struct platform_data {
  91         const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];
  92         struct sensor_group_data *sgrp_data;
  93         u32 sensors_count; /* Total count of sensors from each group */
  94         u32 nr_sensor_groups; /* Total number of sensor groups */
  95 };
  96 
  97 static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
  98                            char *buf)
  99 {
 100         struct sensor_data *sdata = container_of(devattr, struct sensor_data,
 101                                                  dev_attr);
 102         ssize_t ret;
 103         u64 x;
 104 
 105         if (sdata->sgrp_data && !sdata->sgrp_data->enable)
 106                 return -ENODATA;
 107 
 108         ret =  opal_get_sensor_data_u64(sdata->id, &x);
 109 
 110         if (ret)
 111                 return ret;
 112 
 113         /* Convert temperature to milli-degrees */
 114         if (sdata->type == TEMP)
 115                 x *= 1000;
 116         /* Convert power to micro-watts */
 117         else if (sdata->type == POWER_INPUT)
 118                 x *= 1000000;
 119 
 120         return sprintf(buf, "%llu\n", x);
 121 }
 122 
 123 static ssize_t show_enable(struct device *dev,
 124                            struct device_attribute *devattr, char *buf)
 125 {
 126         struct sensor_data *sdata = container_of(devattr, struct sensor_data,
 127                                                  dev_attr);
 128 
 129         return sprintf(buf, "%u\n", sdata->sgrp_data->enable);
 130 }
 131 
 132 static ssize_t store_enable(struct device *dev,
 133                             struct device_attribute *devattr,
 134                             const char *buf, size_t count)
 135 {
 136         struct sensor_data *sdata = container_of(devattr, struct sensor_data,
 137                                                  dev_attr);
 138         struct sensor_group_data *sgrp_data = sdata->sgrp_data;
 139         int ret;
 140         bool data;
 141 
 142         ret = kstrtobool(buf, &data);
 143         if (ret)
 144                 return ret;
 145 
 146         ret = mutex_lock_interruptible(&sgrp_data->mutex);
 147         if (ret)
 148                 return ret;
 149 
 150         if (data != sgrp_data->enable) {
 151                 ret =  sensor_group_enable(sgrp_data->gid, data);
 152                 if (!ret)
 153                         sgrp_data->enable = data;
 154         }
 155 
 156         if (!ret)
 157                 ret = count;
 158 
 159         mutex_unlock(&sgrp_data->mutex);
 160         return ret;
 161 }
 162 
 163 static ssize_t show_label(struct device *dev, struct device_attribute *devattr,
 164                           char *buf)
 165 {
 166         struct sensor_data *sdata = container_of(devattr, struct sensor_data,
 167                                                  dev_attr);
 168 
 169         return sprintf(buf, "%s\n", sdata->label);
 170 }
 171 
 172 static int get_logical_cpu(int hwcpu)
 173 {
 174         int cpu;
 175 
 176         for_each_possible_cpu(cpu)
 177                 if (get_hard_smp_processor_id(cpu) == hwcpu)
 178                         return cpu;
 179 
 180         return -ENOENT;
 181 }
 182 
 183 static void make_sensor_label(struct device_node *np,
 184                               struct sensor_data *sdata, const char *label)
 185 {
 186         u32 id;
 187         size_t n;
 188 
 189         n = snprintf(sdata->label, sizeof(sdata->label), "%s", label);
 190 
 191         /*
 192          * Core temp pretty print
 193          */
 194         if (!of_property_read_u32(np, "ibm,pir", &id)) {
 195                 int cpuid = get_logical_cpu(id);
 196 
 197                 if (cpuid >= 0)
 198                         /*
 199                          * The digital thermal sensors are associated
 200                          * with a core.
 201                          */
 202                         n += snprintf(sdata->label + n,
 203                                       sizeof(sdata->label) - n, " %d",
 204                                       cpuid);
 205                 else
 206                         n += snprintf(sdata->label + n,
 207                                       sizeof(sdata->label) - n, " phy%d", id);
 208         }
 209 
 210         /*
 211          * Membuffer pretty print
 212          */
 213         if (!of_property_read_u32(np, "ibm,chip-id", &id))
 214                 n += snprintf(sdata->label + n, sizeof(sdata->label) - n,
 215                               " %d", id & 0xffff);
 216 }
 217 
 218 static int get_sensor_index_attr(const char *name, u32 *index, char *attr)
 219 {
 220         char *hash_pos = strchr(name, '#');
 221         char buf[8] = { 0 };
 222         char *dash_pos;
 223         u32 copy_len;
 224         int err;
 225 
 226         if (!hash_pos)
 227                 return -EINVAL;
 228 
 229         dash_pos = strchr(hash_pos, '-');
 230         if (!dash_pos)
 231                 return -EINVAL;
 232 
 233         copy_len = dash_pos - hash_pos - 1;
 234         if (copy_len >= sizeof(buf))
 235                 return -EINVAL;
 236 
 237         strncpy(buf, hash_pos + 1, copy_len);
 238 
 239         err = kstrtou32(buf, 10, index);
 240         if (err)
 241                 return err;
 242 
 243         strncpy(attr, dash_pos + 1, MAX_ATTR_LEN);
 244 
 245         return 0;
 246 }
 247 
 248 static const char *convert_opal_attr_name(enum sensors type,
 249                                           const char *opal_attr)
 250 {
 251         const char *attr_name = NULL;
 252 
 253         if (!strcmp(opal_attr, DT_FAULT_ATTR_SUFFIX)) {
 254                 attr_name = "fault";
 255         } else if (!strcmp(opal_attr, DT_DATA_ATTR_SUFFIX)) {
 256                 attr_name = "input";
 257         } else if (!strcmp(opal_attr, DT_THRESHOLD_ATTR_SUFFIX)) {
 258                 if (type == TEMP)
 259                         attr_name = "max";
 260                 else if (type == FAN)
 261                         attr_name = "min";
 262         }
 263 
 264         return attr_name;
 265 }
 266 
 267 /*
 268  * This function translates the DT node name into the 'hwmon' attribute name.
 269  * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc.
 270  * which need to be mapped as fan2_input, temp1_max respectively before
 271  * populating them inside hwmon device class.
 272  */
 273 static const char *parse_opal_node_name(const char *node_name,
 274                                         enum sensors type, u32 *index)
 275 {
 276         char attr_suffix[MAX_ATTR_LEN];
 277         const char *attr_name;
 278         int err;
 279 
 280         err = get_sensor_index_attr(node_name, index, attr_suffix);
 281         if (err)
 282                 return ERR_PTR(err);
 283 
 284         attr_name = convert_opal_attr_name(type, attr_suffix);
 285         if (!attr_name)
 286                 return ERR_PTR(-ENOENT);
 287 
 288         return attr_name;
 289 }
 290 
 291 static int get_sensor_type(struct device_node *np)
 292 {
 293         enum sensors type;
 294         const char *str;
 295 
 296         for (type = 0; type < ARRAY_SIZE(legacy_compatibles); type++) {
 297                 if (of_device_is_compatible(np, legacy_compatibles[type]))
 298                         return type;
 299         }
 300 
 301         /*
 302          * Let's check if we have a newer device tree
 303          */
 304         if (!of_device_is_compatible(np, "ibm,opal-sensor"))
 305                 return MAX_SENSOR_TYPE;
 306 
 307         if (of_property_read_string(np, "sensor-type", &str))
 308                 return MAX_SENSOR_TYPE;
 309 
 310         for (type = 0; type < MAX_SENSOR_TYPE; type++)
 311                 if (!strcmp(str, sensor_groups[type].name))
 312                         return type;
 313 
 314         return MAX_SENSOR_TYPE;
 315 }
 316 
 317 static u32 get_sensor_hwmon_index(struct sensor_data *sdata,
 318                                   struct sensor_data *sdata_table, int count)
 319 {
 320         int i;
 321 
 322         /*
 323          * We don't use the OPAL index on newer device trees
 324          */
 325         if (sdata->opal_index != INVALID_INDEX) {
 326                 for (i = 0; i < count; i++)
 327                         if (sdata_table[i].opal_index == sdata->opal_index &&
 328                             sdata_table[i].type == sdata->type)
 329                                 return sdata_table[i].hwmon_index;
 330         }
 331         return ++sensor_groups[sdata->type].hwmon_index;
 332 }
 333 
 334 static int init_sensor_group_data(struct platform_device *pdev,
 335                                   struct platform_data *pdata)
 336 {
 337         struct sensor_group_data *sgrp_data;
 338         struct device_node *groups, *sgrp;
 339         int count = 0, ret = 0;
 340         enum sensors type;
 341 
 342         groups = of_find_compatible_node(NULL, NULL, "ibm,opal-sensor-group");
 343         if (!groups)
 344                 return ret;
 345 
 346         for_each_child_of_node(groups, sgrp) {
 347                 type = get_sensor_type(sgrp);
 348                 if (type != MAX_SENSOR_TYPE)
 349                         pdata->nr_sensor_groups++;
 350         }
 351 
 352         if (!pdata->nr_sensor_groups)
 353                 goto out;
 354 
 355         sgrp_data = devm_kcalloc(&pdev->dev, pdata->nr_sensor_groups,
 356                                  sizeof(*sgrp_data), GFP_KERNEL);
 357         if (!sgrp_data) {
 358                 ret = -ENOMEM;
 359                 goto out;
 360         }
 361 
 362         for_each_child_of_node(groups, sgrp) {
 363                 u32 gid;
 364 
 365                 type = get_sensor_type(sgrp);
 366                 if (type == MAX_SENSOR_TYPE)
 367                         continue;
 368 
 369                 if (of_property_read_u32(sgrp, "sensor-group-id", &gid))
 370                         continue;
 371 
 372                 if (of_count_phandle_with_args(sgrp, "sensors", NULL) <= 0)
 373                         continue;
 374 
 375                 sensor_groups[type].attr_count++;
 376                 sgrp_data[count].gid = gid;
 377                 mutex_init(&sgrp_data[count].mutex);
 378                 sgrp_data[count++].enable = false;
 379         }
 380 
 381         pdata->sgrp_data = sgrp_data;
 382 out:
 383         of_node_put(groups);
 384         return ret;
 385 }
 386 
 387 static struct sensor_group_data *get_sensor_group(struct platform_data *pdata,
 388                                                   struct device_node *node,
 389                                                   enum sensors gtype)
 390 {
 391         struct sensor_group_data *sgrp_data = pdata->sgrp_data;
 392         struct device_node *groups, *sgrp;
 393 
 394         groups = of_find_compatible_node(NULL, NULL, "ibm,opal-sensor-group");
 395         if (!groups)
 396                 return NULL;
 397 
 398         for_each_child_of_node(groups, sgrp) {
 399                 struct of_phandle_iterator it;
 400                 u32 gid;
 401                 int rc, i;
 402                 enum sensors type;
 403 
 404                 type = get_sensor_type(sgrp);
 405                 if (type != gtype)
 406                         continue;
 407 
 408                 if (of_property_read_u32(sgrp, "sensor-group-id", &gid))
 409                         continue;
 410 
 411                 of_for_each_phandle(&it, rc, sgrp, "sensors", NULL, 0)
 412                         if (it.phandle == node->phandle) {
 413                                 of_node_put(it.node);
 414                                 break;
 415                         }
 416 
 417                 if (rc)
 418                         continue;
 419 
 420                 for (i = 0; i < pdata->nr_sensor_groups; i++)
 421                         if (gid == sgrp_data[i].gid) {
 422                                 of_node_put(sgrp);
 423                                 of_node_put(groups);
 424                                 return &sgrp_data[i];
 425                         }
 426         }
 427 
 428         of_node_put(groups);
 429         return NULL;
 430 }
 431 
 432 static int populate_attr_groups(struct platform_device *pdev)
 433 {
 434         struct platform_data *pdata = platform_get_drvdata(pdev);
 435         const struct attribute_group **pgroups = pdata->attr_groups;
 436         struct device_node *opal, *np;
 437         enum sensors type;
 438         int ret;
 439 
 440         ret = init_sensor_group_data(pdev, pdata);
 441         if (ret)
 442                 return ret;
 443 
 444         opal = of_find_node_by_path("/ibm,opal/sensors");
 445         for_each_child_of_node(opal, np) {
 446                 const char *label;
 447 
 448                 type = get_sensor_type(np);
 449                 if (type == MAX_SENSOR_TYPE)
 450                         continue;
 451 
 452                 sensor_groups[type].attr_count++;
 453 
 454                 /*
 455                  * add attributes for labels, min and max
 456                  */
 457                 if (!of_property_read_string(np, "label", &label))
 458                         sensor_groups[type].attr_count++;
 459                 if (of_find_property(np, "sensor-data-min", NULL))
 460                         sensor_groups[type].attr_count++;
 461                 if (of_find_property(np, "sensor-data-max", NULL))
 462                         sensor_groups[type].attr_count++;
 463         }
 464 
 465         of_node_put(opal);
 466 
 467         for (type = 0; type < MAX_SENSOR_TYPE; type++) {
 468                 sensor_groups[type].group.attrs = devm_kcalloc(&pdev->dev,
 469                                         sensor_groups[type].attr_count + 1,
 470                                         sizeof(struct attribute *),
 471                                         GFP_KERNEL);
 472                 if (!sensor_groups[type].group.attrs)
 473                         return -ENOMEM;
 474 
 475                 pgroups[type] = &sensor_groups[type].group;
 476                 pdata->sensors_count += sensor_groups[type].attr_count;
 477                 sensor_groups[type].attr_count = 0;
 478         }
 479 
 480         return 0;
 481 }
 482 
 483 static void create_hwmon_attr(struct sensor_data *sdata, const char *attr_name,
 484                               ssize_t (*show)(struct device *dev,
 485                                               struct device_attribute *attr,
 486                                               char *buf),
 487                             ssize_t (*store)(struct device *dev,
 488                                              struct device_attribute *attr,
 489                                              const char *buf, size_t count))
 490 {
 491         snprintf(sdata->name, MAX_ATTR_LEN, "%s%d_%s",
 492                  sensor_groups[sdata->type].name, sdata->hwmon_index,
 493                  attr_name);
 494 
 495         sysfs_attr_init(&sdata->dev_attr.attr);
 496         sdata->dev_attr.attr.name = sdata->name;
 497         sdata->dev_attr.show = show;
 498         if (store) {
 499                 sdata->dev_attr.store = store;
 500                 sdata->dev_attr.attr.mode = 0664;
 501         } else {
 502                 sdata->dev_attr.attr.mode = 0444;
 503         }
 504 }
 505 
 506 static void populate_sensor(struct sensor_data *sdata, int od, int hd, int sid,
 507                             const char *attr_name, enum sensors type,
 508                             const struct attribute_group *pgroup,
 509                             struct sensor_group_data *sgrp_data,
 510                             ssize_t (*show)(struct device *dev,
 511                                             struct device_attribute *attr,
 512                                             char *buf),
 513                             ssize_t (*store)(struct device *dev,
 514                                              struct device_attribute *attr,
 515                                              const char *buf, size_t count))
 516 {
 517         sdata->id = sid;
 518         sdata->type = type;
 519         sdata->opal_index = od;
 520         sdata->hwmon_index = hd;
 521         create_hwmon_attr(sdata, attr_name, show, store);
 522         pgroup->attrs[sensor_groups[type].attr_count++] = &sdata->dev_attr.attr;
 523         sdata->sgrp_data = sgrp_data;
 524 }
 525 
 526 static char *get_max_attr(enum sensors type)
 527 {
 528         switch (type) {
 529         case POWER_INPUT:
 530                 return "input_highest";
 531         default:
 532                 return "highest";
 533         }
 534 }
 535 
 536 static char *get_min_attr(enum sensors type)
 537 {
 538         switch (type) {
 539         case POWER_INPUT:
 540                 return "input_lowest";
 541         default:
 542                 return "lowest";
 543         }
 544 }
 545 
 546 /*
 547  * Iterate through the device tree for each child of 'sensors' node, create
 548  * a sysfs attribute file, the file is named by translating the DT node name
 549  * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max
 550  * etc..
 551  */
 552 static int create_device_attrs(struct platform_device *pdev)
 553 {
 554         struct platform_data *pdata = platform_get_drvdata(pdev);
 555         const struct attribute_group **pgroups = pdata->attr_groups;
 556         struct device_node *opal, *np;
 557         struct sensor_data *sdata;
 558         u32 count = 0;
 559         u32 group_attr_id[MAX_SENSOR_TYPE] = {0};
 560 
 561         sdata = devm_kcalloc(&pdev->dev,
 562                              pdata->sensors_count, sizeof(*sdata),
 563                              GFP_KERNEL);
 564         if (!sdata)
 565                 return -ENOMEM;
 566 
 567         opal = of_find_node_by_path("/ibm,opal/sensors");
 568         for_each_child_of_node(opal, np) {
 569                 struct sensor_group_data *sgrp_data;
 570                 const char *attr_name;
 571                 u32 opal_index, hw_id;
 572                 u32 sensor_id;
 573                 const char *label;
 574                 enum sensors type;
 575 
 576                 type = get_sensor_type(np);
 577                 if (type == MAX_SENSOR_TYPE)
 578                         continue;
 579 
 580                 /*
 581                  * Newer device trees use a "sensor-data" property
 582                  * name for input.
 583                  */
 584                 if (of_property_read_u32(np, "sensor-id", &sensor_id) &&
 585                     of_property_read_u32(np, "sensor-data", &sensor_id)) {
 586                         dev_info(&pdev->dev,
 587                                  "'sensor-id' missing in the node '%pOFn'\n",
 588                                  np);
 589                         continue;
 590                 }
 591 
 592                 sdata[count].id = sensor_id;
 593                 sdata[count].type = type;
 594 
 595                 /*
 596                  * If we can not parse the node name, it means we are
 597                  * running on a newer device tree. We can just forget
 598                  * about the OPAL index and use a defaut value for the
 599                  * hwmon attribute name
 600                  */
 601                 attr_name = parse_opal_node_name(np->name, type, &opal_index);
 602                 if (IS_ERR(attr_name)) {
 603                         attr_name = "input";
 604                         opal_index = INVALID_INDEX;
 605                 }
 606 
 607                 hw_id = get_sensor_hwmon_index(&sdata[count], sdata, count);
 608                 sgrp_data = get_sensor_group(pdata, np, type);
 609                 populate_sensor(&sdata[count], opal_index, hw_id, sensor_id,
 610                                 attr_name, type, pgroups[type], sgrp_data,
 611                                 show_sensor, NULL);
 612                 count++;
 613 
 614                 if (!of_property_read_string(np, "label", &label)) {
 615                         /*
 616                          * For the label attribute, we can reuse the
 617                          * "properties" of the previous "input"
 618                          * attribute. They are related to the same
 619                          * sensor.
 620                          */
 621 
 622                         make_sensor_label(np, &sdata[count], label);
 623                         populate_sensor(&sdata[count], opal_index, hw_id,
 624                                         sensor_id, "label", type, pgroups[type],
 625                                         NULL, show_label, NULL);
 626                         count++;
 627                 }
 628 
 629                 if (!of_property_read_u32(np, "sensor-data-max", &sensor_id)) {
 630                         attr_name = get_max_attr(type);
 631                         populate_sensor(&sdata[count], opal_index, hw_id,
 632                                         sensor_id, attr_name, type,
 633                                         pgroups[type], sgrp_data, show_sensor,
 634                                         NULL);
 635                         count++;
 636                 }
 637 
 638                 if (!of_property_read_u32(np, "sensor-data-min", &sensor_id)) {
 639                         attr_name = get_min_attr(type);
 640                         populate_sensor(&sdata[count], opal_index, hw_id,
 641                                         sensor_id, attr_name, type,
 642                                         pgroups[type], sgrp_data, show_sensor,
 643                                         NULL);
 644                         count++;
 645                 }
 646 
 647                 if (sgrp_data && !sgrp_data->enable) {
 648                         sgrp_data->enable = true;
 649                         hw_id = ++group_attr_id[type];
 650                         populate_sensor(&sdata[count], opal_index, hw_id,
 651                                         sgrp_data->gid, "enable", type,
 652                                         pgroups[type], sgrp_data, show_enable,
 653                                         store_enable);
 654                         count++;
 655                 }
 656         }
 657 
 658         of_node_put(opal);
 659         return 0;
 660 }
 661 
 662 static int ibmpowernv_probe(struct platform_device *pdev)
 663 {
 664         struct platform_data *pdata;
 665         struct device *hwmon_dev;
 666         int err;
 667 
 668         pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 669         if (!pdata)
 670                 return -ENOMEM;
 671 
 672         platform_set_drvdata(pdev, pdata);
 673         pdata->sensors_count = 0;
 674         pdata->nr_sensor_groups = 0;
 675         err = populate_attr_groups(pdev);
 676         if (err)
 677                 return err;
 678 
 679         /* Create sysfs attribute data for each sensor found in the DT */
 680         err = create_device_attrs(pdev);
 681         if (err)
 682                 return err;
 683 
 684         /* Finally, register with hwmon */
 685         hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME,
 686                                                            pdata,
 687                                                            pdata->attr_groups);
 688 
 689         return PTR_ERR_OR_ZERO(hwmon_dev);
 690 }
 691 
 692 static const struct platform_device_id opal_sensor_driver_ids[] = {
 693         {
 694                 .name = "opal-sensor",
 695         },
 696         { }
 697 };
 698 MODULE_DEVICE_TABLE(platform, opal_sensor_driver_ids);
 699 
 700 static const struct of_device_id opal_sensor_match[] = {
 701         { .compatible   = "ibm,opal-sensor" },
 702         { },
 703 };
 704 MODULE_DEVICE_TABLE(of, opal_sensor_match);
 705 
 706 static struct platform_driver ibmpowernv_driver = {
 707         .probe          = ibmpowernv_probe,
 708         .id_table       = opal_sensor_driver_ids,
 709         .driver         = {
 710                 .name   = DRVNAME,
 711                 .of_match_table = opal_sensor_match,
 712         },
 713 };
 714 
 715 module_platform_driver(ibmpowernv_driver);
 716 
 717 MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
 718 MODULE_DESCRIPTION("IBM POWERNV platform sensors");
 719 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */