11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
27224adbbSNeelesh Gupta /*
37224adbbSNeelesh Gupta  * PowerNV sensor code
47224adbbSNeelesh Gupta  *
57224adbbSNeelesh Gupta  * Copyright (C) 2013 IBM
67224adbbSNeelesh Gupta  */
77224adbbSNeelesh Gupta 
87224adbbSNeelesh Gupta #include <linux/delay.h>
9*81d7cac4SRob Herring #include <linux/of.h>
108de303baSNeelesh Gupta #include <linux/of_platform.h>
11*81d7cac4SRob Herring #include <linux/platform_device.h>
127224adbbSNeelesh Gupta #include <asm/opal.h>
138de303baSNeelesh Gupta #include <asm/machdep.h>
147224adbbSNeelesh Gupta 
157224adbbSNeelesh Gupta /*
167224adbbSNeelesh Gupta  * This will return sensor information to driver based on the requested sensor
177224adbbSNeelesh Gupta  * handle. A handle is an opaque id for the powernv, read by the driver from the
187224adbbSNeelesh Gupta  * device tree..
197224adbbSNeelesh Gupta  */
opal_get_sensor_data(u32 sensor_hndl,u32 * sensor_data)207224adbbSNeelesh Gupta int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
217224adbbSNeelesh Gupta {
227224adbbSNeelesh Gupta 	int ret, token;
237224adbbSNeelesh Gupta 	struct opal_msg msg;
249000c17dSAnton Blanchard 	__be32 data;
257224adbbSNeelesh Gupta 
267224adbbSNeelesh Gupta 	token = opal_async_get_token_interruptible();
2795e1bc1dSStewart Smith 	if (token < 0)
2895e1bc1dSStewart Smith 		return token;
297224adbbSNeelesh Gupta 
309000c17dSAnton Blanchard 	ret = opal_sensor_read(sensor_hndl, token, &data);
316bc08d03SCédric Le Goater 	switch (ret) {
326bc08d03SCédric Le Goater 	case OPAL_ASYNC_COMPLETION:
337224adbbSNeelesh Gupta 		ret = opal_async_wait_response(token, &msg);
347224adbbSNeelesh Gupta 		if (ret) {
357224adbbSNeelesh Gupta 			pr_err("%s: Failed to wait for the async response, %d\n",
367224adbbSNeelesh Gupta 			       __func__, ret);
3795e1bc1dSStewart Smith 			goto out;
387224adbbSNeelesh Gupta 		}
397224adbbSNeelesh Gupta 
40d0226d31SSuraj Jitindar Singh 		ret = opal_error_code(opal_get_async_rc(msg));
416bc08d03SCédric Le Goater 		*sensor_data = be32_to_cpu(data);
426bc08d03SCédric Le Goater 		break;
436bc08d03SCédric Le Goater 
446bc08d03SCédric Le Goater 	case OPAL_SUCCESS:
456bc08d03SCédric Le Goater 		ret = 0;
466bc08d03SCédric Le Goater 		*sensor_data = be32_to_cpu(data);
476bc08d03SCédric Le Goater 		break;
486bc08d03SCédric Le Goater 
4917bb6951SVipin K Parashar 	case OPAL_WRONG_STATE:
5017bb6951SVipin K Parashar 		ret = -EIO;
5117bb6951SVipin K Parashar 		break;
5217bb6951SVipin K Parashar 
536bc08d03SCédric Le Goater 	default:
546bc08d03SCédric Le Goater 		ret = opal_error_code(ret);
556bc08d03SCédric Le Goater 		break;
566bc08d03SCédric Le Goater 	}
577224adbbSNeelesh Gupta 
587224adbbSNeelesh Gupta out:
5995e1bc1dSStewart Smith 	opal_async_release_token(token);
607224adbbSNeelesh Gupta 	return ret;
617224adbbSNeelesh Gupta }
627224adbbSNeelesh Gupta EXPORT_SYMBOL_GPL(opal_get_sensor_data);
638de303baSNeelesh Gupta 
opal_get_sensor_data_u64(u32 sensor_hndl,u64 * sensor_data)645cdcb01eSShilpasri G Bhat int opal_get_sensor_data_u64(u32 sensor_hndl, u64 *sensor_data)
655cdcb01eSShilpasri G Bhat {
665cdcb01eSShilpasri G Bhat 	int ret, token;
675cdcb01eSShilpasri G Bhat 	struct opal_msg msg;
685cdcb01eSShilpasri G Bhat 	__be64 data;
695cdcb01eSShilpasri G Bhat 
705cdcb01eSShilpasri G Bhat 	if (!opal_check_token(OPAL_SENSOR_READ_U64)) {
715cdcb01eSShilpasri G Bhat 		u32 sdata;
725cdcb01eSShilpasri G Bhat 
735cdcb01eSShilpasri G Bhat 		ret = opal_get_sensor_data(sensor_hndl, &sdata);
745cdcb01eSShilpasri G Bhat 		if (!ret)
755cdcb01eSShilpasri G Bhat 			*sensor_data = sdata;
765cdcb01eSShilpasri G Bhat 		return ret;
775cdcb01eSShilpasri G Bhat 	}
785cdcb01eSShilpasri G Bhat 
795cdcb01eSShilpasri G Bhat 	token = opal_async_get_token_interruptible();
805cdcb01eSShilpasri G Bhat 	if (token < 0)
815cdcb01eSShilpasri G Bhat 		return token;
825cdcb01eSShilpasri G Bhat 
835cdcb01eSShilpasri G Bhat 	ret = opal_sensor_read_u64(sensor_hndl, token, &data);
845cdcb01eSShilpasri G Bhat 	switch (ret) {
855cdcb01eSShilpasri G Bhat 	case OPAL_ASYNC_COMPLETION:
865cdcb01eSShilpasri G Bhat 		ret = opal_async_wait_response(token, &msg);
875cdcb01eSShilpasri G Bhat 		if (ret) {
885cdcb01eSShilpasri G Bhat 			pr_err("%s: Failed to wait for the async response, %d\n",
895cdcb01eSShilpasri G Bhat 			       __func__, ret);
905cdcb01eSShilpasri G Bhat 			goto out_token;
915cdcb01eSShilpasri G Bhat 		}
925cdcb01eSShilpasri G Bhat 
935cdcb01eSShilpasri G Bhat 		ret = opal_error_code(opal_get_async_rc(msg));
945cdcb01eSShilpasri G Bhat 		*sensor_data = be64_to_cpu(data);
955cdcb01eSShilpasri G Bhat 		break;
965cdcb01eSShilpasri G Bhat 
975cdcb01eSShilpasri G Bhat 	case OPAL_SUCCESS:
985cdcb01eSShilpasri G Bhat 		ret = 0;
995cdcb01eSShilpasri G Bhat 		*sensor_data = be64_to_cpu(data);
1005cdcb01eSShilpasri G Bhat 		break;
1015cdcb01eSShilpasri G Bhat 
1025cdcb01eSShilpasri G Bhat 	case OPAL_WRONG_STATE:
1035cdcb01eSShilpasri G Bhat 		ret = -EIO;
1045cdcb01eSShilpasri G Bhat 		break;
1055cdcb01eSShilpasri G Bhat 
1065cdcb01eSShilpasri G Bhat 	default:
1075cdcb01eSShilpasri G Bhat 		ret = opal_error_code(ret);
1085cdcb01eSShilpasri G Bhat 		break;
1095cdcb01eSShilpasri G Bhat 	}
1105cdcb01eSShilpasri G Bhat 
1115cdcb01eSShilpasri G Bhat out_token:
1125cdcb01eSShilpasri G Bhat 	opal_async_release_token(token);
1135cdcb01eSShilpasri G Bhat 	return ret;
1145cdcb01eSShilpasri G Bhat }
1155cdcb01eSShilpasri G Bhat EXPORT_SYMBOL_GPL(opal_get_sensor_data_u64);
1165cdcb01eSShilpasri G Bhat 
opal_sensor_init(void)11796e023e7SAlistair Popple int __init opal_sensor_init(void)
1188de303baSNeelesh Gupta {
1198de303baSNeelesh Gupta 	struct platform_device *pdev;
1208de303baSNeelesh Gupta 	struct device_node *sensor;
1218de303baSNeelesh Gupta 
1228de303baSNeelesh Gupta 	sensor = of_find_node_by_path("/ibm,opal/sensors");
1238de303baSNeelesh Gupta 	if (!sensor) {
1248de303baSNeelesh Gupta 		pr_err("Opal node 'sensors' not found\n");
1258de303baSNeelesh Gupta 		return -ENODEV;
1268de303baSNeelesh Gupta 	}
1278de303baSNeelesh Gupta 
1288de303baSNeelesh Gupta 	pdev = of_platform_device_create(sensor, "opal-sensor", NULL);
1298de303baSNeelesh Gupta 	of_node_put(sensor);
1308de303baSNeelesh Gupta 
1318de303baSNeelesh Gupta 	return PTR_ERR_OR_ZERO(pdev);
1328de303baSNeelesh Gupta }
133