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 */ 18 int 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 56 out: 57 opal_async_release_token(token); 58 return ret; 59 } 60 EXPORT_SYMBOL_GPL(opal_get_sensor_data); 61 62 int 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 109 out_token: 110 opal_async_release_token(token); 111 return ret; 112 } 113 EXPORT_SYMBOL_GPL(opal_get_sensor_data_u64); 114 115 int __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