ti-bandgap.c 39.7 KB
Newer Older
1
/*
2
 * TI Bandgap temperature sensor driver
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
 *
 * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
 * Author: J Keerthy <j-keerthy@ti.com>
 * Author: Moiz Sonasath <m-sonasath@ti.com>
 * Couple of fixes, DT and MFD adaptation:
 *   Eduardo Valentin <eduardo.valentin@ti.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/module.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/types.h>
36
#include <linux/spinlock.h>
37 38 39 40
#include <linux/reboot.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/of_irq.h>
41
#include <linux/of_gpio.h>
42
#include <linux/io.h>
43

44
#include "ti-bandgap.h"
45

46 47
/***   Helper functions to access registers and their bitfields   ***/

48
/**
49 50
 * ti_bandgap_readl() - simple read helper function
 * @bgp: pointer to ti_bandgap structure
51 52 53
 * @reg: desired register (offset) to be read
 *
 * Helper function to read bandgap registers. It uses the io remapped area.
54
 * Return: the register value.
55
 */
56
static u32 ti_bandgap_readl(struct ti_bandgap *bgp, u32 reg)
57
{
58
	return readl(bgp->base + reg);
59 60
}

61
/**
62 63
 * ti_bandgap_writel() - simple write helper function
 * @bgp: pointer to ti_bandgap structure
64 65 66 67 68
 * @val: desired register value to be written
 * @reg: desired register (offset) to be written
 *
 * Helper function to write bandgap registers. It uses the io remapped area.
 */
69
static void ti_bandgap_writel(struct ti_bandgap *bgp, u32 val, u32 reg)
70
{
71
	writel(val, bgp->base + reg);
72 73
}

74 75 76 77 78 79
/**
 * DOC: macro to update bits.
 *
 * RMW_BITS() - used to read, modify and update bandgap bitfields.
 *            The value passed will be shifted.
 */
80
#define RMW_BITS(bgp, id, reg, mask, val)			\
81 82 83 84
do {								\
	struct temp_sensor_registers *t;			\
	u32 r;							\
								\
85
	t = bgp->conf->sensors[(id)].registers;		\
86
	r = ti_bandgap_readl(bgp, t->reg);			\
87 88
	r &= ~t->mask;						\
	r |= (val) << __ffs(t->mask);				\
89
	ti_bandgap_writel(bgp, r, t->reg);			\
90 91
} while (0)

92 93
/***   Basic helper functions   ***/

94
/**
95 96
 * ti_bandgap_power() - controls the power state of a bandgap device
 * @bgp: pointer to ti_bandgap structure
97 98 99 100
 * @on: desired power state (1 - on, 0 - off)
 *
 * Used to power on/off a bandgap device instance. Only used on those
 * that features tempsoff bit.
101 102
 *
 * Return: 0 on success, -ENOTSUPP if tempsoff is not supported.
103
 */
104
static int ti_bandgap_power(struct ti_bandgap *bgp, bool on)
105
{
P
Pavel Machek 已提交
106
	int i;
107

P
Pavel Machek 已提交
108 109
	if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH))
		return -ENOTSUPP;
110

111
	for (i = 0; i < bgp->conf->sensor_count; i++)
112
		/* active on 0 */
113
		RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on);
P
Pavel Machek 已提交
114
	return 0;
115 116
}

117
/**
118 119
 * ti_bandgap_read_temp() - helper function to read sensor temperature
 * @bgp: pointer to ti_bandgap structure
120 121 122 123 124 125
 * @id: bandgap sensor id
 *
 * Function to concentrate the steps to read sensor temperature register.
 * This function is desired because, depending on bandgap device version,
 * it might be needed to freeze the bandgap state machine, before fetching
 * the register value.
126 127
 *
 * Return: temperature in ADC values.
128
 */
129
static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id)
130 131
{
	struct temp_sensor_registers *tsr;
132
	u32 temp, reg;
133

134
	tsr = bgp->conf->sensors[id].registers;
135 136
	reg = tsr->temp_sensor_ctrl;

137
	if (TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
138
		RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
139 140 141 142 143 144 145 146
		/*
		 * In case we cannot read from cur_dtemp / dtemp_0,
		 * then we read from the last valid temp read
		 */
		reg = tsr->ctrl_dtemp_1;
	}

	/* read temperature */
147
	temp = ti_bandgap_readl(bgp, reg);
148 149
	temp &= tsr->bgap_dtemp_mask;

150
	if (TI_BANDGAP_HAS(bgp, FREEZE_BIT))
151
		RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
152 153 154 155

	return temp;
}

156 157
/***   IRQ handlers   ***/

158
/**
159
 * ti_bandgap_talert_irq_handler() - handles Temperature alert IRQs
160
 * @irq: IRQ number
161
 * @data: private data (struct ti_bandgap *)
162 163 164 165 166 167
 *
 * This is the Talert handler. Use it only if bandgap device features
 * HAS(TALERT). This handler goes over all sensors and checks their
 * conditions and acts accordingly. In case there are events pending,
 * it will reset the event mask to wait for the opposite event (next event).
 * Every time there is a new event, it will be reported to thermal layer.
168 169
 *
 * Return: IRQ_HANDLED
170
 */
171
static irqreturn_t ti_bandgap_talert_irq_handler(int irq, void *data)
172
{
173
	struct ti_bandgap *bgp = data;
174
	struct temp_sensor_registers *tsr;
175
	u32 t_hot = 0, t_cold = 0, ctrl;
176 177
	int i;

178 179 180
	spin_lock(&bgp->lock);
	for (i = 0; i < bgp->conf->sensor_count; i++) {
		tsr = bgp->conf->sensors[i].registers;
181
		ctrl = ti_bandgap_readl(bgp, tsr->bgap_status);
182 183 184

		/* Read the status of t_hot */
		t_hot = ctrl & tsr->status_hot_mask;
185 186

		/* Read the status of t_cold */
187
		t_cold = ctrl & tsr->status_cold_mask;
188 189 190 191

		if (!t_cold && !t_hot)
			continue;

192
		ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
193 194 195 196 197 198 199 200 201 202 203 204 205
		/*
		 * One TALERT interrupt: Two sources
		 * If the interrupt is due to t_hot then mask t_hot and
		 * and unmask t_cold else mask t_cold and unmask t_hot
		 */
		if (t_hot) {
			ctrl &= ~tsr->mask_hot_mask;
			ctrl |= tsr->mask_cold_mask;
		} else if (t_cold) {
			ctrl &= ~tsr->mask_cold_mask;
			ctrl |= tsr->mask_hot_mask;
		}

206
		ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
207

208
		dev_dbg(bgp->dev,
209
			"%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
210
			__func__, bgp->conf->sensors[i].domain,
211 212
			t_hot, t_cold);

213
		/* report temperature to whom may concern */
214 215
		if (bgp->conf->report_temperature)
			bgp->conf->report_temperature(bgp, i);
216
	}
217
	spin_unlock(&bgp->lock);
218 219 220 221

	return IRQ_HANDLED;
}

222
/**
223
 * ti_bandgap_tshut_irq_handler() - handles Temperature shutdown signal
224 225 226 227 228 229
 * @irq: IRQ number
 * @data: private data (unused)
 *
 * This is the Tshut handler. Use it only if bandgap device features
 * HAS(TSHUT). If any sensor fires the Tshut signal, we simply shutdown
 * the system.
230 231
 *
 * Return: IRQ_HANDLED
232
 */
233
static irqreturn_t ti_bandgap_tshut_irq_handler(int irq, void *data)
234
{
235 236 237
	pr_emerg("%s: TSHUT temperature reached. Needs shut down...\n",
		 __func__);

238 239 240 241 242
	orderly_poweroff(true);

	return IRQ_HANDLED;
}

243 244
/***   Helper functions which manipulate conversion ADC <-> mi Celsius   ***/

245
/**
246 247
 * ti_bandgap_adc_to_mcelsius() - converts an ADC value to mCelsius scale
 * @bgp: struct ti_bandgap pointer
248 249 250 251 252 253
 * @adc_val: value in ADC representation
 * @t: address where to write the resulting temperature in mCelsius
 *
 * Simple conversion from ADC representation to mCelsius. In case the ADC value
 * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
 * The conversion table is indexed by the ADC values.
254 255 256
 *
 * Return: 0 if conversion was successful, else -ERANGE in case the @adc_val
 * argument is out of the ADC conv table range.
257
 */
258
static
259
int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t)
260
{
261
	const struct ti_bandgap_data *conf = bgp->conf;
262 263

	/* look up for temperature in the table and return the temperature */
P
Pavel Machek 已提交
264 265
	if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val)
		return -ERANGE;
266

267
	*t = bgp->conf->conv_table[adc_val - conf->adc_start_val];
P
Pavel Machek 已提交
268
	return 0;
269 270
}

271
/**
272 273
 * ti_bandgap_mcelsius_to_adc() - converts a mCelsius value to ADC scale
 * @bgp: struct ti_bandgap pointer
274 275 276 277 278 279
 * @temp: value in mCelsius
 * @adc: address where to write the resulting temperature in ADC representation
 *
 * Simple conversion from mCelsius to ADC values. In case the temp value
 * is out of the ADC conv table range, it returns -ERANGE, 0 on success.
 * The conversion table is indexed by the ADC values.
280 281 282
 *
 * Return: 0 if conversion was successful, else -ERANGE in case the @temp
 * argument is out of the ADC conv table range.
283
 */
284
static
285
int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc)
286
{
287
	const struct ti_bandgap_data *conf = bgp->conf;
288
	const int *conv_table = bgp->conf->conv_table;
P
Pavel Machek 已提交
289
	int high, low, mid;
290 291

	low = 0;
292
	high = conf->adc_end_val - conf->adc_start_val;
293 294
	mid = (high + low) / 2;

P
Pavel Machek 已提交
295 296
	if (temp < conv_table[low] || temp > conv_table[high])
		return -ERANGE;
297 298

	while (low < high) {
299
		if (temp < conv_table[mid])
300 301 302 303 304 305
			high = mid - 1;
		else
			low = mid + 1;
		mid = (low + high) / 2;
	}

306
	*adc = conf->adc_start_val + low;
P
Pavel Machek 已提交
307
	return 0;
308 309
}

310
/**
311 312
 * ti_bandgap_add_hyst() - add hysteresis (in mCelsius) to an ADC value
 * @bgp: struct ti_bandgap pointer
313 314 315 316 317
 * @adc_val: temperature value in ADC representation
 * @hyst_val: hysteresis value in mCelsius
 * @sum: address where to write the resulting temperature (in ADC scale)
 *
 * Adds an hysteresis value (in mCelsius) to a ADC temperature value.
318 319
 *
 * Return: 0 on success, -ERANGE otherwise.
320
 */
321
static
322 323
int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val,
			u32 *sum)
324 325 326 327 328 329 330
{
	int temp, ret;

	/*
	 * Need to add in the mcelsius domain, so we have a temperature
	 * the conv_table range
	 */
331
	ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp);
332
	if (ret < 0)
P
Pavel Machek 已提交
333
		return ret;
334 335 336

	temp += hyst_val;

337
	ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum);
338 339 340
	return ret;
}

341 342
/***   Helper functions handling device Alert/Shutdown signals   ***/

343
/**
344 345
 * ti_bandgap_unmask_interrupts() - unmasks the events of thot & tcold
 * @bgp: struct ti_bandgap pointer
346
 * @id: bandgap sensor id
347 348 349 350 351 352
 * @t_hot: hot temperature value to trigger alert signal
 * @t_cold: cold temperature value to trigger alert signal
 *
 * Checks the requested t_hot and t_cold values and configures the IRQ event
 * masks accordingly. Call this function only if bandgap features HAS(TALERT).
 */
353 354
static void ti_bandgap_unmask_interrupts(struct ti_bandgap *bgp, int id,
					 u32 t_hot, u32 t_cold)
355 356 357 358 359
{
	struct temp_sensor_registers *tsr;
	u32 temp, reg_val;

	/* Read the current on die temperature */
360
	temp = ti_bandgap_read_temp(bgp, id);
361

362
	tsr = bgp->conf->sensors[id].registers;
363
	reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
364

365 366 367 368 369 370 371 372 373
	if (temp < t_hot)
		reg_val |= tsr->mask_hot_mask;
	else
		reg_val &= ~tsr->mask_hot_mask;

	if (t_cold < temp)
		reg_val |= tsr->mask_cold_mask;
	else
		reg_val &= ~tsr->mask_cold_mask;
374
	ti_bandgap_writel(bgp, reg_val, tsr->bgap_mask_ctrl);
375 376
}

377
/**
378 379
 * ti_bandgap_update_alert_threshold() - sequence to update thresholds
 * @bgp: struct ti_bandgap pointer
380 381 382 383 384 385 386 387 388 389
 * @id: bandgap sensor id
 * @val: value (ADC) of a new threshold
 * @hot: desired threshold to be updated. true if threshold hot, false if
 *       threshold cold
 *
 * It will program the required thresholds (hot and cold) for TALERT signal.
 * This function can be used to update t_hot or t_cold, depending on @hot value.
 * It checks the resulting t_hot and t_cold values, based on the new passed @val
 * and configures the thresholds so that t_hot is always greater than t_cold.
 * Call this function only if bandgap features HAS(TALERT).
390 391
 *
 * Return: 0 if no error, else corresponding error
392
 */
393 394
static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id,
					     int val, bool hot)
395
{
396
	struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data;
397
	struct temp_sensor_registers *tsr;
398 399
	u32 thresh_val, reg_val, t_hot, t_cold;
	int err = 0;
400

401
	tsr = bgp->conf->sensors[id].registers;
402

403
	/* obtain the current value */
404
	thresh_val = ti_bandgap_readl(bgp, tsr->bgap_threshold);
405 406 407 408 409 410 411 412 413
	t_cold = (thresh_val & tsr->threshold_tcold_mask) >>
		__ffs(tsr->threshold_tcold_mask);
	t_hot = (thresh_val & tsr->threshold_thot_mask) >>
		__ffs(tsr->threshold_thot_mask);
	if (hot)
		t_hot = val;
	else
		t_cold = val;

414
	if (t_cold > t_hot) {
415
		if (hot)
416 417 418
			err = ti_bandgap_add_hyst(bgp, t_hot,
						  -ts_data->hyst_val,
						  &t_cold);
419
		else
420 421 422
			err = ti_bandgap_add_hyst(bgp, t_cold,
						  ts_data->hyst_val,
						  &t_hot);
423 424
	}

425
	/* write the new threshold values */
426 427 428 429
	reg_val = thresh_val &
		  ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask);
	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) |
		   (t_cold << __ffs(tsr->threshold_tcold_mask));
430
	ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold);
431

432
	if (err) {
433
		dev_err(bgp->dev, "failed to reprogram thot threshold\n");
434 435
		err = -EIO;
		goto exit;
436 437
	}

438
	ti_bandgap_unmask_interrupts(bgp, id, t_hot, t_cold);
439 440
exit:
	return err;
441 442
}

443
/**
444 445
 * ti_bandgap_validate() - helper to check the sanity of a struct ti_bandgap
 * @bgp: struct ti_bandgap pointer
446 447 448 449
 * @id: bandgap sensor id
 *
 * Checks if the bandgap pointer is valid and if the sensor id is also
 * applicable.
450 451 452
 *
 * Return: 0 if no errors, -EINVAL for invalid @bgp pointer or -ERANGE if
 * @id cannot index @bgp sensors.
453
 */
454
static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
455
{
456
	if (!bgp || IS_ERR(bgp)) {
457
		pr_err("%s: invalid bandgap pointer\n", __func__);
P
Pavel Machek 已提交
458
		return -EINVAL;
459 460
	}

461 462
	if ((id < 0) || (id >= bgp->conf->sensor_count)) {
		dev_err(bgp->dev, "%s: sensor id out of range (%d)\n",
463
			__func__, id);
P
Pavel Machek 已提交
464
		return -ERANGE;
465 466
	}

P
Pavel Machek 已提交
467
	return 0;
468 469
}

470
/**
471 472
 * _ti_bandgap_write_threshold() - helper to update TALERT t_cold or t_hot
 * @bgp: struct ti_bandgap pointer
473 474 475 476 477 478 479 480 481
 * @id: bandgap sensor id
 * @val: value (mCelsius) of a new threshold
 * @hot: desired threshold to be updated. true if threshold hot, false if
 *       threshold cold
 *
 * It will update the required thresholds (hot and cold) for TALERT signal.
 * This function can be used to update t_hot or t_cold, depending on @hot value.
 * Validates the mCelsius range and update the requested threshold.
 * Call this function only if bandgap features HAS(TALERT).
482 483
 *
 * Return: 0 if no error, else corresponding error value.
484
 */
485 486
static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val,
				       bool hot)
487
{
488 489 490 491 492
	struct temp_sensor_data *ts_data;
	struct temp_sensor_registers *tsr;
	u32 adc_val;
	int ret;

493
	ret = ti_bandgap_validate(bgp, id);
494
	if (ret)
P
Pavel Machek 已提交
495
		return ret;
496

P
Pavel Machek 已提交
497 498
	if (!TI_BANDGAP_HAS(bgp, TALERT))
		return -ENOTSUPP;
499

500 501
	ts_data = bgp->conf->sensors[id].ts_data;
	tsr = bgp->conf->sensors[id].registers;
502 503 504 505 506 507
	if (hot) {
		if (val < ts_data->min_temp + ts_data->hyst_val)
			ret = -EINVAL;
	} else {
		if (val > ts_data->max_temp + ts_data->hyst_val)
			ret = -EINVAL;
508 509
	}

510
	if (ret)
P
Pavel Machek 已提交
511
		return ret;
512

513
	ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val);
514
	if (ret < 0)
P
Pavel Machek 已提交
515
		return ret;
516

517
	spin_lock(&bgp->lock);
518
	ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot);
519
	spin_unlock(&bgp->lock);
520
	return ret;
521 522
}

523
/**
524 525
 * _ti_bandgap_read_threshold() - helper to read TALERT t_cold or t_hot
 * @bgp: struct ti_bandgap pointer
526 527 528 529 530 531 532 533
 * @id: bandgap sensor id
 * @val: value (mCelsius) of a threshold
 * @hot: desired threshold to be read. true if threshold hot, false if
 *       threshold cold
 *
 * It will fetch the required thresholds (hot and cold) for TALERT signal.
 * This function can be used to read t_hot or t_cold, depending on @hot value.
 * Call this function only if bandgap features HAS(TALERT).
534 535 536
 *
 * Return: 0 if no error, -ENOTSUPP if it has no TALERT support, or the
 * corresponding error value if some operation fails.
537
 */
538 539
static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id,
				      int *val, bool hot)
540 541
{
	struct temp_sensor_registers *tsr;
542 543
	u32 temp, mask;
	int ret = 0;
544

545
	ret = ti_bandgap_validate(bgp, id);
546
	if (ret)
547
		goto exit;
548

549
	if (!TI_BANDGAP_HAS(bgp, TALERT)) {
550 551 552
		ret = -ENOTSUPP;
		goto exit;
	}
553

554
	tsr = bgp->conf->sensors[id].registers;
555 556 557 558 559
	if (hot)
		mask = tsr->threshold_thot_mask;
	else
		mask = tsr->threshold_tcold_mask;

560
	temp = ti_bandgap_readl(bgp, tsr->bgap_threshold);
561
	temp = (temp & mask) >> __ffs(mask);
P
Pavel Machek 已提交
562
	ret = ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
563
	if (ret) {
564
		dev_err(bgp->dev, "failed to read thot\n");
565 566
		ret = -EIO;
		goto exit;
567 568
	}

569
	*val = temp;
570

571
exit:
572
	return ret;
573 574
}

575 576 577
/***   Exposed APIs   ***/

/**
578
 * ti_bandgap_read_thot() - reads sensor current thot
579 580 581
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @thot: resulting current thot value
582
 *
583
 * Return: 0 on success or the proper error code
584
 */
585
int ti_bandgap_read_thot(struct ti_bandgap *bgp, int id, int *thot)
586
{
587
	return _ti_bandgap_read_threshold(bgp, id, thot, true);
588 589
}

590
/**
591
 * ti_bandgap_write_thot() - sets sensor current thot
592 593 594
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @val: desired thot value
595
 *
596
 * Return: 0 on success or the proper error code
597
 */
598
int ti_bandgap_write_thot(struct ti_bandgap *bgp, int id, int val)
599
{
600
	return _ti_bandgap_write_threshold(bgp, id, val, true);
601 602 603
}

/**
604
 * ti_bandgap_read_tcold() - reads sensor current tcold
605 606 607
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @tcold: resulting current tcold value
608
 *
609
 * Return: 0 on success or the proper error code
610
 */
611
int ti_bandgap_read_tcold(struct ti_bandgap *bgp, int id, int *tcold)
612
{
613
	return _ti_bandgap_read_threshold(bgp, id, tcold, false);
614 615 616
}

/**
617
 * ti_bandgap_write_tcold() - sets the sensor tcold
618 619 620
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @val: desired tcold value
621
 *
622
 * Return: 0 on success or the proper error code
623
 */
624
int ti_bandgap_write_tcold(struct ti_bandgap *bgp, int id, int val)
625
{
626
	return _ti_bandgap_write_threshold(bgp, id, val, false);
627 628
}

629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
/**
 * ti_bandgap_read_counter() - read the sensor counter
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @interval: resulting update interval in miliseconds
 */
static void ti_bandgap_read_counter(struct ti_bandgap *bgp, int id,
				    int *interval)
{
	struct temp_sensor_registers *tsr;
	int time;

	tsr = bgp->conf->sensors[id].registers;
	time = ti_bandgap_readl(bgp, tsr->bgap_counter);
	time = (time & tsr->counter_mask) >>
					__ffs(tsr->counter_mask);
	time = time * 1000 / bgp->clk_rate;
	*interval = time;
}

/**
 * ti_bandgap_read_counter_delay() - read the sensor counter delay
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @interval: resulting update interval in miliseconds
 */
static void ti_bandgap_read_counter_delay(struct ti_bandgap *bgp, int id,
					  int *interval)
{
	struct temp_sensor_registers *tsr;
	int reg_val;

	tsr = bgp->conf->sensors[id].registers;

	reg_val = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
	reg_val = (reg_val & tsr->mask_counter_delay_mask) >>
				__ffs(tsr->mask_counter_delay_mask);
	switch (reg_val) {
	case 0:
		*interval = 0;
		break;
	case 1:
		*interval = 1;
		break;
	case 2:
		*interval = 10;
		break;
	case 3:
		*interval = 100;
		break;
	case 4:
		*interval = 250;
		break;
	case 5:
		*interval = 500;
		break;
	default:
		dev_warn(bgp->dev, "Wrong counter delay value read from register %X",
			 reg_val);
	}
}

691
/**
692
 * ti_bandgap_read_update_interval() - read the sensor update interval
693 694 695
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @interval: resulting update interval in miliseconds
696
 *
697
 * Return: 0 on success or the proper error code
698
 */
699 700
int ti_bandgap_read_update_interval(struct ti_bandgap *bgp, int id,
				    int *interval)
701
{
702
	int ret = 0;
703

704
	ret = ti_bandgap_validate(bgp, id);
705
	if (ret)
706
		goto exit;
707

708 709 710 711 712
	if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
	    !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
		ret = -ENOTSUPP;
		goto exit;
	}
713

714 715 716 717
	if (TI_BANDGAP_HAS(bgp, COUNTER)) {
		ti_bandgap_read_counter(bgp, id, interval);
		goto exit;
	}
718

719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
	ti_bandgap_read_counter_delay(bgp, id, interval);
exit:
	return ret;
}

/**
 * ti_bandgap_write_counter_delay() - set the counter_delay
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @interval: desired update interval in miliseconds
 *
 * Return: 0 on success or the proper error code
 */
static int ti_bandgap_write_counter_delay(struct ti_bandgap *bgp, int id,
					  u32 interval)
{
	int rval;

	switch (interval) {
	case 0: /* Immediate conversion */
		rval = 0x0;
		break;
	case 1: /* Conversion after ever 1ms */
		rval = 0x1;
		break;
	case 10: /* Conversion after ever 10ms */
		rval = 0x2;
		break;
	case 100: /* Conversion after ever 100ms */
		rval = 0x3;
		break;
	case 250: /* Conversion after ever 250ms */
		rval = 0x4;
		break;
	case 500: /* Conversion after ever 500ms */
		rval = 0x5;
		break;
	default:
		dev_warn(bgp->dev, "Delay %d ms is not supported\n", interval);
		return -EINVAL;
	}

	spin_lock(&bgp->lock);
	RMW_BITS(bgp, id, bgap_mask_ctrl, mask_counter_delay_mask, rval);
	spin_unlock(&bgp->lock);
764 765 766 767

	return 0;
}

768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
/**
 * ti_bandgap_write_counter() - set the bandgap sensor counter
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @interval: desired update interval in miliseconds
 */
static void ti_bandgap_write_counter(struct ti_bandgap *bgp, int id,
				     u32 interval)
{
	interval = interval * bgp->clk_rate / 1000;
	spin_lock(&bgp->lock);
	RMW_BITS(bgp, id, bgap_counter, counter_mask, interval);
	spin_unlock(&bgp->lock);
}

783
/**
784
 * ti_bandgap_write_update_interval() - set the update interval
785 786 787
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @interval: desired update interval in miliseconds
788
 *
789
 * Return: 0 on success or the proper error code
790
 */
791 792
int ti_bandgap_write_update_interval(struct ti_bandgap *bgp,
				     int id, u32 interval)
793
{
794
	int ret = ti_bandgap_validate(bgp, id);
795
	if (ret)
796
		goto exit;
797

798 799 800 801 802
	if (!TI_BANDGAP_HAS(bgp, COUNTER) &&
	    !TI_BANDGAP_HAS(bgp, COUNTER_DELAY)) {
		ret = -ENOTSUPP;
		goto exit;
	}
803

804 805 806 807
	if (TI_BANDGAP_HAS(bgp, COUNTER)) {
		ti_bandgap_write_counter(bgp, id, interval);
		goto exit;
	}
808

809 810 811
	ret = ti_bandgap_write_counter_delay(bgp, id, interval);
exit:
	return ret;
812 813 814
}

/**
815
 * ti_bandgap_read_temperature() - report current temperature
816 817 818
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @temperature: resulting temperature
819
 *
820
 * Return: 0 on success or the proper error code
821
 */
822 823
int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id,
				int *temperature)
824 825 826 827
{
	u32 temp;
	int ret;

828
	ret = ti_bandgap_validate(bgp, id);
829 830 831
	if (ret)
		return ret;

832
	spin_lock(&bgp->lock);
833
	temp = ti_bandgap_read_temp(bgp, id);
834
	spin_unlock(&bgp->lock);
835

P
Pavel Machek 已提交
836
	ret = ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
837 838 839 840 841 842 843 844 845
	if (ret)
		return -EIO;

	*temperature = temp;

	return 0;
}

/**
846
 * ti_bandgap_set_sensor_data() - helper function to store thermal
847
 * framework related data.
848 849 850
 * @bgp: pointer to bandgap instance
 * @id: sensor id
 * @data: thermal framework related data to be stored
851
 *
852
 * Return: 0 on success or the proper error code
853
 */
854
int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data)
855
{
856
	int ret = ti_bandgap_validate(bgp, id);
857 858 859
	if (ret)
		return ret;

860
	bgp->regval[id].data = data;
861 862 863 864 865

	return 0;
}

/**
866
 * ti_bandgap_get_sensor_data() - helper function to get thermal
867
 * framework related data.
868 869
 * @bgp: pointer to bandgap instance
 * @id: sensor id
870
 *
871
 * Return: data stored by set function with sensor id on success or NULL
872
 */
873
void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id)
874
{
875
	int ret = ti_bandgap_validate(bgp, id);
876 877 878
	if (ret)
		return ERR_PTR(ret);

879
	return bgp->regval[id].data;
880 881
}

882 883
/***   Helper functions used during device initialization   ***/

884
/**
885 886
 * ti_bandgap_force_single_read() - executes 1 single ADC conversion
 * @bgp: pointer to struct ti_bandgap
887 888 889 890
 * @id: sensor id which it is desired to read 1 temperature
 *
 * Used to initialize the conversion state machine and set it to a valid
 * state. Called during device initialization and context restore events.
891 892
 *
 * Return: 0
893
 */
894
static int
895
ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
896
{
897 898
	u32 counter = 1000;
	struct temp_sensor_registers *tsr;
899 900

	/* Select single conversion mode */
901
	if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
902
		RMW_BITS(bgp, id, bgap_mode_ctrl, mode_ctrl_mask, 0);
903 904

	/* Start of Conversion = 1 */
905
	RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1);
906

907 908 909 910 911 912 913 914
	/* Wait for EOCZ going up */
	tsr = bgp->conf->sensors[id].registers;

	while (--counter) {
		if (ti_bandgap_readl(bgp, tsr->temp_sensor_ctrl) &
		    tsr->bgap_eocz_mask)
			break;
	}
915

916
	/* Start of Conversion = 0 */
917
	RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0);
918

919 920 921 922 923 924 925 926
	/* Wait for EOCZ going down */
	counter = 1000;
	while (--counter) {
		if (!(ti_bandgap_readl(bgp, tsr->temp_sensor_ctrl) &
		      tsr->bgap_eocz_mask))
			break;
	}

927 928 929 930
	return 0;
}

/**
931 932
 * ti_bandgap_set_continous_mode() - One time enabling of continuous mode
 * @bgp: pointer to struct ti_bandgap
933
 *
934 935 936 937
 * Call this function only if HAS(MODE_CONFIG) is set. As this driver may
 * be used for junction temperature monitoring, it is desirable that the
 * sensors are operational all the time, so that alerts are generated
 * properly.
938 939
 *
 * Return: 0
940
 */
941
static int ti_bandgap_set_continuous_mode(struct ti_bandgap *bgp)
942 943 944
{
	int i;

945
	for (i = 0; i < bgp->conf->sensor_count; i++) {
946
		/* Perform a single read just before enabling continuous */
947
		ti_bandgap_force_single_read(bgp, i);
948
		RMW_BITS(bgp, i, bgap_mode_ctrl, mode_ctrl_mask, 1);
949 950 951 952 953
	}

	return 0;
}

954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
/**
 * ti_bandgap_get_trend() - To fetch the temperature trend of a sensor
 * @bgp: pointer to struct ti_bandgap
 * @id: id of the individual sensor
 * @trend: Pointer to trend.
 *
 * This function needs to be called to fetch the temperature trend of a
 * Particular sensor. The function computes the difference in temperature
 * w.r.t time. For the bandgaps with built in history buffer the temperatures
 * are read from the buffer and for those without the Buffer -ENOTSUPP is
 * returned.
 *
 * Return: 0 if no error, else return corresponding error. If no
 *		error then the trend value is passed on to trend parameter
 */
int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
{
	struct temp_sensor_registers *tsr;
	u32 temp1, temp2, reg1, reg2;
	int t1, t2, interval, ret = 0;

	ret = ti_bandgap_validate(bgp, id);
	if (ret)
		goto exit;

	if (!TI_BANDGAP_HAS(bgp, HISTORY_BUFFER) ||
	    !TI_BANDGAP_HAS(bgp, FREEZE_BIT)) {
		ret = -ENOTSUPP;
		goto exit;
	}

985 986
	spin_lock(&bgp->lock);

987 988 989
	tsr = bgp->conf->sensors[id].registers;

	/* Freeze and read the last 2 valid readings */
990
	RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
	reg1 = tsr->ctrl_dtemp_1;
	reg2 = tsr->ctrl_dtemp_2;

	/* read temperature from history buffer */
	temp1 = ti_bandgap_readl(bgp, reg1);
	temp1 &= tsr->bgap_dtemp_mask;

	temp2 = ti_bandgap_readl(bgp, reg2);
	temp2 &= tsr->bgap_dtemp_mask;

	/* Convert from adc values to mCelsius temperature */
	ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1);
	if (ret)
1004
		goto unfreeze;
1005 1006 1007

	ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2);
	if (ret)
1008
		goto unfreeze;
1009 1010 1011

	/* Fetch the update interval */
	ret = ti_bandgap_read_update_interval(bgp, id, &interval);
1012
	if (ret)
1013
		goto unfreeze;
1014

1015 1016 1017 1018
	/* Set the interval to 1 ms if bandgap counter delay is not set */
	if (interval == 0)
		interval = 1;

1019 1020 1021 1022 1023
	*trend = (t1 - t2) / interval;

	dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
		t1, t2, *trend);

1024 1025 1026
unfreeze:
	RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
	spin_unlock(&bgp->lock);
1027 1028 1029 1030
exit:
	return ret;
}

1031
/**
1032 1033
 * ti_bandgap_tshut_init() - setup and initialize tshut handling
 * @bgp: pointer to struct ti_bandgap
1034 1035 1036 1037 1038 1039 1040 1041
 * @pdev: pointer to device struct platform_device
 *
 * Call this function only in case the bandgap features HAS(TSHUT).
 * In this case, the driver needs to handle the TSHUT signal as an IRQ.
 * The IRQ is wired as a GPIO, and for this purpose, it is required
 * to specify which GPIO line is used. TSHUT IRQ is fired anytime
 * one of the bandgap sensors violates the TSHUT high/hot threshold.
 * And in that case, the system must go off.
1042 1043
 *
 * Return: 0 if no error, else error status
1044
 */
1045 1046
static int ti_bandgap_tshut_init(struct ti_bandgap *bgp,
				 struct platform_device *pdev)
1047
{
1048
	int gpio_nr = bgp->tshut_gpio;
1049 1050 1051 1052 1053
	int status;

	/* Request for gpio_86 line */
	status = gpio_request(gpio_nr, "tshut");
	if (status < 0) {
1054
		dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86);
1055 1056 1057 1058
		return status;
	}
	status = gpio_direction_input(gpio_nr);
	if (status) {
1059
		dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr);
1060 1061 1062
		return status;
	}

1063 1064
	status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler,
			     IRQF_TRIGGER_RISING, "tshut", NULL);
1065 1066
	if (status) {
		gpio_free(gpio_nr);
1067
		dev_err(bgp->dev, "request irq failed for TSHUT");
1068 1069 1070 1071 1072
	}

	return 0;
}

1073
/**
1074 1075
 * ti_bandgap_alert_init() - setup and initialize talert handling
 * @bgp: pointer to struct ti_bandgap
1076 1077 1078 1079 1080 1081 1082
 * @pdev: pointer to device struct platform_device
 *
 * Call this function only in case the bandgap features HAS(TALERT).
 * In this case, the driver needs to handle the TALERT signals as an IRQs.
 * TALERT is a normal IRQ and it is fired any time thresholds (hot or cold)
 * are violated. In these situation, the driver must reprogram the thresholds,
 * accordingly to specified policy.
1083 1084
 *
 * Return: 0 if no error, else return corresponding error.
1085
 */
1086 1087
static int ti_bandgap_talert_init(struct ti_bandgap *bgp,
				  struct platform_device *pdev)
1088 1089 1090
{
	int ret;

1091 1092
	bgp->irq = platform_get_irq(pdev, 0);
	if (bgp->irq < 0) {
1093
		dev_err(&pdev->dev, "get_irq failed\n");
1094
		return bgp->irq;
1095
	}
1096
	ret = request_threaded_irq(bgp->irq, NULL,
1097
				   ti_bandgap_talert_irq_handler,
1098
				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
1099
				   "talert", bgp);
1100 1101 1102 1103 1104 1105 1106 1107
	if (ret) {
		dev_err(&pdev->dev, "Request threaded irq failed.\n");
		return ret;
	}

	return 0;
}

1108
static const struct of_device_id of_ti_bandgap_match[];
1109
/**
1110
 * ti_bandgap_build() - parse DT and setup a struct ti_bandgap
1111 1112 1113 1114
 * @pdev: pointer to device struct platform_device
 *
 * Used to read the device tree properties accordingly to the bandgap
 * matching version. Based on bandgap version and its capabilities it
1115
 * will build a struct ti_bandgap out of the required DT entries.
1116 1117 1118
 *
 * Return: valid bandgap structure if successful, else returns ERR_PTR
 * return value must be verified with IS_ERR.
1119
 */
1120
static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
1121 1122 1123
{
	struct device_node *node = pdev->dev.of_node;
	const struct of_device_id *of_id;
1124
	struct ti_bandgap *bgp;
1125 1126 1127 1128 1129 1130 1131 1132 1133
	struct resource *res;
	int i;

	/* just for the sake */
	if (!node) {
		dev_err(&pdev->dev, "no platform information available\n");
		return ERR_PTR(-EINVAL);
	}

1134
	bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
1135
	if (!bgp) {
1136 1137 1138 1139
		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
		return ERR_PTR(-ENOMEM);
	}

1140
	of_id = of_match_device(of_ti_bandgap_match, &pdev->dev);
1141
	if (of_id)
1142
		bgp->conf = of_id->data;
1143

1144 1145 1146
	/* register shadow for context save and restore */
	bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) *
				   bgp->conf->sensor_count, GFP_KERNEL);
1147
	if (!bgp->regval) {
1148 1149 1150 1151
		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
		return ERR_PTR(-ENOMEM);
	}

1152 1153 1154 1155 1156 1157 1158
	i = 0;
	do {
		void __iomem *chunk;

		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
		if (!res)
			break;
1159
		chunk = devm_ioremap_resource(&pdev->dev, res);
1160
		if (i == 0)
1161
			bgp->base = chunk;
1162 1163
		if (IS_ERR(chunk))
			return ERR_CAST(chunk);
1164

1165 1166 1167
		i++;
	} while (res);

1168
	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1169
		bgp->tshut_gpio = of_get_gpio(node, 0);
1170
		if (!gpio_is_valid(bgp->tshut_gpio)) {
1171
			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
1172
				bgp->tshut_gpio);
1173 1174 1175 1176
			return ERR_PTR(-EINVAL);
		}
	}

1177
	return bgp;
1178 1179
}

1180 1181
/***   Device driver call backs   ***/

1182
static
1183
int ti_bandgap_probe(struct platform_device *pdev)
1184
{
1185
	struct ti_bandgap *bgp;
1186 1187
	int clk_rate, ret = 0, i;

1188
	bgp = ti_bandgap_build(pdev);
1189
	if (IS_ERR(bgp)) {
1190
		dev_err(&pdev->dev, "failed to fetch platform data\n");
1191
		return PTR_ERR(bgp);
1192
	}
1193
	bgp->dev = &pdev->dev;
1194

1195 1196
	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
		ret = ti_bandgap_tshut_init(bgp, pdev);
1197 1198 1199 1200 1201 1202 1203
		if (ret) {
			dev_err(&pdev->dev,
				"failed to initialize system tshut IRQ\n");
			return ret;
		}
	}

1204
	bgp->fclock = clk_get(NULL, bgp->conf->fclock_name);
1205
	ret = IS_ERR(bgp->fclock);
1206 1207
	if (ret) {
		dev_err(&pdev->dev, "failed to request fclock reference\n");
1208
		ret = PTR_ERR(bgp->fclock);
1209 1210 1211
		goto free_irqs;
	}

P
Pavel Machek 已提交
1212
	bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name);
1213
	ret = IS_ERR(bgp->div_clk);
1214
	if (ret) {
P
Pavel Machek 已提交
1215
		dev_err(&pdev->dev, "failed to request div_ts_ck clock ref\n");
1216
		ret = PTR_ERR(bgp->div_clk);
1217 1218 1219
		goto free_irqs;
	}

1220
	for (i = 0; i < bgp->conf->sensor_count; i++) {
1221 1222 1223
		struct temp_sensor_registers *tsr;
		u32 val;

1224
		tsr = bgp->conf->sensors[i].registers;
1225 1226 1227 1228 1229
		/*
		 * check if the efuse has a non-zero value if not
		 * it is an untrimmed sample and the temperatures
		 * may not be accurate
		 */
1230
		val = ti_bandgap_readl(bgp, tsr->bgap_efuse);
1231 1232 1233 1234 1235
		if (ret || !val)
			dev_info(&pdev->dev,
				 "Non-trimmed BGAP, Temp not accurate\n");
	}

1236 1237 1238
	clk_rate = clk_round_rate(bgp->div_clk,
				  bgp->conf->sensors[0].ts_data->max_freq);
	if (clk_rate < bgp->conf->sensors[0].ts_data->min_freq ||
1239
	    clk_rate <= 0) {
1240 1241 1242 1243 1244
		ret = -ENODEV;
		dev_err(&pdev->dev, "wrong clock rate (%d)\n", clk_rate);
		goto put_clks;
	}

1245
	ret = clk_set_rate(bgp->div_clk, clk_rate);
1246 1247 1248
	if (ret)
		dev_err(&pdev->dev, "Cannot re-set clock rate. Continuing\n");

1249
	bgp->clk_rate = clk_rate;
1250
	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1251
		clk_prepare_enable(bgp->fclock);
1252

1253

1254 1255 1256
	spin_lock_init(&bgp->lock);
	bgp->dev = &pdev->dev;
	platform_set_drvdata(pdev, bgp);
1257

1258
	ti_bandgap_power(bgp, true);
1259 1260

	/* Set default counter to 1 for now */
1261
	if (TI_BANDGAP_HAS(bgp, COUNTER))
1262 1263
		for (i = 0; i < bgp->conf->sensor_count; i++)
			RMW_BITS(bgp, i, bgap_counter, counter_mask, 1);
1264

1265
	/* Set default thresholds for alert and shutdown */
1266
	for (i = 0; i < bgp->conf->sensor_count; i++) {
1267 1268
		struct temp_sensor_data *ts_data;

1269
		ts_data = bgp->conf->sensors[i].ts_data;
1270

1271
		if (TI_BANDGAP_HAS(bgp, TALERT)) {
1272
			/* Set initial Talert thresholds */
1273
			RMW_BITS(bgp, i, bgap_threshold,
1274
				 threshold_tcold_mask, ts_data->t_cold);
1275
			RMW_BITS(bgp, i, bgap_threshold,
1276 1277
				 threshold_thot_mask, ts_data->t_hot);
			/* Enable the alert events */
1278 1279
			RMW_BITS(bgp, i, bgap_mask_ctrl, mask_hot_mask, 1);
			RMW_BITS(bgp, i, bgap_mask_ctrl, mask_cold_mask, 1);
1280 1281
		}

1282
		if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG)) {
1283
			/* Set initial Tshut thresholds */
1284
			RMW_BITS(bgp, i, tshut_threshold,
1285
				 tshut_hot_mask, ts_data->tshut_hot);
1286
			RMW_BITS(bgp, i, tshut_threshold,
1287
				 tshut_cold_mask, ts_data->tshut_cold);
1288 1289 1290
		}
	}

1291 1292
	if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
		ti_bandgap_set_continuous_mode(bgp);
1293 1294

	/* Set .250 seconds time as default counter */
1295
	if (TI_BANDGAP_HAS(bgp, COUNTER))
1296 1297 1298
		for (i = 0; i < bgp->conf->sensor_count; i++)
			RMW_BITS(bgp, i, bgap_counter, counter_mask,
				 bgp->clk_rate / 4);
1299 1300

	/* Every thing is good? Then expose the sensors */
1301
	for (i = 0; i < bgp->conf->sensor_count; i++) {
1302 1303
		char *domain;

1304 1305 1306 1307 1308
		if (bgp->conf->sensors[i].register_cooling) {
			ret = bgp->conf->sensors[i].register_cooling(bgp, i);
			if (ret)
				goto remove_sensors;
		}
1309

1310 1311 1312 1313 1314 1315
		if (bgp->conf->expose_sensor) {
			domain = bgp->conf->sensors[i].domain;
			ret = bgp->conf->expose_sensor(bgp, i, domain);
			if (ret)
				goto remove_last_cooling;
		}
1316 1317 1318 1319 1320 1321 1322
	}

	/*
	 * Enable the Interrupts once everything is set. Otherwise irq handler
	 * might be called as soon as it is enabled where as rest of framework
	 * is still getting initialised.
	 */
1323 1324
	if (TI_BANDGAP_HAS(bgp, TALERT)) {
		ret = ti_bandgap_talert_init(bgp, pdev);
1325 1326
		if (ret) {
			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
1327
			i = bgp->conf->sensor_count;
1328 1329 1330 1331 1332 1333
			goto disable_clk;
		}
	}

	return 0;

1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
remove_last_cooling:
	if (bgp->conf->sensors[i].unregister_cooling)
		bgp->conf->sensors[i].unregister_cooling(bgp, i);
remove_sensors:
	for (i--; i >= 0; i--) {
		if (bgp->conf->sensors[i].unregister_cooling)
			bgp->conf->sensors[i].unregister_cooling(bgp, i);
		if (bgp->conf->remove_sensor)
			bgp->conf->remove_sensor(bgp, i);
	}
	ti_bandgap_power(bgp, false);
1345
disable_clk:
1346
	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1347
		clk_disable_unprepare(bgp->fclock);
1348
put_clks:
1349 1350
	clk_put(bgp->fclock);
	clk_put(bgp->div_clk);
1351
free_irqs:
1352
	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1353 1354
		free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
		gpio_free(bgp->tshut_gpio);
1355 1356 1357 1358 1359 1360
	}

	return ret;
}

static
1361
int ti_bandgap_remove(struct platform_device *pdev)
1362
{
1363
	struct ti_bandgap *bgp = platform_get_drvdata(pdev);
1364 1365 1366
	int i;

	/* First thing is to remove sensor interfaces */
1367
	for (i = 0; i < bgp->conf->sensor_count; i++) {
1368
		if (bgp->conf->sensors[i].unregister_cooling)
1369
			bgp->conf->sensors[i].unregister_cooling(bgp, i);
1370

1371 1372
		if (bgp->conf->remove_sensor)
			bgp->conf->remove_sensor(bgp, i);
1373 1374
	}

1375
	ti_bandgap_power(bgp, false);
1376

1377
	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1378 1379 1380
		clk_disable_unprepare(bgp->fclock);
	clk_put(bgp->fclock);
	clk_put(bgp->div_clk);
1381

1382
	if (TI_BANDGAP_HAS(bgp, TALERT))
1383
		free_irq(bgp->irq, bgp);
1384

1385
	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1386 1387
		free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
		gpio_free(bgp->tshut_gpio);
1388 1389 1390 1391 1392
	}

	return 0;
}

1393
#ifdef CONFIG_PM_SLEEP
1394
static int ti_bandgap_save_ctxt(struct ti_bandgap *bgp)
1395 1396 1397
{
	int i;

1398
	for (i = 0; i < bgp->conf->sensor_count; i++) {
1399 1400 1401
		struct temp_sensor_registers *tsr;
		struct temp_sensor_regval *rval;

1402
		rval = &bgp->regval[i];
1403
		tsr = bgp->conf->sensors[i].registers;
1404

1405 1406
		if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
			rval->bg_mode_ctrl = ti_bandgap_readl(bgp,
1407
							tsr->bgap_mode_ctrl);
1408 1409
		if (TI_BANDGAP_HAS(bgp, COUNTER))
			rval->bg_counter = ti_bandgap_readl(bgp,
1410
							tsr->bgap_counter);
1411 1412
		if (TI_BANDGAP_HAS(bgp, TALERT)) {
			rval->bg_threshold = ti_bandgap_readl(bgp,
1413
							tsr->bgap_threshold);
1414
			rval->bg_ctrl = ti_bandgap_readl(bgp,
1415
						   tsr->bgap_mask_ctrl);
1416 1417
		}

1418 1419
		if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
			rval->tshut_threshold = ti_bandgap_readl(bgp,
1420
						   tsr->tshut_threshold);
1421 1422 1423 1424 1425
	}

	return 0;
}

1426
static int ti_bandgap_restore_ctxt(struct ti_bandgap *bgp)
1427 1428 1429
{
	int i;

1430
	for (i = 0; i < bgp->conf->sensor_count; i++) {
1431 1432 1433 1434
		struct temp_sensor_registers *tsr;
		struct temp_sensor_regval *rval;
		u32 val = 0;

1435
		rval = &bgp->regval[i];
1436
		tsr = bgp->conf->sensors[i].registers;
1437

1438 1439
		if (TI_BANDGAP_HAS(bgp, COUNTER))
			val = ti_bandgap_readl(bgp, tsr->bgap_counter);
1440

1441 1442 1443
		if (TI_BANDGAP_HAS(bgp, TSHUT_CONFIG))
			ti_bandgap_writel(bgp, rval->tshut_threshold,
					  tsr->tshut_threshold);
1444 1445 1446
		/* Force immediate temperature measurement and update
		 * of the DTEMP field
		 */
1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
		ti_bandgap_force_single_read(bgp, i);

		if (TI_BANDGAP_HAS(bgp, COUNTER))
			ti_bandgap_writel(bgp, rval->bg_counter,
					  tsr->bgap_counter);
		if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
			ti_bandgap_writel(bgp, rval->bg_mode_ctrl,
					  tsr->bgap_mode_ctrl);
		if (TI_BANDGAP_HAS(bgp, TALERT)) {
			ti_bandgap_writel(bgp, rval->bg_threshold,
					  tsr->bgap_threshold);
			ti_bandgap_writel(bgp, rval->bg_ctrl,
					  tsr->bgap_mask_ctrl);
1460 1461 1462 1463 1464 1465
		}
	}

	return 0;
}

1466
static int ti_bandgap_suspend(struct device *dev)
1467
{
1468
	struct ti_bandgap *bgp = dev_get_drvdata(dev);
1469 1470
	int err;

1471 1472
	err = ti_bandgap_save_ctxt(bgp);
	ti_bandgap_power(bgp, false);
1473

1474
	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1475
		clk_disable_unprepare(bgp->fclock);
1476 1477 1478 1479

	return err;
}

1480
static int ti_bandgap_resume(struct device *dev)
1481
{
1482
	struct ti_bandgap *bgp = dev_get_drvdata(dev);
1483

1484
	if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1485
		clk_prepare_enable(bgp->fclock);
1486

1487
	ti_bandgap_power(bgp, true);
1488

1489
	return ti_bandgap_restore_ctxt(bgp);
1490
}
1491 1492
static SIMPLE_DEV_PM_OPS(ti_bandgap_dev_pm_ops, ti_bandgap_suspend,
			 ti_bandgap_resume);
1493

1494
#define DEV_PM_OPS	(&ti_bandgap_dev_pm_ops)
1495 1496 1497 1498
#else
#define DEV_PM_OPS	NULL
#endif

1499
static const struct of_device_id of_ti_bandgap_match[] = {
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
#ifdef CONFIG_OMAP4_THERMAL
	{
		.compatible = "ti,omap4430-bandgap",
		.data = (void *)&omap4430_data,
	},
	{
		.compatible = "ti,omap4460-bandgap",
		.data = (void *)&omap4460_data,
	},
	{
		.compatible = "ti,omap4470-bandgap",
		.data = (void *)&omap4470_data,
	},
1513 1514 1515 1516 1517 1518
#endif
#ifdef CONFIG_OMAP5_THERMAL
	{
		.compatible = "ti,omap5430-bandgap",
		.data = (void *)&omap5430_data,
	},
1519 1520 1521 1522 1523 1524
#endif
#ifdef CONFIG_DRA752_THERMAL
	{
		.compatible = "ti,dra752-bandgap",
		.data = (void *)&dra752_data,
	},
1525
#endif
1526 1527 1528
	/* Sentinel */
	{ },
};
1529
MODULE_DEVICE_TABLE(of, of_ti_bandgap_match);
1530

1531 1532 1533
static struct platform_driver ti_bandgap_sensor_driver = {
	.probe = ti_bandgap_probe,
	.remove = ti_bandgap_remove,
1534
	.driver = {
1535
			.name = "ti-soc-thermal",
1536
			.pm = DEV_PM_OPS,
1537
			.of_match_table	= of_ti_bandgap_match,
1538 1539 1540
	},
};

1541
module_platform_driver(ti_bandgap_sensor_driver);
1542 1543 1544

MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
MODULE_LICENSE("GPL v2");
1545
MODULE_ALIAS("platform:ti-soc-thermal");
1546
MODULE_AUTHOR("Texas Instrument Inc.");