Blame view

drivers/thermal/kirkwood_thermal.c 3.23 KB
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  /*
   * Kirkwood thermal sensor driver
   *
   * Copyright (C) 2012 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
   *
   * This software is licensed under the terms of the GNU General Public
   * License version 2, as published by the Free Software Foundation, and
   * may be copied, distributed, and modified under those terms.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   * GNU General Public License for more details.
   *
   */
  #include <linux/device.h>
  #include <linux/err.h>
  #include <linux/io.h>
  #include <linux/kernel.h>
  #include <linux/of.h>
  #include <linux/module.h>
  #include <linux/platform_device.h>
  #include <linux/thermal.h>
  
  #define KIRKWOOD_THERMAL_VALID_OFFSET	9
  #define KIRKWOOD_THERMAL_VALID_MASK	0x1
  #define KIRKWOOD_THERMAL_TEMP_OFFSET	10
  #define KIRKWOOD_THERMAL_TEMP_MASK	0x1FF
  
  /* Kirkwood Thermal Sensor Dev Structure */
  struct kirkwood_thermal_priv {
  	void __iomem *sensor;
  };
  
  static int kirkwood_get_temp(struct thermal_zone_device *thermal,
17e8351a7   Sascha Hauer   thermal: consiste...
36
  			  int *temp)
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
37
38
39
40
41
42
43
  {
  	unsigned long reg;
  	struct kirkwood_thermal_priv *priv = thermal->devdata;
  
  	reg = readl_relaxed(priv->sensor);
  
  	/* Valid check */
02519d339   Ezequiel Garcia   thermal: kirkwood...
44
45
  	if (!((reg >> KIRKWOOD_THERMAL_VALID_OFFSET) &
  	    KIRKWOOD_THERMAL_VALID_MASK)) {
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
46
47
48
49
50
51
52
  		dev_err(&thermal->device,
  			"Temperature sensor reading not valid
  ");
  		return -EIO;
  	}
  
  	/*
696b6075a   Ezequiel Garcia   thermal: kirkwood...
53
54
55
  	 * Calculate temperature. According to Marvell internal
  	 * documentation the formula for this is:
  	 * Celsius = (322-reg)/1.3625
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
56
57
58
  	 */
  	reg = (reg >> KIRKWOOD_THERMAL_TEMP_OFFSET) &
  		KIRKWOOD_THERMAL_TEMP_MASK;
696b6075a   Ezequiel Garcia   thermal: kirkwood...
59
  	*temp = ((3220000000UL - (10000000UL * reg)) / 13625);
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  
  	return 0;
  }
  
  static struct thermal_zone_device_ops ops = {
  	.get_temp = kirkwood_get_temp,
  };
  
  static const struct of_device_id kirkwood_thermal_id_table[] = {
  	{ .compatible = "marvell,kirkwood-thermal" },
  	{}
  };
  
  static int kirkwood_thermal_probe(struct platform_device *pdev)
  {
  	struct thermal_zone_device *thermal = NULL;
  	struct kirkwood_thermal_priv *priv;
  	struct resource *res;
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
78
79
80
  	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  	if (!priv)
  		return -ENOMEM;
c28f692c6   Wolfram Sang   drivers/thermal: ...
81
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
aa3b5d222   Sachin Kamat   Thermal: kirkwood...
82
83
84
  	priv->sensor = devm_ioremap_resource(&pdev->dev, res);
  	if (IS_ERR(priv->sensor))
  		return PTR_ERR(priv->sensor);
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  
  	thermal = thermal_zone_device_register("kirkwood_thermal", 0, 0,
  					       priv, &ops, NULL, 0, 0);
  	if (IS_ERR(thermal)) {
  		dev_err(&pdev->dev,
  			"Failed to register thermal zone device
  ");
  		return PTR_ERR(thermal);
  	}
  
  	platform_set_drvdata(pdev, thermal);
  
  	return 0;
  }
  
  static int kirkwood_thermal_exit(struct platform_device *pdev)
  {
  	struct thermal_zone_device *kirkwood_thermal =
  		platform_get_drvdata(pdev);
  
  	thermal_zone_device_unregister(kirkwood_thermal);
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
106
107
108
109
110
111
112
113
114
115
116
  
  	return 0;
  }
  
  MODULE_DEVICE_TABLE(of, kirkwood_thermal_id_table);
  
  static struct platform_driver kirkwood_thermal_driver = {
  	.probe = kirkwood_thermal_probe,
  	.remove = kirkwood_thermal_exit,
  	.driver = {
  		.name = "kirkwood_thermal",
90c3194e4   Sachin Kamat   Thermal: kirkwood...
117
  		.of_match_table = kirkwood_thermal_id_table,
7060aa366   Nobuhiro Iwamatsu   thermal: Add supp...
118
119
120
121
122
123
124
125
  	},
  };
  
  module_platform_driver(kirkwood_thermal_driver);
  
  MODULE_AUTHOR("Nobuhiro Iwamatsu <iwamatsu@nigauri.org>");
  MODULE_DESCRIPTION("kirkwood thermal driver");
  MODULE_LICENSE("GPL");