17224adbbSNeelesh Gupta /* 27224adbbSNeelesh Gupta * PowerNV sensor code 37224adbbSNeelesh Gupta * 47224adbbSNeelesh Gupta * Copyright (C) 2013 IBM 57224adbbSNeelesh Gupta * 67224adbbSNeelesh Gupta * This program is free software; you can redistribute it and/or modify 77224adbbSNeelesh Gupta * it under the terms of the GNU General Public License as published by 87224adbbSNeelesh Gupta * the Free Software Foundation; either version 2 of the License, or 97224adbbSNeelesh Gupta * (at your option) any later version. 107224adbbSNeelesh Gupta * 117224adbbSNeelesh Gupta * This program is distributed in the hope that it will be useful, 127224adbbSNeelesh Gupta * but WITHOUT ANY WARRANTY; without even the implied warranty of 137224adbbSNeelesh Gupta * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147224adbbSNeelesh Gupta * GNU General Public License for more details. 157224adbbSNeelesh Gupta * 167224adbbSNeelesh Gupta * You should have received a copy of the GNU General Public License 177224adbbSNeelesh Gupta * along with this program; if not, write to the Free Software 187224adbbSNeelesh Gupta * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 197224adbbSNeelesh Gupta */ 207224adbbSNeelesh Gupta 217224adbbSNeelesh Gupta #include <linux/delay.h> 228de303baSNeelesh Gupta #include <linux/of_platform.h> 237224adbbSNeelesh Gupta #include <asm/opal.h> 248de303baSNeelesh Gupta #include <asm/machdep.h> 257224adbbSNeelesh Gupta 267224adbbSNeelesh Gupta /* 277224adbbSNeelesh Gupta * This will return sensor information to driver based on the requested sensor 287224adbbSNeelesh Gupta * handle. A handle is an opaque id for the powernv, read by the driver from the 297224adbbSNeelesh Gupta * device tree.. 307224adbbSNeelesh Gupta */ 317224adbbSNeelesh Gupta int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) 327224adbbSNeelesh Gupta { 337224adbbSNeelesh Gupta int ret, token; 347224adbbSNeelesh Gupta struct opal_msg msg; 359000c17dSAnton Blanchard __be32 data; 367224adbbSNeelesh Gupta 377224adbbSNeelesh Gupta token = opal_async_get_token_interruptible(); 3895e1bc1dSStewart Smith if (token < 0) 3995e1bc1dSStewart Smith return token; 407224adbbSNeelesh Gupta 419000c17dSAnton Blanchard ret = opal_sensor_read(sensor_hndl, token, &data); 426bc08d03SCédric Le Goater switch (ret) { 436bc08d03SCédric Le Goater case OPAL_ASYNC_COMPLETION: 447224adbbSNeelesh Gupta ret = opal_async_wait_response(token, &msg); 457224adbbSNeelesh Gupta if (ret) { 467224adbbSNeelesh Gupta pr_err("%s: Failed to wait for the async response, %d\n", 477224adbbSNeelesh Gupta __func__, ret); 4895e1bc1dSStewart Smith goto out; 497224adbbSNeelesh Gupta } 507224adbbSNeelesh Gupta 51d0226d31SSuraj Jitindar Singh ret = opal_error_code(opal_get_async_rc(msg)); 526bc08d03SCédric Le Goater *sensor_data = be32_to_cpu(data); 536bc08d03SCédric Le Goater break; 546bc08d03SCédric Le Goater 556bc08d03SCédric Le Goater case OPAL_SUCCESS: 566bc08d03SCédric Le Goater ret = 0; 576bc08d03SCédric Le Goater *sensor_data = be32_to_cpu(data); 586bc08d03SCédric Le Goater break; 596bc08d03SCédric Le Goater 6017bb6951SVipin K Parashar case OPAL_WRONG_STATE: 6117bb6951SVipin K Parashar ret = -EIO; 6217bb6951SVipin K Parashar break; 6317bb6951SVipin K Parashar 646bc08d03SCédric Le Goater default: 656bc08d03SCédric Le Goater ret = opal_error_code(ret); 666bc08d03SCédric Le Goater break; 676bc08d03SCédric Le Goater } 687224adbbSNeelesh Gupta 697224adbbSNeelesh Gupta out: 7095e1bc1dSStewart Smith opal_async_release_token(token); 717224adbbSNeelesh Gupta return ret; 727224adbbSNeelesh Gupta } 737224adbbSNeelesh Gupta EXPORT_SYMBOL_GPL(opal_get_sensor_data); 748de303baSNeelesh Gupta 75*5cdcb01eSShilpasri G Bhat int opal_get_sensor_data_u64(u32 sensor_hndl, u64 *sensor_data) 76*5cdcb01eSShilpasri G Bhat { 77*5cdcb01eSShilpasri G Bhat int ret, token; 78*5cdcb01eSShilpasri G Bhat struct opal_msg msg; 79*5cdcb01eSShilpasri G Bhat __be64 data; 80*5cdcb01eSShilpasri G Bhat 81*5cdcb01eSShilpasri G Bhat if (!opal_check_token(OPAL_SENSOR_READ_U64)) { 82*5cdcb01eSShilpasri G Bhat u32 sdata; 83*5cdcb01eSShilpasri G Bhat 84*5cdcb01eSShilpasri G Bhat ret = opal_get_sensor_data(sensor_hndl, &sdata); 85*5cdcb01eSShilpasri G Bhat if (!ret) 86*5cdcb01eSShilpasri G Bhat *sensor_data = sdata; 87*5cdcb01eSShilpasri G Bhat return ret; 88*5cdcb01eSShilpasri G Bhat } 89*5cdcb01eSShilpasri G Bhat 90*5cdcb01eSShilpasri G Bhat token = opal_async_get_token_interruptible(); 91*5cdcb01eSShilpasri G Bhat if (token < 0) 92*5cdcb01eSShilpasri G Bhat return token; 93*5cdcb01eSShilpasri G Bhat 94*5cdcb01eSShilpasri G Bhat ret = opal_sensor_read_u64(sensor_hndl, token, &data); 95*5cdcb01eSShilpasri G Bhat switch (ret) { 96*5cdcb01eSShilpasri G Bhat case OPAL_ASYNC_COMPLETION: 97*5cdcb01eSShilpasri G Bhat ret = opal_async_wait_response(token, &msg); 98*5cdcb01eSShilpasri G Bhat if (ret) { 99*5cdcb01eSShilpasri G Bhat pr_err("%s: Failed to wait for the async response, %d\n", 100*5cdcb01eSShilpasri G Bhat __func__, ret); 101*5cdcb01eSShilpasri G Bhat goto out_token; 102*5cdcb01eSShilpasri G Bhat } 103*5cdcb01eSShilpasri G Bhat 104*5cdcb01eSShilpasri G Bhat ret = opal_error_code(opal_get_async_rc(msg)); 105*5cdcb01eSShilpasri G Bhat *sensor_data = be64_to_cpu(data); 106*5cdcb01eSShilpasri G Bhat break; 107*5cdcb01eSShilpasri G Bhat 108*5cdcb01eSShilpasri G Bhat case OPAL_SUCCESS: 109*5cdcb01eSShilpasri G Bhat ret = 0; 110*5cdcb01eSShilpasri G Bhat *sensor_data = be64_to_cpu(data); 111*5cdcb01eSShilpasri G Bhat break; 112*5cdcb01eSShilpasri G Bhat 113*5cdcb01eSShilpasri G Bhat case OPAL_WRONG_STATE: 114*5cdcb01eSShilpasri G Bhat ret = -EIO; 115*5cdcb01eSShilpasri G Bhat break; 116*5cdcb01eSShilpasri G Bhat 117*5cdcb01eSShilpasri G Bhat default: 118*5cdcb01eSShilpasri G Bhat ret = opal_error_code(ret); 119*5cdcb01eSShilpasri G Bhat break; 120*5cdcb01eSShilpasri G Bhat } 121*5cdcb01eSShilpasri G Bhat 122*5cdcb01eSShilpasri G Bhat out_token: 123*5cdcb01eSShilpasri G Bhat opal_async_release_token(token); 124*5cdcb01eSShilpasri G Bhat return ret; 125*5cdcb01eSShilpasri G Bhat } 126*5cdcb01eSShilpasri G Bhat EXPORT_SYMBOL_GPL(opal_get_sensor_data_u64); 127*5cdcb01eSShilpasri G Bhat 12896e023e7SAlistair Popple int __init opal_sensor_init(void) 1298de303baSNeelesh Gupta { 1308de303baSNeelesh Gupta struct platform_device *pdev; 1318de303baSNeelesh Gupta struct device_node *sensor; 1328de303baSNeelesh Gupta 1338de303baSNeelesh Gupta sensor = of_find_node_by_path("/ibm,opal/sensors"); 1348de303baSNeelesh Gupta if (!sensor) { 1358de303baSNeelesh Gupta pr_err("Opal node 'sensors' not found\n"); 1368de303baSNeelesh Gupta return -ENODEV; 1378de303baSNeelesh Gupta } 1388de303baSNeelesh Gupta 1398de303baSNeelesh Gupta pdev = of_platform_device_create(sensor, "opal-sensor", NULL); 1408de303baSNeelesh Gupta of_node_put(sensor); 1418de303baSNeelesh Gupta 1428de303baSNeelesh Gupta return PTR_ERR_OR_ZERO(pdev); 1438de303baSNeelesh Gupta } 144