linux/arch/powerpc/platforms/powernv/opal-sensor.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * PowerNV sensor code
   4 *
   5 * Copyright (C) 2013 IBM
   6 */
   7
   8#include <linux/delay.h>
   9#include <linux/of_platform.h>
  10#include <asm/opal.h>
  11#include <asm/machdep.h>
  12
  13/*
  14 * This will return sensor information to driver based on the requested sensor
  15 * handle. A handle is an opaque id for the powernv, read by the driver from the
  16 * device tree..
  17 */
  18int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
  19{
  20        int ret, token;
  21        struct opal_msg msg;
  22        __be32 data;
  23
  24        token = opal_async_get_token_interruptible();
  25        if (token < 0)
  26                return token;
  27
  28        ret = opal_sensor_read(sensor_hndl, token, &data);
  29        switch (ret) {
  30        case OPAL_ASYNC_COMPLETION:
  31                ret = opal_async_wait_response(token, &msg);
  32                if (ret) {
  33                        pr_err("%s: Failed to wait for the async response, %d\n",
  34                               __func__, ret);
  35                        goto out;
  36                }
  37
  38                ret = opal_error_code(opal_get_async_rc(msg));
  39                *sensor_data = be32_to_cpu(data);
  40                break;
  41
  42        case OPAL_SUCCESS:
  43                ret = 0;
  44                *sensor_data = be32_to_cpu(data);
  45                break;
  46
  47        case OPAL_WRONG_STATE:
  48                ret = -EIO;
  49                break;
  50
  51        default:
  52                ret = opal_error_code(ret);
  53                break;
  54        }
  55
  56out:
  57        opal_async_release_token(token);
  58        return ret;
  59}
  60EXPORT_SYMBOL_GPL(opal_get_sensor_data);
  61
  62int opal_get_sensor_data_u64(u32 sensor_hndl, u64 *sensor_data)
  63{
  64        int ret, token;
  65        struct opal_msg msg;
  66        __be64 data;
  67
  68        if (!opal_check_token(OPAL_SENSOR_READ_U64)) {
  69                u32 sdata;
  70
  71                ret = opal_get_sensor_data(sensor_hndl, &sdata);
  72                if (!ret)
  73                        *sensor_data = sdata;
  74                return ret;
  75        }
  76
  77        token = opal_async_get_token_interruptible();
  78        if (token < 0)
  79                return token;
  80
  81        ret = opal_sensor_read_u64(sensor_hndl, token, &data);
  82        switch (ret) {
  83        case OPAL_ASYNC_COMPLETION:
  84                ret = opal_async_wait_response(token, &msg);
  85                if (ret) {
  86                        pr_err("%s: Failed to wait for the async response, %d\n",
  87                               __func__, ret);
  88                        goto out_token;
  89                }
  90
  91                ret = opal_error_code(opal_get_async_rc(msg));
  92                *sensor_data = be64_to_cpu(data);
  93                break;
  94
  95        case OPAL_SUCCESS:
  96                ret = 0;
  97                *sensor_data = be64_to_cpu(data);
  98                break;
  99
 100        case OPAL_WRONG_STATE:
 101                ret = -EIO;
 102                break;
 103
 104        default:
 105                ret = opal_error_code(ret);
 106                break;
 107        }
 108
 109out_token:
 110        opal_async_release_token(token);
 111        return ret;
 112}
 113EXPORT_SYMBOL_GPL(opal_get_sensor_data_u64);
 114
 115int __init opal_sensor_init(void)
 116{
 117        struct platform_device *pdev;
 118        struct device_node *sensor;
 119
 120        sensor = of_find_node_by_path("/ibm,opal/sensors");
 121        if (!sensor) {
 122                pr_err("Opal node 'sensors' not found\n");
 123                return -ENODEV;
 124        }
 125
 126        pdev = of_platform_device_create(sensor, "opal-sensor", NULL);
 127        of_node_put(sensor);
 128
 129        return PTR_ERR_OR_ZERO(pdev);
 130}
 131