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