aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2013-01-31 04:03:33 -0500
committerZhang Rui <rui.zhang@intel.com>2013-02-06 01:13:58 -0500
commit3676d1dd3d3069ca70b8075c0e86482cbaa01c2f (patch)
tree425b072f4e6122da75182681005accb6e9243ee0 /drivers/thermal
parentb2bbc6a2ace78eaca2f6482b58b984519aa783ac (diff)
thermal: rcar: multi channel support
R-Car thermal sensor will be multi channel sensor in next generation. But "IRQ controlling method" and "register mapping" are different between old/new chip. This patch adds multi sensor support. Then, this driver assumes there is common register if platform has IRQ resource. The IRQ will be supported soon. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/rcar_thermal.c128
1 files changed, 94 insertions, 34 deletions
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index e19b267f76d6..1ba02770153a 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -38,16 +38,27 @@
38/* THSSR */ 38/* THSSR */
39#define CTEMP 0x3f 39#define CTEMP 0x3f
40 40
41struct rcar_thermal_common {
42 void __iomem *base;
43 struct device *dev;
44 struct list_head head;
45};
41 46
42struct rcar_thermal_priv { 47struct rcar_thermal_priv {
43 void __iomem *base; 48 void __iomem *base;
44 struct device *dev; 49 struct rcar_thermal_common *common;
50 struct thermal_zone_device *zone;
45 struct mutex lock; 51 struct mutex lock;
52 struct list_head list;
46}; 53};
47 54
55#define rcar_thermal_for_each_priv(pos, common) \
56 list_for_each_entry(pos, &common->head, list)
57
48#define MCELSIUS(temp) ((temp) * 1000) 58#define MCELSIUS(temp) ((temp) * 1000)
49#define rcar_zone_to_priv(zone) ((zone)->devdata) 59#define rcar_zone_to_priv(zone) ((zone)->devdata)
50#define rcar_priv_to_dev(priv) ((priv)->dev) 60#define rcar_priv_to_dev(priv) ((priv)->common->dev)
61#define rcar_has_irq_support(priv) ((priv)->common->base)
51 62
52/* 63/*
53 * basic functions 64 * basic functions
@@ -129,6 +140,7 @@ static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
129 int trip, enum thermal_trip_type *type) 140 int trip, enum thermal_trip_type *type)
130{ 141{
131 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); 142 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
143 struct device *dev = rcar_priv_to_dev(priv);
132 144
133 /* see rcar_thermal_get_temp() */ 145 /* see rcar_thermal_get_temp() */
134 switch (trip) { 146 switch (trip) {
@@ -136,7 +148,7 @@ static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
136 *type = THERMAL_TRIP_CRITICAL; 148 *type = THERMAL_TRIP_CRITICAL;
137 break; 149 break;
138 default: 150 default:
139 dev_err(priv->dev, "rcar driver trip error\n"); 151 dev_err(dev, "rcar driver trip error\n");
140 return -EINVAL; 152 return -EINVAL;
141 } 153 }
142 154
@@ -147,6 +159,7 @@ static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone,
147 int trip, unsigned long *temp) 159 int trip, unsigned long *temp)
148{ 160{
149 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); 161 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
162 struct device *dev = rcar_priv_to_dev(priv);
150 163
151 /* see rcar_thermal_get_temp() */ 164 /* see rcar_thermal_get_temp() */
152 switch (trip) { 165 switch (trip) {
@@ -154,7 +167,7 @@ static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone,
154 *temp = MCELSIUS(90); 167 *temp = MCELSIUS(90);
155 break; 168 break;
156 default: 169 default:
157 dev_err(priv->dev, "rcar driver trip error\n"); 170 dev_err(dev, "rcar driver trip error\n");
158 return -EINVAL; 171 return -EINVAL;
159 } 172 }
160 173
@@ -165,12 +178,12 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone,
165 int trip, enum thermal_trip_type type) 178 int trip, enum thermal_trip_type type)
166{ 179{
167 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); 180 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
181 struct device *dev = rcar_priv_to_dev(priv);
168 182
169 switch (type) { 183 switch (type) {
170 case THERMAL_TRIP_CRITICAL: 184 case THERMAL_TRIP_CRITICAL:
171 /* FIXME */ 185 /* FIXME */
172 dev_warn(priv->dev, 186 dev_warn(dev, "Thermal reached to critical temperature\n");
173 "Thermal reached to critical temperature\n");
174 machine_power_off(); 187 machine_power_off();
175 break; 188 break;
176 default: 189 default:
@@ -192,51 +205,98 @@ static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
192 */ 205 */
193static int rcar_thermal_probe(struct platform_device *pdev) 206static int rcar_thermal_probe(struct platform_device *pdev)
194{ 207{
195 struct thermal_zone_device *zone; 208 struct rcar_thermal_common *common;
196 struct rcar_thermal_priv *priv; 209 struct rcar_thermal_priv *priv;
197 struct resource *res; 210 struct device *dev = &pdev->dev;
198 211 struct resource *res, *irq;
199 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 212 int mres = 0;
200 if (!res) { 213 int i;
201 dev_err(&pdev->dev, "Could not get platform resource\n");
202 return -ENODEV;
203 }
204 214
205 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 215 common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
206 if (!priv) { 216 if (!common) {
207 dev_err(&pdev->dev, "Could not allocate priv\n"); 217 dev_err(dev, "Could not allocate common\n");
208 return -ENOMEM; 218 return -ENOMEM;
209 } 219 }
210 220
211 priv->dev = &pdev->dev; 221 INIT_LIST_HEAD(&common->head);
212 mutex_init(&priv->lock); 222 common->dev = dev;
213 priv->base = devm_ioremap_nocache(&pdev->dev, 223
214 res->start, resource_size(res)); 224 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
215 if (!priv->base) { 225 if (irq) {
216 dev_err(&pdev->dev, "Unable to ioremap thermal register\n"); 226 /*
217 return -ENOMEM; 227 * platform has IRQ support.
228 * Then, drier use common register
229 */
230 res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
231 if (!res) {
232 dev_err(dev, "Could not get platform resource\n");
233 return -ENODEV;
234 }
235
236 /*
237 * rcar_has_irq_support() will be enabled
238 */
239 common->base = devm_request_and_ioremap(dev, res);
240 if (!common->base) {
241 dev_err(dev, "Unable to ioremap thermal register\n");
242 return -ENOMEM;
243 }
218 } 244 }
219 245
220 zone = thermal_zone_device_register("rcar_thermal", 1, 0, priv, 246 for (i = 0;; i++) {
221 &rcar_thermal_zone_ops, NULL, 0, 247 res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
222 IDLE_INTERVAL); 248 if (!res)
223 if (IS_ERR(zone)) { 249 break;
224 dev_err(&pdev->dev, "thermal zone device is NULL\n"); 250
225 return PTR_ERR(zone); 251 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
252 if (!priv) {
253 dev_err(dev, "Could not allocate priv\n");
254 return -ENOMEM;
255 }
256
257 priv->base = devm_request_and_ioremap(dev, res);
258 if (!priv->base) {
259 dev_err(dev, "Unable to ioremap priv register\n");
260 return -ENOMEM;
261 }
262
263 priv->common = common;
264 mutex_init(&priv->lock);
265 INIT_LIST_HEAD(&priv->list);
266
267 priv->zone = thermal_zone_device_register("rcar_thermal",
268 1, 0, priv,
269 &rcar_thermal_zone_ops, NULL, 0,
270 IDLE_INTERVAL);
271 if (IS_ERR(priv->zone)) {
272 dev_err(dev, "can't register thermal zone\n");
273 goto error_unregister;
274 }
275
276 list_move_tail(&priv->list, &common->head);
226 } 277 }
227 278
228 platform_set_drvdata(pdev, zone); 279 platform_set_drvdata(pdev, common);
229 280
230 dev_info(&pdev->dev, "proved\n"); 281 dev_info(dev, "%d sensor proved\n", i);
231 282
232 return 0; 283 return 0;
284
285error_unregister:
286 rcar_thermal_for_each_priv(priv, common)
287 thermal_zone_device_unregister(priv->zone);
288
289 return -ENODEV;
233} 290}
234 291
235static int rcar_thermal_remove(struct platform_device *pdev) 292static int rcar_thermal_remove(struct platform_device *pdev)
236{ 293{
237 struct thermal_zone_device *zone = platform_get_drvdata(pdev); 294 struct rcar_thermal_common *common = platform_get_drvdata(pdev);
295 struct rcar_thermal_priv *priv;
296
297 rcar_thermal_for_each_priv(priv, common)
298 thermal_zone_device_unregister(priv->zone);
238 299
239 thermal_zone_device_unregister(zone);
240 platform_set_drvdata(pdev, NULL); 300 platform_set_drvdata(pdev, NULL);
241 301
242 return 0; 302 return 0;