PageRenderTime 47ms CodeModel.GetById 16ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/misc/omap_temp_sensor.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 754 lines | 572 code | 113 blank | 69 comment | 55 complexity | 927280a74bfd363b6c3ad1dad144d60c MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * OMAP4 Temperature sensor driver file
  3 *
  4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
  5 * Author: J Keerthy <j-keerthy@ti.com>
  6 * Author: Moiz Sonasath <m-sonasath@ti.com>
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * version 2 as published by the Free Software Foundation.
 11 *
 12 * This program is distributed in the hope that it will be useful, but
 13 * WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15 * General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 20 * 02110-1301 USA
 21 *
 22 */
 23
 24#include <linux/kernel.h>
 25#include <linux/module.h>
 26#include <linux/clk.h>
 27#include <linux/delay.h>
 28#include <linux/device.h>
 29#include <linux/err.h>
 30#include <linux/gpio.h>
 31#include <linux/init.h>
 32#include <linux/interrupt.h>
 33#include <linux/io.h>
 34#include <linux/mutex.h>
 35#include <linux/platform_device.h>
 36#include <linux/pm_runtime.h>
 37#include <linux/reboot.h>
 38#include <linux/slab.h>
 39#include <linux/sysfs.h>
 40#include <linux/types.h>
 41
 42#include <plat/common.h>
 43#include <plat/omap-pm.h>
 44#include <plat/omap_device.h>
 45#include <plat/temperature_sensor.h>
 46#include <plat/omap-pm.h>
 47
 48/* TO DO: This needs to be fixed */
 49#include "../../../../arch/arm/mach-omap2/control.h"
 50/* #include <plat/control.h> */
 51
 52#include <mach/ctrl_module_core_44xx.h>
 53
 54extern void omap_thermal_throttle(void);
 55extern void omap_thermal_unthrottle(void);
 56
 57static void throttle_delayed_work_fn(struct work_struct *work);
 58static int throttle_state = 1;
 59
 60#define THROTTLE_DELAY_MS	1000
 61
 62#define TSHUT_THRESHOLD_TSHUT_HOT	110000	/* 110 deg C */
 63#define TSHUT_THRESHOLD_TSHUT_COLD	100000	/* 100 deg C */
 64#define BGAP_THRESHOLD_T_HOT		72000	/* 72 deg C */
 65#define BGAP_THRESHOLD_T_COLD		68000	/* 68 deg C */
 66#define OMAP_ADC_START_VALUE	530
 67#define OMAP_ADC_END_VALUE	923
 68
 69/*
 70 * omap_temp_sensor structure
 71 * @pdev - Platform device pointer
 72 * @dev - device pointer
 73 * @clock - Clock pointer
 74 * @sensor_mutex - Mutex for sysfs, irq and PM
 75 * @irq - MPU Irq number for thermal alertemp_sensor
 76 * @tshut_irq -  Thermal shutdown IRQ
 77 * @phy_base - Physical base of the temp I/O
 78 * @is_efuse_valid - Flag to determine if eFuse is valid or not
 79 * @clk_on - Manages the current clock state
 80 * @clk_rate - Holds current clock rate
 81 */
 82struct omap_temp_sensor {
 83	struct platform_device *pdev;
 84	struct device *dev;
 85	struct clk *clock;
 86	struct spinlock lock;
 87	unsigned int irq;
 88	unsigned int tshut_irq;
 89	unsigned long phy_base;
 90	int is_efuse_valid;
 91	u8 clk_on;
 92	unsigned long clk_rate;
 93	u32 current_temp;
 94	struct delayed_work throttle_work;
 95};
 96
 97#ifdef CONFIG_PM
 98struct omap_temp_sensor_regs {
 99	u32 temp_sensor_ctrl;
100	u32 bg_ctrl;
101	u32 bg_counter;
102	u32 bg_threshold;
103	u32 temp_sensor_tshut_threshold;
104};
105
106static struct omap_temp_sensor_regs temp_sensor_context;
107static struct omap_temp_sensor *temp_sensor_pm;
108#endif
109
110/*
111 * Temperature values in milli degrees celsius ADC code values from 530 to 923
112 */
113static int adc_to_temp[] = {
114	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
115	-37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
116	-34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
117	-30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
118	-27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
119	-24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
120	-20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
121	-17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
122	-13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
123	-10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
124	-6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
125	-2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
126	2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
127	6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
128	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
129	15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
130	19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
131	23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
132	26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
133	30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
134	34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
135	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
136	42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
137	45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
138	49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
139	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
140	57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
141	60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
142	64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
143	68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
144	72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
145	75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
146	79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
147	83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
148	86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
149	90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
150	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
151	98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
152	101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
153	104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
154	108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
155	111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
156	114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
157	117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
158	121000, 121400, 121800, 122200, 122600, 123000
159};
160
161static unsigned long omap_temp_sensor_readl(struct omap_temp_sensor
162					    *temp_sensor, u32 reg)
163{
164	return omap_ctrl_readl(temp_sensor->phy_base + reg);
165}
166
167static void omap_temp_sensor_writel(struct omap_temp_sensor *temp_sensor,
168				    u32 val, u32 reg)
169{
170	omap_ctrl_writel(val, (temp_sensor->phy_base + reg));
171}
172
173static int adc_to_temp_conversion(int adc_val)
174{
175	if (adc_val < OMAP_ADC_START_VALUE || adc_val > OMAP_ADC_END_VALUE) {
176		pr_err("%s:Temp read is invalid %i\n", __func__, adc_val);
177		return -EINVAL;
178	}
179
180	return adc_to_temp[adc_val - OMAP_ADC_START_VALUE];
181}
182
183static int temp_to_adc_conversion(long temp)
184{
185	int i;
186
187	for (i = 0; i <= OMAP_ADC_END_VALUE - OMAP_ADC_START_VALUE; i++)
188		if (temp < adc_to_temp[i])
189			return OMAP_ADC_START_VALUE + i - 1;
190	return -EINVAL;
191}
192
193static int omap_read_current_temp(struct omap_temp_sensor *temp_sensor)
194{
195	int adc;
196
197	adc = omap_temp_sensor_readl(temp_sensor, TEMP_SENSOR_CTRL_OFFSET);
198	adc &= (OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK);
199
200	if (!temp_sensor->is_efuse_valid)
201		pr_err_once("%s: Invalid EFUSE, Non-trimmed BGAP,"
202			    "Temp not accurate\n", __func__ );
203
204	if (adc < OMAP_ADC_START_VALUE || adc > OMAP_ADC_END_VALUE) {
205		pr_err("%s:Invalid adc code reported by the sensor %d",
206			__func__, adc);
207		return -EINVAL;
208	}
209
210	return adc_to_temp_conversion(adc);
211}
212
213static void omap_configure_temp_sensor_thresholds(struct omap_temp_sensor
214						  *temp_sensor)
215{
216	u32 temp = 0, t_hot, t_cold, tshut_hot, tshut_cold;
217
218	t_hot = temp_to_adc_conversion(BGAP_THRESHOLD_T_HOT);
219	t_cold = temp_to_adc_conversion(BGAP_THRESHOLD_T_COLD);
220
221	if ((t_hot == -EINVAL) || (t_cold == -EINVAL)) {
222		pr_err("%s:Temp thresholds out of bounds\n", __func__);
223		return;
224	}
225	temp |= ((t_hot << OMAP4_T_HOT_SHIFT) | (t_cold << OMAP4_T_COLD_SHIFT));
226	omap_temp_sensor_writel(temp_sensor, temp, BGAP_THRESHOLD_OFFSET);
227
228	tshut_hot = temp_to_adc_conversion(TSHUT_THRESHOLD_TSHUT_HOT);
229	tshut_cold = temp_to_adc_conversion(TSHUT_THRESHOLD_TSHUT_COLD);
230	if ((tshut_hot == -EINVAL) || (tshut_cold == -EINVAL)) {
231		pr_err("%s:Temp shutdown thresholds out of bounds\n", __func__);
232		return;
233	}
234	temp |= ((tshut_hot << OMAP4_TSHUT_HOT_SHIFT)
235			| (tshut_cold << OMAP4_TSHUT_COLD_SHIFT));
236	omap_temp_sensor_writel(temp_sensor, temp, BGAP_TSHUT_OFFSET);
237}
238
239static void omap_configure_temp_sensor_counter(struct omap_temp_sensor
240					       *temp_sensor, u32 counter)
241{
242	u32 val;
243
244	val = omap_temp_sensor_readl(temp_sensor, BGAP_COUNTER_OFFSET);
245	val = val & ~(OMAP4_COUNTER_MASK);
246	val = val | (counter << OMAP4_COUNTER_SHIFT);
247	omap_temp_sensor_writel(temp_sensor, val, BGAP_COUNTER_OFFSET);
248}
249
250static void omap_enable_continuous_mode(struct omap_temp_sensor *temp_sensor)
251{
252	u32 val;
253
254	val = omap_temp_sensor_readl(temp_sensor, BGAP_CTRL_OFFSET);
255
256	val = val | (1 << OMAP4_SINGLE_MODE_SHIFT);
257
258	omap_temp_sensor_writel(temp_sensor, val, BGAP_CTRL_OFFSET);
259}
260
261/*
262 * sysfs hook functions
263 */
264static ssize_t omap_temp_show_current(struct device *dev,
265				struct device_attribute *devattr,
266				char *buf)
267{
268	struct platform_device *pdev = to_platform_device(dev);
269	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
270
271	return sprintf(buf, "%d\n", omap_read_current_temp(temp_sensor));
272}
273
274static ssize_t omap_throttle_store(struct device *dev,
275	struct device_attribute *devattr, const char *buf, size_t count)
276{
277	if (count && buf[0] == '1') {
278                throttle_state = 1;
279//		omap_thermal_throttle();
280	}
281	else {
282		throttle_state = 0;
283		omap_thermal_unthrottle();
284	}
285	return count;
286}
287
288static DEVICE_ATTR(temperature, S_IRUGO, omap_temp_show_current, NULL);
289static DEVICE_ATTR(throttle, S_IWUSR, NULL, omap_throttle_store);
290static struct attribute *omap_temp_sensor_attributes[] = {
291	&dev_attr_temperature.attr,
292	&dev_attr_throttle.attr,
293	NULL
294};
295
296static const struct attribute_group omap_temp_sensor_group = {
297	.attrs = omap_temp_sensor_attributes,
298};
299
300static int omap_temp_sensor_enable(struct omap_temp_sensor *temp_sensor)
301{
302	u32 temp;
303	u32 ret = 0;
304	unsigned long clk_rate;
305
306	unsigned long flags;
307
308	spin_lock_irqsave(&temp_sensor->lock, flags);
309
310	if (temp_sensor->clk_on) {
311		pr_debug("%s: clock already on\n", __func__);
312		goto out;
313	}
314
315	ret = pm_runtime_get_sync(&temp_sensor->pdev->dev);
316	if (ret) {
317		pr_err("%s:get sync failed\n", __func__);
318		ret = -EINVAL;
319		goto out;
320	}
321
322	clk_set_rate(temp_sensor->clock, 1000000);
323	clk_rate = clk_get_rate(temp_sensor->clock);
324	temp_sensor->clk_rate = clk_rate;
325
326	temp = omap_temp_sensor_readl(temp_sensor,
327					TEMP_SENSOR_CTRL_OFFSET);
328	temp &= ~(OMAP4_BGAP_TEMPSOFF_MASK);
329
330	/* write BGAP_TEMPSOFF should be reset to 0 */
331	omap_temp_sensor_writel(temp_sensor, temp,
332				TEMP_SENSOR_CTRL_OFFSET);
333	temp_sensor->clk_on = 1;
334
335out:
336spin_unlock_irqrestore(&temp_sensor->lock, flags);
337	return ret;
338}
339
340
341static int omap_temp_sensor_disable(struct omap_temp_sensor *temp_sensor)
342{
343	u32 temp;
344	u32 ret = 0;
345	u32 counter = 1000;
346	unsigned long flags;
347
348	spin_lock_irqsave(&temp_sensor->lock, flags);
349
350	if (!temp_sensor->clk_on) {
351		pr_debug("%s: clock already off\n", __func__);
352		goto out;
353	}
354	temp = omap_temp_sensor_readl(temp_sensor,
355				TEMP_SENSOR_CTRL_OFFSET);
356	temp |= OMAP4_BGAP_TEMPSOFF_MASK;
357
358	/* write BGAP_TEMPSOFF should be set to 1 before gating clock */
359	omap_temp_sensor_writel(temp_sensor, temp,
360				TEMP_SENSOR_CTRL_OFFSET);
361	temp = omap_temp_sensor_readl(temp_sensor, BGAP_STATUS_OFFSET);
362
363	/* wait till the clean stop bit is set */
364	while ((temp & OMAP4_CLEAN_STOP_MASK) && --counter)
365		temp = omap_temp_sensor_readl(temp_sensor,
366						BGAP_STATUS_OFFSET);
367	/* Gate the clock */
368	ret = pm_runtime_put_sync_suspend(&temp_sensor->pdev->dev);
369	if (ret) {
370		pr_err("%s:put sync failed\n", __func__);
371		ret = -EINVAL;
372		goto out;
373	}
374	temp_sensor->clk_on = 0;
375
376out:
377	spin_unlock_irqrestore(&temp_sensor->lock, flags);
378	return ret;
379}
380
381/*
382 * Check if the die sensor is cooling down. If it's higher than
383 * t_hot since the last throttle then throttle it again.
384 * OMAP junction temperature could stay for a long time in an
385 * unacceptable temperature range. The idea here is to check after
386 * t_hot->throttle the system really came below t_hot else re-throttle
387 * and keep doing till it's under t_hot temp range.
388 */
389static void throttle_delayed_work_fn(struct work_struct *work)
390{
391	int curr;
392	struct omap_temp_sensor *temp_sensor =
393				container_of(work, struct omap_temp_sensor,
394					     throttle_work.work);
395	curr = omap_read_current_temp(temp_sensor);
396
397	if ((curr >= BGAP_THRESHOLD_T_HOT || curr < 0)) {
398		pr_warn("%s: OMAP temp read %d exceeds the threshold\n",
399			__func__, curr);
400	if (throttle_state == 1)
401		omap_thermal_throttle();
402		schedule_delayed_work(&temp_sensor->throttle_work,
403			msecs_to_jiffies(THROTTLE_DELAY_MS));
404	} else {
405		schedule_delayed_work(&temp_sensor->throttle_work,
406			msecs_to_jiffies(THROTTLE_DELAY_MS));
407	}
408}
409
410static irqreturn_t omap_tshut_irq_handler(int irq, void *data)
411{
412	struct omap_temp_sensor *temp_sensor = (struct omap_temp_sensor *)data;
413
414	/* Need to handle thermal mgmt in bootloader
415	 * to avoid restart again at kernel level
416	 */
417	if (temp_sensor->is_efuse_valid) {
418		pr_emerg("%s: Thermal shutdown reached rebooting device\n",
419			__func__);
420		kernel_restart(NULL);
421	} else {
422		pr_err("%s:Invalid EFUSE, Non-trimmed BGAP\n", __func__);
423	}
424
425	return IRQ_HANDLED;
426}
427
428static irqreturn_t omap_talert_irq_handler(int irq, void *data)
429{
430	struct omap_temp_sensor *temp_sensor = (struct omap_temp_sensor *)data;
431	int t_hot, t_cold, temp_offset;
432
433	t_hot = omap_temp_sensor_readl(temp_sensor, BGAP_STATUS_OFFSET)
434	    & OMAP4_HOT_FLAG_MASK;
435	t_cold = omap_temp_sensor_readl(temp_sensor, BGAP_STATUS_OFFSET)
436	    & OMAP4_COLD_FLAG_MASK;
437	temp_offset = omap_temp_sensor_readl(temp_sensor, BGAP_CTRL_OFFSET);
438	if (t_hot) {
439		if (throttle_state == 1)
440			omap_thermal_throttle();
441		schedule_delayed_work(&temp_sensor->throttle_work,
442			msecs_to_jiffies(THROTTLE_DELAY_MS));
443		temp_offset &= ~(OMAP4_MASK_HOT_MASK);
444		temp_offset |= OMAP4_MASK_COLD_MASK;
445	} else if (t_cold) {
446		cancel_delayed_work_sync(&temp_sensor->throttle_work);
447		omap_thermal_unthrottle();
448		temp_offset &= ~(OMAP4_MASK_COLD_MASK);
449		temp_offset |= OMAP4_MASK_HOT_MASK;
450	}
451
452	omap_temp_sensor_writel(temp_sensor, temp_offset, BGAP_CTRL_OFFSET);
453
454	return IRQ_HANDLED;
455}
456
457static int __devinit omap_temp_sensor_probe(struct platform_device *pdev)
458{
459	struct device *dev = &pdev->dev;
460	struct omap_temp_sensor_pdata *pdata = pdev->dev.platform_data;
461	struct omap_temp_sensor *temp_sensor;
462	struct resource *mem;
463	int ret = 0, val;
464
465	if (!pdata) {
466		dev_err(dev, "%s: platform data missing\n", __func__);
467		return -EINVAL;
468	}
469
470	temp_sensor = kzalloc(sizeof(struct omap_temp_sensor), GFP_KERNEL);
471	if (!temp_sensor)
472		return -ENOMEM;
473
474	spin_lock_init(&temp_sensor->lock);
475
476	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
477	if (!mem) {
478		dev_err(dev, "%s:no mem resource\n", __func__);
479		ret = -EINVAL;
480		goto plat_res_err;
481	}
482
483	temp_sensor->irq = platform_get_irq_byname(pdev, "thermal_alert");
484	if (temp_sensor->irq < 0) {
485		dev_err(dev, "%s:Cannot get thermal alert irq\n",
486			__func__);
487		ret = -EINVAL;
488		goto get_irq_err;
489	}
490
491	ret = gpio_request_one(OMAP_TSHUT_GPIO, GPIOF_DIR_IN,
492		"thermal_shutdown");
493	if (ret) {
494		dev_err(dev, "%s: Could not get tshut_gpio\n",
495			__func__);
496		goto tshut_gpio_req_err;
497	}
498
499	temp_sensor->tshut_irq = gpio_to_irq(OMAP_TSHUT_GPIO);
500	if (temp_sensor->tshut_irq < 0) {
501		dev_err(dev, "%s:Cannot get thermal shutdown irq\n",
502			__func__);
503		ret = -EINVAL;
504		goto get_tshut_irq_err;
505	}
506
507	temp_sensor->phy_base = pdata->offset;
508	temp_sensor->pdev = pdev;
509	temp_sensor->dev = dev;
510
511	pm_runtime_enable(dev);
512	pm_runtime_irq_safe(dev);
513
514	/*
515	 * check if the efuse has a non-zero value if not
516	 * it is an untrimmed sample and the temperatures
517	 * may not be accurate */
518	if (omap_readl(OMAP4_CTRL_MODULE_CORE +
519			OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP))
520		temp_sensor->is_efuse_valid = 1;
521
522	temp_sensor->clock = clk_get(&temp_sensor->pdev->dev, "fck");
523	if (IS_ERR(temp_sensor->clock)) {
524		ret = PTR_ERR(temp_sensor->clock);
525		pr_err("%s:Unable to get fclk: %d\n", __func__, ret);
526		ret = -EINVAL;
527		goto clk_get_err;
528	}
529
530	/* Init delayed work for throttle decision */
531	INIT_DELAYED_WORK(&temp_sensor->throttle_work,
532			  throttle_delayed_work_fn);
533
534	platform_set_drvdata(pdev, temp_sensor);
535
536	ret = omap_temp_sensor_enable(temp_sensor);
537	if (ret) {
538		dev_err(dev, "%s:Cannot enable temp sensor\n", __func__);
539		goto sensor_enable_err;
540	}
541
542	omap_enable_continuous_mode(temp_sensor);
543	omap_configure_temp_sensor_thresholds(temp_sensor);
544	/* 1 ms */
545	omap_configure_temp_sensor_counter(temp_sensor, 1);
546
547	/* Wait till the first conversion is done wait for at least 1ms */
548	mdelay(2);
549
550	/* Read the temperature once due to hw issue*/
551	omap_read_current_temp(temp_sensor);
552
553	/* Set 2 seconds time as default counter */
554	omap_configure_temp_sensor_counter(temp_sensor,
555						temp_sensor->clk_rate * 2);
556	ret = request_threaded_irq(temp_sensor->irq, NULL,
557			omap_talert_irq_handler,
558			IRQF_TRIGGER_RISING | IRQF_ONESHOT,
559			"temp_sensor", (void *)temp_sensor);
560	if (ret) {
561		dev_err(dev, "Request threaded irq failed.\n");
562		goto req_irq_err;
563	}
564
565	ret = request_threaded_irq(temp_sensor->tshut_irq, NULL,
566			omap_tshut_irq_handler,
567			IRQF_TRIGGER_RISING | IRQF_ONESHOT,
568			"tshut", (void *)temp_sensor);
569	if (ret) {
570		dev_err(dev, "Request threaded irq failed for TSHUT.\n");
571		goto tshut_irq_req_err;
572	}
573
574	ret = sysfs_create_group(&pdev->dev.kobj, &omap_temp_sensor_group);
575	if (ret) {
576		dev_err(&pdev->dev, "could not create sysfs files\n");
577		goto sysfs_create_err;
578	}
579
580	/* unmask the T_COLD and unmask T_HOT at init */
581	val = omap_temp_sensor_readl(temp_sensor, BGAP_CTRL_OFFSET);
582	val |= OMAP4_MASK_COLD_MASK;
583	val |= OMAP4_MASK_HOT_MASK;
584	omap_temp_sensor_writel(temp_sensor, val, BGAP_CTRL_OFFSET);
585
586	dev_info(dev, "%s probed", pdata->name);
587
588	temp_sensor_pm = temp_sensor;
589
590	return 0;
591
592sysfs_create_err:
593	free_irq(temp_sensor->tshut_irq, temp_sensor);
594	cancel_delayed_work_sync(&temp_sensor->throttle_work);
595tshut_irq_req_err:
596	free_irq(temp_sensor->irq, temp_sensor);
597req_irq_err:
598	platform_set_drvdata(pdev, NULL);
599	omap_temp_sensor_disable(temp_sensor);
600sensor_enable_err:
601	clk_put(temp_sensor->clock);
602clk_get_err:
603	pm_runtime_disable(dev);
604get_tshut_irq_err:
605	gpio_free(OMAP_TSHUT_GPIO);
606tshut_gpio_req_err:
607get_irq_err:
608plat_res_err:
609	kfree(temp_sensor);
610	return ret;
611}
612
613static int __devexit omap_temp_sensor_remove(struct platform_device *pdev)
614{
615	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
616
617	sysfs_remove_group(&pdev->dev.kobj, &omap_temp_sensor_group);
618	cancel_delayed_work_sync(&temp_sensor->throttle_work);
619	omap_temp_sensor_disable(temp_sensor);
620	clk_put(temp_sensor->clock);
621	platform_set_drvdata(pdev, NULL);
622	if (temp_sensor->irq)
623		free_irq(temp_sensor->irq, temp_sensor);
624	if (temp_sensor->tshut_irq)
625		free_irq(temp_sensor->tshut_irq, temp_sensor);
626	kfree(temp_sensor);
627
628	return 0;
629}
630
631#ifdef CONFIG_PM
632static void omap_temp_sensor_save_ctxt(struct omap_temp_sensor *temp_sensor)
633{
634	temp_sensor_context.temp_sensor_ctrl =
635	    omap_temp_sensor_readl(temp_sensor, TEMP_SENSOR_CTRL_OFFSET);
636	temp_sensor_context.bg_ctrl =
637	    omap_temp_sensor_readl(temp_sensor, BGAP_CTRL_OFFSET);
638	temp_sensor_context.bg_counter =
639	    omap_temp_sensor_readl(temp_sensor, BGAP_COUNTER_OFFSET);
640	temp_sensor_context.bg_threshold =
641	    omap_temp_sensor_readl(temp_sensor, BGAP_THRESHOLD_OFFSET);
642	temp_sensor_context.temp_sensor_tshut_threshold =
643	    omap_temp_sensor_readl(temp_sensor, BGAP_TSHUT_OFFSET);
644}
645
646static void omap_temp_sensor_restore_ctxt(struct omap_temp_sensor *temp_sensor)
647{
648	omap_temp_sensor_writel(temp_sensor,
649				temp_sensor_context.temp_sensor_ctrl,
650				TEMP_SENSOR_CTRL_OFFSET);
651	omap_temp_sensor_writel(temp_sensor,
652				temp_sensor_context.bg_ctrl,
653				BGAP_CTRL_OFFSET);
654	omap_temp_sensor_writel(temp_sensor,
655				temp_sensor_context.bg_counter,
656				BGAP_COUNTER_OFFSET);
657	omap_temp_sensor_writel(temp_sensor,
658				temp_sensor_context.bg_threshold,
659				BGAP_THRESHOLD_OFFSET);
660	omap_temp_sensor_writel(temp_sensor,
661				temp_sensor_context.temp_sensor_tshut_threshold,
662				BGAP_TSHUT_OFFSET);
663}
664
665static int omap_temp_sensor_suspend(struct platform_device *pdev,
666				    pm_message_t state)
667{
668	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
669
670	omap_temp_sensor_disable(temp_sensor);
671
672	return 0;
673}
674
675static int omap_temp_sensor_resume(struct platform_device *pdev)
676{
677	struct omap_temp_sensor *temp_sensor = platform_get_drvdata(pdev);
678
679	omap_temp_sensor_enable(temp_sensor);
680
681	return 0;
682}
683
684void omap_temp_sensor_idle(int idle_state)
685{
686	if (!temp_sensor_pm)
687		return;
688
689	if (idle_state)
690		omap_temp_sensor_disable(temp_sensor_pm);
691	else
692		omap_temp_sensor_enable(temp_sensor_pm);
693}
694
695#else
696omap_temp_sensor_suspend NULL
697omap_temp_sensor_resume NULL
698
699#endif /* CONFIG_PM */
700static int omap_temp_sensor_runtime_suspend(struct device *dev)
701{
702	struct omap_temp_sensor *temp_sensor =
703			platform_get_drvdata(to_platform_device(dev));
704
705	omap_temp_sensor_save_ctxt(temp_sensor);
706	return 0;
707}
708
709static int omap_temp_sensor_runtime_resume(struct device *dev)
710{
711	struct omap_temp_sensor *temp_sensor =
712			platform_get_drvdata(to_platform_device(dev));
713	if (omap_pm_was_context_lost(dev)) {
714		omap_temp_sensor_restore_ctxt(temp_sensor);
715	}
716	return 0;
717}
718
719static const struct dev_pm_ops omap_temp_sensor_dev_pm_ops = {
720	.runtime_suspend = omap_temp_sensor_runtime_suspend,
721	.runtime_resume = omap_temp_sensor_runtime_resume,
722};
723
724static struct platform_driver omap_temp_sensor_driver = {
725	.probe = omap_temp_sensor_probe,
726	.remove = omap_temp_sensor_remove,
727	.suspend = omap_temp_sensor_suspend,
728	.resume = omap_temp_sensor_resume,
729	.driver = {
730		.name = "omap_temp_sensor",
731		.pm = &omap_temp_sensor_dev_pm_ops,
732	},
733};
734
735int __init omap_temp_sensor_init(void)
736{
737	if (!cpu_is_omap446x())
738		return 0;
739
740	return platform_driver_register(&omap_temp_sensor_driver);
741}
742
743static void __exit omap_temp_sensor_exit(void)
744{
745	platform_driver_unregister(&omap_temp_sensor_driver);
746}
747
748module_init(omap_temp_sensor_init);
749module_exit(omap_temp_sensor_exit);
750
751MODULE_DESCRIPTION("OMAP446X Temperature Sensor Driver");
752MODULE_LICENSE("GPL");
753MODULE_ALIAS("platform:" DRIVER_NAME);
754MODULE_AUTHOR("Texas Instruments Inc");