Add SPDX license identifiers to all files which:
 - Have no license information of any form
 - Have MODULE_LICENCE("GPL*") inside which was used in the initial
   scan/conversion to ignore the file
These files fall under the project license, GPL v2 only. The resulting SPDX
license identifier is:
  GPL-2.0-only
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
		
	
			
		
			
				
	
	
		
			127 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0-only
 | |
| #include <linux/io.h>
 | |
| #include <linux/delay.h>
 | |
| #include <linux/module.h>
 | |
| #include <linux/thermal.h>
 | |
| #include <linux/platform_device.h>
 | |
| 
 | |
| /*
 | |
|  * According to a data sheet draft, "this temperature sensor uses a bandgap
 | |
|  * type of circuit to compare a voltage which has a negative temperature
 | |
|  * coefficient with a voltage that is proportional to absolute temperature.
 | |
|  * A resistor bank allows 41 different temperature thresholds to be selected
 | |
|  * and the logic output will then indicate whether the actual die temperature
 | |
|  * lies above or below the selected threshold."
 | |
|  */
 | |
| 
 | |
| #define TEMPSI_CMD	0
 | |
| #define TEMPSI_RES	4
 | |
| #define TEMPSI_CFG	8
 | |
| 
 | |
| #define CMD_OFF		0
 | |
| #define CMD_ON		1
 | |
| #define CMD_READ	2
 | |
| 
 | |
| #define IDX_MIN		15
 | |
| #define IDX_MAX		40
 | |
| 
 | |
| struct tango_thermal_priv {
 | |
| 	void __iomem *base;
 | |
| 	int thresh_idx;
 | |
| };
 | |
| 
 | |
| static bool temp_above_thresh(void __iomem *base, int thresh_idx)
 | |
| {
 | |
| 	writel(CMD_READ | thresh_idx << 8, base + TEMPSI_CMD);
 | |
| 	usleep_range(10, 20);
 | |
| 	writel(CMD_READ | thresh_idx << 8, base + TEMPSI_CMD);
 | |
| 
 | |
| 	return readl(base + TEMPSI_RES);
 | |
| }
 | |
| 
 | |
| static int tango_get_temp(void *arg, int *res)
 | |
| {
 | |
| 	struct tango_thermal_priv *priv = arg;
 | |
| 	int idx = priv->thresh_idx;
 | |
| 
 | |
| 	if (temp_above_thresh(priv->base, idx)) {
 | |
| 		/* Search upward by incrementing thresh_idx */
 | |
| 		while (idx < IDX_MAX && temp_above_thresh(priv->base, ++idx))
 | |
| 			cpu_relax();
 | |
| 		idx = idx - 1; /* always return lower bound */
 | |
| 	} else {
 | |
| 		/* Search downward by decrementing thresh_idx */
 | |
| 		while (idx > IDX_MIN && !temp_above_thresh(priv->base, --idx))
 | |
| 			cpu_relax();
 | |
| 	}
 | |
| 
 | |
| 	*res = (idx * 9 / 2 - 38) * 1000; /* millidegrees Celsius */
 | |
| 	priv->thresh_idx = idx;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static const struct thermal_zone_of_device_ops ops = {
 | |
| 	.get_temp	= tango_get_temp,
 | |
| };
 | |
| 
 | |
| static void tango_thermal_init(struct tango_thermal_priv *priv)
 | |
| {
 | |
| 	writel(0, priv->base + TEMPSI_CFG);
 | |
| 	writel(CMD_ON, priv->base + TEMPSI_CMD);
 | |
| }
 | |
| 
 | |
| static int tango_thermal_probe(struct platform_device *pdev)
 | |
| {
 | |
| 	struct resource *res;
 | |
| 	struct tango_thermal_priv *priv;
 | |
| 	struct thermal_zone_device *tzdev;
 | |
| 
 | |
| 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 | |
| 	if (!priv)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | |
| 	priv->base = devm_ioremap_resource(&pdev->dev, res);
 | |
| 	if (IS_ERR(priv->base))
 | |
| 		return PTR_ERR(priv->base);
 | |
| 
 | |
| 	platform_set_drvdata(pdev, priv);
 | |
| 	priv->thresh_idx = IDX_MIN;
 | |
| 	tango_thermal_init(priv);
 | |
| 
 | |
| 	tzdev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &ops);
 | |
| 	return PTR_ERR_OR_ZERO(tzdev);
 | |
| }
 | |
| 
 | |
| static int __maybe_unused tango_thermal_resume(struct device *dev)
 | |
| {
 | |
| 	tango_thermal_init(dev_get_drvdata(dev));
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume);
 | |
| 
 | |
| static const struct of_device_id tango_sensor_ids[] = {
 | |
| 	{
 | |
| 		.compatible = "sigma,smp8758-thermal",
 | |
| 	},
 | |
| 	{ /* sentinel */ }
 | |
| };
 | |
| MODULE_DEVICE_TABLE(of, tango_sensor_ids);
 | |
| 
 | |
| static struct platform_driver tango_thermal_driver = {
 | |
| 	.probe	= tango_thermal_probe,
 | |
| 	.driver	= {
 | |
| 		.name		= "tango-thermal",
 | |
| 		.of_match_table	= tango_sensor_ids,
 | |
| 		.pm		= &tango_thermal_pm,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| module_platform_driver(tango_thermal_driver);
 | |
| 
 | |
| MODULE_LICENSE("GPL");
 | |
| MODULE_AUTHOR("Sigma Designs");
 | |
| MODULE_DESCRIPTION("Tango temperature sensor");
 |