blob: b49f04daaf477976807d92cf0ba7f563a1c271c0 [file] [log] [blame]
Kuninori Morimotoc9545792018-07-30 07:56:06 +00001// SPDX-License-Identifier: GPL-2.0
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +10002/*
3 * R-Car THS/TSC thermal sensor driver
4 *
5 * Copyright (C) 2012 Renesas Solutions Corp.
6 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +10007 */
8#include <linux/delay.h>
9#include <linux/err.h>
Kuninori Morimotoe0a51722013-01-31 09:04:48 +000010#include <linux/irq.h>
11#include <linux/interrupt.h>
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100012#include <linux/io.h>
13#include <linux/module.h>
Kuninori Morimoto8b477ea2016-01-28 02:45:08 +000014#include <linux/of_device.h>
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100015#include <linux/platform_device.h>
Kuninori Morimoto51d45d22013-03-26 06:08:52 +000016#include <linux/pm_runtime.h>
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -080017#include <linux/reboot.h>
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100018#include <linux/slab.h>
19#include <linux/spinlock.h>
20#include <linux/thermal.h>
21
Kuninori Morimoto64a411e2016-07-19 10:01:37 +000022#include "thermal_hwmon.h"
23
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -080024#define IDLE_INTERVAL 5000
25
Kuninori Morimotoe0a51722013-01-31 09:04:48 +000026#define COMMON_STR 0x00
27#define COMMON_ENR 0x04
28#define COMMON_INTMSK 0x0c
29
30#define REG_POSNEG 0x20
31#define REG_FILONOFF 0x28
Kuninori Morimotoe9137a52013-01-31 09:03:46 +000032#define REG_THSCR 0x2c
33#define REG_THSSR 0x30
Kuninori Morimotoe0a51722013-01-31 09:04:48 +000034#define REG_INTCTRL 0x34
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100035
36/* THSCR */
Kuninori Morimotof8f53e12013-01-31 09:03:11 +000037#define CPCTL (1 << 12)
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100038
39/* THSSR */
40#define CTEMP 0x3f
41
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +000042struct rcar_thermal_common {
43 void __iomem *base;
44 struct device *dev;
45 struct list_head head;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +000046 spinlock_t lock;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +000047};
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100048
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +090049struct rcar_thermal_chip {
50 unsigned int use_of_thermal : 1;
51 unsigned int has_filonoff : 1;
52 unsigned int irq_per_ch : 1;
53 unsigned int needs_suspend_resume : 1;
54 unsigned int nirqs;
Yoshihiro Kaneko20386f02019-05-08 13:08:45 +020055 unsigned int ctemp_bands;
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +090056};
57
58static const struct rcar_thermal_chip rcar_thermal = {
59 .use_of_thermal = 0,
60 .has_filonoff = 1,
61 .irq_per_ch = 0,
62 .needs_suspend_resume = 0,
63 .nirqs = 1,
Yoshihiro Kaneko20386f02019-05-08 13:08:45 +020064 .ctemp_bands = 1,
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +090065};
66
67static const struct rcar_thermal_chip rcar_gen2_thermal = {
68 .use_of_thermal = 1,
69 .has_filonoff = 1,
70 .irq_per_ch = 0,
71 .needs_suspend_resume = 0,
72 .nirqs = 1,
Yoshihiro Kaneko20386f02019-05-08 13:08:45 +020073 .ctemp_bands = 1,
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +090074};
75
76static const struct rcar_thermal_chip rcar_gen3_thermal = {
77 .use_of_thermal = 1,
78 .has_filonoff = 0,
79 .irq_per_ch = 1,
80 .needs_suspend_resume = 1,
81 /*
82 * The Gen3 chip has 3 interrupts, but this driver uses only 2
83 * interrupts to detect a temperature change, rise or fall.
84 */
85 .nirqs = 2,
Yoshihiro Kaneko20386f02019-05-08 13:08:45 +020086 .ctemp_bands = 2,
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +090087};
88
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100089struct rcar_thermal_priv {
90 void __iomem *base;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +000091 struct rcar_thermal_common *common;
92 struct thermal_zone_device *zone;
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +090093 const struct rcar_thermal_chip *chip;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +000094 struct delayed_work work;
Kuninori Morimotob2bbc6a2013-01-31 09:03:22 +000095 struct mutex lock;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +000096 struct list_head list;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +000097 int id;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +100098};
99
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000100#define rcar_thermal_for_each_priv(pos, common) \
101 list_for_each_entry(pos, &common->head, list)
102
Kuninori Morimotoc4997032012-11-26 02:32:06 +0000103#define MCELSIUS(temp) ((temp) * 1000)
Kuninori Morimoto9dde8f82013-01-31 09:02:51 +0000104#define rcar_zone_to_priv(zone) ((zone)->devdata)
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000105#define rcar_priv_to_dev(priv) ((priv)->common->dev)
106#define rcar_has_irq_support(priv) ((priv)->common->base)
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000107#define rcar_id_to_shift(priv) ((priv)->id * 8)
108
Kuninori Morimotoca1e4552015-12-15 01:17:07 +0000109static const struct of_device_id rcar_thermal_dt_ids[] = {
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900110 {
111 .compatible = "renesas,rcar-thermal",
112 .data = &rcar_thermal,
113 },
114 {
115 .compatible = "renesas,rcar-gen2-thermal",
116 .data = &rcar_gen2_thermal,
117 },
118 {
Fabrizio Castrob8d3d112018-12-13 20:23:10 +0000119 .compatible = "renesas,thermal-r8a774c0",
120 .data = &rcar_gen3_thermal,
121 },
122 {
Sergei Shtylyov92ca3662018-10-05 00:03:13 +0300123 .compatible = "renesas,thermal-r8a77970",
124 .data = &rcar_gen3_thermal,
125 },
126 {
Yoshihiro Kanekoe36e1302018-12-17 23:50:21 +0900127 .compatible = "renesas,thermal-r8a77990",
128 .data = &rcar_gen3_thermal,
129 },
130 {
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900131 .compatible = "renesas,thermal-r8a77995",
132 .data = &rcar_gen3_thermal,
133 },
Kuninori Morimotoca1e4552015-12-15 01:17:07 +0000134 {},
135};
136MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
137
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000138/*
139 * basic functions
140 */
Kuninori Morimotoe9137a52013-01-31 09:03:46 +0000141#define rcar_thermal_common_read(c, r) \
142 _rcar_thermal_common_read(c, COMMON_ ##r)
143static u32 _rcar_thermal_common_read(struct rcar_thermal_common *common,
144 u32 reg)
145{
146 return ioread32(common->base + reg);
147}
148
149#define rcar_thermal_common_write(c, r, d) \
150 _rcar_thermal_common_write(c, COMMON_ ##r, d)
151static void _rcar_thermal_common_write(struct rcar_thermal_common *common,
152 u32 reg, u32 data)
153{
154 iowrite32(data, common->base + reg);
155}
156
157#define rcar_thermal_common_bset(c, r, m, d) \
158 _rcar_thermal_common_bset(c, COMMON_ ##r, m, d)
159static void _rcar_thermal_common_bset(struct rcar_thermal_common *common,
160 u32 reg, u32 mask, u32 data)
161{
162 u32 val;
163
164 val = ioread32(common->base + reg);
165 val &= ~mask;
166 val |= (data & mask);
167 iowrite32(val, common->base + reg);
168}
Kuninori Morimotoe9137a52013-01-31 09:03:46 +0000169
170#define rcar_thermal_read(p, r) _rcar_thermal_read(p, REG_ ##r)
171static u32 _rcar_thermal_read(struct rcar_thermal_priv *priv, u32 reg)
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000172{
Kuninori Morimotob2bbc6a2013-01-31 09:03:22 +0000173 return ioread32(priv->base + reg);
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000174}
175
Kuninori Morimotoe9137a52013-01-31 09:03:46 +0000176#define rcar_thermal_write(p, r, d) _rcar_thermal_write(p, REG_ ##r, d)
177static void _rcar_thermal_write(struct rcar_thermal_priv *priv,
178 u32 reg, u32 data)
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000179{
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000180 iowrite32(data, priv->base + reg);
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000181}
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000182
Kuninori Morimotoe9137a52013-01-31 09:03:46 +0000183#define rcar_thermal_bset(p, r, m, d) _rcar_thermal_bset(p, REG_ ##r, m, d)
184static void _rcar_thermal_bset(struct rcar_thermal_priv *priv, u32 reg,
185 u32 mask, u32 data)
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000186{
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000187 u32 val;
188
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000189 val = ioread32(priv->base + reg);
190 val &= ~mask;
191 val |= (data & mask);
192 iowrite32(val, priv->base + reg);
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000193}
194
195/*
196 * zone device functions
197 */
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000198static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000199{
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000200 struct device *dev = rcar_priv_to_dev(priv);
Niklas Söderlundb03628b2020-05-14 17:25:05 +0200201 int old, new, ctemp = -EINVAL;
202 unsigned int i;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000203
Kuninori Morimotob2bbc6a2013-01-31 09:03:22 +0000204 mutex_lock(&priv->lock);
205
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000206 /*
207 * TSC decides a value of CPTAP automatically,
208 * and this is the conditions which validate interrupt.
209 */
210 rcar_thermal_bset(priv, THSCR, CPCTL, CPCTL);
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000211
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000212 old = ~0;
213 for (i = 0; i < 128; i++) {
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000214 /*
215 * we need to wait 300us after changing comparator offset
216 * to get stable temperature.
217 * see "Usage Notes" on datasheet
218 */
Geert Uytterhoeven263c8c42020-01-15 13:54:17 +0100219 usleep_range(300, 400);
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000220
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000221 new = rcar_thermal_read(priv, THSSR) & CTEMP;
222 if (new == old) {
223 ctemp = new;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000224 break;
225 }
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000226 old = new;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000227 }
228
Niklas Söderlundb03628b2020-05-14 17:25:05 +0200229 if (ctemp < 0) {
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000230 dev_err(dev, "thermal sensor was broken\n");
Wei Yongjunf0e68fc2013-02-22 13:22:39 +0000231 goto err_out_unlock;
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000232 }
233
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000234 /*
235 * enable IRQ
236 */
237 if (rcar_has_irq_support(priv)) {
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900238 if (priv->chip->has_filonoff)
239 rcar_thermal_write(priv, FILONOFF, 0);
Kuninori Morimotof8f53e12013-01-31 09:03:11 +0000240
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000241 /* enable Rising/Falling edge interrupt */
242 rcar_thermal_write(priv, POSNEG, 0x1);
243 rcar_thermal_write(priv, INTCTRL, (((ctemp - 0) << 8) |
244 ((ctemp - 1) << 0)));
245 }
246
Wei Yongjunf0e68fc2013-02-22 13:22:39 +0000247err_out_unlock:
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000248 mutex_unlock(&priv->lock);
Niklas Söderlund57ed7372020-03-10 18:00:28 +0100249
Niklas Söderlundb03628b2020-05-14 17:25:05 +0200250 return ctemp;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000251}
252
Kuninori Morimoto8b477ea2016-01-28 02:45:08 +0000253static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv,
254 int *temp)
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000255{
Niklas Söderlund0fa04202020-03-10 18:00:29 +0100256 int ctemp;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000257
Niklas Söderlund57ed7372020-03-10 18:00:28 +0100258 ctemp = rcar_thermal_update_temp(priv);
259 if (ctemp < 0)
260 return ctemp;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000261
Niklas Söderlunddff6d4f2020-01-17 17:05:53 +0100262 /* Guaranteed operating range is -45C to 125C. */
Kuninori Morimoto5440c402015-12-15 01:18:13 +0000263
Niklas Söderlund0fa04202020-03-10 18:00:29 +0100264 if (priv->chip->ctemp_bands == 1)
265 *temp = MCELSIUS((ctemp * 5) - 65);
266 else if (ctemp < 24)
267 *temp = MCELSIUS(((ctemp * 55) - 720) / 10);
268 else
269 *temp = MCELSIUS((ctemp * 5) - 60);
Kuninori Morimoto5440c402015-12-15 01:18:13 +0000270
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000271 return 0;
272}
273
Kuninori Morimoto8b477ea2016-01-28 02:45:08 +0000274static int rcar_thermal_of_get_temp(void *data, int *temp)
275{
276 struct rcar_thermal_priv *priv = data;
277
278 return rcar_thermal_get_current_temp(priv, temp);
279}
280
281static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
282{
283 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
284
285 return rcar_thermal_get_current_temp(priv, temp);
286}
287
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -0800288static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
289 int trip, enum thermal_trip_type *type)
290{
291 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000292 struct device *dev = rcar_priv_to_dev(priv);
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -0800293
294 /* see rcar_thermal_get_temp() */
295 switch (trip) {
296 case 0: /* +90 <= temp */
297 *type = THERMAL_TRIP_CRITICAL;
298 break;
299 default:
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000300 dev_err(dev, "rcar driver trip error\n");
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -0800301 return -EINVAL;
302 }
303
304 return 0;
305}
306
307static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone,
Sascha Hauer17e83512015-07-24 08:12:54 +0200308 int trip, int *temp)
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -0800309{
310 struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000311 struct device *dev = rcar_priv_to_dev(priv);
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -0800312
313 /* see rcar_thermal_get_temp() */
314 switch (trip) {
315 case 0: /* +90 <= temp */
316 *temp = MCELSIUS(90);
317 break;
318 default:
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000319 dev_err(dev, "rcar driver trip error\n");
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -0800320 return -EINVAL;
321 }
322
323 return 0;
324}
325
Kuninori Morimoto8b477ea2016-01-28 02:45:08 +0000326static const struct thermal_zone_of_device_ops rcar_thermal_zone_of_ops = {
327 .get_temp = rcar_thermal_of_get_temp,
328};
329
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000330static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
kuninori.morimoto.gx@renesas.comd2a73e22012-12-02 18:48:41 -0800331 .get_temp = rcar_thermal_get_temp,
332 .get_trip_type = rcar_thermal_get_trip_type,
333 .get_trip_temp = rcar_thermal_get_trip_temp,
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000334};
335
336/*
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000337 * interrupt
338 */
339#define rcar_thermal_irq_enable(p) _rcar_thermal_irq_ctrl(p, 1)
340#define rcar_thermal_irq_disable(p) _rcar_thermal_irq_ctrl(p, 0)
341static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)
342{
343 struct rcar_thermal_common *common = priv->common;
344 unsigned long flags;
345 u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */
346
Kuninori Morimotoffbcdf82015-12-15 01:17:56 +0000347 if (!rcar_has_irq_support(priv))
348 return;
349
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000350 spin_lock_irqsave(&common->lock, flags);
351
352 rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask);
353
354 spin_unlock_irqrestore(&common->lock, flags);
355}
356
357static void rcar_thermal_work(struct work_struct *work)
358{
359 struct rcar_thermal_priv *priv;
Kuninori Morimotoa1ade562015-12-15 01:17:40 +0000360 int ret;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000361
362 priv = container_of(work, struct rcar_thermal_priv, work.work);
363
Kuninori Morimotoa1ade562015-12-15 01:17:40 +0000364 ret = rcar_thermal_update_temp(priv);
365 if (ret < 0)
366 return;
367
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000368 rcar_thermal_irq_enable(priv);
Patrick Titiano94771652014-02-28 14:10:04 +0100369
Niklas Söderlund7617e772020-03-10 18:00:27 +0100370 thermal_zone_device_update(priv->zone, THERMAL_EVENT_UNSPECIFIED);
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000371}
372
373static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status)
374{
375 struct device *dev = rcar_priv_to_dev(priv);
376
377 status = (status >> rcar_id_to_shift(priv)) & 0x3;
378
Patrick Titiano206c0cb2014-02-28 14:10:03 +0100379 if (status) {
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000380 dev_dbg(dev, "thermal%d %s%s\n",
381 priv->id,
382 (status & 0x2) ? "Rising " : "",
383 (status & 0x1) ? "Falling" : "");
384 }
385
386 return status;
387}
388
389static irqreturn_t rcar_thermal_irq(int irq, void *data)
390{
391 struct rcar_thermal_common *common = data;
392 struct rcar_thermal_priv *priv;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000393 u32 status, mask;
394
Tian Tao4eb7d0c2020-10-27 09:06:30 +0800395 spin_lock(&common->lock);
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000396
397 mask = rcar_thermal_common_read(common, INTMSK);
398 status = rcar_thermal_common_read(common, STR);
399 rcar_thermal_common_write(common, STR, 0x000F0F0F & mask);
400
Tian Tao4eb7d0c2020-10-27 09:06:30 +0800401 spin_unlock(&common->lock);
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000402
403 status = status & ~mask;
404
405 /*
406 * check the status
407 */
408 rcar_thermal_for_each_priv(priv, common) {
409 if (rcar_thermal_had_changed(priv, status)) {
410 rcar_thermal_irq_disable(priv);
Geert Uytterhoeven3a313862018-10-12 09:20:15 +0200411 queue_delayed_work(system_freezable_wq, &priv->work,
412 msecs_to_jiffies(300));
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000413 }
414 }
415
416 return IRQ_HANDLED;
417}
418
419/*
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000420 * platform functions
421 */
Kuninori Morimoto84f0e492015-11-10 02:12:06 +0000422static int rcar_thermal_remove(struct platform_device *pdev)
423{
424 struct rcar_thermal_common *common = platform_get_drvdata(pdev);
425 struct device *dev = &pdev->dev;
426 struct rcar_thermal_priv *priv;
427
428 rcar_thermal_for_each_priv(priv, common) {
Kuninori Morimotoffbcdf82015-12-15 01:17:56 +0000429 rcar_thermal_irq_disable(priv);
Geert Uytterhoeven697ee782018-10-12 09:20:16 +0200430 cancel_delayed_work_sync(&priv->work);
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900431 if (priv->chip->use_of_thermal)
Kuninori Morimoto64a411e2016-07-19 10:01:37 +0000432 thermal_remove_hwmon_sysfs(priv->zone);
Bui Duc Phucd4b23c5c2016-08-22 03:19:49 +0000433 else
434 thermal_zone_device_unregister(priv->zone);
Kuninori Morimoto84f0e492015-11-10 02:12:06 +0000435 }
436
437 pm_runtime_put(dev);
438 pm_runtime_disable(dev);
439
440 return 0;
441}
442
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000443static int rcar_thermal_probe(struct platform_device *pdev)
444{
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000445 struct rcar_thermal_common *common;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000446 struct rcar_thermal_priv *priv;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000447 struct device *dev = &pdev->dev;
448 struct resource *res, *irq;
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900449 const struct rcar_thermal_chip *chip = of_device_get_match_data(dev);
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000450 int mres = 0;
451 int i;
Devendra Nagafb84d992013-03-04 16:52:47 +0000452 int ret = -ENODEV;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000453 int idle = IDLE_INTERVAL;
Yoshihiro Shimoda11313742015-01-07 10:13:10 +0900454 u32 enr_bits = 0;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000455
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000456 common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
Jingoo Hanb0a60d82014-05-07 15:03:25 +0900457 if (!common)
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000458 return -ENOMEM;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000459
Kuninori Morimoto84f0e492015-11-10 02:12:06 +0000460 platform_set_drvdata(pdev, common);
461
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000462 INIT_LIST_HEAD(&common->head);
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000463 spin_lock_init(&common->lock);
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000464 common->dev = dev;
465
Kuninori Morimoto51d45d22013-03-26 06:08:52 +0000466 pm_runtime_enable(dev);
467 pm_runtime_get_sync(dev);
468
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900469 for (i = 0; i < chip->nirqs; i++) {
Sergei Shtylyovdf016bb2018-10-03 23:47:34 +0300470 irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900471 if (!irq)
472 continue;
473 if (!common->base) {
474 /*
475 * platform has IRQ support.
476 * Then, driver uses common registers
477 * rcar_has_irq_support() will be enabled
478 */
479 res = platform_get_resource(pdev, IORESOURCE_MEM,
480 mres++);
481 common->base = devm_ioremap_resource(dev, res);
Niklas Söderlund39056e82020-03-10 12:47:09 +0100482 if (IS_ERR(common->base)) {
483 ret = PTR_ERR(common->base);
484 goto error_unregister;
485 }
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000486
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900487 idle = 0; /* polling delay is not needed */
488 }
489
490 ret = devm_request_irq(dev, irq->start, rcar_thermal_irq,
491 IRQF_SHARED, dev_name(dev), common);
492 if (ret) {
493 dev_err(dev, "irq request failed\n ");
494 goto error_unregister;
495 }
496
497 /* update ENR bits */
498 if (chip->irq_per_ch)
499 enr_bits |= 1 << i;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000500 }
501
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000502 for (i = 0;; i++) {
503 res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
504 if (!res)
505 break;
506
507 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
508 if (!priv) {
Kuninori Morimoto1dc20822013-03-26 06:08:10 +0000509 ret = -ENOMEM;
510 goto error_unregister;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000511 }
512
Sachin Kamat50955262013-03-04 06:45:33 +0000513 priv->base = devm_ioremap_resource(dev, res);
Kuninori Morimoto1dc20822013-03-26 06:08:10 +0000514 if (IS_ERR(priv->base)) {
515 ret = PTR_ERR(priv->base);
516 goto error_unregister;
517 }
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000518
519 priv->common = common;
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000520 priv->id = i;
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900521 priv->chip = chip;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000522 mutex_init(&priv->lock);
523 INIT_LIST_HEAD(&priv->list);
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000524 INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
Kuninori Morimotoa1ade562015-12-15 01:17:40 +0000525 ret = rcar_thermal_update_temp(priv);
526 if (ret < 0)
527 goto error_unregister;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000528
Geert Uytterhoeven392573b2020-08-19 11:27:16 +0200529 if (chip->use_of_thermal) {
Eduardo Valentin5e3258682016-03-09 13:09:43 -0800530 priv->zone = devm_thermal_zone_of_sensor_register(
Kuninori Morimoto8b477ea2016-01-28 02:45:08 +0000531 dev, i, priv,
532 &rcar_thermal_zone_of_ops);
Geert Uytterhoeven392573b2020-08-19 11:27:16 +0200533 } else {
Kuninori Morimoto8b477ea2016-01-28 02:45:08 +0000534 priv->zone = thermal_zone_device_register(
535 "rcar_thermal",
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000536 1, 0, priv,
537 &rcar_thermal_zone_ops, NULL, 0,
Kuninori Morimotoe0a51722013-01-31 09:04:48 +0000538 idle);
Andrzej Pietrasiewiczbbcf90c2020-06-29 14:29:22 +0200539
540 ret = thermal_zone_device_enable(priv->zone);
541 if (ret) {
542 thermal_zone_device_unregister(priv->zone);
543 priv->zone = ERR_PTR(ret);
544 }
545 }
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000546 if (IS_ERR(priv->zone)) {
547 dev_err(dev, "can't register thermal zone\n");
Devendra Nagafb84d992013-03-04 16:52:47 +0000548 ret = PTR_ERR(priv->zone);
Dirk Behme87260d32016-04-21 12:24:55 +0200549 priv->zone = NULL;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000550 goto error_unregister;
551 }
552
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900553 if (chip->use_of_thermal) {
Kuninori Morimoto64a411e2016-07-19 10:01:37 +0000554 /*
555 * thermal_zone doesn't enable hwmon as default,
556 * but, enable it here to keep compatible
557 */
558 priv->zone->tzp->no_hwmon = false;
559 ret = thermal_add_hwmon_sysfs(priv->zone);
560 if (ret)
561 goto error_unregister;
562 }
563
Kuninori Morimotoffbcdf82015-12-15 01:17:56 +0000564 rcar_thermal_irq_enable(priv);
Kuninori Morimoto1dc20822013-03-26 06:08:10 +0000565
566 list_move_tail(&priv->list, &common->head);
Yoshihiro Shimoda11313742015-01-07 10:13:10 +0900567
568 /* update ENR bits */
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900569 if (!chip->irq_per_ch)
570 enr_bits |= 3 << (i * 8);
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000571 }
572
Simon Horman542cdf42018-07-24 13:14:13 +0200573 if (common->base && enr_bits)
Yoshihiro Shimoda11313742015-01-07 10:13:10 +0900574 rcar_thermal_common_write(common, ENR, enr_bits);
575
Laurent Pinchart3db46c92013-05-14 23:00:32 +0000576 dev_info(dev, "%d sensor probed\n", i);
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000577
578 return 0;
Kuninori Morimoto3676d1d2013-01-31 09:03:33 +0000579
580error_unregister:
Kuninori Morimoto84f0e492015-11-10 02:12:06 +0000581 rcar_thermal_remove(pdev);
Kuninori Morimoto51d45d22013-03-26 06:08:52 +0000582
Devendra Nagafb84d992013-03-04 16:52:47 +0000583 return ret;
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000584}
585
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900586#ifdef CONFIG_PM_SLEEP
587static int rcar_thermal_suspend(struct device *dev)
588{
589 struct rcar_thermal_common *common = dev_get_drvdata(dev);
590 struct rcar_thermal_priv *priv = list_first_entry(&common->head,
591 typeof(*priv), list);
592
593 if (priv->chip->needs_suspend_resume) {
594 rcar_thermal_common_write(common, ENR, 0);
595 rcar_thermal_irq_disable(priv);
596 rcar_thermal_bset(priv, THSCR, CPCTL, 0);
597 }
598
599 return 0;
600}
601
602static int rcar_thermal_resume(struct device *dev)
603{
604 struct rcar_thermal_common *common = dev_get_drvdata(dev);
605 struct rcar_thermal_priv *priv = list_first_entry(&common->head,
606 typeof(*priv), list);
607 int ret;
608
609 if (priv->chip->needs_suspend_resume) {
610 ret = rcar_thermal_update_temp(priv);
611 if (ret < 0)
612 return ret;
613 rcar_thermal_irq_enable(priv);
614 rcar_thermal_common_write(common, ENR, 0x03);
615 }
616
617 return 0;
618}
619#endif
620
621static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
622 rcar_thermal_resume);
623
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000624static struct platform_driver rcar_thermal_driver = {
625 .driver = {
626 .name = "rcar_thermal",
Yoshihiro Kaneko1969d9d2018-05-20 18:26:17 +0900627 .pm = &rcar_thermal_pm_ops,
Kuninori Morimoto76cc1882013-01-31 09:05:26 +0000628 .of_match_table = rcar_thermal_dt_ids,
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000629 },
630 .probe = rcar_thermal_probe,
631 .remove = rcar_thermal_remove,
632};
633module_platform_driver(rcar_thermal_driver);
634
Kuninori Morimotoc9545792018-07-30 07:56:06 +0000635MODULE_LICENSE("GPL v2");
Kuninori Morimoto1e426ff2012-07-21 10:53:48 +1000636MODULE_DESCRIPTION("R-Car THS/TSC thermal sensor driver");
637MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");