brintos

brintos / linux-shallow public Read only

0
0
Text · 13.3 KiB · ddc8341 Raw
589 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *  R-Car THS/TSC thermal sensor driver4 *5 * Copyright (C) 2012 Renesas Solutions Corp.6 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>7 */8#include <linux/delay.h>9#include <linux/err.h>10#include <linux/irq.h>11#include <linux/interrupt.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/platform_device.h>16#include <linux/pm_runtime.h>17#include <linux/reboot.h>18#include <linux/slab.h>19#include <linux/spinlock.h>20#include <linux/thermal.h>21 22#include "../thermal_hwmon.h"23 24#define IDLE_INTERVAL	500025 26#define COMMON_STR	0x0027#define COMMON_ENR	0x0428#define COMMON_INTMSK	0x0c29 30#define REG_POSNEG	0x2031#define REG_FILONOFF	0x2832#define REG_THSCR	0x2c33#define REG_THSSR	0x3034#define REG_INTCTRL	0x3435 36/* THSCR */37#define CPCTL	(1 << 12)38 39/* THSSR */40#define CTEMP	0x3f41 42struct rcar_thermal_common {43	void __iomem *base;44	struct device *dev;45	struct list_head head;46	spinlock_t lock;47};48 49struct 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;55	unsigned int ctemp_bands;56};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,64	.ctemp_bands = 1,65};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,73	.ctemp_bands = 1,74};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 283	 * interrupts to detect a temperature change, rise or fall.84	 */85	.nirqs = 2,86	.ctemp_bands = 2,87};88 89struct rcar_thermal_priv {90	void __iomem *base;91	struct rcar_thermal_common *common;92	struct thermal_zone_device *zone;93	const struct rcar_thermal_chip *chip;94	struct delayed_work work;95	struct mutex lock;96	struct list_head list;97	int id;98};99 100#define rcar_thermal_for_each_priv(pos, common)	\101	list_for_each_entry(pos, &common->head, list)102 103#define MCELSIUS(temp)			((temp) * 1000)104#define rcar_priv_to_dev(priv)		((priv)->common->dev)105#define rcar_has_irq_support(priv)	((priv)->common->base)106#define rcar_id_to_shift(priv)		((priv)->id * 8)107 108static const struct of_device_id rcar_thermal_dt_ids[] = {109	{110		.compatible = "renesas,rcar-thermal",111		.data = &rcar_thermal,112	},113	{114		.compatible = "renesas,rcar-gen2-thermal",115		 .data = &rcar_gen2_thermal,116	},117	{118		.compatible = "renesas,thermal-r8a774c0",119		.data = &rcar_gen3_thermal,120	},121	{122		.compatible = "renesas,thermal-r8a77970",123		.data = &rcar_gen3_thermal,124	},125	{126		.compatible = "renesas,thermal-r8a77990",127		.data = &rcar_gen3_thermal,128	},129	{130		.compatible = "renesas,thermal-r8a77995",131		.data = &rcar_gen3_thermal,132	},133	{},134};135MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);136 137/*138 *		basic functions139 */140#define rcar_thermal_common_read(c, r) \141	_rcar_thermal_common_read(c, COMMON_ ##r)142static u32 _rcar_thermal_common_read(struct rcar_thermal_common *common,143				     u32 reg)144{145	return ioread32(common->base + reg);146}147 148#define rcar_thermal_common_write(c, r, d) \149	_rcar_thermal_common_write(c, COMMON_ ##r, d)150static void _rcar_thermal_common_write(struct rcar_thermal_common *common,151				       u32 reg, u32 data)152{153	iowrite32(data, common->base + reg);154}155 156#define rcar_thermal_common_bset(c, r, m, d) \157	_rcar_thermal_common_bset(c, COMMON_ ##r, m, d)158static void _rcar_thermal_common_bset(struct rcar_thermal_common *common,159				      u32 reg, u32 mask, u32 data)160{161	u32 val;162 163	val = ioread32(common->base + reg);164	val &= ~mask;165	val |= (data & mask);166	iowrite32(val, common->base + reg);167}168 169#define rcar_thermal_read(p, r) _rcar_thermal_read(p, REG_ ##r)170static u32 _rcar_thermal_read(struct rcar_thermal_priv *priv, u32 reg)171{172	return ioread32(priv->base + reg);173}174 175#define rcar_thermal_write(p, r, d) _rcar_thermal_write(p, REG_ ##r, d)176static void _rcar_thermal_write(struct rcar_thermal_priv *priv,177				u32 reg, u32 data)178{179	iowrite32(data, priv->base + reg);180}181 182#define rcar_thermal_bset(p, r, m, d) _rcar_thermal_bset(p, REG_ ##r, m, d)183static void _rcar_thermal_bset(struct rcar_thermal_priv *priv, u32 reg,184			       u32 mask, u32 data)185{186	u32 val;187 188	val = ioread32(priv->base + reg);189	val &= ~mask;190	val |= (data & mask);191	iowrite32(val, priv->base + reg);192}193 194/*195 *		zone device functions196 */197static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)198{199	struct device *dev = rcar_priv_to_dev(priv);200	int old, new, ctemp = -EINVAL;201	unsigned int i;202 203	mutex_lock(&priv->lock);204 205	/*206	 * TSC decides a value of CPTAP automatically,207	 * and this is the conditions which validate interrupt.208	 */209	rcar_thermal_bset(priv, THSCR, CPCTL, CPCTL);210 211	old = ~0;212	for (i = 0; i < 128; i++) {213		/*214		 * we need to wait 300us after changing comparator offset215		 * to get stable temperature.216		 * see "Usage Notes" on datasheet217		 */218		usleep_range(300, 400);219 220		new = rcar_thermal_read(priv, THSSR) & CTEMP;221		if (new == old) {222			ctemp = new;223			break;224		}225		old = new;226	}227 228	if (ctemp < 0) {229		dev_err(dev, "thermal sensor was broken\n");230		goto err_out_unlock;231	}232 233	/*234	 * enable IRQ235	 */236	if (rcar_has_irq_support(priv)) {237		if (priv->chip->has_filonoff)238			rcar_thermal_write(priv, FILONOFF, 0);239 240		/* enable Rising/Falling edge interrupt */241		rcar_thermal_write(priv, POSNEG,  0x1);242		rcar_thermal_write(priv, INTCTRL, (((ctemp - 0) << 8) |243						   ((ctemp - 1) << 0)));244	}245 246err_out_unlock:247	mutex_unlock(&priv->lock);248 249	return ctemp;250}251 252static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv,253					 int *temp)254{255	int ctemp;256 257	ctemp = rcar_thermal_update_temp(priv);258	if (ctemp < 0)259		return ctemp;260 261	/* Guaranteed operating range is -45C to 125C. */262 263	if (priv->chip->ctemp_bands == 1)264		*temp = MCELSIUS((ctemp * 5) - 65);265	else if (ctemp < 24)266		*temp = MCELSIUS(((ctemp * 55) - 720) / 10);267	else268		*temp = MCELSIUS((ctemp * 5) - 60);269 270	return 0;271}272 273static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)274{275	struct rcar_thermal_priv *priv = thermal_zone_device_priv(zone);276 277	return rcar_thermal_get_current_temp(priv, temp);278}279 280static struct thermal_zone_device_ops rcar_thermal_zone_ops = {281	.get_temp	= rcar_thermal_get_temp,282};283 284static struct thermal_trip trips[] = {285	{ .type = THERMAL_TRIP_CRITICAL, .temperature = 90000 }286};287 288/*289 *		interrupt290 */291#define rcar_thermal_irq_enable(p)	_rcar_thermal_irq_ctrl(p, 1)292#define rcar_thermal_irq_disable(p)	_rcar_thermal_irq_ctrl(p, 0)293static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)294{295	struct rcar_thermal_common *common = priv->common;296	unsigned long flags;297	u32 mask = 0x3 << rcar_id_to_shift(priv); /* enable Rising/Falling */298 299	if (!rcar_has_irq_support(priv))300		return;301 302	spin_lock_irqsave(&common->lock, flags);303 304	rcar_thermal_common_bset(common, INTMSK, mask, enable ? 0 : mask);305 306	spin_unlock_irqrestore(&common->lock, flags);307}308 309static void rcar_thermal_work(struct work_struct *work)310{311	struct rcar_thermal_priv *priv;312	int ret;313 314	priv = container_of(work, struct rcar_thermal_priv, work.work);315 316	ret = rcar_thermal_update_temp(priv);317	if (ret < 0)318		return;319 320	rcar_thermal_irq_enable(priv);321 322	thermal_zone_device_update(priv->zone, THERMAL_EVENT_UNSPECIFIED);323}324 325static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status)326{327	struct device *dev = rcar_priv_to_dev(priv);328 329	status = (status >> rcar_id_to_shift(priv)) & 0x3;330 331	if (status) {332		dev_dbg(dev, "thermal%d %s%s\n",333			priv->id,334			(status & 0x2) ? "Rising " : "",335			(status & 0x1) ? "Falling" : "");336	}337 338	return status;339}340 341static irqreturn_t rcar_thermal_irq(int irq, void *data)342{343	struct rcar_thermal_common *common = data;344	struct rcar_thermal_priv *priv;345	u32 status, mask;346 347	spin_lock(&common->lock);348 349	mask	= rcar_thermal_common_read(common, INTMSK);350	status	= rcar_thermal_common_read(common, STR);351	rcar_thermal_common_write(common, STR, 0x000F0F0F & mask);352 353	spin_unlock(&common->lock);354 355	status = status & ~mask;356 357	/*358	 * check the status359	 */360	rcar_thermal_for_each_priv(priv, common) {361		if (rcar_thermal_had_changed(priv, status)) {362			rcar_thermal_irq_disable(priv);363			queue_delayed_work(system_freezable_wq, &priv->work,364					   msecs_to_jiffies(300));365		}366	}367 368	return IRQ_HANDLED;369}370 371/*372 *		platform functions373 */374static void rcar_thermal_remove(struct platform_device *pdev)375{376	struct rcar_thermal_common *common = platform_get_drvdata(pdev);377	struct device *dev = &pdev->dev;378	struct rcar_thermal_priv *priv;379 380	rcar_thermal_for_each_priv(priv, common) {381		rcar_thermal_irq_disable(priv);382		cancel_delayed_work_sync(&priv->work);383		if (priv->chip->use_of_thermal)384			thermal_remove_hwmon_sysfs(priv->zone);385		else386			thermal_zone_device_unregister(priv->zone);387	}388 389	pm_runtime_put(dev);390	pm_runtime_disable(dev);391}392 393static int rcar_thermal_probe(struct platform_device *pdev)394{395	struct rcar_thermal_common *common;396	struct rcar_thermal_priv *priv;397	struct device *dev = &pdev->dev;398	struct resource *res;399	const struct rcar_thermal_chip *chip = of_device_get_match_data(dev);400	int mres = 0;401	int i;402	int ret = -ENODEV;403	int idle = IDLE_INTERVAL;404	u32 enr_bits = 0;405 406	common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);407	if (!common)408		return -ENOMEM;409 410	platform_set_drvdata(pdev, common);411 412	INIT_LIST_HEAD(&common->head);413	spin_lock_init(&common->lock);414	common->dev = dev;415 416	pm_runtime_enable(dev);417	pm_runtime_get_sync(dev);418 419	for (i = 0; i < chip->nirqs; i++) {420		int irq;421 422		ret = platform_get_irq_optional(pdev, i);423		if (ret < 0 && ret != -ENXIO)424			goto error_unregister;425		if (ret > 0)426			irq = ret;427		else428			break;429 430		if (!common->base) {431			/*432			 * platform has IRQ support.433			 * Then, driver uses common registers434			 * rcar_has_irq_support() will be enabled435			 */436			res = platform_get_resource(pdev, IORESOURCE_MEM,437						    mres++);438			common->base = devm_ioremap_resource(dev, res);439			if (IS_ERR(common->base)) {440				ret = PTR_ERR(common->base);441				goto error_unregister;442			}443 444			idle = 0; /* polling delay is not needed */445		}446 447		ret = devm_request_irq(dev, irq, rcar_thermal_irq,448				       IRQF_SHARED, dev_name(dev), common);449		if (ret) {450			dev_err(dev, "irq request failed\n");451			goto error_unregister;452		}453 454		/* update ENR bits */455		if (chip->irq_per_ch)456			enr_bits |= 1 << i;457	}458 459	for (i = 0;; i++) {460		res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);461		if (!res)462			break;463 464		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);465		if (!priv) {466			ret = -ENOMEM;467			goto error_unregister;468		}469 470		priv->base = devm_ioremap_resource(dev, res);471		if (IS_ERR(priv->base)) {472			ret = PTR_ERR(priv->base);473			goto error_unregister;474		}475 476		priv->common = common;477		priv->id = i;478		priv->chip = chip;479		mutex_init(&priv->lock);480		INIT_LIST_HEAD(&priv->list);481		INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);482		ret = rcar_thermal_update_temp(priv);483		if (ret < 0)484			goto error_unregister;485 486		if (chip->use_of_thermal) {487			priv->zone = devm_thermal_of_zone_register(488						dev, i, priv,489						&rcar_thermal_zone_ops);490		} else {491			priv->zone = thermal_zone_device_register_with_trips(492				"rcar_thermal", trips, ARRAY_SIZE(trips), priv,493						&rcar_thermal_zone_ops, NULL, 0,494						idle);495 496			ret = thermal_zone_device_enable(priv->zone);497			if (ret) {498				thermal_zone_device_unregister(priv->zone);499				priv->zone = ERR_PTR(ret);500			}501		}502		if (IS_ERR(priv->zone)) {503			dev_err(dev, "can't register thermal zone\n");504			ret = PTR_ERR(priv->zone);505			priv->zone = NULL;506			goto error_unregister;507		}508 509		if (chip->use_of_thermal) {510			ret = thermal_add_hwmon_sysfs(priv->zone);511			if (ret)512				goto error_unregister;513		}514 515		rcar_thermal_irq_enable(priv);516 517		list_move_tail(&priv->list, &common->head);518 519		/* update ENR bits */520		if (!chip->irq_per_ch)521			enr_bits |= 3 << (i * 8);522	}523 524	if (common->base && enr_bits)525		rcar_thermal_common_write(common, ENR, enr_bits);526 527	dev_info(dev, "%d sensor probed\n", i);528 529	return 0;530 531error_unregister:532	rcar_thermal_remove(pdev);533 534	return ret;535}536 537#ifdef CONFIG_PM_SLEEP538static int rcar_thermal_suspend(struct device *dev)539{540	struct rcar_thermal_common *common = dev_get_drvdata(dev);541	struct rcar_thermal_priv *priv = list_first_entry(&common->head,542							  typeof(*priv), list);543 544	if (priv->chip->needs_suspend_resume) {545		rcar_thermal_common_write(common, ENR, 0);546		rcar_thermal_irq_disable(priv);547		rcar_thermal_bset(priv, THSCR, CPCTL, 0);548	}549 550	return 0;551}552 553static int rcar_thermal_resume(struct device *dev)554{555	struct rcar_thermal_common *common = dev_get_drvdata(dev);556	struct rcar_thermal_priv *priv = list_first_entry(&common->head,557							  typeof(*priv), list);558	int ret;559 560	if (priv->chip->needs_suspend_resume) {561		ret = rcar_thermal_update_temp(priv);562		if (ret < 0)563			return ret;564		rcar_thermal_irq_enable(priv);565		rcar_thermal_common_write(common, ENR, 0x03);566	}567 568	return 0;569}570#endif571 572static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,573			 rcar_thermal_resume);574 575static struct platform_driver rcar_thermal_driver = {576	.driver	= {577		.name	= "rcar_thermal",578		.pm = &rcar_thermal_pm_ops,579		.of_match_table = rcar_thermal_dt_ids,580	},581	.probe		= rcar_thermal_probe,582	.remove_new	= rcar_thermal_remove,583};584module_platform_driver(rcar_thermal_driver);585 586MODULE_LICENSE("GPL v2");587MODULE_DESCRIPTION("R-Car THS/TSC thermal sensor driver");588MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");589