[PATCH v3 5/7] ARM: OMAP4+: thermal: introduce bandgap temperature sensor

Eduardo Valentin eduardo.valentin at ti.com
Thu Jun 28 01:09:29 EDT 2012


Hello,

On Wed, Jun 27, 2012 at 10:05:03PM +0400, Konstantin Baydarov wrote:
> In the System Control Module, OMAP supplies a voltage reference
> and a temperature sensor feature that are gathered in the band
> gap voltage and temperature sensor (VBGAPTS) module. The band
> gap provides current and voltage reference for its internal
> circuits and other analog IP blocks. The analog-to-digital
> converter (ADC) produces an output value that is proportional
> to the silicon temperature.
> 
> This patch provides a platform driver which expose this feature.
> It is moduled as a MFD child of the System Control Module core
> MFD driver.
> 
> This driver provides only APIs to access the device properties,
> like temperature, thresholds and update rate.
> 
> Changes since previous version:
> - Bandgap and usb phy: drivers are now independent from control module driver,
> they use their own API functions.
> - Bandgap and usb phy: Added private spinlocks for bandgap and usb drivers.
> - Bandgap: Check the type of bandgap dynamically in bandgap driver probe
> function by reading
> omap core control module revision register CONTROL_GEN_CORE_REVISION.
> - Parent SCM platform device IOMEM resources is used to get the base address
> of SCM window.

Same comment on USB-phy applies here. What do we gain by reusing same ioresource
from parent on all children for ioremapping?

> - SCM Dependency was removed from Kconfig.
> - Bandgap masks defines were moved to drivers/thermal/omap-bandgap.c.
> 
> Signed-off-by: Konstantin Baydarov <kbaidarov at dev.rtsoft.ru>
> Signed-off-by: Eduardo Valentin <eduardo.valentin at ti.com>
> Signed-off-by: Keerthy <j-keerthy at ti.com>
> ---
>  .../devicetree/bindings/thermal/omap_bandgap.txt   |   27 +
>  drivers/thermal/Kconfig                            |   12 +
>  drivers/thermal/Makefile                           |    4 +-
>  drivers/thermal/omap-bandgap.c                     | 1773 ++++++++++++++++++++
>  drivers/thermal/omap-bandgap.h                     |   64 +
>  5 files changed, 1879 insertions(+), 1 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/thermal/omap_bandgap.txt
>  create mode 100644 drivers/thermal/omap-bandgap.c
>  create mode 100644 drivers/thermal/omap-bandgap.h
> 
> diff --git a/Documentation/devicetree/bindings/thermal/omap_bandgap.txt b/Documentation/devicetree/bindings/thermal/omap_bandgap.txt
> new file mode 100644
> index 0000000..430bcf8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/omap_bandgap.txt
> @@ -0,0 +1,27 @@
> +* Texas Instrument OMAP SCM bandgap bindings
> +
> +In the System Control Module, OMAP supplies a voltage reference
> +and a temperature sensor feature that are gathered in the band
> +gap voltage and temperature sensor (VBGAPTS) module. The band
> +gap provides current and voltage reference for its internal
> +circuits and other analog IP blocks. The analog-to-digital
> +converter (ADC) produces an output value that is proportional
> +to the silicon temperature.
> +
> +Required properties:
> +- compatible : Should be:
> +  - "ti,omap4460-control-bandgap" : for OMAP4460 bandgap
> +  - "ti,omap5430-control-bandgap" : for OMAP5430 bandgap

Please update documentation.

> +- interrupts : this entry should indicate which interrupt line
> +the talert signal is routed to;
> +Specific:
> +- ti,tshut-gpio : this entry should be used to inform which GPIO
> +line the tshut signal is routed to;
> +
> +Example:
> +
> +bandgap {
> +	compatible = "ti,omap4460-control-bandgap";
> +	interrupts = <0 126 4>; /* talert */
> +	ti,tshut-gpio = <86>;
> +};
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 514a691..f9989e8 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -26,3 +26,15 @@ config SPEAR_THERMAL
>  	help
>  	  Enable this to plug the SPEAr thermal sensor driver into the Linux
>  	  thermal framework
> +
> +config OMAP_BANDGAP
> +	tristate "Texas Instruments OMAP4+ temperature sensor driver"
> +	depends on THERMAL
> +	help
> +	  If you say yes here you get support for the Texas Instruments
> +	  OMAP4460+ on die bandgap temperature sensor support. The register
> +	  set is part of system control module.
> +
> +	  This includes alert interrupts generation and also the TSHUT
> +	  support.
> +
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index a9fff0b..5ff1af1 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -3,4 +3,6 @@
>  #
>  
>  obj-$(CONFIG_THERMAL)		+= thermal_sys.o
> -obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
> \ No newline at end of file
> +obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
> +obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal.o
> +omap-thermal-y			:= omap-bandgap.o
> diff --git a/drivers/thermal/omap-bandgap.c b/drivers/thermal/omap-bandgap.c
> new file mode 100644
> index 0000000..c68fa1a
> --- /dev/null
> +++ b/drivers/thermal/omap-bandgap.c
> @@ -0,0 +1,1773 @@
> +/*
> + * OMAP4 Bandgap temperature sensor driver
> + *
> + * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Author: J Keerthy <j-keerthy at ti.com>
> + * Author: Moiz Sonasath <m-sonasath at ti.com>
> + * Couple of fixes, DT and MFD adaptation:
> + *   Eduardo Valentin <eduardo.valentin at 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>
> +#include <linux/mutex.h>
> +#include <linux/reboot.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_irq.h>
> +
> +#include "omap-bandgap.h"
> +
> +/* Offsets from the base of temperature sensor registers */
> +
> +#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET	0x32C
> +#define OMAP4460_BGAP_CTRL_OFFSET		0x378
> +#define OMAP4460_BGAP_COUNTER_OFFSET		0x37C
> +#define OMAP4460_BGAP_THRESHOLD_OFFSET		0x380
> +#define OMAP4460_BGAP_TSHUT_OFFSET		0x384
> +#define OMAP4460_BGAP_STATUS_OFFSET		0x388
> +#define OMAP4460_FUSE_OPP_BGAP			0x260
> +
> +#define OMAP5430_TEMP_SENSOR_MPU_OFFSET		0x32C
> +#define OMAP5430_BGAP_CTRL_OFFSET		0x380
> +#define OMAP5430_BGAP_COUNTER_MPU_OFFSET	0x39C
> +#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET	0x384
> +#define OMAP5430_BGAP_TSHUT_MPU_OFFSET		0x390
> +#define OMAP5430_BGAP_STATUS_OFFSET		0x3A8
> +#define OMAP5430_FUSE_OPP_BGAP_MPU		0x1E4
> +
> +#define OMAP5430_TEMP_SENSOR_GPU_OFFSET		0x330
> +#define OMAP5430_BGAP_COUNTER_GPU_OFFSET	0x3A0
> +#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET	0x388
> +#define OMAP5430_BGAP_TSHUT_GPU_OFFSET		0x394
> +#define OMAP5430_FUSE_OPP_BGAP_GPU		0x1E0
> +
> +#define OMAP5430_TEMP_SENSOR_CORE_OFFSET	0x334
> +#define OMAP5430_BGAP_COUNTER_CORE_OFFSET	0x3A4
> +#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET	0x38C
> +#define OMAP5430_BGAP_TSHUT_CORE_OFFSET		0x398
> +#define OMAP5430_FUSE_OPP_BGAP_CORE		0x1E8
> +
> +#define OMAP4460_TSHUT_HOT		900	/* 122 deg C */
> +#define OMAP4460_TSHUT_COLD		895	/* 100 deg C */
> +#define OMAP4460_T_HOT			800	/* 73 deg C */
> +#define OMAP4460_T_COLD			795	/* 71 deg C */
> +#define OMAP4460_MAX_FREQ		1500000
> +#define OMAP4460_MIN_FREQ		1000000
> +#define OMAP4460_MIN_TEMP		-40000
> +#define OMAP4460_MAX_TEMP		123000
> +#define OMAP4460_HYST_VAL		5000
> +#define OMAP4460_ADC_START_VALUE	530
> +#define OMAP4460_ADC_END_VALUE		932
> +
> +#define OMAP5430_MPU_TSHUT_HOT		915
> +#define OMAP5430_MPU_TSHUT_COLD		900
> +#define OMAP5430_MPU_T_HOT		800
> +#define OMAP5430_MPU_T_COLD		795
> +#define OMAP5430_MPU_MAX_FREQ		1500000
> +#define OMAP5430_MPU_MIN_FREQ		1000000
> +#define OMAP5430_MPU_MIN_TEMP		-40000
> +#define OMAP5430_MPU_MAX_TEMP		125000
> +#define OMAP5430_MPU_HYST_VAL		5000
> +#define OMAP5430_ADC_START_VALUE	532
> +#define OMAP5430_ADC_END_VALUE		934
> +
> +#define OMAP5430_GPU_TSHUT_HOT		915
> +#define OMAP5430_GPU_TSHUT_COLD		900
> +#define OMAP5430_GPU_T_HOT		800
> +#define OMAP5430_GPU_T_COLD		795
> +#define OMAP5430_GPU_MAX_FREQ		1500000
> +#define OMAP5430_GPU_MIN_FREQ		1000000
> +#define OMAP5430_GPU_MIN_TEMP		-40000
> +#define OMAP5430_GPU_MAX_TEMP		125000
> +#define OMAP5430_GPU_HYST_VAL		5000
> +
> +#define OMAP5430_CORE_TSHUT_HOT		915
> +#define OMAP5430_CORE_TSHUT_COLD	900
> +#define OMAP5430_CORE_T_HOT		800
> +#define OMAP5430_CORE_T_COLD		795
> +#define OMAP5430_CORE_MAX_FREQ		1500000
> +#define OMAP5430_CORE_MIN_FREQ		1000000
> +#define OMAP5430_CORE_MIN_TEMP		-40000
> +#define OMAP5430_CORE_MAX_TEMP		125000
> +#define OMAP5430_CORE_HYST_VAL		5000
> +
> +/* TEMP_SENSOR OMAP4430 */
> +#define OMAP4430_BGAP_TEMPSOFF_SHIFT			12
> +#define OMAP4430_BGAP_TEMPSOFF_MASK			(1 << 12)
> +#define OMAP4430_BGAP_TSHUT_SHIFT				11
> +#define OMAP4430_BGAP_TSHUT_MASK				(1 << 11)
> +#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
> +#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
> +#define OMAP4430_BGAP_TEMP_SENSOR_SOC_SHIFT		9
> +#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
> +#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
> +#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
> +#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
> +#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
> +
> +/* TEMP_SENSOR OMAP4460 */
> +#define OMAP4460_BGAP_TEMPSOFF_SHIFT			13
> +#define OMAP4460_BGAP_TEMPSOFF_MASK			(1 << 13)
> +#define OMAP4460_BGAP_TEMP_SENSOR_SOC_SHIFT		11
> +#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK		(1 << 11)
> +#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
> +#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 10)
> +#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
> +#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
> +
> +/* BANDGAP_CTRL */
> +#define OMAP4460_SINGLE_MODE_SHIFT			31
> +#define OMAP4460_SINGLE_MODE_MASK			(1 << 31)
> +#define OMAP4460_MASK_HOT_SHIFT				1
> +#define OMAP4460_MASK_HOT_MASK				(1 << 1)
> +#define OMAP4460_MASK_COLD_SHIFT			0
> +#define OMAP4460_MASK_COLD_MASK				(1 << 0)
> +
> +/* BANDGAP_COUNTER */
> +#define OMAP4460_COUNTER_SHIFT				0
> +#define OMAP4460_COUNTER_MASK				(0xffffff << 0)
> +
> +/* BANDGAP_THRESHOLD */
> +#define OMAP4460_T_HOT_SHIFT				16
> +#define OMAP4460_T_HOT_MASK				(0x3ff << 16)
> +#define OMAP4460_T_COLD_SHIFT				0
> +#define OMAP4460_T_COLD_MASK				(0x3ff << 0)
> +
> +/* TSHUT_THRESHOLD */
> +#define OMAP4460_TSHUT_HOT_SHIFT			16
> +#define OMAP4460_TSHUT_HOT_MASK				(0x3ff << 16)
> +#define OMAP4460_TSHUT_COLD_SHIFT			0
> +#define OMAP4460_TSHUT_COLD_MASK			(0x3ff << 0)
> +
> +/* BANDGAP_STATUS */
> +#define OMAP4460_CLEAN_STOP_SHIFT			3
> +#define OMAP4460_CLEAN_STOP_MASK			(1 << 3)
> +#define OMAP4460_BGAP_ALERT_SHIFT			2
> +#define OMAP4460_BGAP_ALERT_MASK			(1 << 2)
> +#define OMAP4460_HOT_FLAG_SHIFT				1
> +#define OMAP4460_HOT_FLAG_MASK				(1 << 1)
> +#define OMAP4460_COLD_FLAG_SHIFT			0
> +#define OMAP4460_COLD_FLAG_MASK				(1 << 0)
> +
> +/* TEMP_SENSOR OMAP5430 */
> +#define OMAP5430_BGAP_TEMP_SENSOR_SOC_SHIFT		12
> +#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK		(1 << 12)
> +#define OMAP5430_BGAP_TEMPSOFF_SHIFT			11
> +#define OMAP5430_BGAP_TEMPSOFF_MASK			(1 << 11)
> +#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_SHIFT		10
> +#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 10)
> +#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
> +#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
> +
> +/* BANDGAP_CTRL */
> +#define OMAP5430_MASK_HOT_CORE_SHIFT			5
> +#define OMAP5430_MASK_HOT_CORE_MASK			(1 << 5)
> +#define OMAP5430_MASK_COLD_CORE_SHIFT			4
> +#define OMAP5430_MASK_COLD_CORE_MASK			(1 << 4)
> +#define OMAP5430_MASK_HOT_MM_SHIFT			3
> +#define OMAP5430_MASK_HOT_MM_MASK			(1 << 3)
> +#define OMAP5430_MASK_COLD_MM_SHIFT			2
> +#define OMAP5430_MASK_COLD_MM_MASK			(1 << 2)
> +#define OMAP5430_MASK_HOT_MPU_SHIFT			1
> +#define OMAP5430_MASK_HOT_MPU_MASK			(1 << 1)
> +#define OMAP5430_MASK_COLD_MPU_SHIFT			0
> +#define OMAP5430_MASK_COLD_MPU_MASK			(1 << 0)
> +
> +/* BANDGAP_COUNTER */
> +#define OMAP5430_REPEAT_MODE_SHIFT			31
> +#define OMAP5430_REPEAT_MODE_MASK			(1 << 31)
> +#define OMAP5430_COUNTER_SHIFT				0
> +#define OMAP5430_COUNTER_MASK				(0xffffff << 0)
> +
> +/* BANDGAP_THRESHOLD */
> +#define OMAP5430_T_HOT_SHIFT				16
> +#define OMAP5430_T_HOT_MASK				(0x3ff << 16)
> +#define OMAP5430_T_COLD_SHIFT				0
> +#define OMAP5430_T_COLD_MASK				(0x3ff << 0)
> +
> +/* TSHUT_THRESHOLD */
> +#define OMAP5430_TSHUT_HOT_SHIFT			16
> +#define OMAP5430_TSHUT_HOT_MASK				(0x3ff << 16)
> +#define OMAP5430_TSHUT_COLD_SHIFT			0
> +#define OMAP5430_TSHUT_COLD_MASK			(0x3ff << 0)
> +
> +/* BANDGAP_STATUS */
> +#define OMAP5430_BGAP_ALERT_SHIFT			31
> +#define OMAP5430_BGAP_ALERT_MASK			(1 << 31)
> +#define OMAP5430_HOT_CORE_FLAG_SHIFT			5
> +#define OMAP5430_HOT_CORE_FLAG_MASK			(1 << 5)
> +#define OMAP5430_COLD_CORE_FLAG_SHIFT			4
> +#define OMAP5430_COLD_CORE_FLAG_MASK			(1 << 4)
> +#define OMAP5430_HOT_MM_FLAG_SHIFT			3
> +#define OMAP5430_HOT_MM_FLAG_MASK			(1 << 3)
> +#define OMAP5430_COLD_MM_FLAG_SHIFT			2
> +#define OMAP5430_COLD_MM_FLAG_MASK			(1 << 2)
> +#define OMAP5430_HOT_MPU_FLAG_SHIFT			1
> +#define OMAP5430_HOT_MPU_FLAG_MASK			(1 << 1)
> +#define OMAP5430_COLD_MPU_FLAG_SHIFT			0
> +#define OMAP5430_COLD_MPU_FLAG_MASK			(1 << 0)
> +
> +
> +/**
> + * The register offsets and bit fields might change across
> + * OMAP versions hence populating them in this structure.
> + */
> +
> +struct temp_sensor_registers {
> +	u32	temp_sensor_ctrl;
> +	u32	bgap_tempsoff_mask;
> +	u32	bgap_soc_mask;
> +	u32	bgap_eocz_mask;
> +	u32	bgap_dtemp_mask;
> +
> +	u32	bgap_mask_ctrl;
> +	u32	mask_hot_mask;
> +	u32	mask_cold_mask;
> +
> +	u32	bgap_mode_ctrl;
> +	u32	mode_ctrl_mask;
> +
> +	u32	bgap_counter;
> +	u32	counter_mask;
> +
> +	u32	bgap_threshold;
> +	u32	threshold_thot_mask;
> +	u32	threshold_tcold_mask;
> +
> +	u32	tshut_threshold;
> +	u32	tshut_hot_mask;
> +	u32	tshut_cold_mask;
> +
> +	u32	bgap_status;
> +	u32	status_clean_stop_mask;
> +	u32	status_bgap_alert_mask;
> +	u32	status_hot_mask;
> +	u32	status_cold_mask;
> +
> +	u32	bgap_efuse;
> +	spinlock_t	bg_reg_lock;
> +};
> +
> +/**
> + * The thresholds and limits for temperature sensors.
> + */
> +struct temp_sensor_data {
> +	u32	tshut_hot;
> +	u32	tshut_cold;
> +	u32	t_hot;
> +	u32	t_cold;
> +	u32	min_freq;
> +	u32	max_freq;
> +	int	max_temp;
> +	int	min_temp;
> +	int	hyst_val;
> +	u32	adc_start_val;
> +	u32	adc_end_val;
> +	u32	update_int1;
> +	u32	update_int2;
> +};
> +
> +/**
> + * struct temp_sensor_regval - temperature sensor register values
> + * @bg_mode_ctrl: temp sensor control register value
> + * @bg_ctrl: bandgap ctrl register value
> + * @bg_counter: bandgap counter value
> + * @bg_threshold: bandgap threshold register value
> + * @tshut_threshold: bandgap tshut register value
> + */
> +struct temp_sensor_regval {
> +	u32			bg_mode_ctrl;
> +	u32			bg_ctrl;
> +	u32			bg_counter;
> +	u32			bg_threshold;
> +	u32			tshut_threshold;
> +};
> +
> +/**
> + * struct omap_temp_sensor - bandgap temperature sensor platform data
> + * @ts_data: pointer to struct with thresholds, limits of temperature sensor
> + * @registers: pointer to the list of register offsets and bitfields
> + * @regval: temperature sensor register values
> + * @domain: the name of the domain where the sensor is located
> + */
> +struct omap_temp_sensor {
> +	struct temp_sensor_data		*ts_data;
> +	struct temp_sensor_registers	*registers;
> +	struct temp_sensor_regval	*regval;
> +	char				*domain;
> +};
> +
> +/**
> + * struct omap_bandgap_data - bandgap platform data structure
> + * @has_talert: indicates if the chip has talert output line
> + * @has_tshut: indicates if the chip has tshut output line
> + * @conv_table: Pointer to adc to temperature conversion table
> + * @fclock_name: clock name of the functional clock
> + * @div_ck_nme: clock name of the clock divisor
> + * @sensor_count: count of temperature sensor device in scm
> + * @sensors: array of sensors present in this bandgap instance
> + * @expose_sensor: callback to export sensor to thermal API
> + */
> +struct omap_bandgap_data {
> +	bool				has_talert;
> +	bool				has_tshut;
> +	int				tshut_gpio;
> +	const int			*conv_table;
> +	char				*fclock_name;
> +	char				*div_ck_name;
> +	int				sensor_count;
> +	int (*report_temperature)(struct omap_bandgap *bg_ptr, int id);
> +	int (*expose_sensor)(struct omap_bandgap *bg_ptr, int id, char *domain);
> +	int				irq;
> +
> +	/* this needs to be at the end */
> +	struct omap_temp_sensor		sensors[];
> +};
> +
> +/* TODO: provide data structures for 4430 */
> +
> +/*
> + * OMAP4460 has one instance of thermal sensor for MPU
> + * need to describe the individual bit fields
> + */
> +static struct temp_sensor_registers
> +omap4460_mpu_temp_sensor_registers = {
> +	.temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET,
> +	.bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK,
> +	.bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK,
> +	.bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK,
> +	.bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK,
> +
> +	.bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
> +	.mask_hot_mask = OMAP4460_MASK_HOT_MASK,
> +	.mask_cold_mask = OMAP4460_MASK_COLD_MASK,
> +
> +	.bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
> +	.mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK,
> +
> +	.bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET,
> +	.counter_mask = OMAP4460_COUNTER_MASK,
> +
> +	.bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET,
> +	.threshold_thot_mask = OMAP4460_T_HOT_MASK,
> +	.threshold_tcold_mask = OMAP4460_T_COLD_MASK,
> +
> +	.tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET,
> +	.tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK,
> +	.tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK,
> +
> +	.bgap_status = OMAP4460_BGAP_STATUS_OFFSET,
> +	.status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK,
> +	.status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK,
> +	.status_hot_mask = OMAP4460_HOT_FLAG_MASK,
> +	.status_cold_mask = OMAP4460_COLD_FLAG_MASK,
> +
> +	.bgap_efuse = OMAP4460_FUSE_OPP_BGAP,
> +};
> +
> +/*
> + * OMAP4460 has one instance of thermal sensor for MPU
> + * need to describe the individual bit fields
> + */
> +static struct temp_sensor_registers
> +omap5430_mpu_temp_sensor_registers = {
> +	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET,
> +	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
> +	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
> +	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
> +	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
> +
> +	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
> +	.mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK,
> +	.mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK,
> +
> +	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
> +	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
> +
> +	.bgap_counter = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
> +	.counter_mask = OMAP5430_COUNTER_MASK,
> +
> +	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET,
> +	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
> +	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
> +
> +	.tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET,
> +	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
> +	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
> +
> +	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
> +	.status_clean_stop_mask = 0x0,
> +	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
> +	.status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK,
> +	.status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK,
> +
> +	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU,
> +};
> +
> +/*
> + * OMAP4460 has one instance of thermal sensor for MPU
> + * need to describe the individual bit fields
> + */
> +static struct temp_sensor_registers
> +omap5430_gpu_temp_sensor_registers = {
> +	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET,
> +	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
> +	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
> +	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
> +	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
> +
> +	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
> +	.mask_hot_mask = OMAP5430_MASK_HOT_MM_MASK,
> +	.mask_cold_mask = OMAP5430_MASK_COLD_MM_MASK,
> +
> +	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
> +	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
> +
> +	.bgap_counter = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
> +	.counter_mask = OMAP5430_COUNTER_MASK,
> +
> +	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET,
> +	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
> +	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
> +
> +	.tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET,
> +	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
> +	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
> +
> +	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
> +	.status_clean_stop_mask = 0x0,
> +	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
> +	.status_hot_mask = OMAP5430_HOT_MM_FLAG_MASK,
> +	.status_cold_mask = OMAP5430_COLD_MM_FLAG_MASK,
> +
> +	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU,
> +};
> +
> +/*
> + * OMAP4460 has one instance of thermal sensor for MPU
> + * need to describe the individual bit fields
> + */
> +static struct temp_sensor_registers
> +omap5430_core_temp_sensor_registers = {
> +	.temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET,
> +	.bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
> +	.bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
> +	.bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
> +	.bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
> +
> +	.bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
> +	.mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK,
> +	.mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK,
> +
> +	.bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
> +	.mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
> +
> +	.bgap_counter = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
> +	.counter_mask = OMAP5430_COUNTER_MASK,
> +
> +	.bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET,
> +	.threshold_thot_mask = OMAP5430_T_HOT_MASK,
> +	.threshold_tcold_mask = OMAP5430_T_COLD_MASK,
> +
> +	.tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET,
> +	.tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
> +	.tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
> +
> +	.bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
> +	.status_clean_stop_mask = 0x0,
> +	.status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
> +	.status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK,
> +	.status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK,
> +
> +	.bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE,
> +};
> +
> +/* Thresholds and limits for OMAP4460 MPU temperature sensor */
> +static struct temp_sensor_data omap4460_mpu_temp_sensor_data = {
> +	.tshut_hot = OMAP4460_TSHUT_HOT,
> +	.tshut_cold = OMAP4460_TSHUT_COLD,
> +	.t_hot = OMAP4460_T_HOT,
> +	.t_cold = OMAP4460_T_COLD,
> +	.min_freq = OMAP4460_MIN_FREQ,
> +	.max_freq = OMAP4460_MAX_FREQ,
> +	.max_temp = OMAP4460_MAX_TEMP,
> +	.min_temp = OMAP4460_MIN_TEMP,
> +	.hyst_val = OMAP4460_HYST_VAL,
> +	.adc_start_val = OMAP4460_ADC_START_VALUE,
> +	.adc_end_val = OMAP4460_ADC_END_VALUE,
> +	.update_int1 = 1000,
> +	.update_int2 = 2000,
> +};
> +
> +/* Thresholds and limits for OMAP5430 MPU temperature sensor */
> +static struct temp_sensor_data omap5430_mpu_temp_sensor_data = {
> +	.tshut_hot = OMAP5430_MPU_TSHUT_HOT,
> +	.tshut_cold = OMAP5430_MPU_TSHUT_COLD,
> +	.t_hot = OMAP5430_MPU_T_HOT,
> +	.t_cold = OMAP5430_MPU_T_COLD,
> +	.min_freq = OMAP5430_MPU_MIN_FREQ,
> +	.max_freq = OMAP5430_MPU_MAX_FREQ,
> +	.max_temp = OMAP5430_MPU_MAX_TEMP,
> +	.min_temp = OMAP5430_MPU_MIN_TEMP,
> +	.hyst_val = OMAP5430_MPU_HYST_VAL,
> +	.adc_start_val = OMAP5430_ADC_START_VALUE,
> +	.adc_end_val = OMAP5430_ADC_END_VALUE,
> +	.update_int1 = 1000,
> +	.update_int2 = 2000,
> +};
> +
> +/* Thresholds and limits for OMAP5430 GPU temperature sensor */
> +static struct temp_sensor_data omap5430_gpu_temp_sensor_data = {
> +	.tshut_hot = OMAP5430_GPU_TSHUT_HOT,
> +	.tshut_cold = OMAP5430_GPU_TSHUT_COLD,
> +	.t_hot = OMAP5430_GPU_T_HOT,
> +	.t_cold = OMAP5430_GPU_T_COLD,
> +	.min_freq = OMAP5430_GPU_MIN_FREQ,
> +	.max_freq = OMAP5430_GPU_MAX_FREQ,
> +	.max_temp = OMAP5430_GPU_MAX_TEMP,
> +	.min_temp = OMAP5430_GPU_MIN_TEMP,
> +	.hyst_val = OMAP5430_GPU_HYST_VAL,
> +	.adc_start_val = OMAP5430_ADC_START_VALUE,
> +	.adc_end_val = OMAP5430_ADC_END_VALUE,
> +	.update_int1 = 1000,
> +	.update_int2 = 2000,
> +};
> +
> +/* Thresholds and limits for OMAP5430 CORE temperature sensor */
> +static struct temp_sensor_data omap5430_core_temp_sensor_data = {
> +	.tshut_hot = OMAP5430_CORE_TSHUT_HOT,
> +	.tshut_cold = OMAP5430_CORE_TSHUT_COLD,
> +	.t_hot = OMAP5430_CORE_T_HOT,
> +	.t_cold = OMAP5430_CORE_T_COLD,
> +	.min_freq = OMAP5430_CORE_MIN_FREQ,
> +	.max_freq = OMAP5430_CORE_MAX_FREQ,
> +	.max_temp = OMAP5430_CORE_MAX_TEMP,
> +	.min_temp = OMAP5430_CORE_MIN_TEMP,
> +	.hyst_val = OMAP5430_CORE_HYST_VAL,
> +	.adc_start_val = OMAP5430_ADC_START_VALUE,
> +	.adc_end_val = OMAP5430_ADC_END_VALUE,
> +	.update_int1 = 1000,
> +	.update_int2 = 2000,
> +};
> +
> +/*
> + * Temperature values in milli degree celsius
> + * ADC code values from 530 to 923
> + */
> +static const int
> +omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = {
> +	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
> +	-37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
> +	-34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
> +	-30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
> +	-27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
> +	-24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
> +	-20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
> +	-17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
> +	-13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
> +	-10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
> +	-6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
> +	-2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
> +	2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
> +	6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
> +	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
> +	15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
> +	19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
> +	23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
> +	26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
> +	30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
> +	34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
> +	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
> +	42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
> +	45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
> +	49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
> +	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
> +	57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
> +	60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
> +	64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
> +	68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
> +	72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
> +	75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
> +	79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
> +	83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
> +	86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
> +	90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
> +	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
> +	98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
> +	101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
> +	104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
> +	108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
> +	111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
> +	114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
> +	117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
> +	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
> +	124600, 124900, 125000, 125000, 125000, 125000
> +};
> +
> +static const int
> +omap5430_adc_to_temp[OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = {
> +	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600,
> +	-38200, -37800, -37300, -36800,
> +	-36400, -36000, -35600, -35200, -34800, -34300, -33800, -33400, -33000,
> +	-32600,
> +	-32200, -31800, -31300, -30800, -30400, -30000, -29600, -29200, -28700,
> +	-28200, -27800, -27400, -27000, -26600, -26200, -25700, -25200, -24800,
> +	-24400, -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
> +	-20600, -20200, -19700, -19200, -9300, -18400, -18000, -17600, -17200,
> +	-16700, -16200, -15800, -15400, -15000, -14600, -14200, -13700, -13200,
> +	-12800, -12400, -12000, -11600, -11200, -10700, -10200, -9800, -9400,
> +	-9000,
> +	-8600, -8200, -7700, -7200, -6800, -6400, -6000, -5600, -5200, -4800,
> +	-4300,
> +	-3800, -3400, -3000, -2600, -2200, -1800, -1300, -800, -400, 0, 400,
> +	800,
> +	1200, 1600, 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000,
> +	6400, 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10800,
> +	11100,
> +	11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800, 15300,
> +	15800,
> +	16200, 16600, 17000, 17400, 17800, 18200, 18700, 19200, 19600, 20000,
> +	20400,
> +	20800, 21200, 21600, 22100, 22600, 23000, 23400, 23800, 24200, 24600,
> +	25000,
> +	25400, 25900, 26400, 26800, 27200, 27600, 28000, 28400, 28800, 29300,
> +	29800,
> +	30200, 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
> +	34400,
> +	34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800, 38200, 38600,
> +	39000,
> +	39400, 39800, 40200, 40600, 41100, 41600, 42000, 42400, 42800, 43200,
> +	43600,
> +	44000, 44400, 44800, 45300, 45800, 46200, 46600, 47000, 47400, 47800,
> +	48200,
> +	48600, 49000, 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400,
> +	52800,
> +	53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600, 57000,
> +	57400,
> +	57800, 58200, 58700, 59200, 59600, 60000, 60400, 60800, 61200, 61600,
> +	62000,
> +	62400, 62800, 63300, 63800, 64200, 64600, 65000, 65400, 65800, 66200,
> +	66600,
> +	67000, 67400, 67800, 68200, 68700, 69200, 69600, 70000, 70400, 70800,
> +	71200,
> +	71600, 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
> +	75800,
> +	76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000, 79400, 79800,
> +	80300,
> +	80800, 81200, 81600, 82000, 82400, 82800, 83200, 83600, 84000, 84400,
> +	84800,
> +	85200, 85600, 86000, 86400, 86800, 87300, 87800, 88200, 88600, 89000,
> +	89400,
> +	89800, 90200, 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400,
> +	93800,
> +	94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600, 98000,
> +	98400,
> +	98800, 99200, 99600, 100000, 100400, 100800, 101200, 101600, 102000,
> +	102400,
> +	102800, 103200, 103600, 104000, 104400, 104800, 105200, 105600, 106100,
> +	106600, 107000, 107400, 107800, 108200, 108600, 109000, 109400, 109800,
> +	110200, 110600, 111000, 111400, 111800, 112200, 112600, 113000, 113400,
> +	113800, 114200, 114600, 115000, 115400, 115800, 116200, 116600, 117000,
> +	117400, 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
> +	121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
> +	124600, 124900, 125000, 125000, 125000, 125000,
> +};

I suppose not all comments on RFC were considered.. Anyways, I have another version
of this driver which has the data structures in separated files.

> +
> +/*
> + * TODO: Get rid from bg_readl() return value -
> + * It's useless.
> + */
> +
> +static int bg_readl(struct omap_bandgap *bg_ptr, u32 reg, u32 *val)
> +{
> +	if (!bg_ptr)
> +		return -EINVAL;
> +
> +	*val = __raw_readl(bg_ptr->bg_base + reg);
> +	return 0;
> +}
> +
> +/*
> + * TODO: Get rid from bg_writel() return value -
> + * It's useless.

Same thing as in usb-phy. when removing the return value, remember to leave a WARN_ON at least.

> + */
> +static int bg_writel(struct omap_bandgap *bg_ptr, u32 val, u32 reg, spinlock_t *lock)
> +{
> +	unsigned long flags;
> +
> +	if (!bg_ptr)
> +		return -EINVAL;
> +
> +	spin_lock_irqsave(lock, flags);
> +	__raw_writel(val, bg_ptr->bg_base + reg);
> +	spin_unlock_irqrestore(lock, flags);
> +	return 0;
> +}

Please use omap_bandgap_[read/write]l. Otherwise this driver starts to have several prefix patterns (or no prefix pattern)

> +
> +static irqreturn_t talert_irq_handler(int irq, void *data)
> +{
> +	struct omap_bandgap *bg_ptr = data;
> +	struct temp_sensor_registers *tsr;
> +	u32 t_hot = 0, t_cold = 0, temp, ctrl = 0;
> +	int i, r;
> +
> +	bg_ptr = data;
> +	/* Read the status of t_hot */
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
> +		tsr = bg_ptr->pdata->sensors[i].registers;
> +		r = bg_readl(bg_ptr, tsr->bgap_status, &t_hot);
> +		t_hot &= tsr->status_hot_mask;
> +
> +		/* Read the status of t_cold */
> +		r |= bg_readl(bg_ptr, tsr->bgap_status, &t_cold);
> +		t_cold &= tsr->status_cold_mask;
> +
> +		if (!t_cold && !t_hot)
> +			continue;
> +
> +		r |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl, &ctrl);
> +		/*
> +		 * 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;
> +		}
> +
> +		r |= bg_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
> +
> +		if (r) {
> +			dev_err(bg_ptr->dev, "failed to ack talert interrupt\n");
> +			return IRQ_NONE;
> +		}
> +
> +		/* read temperature */
> +		r = bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
> +		temp &= tsr->bgap_dtemp_mask;
> +
> +		/* report temperature to whom may concern */
> +		if (bg_ptr->pdata->report_temperature)
> +			bg_ptr->pdata->report_temperature(bg_ptr, i);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data)
> +{
> +	orderly_poweroff(true);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static
> +int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val,
> +			   int *t)
> +{
> +	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
> +
> +	/* look up for temperature in the table and return the temperature */
> +	if (adc_val < ts_data->adc_start_val || adc_val > ts_data->adc_end_val)
> +		return -ERANGE;
> +
> +	*t = bg_ptr->conv_table[adc_val - ts_data->adc_start_val];
> +
> +	return 0;
> +}
> +
> +static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i,
> +				  int *adc)
> +{
> +	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[i].ts_data;
> +	int high, low, mid;
> +
> +	low = 0;
> +	high = ts_data->adc_end_val - ts_data->adc_start_val;
> +	mid = (high + low) / 2;
> +
> +	if (temp < bg_ptr->conv_table[high] || temp > bg_ptr->conv_table[high])
> +		return -EINVAL;
> +
> +	while (low < high) {
> +		if (temp < bg_ptr->conv_table[mid])
> +			high = mid - 1;
> +		else
> +			low = mid + 1;
> +		mid = (low + high) / 2;
> +	}
> +
> +	*adc = ts_data->adc_start_val + low;
> +
> +	return 0;
> +}
> +
> +static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
> +					 u32 t_hot, u32 t_cold)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 temp = 0, reg_val = 0;
> +	int err;
> +
> +	/* Read the current on die temperature */
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	err = bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
> +	temp &= tsr->bgap_dtemp_mask;
> +
> +	err |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl, &reg_val);
> +	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;
> +	err |= bg_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
> +
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to unmask interrupts\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static
> +int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i,
> +	     u32 *sum)
> +{
> +	int temp, ret;
> +
> +	ret = adc_to_temp_conversion(bg_ptr, i, adc_val, &temp);
> +	if (ret < 0)
> +		return ret;
> +
> +	temp += hyst_val;
> +
> +	return temp_to_adc_conversion(temp, bg_ptr, i, sum);
> +}
> +
> +static
> +int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
> +{
> +	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
> +	struct temp_sensor_registers *tsr;
> +	u32 thresh_val = 0, reg_val;
> +	int cold, err;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +
> +	/* obtain the T cold value */
> +	err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
> +	cold = (thresh_val & tsr->threshold_tcold_mask) >>
> +	    __ffs(tsr->threshold_tcold_mask);
> +	if (t_hot <= cold) {
> +		/* change the t_cold to t_hot - 5000 millidegrees */
> +		err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id, &cold);
> +		/* write the new t_cold value */
> +		reg_val = thresh_val & (~tsr->threshold_tcold_mask);
> +		reg_val |= cold << __ffs(tsr->threshold_tcold_mask);
> +		err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
> +		thresh_val = reg_val;
> +	}
> +
> +	/* write the new t_hot value */
> +	reg_val = thresh_val & ~tsr->threshold_thot_mask;
> +	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
> +	err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
> +		return -EIO;
> +	}
> +
> +	return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
> +}
> +
> +static
> +int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id,
> +				       int t_hot, int t_cold)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 reg_val, thresh_val;
> +	int err;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
> +
> +	/* write the new t_cold value */
> +	reg_val = thresh_val & ~tsr->threshold_tcold_mask;
> +	reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
> +	err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
> +		return -EIO;
> +	}
> +
> +	err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
> +
> +	/* write the new t_hot value */
> +	reg_val = thresh_val & ~tsr->threshold_thot_mask;
> +	reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
> +	err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
> +		return -EIO;
> +	}
> +
> +	err = bg_readl(bg_ptr, tsr->bgap_mask_ctrl, &reg_val);
> +	reg_val |= tsr->mask_hot_mask;
> +	reg_val |= tsr->mask_cold_mask;
> +	err |= bg_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
> +		return -EIO;
> +	}
> +
> +	return err;
> +}
> +
> +static
> +int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id,
> +				int t_cold)
> +{
> +	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
> +	struct temp_sensor_registers *tsr;
> +	u32 thresh_val = 0, reg_val;
> +	int hot, err;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	/* obtain the T cold value */
> +	err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
> +	hot = (thresh_val & tsr->threshold_thot_mask) >>
> +	    __ffs(tsr->threshold_thot_mask);
> +
> +	if (t_cold >= hot) {
> +		/* change the t_hot to t_cold + 5000 millidegrees */
> +		err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id, &hot);
> +		/* write the new t_hot value */
> +		reg_val = thresh_val & (~tsr->threshold_thot_mask);
> +		reg_val |= hot << __ffs(tsr->threshold_thot_mask);
> +		err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
> +		thresh_val = reg_val;
> +	}
> +
> +	/* write the new t_cold value */
> +	reg_val = thresh_val & ~tsr->threshold_tcold_mask;
> +	reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
> +	err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
> +		return -EIO;
> +	}
> +
> +	return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold);
> +}
> +
> +static int temp_sensor_configure_tshut_hot(struct omap_bandgap *bg_ptr,
> +					   int id, int tshut_hot)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 reg_val;
> +	int err;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	err = bg_readl(bg_ptr, tsr->tshut_threshold, &reg_val);
> +	reg_val &= ~tsr->tshut_hot_mask;
> +	reg_val |= tshut_hot << __ffs(tsr->tshut_hot_mask);
> +	err |= bg_writel(bg_ptr, reg_val, tsr->tshut_threshold, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram tshut thot\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr,
> +					    int id, int tshut_cold)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 reg_val;
> +	int err;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	err = bg_readl(bg_ptr, tsr->tshut_threshold, &reg_val);
> +	reg_val &= ~tsr->tshut_cold_mask;
> +	reg_val |= tshut_cold << __ffs(tsr->tshut_cold_mask);
> +	err |= bg_writel(bg_ptr, reg_val, tsr->tshut_threshold, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id,
> +					 u32 counter)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 val = 0;
> +	int err;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	err = bg_readl(bg_ptr, tsr->bgap_counter, &val);
> +	val &= ~tsr->counter_mask;
> +	val |= counter << __ffs(tsr->counter_mask);
> +	err |= bg_writel(bg_ptr, val, tsr->bgap_counter, &tsr->bg_reg_lock);
> +	if (err) {
> +		dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Exposed APIs */
> +/**
> + * omap_bandgap_read_thot() - reads sensor current thot
> + * @bg_ptr - pointer to bandgap instance
> + * @id - sensor id
> + * @thot - resulting current thot value
> + *
> + * returns 0 on success or the proper error code
> + */
> +int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id,
> +			      int *thot)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 temp;
> +	int ret;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	ret = bg_readl(bg_ptr, tsr->bgap_threshold, &temp);
> +	temp = (temp & tsr->threshold_thot_mask) >>
> +		__ffs(tsr->threshold_thot_mask);
> +	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
> +	if (ret) {
> +		dev_err(bg_ptr->dev, "failed to read thot\n");
> +		return -EIO;
> +	}
> +
> +	*thot = temp;
> +
> +	return 0;
> +}
> +
> +/**
> + * omap_bandgap_write_thot() - sets sensor current thot
> + * @bg_ptr - pointer to bandgap instance
> + * @id - sensor id
> + * @val - desired thot value
> + *
> + * returns 0 on success or the proper error code
> + */
> +int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val)
> +{
> +	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
> +	struct temp_sensor_registers *tsr;
> +	u32 t_hot;
> +	int ret;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +
> +	if (val < ts_data->min_temp + ts_data->hyst_val)
> +		return -EINVAL;
> +	ret = temp_to_adc_conversion(val, bg_ptr, id, &t_hot);
> +	if (ret < 0)
> +		return ret;
> +
> +	mutex_lock(&bg_ptr->bg_mutex);
> +	temp_sensor_configure_thot(bg_ptr, id, t_hot);
> +	mutex_unlock(&bg_ptr->bg_mutex);
> +
> +	return 0;
> +}
> +
> +/**
> + * omap_bandgap_read_tcold() - reads sensor current tcold
> + * @bg_ptr - pointer to bandgap instance
> + * @id - sensor id
> + * @tcold - resulting current tcold value
> + *
> + * returns 0 on success or the proper error code
> + */
> +int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
> +			       int *tcold)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 temp;
> +	int ret;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	ret = bg_readl(bg_ptr, tsr->bgap_threshold, &temp);
> +	temp = (temp & tsr->threshold_tcold_mask)
> +	    >> __ffs(tsr->threshold_tcold_mask);
> +	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
> +	if (ret)
> +		return -EIO;
> +
> +	*tcold = temp;
> +
> +	return 0;
> +}
> +
> +/**
> + * omap_bandgap_write_tcold() - sets the sensor tcold
> + * @bg_ptr - pointer to bandgap instance
> + * @id - sensor id
> + * @val - desired tcold value
> + *
> + * returns 0 on success or the proper error code
> + */
> +int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val)
> +{
> +	struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
> +	struct temp_sensor_registers *tsr;
> +	u32 t_cold;
> +	int ret;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	if (val > ts_data->max_temp + ts_data->hyst_val)
> +		return -EINVAL;
> +
> +	ret = temp_to_adc_conversion(val, bg_ptr, id, &t_cold);
> +	if (ret < 0)
> +		return ret;
> +
> +	mutex_lock(&bg_ptr->bg_mutex);
> +	temp_sensor_configure_tcold(bg_ptr, id, t_cold);
> +	mutex_unlock(&bg_ptr->bg_mutex);
> +
> +	return 0;
> +}
> +
> +/**
> + * omap_bandgap_read_update_interval() - read the sensor update interval
> + * @bg_ptr - pointer to bandgap instance
> + * @id - sensor id
> + * @interval - resulting update interval in miliseconds
> + *
> + * returns 0 on success or the proper error code
> + */
> +int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
> +					 int *interval)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 time;
> +	int ret;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	ret = bg_readl(bg_ptr, tsr->bgap_counter, &time);
> +	if (ret)
> +		return ret;
> +	time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask);
> +	time = time * 1000 / bg_ptr->clk_rate;
> +
> +	*interval = time;
> +
> +	return 0;
> +}
> +
> +/**
> + * omap_bandgap_write_update_interval() - set the update interval
> + * @bg_ptr - pointer to bandgap instance
> + * @id - sensor id
> + * @interval - desired update interval in miliseconds
> + *
> + * returns 0 on success or the proper error code
> + */
> +int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr,
> +					  int id, u32 interval)
> +{
> +	interval = interval * bg_ptr->clk_rate / 1000;
> +	mutex_lock(&bg_ptr->bg_mutex);
> +	configure_temp_sensor_counter(bg_ptr, id, interval);
> +	mutex_unlock(&bg_ptr->bg_mutex);
> +
> +	return 0;
> +}
> +
> +/**
> + * omap_bandgap_read_temperature() - report current temperature
> + * @bg_ptr - pointer to bandgap instance
> + * @id - sensor id
> + * @temperature - resulting temperature
> + *
> + * returns 0 on success or the proper error code
> + */
> +int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
> +				     int *temperature)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 temp;
> +	int ret;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	ret = bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
> +	temp &= tsr->bgap_dtemp_mask;
> +
> +	ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
> +	if (ret)
> +		return -EIO;
> +
> +	*temperature = temp;
> +
> +	return 0;
> +}
> +
> +/**
> + * enable_continuous_mode() - One time enabling of continuous conversion mode
> + * @bg_ptr - pointer to scm instance
> + */
> +static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
> +{
> +	struct temp_sensor_registers *tsr;
> +	int i, r;
> +	u32 val;
> +
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
> +		tsr = bg_ptr->pdata->sensors[i].registers;
> +		r = bg_readl(bg_ptr, tsr->bgap_mode_ctrl, &val);
> +		val |= 1 << __ffs(tsr->mode_ctrl_mask);
> +		r |= bg_writel(bg_ptr, val, tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
> +		if (r)
> +			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
> +	}
> +
> +	return r ? -EIO : 0;
> +}
> +
> +static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr,
> +				      struct platform_device *pdev)
> +{
> +	int gpio_nr = bg_ptr->tshut_gpio;
> +	int status;
> +
> +	/* Request for gpio_86 line */
> +	status = gpio_request(gpio_nr, "tshut");
> +	if (status < 0) {
> +		dev_err(bg_ptr->dev,
> +			"Could not request for TSHUT GPIO:%i\n", 86);
> +		return status;
> +	}
> +	status = gpio_direction_input(gpio_nr);
> +	if (status) {
> +		dev_err(bg_ptr->dev,
> +			"Cannot set input TSHUT GPIO %d\n", gpio_nr);
> +		return status;
> +	}
> +
> +	status = request_irq(gpio_to_irq(gpio_nr),
> +			     omap_bandgap_tshut_irq_handler,
> +			     IRQF_TRIGGER_RISING, "tshut",
> +			     NULL);
> +	if (status) {
> +		gpio_free(gpio_nr);
> +		dev_err(bg_ptr->dev, "request irq failed for TSHUT");
> +	}
> +
> +	return 0;
> +}
> +
> +static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr,
> +				       struct platform_device *pdev)
> +{
> +	int ret;
> +
> +	bg_ptr->irq = platform_get_irq(pdev, 0);
> +	if (bg_ptr->irq < 0) {
> +		dev_err(&pdev->dev, "get_irq failed\n");
> +		return bg_ptr->irq;
> +	}
> +	ret = request_threaded_irq(bg_ptr->irq, NULL,
> +				   talert_irq_handler,
> +				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> +				   "talert", bg_ptr);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Request threaded irq failed.\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct omap_bandgap_data omap4460_data = {
> +	.has_talert = true,
> +	.has_tshut = true,
> +	.tshut_gpio = 86,
> +	.fclock_name = "bandgap_ts_fclk",
> +	.div_ck_name = "div_ts_ck",
> +	.conv_table = omap4460_adc_to_temp,
> +	.irq = 126,
> +	.sensors = {
> +		{
> +			.registers = &omap4460_mpu_temp_sensor_registers,
> +			.ts_data = &omap4460_mpu_temp_sensor_data,
> +			.domain = "cpu",
> +		},
> +	},
> +	.sensor_count = 1,
> +};
> +
> +static const struct omap_bandgap_data omap5430_data = {
> +	.has_talert = true,
> +	.has_tshut = true,
> +	.tshut_gpio = 0, /* TODO. Fill correct tshut_gpio */
> +	.fclock_name = "ts_clk_div_ck",
> +	.div_ck_name = "ts_clk_div_ck",
> +	.conv_table = omap5430_adc_to_temp,
> +	.irq = 0, /* TODO. Fill correct irq */
> +	.sensors = {
> +		{
> +			.registers = &omap5430_mpu_temp_sensor_registers,
> +			.ts_data = &omap5430_mpu_temp_sensor_data,
> +			.domain = "cpu",
> +		},
> +		{
> +			.registers = &omap5430_gpu_temp_sensor_registers,
> +			.ts_data = &omap5430_gpu_temp_sensor_data,
> +			.domain = "gpu",
> +		},
> +		{
> +			.registers = &omap5430_core_temp_sensor_registers,
> +			.ts_data = &omap5430_core_temp_sensor_data,
> +			.domain = "core",
> +		},
> +	},
> +	.sensor_count = 3,
> +};
> +
> +static const struct of_device_id of_omap_bandgap_match[] = {
> +	/*
> +	 * TODO: Add support to 4430
> +	 * { .compatible = "ti,omap4430-bandgap", .data = , },
> +	 */
> +	{
> +		.compatible = "ti,omap4-bandgap",

You didnt update the doc.

> +	},
> +	/* Sentinel */
> +	{ },
> +};
> +
> +static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
> +{
> +	struct device_node *node = pdev->dev.of_node;
> +	struct omap_bandgap *bg_ptr;
> +	u32 val;
> +	struct resource *io_res;
> +	struct platform_device *pparent;
> +
> +	/* just for the sake */
> +	if (!node) {
> +		dev_err(&pdev->dev, "No platform information available\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
> +				    GFP_KERNEL);
> +	if (!bg_ptr) {
> +		dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	if (!pdev->dev.parent) {
> +		dev_err(&pdev->dev, "No parent device!\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	pparent = to_platform_device(pdev->dev.parent);
> +	io_res = platform_get_resource(pparent, IORESOURCE_MEM, 0);

Same question on usbphy applies here. what do we want to achieve by doing this at children code?

> +	if (!io_res) {
> +		dev_err(&pdev->dev, "Failed to get IO resource\n");
> +		return ERR_PTR(-ENOENT);
> +	}
> +
> +	bg_ptr->bg_base = ioremap(io_res->start, resource_size(io_res));
> +	if (!bg_ptr->bg_base)
> +		return 0;
> +
> +	bg_readl(bg_ptr, 0x0, &val);

use a macro for the offset.

> +
> +	/*
> +	 * Check omap control core module revision to find out
> +	 * bandgap type
> +	 */
> +	switch ((val & 0x3ff) >> 8) {
> +	case 1:
> +		/* 4430 */
> +		bg_ptr->pdata = &omap4460_data;
> +		break;
> +	case 2:
> +		/* 4460 */
> +		bg_ptr->pdata = &omap4460_data;
> +		break;

3 would be 4470.

But O5 has exactly same register value as 4430.

So, I think this won't work just the way it is.

We can either go back to the previous "compatible" approach.
Or we can have a match function mixed with compatible and register value.
Meaning, when omap4- is passed in compatible, you match in the above way.
But when omap5- is passed in compatible, you match in a way which fits to
o5 register value.

This is getting overcomplicated though...

> +	default:
> +		/* Unknown omap control core module revision */
> +		return 0;
> +	}
> +
> +	if (bg_ptr->pdata->has_tshut) {
> +		bg_ptr->tshut_gpio = bg_ptr->pdata->tshut_gpio;
> +		if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
> +			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
> +				bg_ptr->tshut_gpio);
> +			return ERR_PTR(-EINVAL);
> +		}
> +	}
> +
> +	return bg_ptr;
> +}
> +
> +struct resource *platform_get_resource_dbg(struct platform_device *dev,
> +				       unsigned int type, unsigned int num);
> +
> +static
> +int __devinit omap_bandgap_probe(struct platform_device *pdev)
> +{
> +	struct omap_bandgap *bg_ptr;
> +	int clk_rate, ret = 0, i;
> +
> +	bg_ptr = omap_bandgap_build(pdev);
> +	if (IS_ERR_OR_NULL(bg_ptr)) {
> +		dev_err(&pdev->dev, "failed to fetch platform data\n");
> +		return PTR_ERR(bg_ptr);
> +	}
> +
> +	if (bg_ptr->pdata->has_talert) {
> +		ret = omap_bandgap_talert_init(bg_ptr, pdev);
> +		if (ret) {
> +			dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
> +			return ret;
> +		}
> +	}
> +
> +	if (bg_ptr->pdata->has_tshut) {
> +		ret = omap_bandgap_tshut_init(bg_ptr, pdev);
> +		if (ret) {
> +			dev_err(&pdev->dev,
> +				"failed to initialize system tshut IRQ\n");
> +			goto free_talert;
> +		}
> +	}
> +
> +	bg_ptr->fclock = clk_get(NULL, bg_ptr->pdata->fclock_name);
> +	ret = IS_ERR_OR_NULL(bg_ptr->fclock);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to request fclock reference\n");
> +		goto free_irqs;
> +	}
> +
> +	bg_ptr->div_clk = clk_get(NULL,  bg_ptr->pdata->div_ck_name);
> +	ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"failed to request div_ts_ck clock ref\n");
> +		goto free_irqs;
> +	}
> +
> +	bg_ptr->conv_table = bg_ptr->pdata->conv_table;
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
> +		struct temp_sensor_registers *tsr;
> +		u32 val;
> +
> +		tsr = bg_ptr->pdata->sensors[i].registers;
> +		/* Initialize register lock */
> +		spin_lock_init(&tsr->bg_reg_lock);
> +
> +		/*
> +		 * check if the efuse has a non-zero value if not
> +		 * it is an untrimmed sample and the temperatures
> +		 * may not be accurate
> +		 */
> +		ret = bg_readl(bg_ptr, tsr->bgap_efuse, &val);
> +		if (ret || !val)
> +			dev_info(&pdev->dev,
> +				 "Non-trimmed BGAP, Temp not accurate\n");
> +	}
> +
> +	clk_rate = clk_round_rate(bg_ptr->div_clk,
> +				  bg_ptr->pdata->sensors[0].ts_data->max_freq);
> +	if (clk_rate < bg_ptr->pdata->sensors[0].ts_data->min_freq ||
> +	    clk_rate == 0xffffffff) {
> +		ret = -ENODEV;
> +		goto put_clks;
> +	}
> +
> +	ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Cannot set clock rate\n");
> +		goto put_clks;
> +	}
> +
> +	bg_ptr->clk_rate = clk_rate;
> +	clk_enable(bg_ptr->fclock);
> +
> +	mutex_init(&bg_ptr->bg_mutex);
> +	bg_ptr->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, bg_ptr);
> +
> +	/* 1 clk cycle */
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++)
> +		configure_temp_sensor_counter(bg_ptr, i, 1);
> +
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
> +		struct temp_sensor_data *ts_data;
> +
> +		ts_data = bg_ptr->pdata->sensors[i].ts_data;
> +
> +		temp_sensor_init_talert_thresholds(bg_ptr, i,
> +						   ts_data->t_hot,
> +						   ts_data->t_cold);
> +		temp_sensor_configure_tshut_hot(bg_ptr, i,
> +						ts_data->tshut_hot);
> +		temp_sensor_configure_tshut_cold(bg_ptr, i,
> +						 ts_data->tshut_cold);
> +	}
> +
> +	enable_continuous_mode(bg_ptr);
> +
> +	/* Set .250 seconds time as default counter */
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++)
> +		configure_temp_sensor_counter(bg_ptr, i,
> +					      bg_ptr->clk_rate / 4);
> +
> +	/* Every thing is good? Then expose the sensors */
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
> +		char *domain;
> +
> +		domain = bg_ptr->pdata->sensors[i].domain;
> +		if (bg_ptr->pdata->expose_sensor)
> +			bg_ptr->pdata->expose_sensor(bg_ptr, i, domain);
> +	}
> +
> +	return 0;
> +
> +put_clks:
> +	clk_disable(bg_ptr->fclock);
> +	clk_put(bg_ptr->fclock);
> +	clk_put(bg_ptr->div_clk);
> +free_irqs:
> +	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
> +	gpio_free(bg_ptr->tshut_gpio);
> +free_talert:
> +	free_irq(bg_ptr->irq, bg_ptr);
> +
> +	return ret;
> +}
> +
> +static
> +int __devexit omap_bandgap_remove(struct platform_device *pdev)
> +{
> +	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
> +
> +	clk_disable(bg_ptr->fclock);
> +	clk_put(bg_ptr->fclock);
> +	clk_put(bg_ptr->div_clk);
> +	free_irq(bg_ptr->irq, bg_ptr);
> +	free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
> +	gpio_free(bg_ptr->tshut_gpio);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
> +{
> +	int err = 0;
> +	int i;
> +
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
> +		struct temp_sensor_registers *tsr;
> +		struct temp_sensor_regval *rval;
> +
> +		rval = bg_ptr->pdata->sensors[i].regval;
> +		tsr = bg_ptr->pdata->sensors[i].registers;
> +
> +		err = bg_readl(bg_ptr, tsr->bgap_mode_ctrl,
> +					 &rval->bg_mode_ctrl);
> +		err |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl,
> +					  &rval->bg_ctrl);
> +		err |= bg_readl(bg_ptr, tsr->bgap_counter,
> +					  &rval->bg_counter);
> +		err |= bg_readl(bg_ptr, tsr->bgap_threshold,
> +					  &rval->bg_threshold);
> +		err |= bg_readl(bg_ptr, tsr->tshut_threshold,
> +					  &rval->tshut_threshold);
> +
> +		if (err)
> +			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
> +	}
> +
> +	return err ? -EIO : 0;
> +}
> +
> +static int
> +omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
> +{
> +	struct temp_sensor_registers *tsr;
> +	u32 temp = 0, counter = 1000;
> +	int err;
> +
> +	tsr = bg_ptr->pdata->sensors[id].registers;
> +	/* Select single conversion mode */
> +	err = bg_readl(bg_ptr, tsr->bgap_mode_ctrl, &temp);
> +	temp &= ~(1 << __ffs(tsr->mode_ctrl_mask));
> +	bg_writel(bg_ptr, temp, tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
> +
> +	/* Start of Conversion = 1 */
> +	err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
> +	temp |= 1 << __ffs(tsr->bgap_soc_mask);
> +	bg_writel(bg_ptr, temp, tsr->temp_sensor_ctrl, &tsr->bg_reg_lock);
> +	/* Wait until DTEMP is updated */
> +	err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
> +	temp &= (tsr->bgap_dtemp_mask);
> +	while ((temp == 0) && --counter) {
> +		err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
> +		temp &= (tsr->bgap_dtemp_mask);
> +	}
> +	/* Start of Conversion = 0 */
> +	err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
> +	temp &= ~(1 << __ffs(tsr->bgap_soc_mask));
> +	err |= bg_writel(bg_ptr, temp, tsr->temp_sensor_ctrl, &tsr->bg_reg_lock);
> +
> +	return err ? -EIO : 0;
> +}
> +
> +static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
> +{
> +	int i, err = 0;
> +	u32 temp = 0;
> +
> +	for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
> +		struct temp_sensor_registers *tsr;
> +		struct temp_sensor_regval *rval;
> +		u32 val = 0;
> +
> +		rval = bg_ptr->pdata->sensors[i].regval;
> +		tsr = bg_ptr->pdata->sensors[i].registers;
> +
> +		err = bg_readl(bg_ptr, tsr->bgap_counter, &val);
> +		if (val == 0) {
> +			err |= bg_writel(bg_ptr, rval->bg_threshold,
> +						   tsr->bgap_threshold, &tsr->bg_reg_lock);
> +			err |= bg_writel(bg_ptr, rval->tshut_threshold,
> +						   tsr->tshut_threshold, &tsr->bg_reg_lock);
> +			/* Force immediate temperature measurement and update
> +			 * of the DTEMP field
> +			 */
> +			omap_bandgap_force_single_read(bg_ptr, i);
> +			err |= bg_writel(bg_ptr, rval->bg_counter,
> +						   tsr->bgap_counter, &tsr->bg_reg_lock);
> +			err |= bg_writel(bg_ptr, rval->bg_mode_ctrl,
> +						   tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
> +			err |= bg_writel(bg_ptr, rval->bg_ctrl,
> +						   tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
> +		} else {
> +			err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl,
> +						 &temp);
> +			temp &= (tsr->bgap_dtemp_mask);
> +			if (temp == 0) {
> +				omap_bandgap_force_single_read(bg_ptr, i);
> +				err |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl,
> +							  &temp);
> +				temp |= 1 << __ffs(tsr->mode_ctrl_mask);
> +				err |= bg_writel(bg_ptr, temp,
> +							   tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
> +			}
> +		}
> +		if (err)
> +			dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
> +	}
> +
> +	return err ? -EIO : 0;
> +}
> +
> +static int omap_bandgap_suspend(struct device *dev)
> +{
> +	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
> +	int err;
> +
> +	err = omap_bandgap_save_ctxt(bg_ptr);
> +	clk_disable(bg_ptr->fclock);
> +
> +	return err;
> +}
> +
> +static int omap_bandgap_resume(struct device *dev)
> +{
> +	struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
> +
> +	clk_enable(bg_ptr->fclock);
> +
> +	return omap_bandgap_restore_ctxt(bg_ptr);
> +}
> +static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
> +				omap_bandgap_resume)
> +};
> +
> +#define DEV_PM_OPS	(&omap_bandgap_dev_pm_ops)
> +#else
> +#define DEV_PM_OPS	NULL
> +#endif
> +
> +static struct platform_driver omap_bandgap_sensor_driver = {
> +	.probe = omap_bandgap_probe,
> +	.remove = omap_bandgap_remove,
> +	.driver = {
> +			.name = "omap-bandgap",
> +			.pm = DEV_PM_OPS,
> +			.of_match_table	= of_omap_bandgap_match,
> +	},
> +};
> +
> +module_platform_driver(omap_bandgap_sensor_driver);
> +early_platform_init("early_omap_temperature", &omap_bandgap_sensor_driver);
> +
> +static int __init bg_init(void)
> +{
> +	return platform_driver_register(&omap_bandgap_sensor_driver);
> +}
> +
> +static void __exit bg_exit(void)
> +{
> +	platform_driver_unregister(&omap_bandgap_sensor_driver);
> +}
> +
> +module_init(bg_init);
> +module_exit(bg_exit);
> +
> +MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:omap-bandgap");
> +MODULE_AUTHOR("Texas Instrument Inc.");
> diff --git a/drivers/thermal/omap-bandgap.h b/drivers/thermal/omap-bandgap.h
> new file mode 100644
> index 0000000..41f25ff
> --- /dev/null
> +++ b/drivers/thermal/omap-bandgap.h
> @@ -0,0 +1,64 @@
> +/*
> + * OMAP4 Bandgap temperature sensor driver
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
> + * Contact:
> + *   Eduardo Valentin <eduardo.valentin at 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
> + *
> + */
> +#ifndef __OMAP_BANDGAP_H
> +#define __OMAP_BANDGAP_H
> +
> +struct omap_bandgap_data;
> +
> +/**
> + * struct omap_bandgap - bandgap device structure
> + * @dev: device pointer
> + * @pdata: platform data with sensor data
> + * @fclock: pointer to functional clock of temperature sensor
> + * @div_clk: pointer to parent clock of temperature sensor fclk
> + * @conv_table: Pointer to adc to temperature conversion table
> + * @bg_mutex: Mutex for sysfs, irq and PM
> + * @irq: MPU Irq number for thermal alert
> + * @tshut_gpio: GPIO where Tshut signal is routed
> + * @clk_rate: Holds current clock rate
> + */
> +struct omap_bandgap {
> +	struct device			*dev;
> +	const struct omap_bandgap_data	*pdata;
> +	struct clk			*fclock;
> +	struct clk			*div_clk;
> +	const int			*conv_table;
> +	struct mutex			bg_mutex; /* Mutex for irq and PM */
> +	int				irq;
> +	int				tshut_gpio;
> +	u32				clk_rate;
> +	void __iomem			*bg_base;
> +};
> +
> +int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot);
> +int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val);
> +int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold);
> +int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val);
> +int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
> +				      int *interval);
> +int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
> +				       u32 interval);
> +int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
> +				  int *temperature);
> +
> +#endif
> -- 
> 1.7.7.6
> 
> 



More information about the linux-arm-kernel mailing list