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 755cdcb01eSShilpasri G Bhat int opal_get_sensor_data_u64(u32 sensor_hndl, u64 *sensor_data) 765cdcb01eSShilpasri G Bhat { 775cdcb01eSShilpasri G Bhat int ret, token; 785cdcb01eSShilpasri G Bhat struct opal_msg msg; 795cdcb01eSShilpasri G Bhat __be64 data; 805cdcb01eSShilpasri G Bhat 815cdcb01eSShilpasri G Bhat if (!opal_check_token(OPAL_SENSOR_READ_U64)) { 825cdcb01eSShilpasri G Bhat u32 sdata; 835cdcb01eSShilpasri G Bhat 845cdcb01eSShilpasri G Bhat ret = opal_get_sensor_data(sensor_hndl, &sdata); 855cdcb01eSShilpasri G Bhat if (!ret) 865cdcb01eSShilpasri G Bhat *sensor_data = sdata; 875cdcb01eSShilpasri G Bhat return ret; 885cdcb01eSShilpasri G Bhat } 895cdcb01eSShilpasri G Bhat 905cdcb01eSShilpasri G Bhat token = opal_async_get_token_interruptible(); 915cdcb01eSShilpasri G Bhat if (token < 0) 925cdcb01eSShilpasri G Bhat return token; 935cdcb01eSShilpasri G Bhat 945cdcb01eSShilpasri G Bhat ret = opal_sensor_read_u64(sensor_hndl, token, &data); 955cdcb01eSShilpasri G Bhat switch (ret) { 965cdcb01eSShilpasri G Bhat case OPAL_ASYNC_COMPLETION: 975cdcb01eSShilpasri G Bhat ret = opal_async_wait_response(token, &msg); 985cdcb01eSShilpasri G Bhat if (ret) { 995cdcb01eSShilpasri G Bhat pr_err("%s: Failed to wait for the async response, %d\n", 1005cdcb01eSShilpasri G Bhat __func__, ret); 1015cdcb01eSShilpasri G Bhat goto out_token; 1025cdcb01eSShilpasri G Bhat } 1035cdcb01eSShilpasri G Bhat 1045cdcb01eSShilpasri G Bhat ret = opal_error_code(opal_get_async_rc(msg)); 1055cdcb01eSShilpasri G Bhat *sensor_data = be64_to_cpu(data); 1065cdcb01eSShilpasri G Bhat break; 1075cdcb01eSShilpasri G Bhat 1085cdcb01eSShilpasri G Bhat case OPAL_SUCCESS: 1095cdcb01eSShilpasri G Bhat ret = 0; 1105cdcb01eSShilpasri G Bhat *sensor_data = be64_to_cpu(data); 1115cdcb01eSShilpasri G Bhat break; 1125cdcb01eSShilpasri G Bhat 1135cdcb01eSShilpasri G Bhat case OPAL_WRONG_STATE: 1145cdcb01eSShilpasri G Bhat ret = -EIO; 1155cdcb01eSShilpasri G Bhat break; 1165cdcb01eSShilpasri G Bhat 1175cdcb01eSShilpasri G Bhat default: 1185cdcb01eSShilpasri G Bhat ret = opal_error_code(ret); 1195cdcb01eSShilpasri G Bhat break; 1205cdcb01eSShilpasri G Bhat } 1215cdcb01eSShilpasri G Bhat 1225cdcb01eSShilpasri G Bhat out_token: 1235cdcb01eSShilpasri G Bhat opal_async_release_token(token); 1245cdcb01eSShilpasri G Bhat return ret; 1255cdcb01eSShilpasri G Bhat } 1265cdcb01eSShilpasri G Bhat EXPORT_SYMBOL_GPL(opal_get_sensor_data_u64); 1275cdcb01eSShilpasri 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